OSDN Git Service

debugger: implement a dumper for QAbstractItemModel
authorhjk <qtc-committer@nokia.com>
Wed, 3 Jun 2009 10:46:55 +0000 (12:46 +0200)
committerhjk <qtc-committer@nokia.com>
Wed, 3 Jun 2009 10:48:48 +0000 (12:48 +0200)
This also squashes a namespace related bug introduced by the watchutils
refactoring.

share/qtcreator/gdbmacros/gdbmacros.cpp
src/plugins/debugger/debuggeroutputwindow.cpp
src/plugins/debugger/gdb/gdbengine.cpp
src/plugins/debugger/watchutils.cpp
src/plugins/debugger/watchutils.h
tests/manual/gdbdebugger/simple/app.cpp

index 5f75cc8..1bf7670 100644 (file)
@@ -851,6 +851,102 @@ static void qDumpInnerValueOrPointer(QDumper &d,
 
 //////////////////////////////////////////////////////////////////////////////
 
+struct ModelIndex { int r; int c; void *p; void *m; };
+
+static void qDumpQAbstractItem(QDumper &d)
+{
+    ModelIndex mm;
+    mm.r = mm.c = 0;
+    mm.p = mm.m = 0;
+    sscanf(d.templateParameters[0], "%d,%d,%p,%p", &mm.r, &mm.c, &mm.p, &mm.m);
+    const QModelIndex &mi(*reinterpret_cast<QModelIndex *>(&mm));
+    const QAbstractItemModel *m = mi.model();
+    const int rowCount = m->rowCount(mi);
+    if (rowCount < 0)
+        return;
+    const int columnCount = m->columnCount(mi);
+    if (columnCount < 0)
+        return;
+    P(d, "type", NS"QAbstractItem");
+    P(d, "addr", "$" << mm.r << "," << mm.c << "," << mm.p << "," << mm.m);
+    //P(d, "value", "(" << rowCount << "," << columnCount << ")");
+    P(d, "value", m->data(mi, Qt::DisplayRole).toString());
+    P(d, "valueencoded", "2");
+    P(d, "numchild", "1");
+    if (d.dumpChildren) {
+        d << ",children=[";
+        for (int row = 0; row < rowCount; ++row) {
+            for (int column = 0; column < columnCount; ++column) {
+                QModelIndex child = m->index(row, column, mi);
+                d.beginHash();
+                P(d, "name", "[" << row << "," << column << "]");
+                //P(d, "numchild", (m->hasChildren(child) ? "1" : "0"));
+                P(d, "numchild", "1");
+                P(d, "addr", "$" << child.row() << "," << child.column() << ","
+                    << child.internalPointer() << "," << child.model());
+                P(d, "type", NS"QAbstractItem");
+                P(d, "value", m->data(mi, Qt::DisplayRole).toString());
+                P(d, "valueencoded", "2");
+                d.endHash();
+            }
+        }
+        d.beginHash();
+        P(d, "name", "DisplayRole");
+        P(d, "numchild", 0); 
+        P(d, "value", m->data(mi, Qt::DisplayRole).toString());
+        P(d, "valueencoded", 2);
+        P(d, "type", NS"QString");
+        d.endHash();
+        d << "]";
+    }
+    d.disarm();
+}
+
+static void qDumpQAbstractItemModel(QDumper &d)
+{
+    const QAbstractItemModel &m = *reinterpret_cast<const QAbstractItemModel *>(d.data);
+
+    const int rowCount = m.rowCount();
+    if (rowCount < 0)
+        return;
+    const int columnCount = m.columnCount();
+    if (columnCount < 0)
+        return;
+
+    P(d, "type", NS"QAbstractItemModel");
+    P(d, "value", "(" << rowCount << "," << columnCount << ")");
+    P(d, "numchild", "1");
+    if (d.dumpChildren) {
+        d << ",children=[";
+        d.beginHash();
+            P(d, "numchild", "1");
+            P(d, "name", NS"QObject");
+            P(d, "addr", d.data);
+            P(d, "value", m.objectName());
+            P(d, "valueencoded", "2");
+            P(d, "type", NS"QObject");
+            P(d, "displayedtype", m.metaObject()->className());
+        d.endHash();
+        for (int row = 0; row < rowCount; ++row) {
+            for (int column = 0; column < columnCount; ++column) {
+                QModelIndex mi = m.index(row, column);
+                d.beginHash();
+                P(d, "name", "[" << row << "," << column << "]");
+                P(d, "value", m.data(mi, Qt::DisplayRole).toString());
+                P(d, "valueencoded", "2");
+                //P(d, "numchild", (m.hasChildren(mi) ? "1" : "0"));
+                P(d, "numchild", "1");
+                P(d, "addr", "$" << mi.row() << "," << mi.column() << ","
+                    << mi.internalPointer() << "," << mi.model());
+                P(d, "type", NS"QAbstractItem");
+                d.endHash();
+            }
+        }
+        d << "]";
+    }
+    d.disarm();
+}
+
 static void qDumpQByteArray(QDumper &d)
 {
     const QByteArray &ba = *reinterpret_cast<const QByteArray *>(d.data);
@@ -1210,7 +1306,7 @@ static void qDumpQImage(QDumper &d)
     if (d.dumpChildren) {
         d << ",children=[";
         d.beginHash();
-            P(d, "name", "key");
+            P(d, "name", "data");
             P(d, "type", NS "QImageData");
             P(d, "addr", d.data);
         d.endHash();
@@ -2533,7 +2629,8 @@ static void handleProtocolVersion2and3(QDumper & d)
 
     d.setupTemplateParameters();
     P(d, "iname", d.iname);
-    P(d, "addr", d.data);
+    if (d.data)
+        P(d, "addr", d.data);
 
 #ifdef QT_NO_QDATASTREAM
     if (d.protocolVersion == 3) {
@@ -2555,6 +2652,12 @@ static void handleProtocolVersion2and3(QDumper & d)
             if (isEqual(type, "map"))
                 qDumpStdMap(d);
             break;
+        case 'A':
+            if (isEqual(type, "QAbstractItemModel"))
+                qDumpQAbstractItemModel(d);
+            else if (isEqual(type, "QAbstractItem"))
+                qDumpQAbstractItem(d);
+            break;
         case 'B':
             if (isEqual(type, "QByteArray"))
                 qDumpQByteArray(d);
@@ -2715,6 +2818,8 @@ void *qDumpObjectData440(
         // They are mentioned here nevertheless. For types that are not listed
         // here, dumpers won't be used.
         d << "dumpers=["
+            "\""NS"QAbstractItem\","
+            "\""NS"QAbstractItemModel\","
             "\""NS"QByteArray\","
             "\""NS"QDateTime\","
             "\""NS"QDir\","
@@ -2810,7 +2915,6 @@ void *qDumpObjectData440(
         d.iname     = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
         d.exp       = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
         d.innertype = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
-        d.iname     = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
 
         handleProtocolVersion2and3(d);
     }
index d50536e..9c51a53 100644 (file)
@@ -252,8 +252,8 @@ void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &outp
     foreach (QString line, output.split("\n")) {
         // FIXME: QTextEdit asserts on really long lines...
         const int n = 3000;
-        //if (line.size() > n)
-        //    line = line.left(n) + " [...] <cut off>";
+        if (line.size() > n)
+            line = line.left(n) + " [...] <cut off>";
         m_combinedText->appendPlainText(prefix + line);
     }
     QTextCursor cursor = m_combinedText->textCursor();
index b0a6298..770586a 100644 (file)
@@ -2813,7 +2813,7 @@ static void setWatchDataAddress(WatchData &data, const GdbMi &mi)
 {
     if (mi.isValid()) {
         data.addr = _(mi.data());
-        if (data.exp.isEmpty())
+        if (data.exp.isEmpty() && !data.addr.startsWith(_("$")))
             data.exp = _("(*(") + gdbQuoteTypes(data.type) + _("*)") + data.addr + _c(')');
     }
 }
@@ -2885,7 +2885,6 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
         return;
     }
     WatchData data = data0;
-    QTC_ASSERT(!data.exp.isEmpty(), return);
 
     QByteArray params;
     QStringList extraArgs;
@@ -2900,6 +2899,8 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
     QString addr;
     if (data.addr.startsWith(__("0x")))
         addr = _("(void*)") + data.addr;
+    else if (data.exp.isEmpty()) // happens e.g. for QAbstractItem
+        addr = _("0");
     else
         addr = _("&(") + data.exp + _c(')');
 
index f074ee2..887d0c7 100644 (file)
@@ -658,6 +658,7 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
     if (s.startsWith(QLatin1String("std::")))
         return stdType(s.mid(5));
     // Strip namespace
+    // FIXME: that's not a good idea as it makes all namespaces equal.
     const int namespaceIndex = s.lastIndexOf(QLatin1String("::"));
     if (namespaceIndex == -1) {
         // None ... check for std..
@@ -665,7 +666,7 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
         if (sType != UnknownType)
             return sType;
     } else {
-        s.remove(namespaceIndex + 2);
+        s = s.mid(namespaceIndex + 2);
     }
     if (s == QLatin1String("QObject"))
         return QObjectType;
@@ -677,6 +678,8 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
         return QObjectSignalType;
     if (s == QLatin1String("QVector"))
         return QVectorType;
+    if (s == QLatin1String("QAbstractItem"))
+        return QAbstractItemType;
     if (s == QLatin1String("QMap"))
         return QMapType;
     if (s == QLatin1String("QMultiMap"))
@@ -689,6 +692,7 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
 bool QtDumperHelper::needsExpressionSyntax(Type t)
 {
     switch (t) {
+        case QAbstractItemType:
         case QObjectSlotType:
         case QObjectSignalType:
         case QMapType:
@@ -1058,6 +1062,7 @@ void QtDumperHelper::addSize(const QString &name, int size)
             break;
         }
         if (name == QLatin1String("std::wstring")) {
+            // FIXME: check space between > > below?
             m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size);
             break;
         }
@@ -1078,7 +1083,7 @@ QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const
     const Type st = simpleType(typeName);
     if (st != UnknownType) {
         td.isTemplate = false;
-        td.type =st;
+        td.type = st;
         return td;
     }
     // Try template
@@ -1129,6 +1134,8 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
     if (outertype == m_qtNamespace + QLatin1String("QWidget"))
         outertype = m_qtNamespace + QLatin1String("QObject");
 
+    QString inner = td.inner;
+
     extraArgs.clear();
 
     if (!inners.empty()) {
@@ -1147,6 +1154,9 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
 
     // in rare cases we need more or less:
     switch (td.type) {
+    case QAbstractItemType:
+        inner = data.addr.mid(1);
+        break;
     case QObjectType:
     case QWidgetType:
         if (debugger == GdbDebugger) {
@@ -1258,9 +1268,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
     inBuffer->append('\0');
     inBuffer->append(data.exp.toUtf8());
     inBuffer->append('\0');
-    inBuffer->append(td.inner.toUtf8());
-    inBuffer->append('\0');
-    inBuffer->append(data.iname.toUtf8());
+    inBuffer->append(inner.toUtf8());
     inBuffer->append('\0');
 
     if (debug)
index e87b3cd..2b8ef86 100644 (file)
@@ -145,6 +145,7 @@ public:
         UnknownType,
         SupportedType, // A type that requires no special handling by the dumper
         // Below types require special handling
+        QAbstractItemType,
         QObjectType, QWidgetType, QObjectSlotType, QObjectSignalType,
         QVectorType, QMapType, QMultiMapType, QMapNodeType,
         StdVectorType, StdDequeType, StdSetType, StdMapType, StdStackType,
index de12a54..349055c 100644 (file)
@@ -48,6 +48,7 @@
 #include <QtGui/QLabel>
 #include <QtGui/QPainter>
 #include <QtGui/QPainterPath>
+#include <QtGui/QStandardItemModel>
 
 #include <QtNetwork/QHostAddress>
 
@@ -787,6 +788,21 @@ void testStdVector()
     vec.push_back(false);
 }
 
+void testQStandardItemModel()
+{
+    QStandardItemModel m;
+    QStandardItem *i1, *i2, *i11;
+    m.appendRow(QList<QStandardItem *>()
+         << (i1 = new QStandardItem("1")) << (new QStandardItem("a")));
+    m.appendRow(QList<QStandardItem *>()
+         << (i2 = new QStandardItem("2")) << (new QStandardItem("b")));
+    i1->appendRow(QList<QStandardItem *>()
+         << (i11 = new QStandardItem("11")) << (new QStandardItem("aa")));
+    int i = 1;
+    ++i;
+    ++i;
+}
+
 void testQString()
 {
     QString str = "Hello ";
@@ -1090,6 +1106,7 @@ int main(int argc, char *argv[])
     QStringList list;
     list << "aaa" << "bbb" << "cc";
 
+    testQStandardItemModel();
     testQImage();
     testNoArgumentName(1, 2, 3);
     testIO();