1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "cppoutline.h"
36 #include <TranslationUnit.h>
39 #include <coreplugin/ifile.h>
40 #include <coreplugin/editormanager/editormanager.h>
41 #include <cplusplus/OverviewModel.h>
43 #include <QtCore/QDebug>
44 #include <QtCore/QTimer>
45 #include <QtGui/QVBoxLayout>
46 #include <QtGui/QMenu>
48 using namespace CppEditor::Internal;
54 CppOutlineTreeView::CppOutlineTreeView(QWidget *parent) :
55 Utils::NavigationTreeView(parent)
57 // see also QmlJSOutlineTreeView
58 setFocusPolicy(Qt::NoFocus);
59 setExpandsOnDoubleClick(false);
62 void CppOutlineTreeView::contextMenuEvent(QContextMenuEvent *event)
69 contextMenu.addAction(tr("Expand All"), this, SLOT(expandAll()));
70 contextMenu.addAction(tr("Collapse All"), this, SLOT(collapseAll()));
72 contextMenu.exec(event->globalPos());
77 CppOutlineFilterModel::CppOutlineFilterModel(CPlusPlus::OverviewModel *sourceModel, QObject *parent) :
78 QSortFilterProxyModel(parent),
79 m_sourceModel(sourceModel)
81 setSourceModel(m_sourceModel);
84 bool CppOutlineFilterModel::filterAcceptsRow(int sourceRow,
85 const QModelIndex &sourceParent) const
87 // ignore artifical "<Select Symbol>" entry
88 if (!sourceParent.isValid() && sourceRow == 0) {
91 // ignore generated symbols, e.g. by macro expansion (Q_OBJECT)
92 const QModelIndex sourceIndex = m_sourceModel->index(sourceRow, 0, sourceParent);
93 CPlusPlus::Symbol *symbol = m_sourceModel->symbolFromIndex(sourceIndex);
94 if (symbol && symbol->isGenerated())
97 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
101 CppOutlineWidget::CppOutlineWidget(CPPEditorWidget *editor) :
102 TextEditor::IOutlineWidget(),
104 m_treeView(new CppOutlineTreeView(this)),
105 m_model(m_editor->outlineModel()),
106 m_proxyModel(new CppOutlineFilterModel(m_model, this)),
107 m_enableCursorSync(true),
108 m_blockCursorSync(false)
110 QVBoxLayout *layout = new QVBoxLayout;
111 layout->setMargin(0);
112 layout->setSpacing(0);
113 layout->addWidget(m_treeView);
116 m_treeView->setModel(m_proxyModel);
118 connect(m_model, SIGNAL(modelReset()), this, SLOT(modelUpdated()));
121 connect(m_editor, SIGNAL(outlineModelIndexChanged(QModelIndex)),
122 this, SLOT(updateSelectionInTree(QModelIndex)));
123 connect(m_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
124 this, SLOT(updateSelectionInText(QItemSelection)));
125 connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)),
126 this, SLOT(updateTextCursor(QModelIndex)));
129 QList<QAction*> CppOutlineWidget::filterMenuActions() const
131 return QList<QAction*>();
134 void CppOutlineWidget::setCursorSynchronization(bool syncWithCursor)
136 m_enableCursorSync = syncWithCursor;
137 if (m_enableCursorSync)
138 updateSelectionInTree(m_editor->outlineModelIndex());
141 void CppOutlineWidget::modelUpdated()
143 m_treeView->expandAll();
146 void CppOutlineWidget::updateSelectionInTree(const QModelIndex &index)
151 QModelIndex proxyIndex = m_proxyModel->mapFromSource(index);
153 m_blockCursorSync = true;
155 qDebug() << "CppOutline - updating selection due to cursor move";
157 m_treeView->selectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect);
158 m_treeView->scrollTo(proxyIndex);
159 m_blockCursorSync = false;
162 void CppOutlineWidget::updateSelectionInText(const QItemSelection &selection)
167 if (!selection.indexes().isEmpty()) {
168 QModelIndex proxyIndex = selection.indexes().first();
169 updateTextCursor(proxyIndex);
173 void CppOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex)
175 QModelIndex index = m_proxyModel->mapToSource(proxyIndex);
176 CPlusPlus::Symbol *symbol = m_model->symbolFromIndex(index);
178 m_blockCursorSync = true;
181 qDebug() << "CppOutline - moving cursor to" << symbol->line() << symbol->column() - 1;
183 Core::EditorManager *editorManager = Core::EditorManager::instance();
184 editorManager->cutForwardNavigationHistory();
185 editorManager->addCurrentPositionToNavigationHistory();
187 // line has to be 1 based, column 0 based!
188 m_editor->gotoLine(symbol->line(), symbol->column() - 1);
189 m_blockCursorSync = false;
193 bool CppOutlineWidget::syncCursor()
195 return m_enableCursorSync && !m_blockCursorSync;
198 bool CppOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const
200 if (qobject_cast<CPPEditor*>(editor))
205 TextEditor::IOutlineWidget *CppOutlineWidgetFactory::createWidget(Core::IEditor *editor)
207 CPPEditor *cppEditor = qobject_cast<CPPEditor*>(editor);
208 CPPEditorWidget *cppEditorWidget = qobject_cast<CPPEditorWidget*>(cppEditor->widget());
209 Q_ASSERT(cppEditorWidget);
211 CppOutlineWidget *widget = new CppOutlineWidget(cppEditorWidget);