From 7e148d8a079218ac904a5d9448b5d1e5f60341ba Mon Sep 17 00:00:00 2001 From: zarelaky Date: Mon, 8 Jul 2019 13:45:48 +0800 Subject: [PATCH] Debugger: Allow changing item format for all array elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I05000102d4c6b185340581029006b9254c91fcb1 Reviewed-by: Leena Miettinen Reviewed-by: André Hartmann --- src/plugins/debugger/watchhandler.cpp | 106 ++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index a254036bf12..91dcf126c04 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -397,6 +397,7 @@ public: class WatchModel : public WatchModelBase { Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::WatchModel) + typedef QSet WatchItemSet; public: WatchModel(WatchHandler *handler, DebuggerEngine *engine); @@ -446,9 +447,13 @@ public: void grabWidget(); void ungrabWidget(); void timerEvent(QTimerEvent *event) override; - int m_grabWidgetTimerId = -1; +private: + QMenu *createFormatMenuForManySelected(const WatchItemSet &item, QWidget *parent); + void setItemsFormat(const WatchItemSet &items, const DisplayFormat &format); + void addCharsPrintableMenu(QMenu *menu); public: + int m_grabWidgetTimerId = -1; WatchHandler *m_handler; // Not owned. DebuggerEngine *m_engine; // Not owned. @@ -1673,7 +1678,17 @@ bool WatchModel::contextMenuEvent(const ItemViewEvent &ev) [this] { grabWidget(); }); menu->addSeparator(); - menu->addMenu(createFormatMenu(item, menu)); + QModelIndexList mil = ev.currentOrSelectedRows(); + if (mil.size() > 1) { + WatchItemSet wis; + for (const QModelIndex &i : mil) + wis.insert(itemForIndex(i)); + + menu->addMenu(createFormatMenuForManySelected(wis, menu)); + } else { + menu->addMenu(createFormatMenu(item, menu)); + } + menu->addMenu(createMemoryMenu(item, menu)); menu->addMenu(createBreakpointMenu(item, menu)); menu->addSeparator(); @@ -1835,6 +1850,20 @@ QMenu *WatchModel::createMemoryMenu(WatchItem *item, QWidget *parent) return menu; } +void WatchModel::addCharsPrintableMenu(QMenu *menu) +{ + auto addBaseChangeAction = [this, menu](const QString &text, int base) { + addCheckableAction(menu, text, true, theUnprintableBase == base, [this, base] { + theUnprintableBase = base; + emit layoutChanged(); // FIXME + }); + }; + addBaseChangeAction(tr("Treat All Characters as Printable"), 0); + addBaseChangeAction(tr("Show Unprintable Characters as Escape Sequences"), -1); + addBaseChangeAction(tr("Show Unprintable Characters as Octal"), 8); + addBaseChangeAction(tr("Show Unprintable Characters as Hexadecimal"), 16); +} + QMenu *WatchModel::createFormatMenu(WatchItem *item, QWidget *parent) { auto menu = new QMenu(tr("Change Value Display Format"), parent); @@ -1849,17 +1878,7 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item, QWidget *parent) const int typeFormat = theTypeFormats.value(stripForFormat(item->type), AutomaticFormat); const int individualFormat = theIndividualFormats.value(iname, AutomaticFormat); - auto addBaseChangeAction = [this, menu](const QString &text, int base) { - addCheckableAction(menu, text, true, theUnprintableBase == base, [this, base] { - theUnprintableBase = base; - emit layoutChanged(); // FIXME - }); - }; - - addBaseChangeAction(tr("Treat All Characters as Printable"), 0); - addBaseChangeAction(tr("Show Unprintable Characters as Escape Sequences"), -1); - addBaseChangeAction(tr("Show Unprintable Characters as Octal"), 8); - addBaseChangeAction(tr("Show Unprintable Characters as Hexadecimal"), 16); + addCharsPrintableMenu(menu); const QString spacer = " "; menu->addSeparator(); @@ -1911,6 +1930,67 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item, QWidget *parent) return menu; } +void WatchModel::setItemsFormat(const WatchItemSet &items, const DisplayFormat &format) +{ + if (format == AutomaticFormat) { + for (WatchItem *item : items) + theIndividualFormats.remove(item->iname); + } else { + for (WatchItem *item : items) + theIndividualFormats[item->iname] = format; + } + saveFormats(); +} + +QMenu *WatchModel::createFormatMenuForManySelected(const WatchItemSet &items, QWidget *parent) +{ + auto menu = new QMenu(tr("Change Display Format for Selected Values"), parent); + + addCharsPrintableMenu(menu); + + QHash allItemsFormats; + for (WatchItem *item : items) { + const DisplayFormats alternativeFormats = typeFormatList(item); + for (const DisplayFormat &format : alternativeFormats) { + QHash::iterator itr = allItemsFormats.find(format); + if (itr != allItemsFormats.end()) + itr.value() += 1; + else + allItemsFormats[format] = 1; + } + } + + const QString spacer = " "; + menu->addSeparator(); + + addAction(menu, tr("Change Display for Objects"), false); + QString msg = QString(tr("Use Display Format Based on Type")); + addCheckableAction(menu, spacer + msg, true, false, + [this, items] { + setItemsFormat(items, AutomaticFormat); + m_engine->updateLocals(); + }); + + int countOfSelectItems = items.size(); + QHashIterator iter(allItemsFormats); + while (iter.hasNext()) { + iter.next(); + DisplayFormat format = iter.key(); + QString formatName = nameForFormat(format); + if (formatName.isEmpty()) + continue; + + addCheckableAction(menu, spacer + formatName, + iter.value() == countOfSelectItems, + false, + [this, format, items] { + setItemsFormat(items, format); + m_engine->updateLocals(); + }); + } + return menu; +} + static inline QString msgArrayFormat(int n) { return WatchModel::tr("Array of %n items", nullptr, n);