Commit 0ed9043c authored by mae's avatar mae
Browse files

tune auto-indentation of pasted text

auto-indentation of pasted text now only happens when complete
lines including a trailing paragraph separator are copied and pasted.

In addition, the reindent() functions ensures that the relative indentation
within the pasted block is preserved. This mechanism is now also used for
moving lines up/down.

Done with thorbjorn
parent b1f5a40e
......@@ -827,7 +827,7 @@ void BaseTextEditor::moveLineUpDown(bool up)
move.setPosition(end, QTextCursor::KeepAnchor);
}
indent(document(), move, QChar::Null);
reindent(document(), move);
move.endEditBlock();
setTextCursor(move);
......@@ -3356,8 +3356,8 @@ void BaseTextEditor::indentBlock(QTextDocument *, QTextBlock, QChar)
void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(qMin(cursor.selectionStart(), cursor.selectionEnd()));
const QTextBlock end = doc->findBlock(qMax(cursor.selectionStart(), cursor.selectionEnd())).next();
QTextBlock block = doc->findBlock(cursor.selectionStart());
const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
do {
indentBlock(doc, block, typedChar);
block = block.next();
......@@ -3367,6 +3367,29 @@ void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar
}
}
void BaseTextEditor::reindent(QTextDocument *doc, const QTextCursor &cursor)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(cursor.selectionStart());
const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
const TabSettings &ts = d->m_document->tabSettings();
int previousIndentation = ts.indentationColumn(block.text());
indentBlock(doc, block, QChar::Null);
int currentIndentation = ts.indentationColumn(block.text());
int delta = currentIndentation - previousIndentation;
block = block.next();
while (block.isValid() && block != end) {
ts.reindentLine(block, delta);
block = block.next();
}
} else {
indentBlock(doc, cursor.block(), QChar::Null);
}
}
BaseTextEditor::Link BaseTextEditor::findLinkAt(const QTextCursor &, bool)
{
return Link();
......@@ -4466,11 +4489,39 @@ QMimeData *BaseTextEditor::createMimeDataFromSelection() const
if (d->m_inBlockSelectionMode) {
QMimeData *mimeData = new QMimeData;
QString text = d->copyBlockSelection();
mimeData->setData(QLatin1String("application/vnd.nokia.qtcreator.blocktext"), text.toUtf8());
mimeData->setData(QLatin1String("application/vnd.nokia.qtcreator.vblocktext"), text.toUtf8());
mimeData->setText(text); // for exchangeability
return mimeData;
} else if (textCursor().hasSelection()){
QTextCursor cursor = textCursor();
QMimeData *mimeData = new QMimeData;
QString text = cursor.selectedText();
mimeData->setText(text);
/*
Try to figure out whether we are copying an entire block, and store the complete block
including indentation in the qtcreator.blocktext mimetype.
*/
QTextCursor selstart = cursor;
selstart.setPosition(cursor.selectionStart());
QTextCursor selend = cursor;
selend.setPosition(cursor.selectionEnd());
const TabSettings &ts = d->m_document->tabSettings();
bool startOk = ts.cursorIsAtBeginningOfLine(selstart);
bool endOk = (selend.block() != selstart.block() && ts.cursorIsAtBeginningOfLine(selend));
if (startOk && endOk) {
selstart.movePosition(QTextCursor::StartOfBlock);
selend.movePosition(QTextCursor::StartOfBlock);
cursor.setPosition(selstart.position());
cursor.setPosition(selend.position(), QTextCursor::KeepAnchor);
text = cursor.selectedText();
mimeData->setData(QLatin1String("application/vnd.nokia.qtcreator.blocktext"), text.toUtf8());
}
return mimeData;
}
return QPlainTextEdit::createMimeDataFromSelection();
return 0;
}
bool BaseTextEditor::canInsertFromMimeData(const QMimeData *source) const
......@@ -4480,8 +4531,11 @@ bool BaseTextEditor::canInsertFromMimeData(const QMimeData *source) const
void BaseTextEditor::insertFromMimeData(const QMimeData *source)
{
if (!isReadOnly() && source->hasFormat(QLatin1String("application/vnd.nokia.qtcreator.blocktext"))) {
QString text = QString::fromUtf8(source->data(QLatin1String("application/vnd.nokia.qtcreator.blocktext")));
if (isReadOnly())
return;
if (source->hasFormat(QLatin1String("application/vnd.nokia.qtcreator.vblocktext"))) {
QString text = QString::fromUtf8(source->data(QLatin1String("application/vnd.nokia.qtcreator.vblocktext")));
if (text.isEmpty())
return;
QStringList lines = text.split(QLatin1Char('\n'));
......@@ -4511,13 +4565,15 @@ void BaseTextEditor::insertFromMimeData(const QMimeData *source)
return;
}
QString text = source->text();
if (text.isEmpty())
return;
const TabSettings &ts = d->m_document->tabSettings();
QTextCursor cursor = textCursor();
if (cursor.hasSelection() || !ts.m_autoIndent) {
if (!ts.m_autoIndent) {
cursor.beginEditBlock();
cursor.insertText(text);
cursor.endEditBlock();
......@@ -4526,29 +4582,28 @@ void BaseTextEditor::insertFromMimeData(const QMimeData *source)
}
cursor.beginEditBlock();
int bpos = cursor.block().position();
int pos = cursor.position() - bpos;
int fns = ts.firstNonSpace(cursor.block().text());
if (pos <= fns) { // cursor is at beginning of line, we will reindent
if (ts.cursorIsAtBeginningOfLine(cursor)
&& source->hasFormat(QLatin1String("application/vnd.nokia.qtcreator.blocktext"))) {
text = QString::fromUtf8(source->data(QLatin1String("application/vnd.nokia.qtcreator.blocktext")));
if (text.isEmpty())
return;
cursor.removeSelectedText();
bool hasEndingNewline = (text.endsWith(QLatin1Char('\n'))
|| text.endsWith(QChar::ParagraphSeparator)
|| text.endsWith(QLatin1Char('\r')));
int bpos = cursor.block().position();
int pos = cursor.position() - bpos;
if (hasEndingNewline)
cursor.setPosition(bpos); // we'll add a final newline, preserve current line's indentation
cursor.setPosition(bpos); // since we'll add a final newline, preserve current line's indentation
cursor.insertText(text);
pos = cursor.position();
cursor.setPosition(bpos);
cursor.setPosition(pos, QTextCursor::KeepAnchor);
if (hasEndingNewline)
cursor.setPosition(cursor.position()-1, QTextCursor::KeepAnchor);
indent(document(), cursor, QChar::Null);
cursor.setPosition(cursor.position()-1, QTextCursor::KeepAnchor);
reindent(document(), cursor);
cursor.clearSelection();
if (hasEndingNewline)
cursor.setPosition(cursor.position()+1);
cursor.setPosition(cursor.position()+1); // skip newline
} else {
cursor.insertText(text);
}
......
......@@ -521,6 +521,8 @@ protected:
virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
// Indent at cursor. Calls indentBlock for selection or current line.
virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
// Reindent at cursor. Selection will be adjusted according to the indentation change of the first block
virtual void reindent(QTextDocument *doc, const QTextCursor &cursor);
struct Link
{
......
......@@ -87,6 +87,14 @@ void TabSettings::fromSettings(const QString &category, const QSettings *s)
m_tabKeyBehavior = (TabKeyBehavior)s->value(group + QLatin1String(tabKeyBehaviorKey), m_tabKeyBehavior).toInt();
}
bool TabSettings::cursorIsAtBeginningOfLine(const QTextCursor &cursor) const
{
QString text = cursor.block().text();
int fns = firstNonSpace(text);
return (cursor.position() - cursor.block().position() <= fns);
}
int TabSettings::lineIndentPosition(const QString &text) const
{
int i = 0;
......@@ -255,6 +263,32 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const
cursor.endEditBlock();
}
void TabSettings::reindentLine(QTextBlock block, int delta) const
{
const QString text = block.text();
const int oldBlockLength = text.size();
int oldIndent = indentationColumn(text);
int newIndent = qMax(oldIndent + delta, 0);
if (oldIndent == newIndent)
return;
const QString indentString = indentationString(0, newIndent);
newIndent = indentString.length();
if (oldBlockLength == indentString.length() && text == indentString)
return;
QTextCursor cursor(block);
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace(text));
cursor.removeSelectedText();
cursor.insertText(indentString);
cursor.endEditBlock();
}
bool TabSettings::equals(const TabSettings &ts) const
{
return m_spacesForTabs == ts.m_spacesForTabs
......
......@@ -66,7 +66,10 @@ struct TEXTEDITOR_EXPORT TabSettings
QString indentationString(const QString &text) const;
int indentationColumn(const QString &text) const;
bool cursorIsAtBeginningOfLine(const QTextCursor &cursor) const;
void indentLine(QTextBlock block, int newIndent) const;
void reindentLine(QTextBlock block, int delta) const;
int trailingWhitespaces(const QString &text) const;
bool isIndentationClean(const QString &text) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment