diff options
author | hjk <[email protected]> | 2012-05-18 02:28:41 +0200 |
---|---|---|
committer | hjk <[email protected]> | 2012-05-24 14:33:34 +0200 |
commit | e11a3a7697e7b432ac061277694885cf3724f25c (patch) | |
tree | 46a3140ed47b072782541d005d0edbdf1259a554 /src/plugins/debugger/watchhandler.cpp | |
parent | c14c1248ed01f5e16975dc1082b5ce4e58052f8b (diff) |
debugger: rework WatchModel
It's one model for all locals, watch, return, tooltip and inspector
data. This allows more streamlined code paths and better isolation
of the model data from the WatchHandler. WatchItems are now registered
in a hash indexed by iname, so inames can be used as the primary
handle to watch data in the WatchHandler interface.
Change-Id: Idac0a808b5d785307496d1de4198a1f2e9ce3880
Reviewed-by: Aurindam Jana <[email protected]>
Diffstat (limited to 'src/plugins/debugger/watchhandler.cpp')
-rw-r--r-- | src/plugins/debugger/watchhandler.cpp | 1048 |
1 files changed, 585 insertions, 463 deletions
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index c9ada1d5b36..77bc4f9db57 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -40,10 +40,6 @@ #include "debuggerdialogs.h" #include "watchutils.h" -#if USE_WATCH_MODEL_TEST -#include "modeltest.h" -#endif - #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -52,6 +48,7 @@ #include <QDebug> #include <QEvent> #include <QFile> +#include <QPointer> #include <QProcess> #include <QTextStream> #include <QtAlgorithms> @@ -62,6 +59,12 @@ #include <ctype.h> #include <utils/qtcassert.h> +//#define USE_WATCH_MODEL_TEST 0 +//#define USE_EXPENSIVE_CHECKS 0 + +#if USE_WATCH_MODEL_TEST +#include "modeltest.h" +#endif namespace Debugger { namespace Internal { @@ -70,7 +73,13 @@ namespace Internal { enum { debugModel = 0 }; #define MODEL_DEBUG(s) do { if (debugModel) qDebug() << s; } while (0) -#define MODEL_DEBUGX(s) qDebug() << s + +#if USE_EXPENSIVE_CHECKS +#define CHECK(s) s +#else +#define CHECK(s) +#endif + static QHash<QByteArray, int> theWatcherNames; static QHash<QByteArray, int> theTypeFormats; @@ -100,126 +109,222 @@ static QByteArray stripForFormat(const QByteArray &ba) return res; } -void WatchHandler::setUnprintableBase(int base) -{ - theUnprintableBase = base; - emitAllChanged(); -} - -int WatchHandler::unprintableBase() -{ - return theUnprintableBase; -} - //////////////////////////////////////////////////////////////////// // // WatchItem // //////////////////////////////////////////////////////////////////// +// Used to make sure the item cache is notified of construction and +// destruction of items. + +class WatchItem; +WatchItem *itemConstructor(WatchModel *model, const QByteArray &iname); +void itemDestructor(WatchModel *model, WatchItem *item); + class WatchItem : public WatchData { public: - WatchItem() { parent = 0; } - - ~WatchItem() { - if (parent != 0) - parent->children.removeOne(this); - qDeleteAll(children); - } - - WatchItem(const WatchData &data) : WatchData(data) - { parent = 0; } + WatchItem *parent; + QList<WatchItem *> children; - void setData(const WatchData &data) - { static_cast<WatchData &>(*this) = data; } +private: + friend WatchItem *itemConstructor(WatchModel *model, const QByteArray &iname); + friend void itemDestructor(WatchModel *model, WatchItem *item); - WatchItem *parent; - QList<WatchItem *> children; // fetched children + WatchItem() { parent = 0; } + ~WatchItem() {} + WatchItem(const WatchItem &); // Not implemented. }; - /////////////////////////////////////////////////////////////////////// // // WatchModel // /////////////////////////////////////////////////////////////////////// -WatchModel::WatchModel(WatchHandler *handler, WatchType type) - : QAbstractItemModel(handler), m_generationCounter(0), - m_handler(handler), m_type(type) +class WatchModel : public QAbstractItemModel { - m_root = new WatchItem; - m_root->hasChildren = 1; - m_root->state = 0; - m_root->name = WatchHandler::tr("Root"); - m_root->parent = 0; + Q_OBJECT - switch (m_type) { - case ReturnWatch: - m_root->iname = "return"; - m_root->name = WatchHandler::tr("Return Value"); - break; - case LocalsWatch: - m_root->iname = "local"; - m_root->name = WatchHandler::tr("Locals"); - break; - case WatchersWatch: - m_root->iname = "watch"; - m_root->name = WatchHandler::tr("Expressions"); - break; - case TooltipsWatch: - m_root->iname = "tooltip"; - m_root->name = WatchHandler::tr("Tooltip"); - break; - case InspectWatch: - m_root->iname = "inspect"; - m_root->name = WatchHandler::tr("Inspector"); - break; - } +private: + explicit WatchModel(WatchHandler *handler); + ~WatchModel(); + + friend WatchItem *itemConstructor(WatchModel *model, const QByteArray &iname); + friend void itemDestructor(WatchModel *model, WatchItem *item); + +public: + int rowCount(const QModelIndex &idx = QModelIndex()) const; + int columnCount(const QModelIndex &idx) const; + +signals: + void currentIndexRequested(const QModelIndex &idx); + void itemIsExpanded(const QModelIndex &idx); + +private: + QVariant data(const QModelIndex &idx, int role) const; + bool setData(const QModelIndex &idx, const QVariant &value, int role); + QModelIndex index(int, int, const QModelIndex &idx) const; + QModelIndex parent(const QModelIndex &idx) const; + bool hasChildren(const QModelIndex &idx) const; + Qt::ItemFlags flags(const QModelIndex &idx) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + + void invalidateAll(const QModelIndex &parentIndex = QModelIndex()); + WatchItem *createItem(const QByteArray &iname, const QString &name, WatchItem *parent); + + friend class WatchHandler; + + WatchItem *watchItem(const QModelIndex &) const; + QModelIndex watchIndex(const WatchItem *needle) const; + QModelIndex watchIndexHelper(const WatchItem *needle, + const WatchItem *parentItem, const QModelIndex &parentIndex) const; + + void insertDataItem(const WatchData &data); + Q_SLOT void reinsertAllData(); + void reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data); + void insertBulkData(const QList<WatchData> &data); + QString displayForAutoTest(const QByteArray &iname) const; + void reinitialize(); + void destroyItem(WatchItem *item); // With model notification. + void destroyChildren(WatchItem *item); // With model notification. + void destroyHelper(const QList<WatchItem *> &items); // Without model notification. + void emitDataChanged(int column, + const QModelIndex &parentIndex = QModelIndex()); + + friend QDebug operator<<(QDebug d, const WatchModel &m); + + void dump(); + void dumpHelper(WatchItem *item); + Q_SLOT void emitAllChanged(); + + void showInEditorHelper(QString *contents, WatchItem *item, int level); + void setCurrentItem(const QByteArray &iname); + + QString displayType(const WatchData &typeIn) const; + QString formattedValue(const WatchData &data) const; + QString removeInitialNamespace(QString str) const; + QString removeNamespaces(QString str) const; + void formatRequests(QByteArray *out, const WatchItem *item) const; + DebuggerEngine *engine() const; + QString display(const WatchItem *item, int col) const; + int itemFormat(const WatchData &data) const; + bool contentIsValid() const; + + WatchHandler *m_handler; // Not owned. + + WatchItem *m_root; // Owned. + WatchItem *m_localsRoot; // Not owned. + WatchItem *m_inspectorRoot; // Not owned. + WatchItem *m_watchRoot; // Not owned. + WatchItem *m_returnRoot; // Not owned. + WatchItem *m_tooltipRoot; // Not owned. + + QSet<QByteArray> m_expandedINames; + QSet<QByteArray> m_fetchTriggered; + + QStringList typeFormatList(const WatchData &data) const; + TypeFormats m_reportedTypeFormats; + + // QWidgets and QProcesses taking care of special displays. + typedef QMap<QByteArray, QPointer<QObject> > EditHandlers; + EditHandlers m_editHandlers; + + WatchItem *createItem(const QByteArray &iname); + WatchItem *createItem(const WatchData &data); + void assignData(WatchItem *item, const WatchData &data); + WatchItem *findItem(const QByteArray &iname) const; + friend class WatchItem; + QHash<QByteArray, WatchItem *> m_cache; + + #if USE_EXPENSIVE_CHECKS + QHash<const WatchItem *, QByteArray> m_cache2; + void checkTree(); + void checkItem(const WatchItem *item) const; + void checkTree(WatchItem *item, QSet<QByteArray> *inames); + #endif +}; + +WatchModel::WatchModel(WatchHandler *handler) + : m_handler(handler) +{ + m_root = createItem(QByteArray(), tr("Root"), 0); + // Note: Needs to stay + m_localsRoot = createItem("local", tr("Locals"), m_root); + m_inspectorRoot = createItem("inspect", tr("Inspector"), m_root); + m_watchRoot = createItem("watch", tr("Expressions"), m_root); + m_returnRoot = createItem("return", tr("Return Value"), m_root); + m_tooltipRoot = createItem("tooltip", tr("Tooltip"), m_root); + + connect(debuggerCore()->action(SortStructMembers), SIGNAL(valueChanged(QVariant)), + SLOT(reinsertAllData())); + connect(debuggerCore()->action(ShowStdNamespace), SIGNAL(valueChanged(QVariant)), + SLOT(reinsertAllData())); + connect(debuggerCore()->action(ShowQtNamespace), SIGNAL(valueChanged(QVariant)), + SLOT(reinsertAllData())); } WatchModel::~WatchModel() { - delete m_root; + CHECK(checkItem(m_root)); + destroyChildren(m_root); + itemDestructor(this, m_root); + QTC_CHECK(m_cache.isEmpty()); } -WatchItem *WatchModel::rootItem() const +WatchItem *itemConstructor(WatchModel *model, const QByteArray &iname) { - return m_root; + QTC_CHECK(!model->m_cache.contains(iname)); + WatchItem *item = new WatchItem(); + item->iname = iname; + model->m_cache[iname] = item; + CHECK(model->m_cache2[item] = iname); + CHECK(model->checkItem(item)); + return item; } -void WatchModel::reinitialize() +void itemDestructor(WatchModel *model, WatchItem *item) { - int n = m_root->children.size(); - if (n == 0) - return; - //MODEL_DEBUG("REMOVING " << n << " CHILDREN OF " << m_root->iname); - QModelIndex index = watchIndex(m_root); - beginRemoveRows(index, 0, n - 1); - qDeleteAll(m_root->children); - m_root->children.clear(); - endRemoveRows(); + QTC_ASSERT(model->m_cache.value(item->iname) == item, return); + CHECK(model->checkItem(item)); + CHECK(model->m_cache2.remove(item)); + model->m_cache.remove(item->iname); + delete item; } -void WatchModel::emitAllChanged() +WatchItem *WatchModel::createItem(const QByteArray &iname, const QString &name, WatchItem *parent) { - emit layoutChanged(); + WatchItem *item = itemConstructor(this, iname); + item->name = name; + item->hasChildren = true; // parent == 0; + item->state = 0; + item->parent = parent; + if (parent) + parent->children.append(item); + return item; } -void WatchModel::beginCycle(bool fullCycle) +void WatchModel::reinitialize() { - if (fullCycle) - m_generationCounter++; - - //emit enableUpdates(false); + CHECK(checkTree()); + //MODEL_DEBUG("REMOVING " << n << " CHILDREN OF " << m_root->iname); + QTC_CHECK(m_root->children.size() == 5); + destroyChildren(m_localsRoot); + destroyChildren(m_watchRoot); + destroyChildren(m_returnRoot); + destroyChildren(m_tooltipRoot); + destroyChildren(m_inspectorRoot); + QTC_CHECK(m_cache.size() == 6); + CHECK(checkTree()); } -void WatchModel::endCycle() +void WatchModel::emitAllChanged() { - removeOutdated(); - m_fetchTriggered.clear(); - //emit enableUpdates(true); + emit layoutChanged(); } DebuggerEngine *WatchModel::engine() const @@ -237,43 +342,85 @@ void WatchModel::dump() void WatchModel::dumpHelper(WatchItem *item) { qDebug() << "ITEM: " << item->iname - << (item->parent ? item->parent->iname : "<none>") - << item->generation; + << (item->parent ? item->parent->iname : "<none>"); foreach (WatchItem *child, item->children) dumpHelper(child); } -void WatchModel::removeOutdated() +void WatchModel::destroyHelper(const QList<WatchItem *> &items) { - foreach (WatchItem *child, m_root->children) - removeOutdatedHelper(child); -#if DEBUG_MODEL -#if USE_WATCH_MODEL_TEST - (void) new ModelTest(this, this); -#endif -#endif -} - -void WatchModel::removeOutdatedHelper(WatchItem *item) -{ - if (item->generation < m_generationCounter) { - destroyItem(item); - } else { - foreach (WatchItem *child, item->children) - removeOutdatedHelper(child); + for (int i = items.size(); --i >= 0; ) { + WatchItem *item = items.at(i); + destroyHelper(item->children); + itemDestructor(this, item); } } void WatchModel::destroyItem(WatchItem *item) { + const QByteArray iname = item->iname; + CHECK(checkTree()); + QTC_ASSERT(m_cache.contains(iname), return); + + // Deregister from model and parent. + // It's sufficient to do this non-recursively. WatchItem *parent = item->parent; - QModelIndex index = watchIndex(parent); - int n = parent->children.indexOf(item); + QTC_ASSERT(parent, return); + QModelIndex parentIndex = watchIndex(parent); + const int i = parent->children.indexOf(item); //MODEL_DEBUG("NEED TO REMOVE: " << item->iname << "AT" << n); - beginRemoveRows(index, n, n); - parent->children.removeAt(n); + beginRemoveRows(parentIndex, i, i); + parent->children.removeAt(i); endRemoveRows(); - delete item; + + // Destroy contents. + destroyHelper(item->children); + itemDestructor(this, item); + QTC_ASSERT(!m_cache.contains(iname), return); + CHECK(checkTree()); +} + +void WatchModel::destroyChildren(WatchItem *item) +{ + CHECK(checkTree()); + QTC_ASSERT(m_cache.contains(item->iname), return); + if (item->children.isEmpty()) + return; + + QList<WatchItem *> items = item->children; + + // Deregister from model and parent. + // It's sufficient to do this non-recursively. + QModelIndex idx = watchIndex(item); + beginRemoveRows(idx, 0, items.size() - 1); + item->children.clear(); + endRemoveRows(); + + // Destroy contents. + destroyHelper(items); + CHECK(checkTree()); +} + +WatchItem *WatchModel::findItem(const QByteArray &iname) const +{ + return m_cache.value(iname, 0); +} + +WatchItem *WatchModel::createItem(const WatchData &data) +{ + WatchItem *item = itemConstructor(this, data.iname); + static_cast<WatchData &>(*item) = data; + return item; +} + +void WatchModel::assignData(WatchItem *item, const WatchData &data) +{ + CHECK(checkItem(item)); + QTC_ASSERT(data.iname == item->iname, + m_cache.remove(item->iname); + m_cache[data.iname] = item); + static_cast<WatchData &>(*item) = data; + CHECK(checkItem(item)); } void WatchModel::reinsertAllData() @@ -281,26 +428,21 @@ void WatchModel::reinsertAllData() QList<WatchData> list; reinsertAllDataHelper(m_root, &list); reinitialize(); - foreach (WatchItem data, list) { - data.setAllUnneeded(); - insertData(data); - } - layoutChanged(); + insertBulkData(list); } void WatchModel::reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data) { data->append(*item); + data->back().setAllUnneeded(); foreach (WatchItem *child, item->children) reinsertAllDataHelper(child, data); } static QByteArray parentName(const QByteArray &iname) { - int pos = iname.lastIndexOf('.'); - if (pos == -1) - return QByteArray(); - return iname.left(pos); + const int pos = iname.lastIndexOf('.'); + return pos == -1 ? QByteArray() : iname.left(pos); } static QString niceTypeHelper(const QByteArray &typeIn) @@ -576,20 +718,27 @@ static inline QVariant editValue(const WatchData &d) return QVariant(translate(stringValue)); } -bool WatchModel::canFetchMore(const QModelIndex &index) const +bool WatchModel::canFetchMore(const QModelIndex &idx) const { - WatchItem *item = watchItem(index); + if (!idx.isValid()) + return false; + if (!contentIsValid()) + return false; + WatchItem *item = watchItem(idx); QTC_ASSERT(item, return false); - return index.isValid() && contentIsValid() && !m_fetchTriggered.contains(item->iname); + if (!item->iname.contains('.')) + return false; + return !m_fetchTriggered.contains(item->iname); } -void WatchModel::fetchMore(const QModelIndex &index) +void WatchModel::fetchMore(const QModelIndex &idx) { - QTC_ASSERT(index.isValid(), return); - WatchItem *item = watchItem(index); + if (!idx.isValid()) + return; // Triggered by ModelTester. + WatchItem *item = watchItem(idx); QTC_ASSERT(item, return); QTC_ASSERT(!m_fetchTriggered.contains(item->iname), return); - m_handler->m_expandedINames.insert(item->iname); + m_expandedINames.insert(item->iname); m_fetchTriggered.insert(item->iname); if (item->children.isEmpty()) { WatchData data = *item; @@ -634,6 +783,8 @@ QModelIndex WatchModel::parent(const QModelIndex &idx) const int WatchModel::rowCount(const QModelIndex &idx) const { + if (!idx.isValid()) + return m_root->children.size(); if (idx.column() > 0) return 0; return watchItem(idx)->children.size(); @@ -653,12 +804,15 @@ bool WatchModel::hasChildren(const QModelIndex &parent) const WatchItem *WatchModel::watchItem(const QModelIndex &idx) const { - return idx.isValid() + WatchItem *item = idx.isValid() ? static_cast<WatchItem*>(idx.internalPointer()) : m_root; + CHECK(checkItem(item)); + return item; } QModelIndex WatchModel::watchIndex(const WatchItem *item) const { + CHECK(checkItem(item)); return watchIndexHelper(item, m_root, QModelIndex()); } @@ -719,13 +873,40 @@ int WatchModel::itemFormat(const WatchData &data) const bool WatchModel::contentIsValid() const { + // FIXME: // inspector doesn't follow normal beginCycle()/endCycle() - if (m_type == InspectWatch) - return true; + //if (m_type == InspectWatch) + // return true; return m_handler->m_contentsValid; } -static inline QString expression(const WatchItem *item) +#if USE_EXPENSIVE_CHECKS +void WatchModel::checkTree() +{ + QSet<QByteArray> inames; + checkTree(m_root, &inames); + QSet<QByteArray> current = m_cache.keys().toSet(); + Q_ASSERT(inames == current); +} + +void WatchModel::checkTree(WatchItem *item, QSet<QByteArray> *inames) +{ + checkItem(item); + inames->insert(item->iname); + for (int i = 0, n = item->children.size(); i != n; ++i) + checkTree(item->children.at(i), inames); +} + +void WatchModel::checkItem(const WatchItem *item) const +{ + Q_ASSERT(item->children.size() < 1000 * 1000); + Q_ASSERT(m_cache2.contains(item)); + Q_ASSERT(m_cache2.value(item) == item->iname); + Q_ASSERT(m_cache.value(item->iname) == item); +} +#endif + +static QString expression(const WatchItem *item) { if (!item->exp.isEmpty()) return QString::fromLatin1(item->exp); @@ -746,11 +927,11 @@ QString WatchModel::display(const WatchItem *item, int col) const QString result; switch (col) { case 0: - if (m_type == WatchersWatch && item->name.isEmpty()) + if (item->parent == m_watchRoot && item->name.isEmpty()) result = tr("<Edit>"); - else if (m_type == ReturnWatch && item->iname.count('.') == 1) + else if (item->parent == m_returnRoot) result = tr("returned value"); - else if (item->name == QLatin1String("*") && item->parent) + else if (item->name == QLatin1String("*")) result = QLatin1Char('*') + item->parent->name; else result = removeInitialNamespace(item->name); @@ -774,7 +955,7 @@ QString WatchModel::display(const WatchItem *item, int col) const QString WatchModel::displayForAutoTest(const QByteArray &iname) const { - const WatchItem *item = findItem(iname, m_root); + WatchItem *item = findItem(iname); if (item) return display(item, 1) + QLatin1Char(' ') + display(item, 2); return QString(); @@ -782,6 +963,9 @@ QString WatchModel::displayForAutoTest(const QByteArray &iname) const QVariant WatchModel::data(const QModelIndex &idx, int role) const { + if (!idx.isValid()) + return QVariant(); // Triggered by ModelTester. + const WatchItem *item = watchItem(idx); const WatchItem &data = *item; @@ -840,10 +1024,10 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const return data.iname; case LocalsExpandedRole: - return m_handler->m_expandedINames.contains(data.iname); + return m_expandedINames.contains(data.iname); case LocalsTypeFormatListRole: - return m_handler->typeFormatList(data); + return typeFormatList(data); case LocalsTypeRole: return removeNamespaces(displayType(data)); @@ -890,13 +1074,16 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const return QVariant(); } -bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role) { - WatchItem &data = *watchItem(index); + if (!idx.isValid()) + return false; // Triggered by ModelTester. + + WatchItem &data = *watchItem(idx); switch (role) { case Qt::EditRole: - switch (index.column()) { + switch (idx.column()) { case 0: // Watch expression: See delegate. break; case 1: // Change value @@ -909,10 +1096,10 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro case LocalsExpandedRole: if (value.toBool()) { // Should already have been triggered by fetchMore() - //QTC_CHECK(m_handler->m_expandedINames.contains(data.iname)); - m_handler->m_expandedINames.insert(data.iname); + //QTC_CHECK(m_expandedINames.contains(data.iname)); + m_expandedINames.insert(data.iname); } else { - m_handler->m_expandedINames.remove(data.iname); + m_expandedINames.remove(data.iname); } break; @@ -933,7 +1120,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro } } - emit dataChanged(index, index); + //emit dataChanged(idx, idx); return true; } @@ -990,7 +1177,7 @@ QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int ro return QVariant(); } -QStringList WatchHandler::typeFormatList(const WatchData &data) const +QStringList WatchModel::typeFormatList(const WatchData &data) const { if (data.referencingAddress || isPointerType(data.type)) return QStringList() @@ -1026,7 +1213,7 @@ QStringList WatchHandler::typeFormatList(const WatchData &data) const } // Determine sort order of watch items by sort order or alphabetical inames -// according to setting 'SortStructMembers'. We need a map key for bulkInsert +// according to setting 'SortStructMembers'. We need a map key for insertBulkData // and a predicate for finding the insertion position of a single item. // Set this before using any of the below according to action @@ -1086,98 +1273,153 @@ static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *i return it - list.begin(); } -void WatchModel::insertData(const WatchData &data) +void WatchModel::insertDataItem(const WatchData &data) { +#if USE_WATCH_MODEL_TEST + (void) new ModelTest(this, this); +#endif + m_fetchTriggered.remove(data.iname); + CHECK(checkTree()); + QTC_ASSERT(!data.iname.isEmpty(), qDebug() << data.toString(); return); - WatchItem *parent = findItem(parentName(data.iname), m_root); + WatchItem *parent = findItem(parentName(data.iname)); if (!parent) { WatchData parent; parent.iname = parentName(data.iname); MODEL_DEBUG("\nFIXING MISSING PARENT FOR\n" << data.iname); if (!parent.iname.isEmpty()) - insertData(parent); + insertDataItem(parent); return; } - QModelIndex index = watchIndex(parent); - if (WatchItem *oldItem = findItem(data.iname, parent)) { - bool hadChildren = oldItem->hasChildren; + + WatchItem *item = findItem(data.iname); +#if 0 + if (item) { // Overwrite old entry. - bool hasChanged = oldItem->hasChanged(data); - oldItem->setData(data); - oldItem->changed = hasChanged; - oldItem->generation = m_generationCounter; - QModelIndex idx = watchIndex(oldItem); - emit dataChanged(idx, idx.sibling(idx.row(), 2)); + bool hasChanged = item->hasChanged(data); + assignData(item, data); + item->changed = hasChanged; + // QModelIndex idx = watchIndex(oldItem); + // emit dataChanged(idx, idx.sibling(idx.row(), 2)); + } else { + // Add new entry. + item = createItem(data); + item->parent = parent; + item->changed = true; + } + const int n = findInsertPosition(parent->children, item); + QModelIndex idx = watchIndex(parent); + beginInsertRows(idx, n, n); + parent->children.insert(n, item); + endInsertRows(); +#else + if (item) { + // Remove old children. + destroyChildren(item); - // This works around https://bugreports.qt-project.org/browse/QTBUG-7115 - // by creating and destroying a dummy child item. - if (!hadChildren && oldItem->hasChildren) { - WatchData dummy = data; - dummy.iname = data.iname + ".x"; - dummy.hasChildren = false; - dummy.setAllUnneeded(); - insertData(dummy); - destroyItem(findItem(dummy.iname, m_root)); - } + // Overwrite old entry. + bool hasChanged = item->hasChanged(data); + assignData(item, data); + item->changed = hasChanged; + QModelIndex idx = watchIndex(item); + emit dataChanged(idx, idx.sibling(idx.row(), 2)); } else { // Add new entry. - WatchItem *item = new WatchItem(data); + item = createItem(data); item->parent = parent; - item->generation = m_generationCounter; item->changed = true; - const int n = findInsertPosition(parent->children, item); - beginInsertRows(index, n, n); - parent->children.insert(n, item); + const int row = findInsertPosition(parent->children, item); + QModelIndex idx = watchIndex(parent); + beginInsertRows(idx, row, row); + parent->children.insert(row, item); endInsertRows(); + if (m_expandedINames.contains(parentName(data.iname))) { + emit itemIsExpanded(idx); + } +// if (m_expandedINames.contains(data.iname)) { +// QModelIndex child = index(row, 0, idx); +// emit itemIsExpanded(child); +// } } +#endif } void WatchModel::insertBulkData(const QList<WatchData> &list) { + foreach (const WatchData &data, list) + insertDataItem(data); + CHECK(checkTree()); + return; + #if 0 - for (int i = 0; i != list.size(); ++i) - insertData(list.at(i)); + QMap<QByteArray, QList<WatchData> > hash; + + foreach (const WatchData &data, list) { + // we insert everything, including incomplete stuff + // to reduce the number of row add operations in the model. + if (data.isValid()) { + hash[parentName(data.iname)].append(data); + } else { + qWarning("%s:%d: Attempt to bulk-insert invalid watch item: %s", + __FILE__, __LINE__, qPrintable(data.toString())); + } + } + foreach (const QByteArray &parentIName, hash.keys()) { + // FIXME + insertBulkDataX(hash[parentIName]); + } + + foreach (const WatchData &data, list) { + if (data.isSomethingNeeded()) + m_engine->updateWatchData(data); + } + const int n = list.size(); +#if 0 + for (int i = 0; i != n; ++i) + insertData(list.at(i), false); + layoutChanged(); return; #endif // This method does not properly insert items in proper "iname sort - // order", leading to random removal of items in removeOutdated(); + // order". //qDebug() << "WMI:" << list.toString(); //static int bulk = 0; //foreach (const WatchItem &data, list) // qDebug() << "BULK: " << ++bulk << data.toString(); - QTC_ASSERT(!list.isEmpty(), return); + QTC_ASSERT(n > 0, return); QByteArray parentIName = parentName(list.at(0).iname); - WatchItem *parent = findItem(parentIName, m_root); + WatchItem *parent = m_handler->findItem(parentIName); if (!parent) { WatchData parent; parent.iname = parentIName; - insertData(parent); + insertDataItem(parent, true); MODEL_DEBUG("\nFIXING MISSING PARENT FOR\n" << list.at(0).iname); return; } - QModelIndex index = watchIndex(parent); + QModelIndex idx = watchIndex(parent); sortWatchDataAlphabetically = debuggerCore()->boolSetting(SortStructMembers); QMap<WatchDataSortKey, WatchData> newList; typedef QMap<WatchDataSortKey, WatchData>::iterator Iterator; - foreach (const WatchItem &data, list) - newList.insert(WatchDataSortKey(data), data); - if (newList.size() != list.size()) { - qDebug() << "LIST: "; - foreach (const WatchItem &data, list) - qDebug() << data.toString(); - qDebug() << "NEW LIST: "; - foreach (const WatchItem &data, newList) - qDebug() << data.toString(); - qDebug() << "P->CHILDREN: "; - foreach (const WatchItem *item, parent->children) - qDebug() << item->toString(); - qDebug() - << "P->CHILDREN.SIZE: " << parent->children.size() - << "NEWLIST SIZE: " << newList.size() - << "LIST SIZE: " << list.size(); - } + for (int i = 0; i != n; ++i) + newList.insert(WatchDataSortKey(list.at(i)), list.at(i)); + + //if (newList.size() != n) { + // qDebug() << "LIST: "; + // for (int i = 0; i != n; ++i) + // qDebug() << list.at(i).toString(); + // qDebug() << "NEW LIST: "; + // foreach (const WatchData &data, newList) + // qDebug() << data.toString(); + // qDebug() << "P->CHILDREN: "; + // foreach (const WatchItem *item, parent->children) + // qDebug() << item->toString(); + // qDebug() + // << "P->CHILDREN.SIZE: " << parent->children.size() + // << "NEWLIST SIZE: " << newList.size() + // << "LIST SIZE: " << list.size(); + //} QTC_ASSERT(newList.size() == list.size(), return); foreach (WatchItem *oldItem, parent->children) { @@ -1185,12 +1427,9 @@ void WatchModel::insertBulkData(const QList<WatchData> &list) Iterator it = newList.find(oldSortKey); if (it == newList.end()) { WatchData data = *oldItem; - data.generation = m_generationCounter; newList.insert(oldSortKey, data); } else { it->changed = it->hasChanged(*oldItem); - if (it->generation == -1) - it->generation = m_generationCounter; } } @@ -1206,9 +1445,7 @@ void WatchModel::insertBulkData(const QList<WatchData> &list) if (!parent->children[i]->isEqual(*it)) { qDebug() << "REPLACING" << parent->children.at(i)->iname << " WITH " << it->iname << it->generation; - parent->children[i]->setData(*it); - if (parent->children[i]->generation == -1) - parent->children[i]->generation = m_generationCounter; + m_handler->setData(parent->children[i], *it); //emit dataChanged(idx.sibling(i, 0), idx.sibling(i, 2)); } else { //qDebug() << "SKIPPING REPLACEMENT" << parent->children.at(i)->iname; @@ -1218,14 +1455,12 @@ void WatchModel::insertBulkData(const QList<WatchData> &list) // add new items if (oldCount < newList.size()) { - beginInsertRows(index, oldCount, newList.size() - 1); + beginInsertRows(idx, oldCount, newList.size() - 1); //MODEL_DEBUG("INSERT : " << data.iname << data.value); for (int i = oldCount; i < newList.size(); ++i, ++it) { - WatchItem *item = new WatchItem(*it); + WatchItem *item = m_handler->createItem(*it); qDebug() << "ADDING" << it->iname; item->parent = parent; - if (item->generation == -1) - item->generation = m_generationCounter; item->changed = true; parent->children.append(item); } @@ -1233,16 +1468,7 @@ void WatchModel::insertBulkData(const QList<WatchData> &list) } //qDebug() << "ITEMS: " << parent->children.size(); dump(); -} - -WatchItem *WatchModel::findItem(const QByteArray &iname, WatchItem *root) const -{ - if (root->iname == iname) - return root; - for (int i = root->children.size(); --i >= 0; ) - if (WatchItem *item = findItem(iname, root->children.at(i))) - return item; - return 0; +#endif } static void debugRecursion(QDebug &d, const WatchItem *item, int depth) @@ -1271,6 +1497,29 @@ void WatchModel::formatRequests(QByteArray *out, const WatchItem *item) const formatRequests(out, child); } +void WatchModel::showInEditorHelper(QString *contents, WatchItem *item, int depth) +{ + const QChar tab = QLatin1Char('\t'); + const QChar nl = QLatin1Char('\n'); + contents->append(QString(depth, tab)); + contents->append(item->name); + contents->append(tab); + contents->append(item->value); + contents->append(tab); + contents->append(item->type); + contents->append(nl); + foreach (WatchItem *child, item->children) + showInEditorHelper(contents, child, depth + 1); +} + +void WatchModel::setCurrentItem(const QByteArray &iname) +{ + if (WatchItem *item = findItem(iname)) { + QModelIndex idx = watchIndex(item); + emit currentIndexRequested(idx); + } +} + /////////////////////////////////////////////////////////////////////// // // WatchHandler @@ -1280,92 +1529,39 @@ void WatchModel::formatRequests(QByteArray *out, const WatchItem *item) const WatchHandler::WatchHandler(DebuggerEngine *engine) { m_engine = engine; - m_inChange = false; m_watcherCounter = debuggerCore()->sessionValue(QLatin1String("Watchers")) .toStringList().count(); - - m_return = new WatchModel(this, ReturnWatch); - m_locals = new WatchModel(this, LocalsWatch); - m_watchers = new WatchModel(this, WatchersWatch); - m_tooltips = new WatchModel(this, TooltipsWatch); - m_inspect = new WatchModel(this, InspectWatch); - + m_model = new WatchModel(this); m_contentsValid = false; + m_contentsValid = true; // FIXME m_resetLocationScheduled = false; - - connect(debuggerCore()->action(SortStructMembers), SIGNAL(valueChanged(QVariant)), - SLOT(reinsertAllData())); - connect(debuggerCore()->action(ShowStdNamespace), SIGNAL(valueChanged(QVariant)), - SLOT(reinsertAllData())); - connect(debuggerCore()->action(ShowQtNamespace), SIGNAL(valueChanged(QVariant)), - SLOT(reinsertAllData())); -} - -void WatchHandler::beginCycle(bool fullCycle) -{ - m_return->beginCycle(fullCycle); - m_locals->beginCycle(fullCycle); - m_watchers->beginCycle(fullCycle); - m_tooltips->beginCycle(fullCycle); - // don't sync m_inspect here: It's updated on it's own -} - -void WatchHandler::endCycle() -{ - m_return->endCycle(); - m_locals->endCycle(); - m_watchers->endCycle(); - m_tooltips->endCycle(); - - m_contentsValid = true; - m_resetLocationScheduled = false; - - updateWatchersWindow(); } -void WatchHandler::beginCycle(WatchType type, bool fullCycle) +WatchHandler::~WatchHandler() { - model(type)->beginCycle(fullCycle); -} - -void WatchHandler::endCycle(WatchType type) -{ - model(type)->endCycle(); + // Do it manually to prevent calling back in model destructors + // after m_cache is destroyed. + delete m_model; + m_model = 0; } void WatchHandler::cleanup() { - m_expandedINames.clear(); + m_model->m_expandedINames.clear(); theWatcherNames.remove(QByteArray()); - m_return->reinitialize(); - m_locals->reinitialize(); - m_tooltips->reinitialize(); - m_inspect->reinitialize(); - m_return->m_fetchTriggered.clear(); - m_locals->m_fetchTriggered.clear(); - m_watchers->m_fetchTriggered.clear(); - m_tooltips->m_fetchTriggered.clear(); - m_inspect->m_fetchTriggered.clear(); + m_model->reinitialize(); + m_model->m_fetchTriggered.clear(); #if 1 - for (EditHandlers::ConstIterator it = m_editHandlers.begin(); - it != m_editHandlers.end(); ++it) { + for (WatchModel::EditHandlers::ConstIterator it = m_model->m_editHandlers.begin(); + it != m_model->m_editHandlers.end(); ++it) { if (!it.value().isNull()) delete it.value(); } - m_editHandlers.clear(); + m_model->m_editHandlers.clear(); #endif } -void WatchHandler::emitAllChanged() -{ - m_return->emitAllChanged(); - m_locals->emitAllChanged(); - m_watchers->emitAllChanged(); - m_tooltips->emitAllChanged(); - m_inspect->emitAllChanged(); -} - -void WatchHandler::insertData(const WatchData &data) +void WatchHandler::insertIncompleteData(const WatchData &data) { MODEL_DEBUG("INSERTDATA: " << data.toString()); if (!data.isValid()) { @@ -1374,14 +1570,10 @@ void WatchHandler::insertData(const WatchData &data) return; } - if (data.isSomethingNeeded() && data.iname.contains(".")) { + if (data.isSomethingNeeded() && data.iname.contains('.')) { MODEL_DEBUG("SOMETHING NEEDED: " << data.toString()); - if (!m_engine->isSynchronous() - || data.isInspect()) { - WatchModel *model = modelForIName(data.iname); - QTC_ASSERT(model, return); - model->insertData(data); - + if (!m_engine->isSynchronous() || data.isInspect()) { + m_model->insertDataItem(data); m_engine->updateWatchData(data); } else { m_engine->showMessage(QLatin1String("ENDLESS LOOP: SOMETHING NEEDED: ") @@ -1390,71 +1582,47 @@ void WatchHandler::insertData(const WatchData &data) data1.setAllUnneeded(); data1.setValue(QLatin1String("<unavailable synchronous data>")); data1.setHasChildren(false); - WatchModel *model = modelForIName(data.iname); - QTC_ASSERT(model, return); - model->insertData(data1); + m_model->insertDataItem(data1); } } else { - WatchModel *model = modelForIName(data.iname); - QTC_ASSERT(model, return); MODEL_DEBUG("NOTHING NEEDED: " << data.toString()); - model->insertData(data); + m_model->insertDataItem(data); showEditValue(data); } } -void WatchHandler::reinsertAllData() +void WatchHandler::insertData(const WatchData &data) { - m_locals->reinsertAllData(); - m_watchers->reinsertAllData(); - m_tooltips->reinsertAllData(); - m_return->reinsertAllData(); - m_inspect->reinsertAllData(); + QList<WatchData> list; + list.append(data); + insertData(list); } -// Bulk-insertion -void WatchHandler::insertBulkData(const QList<WatchData> &list) +void WatchHandler::insertData(const QList<WatchData> &list) { -#if 1 - foreach (const WatchItem &data, list) - insertData(data); - return; -#endif - - if (list.isEmpty()) - return; - QMap<QByteArray, QList<WatchData> > hash; + m_model->insertBulkData(list); - foreach (const WatchData &data, list) { - // we insert everything, including incomplete stuff - // to reduce the number of row add operations in the model. - if (data.isValid()) { - hash[parentName(data.iname)].append(data); - } else { - qWarning("%s:%d: Attempt to bulk-insert invalid watch item: %s", - __FILE__, __LINE__, qPrintable(data.toString())); - } - } - foreach (const QByteArray &parentIName, hash.keys()) { - WatchModel *model = modelForIName(parentIName); - QTC_ASSERT(model, return); - model->insertBulkData(hash[parentIName]); - } + m_contentsValid = true; + updateWatchersWindow(); +} - foreach (const WatchData &data, list) { - if (data.isSomethingNeeded()) - m_engine->updateWatchData(data); - } +void WatchHandler::removeAllData() +{ + m_model->reinitialize(); } void WatchHandler::removeData(const QByteArray &iname) { - WatchModel *model = modelForIName(iname); - if (!model) - return; - WatchItem *item = model->findItem(iname, model->m_root); + WatchItem *item = m_model->findItem(iname); + if (item) + m_model->destroyItem(item); +} + +void WatchHandler::removeChildren(const QByteArray &iname) +{ + WatchItem *item = m_model->findItem(iname); if (item) - model->destroyItem(item); + m_model->destroyChildren(item); } QByteArray WatchHandler::watcherName(const QByteArray &exp) @@ -1483,14 +1651,13 @@ void WatchHandler::watchExpression(const QString &exp) data.setAllUnneeded(); data.setValue(QString(QLatin1Char(' '))); data.setHasChildren(false); - insertData(data); + insertIncompleteData(data); } else if (m_engine->isSynchronous()) { m_engine->updateWatchData(data); } else { - insertData(data); + insertIncompleteData(data); } updateWatchersWindow(); - emitAllChanged(); } static void swapEndian(char *d, int nchar) @@ -1509,9 +1676,9 @@ static void swapEndian(char *d, int nchar) void WatchHandler::showEditValue(const WatchData &data) { const QByteArray key = data.address ? data.hexAddress() : data.iname; - QObject *w = m_editHandlers.value(key); + QObject *w = m_model->m_editHandlers.value(key); if (data.editformat == 0x0) { - m_editHandlers.remove(data.iname); + m_model->m_editHandlers.remove(data.iname); delete w; } else if (data.editformat == 1 || data.editformat == 3) { // QImage @@ -1524,7 +1691,7 @@ void WatchHandler::showEditValue(const WatchData &data) QLatin1String(data.hexAddress())) : tr("%1 Object at Unknown Address").arg(QLatin1String(data.type)); l->setWindowTitle(title); - m_editHandlers[key] = l; + m_model->m_editHandlers[key] = l; } int width, height, format; QByteArray ba; @@ -1563,7 +1730,7 @@ void WatchHandler::showEditValue(const WatchData &data) if (!t) { delete w; t = new QTextEdit; - m_editHandlers[key] = t; + m_model->m_editHandlers[key] = t; } QByteArray ba = QByteArray::fromHex(data.editvalue); QString str = QString::fromUtf16((ushort *)ba.constData(), ba.size()/2); @@ -1580,7 +1747,7 @@ void WatchHandler::showEditValue(const WatchData &data) p = new QProcess; p->start(QLatin1String(cmd)); p->waitForStarted(); - m_editHandlers[key] = p; + m_model->m_editHandlers[key] = p; } p->write(input + '\n'); } else { @@ -1592,13 +1759,10 @@ void WatchHandler::clearWatches() { if (theWatcherNames.isEmpty()) return; - const QList<WatchItem *> watches = m_watchers->rootItem()->children; - for (int i = watches.size() - 1; i >= 0; i--) - m_watchers->destroyItem(watches.at(i)); + m_model->destroyChildren(m_model->m_watchRoot); theWatcherNames.clear(); m_watcherCounter = 0; updateWatchersWindow(); - emitAllChanged(); saveWatchers(); } @@ -1607,12 +1771,12 @@ void WatchHandler::removeWatchExpression(const QString &exp0) QByteArray exp = exp0.toLatin1(); MODEL_DEBUG("REMOVE WATCH: " << exp); theWatcherNames.remove(exp); - foreach (WatchItem *item, m_watchers->rootItem()->children) { + + foreach (WatchItem *item, m_model->m_watchRoot->children) { if (item->exp == exp) { - m_watchers->destroyItem(item); + m_model->destroyItem(item); saveWatchers(); updateWatchersWindow(); - emitAllChanged(); break; } } @@ -1621,7 +1785,15 @@ void WatchHandler::removeWatchExpression(const QString &exp0) void WatchHandler::updateWatchersWindow() { // Force show/hide of watchers and return view. - debuggerCore()->updateWatchersWindow(); + static int previousShowWatch = -1; + static int previousShowReturn = -1; + int showWatch = !m_model->m_watchRoot->children.isEmpty(); + int showReturn = !m_model->m_returnRoot->children.isEmpty(); + if (showWatch == previousShowWatch && showReturn == previousShowReturn) + return; + previousShowWatch = showWatch; + previousShowReturn = showReturn; + debuggerCore()->updateWatchersWindow(showWatch, showReturn); } QStringList WatchHandler::watchedExpressions() @@ -1684,18 +1856,14 @@ void WatchHandler::loadSessionData() theWatcherNames.clear(); m_watcherCounter = 0; QVariant value = debuggerCore()->sessionValue(QLatin1String("Watchers")); - foreach (WatchItem *item, m_watchers->rootItem()->children) - m_watchers->destroyItem(item); + m_model->destroyChildren(m_model->m_watchRoot); foreach (const QString &exp, value.toStringList()) watchExpression(exp); - updateWatchersWindow(); - emitAllChanged(); } void WatchHandler::updateWatchers() { - foreach (WatchItem *item, m_watchers->rootItem()->children) - m_watchers->destroyItem(item); + m_model->destroyChildren(m_model->m_watchRoot); // Copy over all watchers and mark all watchers as incomplete. foreach (const QByteArray &exp, theWatcherNames.keys()) { WatchData data; @@ -1703,67 +1871,33 @@ void WatchHandler::updateWatchers() data.setAllNeeded(); data.name = QLatin1String(exp); data.exp = exp; - insertData(data); + insertIncompleteData(data); } } -WatchModel *WatchHandler::model(WatchType type) const +QAbstractItemModel *WatchHandler::model() const { - switch (type) { - case ReturnWatch: return m_return; - case LocalsWatch: return m_locals; - case WatchersWatch: return m_watchers; - case TooltipsWatch: return m_tooltips; - case InspectWatch: return m_inspect; - } - QTC_CHECK(false); - return 0; + return m_model; } -WatchModel *WatchHandler::modelForIName(const QByteArray &iname) const +const WatchData *WatchHandler::watchData(const QModelIndex &idx) const { - if (iname.startsWith("return")) - return m_return; - if (iname.startsWith("local")) - return m_locals; - if (iname.startsWith("tooltip")) - return m_tooltips; - if (iname.startsWith("watch")) - return m_watchers; - if (iname.startsWith("inspect")) - return m_inspect; - QTC_ASSERT(false, qDebug() << "INAME: " << iname); - return 0; + return m_model->watchItem(idx); } -const WatchData *WatchHandler::watchData(WatchType type, const QModelIndex &index) const +const WatchData *WatchHandler::findData(const QByteArray &iname) const { - if (index.isValid()) - if (const WatchModel *m = model(type)) - return m->watchItem(index); - return 0; -} - -const WatchData *WatchHandler::findItem(const QByteArray &iname) const -{ - const WatchModel *model = modelForIName(iname); - QTC_ASSERT(model, return 0); - return model->findItem(iname, model->m_root); + return m_model->findItem(iname); } QString WatchHandler::displayForAutoTest(const QByteArray &iname) const { - const WatchModel *model = modelForIName(iname); - QTC_ASSERT(model, return QString()); - return model->displayForAutoTest(iname); + return m_model->displayForAutoTest(iname); } -QModelIndex WatchHandler::itemIndex(const QByteArray &iname) const +bool WatchHandler::hasItem(const QByteArray &iname) const { - if (const WatchModel *model = modelForIName(iname)) - if (WatchItem *item = model->findItem(iname, model->m_root)) - return model->watchIndex(item); - return QModelIndex(); + return m_model->findItem(iname); } void WatchHandler::setFormat(const QByteArray &type0, int format) @@ -1774,17 +1908,13 @@ void WatchHandler::setFormat(const QByteArray &type0, int format) else theTypeFormats[type] = format; saveTypeFormats(); - m_return->emitDataChanged(1); - m_locals->emitDataChanged(1); - m_watchers->emitDataChanged(1); - m_tooltips->emitDataChanged(1); - m_inspect->emitDataChanged(1); + m_model->emitDataChanged(1); } int WatchHandler::format(const QByteArray &iname) const { int result = -1; - if (const WatchData *item = findItem(iname)) { + if (const WatchData *item = m_model->findItem(iname)) { int result = theIndividualFormats.value(item->iname, -1); if (result == -1) result = theTypeFormats.value(stripForFormat(item->type), -1); @@ -1795,10 +1925,9 @@ int WatchHandler::format(const QByteArray &iname) const QByteArray WatchHandler::expansionRequests() const { QByteArray ba; - //m_locals->formatRequests(&ba, m_locals->m_root); - //m_watchers->formatRequests(&ba, m_watchers->m_root); - if (!m_expandedINames.isEmpty()) { - QSetIterator<QByteArray> jt(m_expandedINames); + m_model->formatRequests(&ba, m_model->m_root); + if (!m_model->m_expandedINames.isEmpty()) { + QSetIterator<QByteArray> jt(m_model->m_expandedINames); while (jt.hasNext()) { QByteArray iname = jt.next(); ba.append(iname); @@ -1845,67 +1974,43 @@ QByteArray WatchHandler::individualFormatRequests() const void WatchHandler::addTypeFormats(const QByteArray &type, const QStringList &formats) { - m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats); + m_model->m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats); } QString WatchHandler::editorContents() { QString contents; - showInEditorHelper(&contents, m_locals->m_root, 0); - showInEditorHelper(&contents, m_watchers->m_root, 0); + m_model->showInEditorHelper(&contents, m_model->m_root, 0); return contents; } -void WatchHandler::showInEditorHelper(QString *contents, WatchItem *item, int depth) -{ - const QChar tab = QLatin1Char('\t'); - const QChar nl = QLatin1Char('\n'); - contents->append(QString(depth, tab)); - contents->append(item->name); - contents->append(tab); - contents->append(item->value); - contents->append(tab); - contents->append(item->type); - contents->append(nl); - foreach (WatchItem *child, item->children) - showInEditorHelper(contents, child, depth + 1); -} - void WatchHandler::removeTooltip() { - m_tooltips->reinitialize(); - m_tooltips->emitAllChanged(); + m_model->destroyChildren(m_model->m_tooltipRoot); } void WatchHandler::rebuildModel() { - beginCycle(); - - const QList<WatchItem *> watches = m_watchers->rootItem()->children; - for (int i = watches.size() - 1; i >= 0; i--) - m_watchers->destroyItem(watches.at(i)); - - foreach (const QString &exp, watchedExpressions()) { - WatchData data; - data.exp = exp.toLatin1(); - data.name = exp; - data.iname = watcherName(data.exp); - data.setAllUnneeded(); - - insertData(data); - } +// m_model->destroyChildren(m_model->m_watchRoot); - endCycle(); +// foreach (const QString &exp, watchedExpressions()) { +// WatchData data; +// data.exp = exp.toLatin1(); +// data.name = exp; +// data.iname = watcherName(data.exp); +// data.setAllUnneeded(); +// insertIncompleteData(data); +// } } void WatchHandler::setTypeFormats(const TypeFormats &typeFormats) { - m_reportedTypeFormats = typeFormats; + m_model->m_reportedTypeFormats = typeFormats; } TypeFormats WatchHandler::typeFormats() const { - return m_reportedTypeFormats; + return m_model->m_reportedTypeFormats; } void WatchHandler::editTypeFormats(bool includeLocals, const QByteArray &iname) @@ -1914,11 +2019,11 @@ void WatchHandler::editTypeFormats(bool includeLocals, const QByteArray &iname) TypeFormatsDialog dlg(0); //QHashIterator<QString, QStringList> it(m_reportedTypeFormats); - QList<QString> l = m_reportedTypeFormats.keys(); + QList<QString> l = m_model->m_reportedTypeFormats.keys(); qSort(l.begin(), l.end()); foreach (const QString &ba, l) { int f = iname.isEmpty() ? -1 : format(iname); - dlg.addTypeFormats(ba, m_reportedTypeFormats.value(ba), f); + dlg.addTypeFormats(ba, m_model->m_reportedTypeFormats.value(ba), f); } if (dlg.exec()) setTypeFormats(dlg.typeFormats()); @@ -1927,6 +2032,7 @@ void WatchHandler::editTypeFormats(bool includeLocals, const QByteArray &iname) void WatchHandler::scheduleResetLocation() { m_contentsValid = false; + //m_contentsValid = true; // FIXME m_resetLocationScheduled = true; } @@ -1934,26 +2040,19 @@ void WatchHandler::resetLocation() { if (m_resetLocationScheduled) { m_resetLocationScheduled = false; - m_return->invalidateAll(); - m_locals->invalidateAll(); - m_watchers->invalidateAll(); - m_tooltips->invalidateAll(); - m_inspect->invalidateAll(); + //m_model->invalidateAll(); FIXME } } bool WatchHandler::isValidToolTip(const QByteArray &iname) const { - WatchItem *item = m_tooltips->findItem(iname, m_tooltips->m_root); + WatchItem *item = m_model->findItem(iname); return item && !item->type.trimmed().isEmpty(); } -void WatchHandler::setCurrentModelIndex(WatchType modelType, - const QModelIndex &index) +void WatchHandler::setCurrentItem(const QByteArray &iname) { - if (WatchModel *m = model(modelType)) { - emit m->setCurrentIndex(index); - } + m_model->setCurrentItem(iname); } QHash<QByteArray, int> WatchHandler::watcherNames() @@ -1961,5 +2060,28 @@ QHash<QByteArray, int> WatchHandler::watcherNames() return theWatcherNames; } +void WatchHandler::setUnprintableBase(int base) +{ + theUnprintableBase = base; + m_model->emitAllChanged(); +} + +int WatchHandler::unprintableBase() +{ + return theUnprintableBase; +} + +bool WatchHandler::isExpandedIName(const QByteArray &iname) const +{ + return m_model->m_expandedINames.contains(iname); +} + +QSet<QByteArray> WatchHandler::expandedINames() const +{ + return m_model->m_expandedINames; +} + } // namespace Internal } // namespace Debugger + +#include "watchhandler.moc" |