Commit f053ec8c authored by Henrik Abelsson's avatar Henrik Abelsson Committed by Thorbjørn Lindeijer

Initial support for emacs like fill-paragraph.

Merge-request: 882
Reviewed-by: default avatarThorbjørn Lindeijer <thorbjorn.lindeijer@nokia.com>
parent 4eda7c27
......@@ -3850,6 +3850,129 @@ void BaseTextEditor::format()
cursor.endEditBlock();
}
void BaseTextEditor::rewrapParagraph()
{
const int paragraphWidth = displaySettings().m_wrapColumn;
const QRegExp anyLettersOrNumbers = QRegExp("\\w");
const int tabSize = tabSettings().m_tabSize;
QTextCursor cursor = textCursor();
cursor.beginEditBlock();
// Find start of paragraph.
while (cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::MoveAnchor)) {
QTextBlock block = cursor.block();
QString text = block.text();
// If this block is empty, move marker back to previous and terminate.
if (!text.contains(anyLettersOrNumbers)) {
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor);
break;
}
}
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
// Find indent level of current block.
int indentLevel = 0;
QString text = cursor.block().text();
for (int i = 0; i < text.length(); i++) {
const QChar ch = text.at(i);
if (ch == QLatin1Char(' '))
indentLevel++;
else if (ch == QLatin1Char('\t'))
indentLevel += tabSize - (indentLevel % tabSize);
else
break;
}
// If there is a common prefix, it should be kept and expanded to all lines.
// this allows nice reflowing of doxygen style comments.
QTextCursor nextBlock = cursor;
QString commonPrefix;
if (nextBlock.movePosition(QTextCursor::NextBlock))
{
QString nText = nextBlock.block().text();
int maxLength = qMin(text.length(), nText.length());
for (int i = 0; i < maxLength; ++i) {
const QChar ch = text.at(i);
if (ch != nText[i] || ch.isLetterOrNumber())
break;
commonPrefix.append(ch);
}
}
// Find end of paragraph.
while (cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor)) {
QString text = cursor.block().text();
if (!text.contains(anyLettersOrNumbers))
break;
}
QString selectedText = cursor.selectedText();
// Preserve initial indent level.or common prefix.
QString spacing;
if (commonPrefix.isEmpty()) {
spacing = tabSettings().indentationString(0, indentLevel);
} else {
spacing = commonPrefix;
indentLevel = commonPrefix.length();
}
int currentLength = indentLevel;
QString result;
result.append(spacing);
// Remove existing instances of any common prefix from paragraph to
// reflow.
selectedText.remove(0, commonPrefix.length());
commonPrefix.prepend(QChar::ParagraphSeparator);
selectedText.replace(commonPrefix, QLatin1String("\n"));
// remove any repeated spaces, trim lines to PARAGRAPH_WIDTH width and
// keep the same indentation level as first line in paragraph.
QString currentWord;
for (int i = 0; i < selectedText.length(); ++i) {
QChar ch = selectedText.at(i);
if (ch.isSpace()) {
if (!currentWord.isEmpty()) {
currentLength += currentWord.length() + 1;
if (currentLength > paragraphWidth - indentLevel) {
currentLength = currentWord.length() + 1 + indentLevel;
result.append(QChar::ParagraphSeparator);
result.append(spacing);
}
result.append(currentWord);
result.append(QLatin1String(" "));
currentWord.clear();
}
continue;
}
currentWord.append(ch);
}
result.append(QChar::ParagraphSeparator);
cursor.insertText(result);
cursor.endEditBlock();
}
void BaseTextEditor::unCommentSelection()
{
}
......
......@@ -483,6 +483,7 @@ public:
public slots:
virtual void format();
virtual void rewrapParagraph();
virtual void unCommentSelection();
virtual void setFontSettings(const TextEditor::FontSettings &);
void setFontSettingsIfVisible(const TextEditor::FontSettings &);
......
......@@ -141,6 +141,12 @@ void TextEditorActionHandler::createActions()
advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT);
connect(m_formatAction, SIGNAL(triggered(bool)), this, SLOT(formatAction()));
m_rewrapParagraphAction = new QAction(tr("&Rewrap Paragraph"), this);
command = am->registerAction(m_rewrapParagraphAction, TextEditor::Constants::REWRAP_PARAGRAPH, m_contextId);
//command->setDefaultKeySequence(QKeySequence(tr("Alt+Q"))); (No default key sequence for now.)
advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT);
connect(m_rewrapParagraphAction, SIGNAL(triggered(bool)), this, SLOT(rewrapParagraphAction()));
m_visualizeWhitespaceAction = new QAction(tr("&Visualize Whitespace"), this);
m_visualizeWhitespaceAction->setCheckable(true);
......@@ -398,6 +404,7 @@ FUNCTION2(copyAction, copy)
FUNCTION2(cutAction, cut)
FUNCTION2(pasteAction, paste)
FUNCTION2(formatAction, format)
FUNCTION2(rewrapParagraphAction, rewrapParagraph)
FUNCTION2(selectAllAction, selectAll)
FUNCTION(cleanWhitespace)
FUNCTION(unCommentSelection)
......
......@@ -91,6 +91,7 @@ private slots:
void gotoAction();
void printAction();
void formatAction();
void rewrapParagraphAction();
void setVisualizeWhitespace(bool);
void cleanWhitespace();
void setTextWrapping(bool);
......@@ -125,6 +126,7 @@ private:
QAction *m_gotoAction;
QAction *m_printAction;
QAction *m_formatAction;
QAction *m_rewrapParagraphAction;
QAction *m_visualizeWhitespaceAction;
QAction *m_cleanWhitespaceAction;
QAction *m_textWrappingAction;
......
......@@ -60,8 +60,9 @@ const char * const CUT_LINE = "TextEditor.CutLine";
const char * const DELETE_LINE = "TextEditor.DeleteLine";
const char * const DELETE_WORD = "TextEditor.DeleteWord";
const char * const SELECT_ENCODING = "TextEditor.SelectEncoding";
const char * const REWRAP_PARAGRAPH = "TextEditor.RewrapParagraph";
const char * const GOTO_OPENING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoClosingParenthesis";
const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain";
const char * const C_TEXTEDITOR_MIMETYPE_XML = "application/xml";
......
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