forked from qt-creator/qt-creator
Debugger: Streamline watch editing code.
Implement WatchModel::data() to return the right values for Qt::EditRole, obsoleting the role matching in the delegate. Similarly, handle Qt::EditRole in setData(), leaving only 'Change watch expression' in the delegate, which removes and recreates a row, causing crashes when done in setData().
This commit is contained in:
@@ -240,8 +240,6 @@ enum ModelRoles
|
||||
RequestToggleWatchRole,
|
||||
RequestToolTipByExpressionRole,
|
||||
RequestClearCppCodeModelSnapshotRole,
|
||||
RequestAssignValueRole,
|
||||
RequestAssignTypeRole,
|
||||
RequestWatchExpressionRole,
|
||||
RequestRemoveWatchExpressionRole,
|
||||
|
||||
|
||||
@@ -279,10 +279,11 @@ static inline QRegExp stdStringRegExp(const QString &charType)
|
||||
return re;
|
||||
}
|
||||
|
||||
static QByteArray niceTypeHelper(const QByteArray typeIn)
|
||||
static QString niceTypeHelper(const QByteArray &typeIn)
|
||||
{
|
||||
static QMap<QByteArray, QByteArray> cache;
|
||||
const QMap<QByteArray, QByteArray>::const_iterator it = cache.constFind(typeIn);
|
||||
typedef QMap<QByteArray, QString> Cache;
|
||||
static Cache cache;
|
||||
const Cache::const_iterator it = cache.constFind(typeIn);
|
||||
if (it != cache.constEnd())
|
||||
return it.value();
|
||||
|
||||
@@ -375,20 +376,24 @@ static QByteArray niceTypeHelper(const QByteArray typeIn)
|
||||
}
|
||||
}
|
||||
}
|
||||
QByteArray typeOut = type.toUtf8();
|
||||
typeOut.replace('@', '*');
|
||||
typeOut.replace(" >", ">");
|
||||
cache.insert(typeIn, typeOut); // For simplicity, also cache unmodified types
|
||||
return typeOut;
|
||||
type.replace(QLatin1Char('@'), QLatin1Char('*'));
|
||||
type.replace(QLatin1String(" >"), QLatin1String(">"));
|
||||
cache.insert(typeIn, type); // For simplicity, also cache unmodified types
|
||||
return type;
|
||||
}
|
||||
|
||||
QByteArray WatchModel::niceType(const QByteArray &typeIn) const
|
||||
QString WatchModel::displayType(const WatchData &data) const
|
||||
{
|
||||
QByteArray type = niceTypeHelper(typeIn);
|
||||
if (!data.displayedType.isEmpty())
|
||||
return data.displayedType;
|
||||
QString type = niceTypeHelper(data.type);
|
||||
if (!theDebuggerBoolSetting(ShowStdNamespace))
|
||||
type.replace("std::", "");
|
||||
if (!theDebuggerBoolSetting(ShowQtNamespace))
|
||||
type.replace(engine()->qtNamespace(), "");
|
||||
type.remove(QLatin1String("std::"));
|
||||
if (!theDebuggerBoolSetting(ShowQtNamespace)) {
|
||||
const QString qtNamespace = QString::fromLatin1(engine()->qtNamespace());
|
||||
if (!qtNamespace.isEmpty())
|
||||
type.remove(qtNamespace);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -712,30 +717,31 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
||||
return QVariant(16);
|
||||
return QVariant(formatToIntegerBase(itemFormat(data)));
|
||||
case Qt::EditRole:
|
||||
case Qt::DisplayRole: {
|
||||
switch (idx.column()) {
|
||||
case 0:
|
||||
if (data.name.isEmpty() && role == Qt::DisplayRole)
|
||||
return QVariant(expression(item));
|
||||
case 1:
|
||||
return editValue(data);
|
||||
case 2:
|
||||
if (!data.displayedType.isEmpty()) // To be tested: Can debuggers handle those?
|
||||
return data.displayedType;
|
||||
return QString::fromUtf8(data.type);
|
||||
default: break;
|
||||
} // switch editrole column
|
||||
case Qt::DisplayRole:
|
||||
switch (idx.column()) {
|
||||
case 0:
|
||||
if (data.name.isEmpty())
|
||||
return tr("<Edit>");
|
||||
if (data.name == QLatin1String("*") && item->parent)
|
||||
return QVariant(QLatin1Char('*') + item->parent->name);
|
||||
return data.name;
|
||||
case 1:
|
||||
if (role == Qt::DisplayRole) {
|
||||
return truncateValue(formattedValue(data, itemFormat(data)));
|
||||
} else {
|
||||
return editValue(data);
|
||||
}
|
||||
case 2: {
|
||||
if (!data.displayedType.isEmpty())
|
||||
return data.displayedType;
|
||||
return QString::fromUtf8(niceType(data.type));
|
||||
}
|
||||
case 2:
|
||||
return displayType(data);
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} // switch editrole column
|
||||
case Qt::ToolTipRole:
|
||||
return theDebuggerBoolSetting(UseToolTipsInLocalsView)
|
||||
? data.toToolTip() : QVariant();
|
||||
@@ -855,6 +861,17 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
WatchItem &data = *watchItem(index);
|
||||
|
||||
switch (role) {
|
||||
case Qt::EditRole:
|
||||
switch (index.column()) {
|
||||
case 0: // Watch expression: See delegate.
|
||||
break;
|
||||
case 1: // Change value
|
||||
engine()->assignValueInDebugger(&data, expression(&data), value);
|
||||
break;
|
||||
case 2: // TODO: Implement change type.
|
||||
engine()->assignValueInDebugger(&data, expression(&data), value);
|
||||
break;
|
||||
}
|
||||
case LocalsExpandedRole:
|
||||
if (value.toBool()) {
|
||||
// Should already have been triggered by fetchMore()
|
||||
@@ -888,13 +905,6 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
case RequestWatchExpressionRole:
|
||||
m_handler->watchExpression(value.toString());
|
||||
break;
|
||||
|
||||
case RequestAssignValueRole:
|
||||
engine()->assignValueInDebugger(&data, expression(&data), value);
|
||||
return true;
|
||||
case RequestAssignTypeRole: // TODO: Implement.
|
||||
engine()->assignValueInDebugger(&data, expression(&data), value);
|
||||
return true;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index);
|
||||
|
||||
@@ -119,7 +119,7 @@ signals:
|
||||
void enableUpdates(bool);
|
||||
|
||||
private:
|
||||
QByteArray niceType(const QByteArray &typeIn) const;
|
||||
QString displayType(const WatchData &typeIn) const;
|
||||
void formatRequests(QByteArray *out, const WatchItem *item) const;
|
||||
DebuggerEngine *engine() const;
|
||||
int itemFormat(const WatchData &data) const;
|
||||
|
||||
@@ -40,17 +40,13 @@
|
||||
#include <utils/savedaction.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QMetaProperty>
|
||||
#include <QtCore/QMetaObject>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QContextMenuEvent>
|
||||
#include <QtGui/QDialog>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QItemDelegate>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QResizeEvent>
|
||||
|
||||
@@ -66,7 +62,7 @@ using namespace Debugger::Internal;
|
||||
class WatchDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
WatchDelegate(QObject *parent) : QItemDelegate(parent) {}
|
||||
explicit WatchDelegate(QObject *parent) : QItemDelegate(parent) {}
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
|
||||
const QModelIndex &index) const
|
||||
@@ -89,48 +85,25 @@ public:
|
||||
return new QLineEdit(parent);
|
||||
}
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == 1) {
|
||||
editor->setProperty("modelData", index.data(Qt::EditRole));
|
||||
return;
|
||||
}
|
||||
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
|
||||
QTC_ASSERT(lineEdit, return);
|
||||
if (index.column() == 0) {
|
||||
// Watch window: Edit expression in name column.
|
||||
lineEdit->setText(index.data(LocalsExpressionRole).toString());
|
||||
} else {
|
||||
// To be implemented: Edit type (of a pointer, say).
|
||||
lineEdit->setText(index.data(Qt::EditRole).toString());
|
||||
}
|
||||
}
|
||||
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == 1) { // The value column.
|
||||
const QVariant value = editor->property("modelData");
|
||||
QTC_ASSERT(value.isValid(), return);
|
||||
model->setData(index, value, RequestAssignValueRole);
|
||||
// Standard handling for anything but the watcher name column (change
|
||||
// expression), which removes/recreates a row, which cannot be done
|
||||
// in model->setData().
|
||||
if (index.column() != 0) {
|
||||
QItemDelegate::setModelData(editor, model, index);
|
||||
return;
|
||||
}
|
||||
//qDebug() << "SET MODEL DATA";
|
||||
const QLineEdit *lineEdit = qobject_cast<const QLineEdit*>(editor);
|
||||
QTC_ASSERT(lineEdit, return);
|
||||
const QString value = lineEdit->text();
|
||||
if (index.column() == 2) {
|
||||
// The type column.
|
||||
model->setData(index, QVariant(value), RequestAssignTypeRole);
|
||||
} else if (index.column() == 0) {
|
||||
// The watcher name column: Change the expression.
|
||||
const QMetaProperty userProperty = editor->metaObject()->userProperty();
|
||||
QTC_ASSERT(userProperty.isValid(), return);
|
||||
const QVariant value = editor->property(userProperty.name());
|
||||
const QString exp = index.data(LocalsExpressionRole).toString();
|
||||
if (exp != value ) {
|
||||
if (exp != value.toString()) {
|
||||
model->setData(index, exp, RequestRemoveWatchExpressionRole);
|
||||
model->setData(index, value, RequestWatchExpressionRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &) const
|
||||
@@ -139,7 +112,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WatchWindow
|
||||
|
||||
Reference in New Issue
Block a user