diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index df6075d4a6c..b7ad03ca533 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -748,50 +748,57 @@ def qform__QImage(): return "Normal,Displayed" def qdump__QImage(d, value): - # This relies on current QImage layout - intPtrType = d.lookupType("int").pointer() - offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = d.createValue(d.addressOf(value) + offset, intPtrType) - width = int(base[1]) - height = int(base[2]) + # This relies on current QImage layout: + # QImageData: + # - QAtomicInt ref + # - int width, height, depth, nbytes + # - qreal devicePixelRatio (+20) # Assume qreal == double, Qt 5 only + # - QVector colortable (+20 + gap) + # - uchar *data (+20 + gap + ptr) + # [- uchar **jumptable jumptable with Qt 3 suppor] + # - enum format (+20 + gap + 2 * ptr) + + ptrSize = d.ptrSize() + isQt5 = d.qtVersion() >= 0x050000 + offset = (3 if isQt5 else 2) * ptrSize + base = d.dereference(d.addressOf(value) + offset) + width = d.extractInt(base + 4) + height = d.extractInt(base + 8) + nbytes = d.extractInt(base + 16) + pixelRatioSize = 8 if isQt5 else 0 + jumpTableSize = ptrSize if not isQt5 else 0 # FIXME: Assumes Qt3 Support + bits = d.dereference(base + 20 + pixelRatioSize + ptrSize) + iformat = d.extractInt(base + 20 + pixelRatioSize + jumpTableSize + 2 * ptrSize) d.putValue("(%dx%d)" % (width, height)) - d.putNumChild(0) - #d.putNumChild(1) + d.putNumChild(1) if d.isExpanded(): with Children(d): + d.putIntItem("width", width) + d.putIntItem("height", height) + d.putIntItem("nbytes", nbytes) + d.putIntItem("format", iformat) with SubItem(d, "data"): - d.putNoType() + d.putValue("0x%x" % bits) d.putNumChild(0) - d.putValue("size: %s bytes" % nbytes); + d.putType("void *") + format = d.currentItemFormat() if format == 1: d.putDisplay(StopDisplay) elif format == 2: - d_ptr = value["d"] - bits = d_ptr["data"] - nbytes = d_ptr["nbytes"] - 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", DisplayImageData) - d.put('%s="' % name) - d.put("%08x" % width) - d.put("%08x" % height) - d.put("%08x" % int(d_ptr["format"])) - p = bits.cast(d.intType().pointer()) - for i in xrange(nbytes / 4): - d.put("%08x" % int(p.dereference())) - p += 1 - d.put('",') - else: - # Write to an external file. Much faster ;-( - file = tempfile.mkstemp(prefix="gdbpy_") - filename = file[1].replace("\\", "\\\\") - p = bits.cast(d.charType().pointer()) - gdb.execute("dump binary memory %s %s %s" % - (filename, cleanAddress(p), cleanAddress(p + nbytes))) - d.putDisplay(DisplayImageFile, " %d %d %d %s" - % (width, height, d_ptr["format"], filename)) + # This is critical for performance. Writing to an external + # file using the following is faster when using GDB. + # file = tempfile.mkstemp(prefix="gdbpy_") + # filename = file[1].replace("\\", "\\\\") + # gdb.execute("dump binary memory %s %s %s" % + # (filename, bits, bits + nbytes)) + # d.putDisplay(DisplayImageFile, " %d %d %d %d %s" + # % (width, height, nbytes, iformat, filename)) + d.putField("editformat", DisplayImageData) + d.put('editvalue="') + d.put('%08x%08x%08x%08x' % (width, height, nbytes, iformat)) + d.put(d.readRawMemory(bits, nbytes)) + d.put('",') def qdump__QLinkedList(d, value): diff --git a/src/plugins/debugger/imageviewer.cpp b/src/plugins/debugger/imageviewer.cpp index db7f722e4a8..26d96ad406b 100644 --- a/src/plugins/debugger/imageviewer.cpp +++ b/src/plugins/debugger/imageviewer.cpp @@ -69,6 +69,7 @@ void ImageWidget::setImage(const QImage &image) { setFixedSize(image.size() + QSize(2, 2)); m_image = image; + update(); } void ImageWidget::mousePressEvent(QMouseEvent *ev) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index f400a431296..0616add575f 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1679,28 +1679,37 @@ void WatchHandler::showEditValue(const WatchData &data) showSeparateWidget(l); m_model->m_editHandlers[key] = l; } - int width = 0, height = 0, format = 0; + int width = 0, height = 0, nbytes = 0, format = 0; QByteArray ba; uchar *bits = 0; if (data.editformat == DisplayImageData) { ba = QByteArray::fromHex(data.editvalue); + QTC_ASSERT(ba.size() > 16, return); const int *header = (int *)(ba.data()); if (!ba.at(0) && !ba.at(1)) // Check on 'width' for Python dumpers returning 4-byte swapped-data. - swapEndian(ba.data(), ba.size()); - bits = 12 + (uchar *)(ba.data()); + swapEndian(ba.data(), 16); + bits = 16 + (uchar *)(ba.data()); width = header[0]; height = header[1]; - format = header[2]; + nbytes = header[2]; + format = header[3]; } else if (data.editformat == DisplayImageFile) { QTextStream ts(data.editvalue); QString fileName; - ts >> width >> height >> format >> fileName; + ts >> width >> height >> nbytes >> format >> fileName; QFile f(fileName); f.open(QIODevice::ReadOnly); ba = f.readAll(); bits = (uchar*)ba.data(); + nbytes = width * height; } - l->setImage(QImage(bits, width, height, QImage::Format(format))); + QTC_ASSERT(0 < width && width < 10000, return); + QTC_ASSERT(0 < height && height < 10000, return); + QTC_ASSERT(0 < nbytes && nbytes < 10000 * 10000, return); + QTC_ASSERT(0 < format && format < 32, return); + QImage im(width, height, QImage::Format(format)); + qMemCopy(im.bits(), bits, nbytes); + l->setImage(im); showSeparateWidget(l); } break;