diff options
author | Christian Stenger <christian.stenger@qt.io> | 2018-02-27 12:25:05 +0100 |
---|---|---|
committer | Christian Stenger <christian.stenger@qt.io> | 2018-03-02 09:05:21 +0000 |
commit | 33f2c240490b02ecae00a296022cdb8061a69a3d (patch) | |
tree | 98ad1a4762940d163b0ee93dfed11421d04fef65 /src/plugins/cpptools/cppoverviewmodel.cpp | |
parent | 4523e579436c484d8ce5bd643729477f4214d9f7 (diff) | |
download | qt-creator-33f2c240490b02ecae00a296022cdb8061a69a3d.tar.gz |
CppTools: Fix builtin overview model
5e872c0fcd2 changed the base class to TreeModel which
needs to have TreeItem inserted to fully work as intended.
This patch makes the overview model work without running
into countless soft asserts when using the builtin code model.
Change-Id: I875529bef03ea2cd9a226b05410fd05e247eded1
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Nikita Baryshnikov <nib952051@gmail.com>
Diffstat (limited to 'src/plugins/cpptools/cppoverviewmodel.cpp')
-rw-r--r-- | src/plugins/cpptools/cppoverviewmodel.cpp | 223 |
1 files changed, 90 insertions, 133 deletions
diff --git a/src/plugins/cpptools/cppoverviewmodel.cpp b/src/plugins/cpptools/cppoverviewmodel.cpp index 1cf10b4b9f..eaa4b2a8aa 100644 --- a/src/plugins/cpptools/cppoverviewmodel.cpp +++ b/src/plugins/cpptools/cppoverviewmodel.cpp @@ -37,121 +37,26 @@ using namespace CPlusPlus; namespace CppTools { -bool OverviewModel::hasDocument() const -{ - return _cppDocument; -} - -unsigned OverviewModel::globalSymbolCount() const -{ - unsigned count = 0; - if (_cppDocument) - count += _cppDocument->globalSymbolCount(); - return count; -} - -Symbol *OverviewModel::globalSymbolAt(unsigned index) const -{ return _cppDocument->globalSymbolAt(index); } - -QModelIndex OverviewModel::index(int row, int column, const QModelIndex &parent) const +QVariant SymbolItem::data(int /*column*/, int role) const { - if (!parent.isValid()) { - if (row == 0) // account for no symbol item - return createIndex(row, column); - Symbol *symbol = globalSymbolAt(static_cast<unsigned>(row-1)); // account for no symbol item - return createIndex(row, column, symbol); - } else { - Symbol *parentSymbol = static_cast<Symbol *>( - parent.internalPointer()); - Q_ASSERT(parentSymbol); - - if (Template *t = parentSymbol->asTemplate()) - if (Symbol *templateParentSymbol = t->declaration()) - parentSymbol = templateParentSymbol; - - Scope *scope = parentSymbol->asScope(); - Q_ASSERT(scope != nullptr); - return createIndex(row, 0, scope->memberAt(static_cast<unsigned>(row))); - } -} - -QModelIndex OverviewModel::parent(const QModelIndex &child) const -{ - Symbol *symbol = static_cast<Symbol *>(child.internalPointer()); - if (!symbol) // account for no symbol item - return QModelIndex(); - - if (Scope *scope = symbol->enclosingScope()) { - if (scope->isTemplate() && scope->enclosingScope()) - scope = scope->enclosingScope(); - if (scope->enclosingScope()) { - QModelIndex index; - if (scope->enclosingScope() && scope->enclosingScope()->enclosingScope()) // the parent doesn't have a parent - index = createIndex(static_cast<int>(scope->index()), 0, scope); - else //+1 to account for no symbol item - index = createIndex(static_cast<int>(scope->index() + 1), 0, scope); - return index; - } - } - - return QModelIndex(); -} - -int OverviewModel::rowCount(const QModelIndex &parent) const -{ - if (hasDocument()) { - if (!parent.isValid()) { - return static_cast<int>(globalSymbolCount() + 1); // account for no symbol item - } else { - if (!parent.parent().isValid() && parent.row() == 0) // account for no symbol item - return 0; - Symbol *parentSymbol = static_cast<Symbol *>( - parent.internalPointer()); - Q_ASSERT(parentSymbol); - - if (Template *t = parentSymbol->asTemplate()) - if (Symbol *templateParentSymbol = t->declaration()) - parentSymbol = templateParentSymbol; - - if (Scope *parentScope = parentSymbol->asScope()) { - if (!parentScope->isFunction() && !parentScope->isObjCMethod()) - return static_cast<int>(parentScope->memberCount()); - } - return 0; - } - } - if (!parent.isValid()) - return 1; // account for no symbol item - return 0; -} - -int OverviewModel::columnCount(const QModelIndex &) const -{ - return 1; -} - -QVariant OverviewModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - // account for no symbol item - if (!index.parent().isValid() && index.row() == 0) { + if (!symbol && parent()) { // account for no symbol item switch (role) { case Qt::DisplayRole: - if (rowCount() > 1) - return tr("<Select Symbol>"); - else - return tr("<No Symbols>"); + if (parent()->childCount() > 1) + return QString(QT_TRANSLATE_NOOP("CppTools::OverviewModel", "<Select Symbol>")); + return QString(QT_TRANSLATE_NOOP("CppTools::OverviewModel", "<No Symbols>")); default: return QVariant(); - } //switch + } } + OverviewModel *overviewModel = qobject_cast<OverviewModel *>(model()); + if (!overviewModel) + return QVariant(); + switch (role) { case Qt::DisplayRole: { - Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); - QString name = _overview.prettyName(symbol->name()); + QString name = overviewModel->_overview.prettyName(symbol->name()); if (name.isEmpty()) name = QLatin1String("anonymous"); if (symbol->isObjCForwardClassDeclaration()) @@ -166,32 +71,36 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const name = QLatin1String("@implementation ") + name; if (clazz->isCategory()) { - name += QLatin1String(" (") + _overview.prettyName(clazz->categoryName()) - + QLatin1Char(')'); + name += QString(" (%1)").arg(overviewModel->_overview.prettyName( + clazz->categoryName())); } } if (symbol->isObjCPropertyDeclaration()) name = QLatin1String("@property ") + name; - if (Template *t = symbol->asTemplate()) + // if symbol is a template we might change it now - so, use a copy instead as we're const + Symbol *symbl = symbol; + if (Template *t = symbl->asTemplate()) if (Symbol *templateDeclaration = t->declaration()) { QStringList parameters; parameters.reserve(static_cast<int>(t->templateParameterCount())); - for (unsigned i = 0; i < t->templateParameterCount(); ++i) - parameters.append(_overview.prettyName(t->templateParameterAt(i)->name())); - name += QLatin1Char('<') + parameters.join(QLatin1String(", ")) + QLatin1Char('>'); - symbol = templateDeclaration; + for (unsigned i = 0; i < t->templateParameterCount(); ++i) { + parameters.append(overviewModel->_overview.prettyName( + t->templateParameterAt(i)->name())); + } + name += QString("<%1>").arg(parameters.join(QLatin1String(", "))); + symbl = templateDeclaration; } - if (symbol->isObjCMethod()) { - ObjCMethod *method = symbol->asObjCMethod(); + if (symbl->isObjCMethod()) { + ObjCMethod *method = symbl->asObjCMethod(); if (method->isStatic()) name = QLatin1Char('+') + name; else name = QLatin1Char('-') + name; - } else if (! symbol->isScope() || symbol->isFunction()) { - QString type = _overview.prettyType(symbol->type()); - if (Function *f = symbol->type()->asFunctionType()) { + } else if (! symbl->isScope() || symbl->isFunction()) { + QString type = overviewModel->_overview.prettyType(symbl->type()); + if (Function *f = symbl->type()->asFunctionType()) { name += type; - type = _overview.prettyType(f->returnType()); + type = overviewModel->_overview.prettyType(f->returnType()); } if (! type.isEmpty()) name += QLatin1String(": ") + type; @@ -200,42 +109,58 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const } case Qt::EditRole: { - Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); - QString name = _overview.prettyName(symbol->name()); + QString name = overviewModel->_overview.prettyName(symbol->name()); if (name.isEmpty()) name = QLatin1String("anonymous"); return name; } - case Qt::DecorationRole: { - Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); + case Qt::DecorationRole: return Icons::iconForSymbol(symbol); - } - case FileNameRole: { - Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); - return QString::fromUtf8(symbol->fileName(), static_cast<int>(symbol->fileNameLength())); - } + case AbstractOverviewModel::FileNameRole: + return QString::fromUtf8(symbol->fileName(), static_cast<int>(symbol->fileNameLength())); - case LineNumberRole: { - Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); - return symbol->line(); - } + case AbstractOverviewModel::LineNumberRole: + return symbol->line(); default: return QVariant(); } // switch } + +bool OverviewModel::hasDocument() const +{ + return _cppDocument; +} + +unsigned OverviewModel::globalSymbolCount() const +{ + unsigned count = 0; + if (_cppDocument) + count += _cppDocument->globalSymbolCount(); + return count; +} + +Symbol *OverviewModel::globalSymbolAt(unsigned index) const +{ return _cppDocument->globalSymbolAt(index); } + Symbol *OverviewModel::symbolFromIndex(const QModelIndex &index) const { - return static_cast<Symbol *>(index.internalPointer()); + if (!index.isValid()) + return nullptr; + SymbolItem *item = static_cast<SymbolItem *>(itemForIndex(index)); + return item ? item->symbol : nullptr; } void OverviewModel::rebuild(Document::Ptr doc) { beginResetModel(); _cppDocument = doc; + auto root = new SymbolItem; + buildTree(root, true); + setRootItem(root); endResetModel(); } @@ -265,4 +190,36 @@ Utils::LineColumn OverviewModel::lineColumnFromIndex(const QModelIndex &sourceIn return lineColumn; } +void OverviewModel::buildTree(SymbolItem *root, bool isRoot) +{ + if (!root) + return; + + if (isRoot) { + unsigned rows = globalSymbolCount(); + for (unsigned row = 0; row < rows; ++row) { + Symbol *symbol = globalSymbolAt(row); + auto currentItem = new SymbolItem(symbol); + buildTree(currentItem, false); + root->appendChild(currentItem); + } + root->prependChild(new SymbolItem); // account for no symbol item + } else { + Symbol *symbol = root->symbol; + if (Scope *scope = symbol->asScope()) { + Scope::iterator it = scope->memberBegin(); + Scope::iterator end = scope->memberEnd(); + for ( ; it != end; ++it) { + if (!((*it)->name())) + continue; + if ((*it)->asArgument()) + continue; + auto currentItem = new SymbolItem(*it); + buildTree(currentItem, false); + root->appendChild(currentItem); + } + } + } +} + } // namespace CppTools |