diff options
author | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2014-05-23 13:55:03 -0400 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2014-06-13 18:04:52 +0200 |
commit | 4ecadb38a07e6bccb4fce74341eece23ef4f37d8 (patch) | |
tree | c88d9b570484b01d5508d703e13568ef1fa238e7 /src/plugins/cppeditor | |
parent | eaecac2fd91de739d87e232807349589f5beb5ef (diff) | |
download | qt-creator-4ecadb38a07e6bccb4fce74341eece23ef4f37d8.tar.gz |
CppEditor: Extract CppEditorOutline
Change-Id: I3b41f91f17ce9fb24796f2f6bff353fb3c6177ec
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src/plugins/cppeditor')
-rw-r--r-- | src/plugins/cppeditor/cppeditor.cpp | 239 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.h | 23 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.pro | 2 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.qbs | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditoroutline.cpp | 282 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditoroutline.h | 100 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorplugin.cpp | 16 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppoutline.cpp | 8 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppoutline.h | 2 |
9 files changed, 426 insertions, 247 deletions
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index c9922814df..26e0eb8f0f 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -31,6 +31,7 @@ #include "cppautocompleter.h" #include "cppeditorconstants.h" +#include "cppeditoroutline.h" #include "cppeditorplugin.h" #include "cppfollowsymbolundercursor.h" #include "cpphighlighter.h" @@ -67,7 +68,6 @@ #include <texteditor/refactoroverlay.h> #include <utils/qtcassert.h> -#include <utils/treeviewcombobox.h> #include <cplusplus/ASTPath.h> #include <cplusplus/BackwardsScanner.h> @@ -79,13 +79,11 @@ #include <QMenu> #include <QPointer> #include <QSignalMapper> -#include <QSortFilterProxyModel> #include <QTextEdit> #include <QTimer> #include <QToolButton> enum { - UPDATE_OUTLINE_INTERVAL = 500, UPDATE_USES_INTERVAL = 500, UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 }; @@ -96,31 +94,6 @@ using namespace CppEditor::Internal; namespace { -class OverviewProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - OverviewProxyModel(CPlusPlus::OverviewModel *sourceModel, QObject *parent) : - QSortFilterProxyModel(parent), - m_sourceModel(sourceModel) - { - setSourceModel(m_sourceModel); - } - - bool filterAcceptsRow(int sourceRow,const QModelIndex &sourceParent) const - { - // ignore generated symbols, e.g. by macro expansion (Q_OBJECT) - const QModelIndex sourceIndex = m_sourceModel->index(sourceRow, 0, sourceParent); - CPlusPlus::Symbol *symbol = m_sourceModel->symbolFromIndex(sourceIndex); - if (symbol && symbol->isGenerated()) - return false; - - return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); - } -private: - CPlusPlus::OverviewModel *m_sourceModel; -}; - class CanonicalSymbol { public: @@ -398,6 +371,14 @@ bool handleDoxygenContinuation(QTextCursor &cursor, return false; } +QTimer *newSingleShotTimer(QObject *parent, int msecInterval) +{ + QTimer *timer = new QTimer(parent); + timer->setSingleShot(true); + timer->setInterval(msecInterval); + return timer; +} + } // end of anonymous namespace namespace CppEditor { @@ -419,21 +400,14 @@ class CPPEditorWidgetPrivate public: CPPEditorWidgetPrivate(CPPEditorWidget *q); - QTimer *newSingleShowTimer(int msecInterval); - public: CPPEditorWidget *q; QPointer<CppTools::CppModelManagerInterface> m_modelManager; CPPEditorDocument *m_cppEditorDocument; - Utils::TreeViewComboBox *m_outlineCombo; - CPlusPlus::OverviewModel *m_outlineModel; - QModelIndex m_outlineModelIndex; - QSortFilterProxyModel *m_proxyModel; - QAction *m_sortAction; - QTimer *m_updateOutlineTimer; - QTimer *m_updateOutlineIndexTimer; + CppEditorOutline *m_cppEditorOutline; + QTimer *m_updateUsesTimer; QTimer *m_updateFunctionDeclDefLinkTimer; QHash<int, QTextCharFormat> m_semanticHighlightFormatMap; @@ -463,6 +437,7 @@ CPPEditorWidgetPrivate::CPPEditorWidgetPrivate(CPPEditorWidget *q) : q(q) , m_modelManager(CppModelManagerInterface::instance()) , m_cppEditorDocument(qobject_cast<CPPEditorDocument *>(q->baseTextDocument())) + , m_cppEditorOutline(new CppEditorOutline(q)) , m_localRenaming(q) , m_highlightRevision(0) , m_referencesRevision(0) @@ -474,14 +449,6 @@ CPPEditorWidgetPrivate::CPPEditorWidgetPrivate(CPPEditorWidget *q) { } -QTimer *CPPEditorWidgetPrivate::newSingleShowTimer(int msecInterval) -{ - QTimer *timer = new QTimer(q); - timer->setSingleShot(true); - timer->setInterval(msecInterval); - return timer; -} - CPPEditorWidget::CPPEditorWidget(QWidget *parent) : TextEditor::BaseTextEditorWidget(new CPPEditorDocument(), parent) { @@ -547,6 +514,11 @@ CPPEditorDocument *CPPEditorWidget::cppEditorDocument() const return d->m_cppEditorDocument; } +CppEditorOutline *CPPEditorWidget::outline() const +{ + return d->m_cppEditorOutline; +} + TextEditor::BaseTextEditor *CPPEditorWidget::createEditor() { CPPEditor *editable = new CPPEditor(this); @@ -556,49 +528,15 @@ TextEditor::BaseTextEditor *CPPEditorWidget::createEditor() void CPPEditorWidget::createToolBar(CPPEditor *editor) { - d->m_outlineCombo = new Utils::TreeViewComboBox; - d->m_outlineCombo->setMinimumContentsLength(22); - - // Make the combo box prefer to expand - QSizePolicy policy = d->m_outlineCombo->sizePolicy(); - policy.setHorizontalPolicy(QSizePolicy::Expanding); - d->m_outlineCombo->setSizePolicy(policy); - d->m_outlineCombo->setMaxVisibleItems(40); - - d->m_outlineModel = new OverviewModel(this); - d->m_proxyModel = new OverviewProxyModel(d->m_outlineModel, this); - if (CppEditorPlugin::instance()->sortedOutline()) - d->m_proxyModel->sort(0, Qt::AscendingOrder); - else - d->m_proxyModel->sort(-1, Qt::AscendingOrder); // don't sort yet, but set column for sortedOutline() - d->m_proxyModel->setDynamicSortFilter(true); - d->m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - d->m_outlineCombo->setModel(d->m_proxyModel); - - d->m_outlineCombo->setContextMenuPolicy(Qt::ActionsContextMenu); - d->m_sortAction = new QAction(tr("Sort Alphabetically"), d->m_outlineCombo); - d->m_sortAction->setCheckable(true); - d->m_sortAction->setChecked(sortedOutline()); - connect(d->m_sortAction, SIGNAL(toggled(bool)), - CppEditorPlugin::instance(), SLOT(setSortedOutline(bool))); - d->m_outlineCombo->addAction(d->m_sortAction); - - d->m_updateOutlineTimer = d->newSingleShowTimer(UPDATE_OUTLINE_INTERVAL); - connect(d->m_updateOutlineTimer, SIGNAL(timeout()), this, SLOT(updateOutlineNow())); - - d->m_updateOutlineIndexTimer = d->newSingleShowTimer(UPDATE_OUTLINE_INTERVAL); - connect(d->m_updateOutlineIndexTimer, SIGNAL(timeout()), this, SLOT(updateOutlineIndexNow())); - - d->m_updateUsesTimer = d->newSingleShowTimer(UPDATE_USES_INTERVAL); + d->m_updateUsesTimer = newSingleShotTimer(this, UPDATE_USES_INTERVAL); connect(d->m_updateUsesTimer, SIGNAL(timeout()), this, SLOT(updateUsesNow())); - d->m_updateFunctionDeclDefLinkTimer = d->newSingleShowTimer(UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL); + d->m_updateFunctionDeclDefLinkTimer = newSingleShotTimer(this, UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL); connect(d->m_updateFunctionDeclDefLinkTimer, SIGNAL(timeout()), this, SLOT(updateFunctionDeclDefLinkNow())); - connect(d->m_outlineCombo, SIGNAL(activated(int)), this, SLOT(jumpToOutlineElement())); - connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateOutlineIndex())); - connect(d->m_outlineCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateOutlineToolTip())); + connect(this, SIGNAL(cursorPositionChanged()), + d->m_cppEditorOutline, SLOT(updateIndex())); // set up slots to document changes connect(document(), SIGNAL(contentsChange(int,int,int)), @@ -619,7 +557,7 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor) updatePreprocessorButtonTooltip(); connect(d->m_preprocessorButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget())); editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, d->m_preprocessorButton); - editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, d->m_outlineCombo); + editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, d->m_cppEditorOutline->widget()); } void CPPEditorWidget::paste() @@ -650,7 +588,7 @@ void CPPEditorWidget::selectAll() /// file in this editor is updated. void CPPEditorWidget::onDocumentUpdated() { - d->m_updateOutlineTimer->start(); + d->m_cppEditorOutline->update(); } const Macro *CPPEditorWidget::findCanonicalMacro(const QTextCursor &cursor, Document::Ptr doc) const @@ -855,65 +793,6 @@ void CPPEditorWidget::updatePreprocessorButtonTooltip() d->m_preprocessorButton->setToolTip(cmd->action()->toolTip()); } -void CPPEditorWidget::jumpToOutlineElement() -{ - QModelIndex modelIndex = d->m_outlineCombo->view()->currentIndex(); - QModelIndex sourceIndex = d->m_proxyModel->mapToSource(modelIndex); - Symbol *symbol = d->m_outlineModel->symbolFromIndex(sourceIndex); - if (!symbol) - return; - - const Link &link = linkToSymbol(symbol); - gotoLine(link.targetLine, link.targetColumn); - Core::EditorManager::activateEditor(editor()); -} - -void CPPEditorWidget::setSortedOutline(bool sort) -{ - if (sort != sortedOutline()) { - if (sort) - d->m_proxyModel->sort(0, Qt::AscendingOrder); - else - d->m_proxyModel->sort(-1, Qt::AscendingOrder); - bool block = d->m_sortAction->blockSignals(true); - d->m_sortAction->setChecked(d->m_proxyModel->sortColumn() == 0); - d->m_sortAction->blockSignals(block); - updateOutlineIndexNow(); - } -} - -bool CPPEditorWidget::sortedOutline() const -{ - return (d->m_proxyModel->sortColumn() == 0); -} - -void CPPEditorWidget::updateOutlineNow() -{ - if (!d->m_modelManager) - return; - - const Snapshot snapshot = d->m_modelManager->snapshot(); - Document::Ptr document = snapshot.document(baseTextDocument()->filePath()); - - if (!document) - return; - - if (document->editorRevision() != editorRevision()) { - d->m_updateOutlineTimer->start(); - return; - } - - d->m_outlineModel->rebuild(document); - - d->m_outlineCombo->view()->expandAll(); - updateOutlineIndexNow(); -} - -void CPPEditorWidget::updateOutlineIndex() -{ - d->m_updateOutlineIndexTimer->start(); -} - QList<QTextEdit::ExtraSelection> CPPEditorWidget::createSelectionsFromUses( const QList<SemanticInfo::Use> &uses) { @@ -943,37 +822,6 @@ QList<QTextEdit::ExtraSelection> CPPEditorWidget::createSelectionsFromUses( return result; } -void CPPEditorWidget::updateOutlineIndexNow() -{ - if (!d->m_outlineModel->document()) - return; - - if (d->m_outlineModel->document()->editorRevision() != editorRevision()) { - d->m_updateOutlineIndexTimer->start(); - return; - } - - d->m_updateOutlineIndexTimer->stop(); - - d->m_outlineModelIndex = QModelIndex(); //invalidate - QModelIndex comboIndex = outlineModelIndex(); - - if (comboIndex.isValid()) { - bool blocked = d->m_outlineCombo->blockSignals(true); - - d->m_outlineCombo->setCurrentIndex(d->m_proxyModel->mapFromSource(comboIndex)); - - updateOutlineToolTip(); - - d->m_outlineCombo->blockSignals(blocked); - } -} - -void CPPEditorWidget::updateOutlineToolTip() -{ - d->m_outlineCombo->setToolTip(d->m_outlineCombo->currentText()); -} - void CPPEditorWidget::updateUses() { // Block premature semantic info calculation when editor is created. @@ -1125,23 +973,6 @@ SemanticInfo CPPEditorWidget::semanticInfo() const return d->m_lastSemanticInfo; } -CPlusPlus::OverviewModel *CPPEditorWidget::outlineModel() const -{ - return d->m_outlineModel; -} - -QModelIndex CPPEditorWidget::outlineModelIndex() -{ - if (!d->m_outlineModelIndex.isValid()) { - int line = 0, column = 0; - convertPosition(position(), &line, &column); - d->m_outlineModelIndex = indexForPosition(line, column); - emit outlineModelIndexChanged(d->m_outlineModelIndex); - } - - return d->m_outlineModelIndex; -} - bool CPPEditorWidget::event(QEvent *e) { switch (e->type()) { @@ -1415,28 +1246,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo) updateFunctionDeclDefLink(); } -QModelIndex CPPEditorWidget::indexForPosition(int line, int column, - const QModelIndex &rootIndex) const -{ - QModelIndex lastIndex = rootIndex; - - const int rowCount = d->m_outlineModel->rowCount(rootIndex); - for (int row = 0; row < rowCount; ++row) { - const QModelIndex index = d->m_outlineModel->index(row, 0, rootIndex); - Symbol *symbol = d->m_outlineModel->symbolFromIndex(index); - if (symbol && symbol->line() > unsigned(line)) - break; - lastIndex = index; - } - - if (lastIndex != rootIndex) { - // recurse - lastIndex = indexForPosition(line, column, lastIndex); - } - - return lastIndex; -} - TextEditor::IAssistInterface *CPPEditorWidget::createAssistInterface( TextEditor::AssistKind kind, TextEditor::AssistReason reason) const @@ -1722,5 +1531,3 @@ void CPPEditorWidget::showPreProcessorWidget() } // namespace Internal } // namespace CppEditor - -#include <cppeditor.moc> diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 11384c1c0e..71109d3b73 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -43,10 +43,7 @@ #include <QScopedPointer> -namespace CPlusPlus { -class OverviewModel; -class Symbol; -} +namespace CPlusPlus { class Symbol; } namespace CppTools { class SemanticInfo; @@ -56,6 +53,7 @@ class CommentsSettings; namespace CppEditor { namespace Internal { +class CppEditorOutline; class CPPEditorWidget; class CPPEditorWidgetPrivate; class FollowSymbolUnderCursor; @@ -93,12 +91,10 @@ public: ~CPPEditorWidget(); CPPEditorDocument *cppEditorDocument() const; + CppEditorOutline *outline() const; CppTools::SemanticInfo semanticInfo() const; - CPlusPlus::OverviewModel *outlineModel() const; - QModelIndex outlineModelIndex(); - QSharedPointer<FunctionDeclDefLink> declDefLink() const; void applyDeclDefLinkChanges(bool jumpToMatch); @@ -108,16 +104,12 @@ public: FollowSymbolUnderCursor *followSymbolUnderCursorDelegate(); // exposed for tests -signals: - void outlineModelIndexChanged(const QModelIndex &index); - public slots: void paste() QTC_OVERRIDE; void cut() QTC_OVERRIDE; void selectAll() QTC_OVERRIDE; void unCommentSelection() QTC_OVERRIDE; - void setSortedOutline(bool sort); void switchDeclarationDefinition(bool inNextSplit); void showPreProcessorWidget(); @@ -147,11 +139,6 @@ protected slots: void slotCodeStyleSettingsChanged(const QVariant &) QTC_OVERRIDE; private slots: - void jumpToOutlineElement(); - void updateOutlineNow(); - void updateOutlineIndex(); - void updateOutlineIndexNow(); - void updateOutlineToolTip(); void updateUses(); void updateUsesNow(); void updateFunctionDeclDefLink(); @@ -192,14 +179,10 @@ private: QTextCharFormat textCharFormat(TextEditor::TextStyle category); void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info); - bool sortedOutline() const; QList<QTextEdit::ExtraSelection> createSelectionsFromUses( const QList<TextEditor::HighlightingResult> &uses); - QModelIndex indexForPosition(int line, int column, - const QModelIndex &rootIndex = QModelIndex()) const; - bool handleDocumentationComment(QKeyEvent *e); bool isStartOfDoxygenComment(const QTextCursor &cursor) const; diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index bcaeea8628..6e8ff5552b 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -10,6 +10,7 @@ HEADERS += \ cppeditordocument.h \ cppeditorconstants.h \ cppeditorenums.h \ + cppeditoroutline.h \ cppeditorplugin.h \ cppelementevaluator.h \ cppfilewizard.h \ @@ -40,6 +41,7 @@ SOURCES += \ cppcodemodelinspectordialog.cpp \ cppeditor.cpp \ cppeditordocument.cpp \ + cppeditoroutline.cpp \ cppeditorplugin.cpp \ cppelementevaluator.cpp \ cppfilewizard.cpp \ diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 6a55755d8a..8a80874ef2 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -28,6 +28,7 @@ QtcPlugin { "cppeditorconstants.h", "cppeditordocument.cpp", "cppeditordocument.h", "cppeditorenums.h", + "cppeditoroutline.cpp", "cppeditoroutline.h", "cppeditorplugin.cpp", "cppeditorplugin.h", "cppelementevaluator.cpp", "cppelementevaluator.h", "cppfilewizard.cpp", "cppfilewizard.h", diff --git a/src/plugins/cppeditor/cppeditoroutline.cpp b/src/plugins/cppeditor/cppeditoroutline.cpp new file mode 100644 index 0000000000..5342704774 --- /dev/null +++ b/src/plugins/cppeditor/cppeditoroutline.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cppeditoroutline.h" + +#include "cppeditor.h" +#include "cppeditorplugin.h" + +#include <cpptools/cppmodelmanagerinterface.h> + +#include <cplusplus/OverviewModel.h> +#include <utils/treeviewcombobox.h> + +#include <QSortFilterProxyModel> +#include <QTimer> + +/*! + \class CppEditor::Internal::CppEditorOutline + \brief A helper class of CPPEditorWidget that provides the outline model + and widget, e.g. for the editor's tool bar. + + \internal + + The caller is responsible for deleting the widget returned by widget(). + + \sa CppEditor::Internal::CPPEditorWidget + */ + +enum { UpdateOutlineIntervalInMs = 500 }; + +namespace { + +class OverviewProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + OverviewProxyModel(CPlusPlus::OverviewModel *sourceModel, QObject *parent) + : QSortFilterProxyModel(parent) + , m_sourceModel(sourceModel) + { + setSourceModel(m_sourceModel); + } + + bool filterAcceptsRow(int sourceRow,const QModelIndex &sourceParent) const + { + // Ignore generated symbols, e.g. by macro expansion (Q_OBJECT) + const QModelIndex sourceIndex = m_sourceModel->index(sourceRow, 0, sourceParent); + CPlusPlus::Symbol *symbol = m_sourceModel->symbolFromIndex(sourceIndex); + if (symbol && symbol->isGenerated()) + return false; + + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); + } +private: + CPlusPlus::OverviewModel *m_sourceModel; +}; + +QTimer *newSingleShotTimer(QObject *parent, int msInternal) +{ + QTimer *timer = new QTimer(parent); + timer->setSingleShot(true); + timer->setInterval(msInternal); + return timer; +} + +} // anonymous namespace + +namespace CppEditor { +namespace Internal { + +CppEditorOutline::CppEditorOutline(CPPEditorWidget *editorWidget) + : QObject(editorWidget) + , m_editorWidget(editorWidget) + , m_combo(new Utils::TreeViewComboBox) + , m_model(new CPlusPlus::OverviewModel(this)) + , m_proxyModel(new OverviewProxyModel(m_model, this)) +{ + // Set up proxy model + if (CppEditorPlugin::instance()->sortedOutline()) + m_proxyModel->sort(0, Qt::AscendingOrder); + else + m_proxyModel->sort(-1, Qt::AscendingOrder); // don't sort yet, but set column for sortedOutline() + m_proxyModel->setDynamicSortFilter(true); + m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + + // Set up combo box + m_combo->setModel(m_proxyModel); + + m_combo->setMinimumContentsLength(22); + QSizePolicy policy = m_combo->sizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Expanding); + m_combo->setSizePolicy(policy); + m_combo->setMaxVisibleItems(40); + + m_combo->setContextMenuPolicy(Qt::ActionsContextMenu); + m_sortAction = new QAction(tr("Sort Alphabetically"), m_combo); + m_sortAction->setCheckable(true); + m_sortAction->setChecked(isSorted()); + connect(m_sortAction, SIGNAL(toggled(bool)), + CppEditorPlugin::instance(), SLOT(setSortedOutline(bool))); + m_combo->addAction(m_sortAction); + + connect(m_combo, SIGNAL(activated(int)), this, SLOT(gotoSymbolInEditor())); + connect(m_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateToolTip())); + + // Set up timers + m_updateTimer = newSingleShotTimer(this, UpdateOutlineIntervalInMs); + connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateNow())); + + m_updateIndexTimer = newSingleShotTimer(this, UpdateOutlineIntervalInMs); + connect(m_updateIndexTimer, SIGNAL(timeout()), this, SLOT(updateIndexNow())); +} + +void CppEditorOutline::update() +{ + m_updateTimer->start(); +} + +bool CppEditorOutline::isSorted() const +{ + return m_proxyModel->sortColumn() == 0; +} + +void CppEditorOutline::setSorted(bool sort) +{ + if (sort != isSorted()) { + if (sort) + m_proxyModel->sort(0, Qt::AscendingOrder); + else + m_proxyModel->sort(-1, Qt::AscendingOrder); + bool block = m_sortAction->blockSignals(true); + m_sortAction->setChecked(m_proxyModel->sortColumn() == 0); + m_sortAction->blockSignals(block); + updateIndexNow(); + } +} + +CPlusPlus::OverviewModel *CppEditorOutline::model() const +{ + return m_model; +} + +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; +} + +void CppEditorOutline::updateNow() +{ + CppTools::CppModelManagerInterface *cmmi = CppTools::CppModelManagerInterface::instance(); + if (!cmmi) + return; + + const CPlusPlus::Snapshot snapshot = cmmi->snapshot(); + const QString filePath = m_editorWidget->baseTextDocument()->filePath(); + CPlusPlus::Document::Ptr document = snapshot.document(filePath); + if (!document) + return; + + if (document->editorRevision() != (unsigned) m_editorWidget->document()->revision()) { + m_updateTimer->start(); + return; + } + + m_model->rebuild(document); + + m_combo->view()->expandAll(); + updateIndexNow(); +} + +void CppEditorOutline::updateIndex() +{ + m_updateIndexTimer->start(); +} + +void CppEditorOutline::updateIndexNow() +{ + if (!m_model->document()) + return; + + const unsigned revision = m_editorWidget->document()->revision(); + if (m_model->document()->editorRevision() != revision) { + m_updateIndexTimer->start(); + return; + } + + m_updateIndexTimer->stop(); + + m_modelIndex = QModelIndex(); //invalidate + QModelIndex comboIndex = modelIndex(); + + if (comboIndex.isValid()) { + bool blocked = m_combo->blockSignals(true); + m_combo->setCurrentIndex(m_proxyModel->mapFromSource(comboIndex)); + updateToolTip(); + m_combo->blockSignals(blocked); + } +} + +void CppEditorOutline::updateToolTip() +{ + m_combo->setToolTip(m_combo->currentText()); +} + +void CppEditorOutline::gotoSymbolInEditor() +{ + const QModelIndex modelIndex = m_combo->view()->currentIndex(); + const QModelIndex sourceIndex = m_proxyModel->mapToSource(modelIndex); + CPlusPlus::Symbol *symbol = m_model->symbolFromIndex(sourceIndex); + if (!symbol) + return; + + const TextEditor::BaseTextEditorWidget::Link &link = CPPEditorWidget::linkToSymbol(symbol); + m_editorWidget->gotoLine(link.targetLine, link.targetColumn); + Core::EditorManager::activateEditor(m_editorWidget->editor()); +} + +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); + CPlusPlus::Symbol *symbol = m_model->symbolFromIndex(index); + if (symbol && symbol->line() > unsigned(line)) + break; + lastIndex = index; + } + + if (lastIndex != rootIndex) { + // recurse + lastIndex = indexForPosition(line, column, lastIndex); + } + + return lastIndex; +} + +} // namespace Internal +} // namespace CppEditor + +#include <cppeditoroutline.moc> diff --git a/src/plugins/cppeditor/cppeditoroutline.h b/src/plugins/cppeditor/cppeditoroutline.h new file mode 100644 index 0000000000..126c8710ed --- /dev/null +++ b/src/plugins/cppeditor/cppeditoroutline.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CPPEDITOROUTLINE_H +#define CPPEDITOROUTLINE_H + +#include <QModelIndex> +#include <QObject> + +QT_BEGIN_NAMESPACE +class QAction; +class QSortFilterProxyModel; +class QTimer; +QT_END_NAMESPACE + +namespace CPlusPlus { class OverviewModel; } +namespace Utils { class TreeViewComboBox; } + +namespace CppEditor { +namespace Internal { + +class CPPEditorWidget; + +class CppEditorOutline : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(CppEditorOutline) + +public: + explicit CppEditorOutline(CPPEditorWidget *editorWidget); + + void update(); + + CPlusPlus::OverviewModel *model() const; + QModelIndex modelIndex(); + + QWidget *widget() const; // Must be deleted by client. + +signals: + void modelIndexChanged(const QModelIndex &index); + +public slots: + void updateIndex(); + void setSorted(bool sort); + +private slots: + void updateNow(); + void updateIndexNow(); + void updateToolTip(); + void gotoSymbolInEditor(); + +private: + CppEditorOutline(); + + bool isSorted() const; + QModelIndex indexForPosition(int line, int column, + const QModelIndex &rootIndex = QModelIndex()) const; + +private: + CPPEditorWidget *m_editorWidget; + + Utils::TreeViewComboBox *m_combo; // Not owned + CPlusPlus::OverviewModel *m_model; + QSortFilterProxyModel *m_proxyModel; + QModelIndex m_modelIndex; + QAction *m_sortAction; + QTimer *m_updateTimer; + QTimer *m_updateIndexTimer; +}; + +} // namespace Internal +} // namespace CppEditor + +#endif // CPPEDITOROUTLINE_H diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index d8202e5bfd..cd0b053fa3 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -30,19 +30,19 @@ #include "cppeditorplugin.h" #include "cppclasswizard.h" -#include "cppeditor.h" +#include "cppcodemodelinspectordialog.h" #include "cppeditorconstants.h" +#include "cppeditor.h" +#include "cppeditoroutline.h" #include "cppfilewizard.h" +#include "cpphighlighterfactory.h" #include "cpphoverhandler.h" -#include "cppoutline.h" -#include "cpptypehierarchy.h" #include "cppincludehierarchy.h" -#include "cppsnippetprovider.h" +#include "cppoutline.h" #include "cppquickfixassistant.h" #include "cppquickfixes.h" -#include "cpphighlighterfactory.h" - -#include "cppcodemodelinspectordialog.h" +#include "cppsnippetprovider.h" +#include "cpptypehierarchy.h" #include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/actionmanager/actionmanager.h> @@ -135,7 +135,7 @@ void CppEditorPlugin::initializeEditor(CPPEditorWidget *editor) // function combo box sorting connect(this, SIGNAL(outlineSortingChanged(bool)), - editor, SLOT(setSortedOutline(bool))); + editor->outline(), SLOT(setSorted(bool))); } void CppEditorPlugin::setSortedOutline(bool sorted) diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp index 0410af60f8..31c6cdee69 100644 --- a/src/plugins/cppeditor/cppoutline.cpp +++ b/src/plugins/cppeditor/cppoutline.cpp @@ -29,6 +29,8 @@ #include "cppoutline.h" +#include "cppeditoroutline.h" + #include <cplusplus/OverviewModel.h> #include <coreplugin/find/treeviewfind.h> @@ -92,7 +94,7 @@ CppOutlineWidget::CppOutlineWidget(CPPEditorWidget *editor) : TextEditor::IOutlineWidget(), m_editor(editor), m_treeView(new CppOutlineTreeView(this)), - m_model(m_editor->outlineModel()), + m_model(m_editor->outline()->model()), m_proxyModel(new CppOutlineFilterModel(m_model, this)), m_enableCursorSync(true), m_blockCursorSync(false) @@ -109,7 +111,7 @@ CppOutlineWidget::CppOutlineWidget(CPPEditorWidget *editor) : connect(m_model, SIGNAL(modelReset()), this, SLOT(modelUpdated())); modelUpdated(); - connect(m_editor, SIGNAL(outlineModelIndexChanged(QModelIndex)), + connect(m_editor->outline(), SIGNAL(modelIndexChanged(QModelIndex)), this, SLOT(updateSelectionInTree(QModelIndex))); connect(m_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateSelectionInText(QItemSelection))); @@ -126,7 +128,7 @@ void CppOutlineWidget::setCursorSynchronization(bool syncWithCursor) { m_enableCursorSync = syncWithCursor; if (m_enableCursorSync) - updateSelectionInTree(m_editor->outlineModelIndex()); + updateSelectionInTree(m_editor->outline()->modelIndex()); } void CppOutlineWidget::modelUpdated() diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h index 29969dc197..12ca590c14 100644 --- a/src/plugins/cppeditor/cppoutline.h +++ b/src/plugins/cppeditor/cppoutline.h @@ -38,6 +38,8 @@ #include <QSortFilterProxyModel> +namespace CPlusPlus { class OverviewModel; } + namespace CppEditor { namespace Internal { |