diff --git a/src/plugins/cppeditor/cppeditoroutline.cpp b/src/plugins/cppeditor/cppeditoroutline.cpp index f2d0c7b0d62..70a74075fa6 100644 --- a/src/plugins/cppeditor/cppeditoroutline.cpp +++ b/src/plugins/cppeditor/cppeditoroutline.cpp @@ -140,18 +140,6 @@ bool CppEditorOutline::isSorted() const return m_proxyModel->sortColumn() == 0; } -QModelIndex CppEditorOutline::modelIndex() -{ - if (!m_modelIndex.isValid()) { - int line = 0, column = 0; - m_editorWidget->convertPosition(m_editorWidget->position(), &line, &column); - m_modelIndex = indexForPosition(line, column); - emit modelIndexChanged(m_modelIndex); - } - - return m_modelIndex; -} - QWidget *CppEditorOutline::widget() const { return m_combo; @@ -184,8 +172,9 @@ void CppEditorOutline::updateIndexNow() m_updateIndexTimer->stop(); - m_modelIndex = QModelIndex(); //invalidate - QModelIndex comboIndex = modelIndex(); + int line = 0, column = 0; + m_editorWidget->convertPosition(m_editorWidget->position(), &line, &column); + QModelIndex comboIndex = m_model->indexForPosition(line, column); if (comboIndex.isValid()) { QSignalBlocker blocker(m_combo); @@ -214,41 +203,6 @@ void CppEditorOutline::gotoSymbolInEditor() emit m_editorWidget->activateEditor(); } -static bool contains(const OverviewModel::Range &range, int line, int column) -{ - if (line < range.first.line || line > range.second.line) - return false; - if (line == range.first.line && column < range.first.column) - return false; - if (line == range.second.line && column > range.second.column) - return false; - return true; -} - -QModelIndex CppEditorOutline::indexForPosition(int line, int column, - const QModelIndex &rootIndex) const -{ - QModelIndex lastIndex = rootIndex; - const int rowCount = m_model->rowCount(rootIndex); - for (int row = 0; row < rowCount; ++row) { - const QModelIndex index = m_model->index(row, 0, rootIndex); - const OverviewModel::Range range = m_model->rangeFromIndex(index); - if (range.first.line > line) - break; - // Skip ranges that do not include current line and column. - if (range.second != range.first && !contains(range, line, column)) - continue; - lastIndex = index; - } - - if (lastIndex != rootIndex) { - // recurse - lastIndex = indexForPosition(line, column, lastIndex); - } - - return lastIndex; -} - } // namespace CppEditor::Internal #include diff --git a/src/plugins/cppeditor/cppeditoroutline.h b/src/plugins/cppeditor/cppeditoroutline.h index d1461075d3f..f8a05d90e81 100644 --- a/src/plugins/cppeditor/cppeditoroutline.h +++ b/src/plugins/cppeditor/cppeditoroutline.h @@ -53,13 +53,8 @@ class CppEditorOutline : public QObject public: explicit CppEditorOutline(CppEditorWidget *editorWidget); - QModelIndex modelIndex(); - QWidget *widget() const; // Must be deleted by client. -signals: - void modelIndexChanged(const QModelIndex &index); - public slots: void updateIndex(); @@ -72,8 +67,6 @@ private: CppEditorOutline(); bool isSorted() const; - QModelIndex indexForPosition(int line, int column, - const QModelIndex &rootIndex = QModelIndex()) const; OverviewModel *m_model = nullptr; // Not owned @@ -81,7 +74,6 @@ private: Utils::TreeViewComboBox *m_combo = nullptr; // Not owned QSortFilterProxyModel *m_proxyModel = nullptr; - QModelIndex m_modelIndex; QAction *m_sortAction = nullptr; QTimer *m_updateIndexTimer = nullptr; }; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 214edaad5a3..dd87c18c5cb 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -597,11 +597,6 @@ CppEditorDocument *CppEditorWidget::cppEditorDocument() const return d->m_cppEditorDocument; } -CppEditorOutline *CppEditorWidget::outline() const -{ - return d->m_cppEditorOutline; -} - void CppEditorWidget::paste() { if (d->m_localRenaming.handlePaste()) diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h index c1670f1caa2..1a8098816f2 100644 --- a/src/plugins/cppeditor/cppeditorwidget.h +++ b/src/plugins/cppeditor/cppeditorwidget.h @@ -57,7 +57,6 @@ public: ~CppEditorWidget() override; Internal::CppEditorDocument *cppEditorDocument() const; - Internal::CppEditorOutline *outline() const; bool isSemanticInfoValidExceptLocalUses() const; bool isSemanticInfoValid() const; diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp index 1e298d589fe..63696504b40 100644 --- a/src/plugins/cppeditor/cppoutline.cpp +++ b/src/plugins/cppeditor/cppoutline.cpp @@ -99,13 +99,13 @@ Qt::DropActions CppOutlineFilterModel::supportedDragActions() const CppOutlineWidget::CppOutlineWidget(CppEditorWidget *editor) : m_editor(editor), m_treeView(new CppOutlineTreeView(this)), + m_model(&m_editor->cppEditorDocument()->outlineModel()), + m_proxyModel(new CppOutlineFilterModel(*m_model, this)), m_enableCursorSync(true), m_blockCursorSync(false), m_sorted(false) { - OverviewModel *model = &m_editor->cppEditorDocument()->outlineModel(); - m_proxyModel = new CppOutlineFilterModel(*model, this); - m_proxyModel->setSourceModel(model); + m_proxyModel->setSourceModel(m_model); auto *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); @@ -117,13 +117,19 @@ CppOutlineWidget::CppOutlineWidget(CppEditorWidget *editor) : m_treeView->setSortingEnabled(true); setFocusProxy(m_treeView); - connect(model, &QAbstractItemModel::modelReset, this, &CppOutlineWidget::modelUpdated); + connect(m_model, &QAbstractItemModel::modelReset, this, &CppOutlineWidget::modelUpdated); modelUpdated(); - connect(m_editor->outline(), &CppEditorOutline::modelIndexChanged, - this, &CppOutlineWidget::updateSelectionInTree); connect(m_treeView, &QAbstractItemView::activated, this, &CppOutlineWidget::onItemActivated); + connect(editor, &QPlainTextEdit::cursorPositionChanged, this, [this] { + if (m_model->rootItem()->hasChildren()) + updateIndex(); + }); + + m_updateIndexTimer.setSingleShot(true); + m_updateIndexTimer.setInterval(500); + connect(&m_updateIndexTimer, &QTimer::timeout, this, &CppOutlineWidget::updateIndexNow); } QList CppOutlineWidget::filterMenuActions() const @@ -135,7 +141,7 @@ void CppOutlineWidget::setCursorSynchronization(bool syncWithCursor) { m_enableCursorSync = syncWithCursor; if (m_enableCursorSync) - updateSelectionInTree(m_editor->outline()->modelIndex()); + updateIndexNow(); } bool CppOutlineWidget::isSorted() const @@ -164,17 +170,37 @@ void CppOutlineWidget::modelUpdated() m_treeView->expandAll(); } -void CppOutlineWidget::updateSelectionInTree(const QModelIndex &index) +void CppOutlineWidget::updateIndex() +{ + m_updateIndexTimer.start(); +} + +void CppOutlineWidget::updateIndexNow() { if (!syncCursor()) return; - QModelIndex proxyIndex = m_proxyModel->mapFromSource(index); + const auto revision = static_cast(m_editor->document()->revision()); + if (m_model->editorRevision() != revision) { + m_editor->cppEditorDocument()->updateOutline(); + m_updateIndexTimer.start(); + return; + } + + m_updateIndexTimer.stop(); + + int line = 0, column = 0; + m_editor->convertPosition(m_editor->position(), &line, &column); + QModelIndex index = m_model->indexForPosition(line, column); + + if (index.isValid()) { + m_blockCursorSync = true; + QModelIndex proxyIndex = m_proxyModel->mapFromSource(index); + m_treeView->setCurrentIndex(proxyIndex); + m_treeView->scrollTo(proxyIndex); + m_blockCursorSync = false; + } - m_blockCursorSync = true; - m_treeView->setCurrentIndex(proxyIndex); - m_treeView->scrollTo(proxyIndex); - m_blockCursorSync = false; } void CppOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex) diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h index 9da1fb9082c..053213fd4c9 100644 --- a/src/plugins/cppeditor/cppoutline.h +++ b/src/plugins/cppeditor/cppoutline.h @@ -33,6 +33,7 @@ #include #include +#include namespace CppEditor { namespace Internal { @@ -75,7 +76,8 @@ public: QVariantMap settings() const override; private: void modelUpdated(); - void updateSelectionInTree(const QModelIndex &index); + void updateIndex(); + void updateIndexNow(); void updateTextCursor(const QModelIndex &index); void onItemActivated(const QModelIndex &index); bool syncCursor(); @@ -83,7 +85,9 @@ private: private: CppEditorWidget *m_editor; CppOutlineTreeView *m_treeView; + OverviewModel * const m_model; QSortFilterProxyModel *m_proxyModel; + QTimer m_updateIndexTimer; bool m_enableCursorSync; bool m_blockCursorSync; diff --git a/src/plugins/cppeditor/cppoverviewmodel.cpp b/src/plugins/cppeditor/cppoverviewmodel.cpp index bc1ea2e0f90..a2cfd794701 100644 --- a/src/plugins/cppeditor/cppoverviewmodel.cpp +++ b/src/plugins/cppeditor/cppoverviewmodel.cpp @@ -290,4 +290,39 @@ void OverviewModel::buildTree(SymbolItem *root, bool isRoot) } } +static bool contains(const OverviewModel::Range &range, int line, int column) +{ + if (line < range.first.line || line > range.second.line) + return false; + if (line == range.first.line && column < range.first.column) + return false; + if (line == range.second.line && column > range.second.column) + return false; + return true; +} + +QModelIndex OverviewModel::indexForPosition(int line, int column, + const QModelIndex &rootIndex) const +{ + QModelIndex lastIndex = rootIndex; + const int rowCount = this->rowCount(rootIndex); + for (int row = 0; row < rowCount; ++row) { + const QModelIndex index = this->index(row, 0, rootIndex); + const OverviewModel::Range range = rangeFromIndex(index); + if (range.first.line > line) + break; + // Skip ranges that do not include current line and column. + if (range.second != range.first && !contains(range, line, column)) + continue; + lastIndex = index; + } + + if (lastIndex != rootIndex) { + // recurse + lastIndex = indexForPosition(line, column, lastIndex); + } + + return lastIndex; +} + } // namespace CppEditor::Internal diff --git a/src/plugins/cppeditor/cppoverviewmodel.h b/src/plugins/cppeditor/cppoverviewmodel.h index 436901496b4..6f29eed62b0 100644 --- a/src/plugins/cppeditor/cppoverviewmodel.h +++ b/src/plugins/cppeditor/cppoverviewmodel.h @@ -70,6 +70,8 @@ public: using Range = std::pair; Range rangeFromIndex(const QModelIndex &sourceIndex) const; + QModelIndex indexForPosition(int line, int column, const QModelIndex &rootIndex = {}) const; + private: void rebuild(); CPlusPlus::Symbol *symbolFromIndex(const QModelIndex &index) const;