diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h new file mode 100644 index 0000000000000000000000000000000000000000..9a2f992bf47b46ba5a7695d560126ffac88db04f --- /dev/null +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h @@ -0,0 +1,203 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef CDBSYMBOLGROUPCONTEXT_TPL_H +#define CDBSYMBOLGROUPCONTEXT_TPL_H + +#include <QtCore/QDebug> + +namespace Debugger { +namespace Internal { + +enum { debugSgRecursion = 0 }; + +/* inline static */ bool CdbSymbolGroupContext::isSymbolDisplayable(const DEBUG_SYMBOL_PARAMETERS &p) +{ + if (p.Flags & (DEBUG_SYMBOL_IS_LOCAL|DEBUG_SYMBOL_IS_ARGUMENT)) + return true; + // Do not display static members. + if (p.Flags & DEBUG_SYMBOL_READ_ONLY) + return false; + return true; +} + +template <class OutputIterator> +bool CdbSymbolGroupContext::getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage) +{ + unsigned long start; + unsigned long parentId; + if (!getChildSymbolsPosition(prefix, &start, &parentId, errorMessage)) + return false; + // Skip over expanded children + const unsigned long end = m_symbolParameters.size(); + for (unsigned long s = start; s < end; ++s) { + const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s); + if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) { + *it = symbolAt(s); + ++it; + } + } + return true; +} + +template <class OutputIterator> + bool insertChildrenRecursion(const QString &iname, + CdbSymbolGroupContext *sg, + OutputIterator it, + int maxRecursionLevel, + int level, + QString *errorMessage, + int *childCount = 0); + +// Insert a symbol (and its first level children depending on forceRecursion) +template <class OutputIterator> +bool insertSymbolRecursion(WatchData wd, + CdbSymbolGroupContext *sg, + OutputIterator it, + int maxRecursionLevel, + int level, + QString *errorMessage) +{ + // Find out whether to recurse (has children or at least knows it has children) + // Open next level if specified by recursion depth or child is already expanded + // (Sometimes, some root children are already expanded after creating the context). + const bool hasChildren = wd.childCount > 0 || wd.isChildrenNeeded(); + const bool recurse = hasChildren && (level < maxRecursionLevel || sg->isExpanded(wd.iname)); + if (debugSgRecursion) + qDebug() << Q_FUNC_INFO << '\n' << wd.iname << "level=" << level << "recurse=" << recurse; + bool rc = true; + if (recurse) { // Determine number of children and indicate in model + int childCount; + rc = insertChildrenRecursion(wd.iname, sg, it, maxRecursionLevel, level, errorMessage, &childCount); + if (rc) { + wd.setChildCount(childCount); + wd.setChildrenUnneeded(); + } + } else { + // No further recursion at this level, pretend entry is complete + if (wd.isChildrenNeeded()) { + wd.setChildCount(1); + wd.setChildrenUnneeded(); + } + } + if (debugSgRecursion) + qDebug() << " INSERTING: at " << level << wd.toString(); + *it = wd; + ++it; + return rc; +} + +// Insert the children of prefix. +template <class OutputIterator> + bool insertChildrenRecursion(const QString &iname, + CdbSymbolGroupContext *sg, + OutputIterator it, + int maxRecursionLevel, + int level, + QString *errorMessage, + int *childCountPtr) +{ + if (debugSgRecursion > 1) + qDebug() << Q_FUNC_INFO << '\n' << iname << level; + + QList<WatchData> watchList; + // This implicitly enforces expansion + if (!sg->getChildSymbols(iname, WatchDataBackInserter(watchList), errorMessage)) + return false; + + const int childCount = watchList.size(); + if (childCountPtr) + *childCountPtr = childCount; + int succeededChildCount = 0; + for (int c = 0; c < childCount; c++) { + const WatchData &wd = watchList.at(c); + if (wd.isValid()) { // We sometimes get empty names for deeply nested data + if (!insertSymbolRecursion(wd, sg, it, maxRecursionLevel, level + 1, errorMessage)) + return false; + succeededChildCount++; + } else { + const QString msg = QString::fromLatin1("WARNING: Skipping invalid child symbol #%2 (type %3) of '%4'."). + arg(QLatin1String(Q_FUNC_INFO)).arg(c).arg(wd.type, iname); + qWarning("%s\n", qPrintable(msg)); + } + } + if (childCountPtr) + *childCountPtr = succeededChildCount; + return true; +} + +template <class OutputIterator> +bool CdbSymbolGroupContext::populateModelInitially(CdbSymbolGroupContext *sg, + OutputIterator it, + QString *errorMessage) +{ + if (debugSgRecursion) + qDebug() << "###" << Q_FUNC_INFO; + + // Insert root items + QList<WatchData> watchList; + if (!sg->getChildSymbols(sg->prefix(), WatchDataBackInserter(watchList), errorMessage)) + return false; + + foreach(const WatchData &wd, watchList) + if (!insertSymbolRecursion(wd, sg, it, 0, 0, errorMessage)) + return false; + return true; +} + +template <class OutputIterator> +bool CdbSymbolGroupContext::completeModel(CdbSymbolGroupContext *sg, + const QList<WatchData> &incompleteLocals, + OutputIterator it, + QString *errorMessage) +{ + if (debugSgRecursion) + qDebug().nospace() << "###>" << Q_FUNC_INFO << ' ' << incompleteLocals.size() << '\n'; + // The view reinserts any node being expanded with flag 'ChildrenNeeded'. + // Recurse down one level in context unless this is already the case. + foreach(WatchData wd, incompleteLocals) { + const bool contextExpanded = sg->isExpanded(wd.iname); + if (debugSgRecursion) + qDebug() << " " << wd.iname << "CE=" << contextExpanded; + if (contextExpanded) { // You know that already. + wd.setChildrenUnneeded(); + *it = wd; + ++it; + } else { + if (!insertSymbolRecursion(wd, sg, it, 1, 0, errorMessage)) + return false; + } + } + return true; +} + +} // namespace Internal +} // namespace Debugger + +#endif // CDBSYMBOLGROUPCONTEXT_TPL_H