forked from qt-creator/qt-creator
Fix up Debugger helpers to be able to dump QObject's with CDB.
- Make container dumper routines set "childnumchild" when known in order to avoid roundtrips; avoid repeated invocations of container.end(). - Completed dumper information in some places to avoid roundtrips. - Extended QVariant helpers by dumpers for common GUI types (rectangles, points, sizes, fonts, size policies). - Introduced artificial QObjectChildList/QObjectProperty types to be able to dump QObject children and properties without using gdb expressions. - Fixed dumping of Signal/Slot list to pass on correct types. Avoid recursions if signal is connected to self. - Replaced expressions by addresses in the dumpers to it make work for CDB. - Reworked dumper test program to have -a, making it usable for tests, add further types. - Gdb: Clear output buffer before calling dumpers, avoiding mixups in case evaluation of expression fails. - Fix the dumper parser used by CDB, do not be fooled by "<synthetic>" addresses, etc. - Pass on a "dumperVersion" in initial query.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,6 @@
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
|
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = dumpertest
|
TARGET = dumpertest
|
||||||
CONFIG += console
|
CONFIG += console
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
|
@@ -32,6 +32,8 @@
|
|||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
#include <QtGui/QAction>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
@@ -174,6 +176,20 @@ static int dumpQMapIntString()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dumpQVariant()
|
||||||
|
{
|
||||||
|
QVariant test(QLatin1String("item"));
|
||||||
|
prepareInBuffer("QVariant", "local.qvariant", "local.qvariant", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
fputs("\n\n", stdout);
|
||||||
|
test = QVariant(QStringList(QLatin1String("item1")));
|
||||||
|
prepareInBuffer("QVariant", "local.qvariant", "local.qvariant", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------- std types
|
// --------------- std types
|
||||||
|
|
||||||
static int dumpStdString()
|
static int dumpStdString()
|
||||||
@@ -309,76 +325,127 @@ static int dumpStdMapIntString()
|
|||||||
static int dumpQObject()
|
static int dumpQObject()
|
||||||
{
|
{
|
||||||
// Requires the childOffset to be know, but that is not critical
|
// Requires the childOffset to be know, but that is not critical
|
||||||
QTimer t;
|
QAction action(0);
|
||||||
|
QObject x;
|
||||||
|
QAction *a2= new QAction(&action);
|
||||||
|
a2->setObjectName(QLatin1String("a2"));
|
||||||
|
action.setObjectName(QLatin1String("action"));
|
||||||
|
QObject::connect(&action, SIGNAL(triggered()), &x, SLOT(deleteLater()));
|
||||||
prepareInBuffer("QObject", "local.qobject", "local.qobject", "");
|
prepareInBuffer("QObject", "local.qobject", "local.qobject", "");
|
||||||
qDumpObjectData440(2, 42, testAddress(&t), 1, 0, 0, 0, 0);
|
qDumpObjectData440(2, 42, testAddress(&action), 1, 0, 0, 0, 0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
fputs("\n\n", stdout);
|
||||||
|
// Property list
|
||||||
|
prepareInBuffer("QObjectPropertyList", "local.qobjectpropertylist", "local.qobjectpropertylist", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&action), 1, 0, 0, 0, 0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
fputs("\n\n", stdout);
|
||||||
|
// Signal list
|
||||||
|
prepareInBuffer("QObjectSignalList", "local.qobjectsignallist", "local.qobjectsignallist", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&action), 1, 0, 0, 0, 0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
// Slot list
|
||||||
|
prepareInBuffer("QObjectSlotList", "local.qobjectslotlist", "local.qobjectslotlist", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&action), 1, 0, 0, 0, 0);
|
||||||
|
fputs(qDumpOutBuffer, stdout);
|
||||||
|
fputs("\n\n", stdout);
|
||||||
|
// Signal list
|
||||||
|
prepareInBuffer("QObjectChildList", "local.qobjectchildlist", "local.qobjectchildlist", "");
|
||||||
|
qDumpObjectData440(2, 42, testAddress(&action), 1, 0, 0, 0, 0);
|
||||||
fputs(qDumpOutBuffer, stdout);
|
fputs(qDumpOutBuffer, stdout);
|
||||||
fputc('\n', stdout);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dumpType(const char *arg)
|
static int dumpQObjectList()
|
||||||
{
|
{
|
||||||
if (!qstrcmp(arg, "QString"))
|
// Requires the childOffset to be know, but that is not critical
|
||||||
{ dumpQString(); return true; }
|
QObject *root = new QObject;
|
||||||
if (!qstrcmp(arg, "QSharedPointer<QString>"))
|
root ->setObjectName("root");
|
||||||
{ dumpQSharedPointerQString(); return true; }
|
QTimer *t1 = new QTimer;
|
||||||
if (!qstrcmp(arg, "QStringList"))
|
t1 ->setObjectName("t1");
|
||||||
{ dumpQStringList(); return true; }
|
QTimer *t2 = new QTimer;
|
||||||
if (!qstrcmp(arg, "QList<int>"))
|
t2 ->setObjectName("t2");
|
||||||
{ dumpQIntList(); return true; }
|
QObjectList test;
|
||||||
if (!qstrcmp(arg, "QList<std::string>"))
|
test << root << t1 << t2;
|
||||||
{ dumpStdStringQList(); return true; }
|
prepareInBuffer("QList", "local.qobjectlist", "local.qobjectlist", "QObject *");
|
||||||
if (!qstrcmp(arg, "QVector<int>"))
|
qDumpObjectData440(2, 42, testAddress(&test), sizeof(QObject*), 0, 0, 0, 0);
|
||||||
{ dumpQIntVector(); return true; }
|
fputs(qDumpOutBuffer, stdout);
|
||||||
if (!qstrcmp(arg, "QMap<int,QString>"))
|
fputc('\n', stdout);
|
||||||
{ dumpQMapIntString(); return true; }
|
delete root;
|
||||||
if (!qstrcmp(arg, "QMap<int,int>"))
|
return 0;
|
||||||
{ dumpQMapIntInt(); return true; }
|
}
|
||||||
if (!qstrcmp(arg, "string"))
|
|
||||||
{ dumpStdString(); return true; }
|
typedef int (*DumpFunction)();
|
||||||
if (!qstrcmp(arg, "wstring"))
|
typedef QMap<QString, DumpFunction> TypeDumpFunctionMap;
|
||||||
{ dumpStdWString(); return true; }
|
|
||||||
if (!qstrcmp(arg, "list<int>"))
|
static TypeDumpFunctionMap registerTypes()
|
||||||
{ dumpStdIntList(); return true; }
|
{
|
||||||
if (!qstrcmp(arg, "list<string>"))
|
TypeDumpFunctionMap rc;
|
||||||
{ dumpStdStringList(); return true; }
|
rc.insert("QString", dumpQString);
|
||||||
if (!qstrcmp(arg, "vector<int>"))
|
rc.insert("QSharedPointer<QString>", dumpQSharedPointerQString);
|
||||||
{ dumpStdIntVector(); return true; }
|
rc.insert("QStringList", dumpQStringList);
|
||||||
if (!qstrcmp(arg, "vector<string>"))
|
rc.insert("QList<int>", dumpQIntList);
|
||||||
{ dumpStdStringVector(); return true; }
|
rc.insert("QList<std::string>", dumpStdStringQList);
|
||||||
if (!qstrcmp(arg, "vector<wstring>"))
|
rc.insert("QVector<int>", dumpQIntVector);
|
||||||
{ dumpStdWStringVector(); return true; }
|
rc.insert("QMap<int,QString>", dumpQMapIntString);
|
||||||
if (!qstrcmp(arg, "set<int>"))
|
rc.insert("QMap<int,int>", dumpQMapIntInt);
|
||||||
{ dumpStdIntSet(); return true; }
|
rc.insert("string", dumpStdString);
|
||||||
if (!qstrcmp(arg, "set<string>"))
|
rc.insert("wstring", dumpStdWString);
|
||||||
{ dumpStdStringSet(); return true; }
|
rc.insert("list<int>", dumpStdIntList);
|
||||||
if (!qstrcmp(arg, "map<int,string>"))
|
rc.insert("list<string>", dumpStdStringList);
|
||||||
{ dumpStdMapIntString(); return true; }
|
rc.insert("vector<int>", dumpStdIntVector);
|
||||||
if (!qstrcmp(arg, "QObject"))
|
rc.insert("vector<string>", dumpStdStringVector);
|
||||||
{ dumpQObject(); return true; }
|
rc.insert("vector<wstring>", dumpStdWStringVector);
|
||||||
return false;
|
rc.insert("set<int>", dumpStdIntSet);
|
||||||
|
rc.insert("set<string>", dumpStdStringSet);
|
||||||
|
rc.insert("map<int,string>", dumpStdMapIntString);
|
||||||
|
rc.insert("QObject", dumpQObject);
|
||||||
|
rc.insert("QObjectList", dumpQObjectList);
|
||||||
|
rc.insert("QVariant", dumpQVariant);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
printf("\nQt Creator Debugging Helper testing tool\n\n");
|
||||||
printf("Running query protocol\n");
|
printf("Running query protocol\n");
|
||||||
qDumpObjectData440(1, 42, 0, 1, 0, 0, 0, 0);
|
qDumpObjectData440(1, 42, 0, 1, 0, 0, 0, 0);
|
||||||
fputs(qDumpOutBuffer, stdout);
|
fputs(qDumpOutBuffer, stdout);
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
if (argc < 2)
|
|
||||||
|
const TypeDumpFunctionMap tdm = registerTypes();
|
||||||
|
const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: %s [-a]|<type1> <type2..>\n", argv[0]);
|
||||||
|
printf("Supported types: ");
|
||||||
|
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
|
||||||
|
fputs(qPrintable(it.key()), stdout);
|
||||||
|
fputc(' ', stdout);
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = 0;
|
||||||
|
if (argc == 2 && !qstrcmp(argv[1], "-a")) {
|
||||||
|
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
|
||||||
|
printf("\nTesting: %s\n", qPrintable(it.key()));
|
||||||
|
rc += (*it.value())();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
if (!strcmp(arg, "-u")) {
|
printf("\nTesting: %s\n", arg);
|
||||||
optTestUninitialized = true;
|
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(QLatin1String(arg));
|
||||||
printf("\nTesting uninitialized...\n");
|
if (it == cend) {
|
||||||
continue;
|
rc = -1;
|
||||||
|
fprintf(stderr, "\nUnhandled type: %s\n", argv[i]);
|
||||||
|
} else {
|
||||||
|
rc = (*it.value())();
|
||||||
}
|
}
|
||||||
printf("\nTesting %s\n", arg);
|
|
||||||
if (!dumpType(arg))
|
|
||||||
printf("\nUnhandled type: %s\n", arg);
|
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -561,6 +561,10 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
|
|||||||
*errorMessage = msgNotHandled(wd.type);
|
*errorMessage = msgNotHandled(wd.type);
|
||||||
return DumpNotHandled;
|
return DumpNotHandled;
|
||||||
}
|
}
|
||||||
|
if (wd.addr.isEmpty()) {
|
||||||
|
*errorMessage = QString::fromLatin1("Adress is missing for '%1' (%2).").arg(wd.exp, wd.type);
|
||||||
|
return DumpNotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure types are parsed and known.
|
// Ensure types are parsed and known.
|
||||||
if (!ensureInitialized(errorMessage)) {
|
if (!ensureInitialized(errorMessage)) {
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "watchhandler.h"
|
#include "watchhandler.h"
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QCoreApplication>
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -164,6 +165,46 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
|
|||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When querying an item, the queried item is sometimes returned in incomplete form.
|
||||||
|
// Take over values from source.
|
||||||
|
static inline void fixDumperResult(const WatchData &source,
|
||||||
|
QList<WatchData> *result,
|
||||||
|
bool suppressGrandChildren)
|
||||||
|
{
|
||||||
|
const int size = result->size();
|
||||||
|
if (!size)
|
||||||
|
return;
|
||||||
|
WatchData &returned = result->front();
|
||||||
|
if (returned.iname != source.iname)
|
||||||
|
return;
|
||||||
|
if (returned.type.isEmpty())
|
||||||
|
returned.setType(source.type);
|
||||||
|
if (returned.isValueNeeded()) {
|
||||||
|
if (source.isValueKnown()) {
|
||||||
|
returned.setValue(source.value);
|
||||||
|
} else {
|
||||||
|
// Should not happen
|
||||||
|
returned.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size == 1)
|
||||||
|
return;
|
||||||
|
// Fix the children: If the address is missing, we cannot query any further.
|
||||||
|
const QList<WatchData>::iterator wend = result->end();
|
||||||
|
QList<WatchData>::iterator it = result->begin();
|
||||||
|
for (++it; it != wend; ++it) {
|
||||||
|
WatchData &wd = *it;
|
||||||
|
if (wd.addr.isEmpty() && wd.isSomethingNeeded()) {
|
||||||
|
wd.setAllUnneeded();
|
||||||
|
} else {
|
||||||
|
// Hack: Suppress endless recursion of the model. To be fixed,
|
||||||
|
// the model should not query non-visible items.
|
||||||
|
if (suppressGrandChildren && (wd.isChildrenNeeded() || wd.isHasChildrenNeeded()))
|
||||||
|
wd.setHasChildren(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
|
WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
|
||||||
{
|
{
|
||||||
if (debugCDBWatchHandling)
|
if (debugCDBWatchHandling)
|
||||||
@@ -180,9 +221,7 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
|
|||||||
if (debugCDBWatchHandling)
|
if (debugCDBWatchHandling)
|
||||||
qDebug() << "dumper triggered";
|
qDebug() << "dumper triggered";
|
||||||
// Dumpers omit types for complicated templates
|
// Dumpers omit types for complicated templates
|
||||||
if (!m_dumperResult.isEmpty() && m_dumperResult.front().type.isEmpty()
|
fixDumperResult(wd, &m_dumperResult, false);
|
||||||
&& m_dumperResult.front().iname == wd.iname)
|
|
||||||
m_dumperResult.front().setType(wd.type);
|
|
||||||
// Discard the original item and insert the dumper results
|
// Discard the original item and insert the dumper results
|
||||||
foreach(const WatchData &dwd, m_dumperResult)
|
foreach(const WatchData &dwd, m_dumperResult)
|
||||||
m_wh->insertData(dwd);
|
m_wh->insertData(dwd);
|
||||||
@@ -254,12 +293,17 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
|
|||||||
QList<WatchData> dumperResult;
|
QList<WatchData> dumperResult;
|
||||||
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, OwnerDumper, &dumperResult, errorMessage);
|
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, OwnerDumper, &dumperResult, errorMessage);
|
||||||
if (dr == CdbDumperHelper::DumpOk) {
|
if (dr == CdbDumperHelper::DumpOk) {
|
||||||
|
// Hack to stop endless model recursion
|
||||||
|
const bool suppressGrandChildren = !wh->isExpandedIName(incompleteLocal.iname);
|
||||||
|
fixDumperResult(incompleteLocal, &dumperResult, suppressGrandChildren);
|
||||||
foreach(const WatchData &dwd, dumperResult)
|
foreach(const WatchData &dwd, dumperResult)
|
||||||
wh->insertData(dwd);
|
wh->insertData(dwd);
|
||||||
} else {
|
} else {
|
||||||
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
|
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
|
||||||
qWarning("%s", qPrintable(msg));
|
qWarning("%s", qPrintable(msg));
|
||||||
WatchData wd = incompleteLocal;
|
WatchData wd = incompleteLocal;
|
||||||
|
if (wd.isValueNeeded())
|
||||||
|
wd.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>"));
|
||||||
wd.setAllUnneeded();
|
wd.setAllUnneeded();
|
||||||
wh->insertData(wd);
|
wh->insertData(wd);
|
||||||
}
|
}
|
||||||
|
@@ -3192,24 +3192,36 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
|
|||||||
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
|
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::sendWatchParameters(const QByteArray ¶ms0)
|
static inline QString arrayFillCommand(const char *array, const QByteArray ¶ms)
|
||||||
{
|
{
|
||||||
QByteArray params = params0;
|
|
||||||
params.append('\0');
|
|
||||||
char buf[50];
|
char buf[50];
|
||||||
sprintf(buf, "set {char[%d]} &qDumpInBuffer = {", params.size());
|
sprintf(buf, "set {char[%d]} &%s = {", params.size(), array);
|
||||||
QByteArray encoded;
|
QByteArray encoded;
|
||||||
encoded.append(buf);
|
encoded.append(buf);
|
||||||
for (int i = 0; i != params.size(); ++i) {
|
const int size = params.size();
|
||||||
|
for (int i = 0; i != size; ++i) {
|
||||||
sprintf(buf, "%d,", int(params[i]));
|
sprintf(buf, "%d,", int(params[i]));
|
||||||
encoded.append(buf);
|
encoded.append(buf);
|
||||||
}
|
}
|
||||||
encoded[encoded.size() - 1] = '}';
|
encoded[encoded.size() - 1] = '}';
|
||||||
|
return _(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::sendWatchParameters(const QByteArray ¶ms0)
|
||||||
|
{
|
||||||
|
QByteArray params = params0;
|
||||||
|
params.append('\0');
|
||||||
|
const QString inBufferCmd = arrayFillCommand("qDumpInBuffer", params);
|
||||||
|
|
||||||
params.replace('\0','!');
|
params.replace('\0','!');
|
||||||
emit gdbInputAvailable(LogMisc, QString::fromUtf8(params));
|
emit gdbInputAvailable(LogMisc, QString::fromUtf8(params));
|
||||||
|
|
||||||
postCommand(_(encoded));
|
params.clear();
|
||||||
|
params.append('\0');
|
||||||
|
const QString outBufferCmd = arrayFillCommand("qDumpOutBuffer", params);
|
||||||
|
|
||||||
|
postCommand(inBufferCmd);
|
||||||
|
postCommand(outBufferCmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleVarAssign(const GdbResultRecord &, const QVariant &)
|
void GdbEngine::handleVarAssign(const GdbResultRecord &, const QVariant &)
|
||||||
|
@@ -209,6 +209,8 @@ QString WatchData::toString() const
|
|||||||
QTextStream str(&res);
|
QTextStream str(&res);
|
||||||
if (!iname.isEmpty())
|
if (!iname.isEmpty())
|
||||||
str << "iname=\"" << iname << doubleQuoteComma;
|
str << "iname=\"" << iname << doubleQuoteComma;
|
||||||
|
if (!addr.isEmpty())
|
||||||
|
str << "addr=\"" << addr << doubleQuoteComma;
|
||||||
if (!exp.isEmpty())
|
if (!exp.isEmpty())
|
||||||
str << "exp=\"" << exp << doubleQuoteComma;
|
str << "exp=\"" << exp << doubleQuoteComma;
|
||||||
|
|
||||||
@@ -780,6 +782,7 @@ static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *i
|
|||||||
|
|
||||||
void WatchModel::insertData(const WatchData &data)
|
void WatchModel::insertData(const WatchData &data)
|
||||||
{
|
{
|
||||||
|
// qDebug() << "WMI:" << data.toString();
|
||||||
QTC_ASSERT(!data.iname.isEmpty(), return);
|
QTC_ASSERT(!data.iname.isEmpty(), return);
|
||||||
WatchItem *parent = findItem(parentName(data.iname), m_root);
|
WatchItem *parent = findItem(parentName(data.iname), m_root);
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
|
@@ -470,16 +470,19 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
|||||||
QtDumperResult::Child::Child() :
|
QtDumperResult::Child::Child() :
|
||||||
keyEncoded(0),
|
keyEncoded(0),
|
||||||
valueEncoded(0),
|
valueEncoded(0),
|
||||||
childCount(0),
|
childCount(-1),
|
||||||
valuedisabled(false)
|
valuedisabled(false),
|
||||||
|
valueEncountered(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperResult::QtDumperResult() :
|
QtDumperResult::QtDumperResult() :
|
||||||
|
valueEncountered(false),
|
||||||
valueEncoded(0),
|
valueEncoded(0),
|
||||||
valuedisabled(false),
|
valuedisabled(false),
|
||||||
childCount(0),
|
childCount(-1),
|
||||||
internal(false)
|
internal(false),
|
||||||
|
childChildCount(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,15 +491,17 @@ void QtDumperResult::clear()
|
|||||||
iname.clear();
|
iname.clear();
|
||||||
value.clear();
|
value.clear();
|
||||||
address.clear();
|
address.clear();
|
||||||
|
addressInfo.clear();
|
||||||
type.clear();
|
type.clear();
|
||||||
extra.clear();
|
extra.clear();
|
||||||
displayedType.clear();
|
displayedType.clear();
|
||||||
valueEncoded = 0;
|
valueEncoded = 0;
|
||||||
valuedisabled = false;
|
valueEncountered = valuedisabled = false;
|
||||||
childCount = 0;
|
childCount = -1;
|
||||||
internal = false;
|
internal = false;
|
||||||
childType.clear();
|
childType.clear();
|
||||||
children.clear();
|
children.clear();
|
||||||
|
childChildCount = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<WatchData> QtDumperResult::toWatchData(int source) const
|
QList<WatchData> QtDumperResult::toWatchData(int source) const
|
||||||
@@ -508,15 +513,22 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
|
|||||||
const QChar dot = QLatin1Char('.');
|
const QChar dot = QLatin1Char('.');
|
||||||
const int lastDotIndex = root.iname.lastIndexOf(dot);
|
const int lastDotIndex = root.iname.lastIndexOf(dot);
|
||||||
root.exp = root.name = lastDotIndex == -1 ? iname : iname.mid(lastDotIndex + 1);
|
root.exp = root.name = lastDotIndex == -1 ? iname : iname.mid(lastDotIndex + 1);
|
||||||
|
if (valueEncountered) {
|
||||||
root.setValue(decodeData(value, valueEncoded));
|
root.setValue(decodeData(value, valueEncoded));
|
||||||
root.setType(displayedType.isEmpty() ? type : displayedType);
|
|
||||||
root.valuedisabled = valuedisabled;
|
root.valuedisabled = valuedisabled;
|
||||||
|
}
|
||||||
|
root.setType(displayedType.isEmpty() ? type : displayedType);
|
||||||
root.setAddress(address);
|
root.setAddress(address);
|
||||||
root.source = source;
|
root.source = source;
|
||||||
|
if (childCount >= 0)
|
||||||
root.setHasChildren(childCount > 0);
|
root.setHasChildren(childCount > 0);
|
||||||
// Children
|
// Children. Sanity check after parsing sets childcount to list size
|
||||||
if (childCount > 0) {
|
// if list is not empty
|
||||||
if (children.size() == childCount) {
|
if (children.empty()) {
|
||||||
|
if (childCount > 0)
|
||||||
|
root.setChildrenNeeded();
|
||||||
|
} else {
|
||||||
|
root.setChildrenUnneeded();
|
||||||
for (int c = 0; c < childCount; c++) {
|
for (int c = 0; c < childCount; c++) {
|
||||||
const Child &dchild = children.at(c);
|
const Child &dchild = children.at(c);
|
||||||
rc.push_back(WatchData());
|
rc.push_back(WatchData());
|
||||||
@@ -536,17 +548,35 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
wchild.exp = dchild.exp;
|
wchild.exp = dchild.exp;
|
||||||
|
if (dchild.valueEncountered) {
|
||||||
wchild.valuedisabled = dchild.valuedisabled;
|
wchild.valuedisabled = dchild.valuedisabled;
|
||||||
|
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
|
||||||
|
}
|
||||||
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
|
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
|
||||||
wchild.setAddress(dchild.address);
|
wchild.setAddress(dchild.address);
|
||||||
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
|
// Child overrides.
|
||||||
|
const int effectiveChildChildCount = dchild.childCount == -1 ? childChildCount : dchild.childCount;
|
||||||
|
switch (effectiveChildChildCount) {
|
||||||
|
case -1:
|
||||||
|
wchild.setChildrenNeeded();
|
||||||
|
wchild.setHasChildrenNeeded();
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
wchild.setHasChildren(false);
|
wchild.setHasChildren(false);
|
||||||
}
|
break;
|
||||||
root.setChildrenUnneeded();
|
default:
|
||||||
} else {
|
wchild.setHasChildren(true);
|
||||||
root.setChildrenNeeded();
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (debug) {
|
||||||
|
QDebug nospace = qDebug().nospace();
|
||||||
|
nospace << "QtDumperResult::toWatchData" << *this << '\n';
|
||||||
|
foreach(const WatchData &wd, rc)
|
||||||
|
nospace << " " << wd.toString() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,11 +584,20 @@ QDebug operator<<(QDebug in, const QtDumperResult &d)
|
|||||||
{
|
{
|
||||||
QDebug nospace = in.nospace();
|
QDebug nospace = in.nospace();
|
||||||
nospace << " iname=" << d.iname << " type=" << d.type << " displayed=" << d.displayedType
|
nospace << " iname=" << d.iname << " type=" << d.type << " displayed=" << d.displayedType
|
||||||
<< " address=" << d.address
|
<< " address=" << d.address;
|
||||||
|
if (!d.addressInfo.isEmpty())
|
||||||
|
nospace << " addressInfo=" << d.addressInfo;
|
||||||
|
if (d.valueEncountered) {
|
||||||
|
nospace << " encoded=" << d.valueEncoded
|
||||||
<< " value=" << d.value
|
<< " value=" << d.value
|
||||||
<< " disabled=" << d.valuedisabled
|
<< " disabled=" << d.valuedisabled;
|
||||||
<< " encoded=" << d.valueEncoded << " internal=" << d.internal
|
} else {
|
||||||
|
nospace << " <no value>";
|
||||||
|
}
|
||||||
|
nospace << " childnumchild=" << d.childChildCount
|
||||||
|
<< " internal=" << d.internal
|
||||||
<< " extra='" << d.extra << "'\n";
|
<< " extra='" << d.extra << "'\n";
|
||||||
|
|
||||||
const int realChildCount = d.children.size();
|
const int realChildCount = d.children.size();
|
||||||
if (d.childCount || realChildCount) {
|
if (d.childCount || realChildCount) {
|
||||||
nospace << "childCount=" << d.childCount << '/' << realChildCount
|
nospace << "childCount=" << d.childCount << '/' << realChildCount
|
||||||
@@ -571,8 +610,12 @@ QDebug operator<<(QDebug in, const QtDumperResult &d)
|
|||||||
<< " name=" << c.name;
|
<< " name=" << c.name;
|
||||||
if (!c.key.isEmpty())
|
if (!c.key.isEmpty())
|
||||||
nospace << " keyencoded=" << c.keyEncoded << " key=" << c.key;
|
nospace << " keyencoded=" << c.keyEncoded << " key=" << c.key;
|
||||||
nospace << " valueencoded=" << c.valueEncoded << " value=" << c.value
|
if (c.valueEncountered) {
|
||||||
<< "childcount=" << c.childCount << '\n';
|
nospace << " valueencoded=" << c.valueEncoded << " value=" << c.value;
|
||||||
|
} else {
|
||||||
|
nospace << " <no value>";
|
||||||
|
}
|
||||||
|
nospace << "childcount=" << c.childCount << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return in;
|
return in;
|
||||||
@@ -608,6 +651,7 @@ void QtDumperHelper::clear()
|
|||||||
m_sizeCache.clear();
|
m_sizeCache.clear();
|
||||||
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
||||||
m_expressionCache.clear();
|
m_expressionCache.clear();
|
||||||
|
m_dumperVersion.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void formatQtVersion(int v, QTextStream &str)
|
static inline void formatQtVersion(int v, QTextStream &str)
|
||||||
@@ -622,7 +666,7 @@ QString QtDumperHelper::toString(bool debug) const
|
|||||||
QTextStream str(&rc);
|
QTextStream str(&rc);
|
||||||
str << "version=";
|
str << "version=";
|
||||||
formatQtVersion(m_qtVersion, str);
|
formatQtVersion(m_qtVersion, str);
|
||||||
str << " namespace='" << m_qtNamespace << "'," << m_nameTypeMap.size() << " known types <type enum>: ";
|
str << "dumperversion='" << m_dumperVersion << "' namespace='" << m_qtNamespace << "'," << m_nameTypeMap.size() << " known types <type enum>: ";
|
||||||
const NameTypeMap::const_iterator cend = m_nameTypeMap.constEnd();
|
const NameTypeMap::const_iterator cend = m_nameTypeMap.constEnd();
|
||||||
for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) {
|
for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) {
|
||||||
str <<",[" << it.key() << ',' << it.value() << ']';
|
str <<",[" << it.key() << ',' << it.value() << ']';
|
||||||
@@ -639,9 +683,9 @@ QString QtDumperHelper::toString(bool debug) const
|
|||||||
}
|
}
|
||||||
const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
|
const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
|
||||||
return QCoreApplication::translate("QtDumperHelper",
|
return QCoreApplication::translate("QtDumperHelper",
|
||||||
"%n known types, Qt version: %1, Qt namespace: %2",
|
"%n known types, Qt version: %1, Qt namespace: %2 Dumper version: %3",
|
||||||
0, QCoreApplication::CodecForTr,
|
0, QCoreApplication::CodecForTr,
|
||||||
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace);
|
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace, m_dumperVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperHelper::Type QtDumperHelper::simpleType(const QString &simpleType) const
|
QtDumperHelper::Type QtDumperHelper::simpleType(const QString &simpleType) const
|
||||||
@@ -726,10 +770,9 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
|
|||||||
|
|
||||||
QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Type t)
|
QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Type t)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case QAbstractItemType:
|
case QAbstractItemType:
|
||||||
case QObjectSlotType:
|
|
||||||
case QObjectSignalType:
|
|
||||||
case QVectorType:
|
case QVectorType:
|
||||||
case StdMapType:
|
case StdMapType:
|
||||||
return NeedsComplexExpression;
|
return NeedsComplexExpression;
|
||||||
@@ -738,6 +781,7 @@ QtDumperHelper::ExpressionRequirement QtDumperHelper::expressionRequirements(Typ
|
|||||||
case QMapNodeType:
|
case QMapNodeType:
|
||||||
return NeedsCachedExpression;
|
return NeedsCachedExpression;
|
||||||
default:
|
default:
|
||||||
|
// QObjectSlotType, QObjectSignalType need the signal number, which is numeric
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NeedsNoExpression;
|
return NeedsNoExpression;
|
||||||
@@ -968,9 +1012,9 @@ public:
|
|||||||
explicit QueryDumperParser(const char *s);
|
explicit QueryDumperParser(const char *s);
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
Data() : qtVersion(0) {}
|
|
||||||
QString qtNameSpace;
|
QString qtNameSpace;
|
||||||
QString qtVersion;
|
QString qtVersion;
|
||||||
|
QString dumperVersion;
|
||||||
QStringList types;
|
QStringList types;
|
||||||
QList<SizeEntry> sizes;
|
QList<SizeEntry> sizes;
|
||||||
QMap<QString, QString> expressionCache;
|
QMap<QString, QString> expressionCache;
|
||||||
@@ -986,7 +1030,7 @@ protected:
|
|||||||
virtual bool handleValue(const char *k, int size);
|
virtual bool handleValue(const char *k, int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Mode { None, ExpectingDumpers, ExpectingVersion,
|
enum Mode { None, ExpectingDumpers, ExpectingQtVersion, ExpectingDumperVersion,
|
||||||
ExpectingNameSpace, ExpectingSizes, ExpectingExpressionCache };
|
ExpectingNameSpace, ExpectingSizes, ExpectingExpressionCache };
|
||||||
Mode m_mode;
|
Mode m_mode;
|
||||||
Data m_data;
|
Data m_data;
|
||||||
@@ -1017,7 +1061,11 @@ bool QueryDumperParser::handleKeyword(const char *k, int size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!qstrncmp(k, "qtversion", size)) {
|
if (!qstrncmp(k, "qtversion", size)) {
|
||||||
m_mode = ExpectingVersion;
|
m_mode = ExpectingQtVersion;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!qstrncmp(k, "dumperversion", size)) {
|
||||||
|
m_mode = ExpectingDumperVersion;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!qstrncmp(k, "namespace", size)) {
|
if (!qstrncmp(k, "namespace", size)) {
|
||||||
@@ -1038,7 +1086,7 @@ bool QueryDumperParser::handleKeyword(const char *k, int size)
|
|||||||
|
|
||||||
bool QueryDumperParser::handleListStart()
|
bool QueryDumperParser::handleListStart()
|
||||||
{
|
{
|
||||||
return m_mode == ExpectingDumpers || m_mode == ExpectingVersion;
|
return m_mode == ExpectingDumpers || m_mode == ExpectingQtVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueryDumperParser::handleListEnd()
|
bool QueryDumperParser::handleListEnd()
|
||||||
@@ -1064,7 +1112,10 @@ bool QueryDumperParser::handleValue(const char *k, int size)
|
|||||||
case ExpectingNameSpace:
|
case ExpectingNameSpace:
|
||||||
m_data.qtNameSpace = QString::fromLatin1(k, size);
|
m_data.qtNameSpace = QString::fromLatin1(k, size);
|
||||||
break;
|
break;
|
||||||
case ExpectingVersion: // ["4","1","5"]
|
case ExpectingDumperVersion:
|
||||||
|
m_data.dumperVersion = QString::fromLatin1(k, size);
|
||||||
|
break;
|
||||||
|
case ExpectingQtVersion: // ["4","1","5"]
|
||||||
if (!m_data.qtVersion.isEmpty())
|
if (!m_data.qtVersion.isEmpty())
|
||||||
m_data.qtVersion += QLatin1Char('.');
|
m_data.qtVersion += QLatin1Char('.');
|
||||||
m_data.qtVersion += QString::fromLatin1(k, size);
|
m_data.qtVersion += QString::fromLatin1(k, size);
|
||||||
@@ -1092,6 +1143,7 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
|||||||
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
|
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
|
||||||
addSize(se.first, se.second);
|
addSize(se.first, se.second);
|
||||||
m_expressionCache = parser.data().expressionCache;
|
m_expressionCache = parser.data().expressionCache;
|
||||||
|
m_dumperVersion = parser.data().dumperVersion;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1248,17 +1300,6 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
case QAbstractItemType:
|
case QAbstractItemType:
|
||||||
inner = data.addr.mid(1);
|
inner = data.addr.mid(1);
|
||||||
break;
|
break;
|
||||||
case QObjectType:
|
|
||||||
case QWidgetType:
|
|
||||||
if (debugger == GdbDebugger) {
|
|
||||||
extraArgs[0] = QLatin1String("(char*)&((('");
|
|
||||||
extraArgs[0] += m_qtNamespace;
|
|
||||||
extraArgs[0] += QLatin1String("QObjectPrivate'*)&");
|
|
||||||
extraArgs[0] += data.exp;
|
|
||||||
extraArgs[0] += QLatin1String(")->children)-(char*)&");
|
|
||||||
extraArgs[0] += data.exp;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QVectorType:
|
case QVectorType:
|
||||||
extraArgs[1] = QLatin1String("(char*)&((");
|
extraArgs[1] = QLatin1String("(char*)&((");
|
||||||
extraArgs[1] += data.exp;
|
extraArgs[1] += data.exp;
|
||||||
@@ -1355,6 +1396,8 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
qWarning("Unknown type encountered in %s.\n", Q_FUNC_INFO);
|
qWarning("Unknown type encountered in %s.\n", Q_FUNC_INFO);
|
||||||
break;
|
break;
|
||||||
case SupportedType:
|
case SupportedType:
|
||||||
|
case QObjectType:
|
||||||
|
case QWidgetType:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1412,6 +1455,7 @@ private:
|
|||||||
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
|
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
|
||||||
ExpectingValueDisabled, ExpectingValueEncoded,
|
ExpectingValueDisabled, ExpectingValueEncoded,
|
||||||
ExpectingCommonChildType, ExpectingChildCount,
|
ExpectingCommonChildType, ExpectingChildCount,
|
||||||
|
ExpectingChildChildOverrideCount,
|
||||||
ExpectingExtra,
|
ExpectingExtra,
|
||||||
IgnoreNext,
|
IgnoreNext,
|
||||||
ChildModeStart,
|
ChildModeStart,
|
||||||
@@ -1488,7 +1532,7 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
|
|||||||
if (!qstrncmp(keyword, "displayedtype", size))
|
if (!qstrncmp(keyword, "displayedtype", size))
|
||||||
return ExpectingDisplayedType;
|
return ExpectingDisplayedType;
|
||||||
if (!qstrncmp(keyword, "childnumchild", size))
|
if (!qstrncmp(keyword, "childnumchild", size))
|
||||||
return IgnoreNextChildMode;
|
return ExpectingChildChildOverrideCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return in > ChildModeStart ? IgnoreNextChildMode : IgnoreNext;
|
return in > ChildModeStart ? IgnoreNextChildMode : IgnoreNext;
|
||||||
@@ -1519,10 +1563,17 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
|||||||
case ExpectingIName:
|
case ExpectingIName:
|
||||||
m_result.iname = QString::fromLatin1(valueBA);
|
m_result.iname = QString::fromLatin1(valueBA);
|
||||||
break;
|
break;
|
||||||
case ExpectingAddress:
|
case ExpectingAddress: {
|
||||||
m_result.address = QString::fromLatin1(valueBA);
|
const QString address = QString::fromLatin1(valueBA);
|
||||||
|
if (address.startsWith(QLatin1String("0x"))) {
|
||||||
|
m_result.address = address;
|
||||||
|
} else {
|
||||||
|
m_result.addressInfo = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ExpectingValue:
|
case ExpectingValue:
|
||||||
|
m_result.valueEncountered = true;
|
||||||
m_result.value = valueBA;
|
m_result.value = valueBA;
|
||||||
break;
|
break;
|
||||||
case ExpectingValueDisabled:
|
case ExpectingValueDisabled:
|
||||||
@@ -1549,6 +1600,9 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
|||||||
case ExpectingChildCount:
|
case ExpectingChildCount:
|
||||||
m_result.childCount = QString::fromLatin1(valueBA).toInt();
|
m_result.childCount = QString::fromLatin1(valueBA).toInt();
|
||||||
break;
|
break;
|
||||||
|
case ExpectingChildChildOverrideCount:
|
||||||
|
m_result.childChildCount = QString::fromLatin1(valueBA).toInt();
|
||||||
|
break;
|
||||||
case ExpectingChildren:
|
case ExpectingChildren:
|
||||||
case IgnoreNextChildMode:
|
case IgnoreNextChildMode:
|
||||||
case IgnoreNext:
|
case IgnoreNext:
|
||||||
@@ -1566,6 +1620,7 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
|||||||
m_result.children.back().key = valueBA;
|
m_result.children.back().key = valueBA;
|
||||||
break;
|
break;
|
||||||
case ExpectingChildValue:
|
case ExpectingChildValue:
|
||||||
|
m_result.children.back().valueEncountered = true;
|
||||||
m_result.children.back().value = valueBA;
|
m_result.children.back().value = valueBA;
|
||||||
break;
|
break;
|
||||||
case ExpectingChildExpression:
|
case ExpectingChildExpression:
|
||||||
@@ -1590,11 +1645,12 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
|||||||
bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
|
bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
|
||||||
{
|
{
|
||||||
ValueDumperParser parser(data);
|
ValueDumperParser parser(data);
|
||||||
|
|
||||||
if (!parser.run())
|
if (!parser.run())
|
||||||
return false;
|
return false;
|
||||||
*r = parser.result();
|
*r = parser.result();
|
||||||
// Sanity
|
// Sanity
|
||||||
if (r->childCount < r->children.size())
|
if (!r->children.empty() && r->childCount != r->children.size())
|
||||||
r->childCount = r->children.size();
|
r->childCount = r->children.size();
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << '\n' << data << '\n' << *r;
|
qDebug() << '\n' << data << '\n' << *r;
|
||||||
|
@@ -99,6 +99,7 @@ struct QtDumperResult
|
|||||||
QString exp;
|
QString exp;
|
||||||
QString type;
|
QString type;
|
||||||
QByteArray key;
|
QByteArray key;
|
||||||
|
bool valueEncountered;
|
||||||
QByteArray value;
|
QByteArray value;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,15 +109,18 @@ struct QtDumperResult
|
|||||||
|
|
||||||
QString iname;
|
QString iname;
|
||||||
QString address;
|
QString address;
|
||||||
|
QString addressInfo; // "<synthetic>" or such, in the 2nd adress field.
|
||||||
QString type;
|
QString type;
|
||||||
QString extra;
|
QString extra;
|
||||||
QString displayedType;
|
QString displayedType;
|
||||||
|
bool valueEncountered;
|
||||||
QByteArray value;
|
QByteArray value;
|
||||||
int valueEncoded;
|
int valueEncoded;
|
||||||
bool valuedisabled;
|
bool valuedisabled;
|
||||||
int childCount;
|
int childCount;
|
||||||
bool internal;
|
bool internal;
|
||||||
QString childType;
|
QString childType;
|
||||||
|
int childChildCount;
|
||||||
QList <Child> children;
|
QList <Child> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -242,6 +246,7 @@ private:
|
|||||||
|
|
||||||
QMap<QString, QString> m_expressionCache;
|
QMap<QString, QString> m_expressionCache;
|
||||||
int m_qtVersion;
|
int m_qtVersion;
|
||||||
|
QString m_dumperVersion;
|
||||||
QString m_qtNamespace;
|
QString m_qtNamespace;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user