forked from qt-creator/qt-creator
CppEditor: Extract CppEditorOutline
Change-Id: I3b41f91f17ce9fb24796f2f6bff353fb3c6177ec Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
@@ -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>
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 \
|
||||
|
@@ -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",
|
||||
|
282
src/plugins/cppeditor/cppeditoroutline.cpp
Normal file
282
src/plugins/cppeditor/cppeditoroutline.cpp
Normal file
@@ -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>
|
100
src/plugins/cppeditor/cppeditoroutline.h
Normal file
100
src/plugins/cppeditor/cppeditoroutline.h
Normal file
@@ -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
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -38,6 +38,8 @@
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
namespace CPlusPlus { class OverviewModel; }
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
|
Reference in New Issue
Block a user