From a47fa969cda3709f2d5cd394fa5023fd9f085495 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Mon, 15 Mar 2010 14:48:06 +0100
Subject: [PATCH] debugger: speed up QImage dumper

---
 share/qtcreator/gdbmacros/gdbmacros.py | 39 +++++++++++++++-------
 src/plugins/debugger/gdb/gdbengine.cpp | 14 ++++----
 src/plugins/debugger/gdb/gdbengine.h   |  1 -
 src/plugins/debugger/watchhandler.cpp  | 45 +++++++++++++++++---------
 src/plugins/debugger/watchhandler.h    | 33 ++++++++++---------
 5 files changed, 81 insertions(+), 51 deletions(-)

diff --git a/share/qtcreator/gdbmacros/gdbmacros.py b/share/qtcreator/gdbmacros/gdbmacros.py
index fcfbccb902e..c8d01858edb 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.py
+++ b/share/qtcreator/gdbmacros/gdbmacros.py
@@ -407,18 +407,33 @@ def qdump__QImage(d, item):
         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()
+        if False:
+            # Take four bytes at a time, this is critical for performance.
+            # In fact, even four at a time is too slow beyond 100x100 or so.
+            d.putField("editformat", 1)  # Magic marker for direct "QImage" data.
+            d.beginItem("editvalue")
+            d.put("%08x" % int(d_ptr["width"]))
+            d.put("%08x" % int(d_ptr["height"]))
+            d.put("%08x" % int(d_ptr["format"]))
+            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()
+        else:
+            # Write to an external file. Much faster ;-(
+            file = tempfile.mkstemp(prefix="gdbpy_")
+            filename = file[1]
+            p = bits.cast(gdb.lookup_type("unsigned char").pointer())
+            gdb.execute("dump binary memory %s %s %s" %
+                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
+            d.putField("editformat", 3)  # Magic marker for external "QImage" data.
+            d.beginItem("editvalue")
+            d.put(" %d" % int(d_ptr["width"]))
+            d.put(" %d" % int(d_ptr["height"]))
+            d.put(" %d" % int(d_ptr["format"]))
+            d.put(" %s" % filename)
+            d.endItem()
 
 
 def qdump__QLinkedList(d, item):
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 6fca40e49a0..9924ed5e554 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -3089,12 +3089,6 @@ void GdbEngine::setWatchDataValue(WatchData &data, const GdbMi &mi,
         data.setValueNeeded();
 }
 
-void GdbEngine::setWatchDataEditValue(WatchData &data, const GdbMi &mi)
-{
-    if (mi.isValid())
-        data.editvalue = mi.data();
-}
-
 void GdbEngine::setWatchDataValueToolTip(WatchData &data, const GdbMi &mi,
     int encoding)
 {
@@ -3369,7 +3363,13 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
         data.setChildrenUnneeded();
 
     setWatchDataType(data, item.findChild("type"));
-    setWatchDataEditValue(data, item.findChild("editvalue"));
+    GdbMi mi = item.findChild("editvalue");
+    if (mi.isValid())
+        data.editvalue = mi.data();
+    mi = item.findChild("editformat");
+    if (mi.isValid())
+        data.editformat = mi.data().toInt();
+
     setWatchDataValue(data, item.findChild("value"),
         item.findChild("valueencoded").data().toInt());
     setWatchDataAddress(data, item.findChild("addr"));
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 333e272207b..e9d5a7a1365 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -524,7 +524,6 @@ private: ////////// Convenience Functions //////////
 
     static void setWatchDataValue(WatchData &data, const GdbMi &mi,
         int encoding = 0);
-    static void setWatchDataEditValue(WatchData &data, const GdbMi &mi);
     static void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi,
             int encoding = 0);
     static void setWatchDataChildCount(WatchData &data, const GdbMi &mi);
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 54ba571eb66..d6e39b18053 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -41,10 +41,10 @@
 
 #include <QtCore/QDebug>
 #include <QtCore/QEvent>
-
-#include <QtCore/QtAlgorithms>
+#include <QtCore/QFile>
 #include <QtCore/QTextStream>
 #include <QtCore/QTimer>
+#include <QtCore/QtAlgorithms>
 
 #include <QtGui/QAction>
 #include <QtGui/QApplication>
@@ -1351,41 +1351,56 @@ static void swapEndian(char *d, int nchar)
 
 void WatchHandler::showEditValue(const WatchData &data)
 {
-    // Editvalue is always hex encoded.
-    QByteArray ba = QByteArray::fromHex(data.editvalue);
     QWidget *w = m_editWindows.value(data.iname);
-    const int format = ba.at(0);
-    if (format == 0x1) {
+        
+    if (data.editformat == 0x1 || data.editformat == 0x3) {
         // QImage
         if (!w) {
             w = new QLabel;
             m_editWindows[data.iname] = w;
         }
         if (QLabel *l = qobject_cast<QLabel *>(w)) {
-            char *d = ba.data() + 1;
-            swapEndian(d, ba.size() - 1);
-            const int *header = (int *)(d);
-            const uchar *data = 12 + (uchar *)(d);
-            QImage im(data, header[0], header[1], QImage::Format(header[2]));
+            int width, height, format;
+            QByteArray ba;
+            uchar *bits;
+            if (data.editformat == 0x1) {
+                ba = QByteArray::fromHex(data.editvalue);
+                const int *header = (int *)(ba.data());
+                swapEndian(ba.data(), ba.size());
+                bits = 12 + (uchar *)(ba.data());
+                width = header[0];
+                height = header[1];
+                format = header[2];
+            } else { // data.editformat == 0x3
+                QTextStream ts(data.editvalue);
+                QString fileName;
+                ts >> width >> height >> format >> fileName;
+                QFile f(fileName);
+                f.open(QIODevice::ReadOnly);
+                ba = f.readAll();
+                bits = (uchar*)ba.data();
+            }
+            QImage im(bits, width, height, QImage::Format(format));
             l->setPixmap(QPixmap::fromImage(im));
-            l->resize(header[0], header[1]);
+            l->resize(width, height);
             l->show();
         }
-    } else if (format == 0x2) {
+    } else if (data.editformat == 0x2) {
         // QString
         if (!w) {
             w = new QTextEdit;
             m_editWindows[data.iname] = w;
         }
-        MODEL_DEBUG("DATA: " << ba);
+        QByteArray ba = QByteArray::fromHex(data.editvalue);
         QString str = QString::fromUtf16((ushort *)ba.constData(), ba.size()/2);
+
         if (QTextEdit *t = qobject_cast<QTextEdit *>(w)) {
             t->setText(str);
             t->resize(400, 200);
             t->show();
         }
     } else {
-        QTC_ASSERT(false, qDebug() << "Display format: " << format);
+        QTC_ASSERT(false, qDebug() << "Display format: " << data.editformat);
     }
 }
 
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index 055387d7afd..9e9f0594fee 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -120,23 +120,24 @@ public:
     static const QString &shadowedNameFormat();
 
 public:
-    QByteArray iname;     // internal name sth like 'local.baz.public.a'
-    QByteArray exp;       // the expression
-    QString name;         // displayed name
-    QString value;        // displayed value
-    QByteArray editvalue; // displayed value
-    QString valuetooltip; // tooltip in value column
-    QString type;         // type for further processing
-    QString displayedType;// displayed type (optional)
-    QByteArray variable;  // name of internal Gdb variable if created
-    QByteArray addr;      // displayed address
-    QByteArray saddr;     // stored address (pointer in container)
-    QString framekey;     // key for type cache
-    QScriptValue scriptValue; // if needed...
+    QByteArray iname;     // Internal name sth like 'local.baz.public.a'
+    QByteArray exp;       // The expression
+    QString name;         // Displayed name
+    QString value;        // Displayed value
+    QByteArray editvalue; // Displayed value
+    int editformat;       // Format of displayed value
+    QString valuetooltip; // Tooltip in value column
+    QString type;         // Type for further processing
+    QString displayedType;// Displayed type (optional)
+    QByteArray variable;  // Name of internal Gdb variable if created
+    QByteArray addr;      // Displayed address
+    QByteArray saddr;     // Stored address (pointer in container)
+    QString framekey;     // Key for type cache
+    QScriptValue scriptValue; // If needed...
     bool hasChildren;
-    int generation;       // when updated?
-    bool valueEnabled;    // value will be greyed out or not
-    bool valueEditable;   // value will be editable
+    int generation;       // When updated?
+    bool valueEnabled;    // Value will be greyed out or not
+    bool valueEditable;   // Value will be editable
     bool error;
 
 public:
-- 
GitLab