1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "cppoutline.h"
35 #include <TranslationUnit.h>
38 #include <coreplugin/ifile.h>
39 #include <coreplugin/editormanager/editormanager.h>
40 #include <cplusplus/OverviewModel.h>
42 #include <QtCore/QDebug>
43 #include <QtCore/QTimer>
44 #include <QtGui/QVBoxLayout>
45 #include <QtGui/QMenu>
47 using namespace CppEditor::Internal;
53 CppOutlineTreeView::CppOutlineTreeView(QWidget *parent) :
54 Utils::NavigationTreeView(parent)
56 // see also QmlJSOutlineTreeView
57 setFocusPolicy(Qt::NoFocus);
58 setExpandsOnDoubleClick(false);
61 void CppOutlineTreeView::contextMenuEvent(QContextMenuEvent *event)
68 contextMenu.addAction(tr("Expand All"), this, SLOT(expandAll()));
69 contextMenu.addAction(tr("Collapse All"), this, SLOT(collapseAll()));
71 contextMenu.exec(event->globalPos());
76 CppOutlineFilterModel::CppOutlineFilterModel(CPlusPlus::OverviewModel *sourceModel, QObject *parent) :
77 QSortFilterProxyModel(parent),
78 m_sourceModel(sourceModel)
80 setSourceModel(m_sourceModel);
83 bool CppOutlineFilterModel::filterAcceptsRow(int sourceRow,
84 const QModelIndex &sourceParent) const
86 // ignore artifical "<Select Symbol>" entry
87 if (!sourceParent.isValid() && sourceRow == 0) {
90 // ignore generated symbols, e.g. by macro expansion (Q_OBJECT)
91 const QModelIndex sourceIndex = m_sourceModel->index(sourceRow, 0, sourceParent);
92 CPlusPlus::Symbol *symbol = m_sourceModel->symbolFromIndex(sourceIndex);
93 if (symbol && symbol->isGenerated())
96 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
100 CppOutlineWidget::CppOutlineWidget(CPPEditorWidget *editor) :
101 TextEditor::IOutlineWidget(),
103 m_treeView(new CppOutlineTreeView(this)),
104 m_model(m_editor->outlineModel()),
105 m_proxyModel(new CppOutlineFilterModel(m_model, this)),
106 m_enableCursorSync(true),
107 m_blockCursorSync(false)
109 QVBoxLayout *layout = new QVBoxLayout;
110 layout->setMargin(0);
111 layout->setSpacing(0);
112 layout->addWidget(m_treeView);
115 m_treeView->setModel(m_proxyModel);
117 connect(m_model, SIGNAL(modelReset()), this, SLOT(modelUpdated()));
120 connect(m_editor, SIGNAL(outlineModelIndexChanged(QModelIndex)),
121 this, SLOT(updateSelectionInTree(QModelIndex)));
122 connect(m_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
123 this, SLOT(updateSelectionInText(QItemSelection)));
124 connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)),
125 this, SLOT(updateTextCursor(QModelIndex)));
128 QList<QAction*> CppOutlineWidget::filterMenuActions() const
130 return QList<QAction*>();
133 void CppOutlineWidget::setCursorSynchronization(bool syncWithCursor)
135 m_enableCursorSync = syncWithCursor;
136 if (m_enableCursorSync)
137 updateSelectionInTree(m_editor->outlineModelIndex());
140 void CppOutlineWidget::modelUpdated()
142 m_treeView->expandAll();
145 void CppOutlineWidget::updateSelectionInTree(const QModelIndex &index)
150 QModelIndex proxyIndex = m_proxyModel->mapFromSource(index);
152 m_blockCursorSync = true;
154 qDebug() << "CppOutline - updating selection due to cursor move";
156 m_treeView->selectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect);
157 m_treeView->scrollTo(proxyIndex);
158 m_blockCursorSync = false;
161 void CppOutlineWidget::updateSelectionInText(const QItemSelection &selection)
166 if (!selection.indexes().isEmpty()) {
167 QModelIndex proxyIndex = selection.indexes().first();
168 updateTextCursor(proxyIndex);
172 void CppOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex)
174 QModelIndex index = m_proxyModel->mapToSource(proxyIndex);
175 CPlusPlus::Symbol *symbol = m_model->symbolFromIndex(index);
177 m_blockCursorSync = true;
180 qDebug() << "CppOutline - moving cursor to" << symbol->line() << symbol->column() - 1;
182 Core::EditorManager *editorManager = Core::EditorManager::instance();
183 editorManager->cutForwardNavigationHistory();
184 editorManager->addCurrentPositionToNavigationHistory();
186 // line has to be 1 based, column 0 based!
187 m_editor->gotoLine(symbol->line(), symbol->column() - 1);
188 m_blockCursorSync = false;
192 bool CppOutlineWidget::syncCursor()
194 return m_enableCursorSync && !m_blockCursorSync;
197 bool CppOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const
199 if (qobject_cast<CPPEditor*>(editor))
204 TextEditor::IOutlineWidget *CppOutlineWidgetFactory::createWidget(Core::IEditor *editor)
206 CPPEditor *cppEditor = qobject_cast<CPPEditor*>(editor);
207 CPPEditorWidget *cppEditorWidget = qobject_cast<CPPEditorWidget*>(cppEditor->widget());
208 Q_ASSERT(cppEditorWidget);
210 CppOutlineWidget *widget = new CppOutlineWidget(cppEditorWidget);