forked from qt-creator/qt-creator
Debugger: Fix QObject/property dumper
Change-Id: Ied68fd07e077a185223a68cc504fff5a5b9391ac Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -274,6 +274,9 @@ class DumperBase:
|
||||
# This keeps canonical forms of the typenames, without array indices etc.
|
||||
self.cachedFormats = {}
|
||||
|
||||
self.knownQObjectTypes = set()
|
||||
self.knownNonQObjectTypes = set()
|
||||
|
||||
|
||||
def stripForFormat(self, typeName):
|
||||
if typeName in self.cachedFormats:
|
||||
@@ -769,6 +772,8 @@ class DumperBase:
|
||||
self.putItem(value.dereference())
|
||||
|
||||
def putQObjectNameValue(self, value):
|
||||
if str(value.type) in self.knownNonQObjectTypes:
|
||||
return
|
||||
try:
|
||||
intSize = self.intSize()
|
||||
ptrSize = self.ptrSize()
|
||||
@@ -817,14 +822,50 @@ class DumperBase:
|
||||
if size == 0:
|
||||
return False
|
||||
|
||||
str = self.readMemory(data, 2 * size)
|
||||
self.putValue(str, Hex4EncodedLittleEndian, 1)
|
||||
raw = self.readMemory(data, 2 * size)
|
||||
self.putValue(raw, Hex4EncodedLittleEndian, 1)
|
||||
return True
|
||||
|
||||
except:
|
||||
self.knownNonQObjectTypes.insert(str(value.type))
|
||||
pass
|
||||
|
||||
|
||||
def staticQObjectPropertyNames(self, metaobject):
|
||||
properties = []
|
||||
dd = metaobject["d"]
|
||||
data = self.dereferenceValue(dd["data"])
|
||||
byteArrayDataType = self.lookupType(self.qtNamespace() + "QByteArrayData")
|
||||
byteArrayDataSize = byteArrayDataType.sizeof
|
||||
sd = self.dereferenceValue(dd["stringdata"])
|
||||
|
||||
propertyCount = self.extractInt(data + 24)
|
||||
propertyData = self.extractInt(data + 28)
|
||||
|
||||
for i in range(propertyCount):
|
||||
x = data + (propertyData + 3 * i) * 4
|
||||
literal = sd + self.extractInt(x) * byteArrayDataSize
|
||||
ldata, lsize, lalloc = self.byteArrayDataHelper(literal)
|
||||
properties.append(self.readCArray(ldata, lsize))
|
||||
return properties
|
||||
|
||||
|
||||
# This is called is when a QObject derived class is expanded
|
||||
def putQObjectGuts(self, qobject):
|
||||
smo = self.childWithName(qobject, "staticMetaObject")
|
||||
if smo is None:
|
||||
return
|
||||
with SubItem(self, "[properties]"):
|
||||
propertyNames = self.staticQObjectPropertyNames(smo)
|
||||
propertyCount = len(propertyNames)
|
||||
self.putItemCount(propertyCount)
|
||||
self.putNumChild(propertyCount)
|
||||
with Children(self):
|
||||
for i in range(propertyCount):
|
||||
name = propertyNames[i]
|
||||
self.putCallItem(name, qobject, "property", '"' + name + '"')
|
||||
|
||||
|
||||
def isKnownMovableType(self, type):
|
||||
if type in (
|
||||
"QBrush", "QBitArray", "QByteArray", "QCustomTypeInfo", "QChar", "QDate",
|
||||
|
||||
@@ -717,12 +717,11 @@ class Dumper(DumperBase):
|
||||
def call(self, value, func, *args):
|
||||
return self.call2(value, func, args)
|
||||
|
||||
def hasChildWithName(self, value, name):
|
||||
def childWithName(self, value, name):
|
||||
try:
|
||||
value[name]
|
||||
return True
|
||||
return value[name]
|
||||
except:
|
||||
return False
|
||||
return None
|
||||
|
||||
def makeValue(self, type, init):
|
||||
type = "::" + stripClassTag(str(type));
|
||||
@@ -961,6 +960,11 @@ class Dumper(DumperBase):
|
||||
return toInteger(value.cast(self.voidPtrType()))
|
||||
|
||||
def isQObject(self, value):
|
||||
typeName = str(value.type)
|
||||
if typeName in self.knownQObjectTypes:
|
||||
return True
|
||||
if typeName in self.knownNonQObjectTypes:
|
||||
return False
|
||||
try:
|
||||
vtable = self.dereference(toInteger(value.address)) # + ptrSize
|
||||
if vtable & 0x3: # This is not a pointer.
|
||||
@@ -972,9 +976,15 @@ class Dumper(DumperBase):
|
||||
s = gdb.execute("info symbol 0x%x" % metaObjectEntry, to_string=True)
|
||||
#warn("S: %s " % s)
|
||||
#return s.find("::metaObject() const") > 0
|
||||
return s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0
|
||||
#return str(metaObjectEntry).find("::metaObject() const") > 0
|
||||
if s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0:
|
||||
self.knownQObjectTypes.add(typeName)
|
||||
return True
|
||||
else:
|
||||
self.knownNonQObjectTypes.add(typeName)
|
||||
return False
|
||||
except:
|
||||
self.knownNonQObjectTypes.add(typeName)
|
||||
return False
|
||||
|
||||
def isQObject_B(self, value):
|
||||
@@ -1398,7 +1408,8 @@ class Dumper(DumperBase):
|
||||
#warn("INAME: %s " % self.currentIName)
|
||||
#warn("INAMES: %s " % self.expandedINames)
|
||||
#warn("EXPANDED: %s " % (self.currentIName in self.expandedINames))
|
||||
if self.isQObject(value):
|
||||
isQObject = self.isQObject(value)
|
||||
if isQObject:
|
||||
self.putQObjectNameValue(value) # Is this too expensive?
|
||||
self.putType(typeName)
|
||||
self.putEmptyValue()
|
||||
@@ -1408,6 +1419,9 @@ class Dumper(DumperBase):
|
||||
innerType = None
|
||||
with Children(self, 1, childType=innerType):
|
||||
self.putFields(value)
|
||||
if isQObject:
|
||||
self.putQObjectGuts(value)
|
||||
|
||||
|
||||
def putPlainChildren(self, value):
|
||||
self.putEmptyValue(-99)
|
||||
@@ -1423,6 +1437,41 @@ class Dumper(DumperBase):
|
||||
return bytesToString(binascii.hexlify(mem.tobytes()))
|
||||
return binascii.hexlify(mem)
|
||||
|
||||
def readCArray(self, base, size):
|
||||
inferior = self.selectedInferior()
|
||||
if sys.version_info[0] >= 3:
|
||||
mem = bytes()
|
||||
for i in range(size):
|
||||
char = inferior.read_memory(base + i, 1)[0]
|
||||
if not char:
|
||||
break
|
||||
mem += char
|
||||
return mem.decode("utf8")
|
||||
else:
|
||||
mem = ""
|
||||
for i in range(size):
|
||||
char = inferior.read_memory(base + i, 1)[0]
|
||||
if not char:
|
||||
break
|
||||
mem += char
|
||||
return mem
|
||||
|
||||
def readCString(self, base):
|
||||
inferior = self.selectedInferior()
|
||||
mem = ""
|
||||
while True:
|
||||
char = inferior.read_memory(base, 1)[0]
|
||||
if not char:
|
||||
break
|
||||
mem += char
|
||||
base += 1
|
||||
#if sys.version_info[0] >= 3:
|
||||
# return mem.tobytes()
|
||||
return mem
|
||||
#if sys.version_info[0] >= 3:
|
||||
# return bytesToString(binascii.hexlify(mem.tobytes()))
|
||||
#return binascii.hexlify(mem)
|
||||
|
||||
def putFields(self, value, dumpBase = True):
|
||||
fields = value.type.fields()
|
||||
|
||||
@@ -1638,15 +1687,15 @@ class Dumper(DumperBase):
|
||||
# FIXME: This only works when call from inside a Qt function frame.
|
||||
namespace = ""
|
||||
try:
|
||||
str = gdb.execute("ptype QString::Null", to_string=True)
|
||||
out = gdb.execute("ptype QString::Null", to_string=True)
|
||||
# The result looks like:
|
||||
# "type = const struct myns::QString::Null {"
|
||||
# " <no data fields>"
|
||||
# "}"
|
||||
pos1 = str.find("struct") + 7
|
||||
pos2 = str.find("QString::Null")
|
||||
pos1 = out.find("struct") + 7
|
||||
pos2 = out.find("QString::Null")
|
||||
if pos1 > -1 and pos2 > -1:
|
||||
namespace = str[pos1:pos2]
|
||||
namespace = out[pos1:pos2]
|
||||
self.cachedQtNamespace = namespace
|
||||
self.ns = lambda: self.cachedQtNamespace
|
||||
except:
|
||||
|
||||
@@ -378,8 +378,9 @@ class Dumper(DumperBase):
|
||||
typeClass = typeobj.GetTypeClass()
|
||||
return typeClass == lldb.eTypeClassBuiltin
|
||||
|
||||
def hasChildWithName(self, value, name):
|
||||
return value.GetChildMemberWithName(name).IsValid()
|
||||
def childWithName(self, value, name):
|
||||
child = value.GetChildMemberWithName(name)
|
||||
return child if child.IsValid() else None
|
||||
|
||||
def childAt(self, value, index):
|
||||
return value.GetChildAtIndex(index)
|
||||
|
||||
@@ -1020,6 +1020,114 @@ def extractCString(table, offset):
|
||||
offset += 1
|
||||
return result
|
||||
|
||||
def qdump__QMetaObjectPrivate(d, value):
|
||||
d.putEmptyValue()
|
||||
d.putNumChild(1)
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
# int revision;
|
||||
# int className;
|
||||
# int classInfoCount, classInfoData;
|
||||
# int methodCount, methodData;
|
||||
# int propertyCount, propertyData;
|
||||
# int enumeratorCount, enumeratorData;
|
||||
# int constructorCount, constructorData; //since revision 2
|
||||
# int flags; //since revision 3
|
||||
# int signalCount; //since revision 4
|
||||
d.putIntItem("revision", value["revision"])
|
||||
d.putIntItem("methodCount", value["methodCount"])
|
||||
d.putIntItem("propertyCount", value["propertyCount"])
|
||||
d.putIntItem("enumeratorCount", value["enumeratorCount"])
|
||||
d.putIntItem("constructorCount", value["constructorCount"])
|
||||
d.putIntItem("flags", value["flags"])
|
||||
d.putIntItem("signalCount", value["signalCount"])
|
||||
|
||||
|
||||
|
||||
def qdump__QMetaObject(d, value):
|
||||
d.putEmptyValue()
|
||||
d.putNumChild(1)
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
dd = value["d"]
|
||||
d.putSubItem("d", dd)
|
||||
data = d.dereferenceValue(dd["data"])
|
||||
|
||||
propertyNames = d.staticQObjectPropertyNames(value)
|
||||
propertyIndex = 0
|
||||
for propertyName in propertyNames:
|
||||
with SubItem(d, "property_%s" % propertyIndex):
|
||||
d.putValue(propertyName)
|
||||
propertyIndex += 1
|
||||
|
||||
#byteArrayDataType = d.lookupType(d.qtNamespace() + "QByteArrayData")
|
||||
#byteArrayDataSize = byteArrayDataType.sizeof
|
||||
#sd = d.dereferenceValue(dd["stringdata"])
|
||||
#stringdata, size, alloc = d.byteArrayDataHelper(sd)
|
||||
|
||||
#propertyCount = d.extractInt(data + 24)
|
||||
#propertyData = d.extractInt(data + 28)
|
||||
|
||||
## This is the 'data' member in the qt_meta_stringdata_qobject__*_t struct
|
||||
#d.putIntItem("_byteArrayDataSize", byteArrayDataSize)
|
||||
#d.putAddressItem("_data", data)
|
||||
#d.putAddressItem("_sd_", stringdata)
|
||||
#with SubItem(d, "_sd"):
|
||||
# d.putValue(d.readMemory(stringdata, size), Hex2EncodedLatin1)
|
||||
#with SubItem(d, "_cn"):
|
||||
# d.putValue(d.readMemory(stringdata + d.extractInt(data + 4), size), Hex2EncodedLatin1)
|
||||
|
||||
#for i in range(propertyCount):
|
||||
# with SubItem(d, "property_%s" % i):
|
||||
# x = data + (propertyData + 3 * i) * 4
|
||||
# literal = sd + d.extractInt(x) * byteArrayDataSize
|
||||
# ldata, lsize, lalloc = d.byteArrayDataHelper(literal)
|
||||
# d.putValue(d.readMemory(ldata, lsize), Hex2EncodedLatin1)
|
||||
|
||||
# d.putNumChild(1)
|
||||
# if d.isExpanded():
|
||||
# with Children(d):
|
||||
# if d.isExpanded():
|
||||
# d.putAddressItem("_literal", literal)
|
||||
# d.putIntItem("__data", ldata)
|
||||
# d.putIntItem("__size", lsize)
|
||||
# d.putIntItem("__alloc", lalloc)
|
||||
# d.putIntItem("name", d.extractInt(x))
|
||||
# d.putIntItem("type", d.extractInt(x + 4))
|
||||
# d.putIntItem("flags", d.extractInt(x + 8))
|
||||
|
||||
methodCount = d.extractInt(data + 16)
|
||||
methodData = d.extractInt(data + 20)
|
||||
for i in range(methodCount):
|
||||
with SubItem(d, "method_%s" % i):
|
||||
x = data + (methodData + 5 * i) * 4
|
||||
#d.putEmptyValue()
|
||||
d.putValue(d.readCString(stringdata + d.extractInt(x)))
|
||||
d.putNumChild(1)
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
if d.isExpanded():
|
||||
d.putIntItem("name", d.extractInt(x))
|
||||
d.putIntItem("argc", d.extractInt(x + 4))
|
||||
d.putIntItem("argv", d.extractInt(x + 8))
|
||||
d.putIntItem("type", d.extractInt(x + 12))
|
||||
d.putIntItem("flags", d.extractInt(x + 16))
|
||||
|
||||
d.putSubItem("stringData", dd["stringdata"])
|
||||
d.putIntItem("revision", d.extractInt(data))
|
||||
d.putIntItem("className", d.extractInt(data + 4))
|
||||
d.putIntItem("classInfoCount", d.extractInt(data + 8))
|
||||
d.putIntItem("className", d.extractInt(data + 12))
|
||||
d.putIntItem("methodCount", d.extractInt(data + 16))
|
||||
d.putIntItem("methodData", d.extractInt(data + 20))
|
||||
d.putIntItem("propertyCount", d.extractInt(data + 24))
|
||||
d.putIntItem("propertyData", d.extractInt(data + 28))
|
||||
d.putIntItem("enumeratorCount", d.extractInt(data + 32))
|
||||
d.putIntItem("enumeratorData", d.extractInt(data + 36))
|
||||
d.putIntItem("constructorCount", d.extractInt(data + 40))
|
||||
d.putIntItem("constructorData", d.extractInt(data + 44))
|
||||
d.putIntItem("flags", d.extractInt(data + 48))
|
||||
d.putIntItem("signalCount", d.extractInt(data + 52))
|
||||
|
||||
def qdump__QObject(d, value):
|
||||
d.putQObjectNameValue(value)
|
||||
@@ -1074,8 +1182,8 @@ def qdump__QObject(d, value):
|
||||
#d.checkRef(d_ptr["ref"])
|
||||
d.putNumChild(4)
|
||||
if d.isExpanded():
|
||||
print("DIR: %s\n" % dir())
|
||||
with Children(d):
|
||||
d.putQObjectGuts(value)
|
||||
|
||||
# Local data.
|
||||
if privateTypeName != ns + "QObjectPrivate":
|
||||
@@ -1095,70 +1203,21 @@ def qdump__QObject(d, value):
|
||||
d.putSubItem("parent", d_ptr["parent"])
|
||||
d.putSubItem("children", d_ptr["children"])
|
||||
|
||||
# Properties.
|
||||
with SubItem(d, "properties"):
|
||||
# Prolog
|
||||
extraData = d_ptr["extraData"] # Capitalization!
|
||||
if d.isNull(extraData):
|
||||
dynamicPropertyCount = 0
|
||||
else:
|
||||
extraDataType = d.lookupType(
|
||||
ns + "QObjectPrivate::ExtraData").pointer()
|
||||
extraData = extraData.cast(extraDataType)
|
||||
ed = extraData.dereference()
|
||||
names = ed["propertyNames"]
|
||||
values = ed["propertyValues"]
|
||||
#userData = ed["userData"]
|
||||
namesBegin = names["d"]["begin"]
|
||||
namesEnd = names["d"]["end"]
|
||||
namesArray = names["d"]["array"]
|
||||
dynamicPropertyCount = namesEnd - namesBegin
|
||||
# Metaobject.
|
||||
d.putSubItem("metaobject", mo)
|
||||
|
||||
#staticPropertyCount = d.call(mo, "propertyCount")
|
||||
staticPropertyCount = metaData[6]
|
||||
#warn("PROPERTY COUNT: %s" % staticPropertyCount)
|
||||
propertyCount = staticPropertyCount + dynamicPropertyCount
|
||||
# Static Properties.
|
||||
with SubItem(d, "statics"):
|
||||
staticPropertyCount = d.call(mo, "propertyCount")
|
||||
#staticPropertyCount = metaData[6]
|
||||
#warn("STATIC PROPERTY COUNT: %s" % staticPropertyCount)
|
||||
|
||||
d.putNoType()
|
||||
d.putItemCount(propertyCount)
|
||||
d.putNumChild(propertyCount)
|
||||
d.putItemCount(staticPropertyCount)
|
||||
d.putNumChild(staticPropertyCount)
|
||||
|
||||
if d.isExpanded():
|
||||
# FIXME: Make this global. Don't leak.
|
||||
variant = "'%sQVariant'" % ns
|
||||
# Avoid malloc symbol clash with QVector
|
||||
gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
|
||||
% (variant, variant))
|
||||
gdb.execute("set $d.d.is_shared = 0")
|
||||
|
||||
with Children(d):
|
||||
# Dynamic properties.
|
||||
if dynamicPropertyCount != 0:
|
||||
dummyType = d.voidPtrType().pointer()
|
||||
namesType = d.lookupType(ns + "QByteArray")
|
||||
valuesBegin = values["d"]["begin"]
|
||||
valuesEnd = values["d"]["end"]
|
||||
valuesArray = values["d"]["array"]
|
||||
valuesType = d.lookupType(ns + "QVariant")
|
||||
p = namesArray.cast(dummyType) + namesBegin
|
||||
q = valuesArray.cast(dummyType) + valuesBegin
|
||||
for i in xrange(dynamicPropertyCount):
|
||||
with SubItem(d, i):
|
||||
pp = p.cast(namesType.pointer()).dereference();
|
||||
d.putField("key", d.encodeByteArray(pp))
|
||||
d.putField("keyencoded", Hex2EncodedLatin1)
|
||||
qq = q.cast(valuesType.pointer().pointer())
|
||||
qq = qq.dereference();
|
||||
d.putField("addr", cleanAddress(qq))
|
||||
d.putField("exp", "*(%s*)%s"
|
||||
% (variant, cleanAddress(qq)))
|
||||
t = qdump__QVariant(d, qq)
|
||||
# Override the "QVariant (foo)" output.
|
||||
d.putBetterType(t)
|
||||
p += 1
|
||||
q += 1
|
||||
|
||||
# Static properties.
|
||||
propertyData = metaData[7]
|
||||
for i in xrange(staticPropertyCount):
|
||||
with NoAddress(d):
|
||||
@@ -1168,17 +1227,18 @@ def qdump__QObject(d, value):
|
||||
propertyType = extractCString(metaStringData,
|
||||
metaData[offset + 1])
|
||||
with SubItem(d, propertyName):
|
||||
#flags = metaData[offset + 2]
|
||||
#warn("FLAGS: %s " % flags)
|
||||
#warn("PROPERTY: %s %s " % (propertyType, propertyName))
|
||||
flags = metaData[offset + 2]
|
||||
warn("FLAGS: %s " % flags)
|
||||
warn("PROPERTY: %s %s " % (propertyType, propertyName))
|
||||
# #exp = '((\'%sQObject\'*)%s)->property("%s")' \
|
||||
# % (ns, value.address, propertyName)
|
||||
#exp = '"((\'%sQObject\'*)%s)"' %
|
||||
#(ns, value.address,)
|
||||
#warn("EXPRESSION: %s" % exp)
|
||||
prop = d.call(value, "property",
|
||||
str(cleanAddress(metaStringData + metaData[offset])))
|
||||
value1 = prop["d"]
|
||||
exp = '"((%sQObject*)%s)"' % (ns, value.address)
|
||||
warn("EXPRESSION: %s" % exp)
|
||||
warn("METAOBJECT: %s" % mo)
|
||||
addr = cleanAddress(metaStringData + metaData[offset])
|
||||
warn("ADDRESS: %s" % addr)
|
||||
prop = d.call(value, "property", str(addr))
|
||||
warn("PROP: %s" % prop)
|
||||
#warn(" CODE: %s" % value1["type"])
|
||||
# Type 1 and 2 are bool and int.
|
||||
# Try to save a few cycles in this case:
|
||||
@@ -1217,6 +1277,64 @@ def qdump__QObject(d, value):
|
||||
d.putValue("...")
|
||||
d.putNumChild(0)
|
||||
|
||||
# Dynamic Properties.
|
||||
with SubItem(d, "dynamics"):
|
||||
# Prolog
|
||||
extraData = d_ptr["extraData"] # Capitalization!
|
||||
if d.isNull(extraData):
|
||||
dynamicPropertyCount = 0
|
||||
else:
|
||||
extraDataType = d.lookupType(
|
||||
ns + "QObjectPrivate::ExtraData").pointer()
|
||||
extraData = extraData.cast(extraDataType)
|
||||
ed = extraData.dereference()
|
||||
names = ed["propertyNames"]
|
||||
values = ed["propertyValues"]
|
||||
#userData = ed["userData"]
|
||||
namesBegin = names["d"]["begin"]
|
||||
namesEnd = names["d"]["end"]
|
||||
namesArray = names["d"]["array"]
|
||||
dynamicPropertyCount = namesEnd - namesBegin
|
||||
|
||||
d.putNoType()
|
||||
d.putItemCount(dynamicPropertyCount)
|
||||
d.putNumChild(dynamicPropertyCount)
|
||||
|
||||
if d.isExpanded() and d.isGdb:
|
||||
import gdb
|
||||
# FIXME: Make this global. Don't leak.
|
||||
variant = "'%sQVariant'" % ns
|
||||
# Avoid malloc symbol clash with QVector
|
||||
gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
|
||||
% (variant, variant))
|
||||
gdb.execute("set $d.d.is_shared = 0")
|
||||
|
||||
with Children(d):
|
||||
dummyType = d.voidPtrType().pointer()
|
||||
namesType = d.lookupType(ns + "QByteArray")
|
||||
valuesBegin = values["d"]["begin"]
|
||||
valuesEnd = values["d"]["end"]
|
||||
valuesArray = values["d"]["array"]
|
||||
valuesType = d.lookupType(ns + "QVariant")
|
||||
p = namesArray.cast(dummyType) + namesBegin
|
||||
q = valuesArray.cast(dummyType) + valuesBegin
|
||||
for i in xrange(dynamicPropertyCount):
|
||||
with SubItem(d, i):
|
||||
pp = p.cast(namesType.pointer()).dereference();
|
||||
d.putField("key", d.encodeByteArray(pp))
|
||||
d.putField("keyencoded", Hex2EncodedLatin1)
|
||||
qq = q.cast(valuesType.pointer().pointer())
|
||||
qq = qq.dereference();
|
||||
d.putField("addr", cleanAddress(qq))
|
||||
d.putField("exp", "*(%s*)%s"
|
||||
% (variant, cleanAddress(qq)))
|
||||
t = qdump__QVariant(d, qq)
|
||||
# Override the "QVariant (foo)" output.
|
||||
d.putBetterType(t)
|
||||
p += 1
|
||||
q += 1
|
||||
|
||||
|
||||
# Connections.
|
||||
with SubItem(d, "connections"):
|
||||
d.putNoType()
|
||||
@@ -1910,7 +2028,58 @@ qdumpHelper_QVariants_B = [
|
||||
"QVariantHash",# 28
|
||||
]
|
||||
|
||||
qdumpHelper_QVariants_C = [
|
||||
def qdumpHelper_QVariant_31(d, data):
|
||||
# QVariant::VoidStart
|
||||
d.putBetterType("%sQVariant (void *)" % d.qtNamespace())
|
||||
d.putValue("0x%x" % data["ptr"])
|
||||
|
||||
def qdumpHelper_QVariant_32(d, data):
|
||||
# QVariant::Long
|
||||
d.putBetterType("%sQVariant (long)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["l"]))
|
||||
|
||||
def qdumpHelper_QVariant_33(d, data):
|
||||
# QVariant::Short
|
||||
d.putBetterType("%sQVariant (short)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["s"]))
|
||||
|
||||
def qdumpHelper_QVariant_34(d, data):
|
||||
# QVariant::Char
|
||||
d.putBetterType("%sQVariant (char)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["c"]))
|
||||
|
||||
def qdumpHelper_QVariant_35(d, data):
|
||||
# QVariant::ULong
|
||||
d.putBetterType("%sQVariant (unsigned long)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["ul"]))
|
||||
|
||||
def qdumpHelper_QVariant_36(d, data):
|
||||
# QVariant::UShort
|
||||
d.putBetterType("%sQVariant (unsigned short)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["us"]))
|
||||
|
||||
def qdumpHelper_QVariant_37(d, data):
|
||||
# QVariant::UChar
|
||||
d.putBetterType("%sQVariant (unsigned char)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["uc"]))
|
||||
|
||||
def qdumpHelper_QVariant_38(d, data):
|
||||
# QVariant::UChar
|
||||
d.putBetterType("%sQVariant (float)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["f"]))
|
||||
|
||||
qdumpHelper_QVariants_D = [
|
||||
qdumpHelper_QVariant_31,
|
||||
qdumpHelper_QVariant_32,
|
||||
qdumpHelper_QVariant_33,
|
||||
qdumpHelper_QVariant_34,
|
||||
qdumpHelper_QVariant_35,
|
||||
qdumpHelper_QVariant_36,
|
||||
qdumpHelper_QVariant_37,
|
||||
qdumpHelper_QVariant_38
|
||||
]
|
||||
|
||||
qdumpHelper_QVariants_E = [
|
||||
"QFont", # 64
|
||||
"QPixmap", # 65
|
||||
"QBrush", # 66
|
||||
@@ -1947,6 +2116,11 @@ def qdumpHelper__QVariant(d, value):
|
||||
d.putNumChild(0)
|
||||
return (None, None, True)
|
||||
|
||||
if variantType >= 31 and variantType <= 38:
|
||||
qdumpHelper_QVariants_D[variantType - 31](d, data)
|
||||
d.putNumChild(0)
|
||||
return (None, None, True)
|
||||
|
||||
# Unknown user type.
|
||||
if variantType > 86:
|
||||
return (None, "", False)
|
||||
@@ -1955,7 +2129,7 @@ def qdumpHelper__QVariant(d, value):
|
||||
if variantType <= 28:
|
||||
innert = qdumpHelper_QVariants_B[variantType - 7]
|
||||
else:
|
||||
innert = qdumpHelper_QVariants_C[variantType - 64]
|
||||
innert = qdumpHelper_QVariants_E[variantType - 64]
|
||||
|
||||
inner = d.qtNamespace() + innert
|
||||
|
||||
@@ -1966,6 +2140,9 @@ def qdumpHelper__QVariant(d, value):
|
||||
if innerType.sizeof > sizePD or isSpecial:
|
||||
val = data["ptr"].cast(innerType.pointer().pointer()).dereference().dereference()
|
||||
else:
|
||||
# This can break for returned values
|
||||
#warn("DATA: %s" % data)
|
||||
#warn("DATA ADDRESS: %s" % d.addressOf(data))
|
||||
val = data.cast(innerType)
|
||||
|
||||
d.putEmptyValue(-99)
|
||||
|
||||
@@ -288,8 +288,9 @@ def stdTreeIteratorHelper(d, value):
|
||||
nodeType = d.lookupType(nodeTypeName)
|
||||
data = node.cast(nodeType)["_M_value_field"]
|
||||
with Children(d):
|
||||
if d.hasChildWithName(data, "first"):
|
||||
d.putSubItem("first", data["first"])
|
||||
first = d.childWithName(data, "first")
|
||||
if first:
|
||||
d.putSubItem("first", first)
|
||||
d.putSubItem("second", data["second"])
|
||||
else:
|
||||
d.putSubItem("value", data)
|
||||
|
||||
@@ -2287,28 +2287,37 @@ void tst_Dumpers::dumper_data()
|
||||
" Q_PROPERTY(QString myProp1 READ myProp1 WRITE setMyProp1)\n"
|
||||
" QString myProp1() const { return m_myProp1; }\n"
|
||||
" Q_SLOT void setMyProp1(const QString&mt) { m_myProp1 = mt; }\n"
|
||||
" Q_PROPERTY(QString myProp2 READ myProp2 WRITE setMyProp2)\n"
|
||||
" QString myProp2() const { return m_myProp2; }\n"
|
||||
" Q_SLOT void setMyProp2(const QString&mt) { m_myProp2 = mt; }\n"
|
||||
" Q_PROPERTY(QByteArray myProp2 READ myProp2 WRITE setMyProp2)\n"
|
||||
" QByteArray myProp2() const { return m_myProp2; }\n"
|
||||
" Q_SLOT void setMyProp2(const QByteArray&mt) { m_myProp2 = mt; }\n"
|
||||
" Q_PROPERTY(long myProp3 READ myProp3)\n"
|
||||
" long myProp3() const { return 54; }\n"
|
||||
" Q_PROPERTY(int myProp4 READ myProp4)\n"
|
||||
" int myProp4() const { return 44; }\n"
|
||||
" public:\n"
|
||||
" Ui *m_ui;\n"
|
||||
" QString m_myProp1;\n"
|
||||
" QString m_myProp2;\n"
|
||||
" QByteArray m_myProp2;\n"
|
||||
" };\n"
|
||||
"} // namespace Bar\n"
|
||||
"} // namespace Names\n"
|
||||
"#include <main.moc>\n",
|
||||
""
|
||||
"QApplication app(argc, argv);\n"
|
||||
"Q_UNUSED(app)\n"
|
||||
"Names::Bar::TestObject test;\n"
|
||||
"test.setMyProp1(\"HELLO\");\n"
|
||||
"test.setMyProp2(\"WORLD\");\n"
|
||||
"test.setMyProp1(\"Hello\");\n"
|
||||
"test.setMyProp2(\"World\");\n"
|
||||
"QString s = test.myProp1();\n"
|
||||
"s += test.myProp2();\n")
|
||||
"s += QString::fromLatin1(test.myProp2());\n"
|
||||
"unused(&app, &test, &s);\n")
|
||||
% GuiProfile()
|
||||
% Check("s", "\"HELLOWORLD\"", "@QString")
|
||||
% Check("test", "", "Names::Bar::TestObject");
|
||||
% Check("s", "\"HelloWorld\"", "@QString")
|
||||
% Check("test", "", "Names::Bar::TestObject")
|
||||
% Check("test.[properties]", "<4 items>", "")
|
||||
% Check("test.[properties].myProp1", "\"Hello\"", "@QVariant (QString)")
|
||||
% Check("test.[properties].myProp2", "\"World\"", "@QVariant (QByteArray)")
|
||||
% Check("test.[properties].myProp3", "54", "@QVariant (long)")
|
||||
% Check("test.[properties].myProp4", "44", "@QVariant (int)");
|
||||
|
||||
QTest::newRow("QObject3")
|
||||
<< Data("#include <QWidget>\n"
|
||||
|
||||
@@ -1802,6 +1802,12 @@ namespace qobject {
|
||||
QString myProp2() const { return m_myProp2; }
|
||||
Q_SLOT void setMyProp2(const QString&mt) { m_myProp2 = mt; }
|
||||
|
||||
Q_PROPERTY(long myProp3 READ myProp3)
|
||||
long myProp3() const { return 54; }
|
||||
|
||||
Q_PROPERTY(long myProp4 READ myProp4)
|
||||
long myProp4() const { return 44; }
|
||||
|
||||
public:
|
||||
Ui *m_ui;
|
||||
QString m_myProp1;
|
||||
@@ -1817,6 +1823,7 @@ namespace qobject {
|
||||
Names::Bar::TestObject test;
|
||||
test.setMyProp1("HELLO");
|
||||
test.setMyProp2("WORLD");
|
||||
test.setObjectName("An object");
|
||||
QString s = test.myProp1();
|
||||
s += test.myProp2();
|
||||
BREAK_HERE;
|
||||
|
||||
Reference in New Issue
Block a user