forked from qt-creator/qt-creator
Change-Id: I5cdc6ec672a970a6fcfa52dfa14c2f515cf27f6d Reviewed-by: David Schulz <david.schulz@qt.io>
1761 lines
58 KiB
C++
1761 lines
58 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of Qt Creator.
|
|
**
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "cppcodemodelinspectordialog.h"
|
|
#include "ui_cppcodemodelinspectordialog.h"
|
|
#include "cppeditor.h"
|
|
#include "cppeditordocument.h"
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
#include <coreplugin/icore.h>
|
|
#include <cpptools/baseeditordocumentprocessor.h>
|
|
#include <cpptools/cppcodemodelinspectordumper.h>
|
|
#include <cpptools/cppmodelmanager.h>
|
|
#include <cpptools/cpptoolsbridge.h>
|
|
#include <cpptools/cppworkingcopy.h>
|
|
#include <projectexplorer/project.h>
|
|
|
|
#include <cplusplus/CppDocument.h>
|
|
#include <cplusplus/Overview.h>
|
|
#include <cplusplus/Token.h>
|
|
#include <utils/qtcassert.h>
|
|
|
|
#include <QAbstractTableModel>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QPushButton>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
#include <algorithm>
|
|
|
|
using namespace CPlusPlus;
|
|
using namespace CppTools;
|
|
namespace CMI = CppCodeModelInspector;
|
|
|
|
namespace {
|
|
|
|
template <class T> void resizeColumns(QTreeView *view)
|
|
{
|
|
for (int column = 0; column < T::ColumnCount - 1; ++column)
|
|
view->resizeColumnToContents(column);
|
|
}
|
|
|
|
TextEditor::BaseTextEditor *currentEditor()
|
|
{
|
|
return qobject_cast<TextEditor::BaseTextEditor*>(Core::EditorManager::currentEditor());
|
|
}
|
|
|
|
QString fileInCurrentEditor()
|
|
{
|
|
if (TextEditor::BaseTextEditor *editor = currentEditor())
|
|
return editor->document()->filePath().toString();
|
|
return QString();
|
|
}
|
|
|
|
class DepthFinder : public SymbolVisitor {
|
|
public:
|
|
DepthFinder() : m_symbol(0), m_depth(-1), m_foundDepth(-1), m_stop(false) {}
|
|
|
|
int operator()(const Document::Ptr &document, Symbol *symbol)
|
|
{
|
|
m_symbol = symbol;
|
|
accept(document->globalNamespace());
|
|
return m_foundDepth;
|
|
}
|
|
|
|
bool preVisit(Symbol *symbol)
|
|
{
|
|
if (m_stop)
|
|
return false;
|
|
|
|
if (symbol->asScope()) {
|
|
++m_depth;
|
|
if (symbol == m_symbol) {
|
|
m_foundDepth = m_depth;
|
|
m_stop = true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void postVisit(Symbol *symbol)
|
|
{
|
|
if (symbol->asScope())
|
|
--m_depth;
|
|
}
|
|
|
|
private:
|
|
Symbol *m_symbol;
|
|
int m_depth;
|
|
int m_foundDepth;
|
|
bool m_stop;
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
namespace CppEditor {
|
|
namespace Internal {
|
|
|
|
// --- FilterableView -----------------------------------------------------------------------------
|
|
|
|
class FilterableView : public QWidget
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
FilterableView(QWidget *parent);
|
|
|
|
void setModel(QAbstractItemModel *model);
|
|
QItemSelectionModel *selectionModel() const;
|
|
void selectIndex(const QModelIndex &index);
|
|
void resizeColumns(int columnCount);
|
|
void clearFilter();
|
|
|
|
signals:
|
|
void filterChanged(const QString &filterText);
|
|
|
|
private:
|
|
QTreeView *view;
|
|
QLineEdit *lineEdit;
|
|
};
|
|
|
|
FilterableView::FilterableView(QWidget *parent)
|
|
: QWidget(parent)
|
|
{
|
|
view = new QTreeView(this);
|
|
view->setAlternatingRowColors(true);
|
|
view->setTextElideMode(Qt::ElideMiddle);
|
|
view->setSortingEnabled(true);
|
|
|
|
lineEdit = new QLineEdit(this);
|
|
lineEdit->setPlaceholderText(QLatin1String("File Path"));
|
|
QObject::connect(lineEdit, &QLineEdit::textChanged, this, &FilterableView::filterChanged);
|
|
|
|
QLabel *label = new QLabel(QLatin1String("&Filter:"), this);
|
|
label->setBuddy(lineEdit);
|
|
|
|
QPushButton *clearButton = new QPushButton(QLatin1String("&Clear"), this);
|
|
QObject::connect(clearButton, &QAbstractButton::clicked, this, &FilterableView::clearFilter);
|
|
|
|
QHBoxLayout *filterBarLayout = new QHBoxLayout();
|
|
filterBarLayout->addWidget(label);
|
|
filterBarLayout->addWidget(lineEdit);
|
|
filterBarLayout->addWidget(clearButton);
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout();
|
|
mainLayout->addWidget(view);
|
|
mainLayout->addLayout(filterBarLayout);
|
|
|
|
setLayout(mainLayout);
|
|
}
|
|
|
|
void FilterableView::setModel(QAbstractItemModel *model)
|
|
{
|
|
view->setModel(model);
|
|
}
|
|
|
|
QItemSelectionModel *FilterableView::selectionModel() const
|
|
{
|
|
return view->selectionModel();
|
|
}
|
|
|
|
void FilterableView::selectIndex(const QModelIndex &index)
|
|
{
|
|
if (index.isValid()) {
|
|
view->selectionModel()->setCurrentIndex(index,
|
|
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
|
}
|
|
}
|
|
|
|
void FilterableView::resizeColumns(int columnCount)
|
|
{
|
|
for (int column = 0; column < columnCount - 1; ++column)
|
|
view->resizeColumnToContents(column);
|
|
}
|
|
|
|
void FilterableView::clearFilter()
|
|
{
|
|
lineEdit->clear();
|
|
}
|
|
|
|
// --- ProjectFilesModel --------------------------------------------------------------------------
|
|
|
|
class ProjectFilesModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
ProjectFilesModel(QObject *parent);
|
|
void configure(const QVector<ProjectFile> &files);
|
|
void clear();
|
|
|
|
enum Columns { FileKindColumn, FilePathColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QVector<ProjectFile> m_files;
|
|
};
|
|
|
|
ProjectFilesModel::ProjectFilesModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void ProjectFilesModel::configure(const QVector<ProjectFile> &files)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_files = files;
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void ProjectFilesModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_files.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int ProjectFilesModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_files.size();
|
|
}
|
|
|
|
int ProjectFilesModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return ProjectFilesModel::ColumnCount;
|
|
}
|
|
|
|
QVariant ProjectFilesModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role == Qt::DisplayRole) {
|
|
const int row = index.row();
|
|
const int column = index.column();
|
|
if (column == FileKindColumn) {
|
|
return CMI::Utils::toString(m_files.at(row).kind);
|
|
} else if (column == FilePathColumn) {
|
|
return m_files.at(row).path;
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant ProjectFilesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case FileKindColumn:
|
|
return QLatin1String("File Kind");
|
|
case FilePathColumn:
|
|
return QLatin1String("File Path");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- KeyValueModel ------------------------------------------------------------------------------
|
|
|
|
class KeyValueModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
typedef QList<QPair<QString, QString> > Table;
|
|
|
|
KeyValueModel(QObject *parent);
|
|
void configure(const Table &table);
|
|
void clear();
|
|
|
|
enum Columns { KeyColumn, ValueColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
Table m_table;
|
|
};
|
|
|
|
KeyValueModel::KeyValueModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void KeyValueModel::configure(const Table &table)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_table = table;
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void KeyValueModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_table.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int KeyValueModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_table.size();
|
|
}
|
|
|
|
int KeyValueModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return KeyValueModel::ColumnCount;
|
|
}
|
|
|
|
QVariant KeyValueModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role == Qt::DisplayRole) {
|
|
const int row = index.row();
|
|
const int column = index.column();
|
|
if (column == KeyColumn) {
|
|
return m_table.at(row).first;
|
|
} else if (column == ValueColumn) {
|
|
return m_table.at(row).second;
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant KeyValueModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case KeyColumn:
|
|
return QLatin1String("Key");
|
|
case ValueColumn:
|
|
return QLatin1String("Value");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- SnapshotModel ------------------------------------------------------------------------------
|
|
|
|
class SnapshotModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
SnapshotModel(QObject *parent);
|
|
void configure(const Snapshot &snapshot);
|
|
void setGlobalSnapshot(const Snapshot &snapshot);
|
|
|
|
QModelIndex indexForDocument(const QString &filePath);
|
|
|
|
enum Columns { SymbolCountColumn, SharedColumn, FilePathColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QList<Document::Ptr> m_documents;
|
|
Snapshot m_globalSnapshot;
|
|
};
|
|
|
|
SnapshotModel::SnapshotModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void SnapshotModel::configure(const Snapshot &snapshot)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_documents = CMI::Utils::snapshotToList(snapshot);
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void SnapshotModel::setGlobalSnapshot(const Snapshot &snapshot)
|
|
{
|
|
m_globalSnapshot = snapshot;
|
|
}
|
|
|
|
QModelIndex SnapshotModel::indexForDocument(const QString &filePath)
|
|
{
|
|
for (int i = 0, total = m_documents.size(); i < total; ++i) {
|
|
const Document::Ptr document = m_documents.at(i);
|
|
if (document->fileName() == filePath)
|
|
return index(i, FilePathColumn);
|
|
}
|
|
return QModelIndex();
|
|
}
|
|
|
|
int SnapshotModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_documents.size();
|
|
}
|
|
|
|
int SnapshotModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return SnapshotModel::ColumnCount;
|
|
}
|
|
|
|
QVariant SnapshotModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role == Qt::DisplayRole) {
|
|
const int column = index.column();
|
|
Document::Ptr document = m_documents.at(index.row());
|
|
if (column == SymbolCountColumn) {
|
|
return document->control()->symbolCount();
|
|
} else if (column == SharedColumn) {
|
|
Document::Ptr globalDocument = m_globalSnapshot.document(document->fileName());
|
|
const bool isShared
|
|
= globalDocument && globalDocument->fingerprint() == document->fingerprint();
|
|
return CMI::Utils::toString(isShared);
|
|
} else if (column == FilePathColumn) {
|
|
return QDir::toNativeSeparators(document->fileName());
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant SnapshotModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case SymbolCountColumn:
|
|
return QLatin1String("Symbols");
|
|
case SharedColumn:
|
|
return QLatin1String("Shared");
|
|
case FilePathColumn:
|
|
return QLatin1String("File Path");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- IncludesModel ------------------------------------------------------------------------------
|
|
|
|
static bool includesSorter(const Document::Include &i1,
|
|
const Document::Include &i2)
|
|
{
|
|
return i1.line() < i2.line();
|
|
}
|
|
|
|
class IncludesModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
IncludesModel(QObject *parent);
|
|
void configure(const QList<Document::Include> &includes);
|
|
void clear();
|
|
|
|
enum Columns { ResolvedOrNotColumn, LineNumberColumn, FilePathsColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QList<Document::Include> m_includes;
|
|
};
|
|
|
|
IncludesModel::IncludesModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void IncludesModel::configure(const QList<Document::Include> &includes)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_includes = includes;
|
|
std::stable_sort(m_includes.begin(), m_includes.end(), includesSorter);
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void IncludesModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_includes.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int IncludesModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_includes.size();
|
|
}
|
|
|
|
int IncludesModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return IncludesModel::ColumnCount;
|
|
}
|
|
|
|
QVariant IncludesModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role != Qt::DisplayRole && role != Qt::ForegroundRole)
|
|
return QVariant();
|
|
|
|
static const QBrush greenBrush(QColor(0, 139, 69));
|
|
static const QBrush redBrush(QColor(205, 38, 38));
|
|
|
|
const Document::Include include = m_includes.at(index.row());
|
|
const QString resolvedFileName = QDir::toNativeSeparators(include.resolvedFileName());
|
|
const bool isResolved = !resolvedFileName.isEmpty();
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
const int column = index.column();
|
|
if (column == ResolvedOrNotColumn) {
|
|
return CMI::Utils::toString(isResolved);
|
|
} else if (column == LineNumberColumn) {
|
|
return include.line();
|
|
} else if (column == FilePathsColumn) {
|
|
return QVariant(CMI::Utils::unresolvedFileNameWithDelimiters(include)
|
|
+ QLatin1String(" --> ") + resolvedFileName);
|
|
}
|
|
} else if (role == Qt::ForegroundRole) {
|
|
return isResolved ? greenBrush : redBrush;
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant IncludesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case ResolvedOrNotColumn:
|
|
return QLatin1String("Resolved");
|
|
case LineNumberColumn:
|
|
return QLatin1String("Line");
|
|
case FilePathsColumn:
|
|
return QLatin1String("File Paths");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- DiagnosticMessagesModel --------------------------------------------------------------------
|
|
|
|
static bool diagnosticMessagesModelSorter(const Document::DiagnosticMessage &m1,
|
|
const Document::DiagnosticMessage &m2)
|
|
{
|
|
return m1.line() < m2.line();
|
|
}
|
|
|
|
class DiagnosticMessagesModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
DiagnosticMessagesModel(QObject *parent);
|
|
void configure(const QList<Document::DiagnosticMessage> &messages);
|
|
void clear();
|
|
|
|
enum Columns { LevelColumn, LineColumnNumberColumn, MessageColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QList<Document::DiagnosticMessage> m_messages;
|
|
};
|
|
|
|
DiagnosticMessagesModel::DiagnosticMessagesModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void DiagnosticMessagesModel::configure(
|
|
const QList<Document::DiagnosticMessage> &messages)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_messages = messages;
|
|
std::stable_sort(m_messages.begin(), m_messages.end(), diagnosticMessagesModelSorter);
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void DiagnosticMessagesModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_messages.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int DiagnosticMessagesModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_messages.size();
|
|
}
|
|
|
|
int DiagnosticMessagesModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return DiagnosticMessagesModel::ColumnCount;
|
|
}
|
|
|
|
QVariant DiagnosticMessagesModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role != Qt::DisplayRole && role != Qt::ForegroundRole)
|
|
return QVariant();
|
|
|
|
static const QBrush yellowOrangeBrush(QColor(237, 145, 33));
|
|
static const QBrush redBrush(QColor(205, 38, 38));
|
|
static const QBrush darkRedBrushQColor(QColor(139, 0, 0));
|
|
|
|
const Document::DiagnosticMessage message = m_messages.at(index.row());
|
|
const Document::DiagnosticMessage::Level level
|
|
= static_cast<Document::DiagnosticMessage::Level>(message.level());
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
const int column = index.column();
|
|
if (column == LevelColumn) {
|
|
return CMI::Utils::toString(level);
|
|
} else if (column == LineColumnNumberColumn) {
|
|
return QVariant(QString::number(message.line()) + QLatin1Char(':')
|
|
+ QString::number(message.column()));
|
|
} else if (column == MessageColumn) {
|
|
return message.text();
|
|
}
|
|
} else if (role == Qt::ForegroundRole) {
|
|
switch (level) {
|
|
case Document::DiagnosticMessage::Warning:
|
|
return yellowOrangeBrush;
|
|
case Document::DiagnosticMessage::Error:
|
|
return redBrush;
|
|
case Document::DiagnosticMessage::Fatal:
|
|
return darkRedBrushQColor;
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant DiagnosticMessagesModel::headerData(int section, Qt::Orientation orientation, int role)
|
|
const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case LevelColumn:
|
|
return QLatin1String("Level");
|
|
case LineColumnNumberColumn:
|
|
return QLatin1String("Line:Column");
|
|
case MessageColumn:
|
|
return QLatin1String("Message");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- MacrosModel --------------------------------------------------------------------------------
|
|
|
|
class MacrosModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
MacrosModel(QObject *parent);
|
|
void configure(const QList<Macro> ¯os);
|
|
void clear();
|
|
|
|
enum Columns { LineNumberColumn, MacroColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QList<Macro> m_macros;
|
|
};
|
|
|
|
MacrosModel::MacrosModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void MacrosModel::configure(const QList<Macro> ¯os)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_macros = macros;
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void MacrosModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_macros.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int MacrosModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_macros.size();
|
|
}
|
|
|
|
int MacrosModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return MacrosModel::ColumnCount;
|
|
}
|
|
|
|
QVariant MacrosModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
const int column = index.column();
|
|
if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == MacroColumn)) {
|
|
const Macro macro = m_macros.at(index.row());
|
|
if (column == LineNumberColumn)
|
|
return macro.line();
|
|
else if (column == MacroColumn)
|
|
return macro.toString();
|
|
} else if (role == Qt::TextAlignmentRole) {
|
|
return Qt::AlignTop + Qt::AlignLeft;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant MacrosModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case LineNumberColumn:
|
|
return QLatin1String("Line");
|
|
case MacroColumn:
|
|
return QLatin1String("Macro");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- SymbolsModel -------------------------------------------------------------------------------
|
|
|
|
class SymbolsModel : public QAbstractItemModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
SymbolsModel(QObject *parent);
|
|
void configure(const Document::Ptr &document);
|
|
void clear();
|
|
|
|
enum Columns { SymbolColumn, LineNumberColumn, ColumnCount };
|
|
|
|
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
|
QModelIndex parent(const QModelIndex &child) const;
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
Document::Ptr m_document;
|
|
};
|
|
|
|
SymbolsModel::SymbolsModel(QObject *parent) : QAbstractItemModel(parent)
|
|
{
|
|
}
|
|
|
|
void SymbolsModel::configure(const Document::Ptr &document)
|
|
{
|
|
QTC_CHECK(document);
|
|
emit layoutAboutToBeChanged();
|
|
m_document = document;
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void SymbolsModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_document.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
static Symbol *indexToSymbol(const QModelIndex &index)
|
|
{
|
|
if (Symbol *symbol = static_cast<Symbol*>(index.internalPointer()))
|
|
return symbol;
|
|
return 0;
|
|
}
|
|
|
|
static Scope *indexToScope(const QModelIndex &index)
|
|
{
|
|
if (Symbol *symbol = indexToSymbol(index))
|
|
return symbol->asScope();
|
|
return 0;
|
|
}
|
|
|
|
QModelIndex SymbolsModel::index(int row, int column, const QModelIndex &parent) const
|
|
{
|
|
Scope *scope = 0;
|
|
if (parent.isValid())
|
|
scope = indexToScope(parent);
|
|
else if (m_document)
|
|
scope = m_document->globalNamespace();
|
|
|
|
if (scope) {
|
|
if ((unsigned)row < scope->memberCount())
|
|
return createIndex(row, column, scope->memberAt(row));
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
QModelIndex SymbolsModel::parent(const QModelIndex &child) const
|
|
{
|
|
if (!child.isValid())
|
|
return QModelIndex();
|
|
|
|
if (Symbol *symbol = indexToSymbol(child)) {
|
|
if (Scope *scope = symbol->enclosingScope()) {
|
|
const int row = DepthFinder()(m_document, scope);
|
|
return createIndex(row, 0, scope);
|
|
}
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
int SymbolsModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid()) {
|
|
if (Scope *scope = indexToScope(parent))
|
|
return scope->memberCount();
|
|
} else {
|
|
if (m_document)
|
|
return m_document->globalNamespace()->memberCount();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int SymbolsModel::columnCount(const QModelIndex &) const
|
|
{
|
|
return ColumnCount;
|
|
}
|
|
|
|
QVariant SymbolsModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
const int column = index.column();
|
|
if (role == Qt::DisplayRole) {
|
|
Symbol *symbol = indexToSymbol(index);
|
|
if (!symbol)
|
|
return QVariant();
|
|
if (column == LineNumberColumn) {
|
|
return symbol->line();
|
|
} else if (column == SymbolColumn) {
|
|
QString name = Overview().prettyName(symbol->name());
|
|
if (name.isEmpty())
|
|
name = QLatin1String(symbol->isBlock() ? "<block>" : "<no name>");
|
|
return name;
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant SymbolsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case SymbolColumn:
|
|
return QLatin1String("Symbol");
|
|
case LineNumberColumn:
|
|
return QLatin1String("Line");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- TokensModel --------------------------------------------------------------------------------
|
|
|
|
class TokensModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
TokensModel(QObject *parent);
|
|
void configure(TranslationUnit *translationUnit);
|
|
void clear();
|
|
|
|
enum Columns { SpelledColumn, KindColumn, IndexColumn, OffsetColumn, LineColumnNumberColumn,
|
|
BytesAndCodePointsColumn, GeneratedColumn, ExpandedColumn, WhiteSpaceColumn,
|
|
NewlineColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
struct TokenInfo {
|
|
Token token;
|
|
unsigned line;
|
|
unsigned column;
|
|
};
|
|
QList<TokenInfo> m_tokenInfos;
|
|
};
|
|
|
|
TokensModel::TokensModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void TokensModel::configure(TranslationUnit *translationUnit)
|
|
{
|
|
if (!translationUnit)
|
|
return;
|
|
|
|
emit layoutAboutToBeChanged();
|
|
m_tokenInfos.clear();
|
|
for (int i = 0, total = translationUnit->tokenCount(); i < total; ++i) {
|
|
TokenInfo info;
|
|
info.token = translationUnit->tokenAt(i);
|
|
translationUnit->getPosition(info.token.utf16charsBegin(), &info.line, &info.column);
|
|
m_tokenInfos.append(info);
|
|
}
|
|
emit layoutChanged();
|
|
}
|
|
|
|
void TokensModel::clear()
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_tokenInfos.clear();
|
|
emit layoutChanged();
|
|
}
|
|
|
|
int TokensModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_tokenInfos.size();
|
|
}
|
|
|
|
int TokensModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return TokensModel::ColumnCount;
|
|
}
|
|
|
|
QVariant TokensModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
const int column = index.column();
|
|
if (role == Qt::DisplayRole) {
|
|
const TokenInfo info = m_tokenInfos.at(index.row());
|
|
const Token token = info.token;
|
|
if (column == SpelledColumn)
|
|
return QString::fromUtf8(token.spell());
|
|
else if (column == KindColumn)
|
|
return CMI::Utils::toString(static_cast<Kind>(token.kind()));
|
|
else if (column == IndexColumn)
|
|
return index.row();
|
|
else if (column == OffsetColumn)
|
|
return token.bytesBegin();
|
|
else if (column == LineColumnNumberColumn)
|
|
return QString::fromLatin1("%1:%2").arg(CMI::Utils::toString(info.line),
|
|
CMI::Utils::toString(info.column));
|
|
else if (column == BytesAndCodePointsColumn)
|
|
return QString::fromLatin1("%1/%2").arg(CMI::Utils::toString(token.bytes()),
|
|
CMI::Utils::toString(token.utf16chars()));
|
|
else if (column == GeneratedColumn)
|
|
return CMI::Utils::toString(token.generated());
|
|
else if (column == ExpandedColumn)
|
|
return CMI::Utils::toString(token.expanded());
|
|
else if (column == WhiteSpaceColumn)
|
|
return CMI::Utils::toString(token.whitespace());
|
|
else if (column == NewlineColumn)
|
|
return CMI::Utils::toString(token.newline());
|
|
} else if (role == Qt::TextAlignmentRole) {
|
|
return Qt::AlignTop + Qt::AlignLeft;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant TokensModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case SpelledColumn:
|
|
return QLatin1String("Spelled");
|
|
case KindColumn:
|
|
return QLatin1String("Kind");
|
|
case IndexColumn:
|
|
return QLatin1String("Index");
|
|
case OffsetColumn:
|
|
return QLatin1String("Offset");
|
|
case LineColumnNumberColumn:
|
|
return QLatin1String("Line:Column");
|
|
case BytesAndCodePointsColumn:
|
|
return QLatin1String("Bytes/Codepoints");
|
|
case GeneratedColumn:
|
|
return QLatin1String("Generated");
|
|
case ExpandedColumn:
|
|
return QLatin1String("Expanded");
|
|
case WhiteSpaceColumn:
|
|
return QLatin1String("Whitespace");
|
|
case NewlineColumn:
|
|
return QLatin1String("Newline");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- ProjectPartsModel --------------------------------------------------------------------------
|
|
|
|
class ProjectPartsModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
ProjectPartsModel(QObject *parent);
|
|
|
|
void configure(const QList<ProjectInfo> &projectInfos,
|
|
const ProjectPart::Ptr ¤tEditorsProjectPart);
|
|
|
|
QModelIndex indexForCurrentEditorsProjectPart() const;
|
|
ProjectPart::Ptr projectPartForProjectId(const QString &projectPartId) const;
|
|
|
|
enum Columns { PartNameColumn, PartFilePathColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
QList<ProjectPart::Ptr> m_projectPartsList;
|
|
int m_currentEditorsProjectPartIndex;
|
|
};
|
|
|
|
ProjectPartsModel::ProjectPartsModel(QObject *parent)
|
|
: QAbstractListModel(parent), m_currentEditorsProjectPartIndex(-1)
|
|
{
|
|
}
|
|
|
|
void ProjectPartsModel::configure(const QList<ProjectInfo> &projectInfos,
|
|
const ProjectPart::Ptr ¤tEditorsProjectPart)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_projectPartsList.clear();
|
|
foreach (const ProjectInfo &info, projectInfos) {
|
|
foreach (const ProjectPart::Ptr &projectPart, info.projectParts()) {
|
|
if (!m_projectPartsList.contains(projectPart)) {
|
|
m_projectPartsList << projectPart;
|
|
if (projectPart == currentEditorsProjectPart)
|
|
m_currentEditorsProjectPartIndex = m_projectPartsList.size() - 1;
|
|
}
|
|
}
|
|
}
|
|
emit layoutChanged();
|
|
}
|
|
|
|
QModelIndex ProjectPartsModel::indexForCurrentEditorsProjectPart() const
|
|
{
|
|
if (m_currentEditorsProjectPartIndex == -1)
|
|
return QModelIndex();
|
|
return createIndex(m_currentEditorsProjectPartIndex, PartFilePathColumn);
|
|
}
|
|
|
|
ProjectPart::Ptr ProjectPartsModel::projectPartForProjectId(const QString &projectPartId) const
|
|
{
|
|
foreach (const ProjectPart::Ptr &part, m_projectPartsList) {
|
|
if (part->id() == projectPartId)
|
|
return part;
|
|
}
|
|
return ProjectPart::Ptr();
|
|
}
|
|
|
|
int ProjectPartsModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_projectPartsList.size();
|
|
}
|
|
|
|
int ProjectPartsModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return ProjectPartsModel::ColumnCount;
|
|
}
|
|
|
|
QVariant ProjectPartsModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
const int row = index.row();
|
|
if (role == Qt::DisplayRole) {
|
|
const int column = index.column();
|
|
if (column == PartNameColumn)
|
|
return m_projectPartsList.at(row)->displayName;
|
|
else if (column == PartFilePathColumn)
|
|
return QDir::toNativeSeparators(m_projectPartsList.at(row)->projectFile);
|
|
} else if (role == Qt::UserRole) {
|
|
return m_projectPartsList.at(row)->id();
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant ProjectPartsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case PartNameColumn:
|
|
return QLatin1String("Name");
|
|
case PartFilePathColumn:
|
|
return QLatin1String("Project File Path");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- WorkingCopyModel ---------------------------------------------------------------------------
|
|
|
|
class WorkingCopyModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
WorkingCopyModel(QObject *parent);
|
|
|
|
void configure(const WorkingCopy &workingCopy);
|
|
QModelIndex indexForFile(const QString &filePath);
|
|
|
|
enum Columns { RevisionColumn, FilePathColumn, ColumnCount };
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
|
|
|
private:
|
|
struct WorkingCopyEntry {
|
|
WorkingCopyEntry(const QString &filePath, const QByteArray &source, unsigned revision)
|
|
: filePath(filePath), source(source), revision(revision)
|
|
{}
|
|
|
|
QString filePath;
|
|
QByteArray source;
|
|
unsigned revision;
|
|
};
|
|
|
|
QList<WorkingCopyEntry> m_workingCopyList;
|
|
};
|
|
|
|
WorkingCopyModel::WorkingCopyModel(QObject *parent) : QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
void WorkingCopyModel::configure(const WorkingCopy &workingCopy)
|
|
{
|
|
emit layoutAboutToBeChanged();
|
|
m_workingCopyList.clear();
|
|
QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
m_workingCopyList << WorkingCopyEntry(it.key().toString(), it.value().first,
|
|
it.value().second);
|
|
}
|
|
emit layoutChanged();
|
|
}
|
|
|
|
QModelIndex WorkingCopyModel::indexForFile(const QString &filePath)
|
|
{
|
|
for (int i = 0, total = m_workingCopyList.size(); i < total; ++i) {
|
|
const WorkingCopyEntry entry = m_workingCopyList.at(i);
|
|
if (entry.filePath == filePath)
|
|
return index(i, FilePathColumn);
|
|
}
|
|
return QModelIndex();
|
|
}
|
|
|
|
int WorkingCopyModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return m_workingCopyList.size();
|
|
}
|
|
|
|
int WorkingCopyModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return WorkingCopyModel::ColumnCount;
|
|
}
|
|
|
|
QVariant WorkingCopyModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
const int row = index.row();
|
|
if (role == Qt::DisplayRole) {
|
|
const int column = index.column();
|
|
if (column == RevisionColumn)
|
|
return m_workingCopyList.at(row).revision;
|
|
else if (column == FilePathColumn)
|
|
return m_workingCopyList.at(row).filePath;
|
|
} else if (role == Qt::UserRole) {
|
|
return m_workingCopyList.at(row).source;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant WorkingCopyModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case RevisionColumn:
|
|
return QLatin1String("Revision");
|
|
case FilePathColumn:
|
|
return QLatin1String("File Path");
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
// --- SnapshotInfo -------------------------------------------------------------------------------
|
|
|
|
class SnapshotInfo
|
|
{
|
|
public:
|
|
enum Type { GlobalSnapshot, EditorSnapshot };
|
|
SnapshotInfo(const Snapshot &snapshot, Type type)
|
|
: snapshot(snapshot), type(type) {}
|
|
|
|
Snapshot snapshot;
|
|
Type type;
|
|
};
|
|
|
|
// --- CppCodeModelInspectorDialog ----------------------------------------------------------------
|
|
|
|
CppCodeModelInspectorDialog::CppCodeModelInspectorDialog(QWidget *parent)
|
|
: QDialog(parent)
|
|
, m_ui(new Ui::CppCodeModelInspectorDialog)
|
|
, m_snapshotInfos(new QList<SnapshotInfo>())
|
|
, m_snapshotView(new FilterableView(this))
|
|
, m_snapshotModel(new SnapshotModel(this))
|
|
, m_proxySnapshotModel(new QSortFilterProxyModel(this))
|
|
, m_docGenericInfoModel(new KeyValueModel(this))
|
|
, m_docIncludesModel(new IncludesModel(this))
|
|
, m_docDiagnosticMessagesModel(new DiagnosticMessagesModel(this))
|
|
, m_docMacrosModel(new MacrosModel(this))
|
|
, m_docSymbolsModel(new SymbolsModel(this))
|
|
, m_docTokensModel(new TokensModel(this))
|
|
, m_projectPartsView(new FilterableView(this))
|
|
, m_projectPartsModel(new ProjectPartsModel(this))
|
|
, m_proxyProjectPartsModel(new QSortFilterProxyModel(this))
|
|
, m_partGenericInfoModel(new KeyValueModel(this))
|
|
, m_projectFilesModel(new ProjectFilesModel(this))
|
|
, m_workingCopyView(new FilterableView(this))
|
|
, m_workingCopyModel(new WorkingCopyModel(this))
|
|
, m_proxyWorkingCopyModel(new QSortFilterProxyModel(this))
|
|
{
|
|
m_ui->setupUi(this);
|
|
m_ui->snapshotSelectorAndViewLayout->addWidget(m_snapshotView);
|
|
m_ui->projectPartsSplitter->insertWidget(0, m_projectPartsView);
|
|
m_ui->workingCopySplitter->insertWidget(0, m_workingCopyView);
|
|
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close);
|
|
|
|
m_proxySnapshotModel->setSourceModel(m_snapshotModel);
|
|
m_proxySnapshotModel->setFilterKeyColumn(SnapshotModel::FilePathColumn);
|
|
m_snapshotView->setModel(m_proxySnapshotModel);
|
|
m_ui->docGeneralView->setModel(m_docGenericInfoModel);
|
|
m_ui->docIncludesView->setModel(m_docIncludesModel);
|
|
m_ui->docDiagnosticMessagesView->setModel(m_docDiagnosticMessagesModel);
|
|
m_ui->docDefinedMacrosView->setModel(m_docMacrosModel);
|
|
m_ui->docSymbolsView->setModel(m_docSymbolsModel);
|
|
m_ui->docTokensView->setModel(m_docTokensModel);
|
|
|
|
m_proxyProjectPartsModel->setSourceModel(m_projectPartsModel);
|
|
m_proxyProjectPartsModel->setFilterKeyColumn(ProjectPartsModel::PartFilePathColumn);
|
|
m_projectPartsView->setModel(m_proxyProjectPartsModel);
|
|
m_ui->partGeneralView->setModel(m_partGenericInfoModel);
|
|
m_ui->projectFilesView->setModel(m_projectFilesModel);
|
|
|
|
m_proxyWorkingCopyModel->setSourceModel(m_workingCopyModel);
|
|
m_proxyWorkingCopyModel->setFilterKeyColumn(WorkingCopyModel::FilePathColumn);
|
|
m_workingCopyView->setModel(m_proxyWorkingCopyModel);
|
|
|
|
connect(m_snapshotView->selectionModel(),
|
|
&QItemSelectionModel::currentRowChanged,
|
|
this, &CppCodeModelInspectorDialog::onDocumentSelected);
|
|
connect(m_snapshotView, &FilterableView::filterChanged,
|
|
this, &CppCodeModelInspectorDialog::onSnapshotFilterChanged);
|
|
connect(m_ui->snapshotSelector,
|
|
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
|
this, &CppCodeModelInspectorDialog::onSnapshotSelected);
|
|
connect(m_ui->docSymbolsView, &QTreeView::expanded,
|
|
this, &CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed);
|
|
connect(m_ui->docSymbolsView, &QTreeView::collapsed,
|
|
this, &CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed);
|
|
|
|
connect(m_projectPartsView->selectionModel(),
|
|
&QItemSelectionModel::currentRowChanged,
|
|
this, &CppCodeModelInspectorDialog::onProjectPartSelected);
|
|
connect(m_projectPartsView, &FilterableView::filterChanged,
|
|
this, &CppCodeModelInspectorDialog::onProjectPartFilterChanged);
|
|
|
|
connect(m_workingCopyView->selectionModel(),
|
|
&QItemSelectionModel::currentRowChanged,
|
|
this, &CppCodeModelInspectorDialog::onWorkingCopyDocumentSelected);
|
|
connect(m_workingCopyView, &FilterableView::filterChanged,
|
|
this, &CppCodeModelInspectorDialog::onWorkingCopyFilterChanged);
|
|
|
|
connect(m_ui->refreshButton, &QAbstractButton::clicked, this, &CppCodeModelInspectorDialog::onRefreshRequested);
|
|
connect(m_ui->closeButton, &QAbstractButton::clicked, this, &QWidget::close);
|
|
|
|
refresh();
|
|
}
|
|
|
|
CppCodeModelInspectorDialog::~CppCodeModelInspectorDialog()
|
|
{
|
|
delete m_snapshotInfos;
|
|
delete m_ui;
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onRefreshRequested()
|
|
{
|
|
refresh();
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onSnapshotFilterChanged(const QString &pattern)
|
|
{
|
|
m_proxySnapshotModel->setFilterWildcard(pattern);
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onSnapshotSelected(int row)
|
|
{
|
|
if (row < 0 || row >= m_snapshotInfos->size())
|
|
return;
|
|
|
|
m_snapshotView->clearFilter();
|
|
const SnapshotInfo info = m_snapshotInfos->at(row);
|
|
m_snapshotModel->configure(info.snapshot);
|
|
m_snapshotView->resizeColumns(SnapshotModel::ColumnCount);
|
|
|
|
if (info.type == SnapshotInfo::GlobalSnapshot) {
|
|
// Select first document
|
|
const QModelIndex index = m_proxySnapshotModel->index(0, SnapshotModel::FilePathColumn);
|
|
m_snapshotView->selectIndex(index);
|
|
} else if (info.type == SnapshotInfo::EditorSnapshot) {
|
|
// Select first document, unless we can find the editor document
|
|
QModelIndex index = m_snapshotModel->indexForDocument(fileInCurrentEditor());
|
|
index = m_proxySnapshotModel->mapFromSource(index);
|
|
if (!index.isValid())
|
|
index = m_proxySnapshotModel->index(0, SnapshotModel::FilePathColumn);
|
|
m_snapshotView->selectIndex(index);
|
|
}
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onDocumentSelected(const QModelIndex ¤t,
|
|
const QModelIndex &)
|
|
{
|
|
if (current.isValid()) {
|
|
const QModelIndex index = m_proxySnapshotModel->index(current.row(),
|
|
SnapshotModel::FilePathColumn);
|
|
const QString filePath = QDir::fromNativeSeparators(
|
|
m_proxySnapshotModel->data(index, Qt::DisplayRole).toString());
|
|
const SnapshotInfo info = m_snapshotInfos->at(m_ui->snapshotSelector->currentIndex());
|
|
updateDocumentData(info.snapshot.document(filePath));
|
|
} else {
|
|
clearDocumentData();
|
|
}
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed(const QModelIndex &)
|
|
{
|
|
resizeColumns<SymbolsModel>(m_ui->docSymbolsView);
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onProjectPartFilterChanged(const QString &pattern)
|
|
{
|
|
m_proxyProjectPartsModel->setFilterWildcard(pattern);
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onProjectPartSelected(const QModelIndex ¤t,
|
|
const QModelIndex &)
|
|
{
|
|
if (current.isValid()) {
|
|
QModelIndex index = m_proxyProjectPartsModel->mapToSource(current);
|
|
if (index.isValid()) {
|
|
index = m_projectPartsModel->index(index.row(), ProjectPartsModel::PartFilePathColumn);
|
|
const QString projectPartId = m_projectPartsModel->data(index, Qt::UserRole).toString();
|
|
updateProjectPartData(m_projectPartsModel->projectPartForProjectId(projectPartId));
|
|
}
|
|
} else {
|
|
clearProjectPartData();
|
|
}
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onWorkingCopyFilterChanged(const QString &pattern)
|
|
{
|
|
m_proxyWorkingCopyModel->setFilterWildcard(pattern);
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::onWorkingCopyDocumentSelected(const QModelIndex ¤t,
|
|
const QModelIndex &)
|
|
{
|
|
if (current.isValid()) {
|
|
const QModelIndex index = m_proxyWorkingCopyModel->mapToSource(current);
|
|
if (index.isValid()) {
|
|
const QString source
|
|
= QString::fromUtf8(m_workingCopyModel->data(index, Qt::UserRole).toByteArray());
|
|
m_ui->workingCopySourceEdit->setPlainText(source);
|
|
}
|
|
} else {
|
|
m_ui->workingCopySourceEdit->clear();
|
|
}
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::refresh()
|
|
{
|
|
CppModelManager *cmmi = CppModelManager::instance();
|
|
|
|
const int oldSnapshotIndex = m_ui->snapshotSelector->currentIndex();
|
|
const bool selectEditorRelevant
|
|
= m_ui->selectEditorRelevantEntriesAfterRefreshCheckBox->isChecked();
|
|
|
|
// Snapshots and Documents
|
|
m_snapshotInfos->clear();
|
|
m_ui->snapshotSelector->clear();
|
|
|
|
const Snapshot globalSnapshot = cmmi->snapshot();
|
|
CppCodeModelInspector::Dumper dumper(globalSnapshot);
|
|
m_snapshotModel->setGlobalSnapshot(globalSnapshot);
|
|
|
|
m_snapshotInfos->append(SnapshotInfo(globalSnapshot, SnapshotInfo::GlobalSnapshot));
|
|
const QString globalSnapshotTitle
|
|
= QString::fromLatin1("Global/Indexing Snapshot (%1 Documents)").arg(globalSnapshot.size());
|
|
m_ui->snapshotSelector->addItem(globalSnapshotTitle);
|
|
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
|
|
|
|
TextEditor::BaseTextEditor *editor = currentEditor();
|
|
CppTools::CppEditorDocumentHandle *cppEditorDocument = 0;
|
|
if (editor) {
|
|
const QString editorFilePath = editor->document()->filePath().toString();
|
|
cppEditorDocument = cmmi->cppEditorDocument(editorFilePath);
|
|
if (auto *documentProcessor = CppToolsBridge::baseEditorDocumentProcessor(editorFilePath)) {
|
|
const Snapshot editorSnapshot = documentProcessor->snapshot();
|
|
m_snapshotInfos->append(SnapshotInfo(editorSnapshot, SnapshotInfo::EditorSnapshot));
|
|
const QString editorSnapshotTitle
|
|
= QString::fromLatin1("Current Editor's Snapshot (%1 Documents)")
|
|
.arg(editorSnapshot.size());
|
|
dumper.dumpSnapshot(editorSnapshot, editorSnapshotTitle);
|
|
m_ui->snapshotSelector->addItem(editorSnapshotTitle);
|
|
}
|
|
CppEditorWidget *cppEditorWidget = qobject_cast<CppEditorWidget *>(editor->editorWidget());
|
|
if (cppEditorWidget) {
|
|
SemanticInfo semanticInfo = cppEditorWidget->semanticInfo();
|
|
Snapshot snapshot;
|
|
|
|
// Add semantic info snapshot
|
|
snapshot = semanticInfo.snapshot;
|
|
m_snapshotInfos->append(SnapshotInfo(snapshot, SnapshotInfo::EditorSnapshot));
|
|
m_ui->snapshotSelector->addItem(
|
|
QString::fromLatin1("Current Editor's Semantic Info Snapshot (%1 Documents)")
|
|
.arg(snapshot.size()));
|
|
|
|
// Add a pseudo snapshot containing only the semantic info document since this document
|
|
// is not part of the semantic snapshot.
|
|
snapshot = Snapshot();
|
|
snapshot.insert(cppEditorWidget->semanticInfo().doc);
|
|
m_snapshotInfos->append(SnapshotInfo(snapshot, SnapshotInfo::EditorSnapshot));
|
|
const QString snapshotTitle
|
|
= QString::fromLatin1("Current Editor's Pseudo Snapshot with Semantic Info Document (%1 Documents)")
|
|
.arg(snapshot.size());
|
|
dumper.dumpSnapshot(snapshot, snapshotTitle);
|
|
m_ui->snapshotSelector->addItem(snapshotTitle);
|
|
}
|
|
}
|
|
|
|
int snapshotIndex = 0;
|
|
if (selectEditorRelevant) {
|
|
for (int i = 0, total = m_snapshotInfos->size(); i < total; ++i) {
|
|
const SnapshotInfo info = m_snapshotInfos->at(i);
|
|
if (info.type == SnapshotInfo::EditorSnapshot) {
|
|
snapshotIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
} else if (oldSnapshotIndex < m_snapshotInfos->size()) {
|
|
snapshotIndex = oldSnapshotIndex;
|
|
}
|
|
m_ui->snapshotSelector->setCurrentIndex(snapshotIndex);
|
|
onSnapshotSelected(snapshotIndex);
|
|
|
|
// Project Parts
|
|
const ProjectPart::Ptr editorsProjectPart = cppEditorDocument
|
|
? cppEditorDocument->processor()->parser()->projectPart()
|
|
: ProjectPart::Ptr();
|
|
|
|
const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
|
|
dumper.dumpProjectInfos(projectInfos);
|
|
m_projectPartsModel->configure(projectInfos, editorsProjectPart);
|
|
m_projectPartsView->resizeColumns(ProjectPartsModel::ColumnCount);
|
|
QModelIndex index = m_proxyProjectPartsModel->index(0, ProjectPartsModel::PartFilePathColumn);
|
|
if (index.isValid()) {
|
|
if (selectEditorRelevant && editorsProjectPart) {
|
|
QModelIndex editorPartIndex = m_projectPartsModel->indexForCurrentEditorsProjectPart();
|
|
editorPartIndex = m_proxyProjectPartsModel->mapFromSource(editorPartIndex);
|
|
if (editorPartIndex.isValid())
|
|
index = editorPartIndex;
|
|
}
|
|
m_projectPartsView->selectIndex(index);
|
|
}
|
|
|
|
// Working Copy
|
|
const WorkingCopy workingCopy = cmmi->workingCopy();
|
|
dumper.dumpWorkingCopy(workingCopy);
|
|
m_workingCopyModel->configure(workingCopy);
|
|
m_workingCopyView->resizeColumns(WorkingCopyModel::ColumnCount);
|
|
if (workingCopy.size() > 0) {
|
|
QModelIndex index = m_proxyWorkingCopyModel->index(0, WorkingCopyModel::FilePathColumn);
|
|
if (selectEditorRelevant) {
|
|
const QModelIndex eindex = m_workingCopyModel->indexForFile(fileInCurrentEditor());
|
|
if (eindex.isValid())
|
|
index = m_proxyWorkingCopyModel->mapFromSource(eindex);
|
|
}
|
|
m_workingCopyView->selectIndex(index);
|
|
}
|
|
|
|
// Merged entities
|
|
dumper.dumpMergedEntities(cmmi->headerPaths(), cmmi->definedMacros());
|
|
}
|
|
|
|
enum DocumentTabs {
|
|
DocumentGeneralTab,
|
|
DocumentIncludesTab,
|
|
DocumentDiagnosticsTab,
|
|
DocumentDefinedMacrosTab,
|
|
DocumentPreprocessedSourceTab,
|
|
DocumentSymbolsTab,
|
|
DocumentTokensTab
|
|
};
|
|
|
|
static QString docTabName(int tabIndex, int numberOfEntries = -1)
|
|
{
|
|
const char *names[] = {
|
|
"&General",
|
|
"&Includes",
|
|
"&Diagnostic Messages",
|
|
"(Un)Defined &Macros",
|
|
"P&reprocessed Source",
|
|
"&Symbols",
|
|
"&Tokens"
|
|
};
|
|
QString result = QLatin1String(names[tabIndex]);
|
|
if (numberOfEntries != -1)
|
|
result += QString::fromLatin1(" (%1)").arg(numberOfEntries);
|
|
return result;
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::clearDocumentData()
|
|
{
|
|
m_docGenericInfoModel->clear();
|
|
|
|
m_ui->docTab->setTabText(DocumentIncludesTab, docTabName(DocumentIncludesTab));
|
|
m_docIncludesModel->clear();
|
|
|
|
m_ui->docTab->setTabText(DocumentDiagnosticsTab, docTabName(DocumentDiagnosticsTab));
|
|
m_docDiagnosticMessagesModel->clear();
|
|
|
|
m_ui->docTab->setTabText(DocumentDefinedMacrosTab, docTabName(DocumentDefinedMacrosTab));
|
|
m_docMacrosModel->clear();
|
|
|
|
m_ui->docPreprocessedSourceEdit->clear();
|
|
|
|
m_docSymbolsModel->clear();
|
|
|
|
m_ui->docTab->setTabText(DocumentTokensTab, docTabName(DocumentTokensTab));
|
|
m_docTokensModel->clear();
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::updateDocumentData(const Document::Ptr &document)
|
|
{
|
|
QTC_ASSERT(document, return);
|
|
|
|
// General
|
|
KeyValueModel::Table table = KeyValueModel::Table()
|
|
<< qMakePair(QString::fromLatin1("File Path"),
|
|
QDir::toNativeSeparators(document->fileName()))
|
|
<< qMakePair(QString::fromLatin1("Last Modified"),
|
|
CMI::Utils::toString(document->lastModified()))
|
|
<< qMakePair(QString::fromLatin1("Revision"),
|
|
CMI::Utils::toString(document->revision()))
|
|
<< qMakePair(QString::fromLatin1("Editor Revision"),
|
|
CMI::Utils::toString(document->editorRevision()))
|
|
<< qMakePair(QString::fromLatin1("Check Mode"),
|
|
CMI::Utils::toString(document->checkMode()))
|
|
<< qMakePair(QString::fromLatin1("Tokenized"),
|
|
CMI::Utils::toString(document->isTokenized()))
|
|
<< qMakePair(QString::fromLatin1("Parsed"),
|
|
CMI::Utils::toString(document->isParsed()))
|
|
<< qMakePair(QString::fromLatin1("Project Parts"),
|
|
CMI::Utils::partsForFile(document->fileName()))
|
|
;
|
|
m_docGenericInfoModel->configure(table);
|
|
resizeColumns<KeyValueModel>(m_ui->docGeneralView);
|
|
|
|
// Includes
|
|
m_docIncludesModel->configure(document->resolvedIncludes() + document->unresolvedIncludes());
|
|
resizeColumns<IncludesModel>(m_ui->docIncludesView);
|
|
m_ui->docTab->setTabText(DocumentIncludesTab,
|
|
docTabName(DocumentIncludesTab, m_docIncludesModel->rowCount()));
|
|
|
|
// Diagnostic Messages
|
|
m_docDiagnosticMessagesModel->configure(document->diagnosticMessages());
|
|
resizeColumns<DiagnosticMessagesModel>(m_ui->docDiagnosticMessagesView);
|
|
m_ui->docTab->setTabText(DocumentDiagnosticsTab,
|
|
docTabName(DocumentDiagnosticsTab, m_docDiagnosticMessagesModel->rowCount()));
|
|
|
|
// Macros
|
|
m_docMacrosModel->configure(document->definedMacros());
|
|
resizeColumns<MacrosModel>(m_ui->docDefinedMacrosView);
|
|
m_ui->docTab->setTabText(DocumentDefinedMacrosTab,
|
|
docTabName(DocumentDefinedMacrosTab, m_docMacrosModel->rowCount()));
|
|
|
|
// Source
|
|
m_ui->docPreprocessedSourceEdit->setPlainText(QString::fromUtf8(document->utf8Source()));
|
|
|
|
// Symbols
|
|
m_docSymbolsModel->configure(document);
|
|
resizeColumns<SymbolsModel>(m_ui->docSymbolsView);
|
|
|
|
// Tokens
|
|
m_docTokensModel->configure(document->translationUnit());
|
|
resizeColumns<TokensModel>(m_ui->docTokensView);
|
|
m_ui->docTab->setTabText(DocumentTokensTab,
|
|
docTabName(DocumentTokensTab, m_docTokensModel->rowCount()));
|
|
}
|
|
|
|
enum ProjectPartTabs {
|
|
ProjectPartGeneralTab,
|
|
ProjectPartFilesTab,
|
|
ProjectPartDefinesTab,
|
|
ProjectPartHeaderPathsTab,
|
|
ProjectPartPrecompiledHeadersTab
|
|
};
|
|
|
|
static QString partTabName(int tabIndex, int numberOfEntries = -1)
|
|
{
|
|
const char *names[] = {
|
|
"&General",
|
|
"Project &Files",
|
|
"&Defines",
|
|
"&Header Paths",
|
|
"Pre&compiled Headers"
|
|
};
|
|
QString result = QLatin1String(names[tabIndex]);
|
|
if (numberOfEntries != -1)
|
|
result += QString::fromLatin1(" (%1)").arg(numberOfEntries);
|
|
return result;
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::clearProjectPartData()
|
|
{
|
|
m_partGenericInfoModel->clear();
|
|
m_projectFilesModel->clear();
|
|
|
|
m_ui->projectPartTab->setTabText(ProjectPartFilesTab, partTabName(ProjectPartFilesTab));
|
|
|
|
m_ui->partToolchainDefinesEdit->clear();
|
|
m_ui->partProjectDefinesEdit->clear();
|
|
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab, partTabName(ProjectPartDefinesTab));
|
|
|
|
m_ui->partHeaderPathsEdit->clear();
|
|
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
|
|
partTabName(ProjectPartHeaderPathsTab));
|
|
|
|
m_ui->partPrecompiledHeadersEdit->clear();
|
|
m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
|
|
partTabName(ProjectPartPrecompiledHeadersTab));
|
|
}
|
|
|
|
void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &part)
|
|
{
|
|
QTC_ASSERT(part, return);
|
|
|
|
// General
|
|
QString projectName = QLatin1String("<None>");
|
|
QString projectFilePath = QLatin1String("<None>");
|
|
if (ProjectExplorer::Project *project = part->project) {
|
|
projectName = project->displayName();
|
|
projectFilePath = project->projectFilePath().toUserOutput();
|
|
}
|
|
KeyValueModel::Table table = KeyValueModel::Table()
|
|
<< qMakePair(QString::fromLatin1("Project Part Name"), part->displayName)
|
|
<< qMakePair(QString::fromLatin1("Project Part File"),
|
|
QDir::toNativeSeparators(part->projectFile))
|
|
<< qMakePair(QString::fromLatin1("Project Name"), projectName)
|
|
<< qMakePair(QString::fromLatin1("Project File"), projectFilePath)
|
|
<< qMakePair(QString::fromLatin1("Language Version"),
|
|
CMI::Utils::toString(part->languageVersion))
|
|
<< qMakePair(QString::fromLatin1("Language Extensions"),
|
|
CMI::Utils::toString(part->languageExtensions))
|
|
<< qMakePair(QString::fromLatin1("Qt Version"),
|
|
CMI::Utils::toString(part->qtVersion))
|
|
;
|
|
if (!part->projectConfigFile.isEmpty())
|
|
table.prepend(qMakePair(QString::fromLatin1("Project Config File"),
|
|
part->projectConfigFile));
|
|
m_partGenericInfoModel->configure(table);
|
|
resizeColumns<KeyValueModel>(m_ui->partGeneralView);
|
|
|
|
// Project Files
|
|
m_projectFilesModel->configure(part->files);
|
|
m_ui->projectPartTab->setTabText(ProjectPartFilesTab,
|
|
partTabName(ProjectPartFilesTab, part->files.size()));
|
|
|
|
// Defines
|
|
const QList<QByteArray> defineLines = part->toolchainDefines.split('\n')
|
|
+ part->projectDefines.split('\n');
|
|
int numberOfDefines = 0;
|
|
foreach (const QByteArray &line, defineLines) {
|
|
if (line.startsWith("#define "))
|
|
++numberOfDefines;
|
|
}
|
|
m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(part->toolchainDefines));
|
|
m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(part->projectDefines));
|
|
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
|
|
partTabName(ProjectPartDefinesTab, numberOfDefines));
|
|
|
|
// Header Paths
|
|
m_ui->partHeaderPathsEdit->setPlainText(CMI::Utils::pathListToString(part->headerPaths));
|
|
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
|
|
partTabName(ProjectPartHeaderPathsTab, part->headerPaths.size()));
|
|
|
|
// Precompiled Headers
|
|
m_ui->partPrecompiledHeadersEdit->setPlainText(
|
|
CMI::Utils::pathListToString(part->precompiledHeaders));
|
|
m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
|
|
partTabName(ProjectPartPrecompiledHeadersTab, part->precompiledHeaders.size()));
|
|
}
|
|
|
|
bool CppCodeModelInspectorDialog::event(QEvent *e)
|
|
{
|
|
if (e->type() == QEvent::ShortcutOverride) {
|
|
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
|
|
if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
|
|
ke->accept();
|
|
close();
|
|
return false;
|
|
}
|
|
}
|
|
return QDialog::event(e);
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namespace CppEditor
|
|
|
|
#include "cppcodemodelinspectordialog.moc"
|