diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index abe3b3cb8c01c878c3e86ab0fa40f0968ce586f1..8296d3f74e3080b0750a2b9eb7208d3bb53f9edb 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -479,6 +479,23 @@ QString niceType(QString type) return type; } +static QString formattedValue(const WatchData &data, + int individualFormat, int typeFormat) +{ + if (data.type == "int") { + int format = individualFormat == -1 ? typeFormat : individualFormat; + int value = data.value.toInt(); + if (format == 1) + return ("(hex) ") + QString::number(value, 16); + if (format == 2) + return ("(bin) ") + QString::number(value, 2); + if (format == 3) + return ("(oct) ") + QString::number(value, 8); + } + + return data.value; +} + bool WatchModel::canFetchMore(const QModelIndex &index) const { return index.isValid() && !watchItem(index)->fetchTriggered; @@ -573,6 +590,18 @@ QModelIndex WatchModel::watchIndexHelper(const WatchItem *needle, return QModelIndex(); } +void WatchModel::emitDataChanged(int column, const QModelIndex &parentIndex) +{ + QModelIndex idx1 = index(0, column, parentIndex); + QModelIndex idx2 = index(rowCount(parentIndex) - 1, column, parentIndex); + if (idx1.isValid() && idx2.isValid()) + emit dataChanged(idx1, idx2); + //qDebug() << "CHANGING:\n" << idx1 << "\n" << idx2 << "\n" + // << data(parentIndex, INameRole).toString(); + for (int i = rowCount(parentIndex); --i >= 0; ) + emitDataChanged(column, index(i, 0, parentIndex)); +} + QVariant WatchModel::data(const QModelIndex &idx, int role) const { const WatchItem &data = *watchItem(idx); @@ -581,7 +610,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case Qt::DisplayRole: { switch (idx.column()) { case 0: return data.name; - case 1: return data.value; + case 1: return formattedValue(data, + m_handler->m_individualFormats[data.iname], + m_handler->m_typeFormats[data.type]); case 2: return niceType(data.type); default: break; } @@ -616,7 +647,23 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case ActiveDataRole: qDebug() << "ASK FOR" << data.iname; return true; - + + case TypeFormatListRole: + if (data.type == "int") + return QStringList() << tr("decimal") << tr("hexadecimal") + << tr("binary") << tr("octal"); + break; + + case TypeFormatRole: + return m_handler->m_typeFormats[data.type]; + + case IndividualFormatRole: { + int format = m_handler->m_individualFormats[data.iname]; + if (format == -1) + return m_handler->m_typeFormats[data.type]; + return format; + } + default: break; } @@ -625,12 +672,16 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role) { + WatchItem &data = *watchItem(index); if (role == ExpandedRole) { - QString iname = data(index, INameRole).toString(); if (value.toBool()) - m_handler->m_expandedINames.insert(iname); + m_handler->m_expandedINames.insert(data.iname); else - m_handler->m_expandedINames.remove(iname); + m_handler->m_expandedINames.remove(data.iname); + } else if (role == TypeFormatRole) { + m_handler->setFormat(data.type, value.toInt()); + } else if (role == IndividualFormatRole) { + m_handler->m_individualFormats[data.iname] = value.toInt(); } emit dataChanged(index, index); return true; @@ -773,66 +824,6 @@ void WatchHandler::endCycle() m_locals->removeOutdated(); m_watchers->removeOutdated(); m_tooltips->removeOutdated(); - -/* - if (m_inChange) { - MODEL_DEBUG("RECREATE MODEL IGNORED, CURRENT SET:\n" << toString()); - return; - } - - #ifdef DEBUG_PENDING - MODEL_DEBUG("RECREATE MODEL, CURRENT SET:\n" << toString()); - #endif - - QHash<QString, int> oldTopINames; - QHash<QString, QString> oldValues; - for (int i = 0, n = m_oldSet.size(); i != n; ++i) { - WatchData &data = m_oldSet[i]; - oldValues[data.iname] = data.value; - if (data.level == 2) - ++oldTopINames[data.iname]; - } - #ifdef DEBUG_PENDING - MODEL_DEBUG("OLD VALUES: " << oldValues); - #endif - - for (int i = m_completeSet.size(); --i >= 0; ) { - WatchData &data = m_completeSet[i]; - data.level = data.iname.isEmpty() ? 0 : data.iname.count('.') + 1; - data.childIndex.clear(); - } - - qSort(m_completeSet.begin(), m_completeSet.end(), &iNameSorter); - - // Possibly append dummy items to prevent empty views - bool ok = true; - - if (ok) { - for (int i = 1; i <= 3; ++i) { - WatchData &data = m_displaySet[i]; - if (data.childIndex.size() == 0) { - WatchData dummy; - dummy.state = 0; - dummy.row = 0; - if (i == 1) { - dummy.iname = QLatin1String("local.dummy"); - dummy.name = tr("<No Locals>"); - } else if (i == 2) { - dummy.iname = QLatin1String("tooltip.dummy"); - dummy.name = tr("<No Tooltip>"); - } else { - dummy.iname = QLatin1String("watch.dummy"); - dummy.name = tr("<No Watchers>"); - } - dummy.level = 2; - dummy.parentIndex = i; - dummy.childCount = 0; - data.childIndex.append(m_displaySet.size()); - m_displaySet.append(dummy); - } - } - } -*/ } void WatchHandler::cleanup() @@ -1020,17 +1011,19 @@ void WatchHandler::loadWatchers() sessionValueRequested("Watchers", &value); foreach (const QString &exp, value.toStringList()) m_watcherNames[exp] = watcherCounter++; + //qDebug() << "LOAD WATCHERS: " << m_watchers; //reinitializeWatchersHelper(); } void WatchHandler::saveWatchers() { - //qDebug() << "SAVE WATCHERS: " << m_watchers.keys(); + //qDebug() << "SAVE WATCHERS: " << m_watchers; // Filter out valid watchers. QStringList watcherNames; - const QHash<QString, int>::const_iterator cend = m_watcherNames.constEnd(); - for (QHash<QString, int>::const_iterator it = m_watcherNames.constBegin(); it != cend; ++it) { + QHashIterator<QString, int> it(m_watcherNames); + while (it.hasNext()) { + it.next(); const QString &watcherName = it.key(); if (!watcherName.isEmpty() && watcherName != watcherEditPlaceHolder()) watcherNames.push_back(watcherName); @@ -1038,14 +1031,42 @@ void WatchHandler::saveWatchers() setSessionValueRequested("Watchers", QVariant(watcherNames)); } +void WatchHandler::loadTypeFormats() +{ + QVariant value; + sessionValueRequested("DefaultFormats", &value); + QMap<QString, QVariant> typeFormats = value.toMap(); + QMapIterator<QString, QVariant> it(typeFormats); + while (it.hasNext()) { + it.next(); + if (!it.key().isEmpty()) + m_typeFormats.insert(it.key(), it.value().toInt()); + } +} + +void WatchHandler::saveTypeFormats() +{ + QMap<QString, QVariant> typeFormats; + QHashIterator<QString, int> it(m_typeFormats); + while (it.hasNext()) { + it.next(); + QString key = it.key().trimmed(); + if (!key.isEmpty()) + typeFormats.insert(key, it.value()); + } + setSessionValueRequested("DefaultFormats", QVariant(typeFormats)); +} + void WatchHandler::saveSessionData() { saveWatchers(); + saveTypeFormats(); } void WatchHandler::loadSessionData() { loadWatchers(); + loadTypeFormats(); foreach (const QString &exp, m_watcherNames.keys()) { WatchData data; data.iname = watcherName(exp); @@ -1092,5 +1113,14 @@ QString WatchHandler::watcherEditPlaceHolder() return rc; } +void WatchHandler::setFormat(const QString &type, int format) +{ + m_typeFormats[type] = format; + saveTypeFormats(); + m_locals->emitDataChanged(1); + m_watchers->emitDataChanged(1); + m_tooltips->emitDataChanged(1); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 2ee1cb10746aed776bbc12e1377c2996d911bdb2..b9be24b4ba3fd85f55ca45fcda1000d6555bcbd0 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -139,8 +139,11 @@ enum WatchRoles { INameRole = Qt::UserRole, ExpressionRole, - ExpandedRole, + ExpandedRole, // used to communicate prefered expanded state to the view ActiveDataRole, // used for tooltip + TypeFormatListRole, + TypeFormatRole, // used to communicate alternative formats to the view + IndividualFormatRole }; class WatchModel : public QAbstractItemModel @@ -180,6 +183,9 @@ private: void removeItem(WatchItem *item); void setActiveData(const QString &data) { m_activeData = data; } + void emitDataChanged(int column, + const QModelIndex &parentIndex = QModelIndex()); + private: WatchHandler *m_handler; WatchType m_type; @@ -234,6 +240,10 @@ private: void loadWatchers(); void saveWatchers(); + void loadTypeFormats(); + void saveTypeFormats(); + void setFormat(const QString &type, int format); + bool m_expandPointers; bool m_inChange; @@ -242,6 +252,8 @@ private: QHash<QString, int> m_watcherNames; QString watcherName(const QString &exp); + QHash<QString, int> m_typeFormats; + QHash<QString, int> m_individualFormats; void setDisplayedIName(const QString &iname, bool on); QSet<QString> m_expandedINames; // those expanded in the treeview diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index feab5a2989cb9350b886587d8836978f5116cc01..57946b807e58fda2476938b937f614f36f376b41 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -199,30 +199,65 @@ void WatchWindow::dropEvent(QDropEvent *ev) void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) { + QModelIndex idx = indexAt(ev->pos()); + QModelIndex mi0 = idx.sibling(idx.row(), 0); + QModelIndex mi1 = idx.sibling(idx.row(), 1); + QModelIndex mi2 = idx.sibling(idx.row(), 2); + QString exp = model()->data(mi0).toString(); + QString type = model()->data(mi2).toString(); + + QStringList alternativeFormats = + model()->data(mi0, TypeFormatListRole).toStringList(); + int typeFormat = + model()->data(mi0, TypeFormatRole).toInt(); + int individualFormat = + model()->data(mi0, IndividualFormatRole).toInt(); + + QMenu typeFormatMenu(tr("Change format for type '%1'").arg(type)); + QMenu individualFormatMenu(tr("Change format for expression '%1'").arg(exp)); + QList<QAction *> typeFormatActions; + QList<QAction *> individualFormatActions; + for (int i = 0; i != alternativeFormats.size(); ++i) { + const QString format = alternativeFormats.at(i); + QAction *act = new QAction(format, &typeFormatMenu); + act->setCheckable(true); + if (i == typeFormat) + act->setChecked(true); + typeFormatMenu.addAction(act); + typeFormatActions.append(act); + act = new QAction(format, &individualFormatMenu); + act->setCheckable(true); + if (i == individualFormat) + act->setChecked(true); + individualFormatMenu.addAction(act); + individualFormatActions.append(act); + } + //typeFormatMenu.setActive(!alternativeFormats.isEmpty()); + //individualFormatMenu.setActive(!alternativeFormats.isEmpty()); + QMenu menu; QAction *act1 = new QAction(tr("Adjust column widths to contents"), &menu); QAction *act2 = new QAction(tr("Always adjust column widths to contents"), &menu); + act2->setCheckable(true); act2->setChecked(m_alwaysResizeColumnsToContents); - menu.addAction(act1); - menu.addAction(act2); - - QModelIndex idx = indexAt(ev->pos()); - QModelIndex mi0 = idx.sibling(idx.row(), 0); - QString exp = model()->data(mi0).toString(); - - menu.addSeparator(); - int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression; - menu.addAction(theDebuggerAction(type)->updatedAction(exp)); - //QAction *act4 = theDebuggerAction(WatchExpressionInWindow); //menu.addAction(act4); QAction *act3 = new QAction(tr("Insert new watch item"), &menu); - menu.addAction(act3); QAction *act4 = new QAction(tr("Select widget to watch"), &menu); + + menu.addAction(act1); + menu.addAction(act2); + menu.addSeparator(); + int atype = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression; + menu.addAction(theDebuggerAction(atype)->updatedAction(exp)); + + menu.addAction(act3); menu.addAction(act4); + menu.addMenu(&typeFormatMenu); + menu.addMenu(&individualFormatMenu); menu.addSeparator(); menu.addAction(theDebuggerAction(RecheckDebuggingHelpers)); @@ -232,16 +267,23 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *act = menu.exec(ev->globalPos()); - if (act == act1) + if (act == act1) { resizeColumnsToContents(); - else if (act == act2) + } else if (act == act2) { setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents); - else if (act == act3) + } else if (act == act3) { theDebuggerAction(WatchExpression) ->trigger(WatchHandler::watcherEditPlaceHolder()); - else if (act == act4) { + } else if (act == act4) { grabMouse(Qt::CrossCursor); m_grabbing = true; + } else { + for (int i = 0; i != alternativeFormats.size(); ++i) { + if (act == typeFormatActions.at(i)) + model()->setData(mi1, i, TypeFormatRole); + else if (act == individualFormatActions.at(i)) + model()->setData(mi1, i, IndividualFormatRole); + } } }