diff options
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 c9ada1d5b3..77bc4f9db5 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" |