summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorDenis Mingulov <denis.mingulov@gmail.com>2010-07-16 11:18:30 +0200
committerKai Koehne <kai.koehne@nokia.com>2010-07-16 11:24:02 +0200
commitae8192ad5a88384962f105bd5e18a50784d3edf0 (patch)
treec03e2856e6fa7de518e1ec064942865433929128 /src/plugins
parent915ba478d3ad304be86d7bc2693b17bdc85e755f (diff)
downloadqt-creator-ae8192ad5a88384962f105bd5e18a50784d3edf0.tar.gz
ClassView: Initial implementation
Merge-request: 2167 Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/classview/ClassView.pluginspec22
-rw-r--r--src/plugins/classview/classview.pro38
-rw-r--r--src/plugins/classview/classview.qrc5
-rw-r--r--src/plugins/classview/classview_dependencies.pri7
-rw-r--r--src/plugins/classview/classviewconstants.h62
-rw-r--r--src/plugins/classview/classviewmanager.cpp380
-rw-r--r--src/plugins/classview/classviewmanager.h247
-rw-r--r--src/plugins/classview/classviewnavigationwidget.cpp254
-rw-r--r--src/plugins/classview/classviewnavigationwidget.h148
-rw-r--r--src/plugins/classview/classviewnavigationwidget.ui46
-rw-r--r--src/plugins/classview/classviewnavigationwidgetfactory.cpp150
-rw-r--r--src/plugins/classview/classviewnavigationwidgetfactory.h107
-rw-r--r--src/plugins/classview/classviewparser.cpp688
-rw-r--r--src/plugins/classview/classviewparser.h265
-rw-r--r--src/plugins/classview/classviewparsertreeitem.cpp373
-rw-r--r--src/plugins/classview/classviewparsertreeitem.h190
-rw-r--r--src/plugins/classview/classviewplugin.cpp89
-rw-r--r--src/plugins/classview/classviewplugin.h71
-rw-r--r--src/plugins/classview/classviewsymbolinformation.cpp81
-rw-r--r--src/plugins/classview/classviewsymbolinformation.h89
-rw-r--r--src/plugins/classview/classviewsymbollocation.cpp57
-rw-r--r--src/plugins/classview/classviewsymbollocation.h82
-rw-r--r--src/plugins/classview/classviewtreeitemmodel.cpp129
-rw-r--r--src/plugins/classview/classviewtreeitemmodel.h77
-rw-r--r--src/plugins/classview/classviewutils.cpp232
-rw-r--r--src/plugins/classview/classviewutils.h110
-rw-r--r--src/plugins/classview/images/hierarchicalmode.pngbin0 -> 573 bytes
-rw-r--r--src/plugins/plugins.pro7
28 files changed, 4006 insertions, 0 deletions
diff --git a/src/plugins/classview/ClassView.pluginspec b/src/plugins/classview/ClassView.pluginspec
new file mode 100644
index 0000000000..af18b6b88b
--- /dev/null
+++ b/src/plugins/classview/ClassView.pluginspec
@@ -0,0 +1,22 @@
+<plugin name="ClassView" version="2.1.80" compatVersion="2.1.80">
+ <vendor>Nokia Corporation</vendor>
+ <copyright>(C) 2010 Denis Mingulov</copyright>
+ <license>
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia.
+
+GNU Lesser General Public License Usage
+
+Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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.
+ </license>
+ <category>Qt Creator</category>
+ <description>Class View component.</description>
+ <url>http://qt.nokia.com</url>
+ <dependencyList>
+ <dependency name="Core" version="2.1.80"/>
+ <dependency name="CppTools" version="2.1.80"/>
+ <dependency name="ProjectExplorer" version="2.1.80"/>
+ <dependency name="TextEditor" version="2.1.80"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/classview/classview.pro b/src/plugins/classview/classview.pro
new file mode 100644
index 0000000000..d6de0d148a
--- /dev/null
+++ b/src/plugins/classview/classview.pro
@@ -0,0 +1,38 @@
+TEMPLATE = lib
+TARGET = ClassView
+
+include(classview_dependencies.pri)
+
+HEADERS += \
+ classviewplugin.h \
+ classviewnavigationwidgetfactory.h \
+ classviewconstants.h \
+ classviewnavigationwidget.h \
+ classviewparser.h \
+ classviewmanager.h \
+ classviewsymbollocation.h \
+ classviewsymbolinformation.h \
+ classviewparsertreeitem.h \
+ classviewutils.h \
+ classviewtreeitemmodel.h
+
+SOURCES += \
+ classviewplugin.cpp \
+ classviewnavigationwidgetfactory.cpp \
+ classviewnavigationwidget.cpp \
+ classviewparser.cpp \
+ classviewmanager.cpp \
+ classviewsymbollocation.cpp \
+ classviewsymbolinformation.cpp \
+ classviewparsertreeitem.cpp \
+ classviewutils.cpp \
+ classviewtreeitemmodel.cpp
+
+OTHER_FILES += \
+ ClassView.pluginspec
+
+FORMS += \
+ classviewnavigationwidget.ui
+
+RESOURCES += \
+ classview.qrc
diff --git a/src/plugins/classview/classview.qrc b/src/plugins/classview/classview.qrc
new file mode 100644
index 0000000000..189357bc0b
--- /dev/null
+++ b/src/plugins/classview/classview.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/classview">
+ <file>images/hierarchicalmode.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/classview/classview_dependencies.pri b/src/plugins/classview/classview_dependencies.pri
new file mode 100644
index 0000000000..fd0ecfea3f
--- /dev/null
+++ b/src/plugins/classview/classview_dependencies.pri
@@ -0,0 +1,7 @@
+include(../../qtcreatorplugin.pri)
+include(../../libs/utils/utils.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/cpptools/cpptools.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../libs/cplusplus/cplusplus.pri)
+include(../../plugins/texteditor/texteditor.pri)
diff --git a/src/plugins/classview/classviewconstants.h b/src/plugins/classview/classviewconstants.h
new file mode 100644
index 0000000000..17b03bd560
--- /dev/null
+++ b/src/plugins/classview/classviewconstants.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWCONSTANTS_H
+#define CLASSVIEWCONSTANTS_H
+
+namespace ClassView {
+namespace Constants {
+
+//! Navi Widget Factory id
+const char * const CLASSVIEWNAVIGATION_ID = "Class View";
+
+//! Settings' group
+const char * const CLASSVIEW_SETTINGS_GROUP = "ClassView";
+
+//! Settings' prefix for the tree widget
+const char * const CLASSVIEW_SETTINGS_TREEWIDGET_PREFIX = "TreeWidget.";
+
+//! Flat mode settings
+const char * const CLASSVIEW_SETTINGS_FLATMODE = "FlatMode";
+
+//! Delay in msecs before an update
+const int CLASSVIEW_EDITINGTREEUPDATE_DELAY = 400;
+
+//! QStandardItem roles
+enum ItemRole {
+ SymbolLocationsRole = Qt::UserRole + 1, //!< Symbol locations
+ IconTypeRole, //!< Icon type (integer)
+ SymbolNameRole, //!< Symbol name
+ SymbolTypeRole //!< Symbol type
+};
+
+} // namespace Constants
+} // namespace ClassView
+
+#endif // CLASSVIEWCONSTANTS_H
diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp
new file mode 100644
index 0000000000..b602333684
--- /dev/null
+++ b/src/plugins/classview/classviewmanager.cpp
@@ -0,0 +1,380 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewsymbollocation.h"
+#include "classviewmanager.h"
+#include "classviewnavigationwidgetfactory.h"
+#include "classviewparser.h"
+#include "classviewutils.h"
+
+#include <utils/qtcassert.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <texteditor/basetexteditor.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <texteditor/itexteditor.h>
+
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// ManagerPrivate //////////////////////////////////
+
+/*!
+ \struct ManagerPrivate
+ \brief Private class data for \a Manager
+ \sa Manager
+ */
+struct ManagerPrivate
+{
+ ManagerPrivate() : state(false) {}
+
+ //! instance
+ static Manager *instance;
+
+ //! Pointer to widget factory
+ QPointer<NavigationWidgetFactory> widgetFactory;
+
+ //! State mutex
+ QMutex mutexState;
+
+ //! Internal manager state. \sa Manager::state
+ bool state;
+
+ //! code state/changes parser
+ Parser parser;
+
+ //! separate thread for the parser
+ QThread parserThread;
+
+ //! cpp code model manager
+ QPointer<CppTools::CppModelManagerInterface> codeModelManager;
+
+ //! there is some massive operation ongoing so temporary we should wait
+ bool disableCodeParser;
+};
+
+// static variable initialization
+Manager *ManagerPrivate::instance = 0;
+
+///////////////////////////////// Manager //////////////////////////////////
+
+Manager::Manager(QObject *parent)
+ : QObject(parent),
+ d_ptr(new ManagerPrivate())
+{
+ d_ptr->widgetFactory = NavigationWidgetFactory::instance();
+
+ // register - to be able send between signal/slots
+ qRegisterMetaType<QSharedPointer<QStandardItem> >("QSharedPointer<QStandardItem>");
+
+ initialize();
+
+ // start a separate thread for the parser
+ d_ptr->parser.moveToThread(&d_ptr->parserThread);
+ d_ptr->parserThread.start();
+
+ // initial setup
+ onProjectListChanged();
+}
+
+Manager::~Manager()
+{
+ d_ptr->parserThread.quit();
+ d_ptr->parserThread.wait();
+}
+
+Manager *Manager::instance(QObject *parent)
+{
+ if (!ManagerPrivate::instance)
+ ManagerPrivate::instance = new Manager(parent);
+ return ManagerPrivate::instance;
+}
+
+bool Manager::canFetchMore(QStandardItem *item) const
+{
+ return d_ptr->parser.canFetchMore(item);
+}
+
+void Manager::fetchMore(QStandardItem *item, bool skipRoot)
+{
+ d_ptr->parser.fetchMore(item, skipRoot);
+}
+
+void Manager::initialize()
+{
+ // use Qt::QueuedConnection everywhere
+
+ // widget factory signals
+ connect(d_ptr->widgetFactory, SIGNAL(widgetIsCreated()),
+ SLOT(onWidgetIsCreated()), Qt::QueuedConnection);
+
+ // internal manager state is changed
+ connect(this, SIGNAL(stateChanged(bool)), SLOT(onStateChanged(bool)), Qt::QueuedConnection);
+
+ // connections to enable/disbale navi widget factory
+ ProjectExplorer::SessionManager *sessionManager =
+ ProjectExplorer::ProjectExplorerPlugin::instance()->session();
+ connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
+ SLOT(onProjectListChanged()), Qt::QueuedConnection);
+ connect(sessionManager, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
+ SLOT(onProjectListChanged()), Qt::QueuedConnection);
+
+ Core::ICore *core = Core::ICore::instance();
+
+ // connect to the progress manager for signals about Parsing tasks
+ connect(core->progressManager(), SIGNAL(taskStarted(QString)),
+ SLOT(onTaskStarted(QString)), Qt::QueuedConnection);
+ connect(core->progressManager(), SIGNAL(allTasksFinished(QString)),
+ SLOT(onAllTasksFinished(QString)), Qt::QueuedConnection);
+
+ // connect to the cpp model manager for signals about document updates
+ d_ptr->codeModelManager = CppTools::CppModelManagerInterface::instance();
+
+ // when code manager signals that document is updated - handle it by ourselves
+ connect(d_ptr->codeModelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
+ SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)), Qt::QueuedConnection);
+
+ // when we signals that really document is updated - sent it to the parser
+ connect(this, SIGNAL(requestDocumentUpdated(CPlusPlus::Document::Ptr)),
+ &d_ptr->parser, SLOT(parseDocument(CPlusPlus::Document::Ptr)), Qt::QueuedConnection);
+
+ //
+ connect(d_ptr->codeModelManager, SIGNAL(aboutToRemoveFiles(QStringList)),
+ &d_ptr->parser, SLOT(removeFiles(QStringList)), Qt::QueuedConnection);
+
+ // translate data update from the parser to listeners
+ connect(&d_ptr->parser, SIGNAL(treeDataUpdate(QSharedPointer<QStandardItem>)),
+ this, SLOT(onTreeDataUpdate(QSharedPointer<QStandardItem>)), Qt::QueuedConnection);
+
+ // requet current state - immediately after a notification
+ connect(this, SIGNAL(requestTreeDataUpdate()),
+ &d_ptr->parser, SLOT(requestCurrentState()), Qt::QueuedConnection);
+
+ // full reset request to parser
+ connect(this, SIGNAL(requestResetCurrentState()),
+ &d_ptr->parser, SLOT(resetDataToCurrentState()), Qt::QueuedConnection);
+
+ // clear cache request
+ connect(this, SIGNAL(requestClearCache()),
+ &d_ptr->parser, SLOT(clearCache()), Qt::QueuedConnection);
+
+ // clear full cache request
+ connect(this, SIGNAL(requestClearCacheAll()),
+ &d_ptr->parser, SLOT(clearCacheAll()), Qt::QueuedConnection);
+
+ // flat mode request
+ connect(this, SIGNAL(requestSetFlatMode(bool)),
+ &d_ptr->parser, SLOT(setFlatMode(bool)), Qt::QueuedConnection);
+}
+
+bool Manager::state() const
+{
+ return d_ptr->state;
+}
+
+void Manager::setState(bool state)
+{
+ QMutexLocker locker(&d_ptr->mutexState);
+
+ // boolean comparsion - should be done correctly by any compiler
+ if (state == d_ptr->state)
+ return;
+
+ d_ptr->state = state;
+
+ emit stateChanged(d_ptr->state);
+}
+
+void Manager::onWidgetIsCreated()
+{
+ // do nothing - continue to sleep
+}
+
+void Manager::onWidgetVisibilityIsChanged(bool visibility)
+{
+ // activate data handling - when 1st time 'Class View' will be open
+ if (visibility)
+ setState(true);
+}
+
+void Manager::onStateChanged(bool state)
+{
+ if (state) {
+ // enabled - request a current snapshots etc?..
+ emit requestResetCurrentState();
+ } else {
+ // disabled - clean parsers internal cache
+ emit requestClearCacheAll();
+ }
+}
+
+void Manager::onProjectListChanged()
+{
+ // do nothing if Manager is disabled
+ if (!state())
+ return;
+
+ // update to the latest state
+ requestTreeDataUpdate();
+}
+
+void Manager::onTaskStarted(const QString &type)
+{
+ if (type != CppTools::Constants::TASK_INDEX)
+ return;
+
+ // disable tree updates to speed up
+ d_ptr->disableCodeParser = true;
+}
+
+void Manager::onAllTasksFinished(const QString &type)
+{
+ if (type != CppTools::Constants::TASK_INDEX)
+ return;
+
+ // parsing is finished, enable tree updates
+ d_ptr->disableCodeParser = false;
+
+ // do nothing if Manager is disabled
+ if (!state())
+ return;
+
+ // any document might be changed, emit signal to clear cache
+ emit requestClearCache();
+
+ // request to update a tree to the current state
+ emit requestResetCurrentState();
+}
+
+void Manager::onDocumentUpdated(CPlusPlus::Document::Ptr doc)
+{
+ // do nothing if Manager is disabled
+ if (!state())
+ return;
+
+ // do nothing if updates are disabled
+ if (d_ptr->disableCodeParser)
+ return;
+
+ emit requestDocumentUpdated(doc);
+}
+
+void Manager::gotoLocation(const QString &fileName, int line, int column)
+{
+ bool newEditor = false;
+ TextEditor::BaseTextEditor::openEditorAt(fileName, line, column, QString(), &newEditor);
+}
+
+void Manager::gotoLocations(const QList<QVariant> &list)
+{
+ QSet<SymbolLocation> locations = Utils::roleToLocations(list);
+
+ if (locations.count() == 0)
+ return;
+
+ QString fileName;
+ int line = 0;
+ int column = 0;
+ bool currentPositionAvailable = false;
+
+ // what is open now?
+ Core::IEditor *editor = Core::EditorManager::instance()->currentEditor();
+ if (editor) {
+ // get current file name
+ Core::IFile *file = editor->file();
+ if (file)
+ fileName = file->fileName();
+
+ // if text file - what is current position?
+ TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
+ if (textEditor) {
+ // there is open currently text editor
+ int position = textEditor->position();
+ textEditor->convertPosition(position, &line, &column);
+ currentPositionAvailable = true;
+ }
+ }
+
+ // if there is something open - try to check, is it currently activated symbol?
+ if (currentPositionAvailable) {
+ SymbolLocation current(fileName, line, column);
+ QSet<SymbolLocation>::const_iterator it = locations.find(current);
+ QSet<SymbolLocation>::const_iterator end = locations.constEnd();
+ // is it known location?
+ if (it != end) {
+ // found - do one additional step
+ ++it;
+ if (it == end)
+ it = locations.begin();
+ const SymbolLocation &found = *it;
+ gotoLocation(found.fileName(), found.line(), found.column());
+ return;
+ }
+ }
+
+ // no success - open first item in the list
+ const SymbolLocation loc = *locations.constBegin();
+
+ gotoLocation(loc.fileName(), loc.line(), loc.column());
+}
+
+void Manager::onRequestTreeDataUpdate()
+{
+ // do nothing if Manager is disabled
+ if (!state())
+ return;
+
+ emit requestTreeDataUpdate();
+}
+
+void Manager::setFlatMode(bool flat)
+{
+ emit requestSetFlatMode(flat);
+}
+
+void Manager::onTreeDataUpdate(QSharedPointer<QStandardItem> result)
+{
+ // do nothing if Manager is disabled
+ if (!state())
+ return;
+
+ emit treeDataUpdate(result);
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewmanager.h b/src/plugins/classview/classviewmanager.h
new file mode 100644
index 0000000000..3fb99f30b4
--- /dev/null
+++ b/src/plugins/classview/classviewmanager.h
@@ -0,0 +1,247 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWMANAGER_H
+#define CLASSVIEWMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QStandardItem>
+
+#include <cplusplus/CppDocument.h>
+
+namespace ClassView {
+namespace Internal {
+
+class NavigationWidgetFactory;
+
+/*!
+ \class Manager
+ \brief Class View manager
+
+ Class View Manager. Interacts with other Qt Creator plugins - this is a proxy between them and
+ parser.
+ \a Parser is moved to a separate thread and is connected to \a Manager by signal/slots.
+ Manager's signals starting with 'request' are for Parser.
+ */
+
+class Manager : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(Manager)
+
+public:
+ /*!
+ \brief
+ \param widgetFactory NavigationWidgetFactory
+ \param parent Parent object
+ */
+ virtual ~Manager();
+
+ //! Get an instance of Manager
+ static Manager *instance(QObject *parent = 0);
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item with has to be checked
+ */
+ bool canFetchMore(QStandardItem *item) const;
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item with has to be checked
+ \param skipRoot Skip root item (is needed for the manual update, call not from model)
+ */
+ void fetchMore(QStandardItem *item, bool skipRoot = false);
+
+signals:
+ /*!
+ \brief Internal Manager state is changed.
+ \param state true if Manager is enabled, false otherwise
+ \sa setState, state
+ */
+ void stateChanged(bool state);
+
+ /*!
+ \brief Signal about a tree data update (to tree view).
+ \param result Item with the current tree
+ */
+ void treeDataUpdate(QSharedPointer<QStandardItem> result);
+
+ /*!
+ \brief Signal that a request for sending tree view has to be handled by listeners (parser).
+ \sa onRequestTreeDataUpdate
+ */
+ void requestTreeDataUpdate();
+
+ /*!
+ \brief Signal that document is updated (and has to be reparsed)
+ \param doc Updated document
+ \sa onDocumentUpdated
+ */
+ void requestDocumentUpdated(CPlusPlus::Document::Ptr doc);
+
+ /*!
+ \brief Signal that parser has to reset its internal state to the current (from code manager).
+ */
+ void requestResetCurrentState();
+
+ /*!
+ \brief Request to clear a cache by parser.
+ */
+ void requestClearCache();
+
+ /*!
+ \brief Request to clear a full cache by parser.
+ */
+ void requestClearCacheAll();
+
+ /*!
+ \brief Request to set the flat mode (without subprojects)
+ \param flat True to enable flat mode, false to disable
+ */
+ void requestSetFlatMode(bool flat);
+
+public slots:
+ /*!
+ \brief Open text editor for file \a fileName on line \a lineNumber and column \a column.
+ \param fileName File which has to be open
+ \param lineNumber Line
+ \param column Column
+ */
+ void gotoLocation(const QString &fileName, int line = 0, int column = 0);
+
+ /*!
+ \brief Open text editor for any of location in the list (correctly)
+ \param locations Symbol locations
+ \sa Manager::gotoLocations
+ */
+ void gotoLocations(const QList<QVariant> &locations);
+
+ /*!
+ \brief If somebody wants to receive the latest tree info, if a parsing is enabled then
+ a signal \a requestTreeDataUpdate will be emitted.
+ \sa requestTreeDataUpdate, NavigationWidget::requestDataUpdate
+ */
+ void onRequestTreeDataUpdate();
+
+ /*!
+ \brief Switch to flat mode (without subprojects)
+ \param flat True to enable flat mode, false to disable
+ */
+ void setFlatMode(bool flat);
+
+protected slots:
+ /*!
+ \brief Widget factory creates a widget, handle this situation.
+ \sa setState, state
+ */
+ void onWidgetIsCreated();
+
+ /*!
+ \brief Widget visibility is changed
+ \param visibility Visibility (for just 1 navi pane widget, there might be a lot of them)
+ \sa setState, state
+ */
+ void onWidgetVisibilityIsChanged(bool visibility);
+
+ /*!
+ \brief Reacts to the state changed signal, e.g. request currect code snapshot if needed etc.
+ \param state Current Manager state
+ \sa setState, state, stateChanged
+ */
+ void onStateChanged(bool state);
+
+ /*!
+ \brief Project list is changed (navigation pane visibility might be needed to update).
+ */
+ void onProjectListChanged();
+
+ /*!
+ \brief This slot should called when the code model manager state is changed for \a doc.
+ It will emit a signal \a documentUpdated if
+ \param doc Updated document.
+ \sa documentUpdated
+ */
+ void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
+
+ /*!
+ \brief Progress manager started a task. Do what is needed if it is a parse task.
+ \param type Task index, should be CppTools::Constants::TASK_INDEX for us
+ \sa CppTools::Constants::TASK_INDEX
+ */
+ void onTaskStarted(const QString &type);
+
+ /*!
+ \brief Progress manager finished all task with specified type.
+ Do what is needed if it is a parse task.
+ \param type Task index, should be CppTools::Constants::TASK_INDEX for us
+ \sa CppTools::Constants::TASK_INDEX
+ */
+ void onAllTasksFinished(const QString &type);
+
+ /*!
+ \brief New tree data update (has to be sent to a tree view).
+ \param result Item with the current tree
+ */
+ void onTreeDataUpdate(QSharedPointer<QStandardItem> result);
+
+protected:
+ //! Perform an initialization
+ void initialize();
+
+ /*!
+ \brief Get internal Manager state. If it is disabled, signals about parsing request has not
+ to be emitted at all, if enabled - do parsing in the background even if navi pane
+ is not visible.
+ \return true if Manager is enabled, false otherwise
+ \sa setState, stateChanged
+ */
+ inline bool state() const;
+
+ /*!
+ \brief Set internal Manager state.
+ \param true if Manager has to be enabled, false otherwise
+ \sa state, stateChanged
+ */
+ void setState(bool state);
+
+private:
+ explicit Manager(QObject *parent = 0);
+
+private:
+ //! private class data pointer
+ QScopedPointer<struct ManagerPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWMANAGER_H
diff --git a/src/plugins/classview/classviewnavigationwidget.cpp b/src/plugins/classview/classviewnavigationwidget.cpp
new file mode 100644
index 0000000000..a90a58fa82
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.cpp
@@ -0,0 +1,254 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewnavigationwidget.h"
+#include "ui_classviewnavigationwidget.h"
+#include "classviewtreeitemmodel.h"
+#include "classviewmanager.h"
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include "classviewutils.h"
+#include "classviewconstants.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QPointer>
+
+enum { debug = false };
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// NavigationWidgetPrivate //////////////////////////////////
+
+/*!
+ \struct NavigationWidgetPrivate
+ \brief Internal data structures / methods for NavigationWidget
+ */
+
+struct NavigationWidgetPrivate
+{
+ NavigationWidgetPrivate() : ui(0) {}
+
+ //! Ui generated by Designer
+ Ui::NavigationWidget *ui;
+
+ //! current tree model
+ QPointer<TreeItemModel> treeModel;
+
+ //! full projects mode
+ QPointer<QToolButton> fullProjectsModeButton;
+};
+
+///////////////////////////////// NavigationWidget //////////////////////////////////
+
+
+NavigationWidget::NavigationWidget(QWidget *parent) :
+ QWidget(parent),
+ d_ptr(new NavigationWidgetPrivate())
+{
+ d_ptr->ui = new Ui::NavigationWidget;
+ d_ptr->ui->setupUi(this);
+ d_ptr->ui->treeView->setIndentation(d_ptr->ui->treeView->indentation() * 9/10);
+
+ // tree model
+ d_ptr->treeModel = new TreeItemModel(this);
+ d_ptr->ui->treeView->setModel(d_ptr->treeModel);
+
+ // connect signal/slots
+ // selected item
+ connect(d_ptr->ui->treeView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex)));
+
+ // connections to the manager
+ Manager *manager = Manager::instance();
+
+ connect(this, SIGNAL(visibilityChanged(bool)),
+ manager, SLOT(onWidgetVisibilityIsChanged(bool)));
+
+ connect(this, SIGNAL(requestGotoLocation(QString,int,int)),
+ manager, SLOT(gotoLocation(QString,int,int)));
+
+ connect(this, SIGNAL(requestGotoLocations(QList<QVariant>)),
+ manager, SLOT(gotoLocations(QList<QVariant>)));
+
+ connect(manager, SIGNAL(treeDataUpdate(QSharedPointer<QStandardItem>)),
+ this, SLOT(onDataUpdate(QSharedPointer<QStandardItem>)));
+
+ connect(this, SIGNAL(requestTreeDataUpdate()),
+ manager, SLOT(onRequestTreeDataUpdate()));
+}
+
+NavigationWidget::~NavigationWidget()
+{
+ delete d_ptr->fullProjectsModeButton;
+ delete d_ptr->ui;
+}
+
+void NavigationWidget::hideEvent(QHideEvent *event)
+{
+ emit visibilityChanged(false);
+ QWidget::hideEvent(event);
+}
+
+void NavigationWidget::showEvent(QShowEvent *event)
+{
+ emit visibilityChanged(true);
+
+ // request to update to the current state - to be sure
+ emit requestTreeDataUpdate();
+
+ QWidget::showEvent(event);
+}
+
+QList<QToolButton *> NavigationWidget::createToolButtons()
+{
+ QList<QToolButton *> list;
+
+ // full projects mode
+ if (!d_ptr->fullProjectsModeButton) {
+ // create a button
+ d_ptr->fullProjectsModeButton = new QToolButton();
+ d_ptr->fullProjectsModeButton->setIcon(
+ QIcon(QLatin1String(":/classview/images/hierarchicalmode.png")));
+ d_ptr->fullProjectsModeButton->setCheckable(true);
+ d_ptr->fullProjectsModeButton->setToolTip(tr("Show subprojects"));
+
+ // by default - not a flat mode
+ setFlatMode(false);
+
+ // connections
+ connect(d_ptr->fullProjectsModeButton, SIGNAL(toggled(bool)),
+ this, SLOT(onFullProjectsModeToggled(bool)));
+ }
+
+ list << d_ptr->fullProjectsModeButton;
+
+ return list;
+}
+
+bool NavigationWidget::flatMode() const
+{
+ QTC_ASSERT(d_ptr->fullProjectsModeButton, return false);
+
+ // button is 'full projects mode' - so it has to be inverted
+ return !d_ptr->fullProjectsModeButton->isChecked();
+}
+
+void NavigationWidget::setFlatMode(bool flatMode)
+{
+ QTC_ASSERT(d_ptr->fullProjectsModeButton, return);
+
+ // button is 'full projects mode' - so it has to be inverted
+ d_ptr->fullProjectsModeButton->setChecked(!flatMode);
+}
+
+void NavigationWidget::onFullProjectsModeToggled(bool state)
+{
+ // button is 'full projects mode' - so it has to be inverted
+ Manager::instance()->setFlatMode(!state);
+}
+
+void NavigationWidget::onItemActivated(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+
+ QList<QVariant> list = d_ptr->treeModel->data(index, Constants::SymbolLocationsRole).toList();
+
+ emit requestGotoLocations(list);
+}
+
+void NavigationWidget::onDataUpdate(QSharedPointer<QStandardItem> result)
+{
+ if (result.isNull())
+ return;
+
+ // if this is 1st call
+ bool expandRootItems = false;
+ if (d_ptr->treeModel->invisibleRootItem()->rowCount() == 0)
+ expandRootItems = true;
+
+ QTime timer;
+ if (debug)
+ timer.start();
+ // update is received. root item must be updated - and received information
+ // might be just a root - if a lazy data population is enabled.
+ // so expanded items must be parsed and 'fetched'
+
+ fetchExpandedItems(result.data(), d_ptr->treeModel->invisibleRootItem());
+
+ d_ptr->treeModel->moveRootToTarget(result.data());
+
+ // expand top level projects
+ QModelIndex sessionIndex;
+
+ for (int i = 0; i < d_ptr->treeModel->rowCount(sessionIndex); ++i)
+ d_ptr->ui->treeView->expand(d_ptr->treeModel->index(i, 0, sessionIndex));
+
+ if (debug)
+ qDebug() << "Class View:" << QDateTime::currentDateTime().toString()
+ << "TreeView is updated in" << timer.elapsed() << "msecs";
+}
+
+void NavigationWidget::fetchExpandedItems(QStandardItem *item, const QStandardItem *target) const
+{
+ if (!item || !target)
+ return;
+
+ const QModelIndex &parent = d_ptr->treeModel->indexFromItem(target);
+ if (d_ptr->ui->treeView->isExpanded(parent))
+ Manager::instance()->fetchMore(item, true);
+
+ int itemIndex = 0;
+ int targetIndex = 0;
+ int itemRows = item->rowCount();
+ int targetRows = target->rowCount();
+
+ while (itemIndex < itemRows && targetIndex < targetRows) {
+ QStandardItem *itemChild = item->child(itemIndex);
+ const QStandardItem *targetChild = target->child(targetIndex);
+
+ const SymbolInformation &itemInf = Utils::symbolInformationFromItem(itemChild);
+ const SymbolInformation &targetInf = Utils::symbolInformationFromItem(targetChild);
+
+ if (itemInf < targetInf) {
+ ++itemIndex;
+ } else if (itemInf == targetInf) {
+ fetchExpandedItems(itemChild, targetChild);
+ ++itemIndex;
+ ++targetIndex;
+ } else {
+ ++targetIndex;
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewnavigationwidget.h b/src/plugins/classview/classviewnavigationwidget.h
new file mode 100644
index 0000000000..d431763453
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.h
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWNAVIGATIONWIDGET_H
+#define CLASSVIEWNAVIGATIONWIDGET_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QToolButton>
+#include <QtGui/QStandardItem>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class NavigationWidget
+ \brief A widget for the class view tree
+ */
+
+class NavigationWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(NavigationWidget)
+
+public:
+ explicit NavigationWidget(QWidget *parent = 0);
+ ~NavigationWidget();
+
+ /*!
+ \brief Create QToolbuttons for Navigation Pane Widget
+ \return List with created QToolButtons
+ \sa NavigationWidgetFactory::createWidget
+ */
+ QList<QToolButton *> createToolButtons();
+
+ /*!
+ \brief Get flat mode state
+ \return Flat mode state
+ */
+ bool flatMode() const;
+
+ /*!
+ \brief Set flat mode state
+ \param flatMode Flat mode state
+ */
+ void setFlatMode(bool flatMode);
+
+signals:
+ /*!
+ \brief Widget visibility is changed
+ \param visibility true is plugin becames visible, false otherwise
+ */
+ void visibilityChanged(bool visibility);
+
+ /*!
+ \brief Signal to request to go to location
+ \param name File which has to be open
+ \param line Line
+ \param column Column
+ \sa Manager::gotoLocation
+ */
+ void requestGotoLocation(const QString &name, int line, int column);
+
+ /*!
+ \brief Signal to request to go to any of location in the list
+ \param locations Symbol locations
+ \sa Manager::gotoLocations
+ */
+ void requestGotoLocations(const QList<QVariant> &locations);
+
+ /*!
+ \brief Signal that the widget wants to receive the latest tree info
+ \sa Manager::onRequestTreeDataUpdate
+ */
+ void requestTreeDataUpdate();
+
+public slots:
+ /*!
+ \brief Item is activated in the tree view
+ \param index Item index
+ */
+ void onItemActivated(const QModelIndex &index);
+
+ /*!
+ \brief Receive a new data for the tree
+ \param Result - root item
+ */
+ void onDataUpdate(QSharedPointer<QStandardItem> result);
+
+ /*!
+ \brief Full projects' mode button has been toggled
+ \param state Full projects' mode
+ */
+ void onFullProjectsModeToggled(bool state);
+
+protected:
+ /*!
+ \brief Fetch data for expanded items - to be sure that content will exist
+ \param item
+ \param target
+ */
+ void fetchExpandedItems(QStandardItem *item, const QStandardItem *target) const;
+
+ //! implements QWidget::hideEvent
+ void hideEvent(QHideEvent *event);
+
+ //! implements QWidget::showEvent
+ void showEvent(QShowEvent *event);
+
+private:
+ //! Private class data pointer
+ QScopedPointer<struct NavigationWidgetPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWNAVIGATIONWIDGET_H
diff --git a/src/plugins/classview/classviewnavigationwidget.ui b/src/plugins/classview/classviewnavigationwidget.ui
new file mode 100644
index 0000000000..d9ba960515
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClassView::Internal::NavigationWidget</class>
+ <widget class="QWidget" name="ClassView::Internal::NavigationWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideNone</enum>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="headerHidden">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/classview/classviewnavigationwidgetfactory.cpp b/src/plugins/classview/classviewnavigationwidgetfactory.cpp
new file mode 100644
index 0000000000..2209c7fdc3
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidgetfactory.cpp
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewnavigationwidgetfactory.h"
+#include "classviewnavigationwidget.h"
+#include "classviewconstants.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QKeySequence>
+#include <QtCore/QSettings>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// NavigationWidget //////////////////////////////////
+
+/*!
+ \struct NavigationWidgetFactoryPrivate
+ \brief Private class data for \a NavigationWidgetFactory
+ \sa NavigationWidgetFactory
+ */
+struct NavigationWidgetFactoryPrivate
+{
+ //! constructor
+ NavigationWidgetFactoryPrivate() : naviPaneEnabled(false) {}
+
+ //! NavigationWidgetFactory instance
+ static NavigationWidgetFactory *instance;
+
+ //! Navigation pane visibility
+ bool naviPaneEnabled;
+};
+
+// static variable initialization
+NavigationWidgetFactory *NavigationWidgetFactoryPrivate::instance = 0;
+
+///////////////////////////////// NavigationWidgetFactory //////////////////////////////////
+
+NavigationWidgetFactory::NavigationWidgetFactory()
+ : d_ptr(new NavigationWidgetFactoryPrivate())
+{
+}
+
+NavigationWidgetFactory::~NavigationWidgetFactory()
+{
+ NavigationWidgetFactoryPrivate::instance = 0;
+}
+
+NavigationWidgetFactory *NavigationWidgetFactory::instance()
+{
+ if (!NavigationWidgetFactoryPrivate::instance)
+ NavigationWidgetFactoryPrivate::instance = new NavigationWidgetFactory();
+ return NavigationWidgetFactoryPrivate::instance;
+}
+
+QString NavigationWidgetFactory::displayName() const
+{
+ return tr("Class View");
+}
+
+QString NavigationWidgetFactory::id() const
+{
+ return QLatin1String(Constants::CLASSVIEWNAVIGATION_ID);
+}
+
+QKeySequence NavigationWidgetFactory::activationSequence() const
+{
+ return QKeySequence();
+}
+
+Core::NavigationView NavigationWidgetFactory::createWidget()
+{
+ Core::NavigationView navigationView;
+ NavigationWidget *widget = new NavigationWidget();
+ navigationView.widget = widget;
+ navigationView.dockToolBarWidgets = widget->createToolButtons();
+ emit widgetIsCreated();
+ return navigationView;
+}
+
+QString NavigationWidgetFactory::settingsPrefix(int position) const
+{
+ QChar sep('/');
+ QString group = QLatin1String(Constants::CLASSVIEW_SETTINGS_GROUP) + sep;
+ group += QLatin1String(Constants::CLASSVIEW_SETTINGS_TREEWIDGET_PREFIX)
+ + QString::number(position) + sep;
+ return group;
+}
+
+void NavigationWidgetFactory::saveSettings(int position, QWidget *widget)
+{
+ NavigationWidget *pw = qobject_cast<NavigationWidget *>(widget);
+ QTC_ASSERT(pw, return);
+
+ QSettings *settings = Core::ICore::instance()->settings();
+ QTC_ASSERT(settings, return);
+
+ // .beginGroup is not used - to prevent simultaneous access
+ QString group = settingsPrefix(position);
+
+ // save settings
+ settings->setValue(group + Constants::CLASSVIEW_SETTINGS_FLATMODE, pw->flatMode());
+}
+
+void NavigationWidgetFactory::restoreSettings(int position, QWidget *widget)
+{
+ NavigationWidget *pw = qobject_cast<NavigationWidget *>(widget);
+ QTC_ASSERT(pw, return);
+
+ QSettings *settings = Core::ICore::instance()->settings();
+ QTC_ASSERT(settings, return);
+
+ // .beginGroup is not used - to prevent simultaneous access
+ QString group = settingsPrefix(position);
+
+ // load settings
+ pw->setFlatMode(settings->value(group + Constants::CLASSVIEW_SETTINGS_FLATMODE, false).toBool());
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewnavigationwidgetfactory.h b/src/plugins/classview/classviewnavigationwidgetfactory.h
new file mode 100644
index 0000000000..619a97d36a
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidgetfactory.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWNAVIGATIONWIDGETFACTORY_H
+#define CLASSVIEWNAVIGATIONWIDGETFACTORY_H
+
+#include <coreplugin/inavigationwidgetfactory.h>
+
+#include <QtCore/QScopedPointer>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class NavigationWidgetFactory
+ \brief INavigationWidgetFactory implementation for Class View
+
+ INavigationWidgetFactory implementation for Class View. Singleton instance.
+ Supports \a setState publc slot to add/remove factory to \a ExtensionSystem::PluginManager.
+ Also supports some additional signals, \a widgetIsCreated and \a stateChanged.
+ */
+
+class NavigationWidgetFactory : public Core::INavigationWidgetFactory
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(NavigationWidgetFactory)
+
+public:
+ //! destructor
+ virtual ~NavigationWidgetFactory();
+
+ //! get an instance
+ static NavigationWidgetFactory *instance();
+
+ // Core::INavigationWidgetFactory
+ //! \implements Core::INavigationWidgetFactory::displayName
+ QString displayName() const;
+
+ //! \implements Core::INavigationWidgetFactory::id
+ QString id() const;
+
+ //! \implements Core::INavigationWidgetFactory::activationSequence
+ QKeySequence activationSequence() const;
+
+ //! \implements Core::INavigationWidgetFactory::createWidget
+ Core::NavigationView createWidget();
+
+ //! \implements Core::INavigationWidgetFactory::saveSettings
+ void saveSettings(int position, QWidget *widget);
+
+ //! \implements Core::INavigationWidgetFactory::restoreSettings
+ void restoreSettings(int position, QWidget *widget);
+
+ // own functionality
+
+signals:
+ /*!
+ \brief Signal which informs that the widget factory creates a widget.
+ */
+ void widgetIsCreated();
+
+private:
+ //! Constructor
+ NavigationWidgetFactory();
+
+ /*!
+ \brief Get a settings prefix for the specified position
+ \param position Position
+ \return Settings prefix
+ */
+ QString settingsPrefix(int position) const;
+
+private:
+ //! private class data pointer
+ QScopedPointer<struct NavigationWidgetFactoryPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWNAVIGATIONWIDGETFACTORY_H
diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp
new file mode 100644
index 0000000000..32c5504069
--- /dev/null
+++ b/src/plugins/classview/classviewparser.cpp
@@ -0,0 +1,688 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewparser.h"
+#include "classviewconstants.h"
+#include "classviewutils.h"
+
+// cplusplus shared library. the same folder (cplusplus)
+#include <Symbol.h>
+#include <Symbols.h>
+#include <Scope.h>
+#include <Name.h>
+
+// other
+#include <cplusplus/Overview.h>
+#include <cplusplus/Icons.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectnodes.h>
+#include <coreplugin/ifile.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QTimer>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QReadLocker>
+#include <QtCore/QWriteLocker>
+
+enum { debug = false };
+
+namespace ClassView {
+namespace Internal {
+
+// ----------------------------- ParserPrivate ---------------------------------
+
+/*!
+ \struct ParserPrivate
+ \brief Private class data for \a Parser
+ \sa Parser
+ */
+struct ParserPrivate
+{
+ //! Constructor
+ ParserPrivate() : flatMode(false) {}
+
+ //! Get document from documentList
+ CPlusPlus::Document::Ptr document(const QString &fileName) const;
+
+ CPlusPlus::Overview overview;
+
+ //! timer
+ QPointer<QTimer> timer;
+
+ // documents
+ //! Documents read write lock
+ QReadWriteLock docLocker;
+
+ //! Current document list
+ QHash<QString, CPlusPlus::Document::Ptr> documentList;
+
+ //! Parsed documents' revision - to speed up computations
+ QHash<QString, unsigned> cachedDocTreesRevision;
+
+ //! Parsed documents - to speed up computations
+ QHash<QString, ParserTreeItem::ConstPtr> cachedDocTrees;
+
+ // project trees
+ //! Projects read write lock
+ QReadWriteLock prjLocker;
+
+ //! Parsed projects' revision - to speed up computations
+ QHash<QString, unsigned> cachedPrjTreesRevision;
+
+ //! Merged trees for projects. Not const - projects might be substracted/added
+ QHash<QString, ParserTreeItem::Ptr> cachedPrjTrees;
+
+ //! Cached file lists for projects (non-flat mode)
+ QHash<QString, QStringList> cachedPrjFileLists;
+
+ // other
+ //! List for files which has to be parsed
+ QSet<QString> fileList;
+
+ //! Root item read write lock
+ QReadWriteLock rootItemLocker;
+
+ //! Parsed root item
+ ParserTreeItem::ConstPtr rootItem;
+
+ //! Flat mode
+ bool flatMode;
+};
+
+CPlusPlus::Document::Ptr ParserPrivate::document(const QString &fileName) const
+{
+ if (!documentList.contains(fileName))
+ return CPlusPlus::Document::Ptr();
+ return documentList[fileName];
+}
+
+// ----------------------------- Parser ---------------------------------
+
+Parser::Parser(QObject *parent)
+ : QObject(parent),
+ d_ptr(new ParserPrivate())
+{
+ d_ptr->timer = new QTimer(this);
+ d_ptr->timer->setSingleShot(true);
+
+ // connect signal/slots
+ // internal data reset
+ connect(this, SIGNAL(resetDataDone()), SLOT(onResetDataDone()), Qt::QueuedConnection);
+
+ // timer for emitting changes
+ connect(d_ptr->timer, SIGNAL(timeout()), SLOT(requestCurrentState()), Qt::QueuedConnection);
+}
+
+Parser::~Parser()
+{
+}
+
+bool Parser::canFetchMore(QStandardItem *item) const
+{
+ ParserTreeItem::ConstPtr ptr = findItemByRoot(item);
+ if (ptr.isNull())
+ return false;
+ return ptr->canFetchMore(item);
+}
+
+void Parser::fetchMore(QStandardItem *item, bool skipRoot) const
+{
+ ParserTreeItem::ConstPtr ptr = findItemByRoot(item, skipRoot);
+ if (ptr.isNull())
+ return;
+ ptr->fetchMore(item);
+}
+
+void Parser::setFlatMode(bool flatMode)
+{
+ if (flatMode == d_ptr->flatMode)
+ return;
+
+ // change internal
+ d_ptr->flatMode = flatMode;
+
+ // regenerate and resend current tree
+ emitCurrentTree();
+}
+
+ParserTreeItem::ConstPtr Parser::findItemByRoot(const QStandardItem *item, bool skipRoot) const
+{
+ if (!item)
+ return ParserTreeItem::ConstPtr();
+
+ // go item by item to the root
+ QList<const QStandardItem *> uiList;
+ const QStandardItem *cur = item;
+ while(cur) {
+ uiList.append(cur);
+ cur = cur->parent();
+ }
+
+ if (skipRoot && uiList.count() > 0)
+ uiList.removeLast();
+
+ QReadLocker locker(&d_ptr->rootItemLocker);
+
+ // using internal root - search correct item
+ ParserTreeItem::ConstPtr internal = d_ptr->rootItem;
+
+ while(uiList.count() > 0) {
+ cur = uiList.last();
+ uiList.removeLast();
+ const SymbolInformation &inf = Utils::symbolInformationFromItem(cur);
+ internal = internal->child(inf);
+ if (internal.isNull())
+ break;
+ }
+
+ return internal;
+}
+
+ParserTreeItem::ConstPtr Parser::parse()
+{
+ QTime time;
+ if (debug)
+ time.start();
+
+ ParserTreeItem::Ptr rootItem(new ParserTreeItem());
+
+ // check all projects
+ QList<ProjectExplorer::Project *> projects = getProjectList();
+ foreach(const ProjectExplorer::Project *prj, projects) {
+ if (!prj)
+ continue;
+
+ ParserTreeItem::Ptr item;
+ if (!d_ptr->flatMode)
+ item = ParserTreeItem::Ptr(new ParserTreeItem());
+
+ QString prjName(prj->displayName());
+ QString prjType(prjName);
+ if (prj->file())
+ prjType = prj->file()->fileName();
+ SymbolInformation inf(prjName, prjType);
+
+ QStringList projectList = addProjectNode(item, prj->rootProjectNode());
+
+ if (d_ptr->flatMode) {
+ // use prj path (prjType) as a project id
+// addProject(item, prj->files(ProjectExplorer::Project::ExcludeGeneratedFiles), prjType);
+ //! \todo return back, works too long
+ ParserTreeItem::Ptr flatItem = createFlatTree(projectList);
+ item.swap(flatItem);
+ }
+ item->setIcon(prj->rootProjectNode()->icon());
+ rootItem->appendChild(item, inf);
+ }
+
+ if (debug)
+ qDebug() << "Class View:" << QDateTime::currentDateTime().toString()
+ << "Parsed in " << time.elapsed() << "msecs.";
+
+ return rootItem;
+}
+
+void Parser::addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
+ const QString &projectId)
+{
+ // recalculate cache tree if needed
+ ParserTreeItem::Ptr prj(getCachedOrParseProjectTree(fileList, projectId));
+ if (item.isNull())
+ return;
+
+ // if there is an item - copy project tree to that item
+ item->copy(prj);
+}
+
+void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol *symbol)
+{
+ if (item.isNull() || !symbol)
+ return;
+
+ // easy solution - lets add any scoped symbol and
+ // any symbol which does not contain :: in the name
+
+// if (symbol->isDeclaration())
+// return;
+
+ //! \todo collect statistics and reorder to optimize
+ if (symbol->isForwardClassDeclaration()
+ || symbol->isExtern()
+ || symbol->isFriend()
+ || symbol->isGenerated()
+ || symbol->isUsingNamespaceDirective()
+ || symbol->isUsingDeclaration()
+ )
+ return;
+
+ // skip static local functions
+// if ((!symbol->scope() || symbol->scope()->owner()->isClass())
+// && symbol->isStatic() && symbol->isFunction())
+// return;
+
+
+ const CPlusPlus::Name *symbolName = symbol->name();
+ if (symbolName && symbolName->isQualifiedNameId())
+ return;
+
+ QString name = d_ptr->overview.prettyName(symbol->name()).trimmed();
+ QString type = d_ptr->overview.prettyType(symbol->type()).trimmed();
+ int iconType = CPlusPlus::Icons::iconTypeForSymbol(symbol);
+
+ SymbolInformation information(name, type, iconType);
+
+ ParserTreeItem::Ptr itemAdd;
+
+ // If next line will be removed, 5% speed up for the initial parsing.
+ // But there might be a problem for some files ???
+ // Better to improve qHash timing
+ itemAdd = item->child(information);
+
+ if (itemAdd.isNull())
+ itemAdd = ParserTreeItem::Ptr(new ParserTreeItem());
+
+ // locations are 1-based in Symbol, start with 0 for the editor
+ SymbolLocation location(symbol->fileName(), symbol->line(), symbol->column() - 1);
+ itemAdd->addSymbolLocation(location);
+
+ // prevent showing a content of the functions
+ if (!symbol->isFunction()) {
+ const CPlusPlus::ScopedSymbol *scopedSymbol = symbol->asScopedSymbol();
+ if (scopedSymbol) {
+ CPlusPlus::Scope *scope = scopedSymbol->members();
+ if (scope) {
+ CPlusPlus::Scope::iterator cur = scope->firstSymbol();
+ while (cur != scope->lastSymbol()) {
+ const CPlusPlus::Symbol *curSymbol = *cur;
+ ++cur;
+ if (!curSymbol)
+ continue;
+
+ // if (!symbol->isClass() && curSymbol->isStatic() && curSymbol->isFunction())
+ // return;
+
+ addSymbol(itemAdd, curSymbol);
+ }
+ }
+ }
+ }
+
+ bool appendChild = true;
+
+ // if item is empty and has not to be added
+ if (symbol->isNamespace() && itemAdd->childCount() == 0)
+ appendChild = false;
+
+ if (appendChild)
+ item->appendChild(itemAdd, information);
+}
+
+ParserTreeItem::Ptr Parser::createFlatTree(const QStringList &projectList)
+{
+ QReadLocker locker(&d_ptr->prjLocker);
+
+ ParserTreeItem::Ptr item(new ParserTreeItem());
+ foreach(const QString &project, projectList) {
+ if (!d_ptr->cachedPrjTrees.contains(project))
+ continue;
+ ParserTreeItem::ConstPtr list = d_ptr->cachedPrjTrees[project];
+ item->add(list);
+ }
+ return item;
+}
+
+ParserTreeItem::Ptr Parser::getParseProjectTree(const QStringList &fileList,
+ const QString &projectId)
+{
+ //! \todo Way to optimize - for documentUpdate - use old cached project and subtract
+ //! changed files only (old edition), and add curent editions
+ ParserTreeItem::Ptr item(new ParserTreeItem());
+ unsigned revision = 0;
+ foreach(const QString &file, fileList) {
+ // ? locker for document?..
+ const CPlusPlus::Document::Ptr &doc = d_ptr->document(file);
+ if (doc.isNull())
+ continue;
+
+ revision += doc->revision();
+
+ ParserTreeItem::ConstPtr list = getCachedOrParseDocumentTree(doc);
+ if (list.isNull())
+ continue;
+
+ // add list to out document
+ item->add(list);
+ }
+
+ // update the cache
+ if (!projectId.isEmpty()) {
+ QWriteLocker locker(&d_ptr->prjLocker);
+
+ d_ptr->cachedPrjTrees[projectId] = item;
+ d_ptr->cachedPrjTreesRevision[projectId] = revision;
+ }
+ return item;
+}
+
+ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileList,
+ const QString &projectId)
+{
+ d_ptr->prjLocker.lockForRead();
+
+ // calculate current revision
+ if (!projectId.isEmpty() && d_ptr->cachedPrjTrees.contains(projectId)) {
+ // calculate project's revision
+ unsigned revision = 0;
+ foreach(const QString &file, fileList) {
+ const CPlusPlus::Document::Ptr &doc = d_ptr->document(file);
+ if (doc.isNull())
+ continue;
+ revision += doc->revision();
+ }
+
+ // if even revision is the same, return cached project
+ if (revision == d_ptr->cachedPrjTreesRevision[projectId]) {
+ d_ptr->prjLocker.unlock();
+ return d_ptr->cachedPrjTrees[projectId];
+ }
+ }
+
+ d_ptr->prjLocker.unlock();
+ return getParseProjectTree(fileList, projectId);
+}
+
+ParserTreeItem::ConstPtr Parser::getParseDocumentTree(const CPlusPlus::Document::Ptr &doc)
+{
+ if (doc.isNull())
+ return ParserTreeItem::ConstPtr();
+
+ const QString &fileName = doc->fileName();
+ if (!d_ptr->fileList.contains(fileName))
+ return ParserTreeItem::ConstPtr();
+
+ ParserTreeItem::Ptr itemPtr(new ParserTreeItem());
+
+ unsigned total = doc->globalSymbolCount();
+ for (unsigned i = 0; i < total; i++)
+ addSymbol(itemPtr, doc->globalSymbolAt(i));
+
+ QWriteLocker locker(&d_ptr->docLocker);
+
+ d_ptr->cachedDocTrees[fileName] = itemPtr;
+ d_ptr->cachedDocTreesRevision[fileName] = doc->revision();
+ d_ptr->documentList[fileName] = doc;
+
+ return itemPtr;
+}
+
+ParserTreeItem::ConstPtr Parser::getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc)
+{
+ if (doc.isNull())
+ return ParserTreeItem::ConstPtr();
+
+ const QString &fileName = doc->fileName();
+ d_ptr->docLocker.lockForRead();
+ if (d_ptr->cachedDocTrees.contains(fileName)
+ && d_ptr->cachedDocTreesRevision.contains(fileName)
+ && d_ptr->cachedDocTreesRevision[fileName] == doc->revision()) {
+ d_ptr->docLocker.unlock();
+ return d_ptr->cachedDocTrees[fileName];
+ } else {
+ d_ptr->docLocker.unlock();
+ return getParseDocumentTree(doc);
+ }
+}
+
+void Parser::parseDocument(const CPlusPlus::Document::Ptr &doc)
+{
+ if (doc.isNull())
+ return;
+
+ const QString &name = doc->fileName();
+
+ // if it is external file (not in any of our projects)
+ if (!d_ptr->fileList.contains(name))
+ return;
+
+ getParseDocumentTree(doc);
+
+ QTC_ASSERT(d_ptr->timer, return);
+
+ if (!d_ptr->timer->isActive())
+ d_ptr->timer->start(Constants::CLASSVIEW_EDITINGTREEUPDATE_DELAY);
+ return;
+}
+
+void Parser::clearCacheAll()
+{
+ d_ptr->docLocker.lockForWrite();
+
+ d_ptr->cachedDocTrees.clear();
+ d_ptr->cachedDocTreesRevision.clear();
+ d_ptr->documentList.clear();
+
+ d_ptr->docLocker.unlock();
+
+ clearCache();
+}
+
+void Parser::clearCache()
+{
+ QWriteLocker locker(&d_ptr->prjLocker);
+
+ // remove cached trees
+ d_ptr->cachedPrjFileLists.clear();
+
+ //! \todo where better to clear project's trees?
+ //! When file is add/removed from a particular project?..
+ d_ptr->cachedPrjTrees.clear();
+ d_ptr->cachedPrjTreesRevision.clear();
+}
+
+void Parser::setFileList(const QStringList &fileList)
+{
+ d_ptr->fileList.clear();
+ d_ptr->fileList = QSet<QString>::fromList(fileList);
+}
+
+void Parser::removeFiles(const QStringList &fileList)
+{
+ if (fileList.count() == 0)
+ return;
+
+ QWriteLocker lockerPrj(&d_ptr->prjLocker);
+ QWriteLocker lockerDoc(&d_ptr->docLocker);
+ foreach(const QString &name, fileList) {
+ d_ptr->fileList.remove(name);
+ d_ptr->cachedDocTrees.remove(name);
+ d_ptr->cachedDocTreesRevision.remove(name);
+ d_ptr->documentList.remove(name);
+ d_ptr->cachedPrjTrees.remove(name);
+ d_ptr->cachedPrjFileLists.clear();
+ }
+
+ emit filesAreRemoved();
+}
+
+void Parser::resetData(const CPlusPlus::Snapshot &snapshot)
+{
+ // clear internal cache
+ clearCache();
+
+ d_ptr->docLocker.lockForWrite();
+
+ // copy snapshot's documents
+ CPlusPlus::Snapshot::const_iterator cur = snapshot.begin();
+ CPlusPlus::Snapshot::const_iterator end = snapshot.end();
+ for(; cur != end; cur++)
+ d_ptr->documentList[cur.key()] = cur.value();
+
+ d_ptr->docLocker.unlock();
+
+ // recalculate file list
+ QStringList fileList;
+
+ // check all projects
+ QList<ProjectExplorer::Project *> projects = getProjectList();
+ foreach(const ProjectExplorer::Project *prj, projects) {
+ if (prj)
+ fileList += prj->files(ProjectExplorer::Project::ExcludeGeneratedFiles);
+ }
+ setFileList(fileList);
+
+ emit resetDataDone();
+}
+
+void Parser::resetDataToCurrentState()
+{
+ // get latest data
+ CppTools::CppModelManagerInterface *codeModel = CppTools::CppModelManagerInterface::instance();
+ if (codeModel)
+ resetData(codeModel->snapshot());
+}
+
+void Parser::onResetDataDone()
+{
+ // internal data is resetted, update a tree and send it back
+ emitCurrentTree();
+}
+
+void Parser::requestCurrentState()
+{
+ emitCurrentTree();
+}
+
+void Parser::emitCurrentTree()
+{
+ // stop timer if it is active right now
+ d_ptr->timer->stop();
+
+ d_ptr->rootItemLocker.lockForWrite();
+ d_ptr->rootItem = parse();
+ d_ptr->rootItemLocker.unlock();
+
+ // convert
+ QSharedPointer<QStandardItem> std(new QStandardItem());
+
+ d_ptr->rootItem->convertTo(std.data());
+
+ emit treeDataUpdate(std);
+}
+
+QStringList Parser::projectNodeFileList(const ProjectExplorer::FolderNode *node) const
+{
+ QStringList list;
+ if (!node)
+ return list;
+
+ QList<ProjectExplorer::FileNode *> fileNodes = node->fileNodes();
+ QList<ProjectExplorer::FolderNode *> subFolderNodes = node->subFolderNodes();
+
+ foreach(const ProjectExplorer::FileNode *file, fileNodes) {
+ if (file->isGenerated())
+ continue;
+
+ list << file->path();
+ }
+
+ foreach(const ProjectExplorer::FolderNode *folder, subFolderNodes) {
+ if (folder->nodeType() != ProjectExplorer::FolderNodeType)
+ continue;
+ list << projectNodeFileList(folder);
+ }
+
+ return list;
+}
+
+QStringList Parser::addProjectNode(const ParserTreeItem::Ptr &item,
+ const ProjectExplorer::ProjectNode *node)
+{
+ QStringList projectList;
+ if (!node)
+ return projectList;
+
+ const QString &nodePath = node->path();
+
+ // our own files
+ QStringList fileList;
+
+ // try to improve parsing speed by internal cache
+ if (d_ptr->cachedPrjFileLists.contains(nodePath)) {
+ fileList = d_ptr->cachedPrjFileLists[nodePath];
+ } else {
+ fileList = projectNodeFileList(node);
+ d_ptr->cachedPrjFileLists[nodePath] = fileList;
+ }
+ if (fileList.count() > 0) {
+ addProject(item, fileList, node->path());
+ projectList << node->path();
+ }
+
+ // subnodes
+ QList<ProjectExplorer::ProjectNode *> projectNodes = node->subProjectNodes();
+
+ foreach(const ProjectExplorer::ProjectNode *project, projectNodes) {
+ ParserTreeItem::Ptr itemPrj(new ParserTreeItem());
+ SymbolInformation information(project->displayName(), project->path());
+
+ projectList += addProjectNode(itemPrj, project);
+
+ itemPrj->setIcon(project->icon());
+
+ // append child if item is not null and there is at least 1 child
+ if (!item.isNull() && itemPrj->childCount() > 0)
+ item->appendChild(itemPrj, information);
+ }
+
+ return projectList;
+}
+
+QList<ProjectExplorer::Project *> Parser::getProjectList() const
+{
+ QList<ProjectExplorer::Project *> list;
+
+ // check all projects
+ ProjectExplorer::SessionManager *sessionManager
+ = ProjectExplorer::ProjectExplorerPlugin::instance()->session();
+ QTC_ASSERT(sessionManager, return list);
+
+ list = sessionManager->projects();
+
+ return list;
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewparser.h b/src/plugins/classview/classviewparser.h
new file mode 100644
index 0000000000..fb0eb651eb
--- /dev/null
+++ b/src/plugins/classview/classviewparser.h
@@ -0,0 +1,265 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWPARSER_H
+#define CLASSVIEWPARSER_H
+
+#include <QtCore/QObject>
+
+#include "classviewparsertreeitem.h"
+
+#include <QtCore/QList>
+#include <QtGui/QStandardItem>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+
+#include <CPlusPlusForwardDeclarations.h>
+#include <cplusplus/CppDocument.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+
+// might be changed to forward declaration - is not done to be less dependent
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/project.h>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class Parser
+ \brief Parse cpp information. Multithreading is supported.
+ */
+
+class Parser : public QObject
+{
+ Q_OBJECT
+
+public:
+ /*!
+ \brief Constructor
+ */
+ explicit Parser(QObject *parent = 0);
+ ~Parser();
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item which has to be checked
+ */
+ bool canFetchMore(QStandardItem *item) const;
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item which will be populated (if needed)
+ \param skipRoot Skip root item
+ */
+ void fetchMore(QStandardItem *item, bool skipRoot = false) const;
+
+signals:
+ //! File list is changed
+ void filesAreRemoved();
+
+ /*!
+ \brief Signal about a tree data update
+ */
+ void treeDataUpdate(QSharedPointer<QStandardItem> result);
+
+ /*!
+ \brief Signal that internal data
+ \sa resetData, resetDataToCurrentState
+ */
+ void resetDataDone();
+
+public slots:
+ /*!
+ \brief Request to clear full internal stored data.
+ */
+ void clearCacheAll();
+
+ /*!
+ \brief Request to clear internal stored data, it has to be regenerated on the next request.
+ */
+ void clearCache();
+
+ /*!
+ \brief Request to emit a signal with the current tree state
+ */
+ void requestCurrentState();
+
+ /*!
+ \brief Set file list for the parsing, files outside of this list will not be in any tree.
+ \param fileList Files which must be allowed for the parsing
+ */
+ void setFileList(const QStringList &fileList);
+
+ /*!
+ \brief Remove some files from the file list for the parsing.
+ \param fileList Files which must be removed from the parsing
+ */
+ void removeFiles(const QStringList &fileList);
+
+ /*!
+ \brief Fully reset internal state
+ \param snapshot Code parser snapshot
+ */
+ void resetData(const CPlusPlus::Snapshot &snapshot);
+
+ /*!
+ \brief Fully reset internal state - to the current state
+ \sa resetData
+ */
+ void resetDataToCurrentState();
+
+ /*!
+ \brief Parse document if it is in the project files and add a tree to the internal storage
+ \param doc Document which has to be parsed
+ */
+ void parseDocument(const CPlusPlus::Document::Ptr &doc);
+
+ /*!
+ \brief Switch to flat mode (without subprojects)
+ \param flat True to enable flat mode, false to disable
+ */
+ void setFlatMode(bool flat);
+
+protected slots:
+ /*!
+ \brief Internal data is changed, regenerate the tree
+ \sa resetDataDone
+ */
+ void onResetDataDone();
+
+protected:
+ /*!
+ \brief Parse one particular project and add result to the tree item
+ \param item Item where parsed project has to be stored
+ \param fileList Files
+ \param projectId Project id, is needed for prj cache
+ */
+ void addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
+ const QString &projectId = QString());
+
+ /*!
+ \brief Parse one particular symbol and add result to the tree item (as a parent)
+ \param item Item where parsed symbol has to be stored
+ \param symbol Symbol which has to be used as a source
+ */
+ void addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol *symbol);
+
+ /*!
+ \brief Parse document if it is in the project files and add a tree to the internal storage.
+ Update internal cached tree for this document.
+ \param doc Document which has to be parsed
+ \return A tree
+ \sa parseDocument
+ */
+ ParserTreeItem::ConstPtr getParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
+
+ /*!
+ \brief Get from the cache or parse document if it is in the project files
+ and add a tree to the internal storage
+ \param doc Document which has to be parsed
+ \return A tree
+ \sa parseDocument
+ */
+ ParserTreeItem::ConstPtr getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
+
+ /*!
+ \brief Parse project and add a tree to the internal storage.
+ Update internal cached tree for this project.
+ \param fileList Documents which has to be added to the project
+ \param projectId Project id
+ \return A tree
+ */
+ ParserTreeItem::Ptr getParseProjectTree(const QStringList &fileList, const QString &projectId);
+
+ /*!
+ \brief Get from the cache (if valid) or parse project and add a tree to the internal storage.
+ Update internal cached tree for this project.
+ \param fileList Documents which has to be added to the project
+ \param projectId Project id
+ \return A tree
+ */
+ ParserTreeItem::Ptr getCachedOrParseProjectTree(const QStringList &fileList,
+ const QString &projectId);
+
+ /*!
+ \brief Send a current tree to listeners
+ */
+ void emitCurrentTree();
+
+ /*!
+ \brief Parse the class and produce a new tree
+ \sa addProject
+ */
+ ParserTreeItem::ConstPtr parse();
+
+ /*!
+ \brief Find internal node for the specified UI item
+ \param item Item which has to be found
+ \param skipRoot Skip root item
+ \return Found internal node
+ */
+ ParserTreeItem::ConstPtr findItemByRoot(const QStandardItem *item, bool skipRoot = false) const;
+
+ /*!
+ \brief Generate projects like Project Explorer
+ \param item Item
+ \param node Root node
+ \return List of projects which were added to the item
+ */
+ QStringList addProjectNode(const ParserTreeItem::Ptr &item,
+ const ProjectExplorer::ProjectNode *node);
+
+ /*!
+ \brief Generate project node file list
+ \param node Root node
+ */
+ QStringList projectNodeFileList(const ProjectExplorer::FolderNode *node) const;
+
+ /*!
+ \brief Get the current project list
+ \return Project list
+ */
+ QList<ProjectExplorer::Project *> getProjectList() const;
+
+ /*!
+ \brief Create flat tree from different projects
+ \param projectList List of projects
+ \return Flat tree
+ */
+ ParserTreeItem::Ptr createFlatTree(const QStringList &projectList);
+
+private:
+ //! Private class data pointer
+ QScopedPointer<struct ParserPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPARSER_H
diff --git a/src/plugins/classview/classviewparsertreeitem.cpp b/src/plugins/classview/classviewparsertreeitem.cpp
new file mode 100644
index 0000000000..16e1a66573
--- /dev/null
+++ b/src/plugins/classview/classviewparsertreeitem.cpp
@@ -0,0 +1,373 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewparsertreeitem.h"
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include "classviewconstants.h"
+#include "classviewutils.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtGui/QIcon>
+#include <QtGui/QStandardItem>
+#include <QtCore/QMutex>
+
+#include <QtCore/QDebug>
+
+enum { debug = true };
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// ParserTreeItemPrivate //////////////////////////////////
+
+/*!
+ \struct ParserTreeItemPrivate
+ \brief Private class data for \a ParserTreeItem
+ \sa ParserTreeItem
+ */
+struct ParserTreeItemPrivate
+{
+ //! symbol locations
+ QSet<SymbolLocation> symbolLocations;
+
+ //! symbol informations
+ QHash<SymbolInformation, ParserTreeItem::Ptr> symbolInformations;
+
+ //! An icon
+ QIcon icon;
+};
+
+///////////////////////////////// ParserTreeItem //////////////////////////////////
+
+ParserTreeItem::ParserTreeItem() :
+ d_ptr(new ParserTreeItemPrivate())
+{
+}
+
+ParserTreeItem::~ParserTreeItem()
+{
+}
+
+ParserTreeItem &ParserTreeItem::operator=(const ParserTreeItem &other)
+{
+ d_ptr->symbolLocations = other.d_ptr->symbolLocations;
+ d_ptr->icon = other.d_ptr->icon;
+ d_ptr->symbolInformations.clear();
+ return *this;
+}
+
+void ParserTreeItem::copy(const ParserTreeItem::ConstPtr &from)
+{
+ if (from.isNull())
+ return;
+
+ d_ptr->symbolLocations = from->d_ptr->symbolLocations;
+ d_ptr->icon = from->d_ptr->icon;
+ d_ptr->symbolInformations = from->d_ptr->symbolInformations;
+}
+
+void ParserTreeItem::copyTree(const ParserTreeItem::ConstPtr &target)
+{
+ if (target.isNull())
+ return;
+
+ // copy content
+ d_ptr->symbolLocations = target->d_ptr->symbolLocations;
+ d_ptr->icon = target->d_ptr->icon;
+ d_ptr->symbolInformations.clear();
+
+ // reserve memory
+// int amount = qMin(100 , target->d_ptr->symbolInformations.count() * 2);
+// d_ptr->symbolInformations.reserve(amount);
+
+ // every child
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+ target->d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+ target->d_ptr->symbolInformations.constEnd();
+
+ for(; cur != end; cur++) {
+ ParserTreeItem::Ptr item(new ParserTreeItem());
+ item->copyTree(cur.value());
+ appendChild(item, cur.key());
+ }
+}
+
+void ParserTreeItem::addSymbolLocation(const SymbolLocation &location)
+{
+ d_ptr->symbolLocations.insert(location);
+}
+
+void ParserTreeItem::addSymbolLocation(const QSet<SymbolLocation> &locations)
+{
+ d_ptr->symbolLocations.unite(locations);
+}
+
+void ParserTreeItem::removeSymbolLocation(const SymbolLocation &location)
+{
+ d_ptr->symbolLocations.remove(location);
+}
+
+void ParserTreeItem::removeSymbolLocations(const QSet<SymbolLocation> &locations)
+{
+ d_ptr->symbolLocations.subtract(locations);
+}
+
+QSet<SymbolLocation> ParserTreeItem::symbolLocations() const
+{
+ return d_ptr->symbolLocations;
+}
+
+void ParserTreeItem::appendChild(const ParserTreeItem::Ptr &item, const SymbolInformation &inf)
+{
+ // removeChild must be used to remove an item
+ if (item.isNull())
+ return;
+
+ d_ptr->symbolInformations[inf] = item;
+}
+
+void ParserTreeItem::removeChild(const SymbolInformation &inf)
+{
+ d_ptr->symbolInformations.remove(inf);
+}
+
+ParserTreeItem::Ptr ParserTreeItem::child(const SymbolInformation &inf) const
+{
+ if (!d_ptr->symbolInformations.contains(inf))
+ return ParserTreeItem::Ptr();
+ return d_ptr->symbolInformations[inf];
+}
+
+int ParserTreeItem::childCount() const
+{
+ return d_ptr->symbolInformations.count();
+}
+
+QIcon ParserTreeItem::icon() const
+{
+ return d_ptr->icon;
+}
+
+void ParserTreeItem::setIcon(const QIcon &icon)
+{
+ d_ptr->icon = icon;
+}
+
+void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target)
+{
+ if (target.isNull())
+ return;
+
+ // add locations
+ d_ptr->symbolLocations = d_ptr->symbolLocations.unite(target->d_ptr->symbolLocations);
+
+ // add childs
+ // every target child
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+ target->d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+ target->d_ptr->symbolInformations.constEnd();
+ while(cur != end) {
+ const SymbolInformation &inf = cur.key();
+ const ParserTreeItem::Ptr &targetChild = cur.value();
+ if (d_ptr->symbolInformations.contains(inf)) {
+ // this item has the same child node
+ const ParserTreeItem::Ptr &child = d_ptr->symbolInformations[inf];
+ if (!child.isNull()) {
+ child->add(targetChild);
+ } else {
+ ParserTreeItem::Ptr add(new ParserTreeItem());
+ add->copyTree(targetChild);
+ d_ptr->symbolInformations[inf] = add;
+ }
+ } else {
+ ParserTreeItem::Ptr add(new ParserTreeItem());
+ add->copyTree(targetChild);
+ d_ptr->symbolInformations[inf] = add;
+ }
+ // next item
+ ++cur;
+ }
+}
+
+void ParserTreeItem::subtract(const ParserTreeItem::ConstPtr &target)
+{
+ if (target.isNull())
+ return;
+
+ // every target child
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+ target->d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+ target->d_ptr->symbolInformations.constEnd();
+ while(cur != end) {
+ const SymbolInformation &inf = cur.key();
+ if (d_ptr->symbolInformations.contains(inf)) {
+ // this item has the same child node
+ if (!d_ptr->symbolInformations[inf].isNull())
+ d_ptr->symbolInformations[inf]->subtract(cur.value());
+ if (d_ptr->symbolInformations[inf].isNull()
+ || d_ptr->symbolInformations[inf]->childCount() == 0)
+ d_ptr->symbolInformations.remove(inf);
+ }
+ // next item
+ ++cur;
+ }
+}
+
+void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const
+{
+ if (!item)
+ return;
+
+ QMap<SymbolInformation, ParserTreeItem::Ptr> map;
+
+ // convert to map - to sort it
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+ d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+ d_ptr->symbolInformations.constEnd();
+ while(curHash != endHash) {
+ map.insert(curHash.key(), curHash.value());
+ ++curHash;
+ }
+
+ // add to item
+ QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur = map.constBegin();
+ QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end = map.constEnd();
+ while(cur != end) {
+ const SymbolInformation &inf = cur.key();
+ ParserTreeItem::Ptr ptr = cur.value();
+
+ QStandardItem *add = new QStandardItem();
+ Utils::setSymbolInformationToItem(inf, add);
+ if (!ptr.isNull()) {
+ // icon
+ add->setIcon(ptr->icon());
+
+ // locations
+ add->setData(Utils::locationsToRole(ptr->symbolLocations()),
+ Constants::SymbolLocationsRole);
+
+ if (recursive)
+ cur.value()->convertTo(add, false);
+ }
+ item->appendRow(add);
+ ++cur;
+ }
+}
+
+bool ParserTreeItem::canFetchMore(QStandardItem *item) const
+{
+ if (!item)
+ return false;
+
+ // incremental data population - so we have to check children
+ // count subchildren of both - current QStandardItem and our internal
+
+ // for the current UI item
+ int storedChildren = 0;
+ for (int i = 0; i < item->rowCount(); i++) {
+ QStandardItem *child = item->child(i);
+ if (!child)
+ continue;
+ storedChildren += child->rowCount();
+ }
+ // children for the internal state
+ int internalChildren = 0;
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+ d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+ d_ptr->symbolInformations.constEnd();
+ while(curHash != endHash) {
+ const ParserTreeItem::Ptr &child = curHash.value();
+ if (!child.isNull()) {
+ internalChildren += child->childCount();
+ // if there is already more items than stored, then can be stopped right now
+ if (internalChildren > storedChildren)
+ break;
+ }
+ ++curHash;
+ }
+
+ if(storedChildren < internalChildren)
+ return true;
+
+ return false;
+}
+
+void ParserTreeItem::fetchMore(QStandardItem *item) const
+{
+ if (!item)
+ return;
+
+ for (int i = 0; i < item->rowCount(); i++) {
+ QStandardItem *child = item->child(i);
+ if (!child)
+ continue;
+
+ const SymbolInformation &childInf = Utils::symbolInformationFromItem(child);
+
+ if (d_ptr->symbolInformations.contains(childInf)) {
+ const ParserTreeItem::Ptr &childPtr = d_ptr->symbolInformations[childInf];
+ if (childPtr.isNull())
+ continue;
+
+ // create a standard
+ QScopedPointer<QStandardItem> state(new QStandardItem());
+ childPtr->convertTo(state.data(), false);
+
+ Utils::fetchItemToTarget(child, state.data());
+ }
+ }
+}
+
+void ParserTreeItem::debugDump(int ident) const
+{
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+ d_ptr->symbolInformations.constBegin();
+ QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+ d_ptr->symbolInformations.constEnd();
+ while(curHash != endHash) {
+ const SymbolInformation &inf = curHash.key();
+ qDebug() << QString(2*ident, QChar(' ')) << inf.iconType() << inf.name() << inf.type()
+ << curHash.value().isNull();
+ if (!curHash.value().isNull())
+ curHash.value()->debugDump(ident + 1);
+
+ ++curHash;
+ }
+}
+
+} // namespace Internal
+} // namespace ClassView
+
diff --git a/src/plugins/classview/classviewparsertreeitem.h b/src/plugins/classview/classviewparsertreeitem.h
new file mode 100644
index 0000000000..054aee26f7
--- /dev/null
+++ b/src/plugins/classview/classviewparsertreeitem.h
@@ -0,0 +1,190 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWPARSERTREEITEM_H
+#define CLASSVIEWPARSERTREEITEM_H
+
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+
+#include <QtCore/QSharedPointer>
+#include <QtCore/QScopedPointer>
+
+QT_FORWARD_DECLARE_CLASS(QStandardItem)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class ParserTreeItem
+ \brief Item for the internal Class View Tree
+
+ Item for Class View Tree.
+ Not virtual - to speed up its work.
+ */
+
+class ParserTreeItem
+{
+public:
+ typedef QSharedPointer<ParserTreeItem> Ptr;
+ typedef QSharedPointer<const ParserTreeItem> ConstPtr;
+
+public:
+ ParserTreeItem();
+ ~ParserTreeItem();
+
+ /*!
+ \brief Copy content of \a from item with children to this one.
+ \param from 'From' item
+ */
+ void copyTree(const ParserTreeItem::ConstPtr &from);
+
+ /*!
+ \brief Copy of \a from item to this one.
+ \param from 'From' item
+ */
+ void copy(const ParserTreeItem::ConstPtr &from);
+
+ /*!
+ \brief Add information about symbol location
+ \param location Filled \a SymbolLocation struct with a correct information
+ \sa SymbolLocation, removeSymbolLocation, symbolLocations
+ */
+ void addSymbolLocation(const SymbolLocation &location);
+
+ /*!
+ \brief Add information about symbol locations
+ \param locations Filled \a SymbolLocation struct with a correct information
+ \sa SymbolLocation, removeSymbolLocation, symbolLocations
+ */
+ void addSymbolLocation(const QSet<SymbolLocation> &locations);
+
+ /*!
+ \brief Remove information about symbol location
+ \param location Filled \a SymbolLocation struct with a correct information
+ \sa SymbolLocation, addSymbolLocation, symbolLocations
+ */
+ void removeSymbolLocation(const SymbolLocation &location);
+
+ /*!
+ \brief Remove information about symbol locations
+ \param locations Filled \a SymbolLocation struct with a correct information
+ \sa SymbolLocation, addSymbolLocation, symbolLocations
+ */
+ void removeSymbolLocations(const QSet<SymbolLocation> &locations);
+
+ /*!
+ \brief Get information about symbol positions
+ \sa SymbolLocation, addSymbolLocation, removeSymbolLocation
+ */
+ QSet<SymbolLocation> symbolLocations() const;
+
+ /*!
+ \brief Append child
+ \param item Child item
+ \param inf Symbol information
+ */
+ void appendChild(const ParserTreeItem::Ptr &item, const SymbolInformation &inf);
+
+ /*!
+ \brief Remove child
+ \param inf SymbolInformation which has to be removed
+ */
+ void removeChild(const SymbolInformation &inf);
+
+ /*!
+ \brief Get an item
+ \param inf Symbol information about needed child
+ \return Found child
+ */
+ ParserTreeItem::Ptr child(const SymbolInformation &inf) const;
+
+ /*!
+ \brief How many children
+ \return Amount of chilren
+ */
+ int childCount() const;
+
+ /*!
+ \brief Append this item to the \a QStandardIten item
+ \param item QStandardItem
+ \param recursive Do it recursively for the tree items or not (might be needed for
+ the lazy data population
+
+ */
+ void convertTo(QStandardItem *item, bool recursive = true) const;
+
+ // additional properties
+ //! Assigned icon
+ QIcon icon() const;
+
+ //! Set an icon for this tree node
+ void setIcon(const QIcon &icon);
+
+ /*!
+ \brief Add an internal state with \a target.
+ \param target Item which contains the correct current state
+ */
+ void add(const ParserTreeItem::ConstPtr &target);
+
+ /*!
+ \brief Subtract an internal state with \a target.
+ \param target Item which contains the subtrahend
+ */
+ void subtract(const ParserTreeItem::ConstPtr &target);
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item which has to be checked
+ */
+ bool canFetchMore(QStandardItem *item) const;
+
+ /*!
+ \brief Lazy data population for a \a QStandardItemModel
+ \param item Item which will be populated (if needed)
+ */
+ void fetchMore(QStandardItem *item) const;
+
+ /*!
+ \brief Debug dump
+ */
+ void debugDump(int ident = 0) const;
+
+protected:
+ ParserTreeItem &operator=(const ParserTreeItem &other);
+
+private:
+ //! Private class data pointer
+ QScopedPointer<struct ParserTreeItemPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPARSERTREEITEM_H
diff --git a/src/plugins/classview/classviewplugin.cpp b/src/plugins/classview/classviewplugin.cpp
new file mode 100644
index 0000000000..fc69b461cc
--- /dev/null
+++ b/src/plugins/classview/classviewplugin.cpp
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewplugin.h"
+#include "classviewmanager.h"
+#include "classviewnavigationwidgetfactory.h"
+
+#include <QtCore/QtPlugin>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// PluginPrivate //////////////////////////////////
+/*!
+ \struct PluginPrivate
+ \brief Private class data for \a Plugin
+ \sa Plugin
+ */
+struct PluginPrivate
+{
+ //! Pointer to Navi Widget Factory
+ QPointer<NavigationWidgetFactory> navigationWidgetFactory;
+
+ //! Pointer to Manager
+ QPointer<Manager> manager;
+};
+
+///////////////////////////////// Plugin //////////////////////////////////
+
+Plugin::Plugin()
+ : d_ptr(new PluginPrivate())
+{
+}
+
+Plugin::~Plugin()
+{
+}
+
+bool Plugin::initialize(const QStringList &arguments, QString *errorMessage)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorMessage)
+
+ // create a navigation widget factory
+ d_ptr->navigationWidgetFactory = NavigationWidgetFactory::instance();
+
+ // add to ExtensionSystem
+ addAutoReleasedObject(d_ptr->navigationWidgetFactory);
+
+ // create manager
+ d_ptr->manager = Manager::instance(this);
+
+ return true;
+}
+
+void Plugin::extensionsInitialized()
+{
+}
+
+} // namespace Internal
+} // namespace ClassView
+
+Q_EXPORT_PLUGIN(ClassView::Internal::Plugin)
diff --git a/src/plugins/classview/classviewplugin.h b/src/plugins/classview/classviewplugin.h
new file mode 100644
index 0000000000..b2094597db
--- /dev/null
+++ b/src/plugins/classview/classviewplugin.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWPLUGIN_H
+#define CLASSVIEWPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+#include <QtCore/QScopedPointer>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class Plugin
+ \brief Base class for Class View plugin (class/namespaces in the navigation pane)
+ */
+
+class Plugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(Plugin)
+
+public:
+ //! Constructor
+ Plugin();
+
+ //! Destructor
+ virtual ~Plugin();
+
+ //! \implements ExtensionSystem::IPlugin::initialize
+ bool initialize(const QStringList &arguments, QString *error_message = 0);
+
+ //! \implements ExtensionSystem::IPlugin::extensionsInitialized
+ void extensionsInitialized();
+
+private:
+ //! private class data pointer
+ QScopedPointer<struct PluginPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPLUGIN_H
diff --git a/src/plugins/classview/classviewsymbolinformation.cpp b/src/plugins/classview/classviewsymbolinformation.cpp
new file mode 100644
index 0000000000..209e809c4a
--- /dev/null
+++ b/src/plugins/classview/classviewsymbolinformation.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewsymbolinformation.h"
+#include "classviewutils.h"
+
+#include <QtCore/QPair>
+#include <QtCore/QHash>
+
+namespace ClassView {
+namespace Internal {
+
+SymbolInformation::SymbolInformation() :
+ m_iconType(INT_MIN),
+ m_hash(0)
+{
+}
+
+SymbolInformation::SymbolInformation(const QString &valueName, const QString &valueType,
+ int valueIconType) :
+ m_iconType(valueIconType),
+ m_name(valueName),
+ m_type(valueType)
+{
+ // calculate hash
+ m_hash = qHash(qMakePair(m_iconType, qMakePair(m_name, m_type)));
+}
+
+int SymbolInformation::iconTypeSortOrder() const
+{
+ return Utils::iconTypeSortOrder(m_iconType);
+}
+
+bool SymbolInformation::operator<(const SymbolInformation &other) const
+{
+ // comparsion is not a critical for speed
+ if (iconType() != other.iconType()) {
+ int l = iconTypeSortOrder();
+ int r = other.iconTypeSortOrder();
+ if (l < r)
+ return true;
+ if (l > r)
+ return false;
+ }
+
+ int cmp = name().compare(other.name(), Qt::CaseInsensitive);
+ if (cmp < 0)
+ return true;
+ if (cmp > 0)
+ return false;
+ return type().compare(other.type(), Qt::CaseInsensitive) < 0;
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewsymbolinformation.h b/src/plugins/classview/classviewsymbolinformation.h
new file mode 100644
index 0000000000..988fb0f0b7
--- /dev/null
+++ b/src/plugins/classview/classviewsymbolinformation.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWSYMBOLINFORMATION_H
+#define CLASSVIEWSYMBOLINFORMATION_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class SymbolInformation
+ \brief
+ */
+
+class SymbolInformation
+{
+public:
+ SymbolInformation();
+ SymbolInformation(const QString &name, const QString &type, int iconType = INT_MIN);
+
+ bool operator<(const SymbolInformation &other) const;
+
+ inline const QString &name() const { return m_name; }
+ inline const QString &type() const { return m_type; }
+ inline int iconType() const { return m_iconType; }
+ inline uint hash() const { return m_hash; }
+
+ /*!
+ \brief Get an icon type sort order. Not pre-calculated - is needed for converting
+ to Standard Item only.
+ \return Sort order number.
+ */
+ int iconTypeSortOrder() const;
+
+private:
+ int m_iconType; //!< icon type
+ QString m_name; //!< symbol name (e.g. SymbolInformation)
+ QString m_type; //!< symbol type (e.g. (int char))
+
+ uint m_hash; //!< precalculated hash value - to speed up qHash
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+inline bool operator==(const ClassView::Internal::SymbolInformation &a,
+ const ClassView::Internal::SymbolInformation &b)
+{
+ return a.iconType() == b.iconType() && a.name() == b.name() && a.type() == b.type();
+}
+
+//! qHash overload for QHash/QSet
+inline uint qHash(const ClassView::Internal::SymbolInformation &information)
+{
+ return information.hash();
+}
+
+Q_DECLARE_METATYPE(ClassView::Internal::SymbolInformation)
+
+#endif // CLASSVIEWSYMBOLINFORMATION_H
diff --git a/src/plugins/classview/classviewsymbollocation.cpp b/src/plugins/classview/classviewsymbollocation.cpp
new file mode 100644
index 0000000000..d245b06e93
--- /dev/null
+++ b/src/plugins/classview/classviewsymbollocation.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewsymbollocation.h"
+#include <QtCore/QPair>
+#include <QtCore/QHash>
+
+namespace ClassView {
+namespace Internal {
+
+SymbolLocation::SymbolLocation() :
+ m_line(0),
+ m_column(0),
+ m_hash(0)
+{
+}
+
+SymbolLocation::SymbolLocation(QString file, int lineNumber, int columnNumber) :
+ m_fileName(file),
+ m_line(lineNumber),
+ m_column(columnNumber)
+{
+ if (m_column < 0)
+ m_column = 0;
+
+ // pre-computate hash value
+ m_hash = qHash(qMakePair(m_fileName, qMakePair(m_line, m_column)));
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewsymbollocation.h b/src/plugins/classview/classviewsymbollocation.h
new file mode 100644
index 0000000000..b886a2470f
--- /dev/null
+++ b/src/plugins/classview/classviewsymbollocation.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWSYMBOLLOCATION_H
+#define CLASSVIEWSYMBOLLOCATION_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class SymbolLocation
+ \brief Special struct to store information about symbol location (to find which exactly location
+ has to be open when the user clicks on any tree item. It might be used in QSet/QHash.
+ */
+class SymbolLocation
+{
+public:
+ //! Default constructor
+ SymbolLocation();
+
+ //! Constructor
+ SymbolLocation(QString file, int lineNumber = 0, int columnNumber = 0);
+
+ inline const QString &fileName() const { return m_fileName; }
+ inline int line() const { return m_line; }
+ inline int column() const { return m_column; }
+ inline int hash() const { return m_hash; }
+
+private:
+ QString m_fileName; //!< file name
+ int m_line; //!< line number
+ int m_column; //!< column
+ int m_hash; //!< precalculated hash value for the object, to speed up qHash
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+inline bool operator==(const ClassView::Internal::SymbolLocation &a,
+ const ClassView::Internal::SymbolLocation &b)
+{
+ return a.line() == b.line() && a.column() == b.column() && a.fileName() == b.fileName();
+}
+
+//! qHash overload for QHash/QSet
+inline uint qHash(const ClassView::Internal::SymbolLocation &location)
+{
+ return location.hash();
+}
+
+Q_DECLARE_METATYPE(ClassView::Internal::SymbolLocation)
+
+#endif // CLASSVIEWSYMBOLLOCATION_H
diff --git a/src/plugins/classview/classviewtreeitemmodel.cpp b/src/plugins/classview/classviewtreeitemmodel.cpp
new file mode 100644
index 0000000000..5ec992cdb2
--- /dev/null
+++ b/src/plugins/classview/classviewtreeitemmodel.cpp
@@ -0,0 +1,129 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewtreeitemmodel.h"
+#include "classviewconstants.h"
+#include "classviewmanager.h"
+#include "classviewutils.h"
+
+#include <cplusplus/Icons.h>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// TreeItemModelPrivate //////////////////////////////////
+
+/*!
+ \struct TreeItemModelPrivate
+ \brief Private class data for \a TreeItemModel
+ \sa TreeItemModel
+ */
+struct TreeItemModelPrivate
+{
+ //! icon provider
+ CPlusPlus::Icons icons;
+};
+
+///////////////////////////////// TreeItemModel //////////////////////////////////
+
+TreeItemModel::TreeItemModel(QObject *parent)
+ : QStandardItemModel(parent),
+ d_ptr(new TreeItemModelPrivate())
+{
+}
+
+TreeItemModel::~TreeItemModel()
+{
+}
+
+QVariant TreeItemModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QStandardItemModel::data(index, role);
+
+ switch (role) {
+ case Qt::DecorationRole: {
+ QVariant iconType = data(index, Constants::IconTypeRole);
+ if (iconType.isValid()) {
+ bool ok = false;
+ int type = iconType.toInt(&ok);
+ if (ok && type >= 0)
+ return d_ptr->icons.iconForType(static_cast<CPlusPlus::Icons::IconType>(type));
+ }
+ }
+ break;
+ case Qt::ToolTipRole:
+ case Qt::DisplayRole: {
+ const SymbolInformation &inf = Utils::symbolInformationFromItem(itemFromIndex(index));
+
+ if (inf.name() == inf.type() || inf.iconType() < 0)
+ return inf.name();
+
+ QString name(inf.name());
+
+ if (!inf.type().isEmpty())
+ name += QLatin1String(" ") + inf.type();
+
+ return name;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return QStandardItemModel::data(index, role);
+}
+
+bool TreeItemModel::canFetchMore(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return false;
+
+ return Manager::instance()->canFetchMore(itemFromIndex(parent));
+}
+
+void TreeItemModel::fetchMore(const QModelIndex &parent)
+{
+ if (!parent.isValid())
+ return;
+
+ return Manager::instance()->fetchMore(itemFromIndex(parent));
+}
+
+void TreeItemModel::moveRootToTarget(const QStandardItem *target)
+{
+ emit layoutAboutToBeChanged();
+
+ Utils::moveItemToTarget(invisibleRootItem(), target);
+
+ emit layoutChanged();
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewtreeitemmodel.h b/src/plugins/classview/classviewtreeitemmodel.h
new file mode 100644
index 0000000000..45bcf99796
--- /dev/null
+++ b/src/plugins/classview/classviewtreeitemmodel.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWTREEITEMMODEL_H
+#define CLASSVIEWTREEITEMMODEL_H
+
+#include <QtGui/QStandardItemModel>
+#include <QtCore/QModelIndex>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSet>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class TreeItemModel
+ \brief Model for Class View Tree
+ */
+
+class TreeItemModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit TreeItemModel(QObject *parent=0);
+ virtual ~TreeItemModel();
+
+ /*!
+ \brief move root item to the target
+ \param target Target item
+ */
+ void moveRootToTarget(const QStandardItem *target);
+
+ //! \implements QStandardItemModel::data
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ //! \implements QStandardItemModel::canFetchMore
+ virtual bool canFetchMore(const QModelIndex &parent) const;
+
+ //! \implements QStandardItemModel::fetchMore
+ virtual void fetchMore(const QModelIndex &parent);
+
+private:
+ //! private class data pointer
+ QScopedPointer<struct TreeItemModelPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWTREEMODEL_H
diff --git a/src/plugins/classview/classviewutils.cpp b/src/plugins/classview/classviewutils.cpp
new file mode 100644
index 0000000000..244a55e903
--- /dev/null
+++ b/src/plugins/classview/classviewutils.cpp
@@ -0,0 +1,232 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "classviewutils.h"
+#include "classviewconstants.h"
+#include "classviewsymbolinformation.h"
+
+// needed for the correct sorting order
+#include <cplusplus/Icons.h>
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QDebug>
+
+namespace ClassView {
+namespace Constants {
+
+//! Default icon sort order
+const int IconSortOrder[] = {
+ CPlusPlus::Icons::NamespaceIconType,
+ CPlusPlus::Icons::EnumIconType,
+ CPlusPlus::Icons::ClassIconType,
+ CPlusPlus::Icons::FuncPublicIconType,
+ CPlusPlus::Icons::FuncProtectedIconType,
+ CPlusPlus::Icons::FuncPrivateIconType,
+ CPlusPlus::Icons::SignalIconType,
+ CPlusPlus::Icons::SlotPublicIconType,
+ CPlusPlus::Icons::SlotProtectedIconType,
+ CPlusPlus::Icons::SlotPrivateIconType,
+ CPlusPlus::Icons::VarPublicIconType,
+ CPlusPlus::Icons::VarProtectedIconType,
+ CPlusPlus::Icons::VarPrivateIconType,
+ CPlusPlus::Icons::EnumeratorIconType,
+ CPlusPlus::Icons::KeywordIconType,
+ CPlusPlus::Icons::MacroIconType,
+ CPlusPlus::Icons::UnknownIconType
+};
+
+} // namespace Constants
+
+namespace Internal {
+
+Utils::Utils()
+{
+}
+
+QList<QVariant> Utils::locationsToRole(const QSet<SymbolLocation> &locations)
+{
+ QList<QVariant> locationsVar;
+ foreach(const SymbolLocation &loc, locations)
+ locationsVar.append(QVariant::fromValue(loc));
+
+ return locationsVar;
+}
+
+QSet<SymbolLocation> Utils::roleToLocations(const QList<QVariant> &locationsVar)
+{
+ QSet<SymbolLocation> locations;
+ foreach(const QVariant &loc, locationsVar) {
+ if (loc.canConvert<SymbolLocation>()) {
+ locations.insert(loc.value<SymbolLocation>());
+ }
+ }
+
+ return locations;
+}
+
+int Utils::iconTypeSortOrder(int icon)
+{
+ static QHash<int, int> sortOrder;
+
+ // initialization
+ if (sortOrder.count() == 0) {
+ for (unsigned i = 0 ;
+ i < sizeof(Constants::IconSortOrder) / sizeof(Constants::IconSortOrder[0]) ; ++i)
+ sortOrder.insert(Constants::IconSortOrder[i], sortOrder.count());
+ }
+
+ // if it is missing - return the same value
+ if (!sortOrder.contains(icon))
+ return icon;
+
+ return sortOrder[icon];
+}
+
+QStandardItem *Utils::setSymbolInformationToItem(const SymbolInformation &information,
+ QStandardItem *item)
+{
+ Q_ASSERT(item);
+
+ item->setData(information.name(), Constants::SymbolNameRole);
+ item->setData(information.type(), Constants::SymbolTypeRole);
+ item->setData(information.iconType(), Constants::IconTypeRole);
+
+ return item;
+}
+
+SymbolInformation Utils::symbolInformationFromItem(const QStandardItem *item)
+{
+ Q_ASSERT(item);
+
+ if (!item)
+ return SymbolInformation();
+
+ const QString &name = item->data(Constants::SymbolNameRole).toString();
+ const QString &type = item->data(Constants::SymbolTypeRole).toString();
+ int iconType = 0;
+
+ QVariant var = item->data(Constants::IconTypeRole);
+ bool ok = false;
+ int value;
+ if (var.isValid())
+ value = var.toInt(&ok);
+ if (ok)
+ iconType = value;
+
+ return SymbolInformation(name, type, iconType);
+}
+
+void Utils::fetchItemToTarget(QStandardItem *item, const QStandardItem *target)
+{
+ if (!item || !target)
+ return;
+
+ int itemIndex = 0;
+ int targetIndex = 0;
+ int itemRows = item->rowCount();
+ int targetRows = target->rowCount();
+
+ while (itemIndex < itemRows && targetIndex < targetRows) {
+ const QStandardItem *itemChild = item->child(itemIndex);
+ const QStandardItem *targetChild = target->child(targetIndex);
+
+ const SymbolInformation &itemInf = symbolInformationFromItem(itemChild);
+ const SymbolInformation &targetInf = symbolInformationFromItem(targetChild);
+
+ if (itemInf < targetInf) {
+ ++itemIndex;
+ } else if (itemInf == targetInf) {
+ ++itemIndex;
+ ++targetIndex;
+ } else {
+ item->insertRow(itemIndex, targetChild->clone());
+ ++itemIndex;
+ ++itemRows;
+ ++targetIndex;
+ }
+ }
+
+ // append
+ while (targetIndex < targetRows) {
+ item->appendRow(target->child(targetIndex)->clone());
+ ++targetIndex;
+ }
+}
+
+void Utils::moveItemToTarget(QStandardItem *item, const QStandardItem *target)
+{
+ if (!item || !target)
+ return;
+
+ int itemIndex = 0;
+ int targetIndex = 0;
+ int itemRows = item->rowCount();
+ int targetRows = target->rowCount();
+
+ while (itemIndex < itemRows && targetIndex < targetRows) {
+ QStandardItem *itemChild = item->child(itemIndex);
+ const QStandardItem *targetChild = target->child(targetIndex);
+
+ const SymbolInformation &itemInf = Utils::symbolInformationFromItem(itemChild);
+ const SymbolInformation &targetInf = Utils::symbolInformationFromItem(targetChild);
+
+ if (itemInf < targetInf) {
+ item->removeRow(itemIndex);
+ --itemRows;
+ } else if (itemInf == targetInf) {
+ moveItemToTarget(itemChild, targetChild);
+ ++itemIndex;
+ ++targetIndex;
+ } else {
+ item->insertRow(itemIndex, targetChild->clone());
+ moveItemToTarget(item->child(itemIndex), targetChild);
+ ++itemIndex;
+ ++itemRows;
+ ++targetIndex;
+ }
+ }
+
+ // append
+ while (targetIndex < targetRows) {
+ item->appendRow(target->child(targetIndex)->clone());
+ moveItemToTarget(item->child(itemIndex), target->child(targetIndex));
+ ++itemIndex;
+ ++itemRows;
+ ++targetIndex;
+ }
+
+ // remove end of item
+ while (itemIndex < itemRows) {
+ item->removeRow(itemIndex);
+ --itemRows;
+ }
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewutils.h b/src/plugins/classview/classviewutils.h
new file mode 100644
index 0000000000..3a7987b995
--- /dev/null
+++ b/src/plugins/classview/classviewutils.h
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CLASSVIEWUTILS_H
+#define CLASSVIEWUTILS_H
+
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include <QtCore/QVariant>
+#include <QtCore/QList>
+#include <QtCore/QSet>
+
+QT_FORWARD_DECLARE_CLASS(QStandardItem)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+ \class Utils
+ \brief Some common utils
+ */
+
+class Utils
+{
+ //! Private constructor
+ Utils();
+public:
+
+ /*!
+ \brief convert internal location container to QVariant compatible
+ \param locations Set of SymbolLocations
+ \return List of variant locations (can be added to an item's data)
+ */
+ static QList<QVariant> locationsToRole(const QSet<SymbolLocation> &locations);
+
+ /*!
+ \brief convert QVariant location container to internal
+ \param locations List of variant locations (from an item's data)
+ \return Set of SymbolLocations
+ */
+ static QSet<SymbolLocation> roleToLocations(const QList<QVariant> &locations);
+
+ /*!
+ \brief Returns sort order value for the icon type
+ \param iconType Icon type
+ \return Sort order value for the provided icon type
+ */
+ static int iconTypeSortOrder(int iconType);
+
+ /*!
+ \brief Get symbol information for the \a QStandardItem
+ \param item Item
+ \return Filled symbol information.
+ */
+ static SymbolInformation symbolInformationFromItem(const QStandardItem *item);
+
+ /*!
+ \brief Set symbol information to the \a QStandardItem
+ \param information
+ \param item Item
+ \return Filled item
+ */
+ static QStandardItem *setSymbolInformationToItem(const SymbolInformation &information,
+ QStandardItem *item);
+
+ /*!
+ \brief Update an item to the target. (sorted, for fetching)
+ \param item Source item
+ \param target Target item
+ */
+ static void fetchItemToTarget(QStandardItem *item, const QStandardItem *target);
+
+ /*!
+ \brief Move an item to the target. (sorted)
+ \param item Source item
+ \param target Target item
+ */
+ static void moveItemToTarget(QStandardItem *item, const QStandardItem *target);
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWUTILS_H
diff --git a/src/plugins/classview/images/hierarchicalmode.png b/src/plugins/classview/images/hierarchicalmode.png
new file mode 100644
index 0000000000..88432d2cb1
--- /dev/null
+++ b/src/plugins/classview/images/hierarchicalmode.png
Binary files differ
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index f66ea47977..094668d4c0 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -34,6 +34,7 @@ SUBDIRS = plugin_coreplugin \
plugin_genericprojectmanager \
plugin_qmljseditor \
plugin_mercurial \
+ plugin_classview \
debugger/dumper.pro
contains(QT_CONFIG, declarative) {
@@ -208,3 +209,9 @@ plugin_mercurial.subdir = mercurial
plugin_mercurial.depends = plugin_vcsbase
plugin_mercurial.depends += plugin_projectexplorer
plugin_mercurial.depends += plugin_coreplugin
+
+plugin_classview.subdir = classview
+plugin_classview.depends = plugin_coreplugin
+plugin_classview.depends += plugin_cpptools
+plugin_classview.depends += plugin_projectexplorer
+plugin_classview.depends += plugin_texteditor