Commit 13a4f739 authored by hjk's avatar hjk

Debugger: List QObject methods and signals in dumper

This mostly re-activates code from the old code path
in the QObject dumper.

Task-number: QTCREATORBUG-11997

Change-Id: Ie3e6eddffe8d0edd7d5947c2eec03d707bd2436b
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 23d1d0b7
......@@ -368,6 +368,17 @@ class DumperBase:
return min(size, self.stringCutOff)
return min(size, limit)
def vectorDataHelper(self, addr):
if self.qtVersion() >= 0x050000:
size = self.extractInt(addr + 4)
alloc = self.extractInt(addr + 8) & 0x7ffffff
data = addr + self.extractPointer(addr + 8 + self.ptrSize())
else:
alloc = self.extractInt(addr + 4)
size = self.extractInt(addr + 8)
data = addr + 16
return data, size, alloc
def byteArrayDataHelper(self, addr):
if self.qtVersion() >= 0x050000:
# QTypedArray:
......@@ -1001,31 +1012,40 @@ class DumperBase:
self.knownStaticMetaObjects[typeName] = result
return result
def staticQObjectPropertyNames(self, metaobject):
properties = []
def staticQObjectMetaData(self, metaobject, offset1, offset2, step):
items = []
dd = metaobject["d"]
data = self.extractPointer(dd["data"])
sd = self.extractPointer(dd["stringdata"])
metaObjectVersion = self.extractInt(data)
propertyCount = self.extractInt(data + 24)
propertyData = self.extractInt(data + 28)
itemCount = self.extractInt(data + offset1)
itemData = -offset2 if offset2 < 0 else self.extractInt(data + offset2)
if metaObjectVersion >= 7: # Qt 5.
byteArrayDataType = self.lookupType(self.qtNamespace() + "QByteArrayData")
byteArrayDataSize = byteArrayDataType.sizeof
for i in range(propertyCount):
x = data + (propertyData + 3 * i) * 4
for i in range(itemCount):
x = data + (itemData + step * i) * 4
literal = sd + self.extractInt(x) * byteArrayDataSize
ldata, lsize, lalloc = self.byteArrayDataHelper(literal)
properties.append(self.extractBlob(ldata, lsize).toString())
items.append(self.extractBlob(ldata, lsize).toString())
else: # Qt 4.
for i in range(propertyCount):
x = data + (propertyData + 3 * i) * 4
for i in range(itemCount):
x = data + (itemData + step * i) * 4
ldata = sd + self.extractInt(x)
properties.append(self.extractCString(ldata).decode("utf8"))
items.append(self.extractCString(ldata).decode("utf8"))
return items
def staticQObjectPropertyNames(self, metaobject):
return self.staticQObjectMetaData(metaobject, 24, 28, 3)
def staticQObjectMethodNames(self, metaobject):
return self.staticQObjectMetaData(metaobject, 16, 20, 5)
return properties
def staticQObjectSignalNames(self, metaobject):
return self.staticQObjectMetaData(metaobject, 52, -14, 5)
def extractCString(self, addr):
result = bytearray()
......@@ -1071,6 +1091,14 @@ class DumperBase:
#with SubItem(self, "[extradata]"):
# self.putValue("0x%x" % toInteger(extraData))
# Parent and children.
try:
d_ptr = qobject["d_ptr"]["d"]
self.putSubItem("[parent]", d_ptr["parent"])
self.putSubItem("[children]", d_ptr["children"])
except:
pass
with SubItem(self, "[properties]"):
propertyCount = 0
if self.isExpanded():
......@@ -1096,6 +1124,65 @@ class DumperBase:
self.putValue('<%s items>' % propertyCount if propertyCount else '<>0 items>')
self.putNumChild(1)
with SubItem(self, "[methods]"):
methodCount = 0
if self.isExpanded():
methodNames = self.staticQObjectMethodNames(smo)
methodCount = len(methodNames)
with Children(self):
for i in range(methodCount):
k = methodNames[i]
with SubItem(self, k):
self.putEmptyValue()
self.putValue('<%s items>' % methodCount if methodCount else ' ')
self.putNumChild(1)
with SubItem(self, "[signals]"):
signalCount = 0
if self.isExpanded():
signalNames = self.staticQObjectSignalNames(smo)
signalCount = len(signalNames)
with Children(self):
for i in range(signalCount):
k = signalNames[i]
with SubItem(self, k):
self.putEmptyValue()
self.putValue('<%s items>' % signalCount if signalCount else ' ')
self.putNumChild(1)
with SubItem(self, "[connections]"):
self.putNoType()
ns = self.qtNamespace()
privateTypeName = ns + "QObjectPrivate"
privateType = self.lookupType(privateTypeName)
dd = qobject["d_ptr"]["d"]
d_ptr = dd.cast(privateType.pointer()).dereference()
connections = d_ptr["connectionLists"]
connectionListCount = 0
if not self.isNull(connections):
connectionListCount = connections["d"]["size"]
self.putItemCount(connectionListCount, 0)
self.putNumChild(connectionListCount)
if self.isExpanded():
pp = 0
with Children(self):
vectorType = self.fieldAt(connections.type.target(), 0).type
innerType = self.templateArgument(vectorType, 0)
# Should check: innerType == ns::QObjectPrivate::ConnectionList
base = self.extractPointer(connections.dereference())
data, size, alloc = self.vectorDataHelper(base)
connectionType = self.lookupType(ns + "QObjectPrivate::Connection")
for i in xrange(size):
first = self.extractPointer(data + i * 2 * ptrSize)
while not self.isNull(first):
self.putSubItem("%s" % pp, self.createPointerValue(first, connectionType))
first = self.extractPointer(first + 3 * ptrSize)
# We need to enforce some upper limit.
pp += 1
if pp > 1000:
break
if pp < 1000:
self.putItemCount(pp)
def isKnownMovableType(self, type):
if type in (
......
......@@ -44,7 +44,7 @@ def qdump__QBasicAtomicInt(d, value):
def qdump__QAtomicPointer(d, value):
d.putType(value.type)
q = value["_q_value"]
p = int(q)
p = toInteger(q)
d.putValue("@0x%x" % p)
d.putNumChild(1 if p else 0)
if d.isExpanded():
......@@ -1329,45 +1329,6 @@ def _qdump__QObject(d, value):
d.putItemCount(pp)
# Signals.
signalCount = int(metaData[13])
with SubItem(d, "signals"):
d.putItemCount(signalCount)
d.putNoType()
d.putNumChild(signalCount)
if signalCount:
# FIXME: empty type does not work for childtype
#d.putField("childtype", ".")
d.putField("childnumchild", "0")
if d.isExpanded():
with Children(d):
for signal in xrange(signalCount):
with SubItem(d, signal):
offset = metaData[14 + 5 * signal]
d.putName("signal %d" % signal)
d.putNoType()
d.putValue(extractCString(metaStringData, offset))
d.putNumChild(0) # FIXME: List the connections here.
# Slots.
with SubItem(d, "slots"):
slotCount = int(metaData[4]) - signalCount
d.putItemCount(slotCount)
d.putNoType()
d.putNumChild(slotCount)
if slotCount:
#d.putField("childtype", ".")
d.putField("childnumchild", "0")
if d.isExpanded():
with Children(d):
for slot in xrange(slotCount):
with SubItem(d, slot):
offset = metaData[14 + 5 * (signalCount + slot)]
d.putName("slot %d" % slot)
d.putNoType()
d.putValue(extractCString(metaStringData, offset))
d.putNumChild(0) # FIXME: List the connections here.
# Active connection.
with SubItem(d, "currentSender"):
d.putNoType()
......@@ -2207,25 +2168,11 @@ def qform__QVector():
def qdump__QVector(d, value):
innerType = d.templateArgument(value.type, 0)
if d.qtVersion() >= 0x050000:
private = value["d"]
d.checkRef(private["ref"])
alloc = int(private["alloc"])
size = int(private["size"])
offset = int(private["offset"])
data = d.pointerValue(private) + offset
else:
anon = d.childAt(value, 0)
private = anon["d"]
d.checkRef(private["ref"])
alloc = int(private["alloc"])
size = int(private["size"])
data = d.addressOf(anon["p"]["array"])
data, size, alloc = d.vectorDataHelper(d.extractPointer(value))
d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
d.putItemCount(size)
d.putNumChild(size)
innerType = d.templateArgument(value.type, 0)
d.putPlotData(innerType, data, size)
......
......@@ -1781,7 +1781,9 @@ namespace qobject {
QObject child(&parent);
child.setObjectName("A Child");
QObject::connect(&child, SIGNAL(destroyed()), &parent, SLOT(deleteLater()));
QObject::connect(&child, SIGNAL(destroyed()), &child, SLOT(deleteLater()));
QObject::disconnect(&child, SIGNAL(destroyed()), &parent, SLOT(deleteLater()));
QObject::disconnect(&child, SIGNAL(destroyed()), &child, SLOT(deleteLater()));
child.setObjectName("A renamed Child");
BREAK_HERE;
// Check child "A renamed Child" QObject.
......@@ -1813,6 +1815,7 @@ namespace qobject {
Q_PROPERTY(QString myProp1 READ myProp1 WRITE setMyProp1)
QString myProp1() const { return m_myProp1; }
Q_SLOT void setMyProp1(const QString&mt) { m_myProp1 = mt; }
Q_INVOKABLE void foo() {}
Q_PROPERTY(QString myProp2 READ myProp2 WRITE setMyProp2)
QString myProp2() const { return m_myProp2; }
......@@ -1824,6 +1827,9 @@ namespace qobject {
Q_PROPERTY(long myProp4 READ myProp4)
long myProp4() const { return 44; }
Q_SIGNAL void sigFoo();
Q_SIGNAL void sigBar(int);
public:
Ui *m_ui;
QString m_myProp1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment