Commit 463ac5d6 authored by hjk's avatar hjk

debugger: start reviving graphical data display

parent bb35660c
...@@ -439,10 +439,13 @@ def findFirstZero(p, max): ...@@ -439,10 +439,13 @@ def findFirstZero(p, max):
p = p + 1 p = p + 1
return -1 return -1
def encodeCharArray(p, maxsize): def encodeCharArray(p, maxsize, size = -1):
t = gdb.lookup_type("unsigned char").pointer() t = gdb.lookup_type("unsigned char").pointer()
p = p.cast(t) p = p.cast(t)
i = findFirstZero(p, maxsize) if size == -1:
i = findFirstZero(p, maxsize)
else:
i = size
limit = select(i < 0, maxsize, i) limit = select(i < 0, maxsize, i)
s = "" s = ""
for i in xrange(limit): for i in xrange(limit):
...@@ -823,7 +826,7 @@ class Dumper: ...@@ -823,7 +826,7 @@ class Dumper:
self.put('},') self.put('},')
def beginItem(self, name): def beginItem(self, name):
self.put('%s="' %s) self.put('%s="' % name)
def endItem(self): def endItem(self):
self.put('",') self.put('",')
...@@ -978,6 +981,12 @@ class Dumper: ...@@ -978,6 +981,12 @@ class Dumper:
if isSimpleType(item.value.type): if isSimpleType(item.value.type):
self.safePutItemHelper(item) self.safePutItemHelper(item)
def itemFormat(self, item):
format = self.formats.get(item.iname)
if format is None:
format = self.typeformats.get(stripClassTag(str(item.value.type)))
return format
def safePutItem(self, item): def safePutItem(self, item):
self.beginHash() self.beginHash()
self.safePutItemHelper(item) self.safePutItemHelper(item)
...@@ -1091,9 +1100,7 @@ class Dumper: ...@@ -1091,9 +1100,7 @@ class Dumper:
elif type.code == gdb.TYPE_CODE_PTR: elif type.code == gdb.TYPE_CODE_PTR:
isHandled = False isHandled = False
format = self.formats.get(item.iname) format = self.itemFormat(item)
if format is None:
format = self.typeformats.get(str(value.type))
if not format is None: if not format is None:
self.putAddress(value.address) self.putAddress(value.address)
......
...@@ -390,6 +390,8 @@ def qdump__QImage(d, item): ...@@ -390,6 +390,8 @@ def qdump__QImage(d, item):
else: else:
checkRef(d_ptr["ref"]) checkRef(d_ptr["ref"])
d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"])) d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
bits = d_ptr["data"]
nbytes = d_ptr["nbytes"]
d.putNumChild(0) d.putNumChild(0)
#d.putNumChild(1) #d.putNumChild(1)
if d.isExpanded(item): if d.isExpanded(item):
...@@ -398,13 +400,25 @@ def qdump__QImage(d, item): ...@@ -398,13 +400,25 @@ def qdump__QImage(d, item):
d.putName("data") d.putName("data")
d.putType(" "); d.putType(" ");
d.putNumChild(0) d.putNumChild(0)
bits = d_ptr["data"]
nbytes = d_ptr["nbytes"]
d.putValue("size: %s bytes" % nbytes); d.putValue("size: %s bytes" % nbytes);
d.putField("valuetooltipencoded", "6") #d.putField("valuetooltipencoded", "6")
d.putField("valuetooltip", encodeCharArray(bits, nbytes)) #d.putField("valuetooltip", encodeCharArray(bits, nbytes))
d.endHash() d.endHash()
d.endChildren() d.endChildren()
format = d.itemFormat(item)
if format == 1:
d.beginItem("editvalue")
d.put("%02x" % 1) # Magic marker for "QImage" data.
d.put("%08x" % int(d_ptr["width"]))
d.put("%08x" % int(d_ptr["height"]))
d.put("%08x" % int(d_ptr["format"]))
# Take 4 at a time, this is critical for performance.
# In fact, even 4 at a time is too slow beyond 100x100 or so.
p = bits.cast(gdb.lookup_type("unsigned int").pointer())
for i in xrange(nbytes / 4):
d.put("%08x" % int(p.dereference()))
p += 1
d.endItem()
def qdump__QLinkedList(d, item): def qdump__QLinkedList(d, item):
......
...@@ -3293,8 +3293,6 @@ void GdbEngine::sendWatchParameters(const QByteArray &params0) ...@@ -3293,8 +3293,6 @@ void GdbEngine::sendWatchParameters(const QByteArray &params0)
void GdbEngine::handleVarAssign(const GdbResponse &) void GdbEngine::handleVarAssign(const GdbResponse &)
{ {
// Everything might have changed, force re-evaluation. // Everything might have changed, force re-evaluation.
// FIXME: Speed this up by re-using variables and only
// marking values as 'unknown'
setTokenBarrier(); setTokenBarrier();
updateLocals(); updateLocals();
} }
...@@ -3370,13 +3368,6 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item, ...@@ -3370,13 +3368,6 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
if (children.isValid() || !manager()->watchHandler()->isExpandedIName(data.iname)) if (children.isValid() || !manager()->watchHandler()->isExpandedIName(data.iname))
data.setChildrenUnneeded(); data.setChildrenUnneeded();
if (manager()->watchHandler()->isDisplayedIName(data.iname)) {
GdbMi editvalue = item.findChild("editvalue");
if (editvalue.isValid()) {
setWatchDataEditValue(data, editvalue);
manager()->watchHandler()->showEditValue(data);
}
}
setWatchDataType(data, item.findChild("type")); setWatchDataType(data, item.findChild("type"));
setWatchDataEditValue(data, item.findChild("editvalue")); setWatchDataEditValue(data, item.findChild("editvalue"));
setWatchDataValue(data, item.findChild("value"), setWatchDataValue(data, item.findChild("value"),
...@@ -4204,13 +4195,13 @@ void GdbEngine::handleAdapterCrashed(const QString &msg) ...@@ -4204,13 +4195,13 @@ void GdbEngine::handleAdapterCrashed(const QString &msg)
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
} }
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const void GdbEngine::addOptionPages(QList<Core::IOptionsPage *> *opts) const
{ {
opts->push_back(new GdbOptionsPage); opts->push_back(new GdbOptionsPage);
opts->push_back(new TrkOptionsPage(m_trkOptions)); opts->push_back(new TrkOptionsPage(m_trkOptions));
} }
QMessageBox * GdbEngine::showMessageBox(int icon, const QString &title, QMessageBox *GdbEngine::showMessageBox(int icon, const QString &title,
const QString &text, int buttons) const QString &text, int buttons)
{ {
return m_manager->showMessageBox(icon, title, text, buttons); return m_manager->showMessageBox(icon, title, text, buttons);
......
...@@ -47,12 +47,9 @@ ...@@ -47,12 +47,9 @@
#include <QtCore/QVariant> #include <QtCore/QVariant>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QAction;
class QMainWindow; class QMainWindow;
class QMessageBox; class QMessageBox;
class QTimer; class QTimer;
class QWidget;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Debugger { namespace Debugger {
......
...@@ -259,7 +259,8 @@ QString WatchData::toString() const ...@@ -259,7 +259,8 @@ QString WatchData::toString() const
str << "value=\"" << value << doubleQuoteComma; str << "value=\"" << value << doubleQuoteComma;
if (!editvalue.isEmpty()) if (!editvalue.isEmpty())
str << "editvalue=\"" << editvalue << doubleQuoteComma; str << "editvalue=\"<...>\",";
// str << "editvalue=\"" << editvalue << doubleQuoteComma;
if (isTypeNeeded()) if (isTypeNeeded())
str << "type=<needed>,"; str << "type=<needed>,";
...@@ -281,8 +282,9 @@ QString WatchData::toString() const ...@@ -281,8 +282,9 @@ QString WatchData::toString() const
return res + QLatin1Char('}'); return res + QLatin1Char('}');
} }
// Format a tooltip fow with aligned colon // Format a tooltip fow with aligned colon.
static void formatToolTipRow(QTextStream &str, const QString &category, const QString &value) static void formatToolTipRow(QTextStream &str,
const QString &category, const QString &value)
{ {
str << "<tr><td>" << category << "</td><td> : </td><td>" str << "<tr><td>" << category << "</td><td> : </td><td>"
<< Qt::escape(value) << "</td></tr>"; << Qt::escape(value) << "</td></tr>";
...@@ -815,10 +817,6 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const ...@@ -815,10 +817,6 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case ExpandedRole: case ExpandedRole:
return m_handler->m_expandedINames.contains(data.iname); return m_handler->m_expandedINames.contains(data.iname);
case ActiveDataRole:
qDebug() << "ASK FOR" << data.iname;
return true;
case TypeFormatListRole: case TypeFormatListRole:
if (isIntType(data.type)) if (isIntType(data.type))
return QStringList() << tr("decimal") << tr("hexadecimal") return QStringList() << tr("decimal") << tr("hexadecimal")
...@@ -830,6 +828,10 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const ...@@ -830,6 +828,10 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
<< tr("UTF8 string") << tr("UTF8 string")
<< tr("UTF16 string") << tr("UTF16 string")
<< tr("UCS4 string"); << tr("UCS4 string");
if (data.type.endsWith(QLatin1String("QImage")))
return QStringList()
<< tr("normal")
<< tr("displayed");
break; break;
case TypeFormatRole: case TypeFormatRole:
...@@ -1202,13 +1204,12 @@ void WatchHandler::endCycle() ...@@ -1202,13 +1204,12 @@ void WatchHandler::endCycle()
void WatchHandler::cleanup() void WatchHandler::cleanup()
{ {
m_expandedINames.clear(); m_expandedINames.clear();
m_displayedINames.clear();
m_locals->reinitialize(); m_locals->reinitialize();
m_tooltips->reinitialize(); m_tooltips->reinitialize();
m_locals->m_fetchTriggered.clear(); m_locals->m_fetchTriggered.clear();
m_watchers->m_fetchTriggered.clear(); m_watchers->m_fetchTriggered.clear();
m_tooltips->m_fetchTriggered.clear(); m_tooltips->m_fetchTriggered.clear();
#if 0 #if 1
for (EditWindows::ConstIterator it = m_editWindows.begin(); for (EditWindows::ConstIterator it = m_editWindows.begin();
it != m_editWindows.end(); ++it) { it != m_editWindows.end(); ++it) {
if (!it.value().isNull()) if (!it.value().isNull())
...@@ -1233,6 +1234,7 @@ void WatchHandler::insertData(const WatchData &data) ...@@ -1233,6 +1234,7 @@ void WatchHandler::insertData(const WatchData &data)
__FILE__, __LINE__, qPrintable(data.toString())); __FILE__, __LINE__, qPrintable(data.toString()));
return; return;
} }
if (data.isSomethingNeeded() && data.iname.contains('.')) { if (data.isSomethingNeeded() && data.iname.contains('.')) {
MODEL_DEBUG("SOMETHING NEEDED: " << data.toString()); MODEL_DEBUG("SOMETHING NEEDED: " << data.toString());
IDebuggerEngine *engine = m_manager->currentEngine(); IDebuggerEngine *engine = m_manager->currentEngine();
...@@ -1253,6 +1255,9 @@ void WatchHandler::insertData(const WatchData &data) ...@@ -1253,6 +1255,9 @@ void WatchHandler::insertData(const WatchData &data)
QTC_ASSERT(model, return); QTC_ASSERT(model, return);
MODEL_DEBUG("NOTHING NEEDED: " << data.toString()); MODEL_DEBUG("NOTHING NEEDED: " << data.toString());
model->insertData(data); model->insertData(data);
if (!data.editvalue.isEmpty())
showEditValue(data);
} }
} }
...@@ -1331,79 +1336,57 @@ void WatchHandler::watchExpression(const QString &exp) ...@@ -1331,79 +1336,57 @@ void WatchHandler::watchExpression(const QString &exp)
saveWatchers(); saveWatchers();
} }
void WatchHandler::setDisplayedIName(const QString &iname, bool on) static void swapEndian(char *d, int nchar)
{ {
Q_UNUSED(iname) QTC_ASSERT(nchar % 4 == 0, return);
Q_UNUSED(on) for (int i = 0; i < nchar; i += 4) {
/* char c = d[i];
WatchData *d = findData(iname); d[i] = d[i + 3];
if (!on || !d) { d[i + 3] = c;
delete m_editWindows.take(iname); c = d[i + 1];
m_displayedINames.remove(iname); d[i + 1] = d[i + 2];
return; d[i + 2] = c;
}
if (d->exp.isEmpty()) {
//emit statusMessageRequested(tr("Sorry. Cannot visualize objects without known address."), 5000);
return;
} }
d->setValueNeeded();
m_displayedINames.insert(iname);
insertData(*d);
*/
} }
void WatchHandler::showEditValue(const WatchData &data) void WatchHandler::showEditValue(const WatchData &data)
{ {
// editvalue is always base64 encoded // Editvalue is always hex encoded.
QByteArray ba = QByteArray::fromBase64(data.editvalue); QByteArray ba = QByteArray::fromHex(data.editvalue);
//QByteArray ba = data.editvalue;
QWidget *w = m_editWindows.value(data.iname); QWidget *w = m_editWindows.value(data.iname);
qDebug() << "SHOW_EDIT_VALUE " << data.toString() << data.type const int format = ba.at(0);
<< data.iname << w; if (format == 0x1) {
if (data.type == QLatin1String("QImage")) { // QImage
if (!w) { if (!w) {
w = new QLabel; w = new QLabel;
m_editWindows[data.iname] = w; m_editWindows[data.iname] = w;
} }
QDataStream ds(&ba, QIODevice::ReadOnly); if (QLabel *l = qobject_cast<QLabel *>(w)) {
QVariant v; char *d = ba.data() + 1;
ds >> v; swapEndian(d, ba.size() - 1);
QString type = QString::fromAscii(v.typeName()); const int *header = (int *)(d);
QImage im = v.value<QImage>(); const uchar *data = 12 + (uchar *)(d);
if (QLabel *l = qobject_cast<QLabel *>(w)) QImage im(data, header[0], header[1], QImage::Format(header[2]));
l->setPixmap(QPixmap::fromImage(im)); l->setPixmap(QPixmap::fromImage(im));
} else if (data.type == QLatin1String("QPixmap")) { l->resize(header[0], header[1]);
if (!w) { l->show();
w = new QLabel;
m_editWindows[data.iname] = w;
} }
QDataStream ds(&ba, QIODevice::ReadOnly); } else if (format == 0x2) {
QVariant v; // QString
ds >> v;
QString type = QString::fromAscii(v.typeName());
QPixmap im = v.value<QPixmap>();
if (QLabel *l = qobject_cast<QLabel *>(w))
l->setPixmap(im);
} else if (data.type == QLatin1String("QString")) {
if (!w) { if (!w) {
w = new QTextEdit; w = new QTextEdit;
m_editWindows[data.iname] = w; m_editWindows[data.iname] = w;
} }
#if 0
QDataStream ds(&ba, QIODevice::ReadOnly);
QVariant v;
ds >> v;
QString type = QString::fromAscii(v.typeName());
QString str = v.value<QString>();
#else
MODEL_DEBUG("DATA: " << ba); MODEL_DEBUG("DATA: " << ba);
QString str = QString::fromUtf16((ushort *)ba.constData(), ba.size()/2); QString str = QString::fromUtf16((ushort *)ba.constData(), ba.size()/2);
#endif if (QTextEdit *t = qobject_cast<QTextEdit *>(w)) {
if (QTextEdit *t = qobject_cast<QTextEdit *>(w))
t->setText(str); t->setText(str);
t->resize(400, 200);
t->show();
}
} else {
QTC_ASSERT(false, qDebug() << "Display format: " << format);
} }
if (w)
w->show();
} }
void WatchHandler::removeWatchExpression() void WatchHandler::removeWatchExpression()
......
...@@ -140,7 +140,7 @@ public: ...@@ -140,7 +140,7 @@ public:
bool error; bool error;
public: public:
int source; // Used by some debuggers (CDB) to tell where it originates from (dumper or symbol evaluation) int source; // Originated from dumper or symbol evaluation? (CDB only)
int state; int state;
bool changed; bool changed;
}; };
...@@ -149,40 +149,21 @@ enum WatchRoles ...@@ -149,40 +149,21 @@ enum WatchRoles
{ {
INameRole = Qt::UserRole, INameRole = Qt::UserRole,
ExpressionRole, ExpressionRole,
ExpandedRole, // used to communicate preferred expanded state to the view ExpandedRole, // Used to communicate preferred expanded state to the view.
ActiveDataRole, // used for tooltip
TypeFormatListRole, TypeFormatListRole,
TypeFormatRole, // used to communicate alternative formats to the view TypeFormatRole, // Used to communicate alternative formats to the view.
IndividualFormatRole, IndividualFormatRole,
AddressRole, // some memory address related to the object AddressRole, // Some memory address related to the object.
}; };
enum IntegerFormat enum IntegerFormat
{ {
DecimalFormat = 0, // keep that at 0 as default DecimalFormat = 0, // Keep that at 0 as default.
HexadecimalFormat, HexadecimalFormat,
BinaryFormat, BinaryFormat,
OctalFormat, OctalFormat,
}; };
enum PointerFomat
{
BaldPointerFormat = 0, // keep that at 0 as default
Latin1StringFormat,
Local8BitStringFormat,
Utf8StringFormat,
Utf16StringFormat,
Ucs4StringFormat,
};
enum DumpableFormat
{
PrettyFormat = 0, // keep that at 0 as default
PlainFomat,
};
class WatchModel : public QAbstractItemModel class WatchModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
...@@ -274,8 +255,6 @@ public: ...@@ -274,8 +255,6 @@ public:
void loadSessionData(); void loadSessionData();
void saveSessionData(); void saveSessionData();
bool isDisplayedIName(const QByteArray &iname) const
{ return m_displayedINames.contains(iname); }
bool isExpandedIName(const QByteArray &iname) const bool isExpandedIName(const QByteArray &iname) const
{ return m_expandedINames.contains(iname); } { return m_expandedINames.contains(iname); }
QSet<QByteArray> expandedINames() const QSet<QByteArray> expandedINames() const
...@@ -308,10 +287,7 @@ private: ...@@ -308,10 +287,7 @@ private:
QByteArray watcherName(const QByteArray &exp); QByteArray watcherName(const QByteArray &exp);
QHash<QString, int> m_typeFormats; QHash<QString, int> m_typeFormats;
QHash<QString, int> m_individualFormats; QHash<QString, int> m_individualFormats;
QSet<QByteArray> m_expandedINames; // Those expanded in the treeview.
void setDisplayedIName(const QString &iname, bool on);
QSet<QByteArray> m_expandedINames; // those expanded in the treeview
QSet<QByteArray> m_displayedINames; // those with "external" viewers
WatchModel *m_locals; WatchModel *m_locals;
WatchModel *m_watchers; WatchModel *m_watchers;
......
...@@ -681,7 +681,7 @@ QString decodeData(const QByteArray &ba, int encoding) ...@@ -681,7 +681,7 @@ QString decodeData(const QByteArray &ba, int encoding)
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *> return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote; (decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
} }
case 11: { // %02x encoded 16 bit data, Big Endian case 11: { // %04x encoded 16 bit data, Big Endian
const QChar doubleQuote(QLatin1Char('"')); const QChar doubleQuote(QLatin1Char('"'));
QByteArray decodedBa = QByteArray::fromHex(ba); QByteArray decodedBa = QByteArray::fromHex(ba);
for (int i = 0; i < decodedBa.size(); i += 2) { for (int i = 0; i < decodedBa.size(); i += 2) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment