From afdff3c96ec01053e35022ea13dc1dd89535fa67 Mon Sep 17 00:00:00 2001 From: Adeel Asghar Date: Sun, 22 May 2016 16:18:39 +0200 Subject: [PATCH] Fixed annotation folding for quotes and comment blocks. If user moves inside the hidden block then unfold automatically. --- OMEdit/OMEditGUI/Editors/BaseEditor.cpp | 37 ++++++++- OMEdit/OMEditGUI/Editors/BaseEditor.h | 5 ++ OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp | 86 ++++++++++++++------- 3 files changed, 95 insertions(+), 33 deletions(-) diff --git a/OMEdit/OMEditGUI/Editors/BaseEditor.cpp b/OMEdit/OMEditGUI/Editors/BaseEditor.cpp index 20097e21fd7..abd0f816619 100644 --- a/OMEdit/OMEditGUI/Editors/BaseEditor.cpp +++ b/OMEdit/OMEditGUI/Editors/BaseEditor.cpp @@ -652,7 +652,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event) const int lineNumbersWidth = mpLineNumberArea->width() - collapseColumnWidth; while (block.isValid() && top <= event->rect().bottom()) { - QTextDocument *doc = document(); + QTextDocument *pTextDocument = document(); top = bottom; const qreal height = blockBoundingRect(block).height(); bottom = top + height; @@ -663,7 +663,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event) if (!nextVisibleBlock.isVisible()) { // invisible blocks do have zero line count - nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber()); + nextVisibleBlock = pTextDocument->findBlockByLineNumber(nextVisibleBlock.firstLineNumber()); nextVisibleBlockNumber = nextVisibleBlock.blockNumber(); } @@ -707,6 +707,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event) if (pTextEditorPage->getSyntaxHighlightingGroupBox()->isChecked() && pTextEditorPage->getCodeFoldingCheckBox()->isChecked()) { painter.save(); painter.setRenderHint(QPainter::Antialiasing, false); + painter.setPen(Qt::gray); TextBlockUserData *nextBlockUserData = BaseEditorDocumentLayout::testUserData(nextBlock); bool drawFoldingControl = nextBlockUserData && BaseEditorDocumentLayout::foldingIndent(block) < nextBlockUserData->foldingIndent(); @@ -715,7 +716,7 @@ void BaseEditor::PlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event) int boxWidth = foldBoxWidth(fm); int size = boxWidth / 4; QRect foldingMarkerBox(lineNumbersWidth + size, top + size, 2 * (size) + 1, 2 * (size) + 1); - QRect foldingLineBox(lineNumbersWidth + size, top, 2 * (size) + 1, fm.height()); + QRect foldingLineBox(lineNumbersWidth + size, top, 2 * (size) + 1, height); if (drawEnd) { painter.drawLine(QPointF(foldingLineBox.center().x(), foldingLineBox.top()), foldingLineBox.center()); @@ -883,6 +884,7 @@ void BaseEditor::PlainTextEdit::updateCursorPosition() Label *pCursorPositionLabel = mpBaseEditor->getModelWidget()->getCursorPositionLabel(); pCursorPositionLabel->setText(QString("Line: %1, Col: %2").arg(line).arg(column)); } + ensureCursorVisible(); } /*! @@ -995,6 +997,35 @@ void BaseEditor::PlainTextEdit::moveCursorVisible(bool ensureVisible) } } +/*! + * \brief BaseEditor::PlainTextEdit::ensureCursorVisible + * Makes sure cursor is visible when user moves it inside hidden block. + */ +void BaseEditor::PlainTextEdit::ensureCursorVisible() +{ + QTextBlock block = textCursor().block(); + if (!block.isVisible()) { + BaseEditorDocumentLayout *pDocumentLayout = qobject_cast(document()->documentLayout()); + // Open all folds of current line. + int indent = BaseEditorDocumentLayout::foldingIndent(block); + block = block.previous(); + while (block.isValid()) { + const int indent2 = BaseEditorDocumentLayout::foldingIndent(block); + if (BaseEditorDocumentLayout::canFold(block) && indent2 < indent) { + BaseEditorDocumentLayout::foldOrUnfold(block, true); + if (block.isVisible()) { + break; + } + indent = indent2; + } + block = block.previous(); + } + pDocumentLayout->requestUpdate(); + pDocumentLayout->emitDocumentSizeChanged(); + } + QPlainTextEdit::ensureCursorVisible(); +} + /*! * \brief BaseEditor::PlainTextEdit::highlightCurrentLine * Hightlights the current line. diff --git a/OMEdit/OMEditGUI/Editors/BaseEditor.h b/OMEdit/OMEditGUI/Editors/BaseEditor.h index d2ae1f9e055..b85e5d57f6f 100644 --- a/OMEdit/OMEditGUI/Editors/BaseEditor.h +++ b/OMEdit/OMEditGUI/Editors/BaseEditor.h @@ -103,6 +103,7 @@ class TextBlockUserData : public QTextBlockUserData : mFoldingIndent(0) , mFolded(false) , mFoldingEndIncluded(false) + , mFoldingState(false) , mLeadingSpaces(-1) {} ~TextBlockUserData(); @@ -142,6 +143,8 @@ class TextBlockUserData : public QTextBlockUserData // Set whether the last character of the folded region will show when the code is folded. inline void setFoldingEndIncluded(bool foldingEndIncluded) {mFoldingEndIncluded = foldingEndIncluded;} inline bool foldingEndIncluded() const {return mFoldingEndIncluded;} + inline void setFoldingState(bool foldingState) {mFoldingState = foldingState;} + inline bool foldingState() const {return mFoldingState;} inline void setLeadingSpaces(int leadingSpaces) {mLeadingSpaces = leadingSpaces;} inline int getLeadingSpaces() {return mLeadingSpaces;} @@ -151,6 +154,7 @@ class TextBlockUserData : public QTextBlockUserData int mFoldingIndent; bool mFolded; bool mFoldingEndIncluded; + bool mFoldingState; int mLeadingSpaces; }; @@ -194,6 +198,7 @@ class BaseEditor : public QWidget void toggleBreakpoint(const QString fileName, int lineNumber); void indentOrUnindent(bool doIndent); void moveCursorVisible(bool ensureVisible = true); + void ensureCursorVisible(); private: BaseEditor *mpBaseEditor; LineNumberArea *mpLineNumberArea; diff --git a/OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp b/OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp index ed0e656e568..a1e8d6fd41d 100644 --- a/OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp +++ b/OMEdit/OMEditGUI/Editors/ModelicaEditor.cpp @@ -708,10 +708,16 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text) /* Hand-written recognizer beats the crap known as QRegEx ;) */ int index = 0, startIndex = 0; int blockState = previousBlockState(); - // store parentheses info - Parentheses parentheses; + bool foldingState = false; + QTextBlock previousTextBlck = currentBlock().previous(); + TextBlockUserData *pPreviousTextBlockUserData = BaseEditorDocumentLayout::userData(previousTextBlck); + if (pPreviousTextBlockUserData) { + foldingState = pPreviousTextBlockUserData->foldingState(); + } QRegExp annotationRegExp("\\bannotation\\b"); int annotationIndex = annotationRegExp.indexIn(text); + // store parentheses info + Parentheses parentheses; TextBlockUserData *pTextBlockUserData = BaseEditorDocumentLayout::userData(currentBlock()); if (pTextBlockUserData) { pTextBlockUserData->clearParentheses(); @@ -742,21 +748,6 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text) blockState = 0; } break; - case 4: - if (text[index] == ';') { - if (index == text.length() - 1) { // if we have some text after closing the annotation then we don't want to fold it. - if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it. - pTextBlockUserData->setFoldingIndent(1); - } - pTextBlockUserData->setFoldingEndIncluded(true); - } else { - pTextBlockUserData->setFoldingIndent(0); - } - blockState = 0; - } else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it. - pTextBlockUserData->setFoldingIndent(1); - } - break; default: /* check if single line comment then set the blockstate to 1. */ if (text[index] == '/' && index+1 3) { + if (text[index] == ';') { + if (index == text.length() - 1) { // if we have some text after closing the annotation then we don't want to fold it. + if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it. + pTextBlockUserData->setFoldingIndent(1); + } + pTextBlockUserData->setFoldingEndIncluded(true); + } else { + pTextBlockUserData->setFoldingIndent(0); + } + foldingState = false; + } else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it. + pTextBlockUserData->setFoldingIndent(1); + } + } else if (annotationIndex < 0) { // if we have one line annotation, we don't want to fold it. + pTextBlockUserData->setFoldingIndent(1); + } else if (startIndex < annotationIndex) { // if we have annotation word before quote or comment block is starting then fold. + pTextBlockUserData->setFoldingIndent(1); + } + } else { + // if no single line comment, no multi line comment and no quotes then check for annotation start + if (blockState < 1 || blockState > 3) { + if (text[index] == 'a' && index+9setParentheses(parentheses); + if (foldingState) { + pTextBlockUserData->setFoldingState(true); + // Hanldle empty blocks inside annotaiton section + if (text.isEmpty() && foldingState) { + pTextBlockUserData->setFoldingIndent(1); + } + } // set text block user data setCurrentBlockUserData(pTextBlockUserData); } @@ -805,9 +830,6 @@ void ModelicaTextHighlighter::highlightMultiLine(const QString &text) setFormat(startIndex, text.length()-startIndex, mQuotationFormat); setCurrentBlockState(3); break; - case 4: - setCurrentBlockState(4); - break; } } @@ -820,6 +842,10 @@ void ModelicaTextHighlighter::highlightBlock(const QString &text) } // set text block state setCurrentBlockState(0); + TextBlockUserData *pTextBlockUserData = BaseEditorDocumentLayout::userData(currentBlock()); + if (pTextBlockUserData) { + pTextBlockUserData->setFoldingState(false); + } setFormat(0, text.length(), mpModelicaEditorPage->getTextRuleColor()); foreach (const HighlightingRule &rule, mHighlightingRules) { QRegExp expression(rule.mPattern);