OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / cppeditor / cppoutline.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "cppoutline.h"
34
35 #include <TranslationUnit.h>
36 #include <Symbol.h>
37
38 #include <coreplugin/ifile.h>
39 #include <coreplugin/editormanager/editormanager.h>
40 #include <cplusplus/OverviewModel.h>
41
42 #include <QtCore/QDebug>
43 #include <QtCore/QTimer>
44 #include <QtGui/QVBoxLayout>
45 #include <QtGui/QMenu>
46
47 using namespace CppEditor::Internal;
48
49 enum {
50     debug = false
51 };
52
53 CppOutlineTreeView::CppOutlineTreeView(QWidget *parent) :
54     Utils::NavigationTreeView(parent)
55 {
56     // see also QmlJSOutlineTreeView
57     setFocusPolicy(Qt::NoFocus);
58     setExpandsOnDoubleClick(false);
59 }
60
61 void CppOutlineTreeView::contextMenuEvent(QContextMenuEvent *event)
62 {
63     if (!event)
64         return;
65
66     QMenu contextMenu;
67
68     contextMenu.addAction(tr("Expand All"), this, SLOT(expandAll()));
69     contextMenu.addAction(tr("Collapse All"), this, SLOT(collapseAll()));
70
71     contextMenu.exec(event->globalPos());
72
73     event->accept();
74 }
75
76 CppOutlineFilterModel::CppOutlineFilterModel(CPlusPlus::OverviewModel *sourceModel, QObject *parent) :
77     QSortFilterProxyModel(parent),
78     m_sourceModel(sourceModel)
79 {
80     setSourceModel(m_sourceModel);
81 }
82
83 bool CppOutlineFilterModel::filterAcceptsRow(int sourceRow,
84                                              const QModelIndex &sourceParent) const
85 {
86     // ignore artifical "<Select Symbol>" entry
87     if (!sourceParent.isValid() && sourceRow == 0) {
88         return false;
89     }
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())
94         return false;
95
96     return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
97 }
98
99
100 CppOutlineWidget::CppOutlineWidget(CPPEditorWidget *editor) :
101     TextEditor::IOutlineWidget(),
102     m_editor(editor),
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)
108 {
109     QVBoxLayout *layout = new QVBoxLayout;
110     layout->setMargin(0);
111     layout->setSpacing(0);
112     layout->addWidget(m_treeView);
113     setLayout(layout);
114
115     m_treeView->setModel(m_proxyModel);
116
117     connect(m_model, SIGNAL(modelReset()), this, SLOT(modelUpdated()));
118     modelUpdated();
119
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)));
126 }
127
128 QList<QAction*> CppOutlineWidget::filterMenuActions() const
129 {
130     return QList<QAction*>();
131 }
132
133 void CppOutlineWidget::setCursorSynchronization(bool syncWithCursor)
134 {
135     m_enableCursorSync = syncWithCursor;
136     if (m_enableCursorSync)
137         updateSelectionInTree(m_editor->outlineModelIndex());
138 }
139
140 void CppOutlineWidget::modelUpdated()
141 {
142     m_treeView->expandAll();
143 }
144
145 void CppOutlineWidget::updateSelectionInTree(const QModelIndex &index)
146 {
147     if (!syncCursor())
148         return;
149
150     QModelIndex proxyIndex = m_proxyModel->mapFromSource(index);
151
152     m_blockCursorSync = true;
153     if (debug)
154         qDebug() << "CppOutline - updating selection due to cursor move";
155
156     m_treeView->selectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect);
157     m_treeView->scrollTo(proxyIndex);
158     m_blockCursorSync = false;
159 }
160
161 void CppOutlineWidget::updateSelectionInText(const QItemSelection &selection)
162 {
163     if (!syncCursor())
164         return;
165
166     if (!selection.indexes().isEmpty()) {
167         QModelIndex proxyIndex = selection.indexes().first();
168         updateTextCursor(proxyIndex);
169     }
170 }
171
172 void CppOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex)
173 {
174     QModelIndex index = m_proxyModel->mapToSource(proxyIndex);
175     CPlusPlus::Symbol *symbol = m_model->symbolFromIndex(index);
176     if (symbol) {
177         m_blockCursorSync = true;
178
179         if (debug)
180             qDebug() << "CppOutline - moving cursor to" << symbol->line() << symbol->column() - 1;
181
182         Core::EditorManager *editorManager = Core::EditorManager::instance();
183         editorManager->cutForwardNavigationHistory();
184         editorManager->addCurrentPositionToNavigationHistory();
185
186         // line has to be 1 based, column 0 based!
187         m_editor->gotoLine(symbol->line(), symbol->column() - 1);
188         m_blockCursorSync = false;
189     }
190 }
191
192 bool CppOutlineWidget::syncCursor()
193 {
194     return m_enableCursorSync && !m_blockCursorSync;
195 }
196
197 bool CppOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const
198 {
199     if (qobject_cast<CPPEditor*>(editor))
200         return true;
201     return false;
202 }
203
204 TextEditor::IOutlineWidget *CppOutlineWidgetFactory::createWidget(Core::IEditor *editor)
205 {
206     CPPEditor *cppEditor = qobject_cast<CPPEditor*>(editor);
207     CPPEditorWidget *cppEditorWidget = qobject_cast<CPPEditorWidget*>(cppEditor->widget());
208     Q_ASSERT(cppEditorWidget);
209
210     CppOutlineWidget *widget = new CppOutlineWidget(cppEditorWidget);
211
212     return widget;
213 }