diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 5e41e3aebe3..1c7796e0266 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -45,22 +45,26 @@ #include #include -#include #include #include +#include -#include -#include -#include #include -#include -#include +#include +#include +#include + +#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include using namespace Utils; @@ -972,5 +976,127 @@ QString StartRemoteEngineDialog::enginePath() const return m_ui->enginepath->text(); } +/////////////////////////////////////////////////////////////////////// +// +// TypeFormatsDialogUi +// +/////////////////////////////////////////////////////////////////////// + +class TypeFormatsDialogPage : public QWidget +{ +public: + TypeFormatsDialogPage() + { + m_layout = new QVBoxLayout; + m_layout->setMargin(5); + m_layout->setSpacing(0); + m_layout->addItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding)); + setLayout(m_layout); + } + + void addTypeFormats(const QString &type, + const QStringList &typeFormats, int current) + { + QHBoxLayout *hl = new QHBoxLayout; + QButtonGroup *group = new QButtonGroup(this); + QLabel *typeLabel = new QLabel(type, this); + hl->addWidget(typeLabel); + for (int i = -1; i != typeFormats.size(); ++i) { + QRadioButton *choice = new QRadioButton(this); + if (i == -1) + choice->setText(tr("Reset")); + else + choice->setText(typeFormats.at(i)); + hl->addWidget(choice); + if (i == current) + choice->setChecked(true); + group->addButton(choice, i); + } + hl->addItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding)); + m_layout->insertLayout(m_layout->count() - 1, hl); + } +private: + QVBoxLayout *m_layout; +}; + +class TypeFormatsDialogUi +{ +public: + TypeFormatsDialogUi(TypeFormatsDialog *q) + { + QVBoxLayout *layout = new QVBoxLayout(q); + tabs = new QTabWidget(q); + + buttonBox = new QDialogButtonBox(q); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + layout->addWidget(tabs); + layout->addWidget(buttonBox); + q->setLayout(layout); + } + + void addPage(const QString &name) + { + TypeFormatsDialogPage *page = new TypeFormatsDialogPage; + pages.append(page); + QScrollArea *scroller = new QScrollArea; + scroller->setWidgetResizable(true); + scroller->setWidget(page); + scroller->setFrameStyle(QFrame::NoFrame); + tabs->addTab(scroller, name); + } + +public: + QDialogButtonBox *buttonBox; + QList pages; + +private: + QTabWidget *tabs; +}; + + +/////////////////////////////////////////////////////////////////////// +// +// TypeFormatsDialog +// +/////////////////////////////////////////////////////////////////////// + + +TypeFormatsDialog::TypeFormatsDialog(QWidget *parent) + : QDialog(parent), m_ui(new TypeFormatsDialogUi(this)) +{ + m_ui->addPage(tr("Qt Types")); + m_ui->addPage(tr("Standard Types")); + m_ui->addPage(tr("Misc Types")); + + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); +} + +TypeFormatsDialog::~TypeFormatsDialog() +{ + delete m_ui; +} + +void TypeFormatsDialog::addTypeFormats(const QString &type0, + const QStringList &typeFormats, int current) +{ + QString type = type0; + type.replace("__", "::"); + int pos = 2; + if (type.startsWith(QLatin1Char('Q'))) + pos = 0; + else if (type.startsWith(QLatin1String("std::"))) + pos = 1; + m_ui->pages[pos]->addTypeFormats(type, typeFormats, current); +} + +TypeFormats TypeFormatsDialog::typeFormats() const +{ + return TypeFormats(); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index 4e09e35f3e2..5d5e2653160 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -33,7 +33,10 @@ #ifndef DEBUGGER_DIALOGS_H #define DEBUGGER_DIALOGS_H +#include +#include #include +#include QT_BEGIN_NAMESPACE @@ -278,6 +281,8 @@ private: QDialogButtonBox *m_box; }; +typedef QHash TypeFormats; + class StartRemoteEngineDialog : public QDialog { Q_OBJECT @@ -295,6 +300,24 @@ private: Ui::StartRemoteEngineDialog *m_ui; }; +class TypeFormatsDialogUi; + +class TypeFormatsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TypeFormatsDialog(QWidget *parent); + ~TypeFormatsDialog(); + + void addTypeFormats(const QString &type, const QStringList &formats, + int currentFormat); + TypeFormats typeFormats() const; + +private: + TypeFormatsDialogUi *m_ui; +}; + } // namespace Debugger } // namespace Internal diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 81ea6173f13..6424bfa63c0 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -37,6 +37,7 @@ #include "debuggeractions.h" #include "debuggercore.h" #include "debuggerengine.h" +#include "debuggerdialogs.h" #include "watchutils.h" #if USE_WATCH_MODEL_TEST @@ -758,43 +759,15 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case LocalsExpandedRole: return m_handler->m_expandedINames.contains(data.iname); - case LocalsTypeFormatListRole: { - if (data.referencingAddress || isPointerType(data.type)) - return QStringList() - << tr("Raw pointer") - << tr("Latin1 string") - << tr("UTF8 string") - << tr("Local 8bit string") - << tr("UTF16 string") - << tr("UCS4 string"); - if (data.type.contains("char[") || data.type.contains("char [")) - return QStringList() - << tr("Latin1 string") - << tr("UTF8 string") - << tr("Local 8bit string"); - bool ok = false; - (void)data.value.toULongLong(&ok, 0); - if ((isIntType(data.type) && data.type != "bool") || ok) - return QStringList() - << tr("Decimal") - << tr("Hexadecimal") - << tr("Binary") - << tr("Octal"); - // Hack: Compensate for namespaces. - QString type = stripTemplate(data.type); - int pos = type.indexOf("::Q"); - if (pos >= 0 && type.count(':') == 2) - type = type.mid(pos + 2); - pos = type.indexOf('<'); - if (pos >= 0) - type = type.left(pos); - type.replace(':', '_'); - return m_handler->m_reportedTypeFormats.value(type); - } + case LocalsTypeFormatListRole: + return m_handler->typeFormatList(data); + case LocalsTypeRole: - return removeNamespaces(displayType(data)); + return removeNamespaces(displayType(data)); + case LocalsRawTypeRole: - return QString::fromLatin1(data.type); + return QString::fromLatin1(data.type); + case LocalsTypeFormatRole: return m_handler->m_typeFormats.value(stripTemplate(data.type), -1); @@ -933,6 +906,41 @@ QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int ro return QVariant(); } +QStringList WatchHandler::typeFormatList(const WatchData &data) const +{ + if (data.referencingAddress || isPointerType(data.type)) + return QStringList() + << tr("Raw pointer") + << tr("Latin1 string") + << tr("UTF8 string") + << tr("Local 8bit string") + << tr("UTF16 string") + << tr("UCS4 string"); + if (data.type.contains("char[") || data.type.contains("char [")) + return QStringList() + << tr("Latin1 string") + << tr("UTF8 string") + << tr("Local 8bit string"); + bool ok = false; + (void)data.value.toULongLong(&ok, 0); + if ((isIntType(data.type) && data.type != "bool") || ok) + return QStringList() + << tr("Decimal") + << tr("Hexadecimal") + << tr("Binary") + << tr("Octal"); + // Hack: Compensate for namespaces. + QString type = stripTemplate(data.type); + int pos = type.indexOf("::Q"); + if (pos >= 0 && type.count(':') == 2) + type = type.mid(pos + 2); + pos = type.indexOf('<'); + if (pos >= 0) + type = type.left(pos); + type.replace(':', '_'); + return m_reportedTypeFormats.value(type); +} + // Determine sort order of watch items by sort order or alphabetical inames // according to setting 'SortStructMembers'. We need a map key for bulkInsert // and a predicate for finding the insertion position of a single item. @@ -1759,5 +1767,31 @@ void WatchHandler::rebuildModel() endCycle(); } +void WatchHandler::setTypeFormats(const TypeFormats &typeFormats) +{ + m_reportedTypeFormats = typeFormats; +} + +TypeFormats WatchHandler::typeFormats() const +{ + return m_reportedTypeFormats; +} + +void WatchHandler::editTypeFormats(bool includeLocals, const QByteArray &iname) +{ + Q_UNUSED(includeLocals); + TypeFormatsDialog dlg(0); + + //QHashIterator it(m_reportedTypeFormats); + QList l = 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); + } + if (dlg.exec()) + setTypeFormats(dlg.typeFormats()); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index b9c05bb587d..b2fe9d91e09 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -48,6 +48,7 @@ namespace Internal { class WatchItem; class WatchHandler; +typedef QHash TypeFormats; enum WatchType { @@ -183,6 +184,9 @@ public: int format(const QByteArray &iname) const; void addTypeFormats(const QByteArray &type, const QStringList &formats); + void setTypeFormats(const TypeFormats &typeFormats); + TypeFormats typeFormats() const; + QStringList typeFormatList(const WatchData &data) const; void setUnprintableBase(int base); static int unprintableBase(); @@ -190,6 +194,7 @@ public: QByteArray watcherName(const QByteArray &exp); void synchronizeWatchers(); QString editorContents(); + void editTypeFormats(bool includeLocals, const QByteArray &iname); private: friend class WatchModel; @@ -211,7 +216,7 @@ private: static QHash m_watcherNames; static QHash m_typeFormats; QHash m_individualFormats; // Indexed by iname. - QHash m_reportedTypeFormats; + TypeFormats m_reportedTypeFormats; // Items expanded in the Locals & Watchers view. QSet m_expandedINames; diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 7e4fea9b417..bf4e3357c79 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -637,7 +637,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *showUnprintableEscape = 0; QAction *showUnprintableOctal = 0; QAction *showUnprintableHexadecimal = 0; - formatMenu.setTitle(tr("Change Display Format...")); + formatMenu.setTitle(tr("Change Local Display Format...")); showUnprintableUnicode = formatMenu.addAction(tr("Treat All Characters as Printable")); showUnprintableUnicode->setCheckable(true); @@ -755,6 +755,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch")); actSelectWidgetToWatch->setEnabled(canHandleWatches && (engine->debuggerCapabilities() & WatchWidgetsCapability)); + QAction *actEditTypeFormats = menu.addAction(tr("Change Global Display Formats...")); + actEditTypeFormats->setEnabled(true); menu.addSeparator(); QAction *actWatchExpression = new QAction(addWatchActionText(exp), &menu); @@ -839,6 +841,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(actInsertNewWatchItem); menu.addAction(actSelectWidgetToWatch); + menu.addAction(actEditTypeFormats); menu.addMenu(&formatMenu); menu.addMenu(&memoryMenu); menu.addMenu(&breakpointMenu); @@ -911,6 +914,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) removeWatchExpression(removeExp); } else if (act == actCopy) { copyToClipboard(DebuggerToolTipWidget::treeModelClipboardContents(model())); + } else if (act == actEditTypeFormats) { + handler->editTypeFormats(true, mi0.data(LocalsINameRole).toByteArray()); } else if (act == actCopyValue) { copyToClipboard(mi1.data().toString()); } else if (act == actRemoveWatches) {