forked from qt-creator/qt-creator
debugger: add dialog to edit display types
Change-Id: If1ea8cdab359bcad80e37dd4a932e4b586527264 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -45,22 +45,26 @@
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <projectexplorer/abi.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <utils/historycompleter.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QRegExp>
|
||||
|
||||
#include <QtGui/QButtonGroup>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QProxyModel>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QGroupBox>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QProxyModel>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QRadioButton>
|
||||
#include <QtGui/QScrollArea>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
|
||||
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<TypeFormatsDialogPage *> 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
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
#ifndef DEBUGGER_DIALOGS_H
|
||||
#define DEBUGGER_DIALOGS_H
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QDialog>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@@ -278,6 +281,8 @@ private:
|
||||
QDialogButtonBox *m_box;
|
||||
};
|
||||
|
||||
typedef QHash<QString, QStringList> 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
|
||||
|
||||
|
||||
@@ -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<QString, QStringList> it(m_reportedTypeFormats);
|
||||
QList<QString> 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
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Internal {
|
||||
|
||||
class WatchItem;
|
||||
class WatchHandler;
|
||||
typedef QHash<QString, QStringList> 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<QByteArray, int> m_watcherNames;
|
||||
static QHash<QByteArray, int> m_typeFormats;
|
||||
QHash<QByteArray, int> m_individualFormats; // Indexed by iname.
|
||||
QHash<QString, QStringList> m_reportedTypeFormats;
|
||||
TypeFormats m_reportedTypeFormats;
|
||||
|
||||
// Items expanded in the Locals & Watchers view.
|
||||
QSet<QByteArray> m_expandedINames;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user