forked from qt-creator/qt-creator
ClassView: improvements of performance for flat tree view
Improved lazy loading mechanism. The main problem here was that fetchMore function creates children items not only for selected item but also for children items. When one changed something in code then whole treeview was rebuilt (and fetchMore function was called). Replaced using "contains" and operator[] with 'value'. Task-number: QTCREATORBUG-8813 Task-number: QTCREATORBUG-8801(partially) Change-Id: If1ab69a0a67ff828275176ad99c3c63d2a1fa4a2 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
@@ -200,9 +200,9 @@ Manager *Manager::instance()
|
|||||||
Checks \a item for lazy data population of a QStandardItemModel.
|
Checks \a item for lazy data population of a QStandardItemModel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Manager::canFetchMore(QStandardItem *item) const
|
bool Manager::canFetchMore(QStandardItem *item, bool skipRoot) const
|
||||||
{
|
{
|
||||||
return d->parser.canFetchMore(item);
|
return d->parser.canFetchMore(item, skipRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -215,6 +215,11 @@ void Manager::fetchMore(QStandardItem *item, bool skipRoot)
|
|||||||
d->parser.fetchMore(item, skipRoot);
|
d->parser.fetchMore(item, skipRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Manager::hasChildren(QStandardItem *item) const
|
||||||
|
{
|
||||||
|
return d->parser.hasChildren(item);
|
||||||
|
}
|
||||||
|
|
||||||
void Manager::initialize()
|
void Manager::initialize()
|
||||||
{
|
{
|
||||||
// use Qt::QueuedConnection everywhere
|
// use Qt::QueuedConnection everywhere
|
||||||
|
|||||||
@@ -54,10 +54,12 @@ public:
|
|||||||
//! Get an instance of Manager
|
//! Get an instance of Manager
|
||||||
static Manager *instance();
|
static Manager *instance();
|
||||||
|
|
||||||
bool canFetchMore(QStandardItem *item) const;
|
bool canFetchMore(QStandardItem *item, bool skipRoot = false) const;
|
||||||
|
|
||||||
void fetchMore(QStandardItem *item, bool skipRoot = false);
|
void fetchMore(QStandardItem *item, bool skipRoot = false);
|
||||||
|
|
||||||
|
bool hasChildren(QStandardItem *item) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateChanged(bool state);
|
void stateChanged(bool state);
|
||||||
|
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ void NavigationWidget::fetchExpandedItems(QStandardItem *item, const QStandardIt
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const QModelIndex &parent = d->treeModel->indexFromItem(target);
|
const QModelIndex &parent = d->treeModel->indexFromItem(target);
|
||||||
if (d->ui->treeView->isExpanded(parent))
|
if (d->ui->treeView->isExpanded(parent) && Manager::instance()->canFetchMore(item, true))
|
||||||
Manager::instance()->fetchMore(item, true);
|
Manager::instance()->fetchMore(item, true);
|
||||||
|
|
||||||
int itemIndex = 0;
|
int itemIndex = 0;
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ namespace Internal {
|
|||||||
class ParserPrivate
|
class ParserPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef QHash<QString, CPlusPlus::Document::Ptr>::const_iterator CitDocumentList;
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
ParserPrivate() : flatMode(false) {}
|
ParserPrivate() : flatMode(false) {}
|
||||||
|
|
||||||
@@ -147,9 +149,10 @@ public:
|
|||||||
|
|
||||||
CPlusPlus::Document::Ptr ParserPrivate::document(const QString &fileName) const
|
CPlusPlus::Document::Ptr ParserPrivate::document(const QString &fileName) const
|
||||||
{
|
{
|
||||||
if (!documentList.contains(fileName))
|
CitDocumentList cit = documentList.find(fileName);
|
||||||
|
if (cit == documentList.end())
|
||||||
return CPlusPlus::Document::Ptr();
|
return CPlusPlus::Document::Ptr();
|
||||||
return documentList[fileName];
|
return cit.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------- Parser ---------------------------------
|
// ----------------------------- Parser ---------------------------------
|
||||||
@@ -186,9 +189,9 @@ Parser::~Parser()
|
|||||||
Checks \a item for lazy data population of a QStandardItemModel.
|
Checks \a item for lazy data population of a QStandardItemModel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Parser::canFetchMore(QStandardItem *item) const
|
bool Parser::canFetchMore(QStandardItem *item, bool skipRoot) const
|
||||||
{
|
{
|
||||||
ParserTreeItem::ConstPtr ptr = findItemByRoot(item);
|
ParserTreeItem::ConstPtr ptr = findItemByRoot(item, skipRoot);
|
||||||
if (ptr.isNull())
|
if (ptr.isNull())
|
||||||
return false;
|
return false;
|
||||||
return ptr->canFetchMore(item);
|
return ptr->canFetchMore(item);
|
||||||
@@ -207,6 +210,14 @@ void Parser::fetchMore(QStandardItem *item, bool skipRoot) const
|
|||||||
ptr->fetchMore(item);
|
ptr->fetchMore(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::hasChildren(QStandardItem *item) const
|
||||||
|
{
|
||||||
|
ParserTreeItem::ConstPtr ptr = findItemByRoot(item);
|
||||||
|
if (ptr.isNull())
|
||||||
|
return false;
|
||||||
|
return ptr->childCount() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Switches to flat mode (without subprojects) if \a flat returns \c true.
|
Switches to flat mode (without subprojects) if \a flat returns \c true.
|
||||||
*/
|
*/
|
||||||
@@ -281,24 +292,18 @@ ParserTreeItem::ConstPtr Parser::parse()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
ParserTreeItem::Ptr item;
|
ParserTreeItem::Ptr item;
|
||||||
if (!d->flatMode)
|
|
||||||
item = ParserTreeItem::Ptr(new ParserTreeItem());
|
|
||||||
|
|
||||||
QString prjName(prj->displayName());
|
QString prjName(prj->displayName());
|
||||||
QString prjType(prjName);
|
QString prjType(prjName);
|
||||||
if (prj->document())
|
if (prj->document())
|
||||||
prjType = prj->projectFilePath().toString();
|
prjType = prj->projectFilePath().toString();
|
||||||
SymbolInformation inf(prjName, prjType);
|
SymbolInformation inf(prjName, prjType);
|
||||||
|
item = ParserTreeItem::Ptr(new ParserTreeItem());
|
||||||
|
|
||||||
QStringList projectList = addProjectNode(item, prj->rootProjectNode());
|
if (d->flatMode)
|
||||||
|
addFlatTree(item, prj->rootProjectNode());
|
||||||
|
else
|
||||||
|
addProjectNode(item, prj->rootProjectNode());
|
||||||
|
|
||||||
if (d->flatMode) {
|
|
||||||
// use prj path (prjType) as a project id
|
|
||||||
// addProject(item, prj->files(Project::ExcludeGeneratedFiles), prjType);
|
|
||||||
//! \todo return back, works too long
|
|
||||||
ParserTreeItem::Ptr flatItem = createFlatTree(projectList);
|
|
||||||
item.swap(flatItem);
|
|
||||||
}
|
|
||||||
item->setIcon(prj->rootProjectNode()->icon());
|
item->setIcon(prj->rootProjectNode()->icon());
|
||||||
rootItem->appendChild(item, inf);
|
rootItem->appendChild(item, inf);
|
||||||
}
|
}
|
||||||
@@ -339,9 +344,6 @@ void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol
|
|||||||
// easy solution - lets add any scoped symbol and
|
// easy solution - lets add any scoped symbol and
|
||||||
// any symbol which does not contain :: in the name
|
// any symbol which does not contain :: in the name
|
||||||
|
|
||||||
// if (symbol->isDeclaration())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
//! \todo collect statistics and reorder to optimize
|
//! \todo collect statistics and reorder to optimize
|
||||||
if (symbol->isForwardClassDeclaration()
|
if (symbol->isForwardClassDeclaration()
|
||||||
|| symbol->isExtern()
|
|| symbol->isExtern()
|
||||||
@@ -352,17 +354,11 @@ void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol
|
|||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// skip static local functions
|
|
||||||
// if ((!symbol->scope() || symbol->scope()->isClass())
|
|
||||||
// && symbol->isStatic() && symbol->isFunction())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
|
|
||||||
const CPlusPlus::Name *symbolName = symbol->name();
|
const CPlusPlus::Name *symbolName = symbol->name();
|
||||||
if (symbolName && symbolName->isQualifiedNameId())
|
if (symbolName && symbolName->isQualifiedNameId())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString name = d->overview.prettyName(symbol->name()).trimmed();
|
QString name = d->overview.prettyName(symbolName).trimmed();
|
||||||
QString type = d->overview.prettyType(symbol->type()).trimmed();
|
QString type = d->overview.prettyType(symbol->type()).trimmed();
|
||||||
int iconType = CPlusPlus::Icons::iconTypeForSymbol(symbol);
|
int iconType = CPlusPlus::Icons::iconTypeForSymbol(symbol);
|
||||||
|
|
||||||
@@ -385,51 +381,25 @@ void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol
|
|||||||
|
|
||||||
// prevent showing a content of the functions
|
// prevent showing a content of the functions
|
||||||
if (!symbol->isFunction()) {
|
if (!symbol->isFunction()) {
|
||||||
const CPlusPlus::Scope *scope = symbol->asScope();
|
if (const CPlusPlus::Scope *scope = symbol->asScope()) {
|
||||||
if (scope) {
|
|
||||||
CPlusPlus::Scope::iterator cur = scope->firstMember();
|
CPlusPlus::Scope::iterator cur = scope->firstMember();
|
||||||
while (cur != scope->lastMember()) {
|
CPlusPlus::Scope::iterator last = scope->lastMember();
|
||||||
|
while (cur != last) {
|
||||||
const CPlusPlus::Symbol *curSymbol = *cur;
|
const CPlusPlus::Symbol *curSymbol = *cur;
|
||||||
++cur;
|
++cur;
|
||||||
if (!curSymbol)
|
if (!curSymbol)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// if (!symbol->isClass() && curSymbol->isStatic() && curSymbol->isFunction())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
addSymbol(itemAdd, curSymbol);
|
addSymbol(itemAdd, curSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool appendChild = true;
|
|
||||||
|
|
||||||
// if item is empty and has not to be added
|
// if item is empty and has not to be added
|
||||||
if (symbol->isNamespace() && itemAdd->childCount() == 0)
|
if (!(symbol->isNamespace() && itemAdd->childCount() == 0))
|
||||||
appendChild = false;
|
|
||||||
|
|
||||||
if (appendChild)
|
|
||||||
item->appendChild(itemAdd, information);
|
item->appendChild(itemAdd, information);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Creates a flat tree from the list of projects specified by \a projectList.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ParserTreeItem::Ptr Parser::createFlatTree(const QStringList &projectList)
|
|
||||||
{
|
|
||||||
QReadLocker locker(&d->prjLocker);
|
|
||||||
|
|
||||||
ParserTreeItem::Ptr item(new ParserTreeItem());
|
|
||||||
foreach (const QString &project, projectList) {
|
|
||||||
if (!d->cachedPrjTrees.contains(project))
|
|
||||||
continue;
|
|
||||||
ParserTreeItem::ConstPtr list = d->cachedPrjTrees[project];
|
|
||||||
item->add(list);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Parses the project with the \a projectId and adds the documents from the
|
Parses the project with the \a projectId and adds the documents from the
|
||||||
\a fileList to the project. Updates the internal cached tree for this
|
\a fileList to the project. Updates the internal cached tree for this
|
||||||
@@ -480,8 +450,9 @@ ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileL
|
|||||||
{
|
{
|
||||||
d->prjLocker.lockForRead();
|
d->prjLocker.lockForRead();
|
||||||
|
|
||||||
|
ParserTreeItem::Ptr item = d->cachedPrjTrees.value(projectId);
|
||||||
// calculate current revision
|
// calculate current revision
|
||||||
if (!projectId.isEmpty() && d->cachedPrjTrees.contains(projectId)) {
|
if (!projectId.isEmpty() && !item.isNull()) {
|
||||||
// calculate project's revision
|
// calculate project's revision
|
||||||
unsigned revision = 0;
|
unsigned revision = 0;
|
||||||
foreach (const QString &file, fileList) {
|
foreach (const QString &file, fileList) {
|
||||||
@@ -494,7 +465,7 @@ ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileL
|
|||||||
// if even revision is the same, return cached project
|
// if even revision is the same, return cached project
|
||||||
if (revision == d->cachedPrjTreesRevision[projectId]) {
|
if (revision == d->cachedPrjTreesRevision[projectId]) {
|
||||||
d->prjLocker.unlock();
|
d->prjLocker.unlock();
|
||||||
return d->cachedPrjTrees[projectId];
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +491,7 @@ ParserTreeItem::ConstPtr Parser::getParseDocumentTree(const CPlusPlus::Document:
|
|||||||
|
|
||||||
ParserTreeItem::Ptr itemPtr(new ParserTreeItem());
|
ParserTreeItem::Ptr itemPtr(new ParserTreeItem());
|
||||||
|
|
||||||
unsigned total = doc->globalSymbolCount();
|
const unsigned total = doc->globalSymbolCount();
|
||||||
for (unsigned i = 0; i < total; ++i)
|
for (unsigned i = 0; i < total; ++i)
|
||||||
addSymbol(itemPtr, doc->globalSymbolAt(i));
|
addSymbol(itemPtr, doc->globalSymbolAt(i));
|
||||||
|
|
||||||
@@ -547,11 +518,13 @@ ParserTreeItem::ConstPtr Parser::getCachedOrParseDocumentTree(const CPlusPlus::D
|
|||||||
|
|
||||||
const QString &fileName = doc->fileName();
|
const QString &fileName = doc->fileName();
|
||||||
d->docLocker.lockForRead();
|
d->docLocker.lockForRead();
|
||||||
if (d->cachedDocTrees.contains(fileName)
|
ParserTreeItem::ConstPtr item = d->cachedDocTrees.value(fileName);
|
||||||
&& d->cachedDocTreesRevision.contains(fileName)
|
CitCachedDocTreeRevision citCachedDocTreeRevision = d->cachedDocTreesRevision.find(fileName);
|
||||||
&& d->cachedDocTreesRevision[fileName] == doc->revision()) {
|
if (!item.isNull()
|
||||||
|
&& citCachedDocTreeRevision != d->cachedDocTreesRevision.end()
|
||||||
|
&& citCachedDocTreeRevision.value() == doc->revision()) {
|
||||||
d->docLocker.unlock();
|
d->docLocker.unlock();
|
||||||
return d->cachedDocTrees[fileName];
|
return item;
|
||||||
}
|
}
|
||||||
d->docLocker.unlock();
|
d->docLocker.unlock();
|
||||||
return getParseDocumentTree(doc);
|
return getParseDocumentTree(doc);
|
||||||
@@ -788,9 +761,10 @@ QStringList Parser::addProjectNode(const ParserTreeItem::Ptr &item,
|
|||||||
// our own files
|
// our own files
|
||||||
QStringList fileList;
|
QStringList fileList;
|
||||||
|
|
||||||
|
CitCachedPrjFileLists cit = d->cachedPrjFileLists.find(nodePath);
|
||||||
// try to improve parsing speed by internal cache
|
// try to improve parsing speed by internal cache
|
||||||
if (d->cachedPrjFileLists.contains(nodePath)) {
|
if (cit != d->cachedPrjFileLists.end()) {
|
||||||
fileList = d->cachedPrjFileLists[nodePath];
|
fileList = cit.value();
|
||||||
} else {
|
} else {
|
||||||
fileList = projectNodeFileList(node);
|
fileList = projectNodeFileList(node);
|
||||||
d->cachedPrjFileLists[nodePath] = fileList;
|
d->cachedPrjFileLists[nodePath] = fileList;
|
||||||
@@ -819,5 +793,44 @@ QStringList Parser::addProjectNode(const ParserTreeItem::Ptr &item,
|
|||||||
return projectList;
|
return projectList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Parser::getAllFiles(const ProjectNode *node)
|
||||||
|
{
|
||||||
|
QStringList fileList;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return fileList;
|
||||||
|
|
||||||
|
const QString &nodePath = node->path();
|
||||||
|
|
||||||
|
CitCachedPrjFileLists cit = d->cachedPrjFileLists.find(nodePath);
|
||||||
|
// try to improve parsing speed by internal cache
|
||||||
|
if (cit != d->cachedPrjFileLists.end()) {
|
||||||
|
fileList = cit.value();
|
||||||
|
} else {
|
||||||
|
fileList = projectNodeFileList(node);
|
||||||
|
d->cachedPrjFileLists[nodePath] = fileList;
|
||||||
|
}
|
||||||
|
// subnodes
|
||||||
|
QList<ProjectExplorer::ProjectNode *> projectNodes = node->subProjectNodes();
|
||||||
|
|
||||||
|
foreach (const ProjectExplorer::ProjectNode *project, projectNodes) {
|
||||||
|
fileList += getAllFiles(project);
|
||||||
|
}
|
||||||
|
return fileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::addFlatTree(const ParserTreeItem::Ptr &item, const ProjectNode *node)
|
||||||
|
{
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QStringList fileList = getAllFiles(node);
|
||||||
|
fileList.removeDuplicates();
|
||||||
|
|
||||||
|
if (fileList.count() > 0) {
|
||||||
|
addProject(item, fileList, node->path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClassView
|
} // namespace ClassView
|
||||||
|
|||||||
@@ -58,9 +58,10 @@ public:
|
|||||||
explicit Parser(QObject *parent = 0);
|
explicit Parser(QObject *parent = 0);
|
||||||
~Parser();
|
~Parser();
|
||||||
|
|
||||||
bool canFetchMore(QStandardItem *item) const;
|
bool canFetchMore(QStandardItem *item, bool skipRoot = false) const;
|
||||||
|
|
||||||
void fetchMore(QStandardItem *item, bool skipRoot = false) const;
|
void fetchMore(QStandardItem *item, bool skipRoot = false) const;
|
||||||
|
bool hasChildren(QStandardItem *item) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
//! File list is changed
|
//! File list is changed
|
||||||
@@ -93,6 +94,9 @@ protected slots:
|
|||||||
void onResetDataDone();
|
void onResetDataDone();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
typedef QHash<QString, unsigned>::const_iterator CitCachedDocTreeRevision;
|
||||||
|
typedef QHash<QString, QStringList>::const_iterator CitCachedPrjFileLists;
|
||||||
|
|
||||||
void addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
|
void addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
|
||||||
const QString &projectId = QString());
|
const QString &projectId = QString());
|
||||||
|
|
||||||
@@ -115,11 +119,12 @@ protected:
|
|||||||
|
|
||||||
QStringList addProjectNode(const ParserTreeItem::Ptr &item,
|
QStringList addProjectNode(const ParserTreeItem::Ptr &item,
|
||||||
const ProjectExplorer::ProjectNode *node);
|
const ProjectExplorer::ProjectNode *node);
|
||||||
|
QStringList getAllFiles(const ProjectExplorer::ProjectNode *node);
|
||||||
|
void addFlatTree(const ParserTreeItem::Ptr &item,
|
||||||
|
const ProjectExplorer::ProjectNode *node);
|
||||||
|
|
||||||
QStringList projectNodeFileList(const ProjectExplorer::FolderNode *node) const;
|
QStringList projectNodeFileList(const ProjectExplorer::FolderNode *node) const;
|
||||||
|
|
||||||
ParserTreeItem::Ptr createFlatTree(const QStringList &projectList);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Private class data pointer
|
//! Private class data pointer
|
||||||
ParserPrivate *d;
|
ParserPrivate *d;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
enum { debug = true };
|
enum { debug = false };
|
||||||
|
|
||||||
namespace ClassView {
|
namespace ClassView {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -130,10 +130,8 @@ void ParserTreeItem::copyTree(const ParserTreeItem::ConstPtr &target)
|
|||||||
// d_ptr->symbolInformations.reserve(amount);
|
// d_ptr->symbolInformations.reserve(amount);
|
||||||
|
|
||||||
// every child
|
// every child
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
|
CitSymbolInformations cur = target->d->symbolInformations.constBegin();
|
||||||
target->d->symbolInformations.constBegin();
|
CitSymbolInformations end = target->d->symbolInformations.constEnd();
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
|
|
||||||
target->d->symbolInformations.constEnd();
|
|
||||||
|
|
||||||
for (; cur != end; ++cur) {
|
for (; cur != end; ++cur) {
|
||||||
ParserTreeItem::Ptr item(new ParserTreeItem());
|
ParserTreeItem::Ptr item(new ParserTreeItem());
|
||||||
@@ -220,9 +218,7 @@ void ParserTreeItem::removeChild(const SymbolInformation &inf)
|
|||||||
|
|
||||||
ParserTreeItem::Ptr ParserTreeItem::child(const SymbolInformation &inf) const
|
ParserTreeItem::Ptr ParserTreeItem::child(const SymbolInformation &inf) const
|
||||||
{
|
{
|
||||||
if (!d->symbolInformations.contains(inf))
|
return d->symbolInformations.value(inf);
|
||||||
return ParserTreeItem::Ptr();
|
|
||||||
return d->symbolInformations[inf];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -267,23 +263,15 @@ void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target)
|
|||||||
|
|
||||||
// add children
|
// add children
|
||||||
// every target child
|
// every target child
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
|
CitSymbolInformations cur = target->d->symbolInformations.constBegin();
|
||||||
target->d->symbolInformations.constBegin();
|
CitSymbolInformations end = target->d->symbolInformations.constEnd();
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
|
|
||||||
target->d->symbolInformations.constEnd();
|
|
||||||
while (cur != end) {
|
while (cur != end) {
|
||||||
const SymbolInformation &inf = cur.key();
|
const SymbolInformation &inf = cur.key();
|
||||||
const ParserTreeItem::Ptr &targetChild = cur.value();
|
const ParserTreeItem::Ptr &targetChild = cur.value();
|
||||||
if (d->symbolInformations.contains(inf)) {
|
|
||||||
// this item has the same child node
|
ParserTreeItem::Ptr child = d->symbolInformations.value(inf);
|
||||||
const ParserTreeItem::Ptr &child = d->symbolInformations[inf];
|
if (!child.isNull()) {
|
||||||
if (!child.isNull()) {
|
child->add(targetChild);
|
||||||
child->add(targetChild);
|
|
||||||
} else {
|
|
||||||
ParserTreeItem::Ptr add(new ParserTreeItem());
|
|
||||||
add->copyTree(targetChild);
|
|
||||||
d->symbolInformations[inf] = add;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ParserTreeItem::Ptr add(new ParserTreeItem());
|
ParserTreeItem::Ptr add(new ParserTreeItem());
|
||||||
add->copyTree(targetChild);
|
add->copyTree(targetChild);
|
||||||
@@ -294,42 +282,11 @@ void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Subtracts an internal state with \a target, which contains the subtrahend.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ParserTreeItem::subtract(const ParserTreeItem::ConstPtr &target)
|
|
||||||
{
|
|
||||||
if (target.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// every target child
|
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
|
|
||||||
target->d->symbolInformations.constBegin();
|
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
|
|
||||||
target->d->symbolInformations.constEnd();
|
|
||||||
while (cur != end) {
|
|
||||||
const SymbolInformation &inf = cur.key();
|
|
||||||
if (d->symbolInformations.contains(inf)) {
|
|
||||||
// this item has the same child node
|
|
||||||
if (!d->symbolInformations[inf].isNull())
|
|
||||||
d->symbolInformations[inf]->subtract(cur.value());
|
|
||||||
if (d->symbolInformations[inf].isNull()
|
|
||||||
|| d->symbolInformations[inf]->childCount() == 0)
|
|
||||||
d->symbolInformations.remove(inf);
|
|
||||||
}
|
|
||||||
// next item
|
|
||||||
++cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Appends this item to the QStandardIten item \a item.
|
Appends this item to the QStandardIten item \a item.
|
||||||
\a recursive does it recursively for the tree items (might be needed for
|
|
||||||
lazy data population.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const
|
void ParserTreeItem::convertTo(QStandardItem *item) const
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
@@ -337,18 +294,17 @@ void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const
|
|||||||
QMap<SymbolInformation, ParserTreeItem::Ptr> map;
|
QMap<SymbolInformation, ParserTreeItem::Ptr> map;
|
||||||
|
|
||||||
// convert to map - to sort it
|
// convert to map - to sort it
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
|
CitSymbolInformations curHash = d->symbolInformations.constBegin();
|
||||||
d->symbolInformations.constBegin();
|
CitSymbolInformations endHash = d->symbolInformations.constEnd();
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
|
|
||||||
d->symbolInformations.constEnd();
|
|
||||||
while (curHash != endHash) {
|
while (curHash != endHash) {
|
||||||
map.insert(curHash.key(), curHash.value());
|
map.insert(curHash.key(), curHash.value());
|
||||||
++curHash;
|
++curHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator MapCitSymbolInformations;
|
||||||
// add to item
|
// add to item
|
||||||
QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur = map.constBegin();
|
MapCitSymbolInformations cur = map.constBegin();
|
||||||
QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end = map.constEnd();
|
MapCitSymbolInformations end = map.constEnd();
|
||||||
while (cur != end) {
|
while (cur != end) {
|
||||||
const SymbolInformation &inf = cur.key();
|
const SymbolInformation &inf = cur.key();
|
||||||
ParserTreeItem::Ptr ptr = cur.value();
|
ParserTreeItem::Ptr ptr = cur.value();
|
||||||
@@ -362,9 +318,6 @@ void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const
|
|||||||
// locations
|
// locations
|
||||||
add->setData(Utils::locationsToRole(ptr->symbolLocations()),
|
add->setData(Utils::locationsToRole(ptr->symbolLocations()),
|
||||||
Constants::SymbolLocationsRole);
|
Constants::SymbolLocationsRole);
|
||||||
|
|
||||||
if (recursive)
|
|
||||||
cur.value()->convertTo(add, false);
|
|
||||||
}
|
}
|
||||||
item->appendRow(add);
|
item->appendRow(add);
|
||||||
++cur;
|
++cur;
|
||||||
@@ -380,33 +333,8 @@ bool ParserTreeItem::canFetchMore(QStandardItem *item) const
|
|||||||
if (!item)
|
if (!item)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// incremental data population - so we have to check children
|
int storedChildren = item->rowCount();
|
||||||
// count subchildren of both - current QStandardItem and our internal
|
int internalChildren = d->symbolInformations.count();
|
||||||
|
|
||||||
// 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->symbolInformations.constBegin();
|
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
|
|
||||||
d->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)
|
if (storedChildren < internalChildren)
|
||||||
return true;
|
return true;
|
||||||
@@ -423,25 +351,7 @@ void ParserTreeItem::fetchMore(QStandardItem *item) const
|
|||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < item->rowCount(); i++) {
|
convertTo(item);
|
||||||
QStandardItem *child = item->child(i);
|
|
||||||
if (!child)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const SymbolInformation &childInf = Utils::symbolInformationFromItem(child);
|
|
||||||
|
|
||||||
if (d->symbolInformations.contains(childInf)) {
|
|
||||||
const ParserTreeItem::Ptr &childPtr = d->symbolInformations[childInf];
|
|
||||||
if (childPtr.isNull())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// create a standard
|
|
||||||
QScopedPointer<QStandardItem> state(new QStandardItem());
|
|
||||||
childPtr->convertTo(state.data(), false);
|
|
||||||
|
|
||||||
Utils::fetchItemToTarget(child, state.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -450,10 +360,8 @@ void ParserTreeItem::fetchMore(QStandardItem *item) const
|
|||||||
|
|
||||||
void ParserTreeItem::debugDump(int ident) const
|
void ParserTreeItem::debugDump(int ident) const
|
||||||
{
|
{
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
|
CitSymbolInformations curHash = d->symbolInformations.constBegin();
|
||||||
d->symbolInformations.constBegin();
|
CitSymbolInformations endHash = d->symbolInformations.constEnd();
|
||||||
QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
|
|
||||||
d->symbolInformations.constEnd();
|
|
||||||
while (curHash != endHash) {
|
while (curHash != endHash) {
|
||||||
const SymbolInformation &inf = curHash.key();
|
const SymbolInformation &inf = curHash.key();
|
||||||
qDebug() << QString(2*ident, QLatin1Char(' ')) << inf.iconType() << inf.name() << inf.type()
|
qDebug() << QString(2*ident, QLatin1Char(' ')) << inf.iconType() << inf.name() << inf.type()
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "classviewsymbolinformation.h"
|
#include "classviewsymbolinformation.h"
|
||||||
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QStandardItem)
|
QT_FORWARD_DECLARE_CLASS(QStandardItem)
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ public:
|
|||||||
|
|
||||||
int childCount() const;
|
int childCount() const;
|
||||||
|
|
||||||
void convertTo(QStandardItem *item, bool recursive = true) const;
|
void convertTo(QStandardItem *item) const;
|
||||||
|
|
||||||
// additional properties
|
// additional properties
|
||||||
//! Assigned icon
|
//! Assigned icon
|
||||||
@@ -85,8 +86,6 @@ public:
|
|||||||
|
|
||||||
void add(const ParserTreeItem::ConstPtr &target);
|
void add(const ParserTreeItem::ConstPtr &target);
|
||||||
|
|
||||||
void subtract(const ParserTreeItem::ConstPtr &target);
|
|
||||||
|
|
||||||
bool canFetchMore(QStandardItem *item) const;
|
bool canFetchMore(QStandardItem *item) const;
|
||||||
|
|
||||||
void fetchMore(QStandardItem *item) const;
|
void fetchMore(QStandardItem *item) const;
|
||||||
@@ -97,6 +96,7 @@ protected:
|
|||||||
ParserTreeItem &operator=(const ParserTreeItem &other);
|
ParserTreeItem &operator=(const ParserTreeItem &other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator CitSymbolInformations;
|
||||||
//! Private class data pointer
|
//! Private class data pointer
|
||||||
ParserTreeItemPrivate *d;
|
ParserTreeItemPrivate *d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,12 +80,12 @@ bool SymbolInformation::operator<(const SymbolInformation &other) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmp = name().compare(other.name(), Qt::CaseInsensitive);
|
int cmp = name().compare(other.name());
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
return true;
|
return true;
|
||||||
if (cmp > 0)
|
if (cmp > 0)
|
||||||
return false;
|
return false;
|
||||||
return type().compare(other.type(), Qt::CaseInsensitive) < 0;
|
return type().compare(other.type()) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ void TreeItemModel::fetchMore(const QModelIndex &parent)
|
|||||||
return Manager::instance()->fetchMore(itemFromIndex(parent));
|
return Manager::instance()->fetchMore(itemFromIndex(parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TreeItemModel::hasChildren(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return Manager::instance()->hasChildren(itemFromIndex(parent));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Moves the root item to the \a target item.
|
Moves the root item to the \a target item.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ public:
|
|||||||
//! \implements QStandardItemModel::fetchMore
|
//! \implements QStandardItemModel::fetchMore
|
||||||
virtual void fetchMore(const QModelIndex &parent);
|
virtual void fetchMore(const QModelIndex &parent);
|
||||||
|
|
||||||
|
virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! private class data pointer
|
//! private class data pointer
|
||||||
TreeItemModelPrivate *d;
|
TreeItemModelPrivate *d;
|
||||||
|
|||||||
Reference in New Issue
Block a user