Debugger: Make QImage dumper work with release versions

This accidentally also allows non-debug Qt users to reproduce the
http://blog.qt.digia.com/blog/2010/04/22/peek-and-poke-vol-3/
smiley drawing.

Change-Id: Ica436f55494d012d5516ef9d00d6310f2ac2d4ee
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-07-01 11:43:56 +02:00
parent 0292600c72
commit abc6e351b8
3 changed files with 58 additions and 41 deletions

View File

@@ -748,50 +748,57 @@ def qform__QImage():
return "Normal,Displayed" return "Normal,Displayed"
def qdump__QImage(d, value): def qdump__QImage(d, value):
# This relies on current QImage layout # This relies on current QImage layout:
intPtrType = d.lookupType("int").pointer() # QImageData:
offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof # - QAtomicInt ref
base = d.createValue(d.addressOf(value) + offset, intPtrType) # - int width, height, depth, nbytes
width = int(base[1]) # - qreal devicePixelRatio (+20) # Assume qreal == double, Qt 5 only
height = int(base[2]) # - QVector<QRgb> 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.putValue("(%dx%d)" % (width, height))
d.putNumChild(0) d.putNumChild(1)
#d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
d.putIntItem("width", width)
d.putIntItem("height", height)
d.putIntItem("nbytes", nbytes)
d.putIntItem("format", iformat)
with SubItem(d, "data"): with SubItem(d, "data"):
d.putNoType() d.putValue("0x%x" % bits)
d.putNumChild(0) d.putNumChild(0)
d.putValue("size: %s bytes" % nbytes); d.putType("void *")
format = d.currentItemFormat() format = d.currentItemFormat()
if format == 1: if format == 1:
d.putDisplay(StopDisplay) d.putDisplay(StopDisplay)
elif format == 2: elif format == 2:
d_ptr = value["d"] # This is critical for performance. Writing to an external
bits = d_ptr["data"] # file using the following is faster when using GDB.
nbytes = d_ptr["nbytes"] # file = tempfile.mkstemp(prefix="gdbpy_")
if False: # filename = file[1].replace("\\", "\\\\")
# Take four bytes at a time, this is critical for performance. # gdb.execute("dump binary memory %s %s %s" %
# In fact, even four at a time is too slow beyond 100x100 or so. # (filename, bits, bits + nbytes))
d.putField("editformat", DisplayImageData) # d.putDisplay(DisplayImageFile, " %d %d %d %d %s"
d.put('%s="' % name) # % (width, height, nbytes, iformat, filename))
d.put("%08x" % width) d.putField("editformat", DisplayImageData)
d.put("%08x" % height) d.put('editvalue="')
d.put("%08x" % int(d_ptr["format"])) d.put('%08x%08x%08x%08x' % (width, height, nbytes, iformat))
p = bits.cast(d.intType().pointer()) d.put(d.readRawMemory(bits, nbytes))
for i in xrange(nbytes / 4): d.put('",')
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))
def qdump__QLinkedList(d, value): def qdump__QLinkedList(d, value):

View File

@@ -69,6 +69,7 @@ void ImageWidget::setImage(const QImage &image)
{ {
setFixedSize(image.size() + QSize(2, 2)); setFixedSize(image.size() + QSize(2, 2));
m_image = image; m_image = image;
update();
} }
void ImageWidget::mousePressEvent(QMouseEvent *ev) void ImageWidget::mousePressEvent(QMouseEvent *ev)

View File

@@ -1679,28 +1679,37 @@ void WatchHandler::showEditValue(const WatchData &data)
showSeparateWidget(l); showSeparateWidget(l);
m_model->m_editHandlers[key] = 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; QByteArray ba;
uchar *bits = 0; uchar *bits = 0;
if (data.editformat == DisplayImageData) { if (data.editformat == DisplayImageData) {
ba = QByteArray::fromHex(data.editvalue); ba = QByteArray::fromHex(data.editvalue);
QTC_ASSERT(ba.size() > 16, return);
const int *header = (int *)(ba.data()); const int *header = (int *)(ba.data());
if (!ba.at(0) && !ba.at(1)) // Check on 'width' for Python dumpers returning 4-byte swapped-data. if (!ba.at(0) && !ba.at(1)) // Check on 'width' for Python dumpers returning 4-byte swapped-data.
swapEndian(ba.data(), ba.size()); swapEndian(ba.data(), 16);
bits = 12 + (uchar *)(ba.data()); bits = 16 + (uchar *)(ba.data());
width = header[0]; width = header[0];
height = header[1]; height = header[1];
format = header[2]; nbytes = header[2];
format = header[3];
} else if (data.editformat == DisplayImageFile) { } else if (data.editformat == DisplayImageFile) {
QTextStream ts(data.editvalue); QTextStream ts(data.editvalue);
QString fileName; QString fileName;
ts >> width >> height >> format >> fileName; ts >> width >> height >> nbytes >> format >> fileName;
QFile f(fileName); QFile f(fileName);
f.open(QIODevice::ReadOnly); f.open(QIODevice::ReadOnly);
ba = f.readAll(); ba = f.readAll();
bits = (uchar*)ba.data(); 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); showSeparateWidget(l);
} }
break; break;