Debugger: Paddle back on the (non-)auto detection of Qt versions

It looks like there are Qt-using scenarios without easy way to have
the right Qt version in the kit,

Among the frequent cases where we need to distinguish Qt versions in
the dumpers are the Qt5/6 container layout differences which can in
some cases be detected from the currently dumped value. Use that now
as the primary distinction and fall back to the previous expensive
peeking only if that is needed. This also postpones any Qt version
related activity until a real Qt type is encountered, i.e. does not
impact non-Qt scenarios.

Task-number: QTCREATORBUG-31033
Change-Id: I67b6e34c42994ad9f6e8ec8698b430b55327cf0c
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2024-06-10 15:16:02 +02:00
parent 3e40f2f0e4
commit 3aee50f5fd
5 changed files with 237 additions and 99 deletions

View File

@@ -77,6 +77,8 @@ class Dumper(DumperBase):
self.isCdb = True
#FIXME
def register_known_qt_types(self):
DumperBase.register_known_qt_types(self)
typeid = self.typeid_for_string('@QVariantMap')
del self.type_code_cache[typeid]
del self.type_target_cache[typeid]

View File

@@ -172,8 +172,6 @@ class DumperBase():
self.qtCustomEventFunc = 0
self.qtCustomEventPltFunc = 0
self.qtPropertyFunc = 0
self.qtversion = None
self.qtns = None
self.passExceptions = False
self.isTesting = False
self.qtLoaded = False
@@ -189,6 +187,11 @@ class DumperBase():
self.dumpermodules = []
# These are sticky for the session
self.qtversion = None
self.qtversionAtLeast6 = None
self.qtnamespace = None
self.init_type_cache()
try:
@@ -211,7 +214,7 @@ class DumperBase():
self.currentPrintsAddress = True
self.currentChildType = None
self.currentChildNumChild = None
self.register_known_types()
self.register_known_simple_types()
def setVariableFetchingOptions(self, args):
self.last_args = args
@@ -233,9 +236,16 @@ class DumperBase():
self.useTimeStamps = int(args.get('timestamps', '0'))
self.partialVariable = args.get('partialvar', '')
self.uninitialized = args.get('uninitialized', [])
self.qtversion = args.get('qtversion', 0x060602)
self.qtnamespace = args.get('qtnamespace', '')
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
if self.qtversion is None:
self.qtversion = args.get('qtversion', None)
if self.qtversion == 0:
self.qtversion = None
if self.qtnamespace is None:
self.qtnamespace = args.get('qtnamespace', None)
#self.warn('NAMESPACE: "%s"' % self.qtNamespace())
#self.warn('EXPANDED INAMES: %s' % self.expandedINames)
#self.warn('WATCHERS: %s' % self.watchers)
@@ -256,11 +266,50 @@ class DumperBase():
args['partialvar'] = ''
self.fetchVariables(args)
def extractQtVersion(self):
# can be overridden in bridges
pass
def qtVersion(self):
if self.qtversion:
return self.qtversion
#self.warn("ACCESSING UNKNOWN QT VERSION")
self.qtversion = self.extractQtVersion()
if self.qtversion:
return self.qtversion
#self.warn("EXTRACTING QT VERSION FAILED. GUESSING NOW.")
if self.qtversionAtLeast6 is None or self.qtversionAtLeast6 is True:
return 0x060602
return 0x050f00
def qtVersionAtLeast(self, version):
# A hack to cover most of the changes from Qt 5 to 6
if version == 0x60000 and self.qtversionAtLeast6 is not None:
return self.qtversionAtLeast6
if version == 0x50000: # FIXME: This drops unknown 4.x for now
return True
return self.qtVersion() >= version
def qtVersionPing(self, typeid, size_for_qt5=-1):
# To be called from places where the type size is sufficient
# to distinguish Qt 5.x and 6.x
if size_for_qt5 == -1:
size_for_qt5 = self.ptrSize()
test_size = self.type_size(typeid)
self.setQtVersionAtLeast6(test_size > size_for_qt5)
def setQtVersionAtLeast6(self, is6):
if self.qtversionAtLeast6 is None:
#self.warn("SETTING Qt VERSION AT LEAST 6 TO %s" % is6)
self.qtversionAtLeast6 = is6
self.register_known_qt_types()
#else:
# self.warn("QT VERSION ALREADY KNOWN")
def qtNamespace(self):
return self.qtnamespace
return '' if self.qtnamespace is None else self.qtnamespace
def resetPerStepCaches(self):
self.perStepCache = {}
@@ -494,8 +543,13 @@ class DumperBase():
def register_struct(self, name, p5=0, p6=0, s=0, qobject_based=False):
# p5 = n -> n * ptrsize for Qt 5
# p6 = n -> n * ptrsize for Qt 6
#if self.qtVersion() >= 0x060000: # FIXME: Qt 5, ptrSize()
if self.qtversionAtLeast6 is None:
self.warn("TOO EARLY TO GUESS QT VERSION")
size = 8 * p6 + s
elif self.qtversionAtLeast6 is True:
size = 8 * p6 + s
else:
size = 8 * p5 + s
typeid = self.typeid_for_string(name)
self.type_code_cache[typeid] = TypeCode.Struct
self.type_size_cache[typeid] = size
@@ -503,7 +557,7 @@ class DumperBase():
self.type_alignment_cache[typeid] = 8
return typeid
def register_known_types(self):
def register_known_simple_types(self):
typeid = 0
self.typeid_cache[''] = typeid
self.type_code_cache[typeid] = TypeCode.Void
@@ -563,6 +617,8 @@ class DumperBase():
self.register_enum('@Qt::ItemDataRole', 4)
def register_known_qt_types(self):
#self.warn("REGISTERING KNOWN QT TYPES NOW")
self.register_struct('@QObject', p5=2, p6=2, qobject_based=True)
self.register_struct('@QObjectPrivate', p5=10, p6=10) # FIXME: Not exact
@@ -711,9 +767,9 @@ class DumperBase():
return limit
def vectorData(self, value):
if self.qtVersion() >= 0x060000:
if self.qtVersionAtLeast(0x060000):
data, length, alloc = self.qArrayData(value)
elif self.qtVersion() >= 0x050000:
elif self.qtVersionAtLeast(0x050000):
vector_data_ptr = self.extractPointer(value)
if self.ptrSize() == 4:
(ref, length, alloc, offset) = self.split('IIIp', vector_data_ptr)
@@ -729,7 +785,7 @@ class DumperBase():
return data, length
def qArrayData(self, value):
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
dd, data, length = self.split('ppp', value)
if dd:
_, _, alloc = self.split('iip', dd)
@@ -740,7 +796,7 @@ class DumperBase():
def qArrayDataHelper(self, array_data_ptr):
# array_data_ptr is what is e.g. stored in a QByteArray's d_ptr.
if self.qtVersion() >= 0x050000:
if self.qtVersionAtLeast(0x050000):
# QTypedArray:
# - QtPrivate::RefCount ref
# - int length
@@ -753,7 +809,7 @@ class DumperBase():
data = data & 0xffffffff
else:
data = data & 0xffffffffffffffff
elif self.qtVersion() >= 0x040000:
elif self.qtVersionAtLeast(0x040000):
# Data:
# - QBasicAtomicInt ref;
# - int alloc, length;
@@ -1597,7 +1653,7 @@ class DumperBase():
intSize = 4
ptrSize = self.ptrSize()
if self.qtVersion() >= 0x060000:
if self.qtVersionAtLeast(0x060000):
# Size of QObjectData: 9 pointer + 2 int
# - vtable
# - QObject *q_ptr;
@@ -1618,7 +1674,7 @@ class DumperBase():
# - QList<QPointer<QObject> > eventFilters;
# - QString objectName
objectNameAddress = extra + 12 * ptrSize
elif self.qtVersion() >= 0x050000:
elif self.qtVersionAtLeast(0x050000):
# Size of QObjectData: 5 pointer + 2 int
# - vtable
# - QObject *q_ptr;
@@ -1811,7 +1867,7 @@ class DumperBase():
# a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself),
# a Q_GADGET SMO has a null superdata (hopefully)
if result and not isQObjectProper:
if self.qtVersion() >= 0x60000 and self.isWindowsTarget():
if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget():
(direct, indirect) = self.split('pp', result)
# since Qt 6 there is an additional indirect super data getter on windows
if direct == 0 and indirect == 0:
@@ -1895,14 +1951,14 @@ class DumperBase():
return result
def listData(self, value, check=True):
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
dd, data, size = self.split('ppi', value)
return data, size
base = self.extractPointer(value)
(ref, alloc, begin, end) = self.split('IIII', base)
array = base + 16
if self.qtVersion() < 0x50000:
if not self.qtVersionAtLeast(0x50000):
array += self.ptrSize()
size = end - begin
@@ -1941,7 +1997,7 @@ class DumperBase():
def metaString(self, metaObjectPtr, index, revision):
ptrSize = self.ptrSize()
stringdataOffset = ptrSize
if self.isWindowsTarget() and self.qtVersion() >= 0x060000:
if self.isWindowsTarget() and self.qtVersionAtLeast(0x060000):
stringdataOffset += ptrSize # indirect super data member
stringdata = self.extract_pointer_at_address(int(metaObjectPtr) + stringdataOffset)
@@ -1970,19 +2026,19 @@ class DumperBase():
self.putField('sortgroup', sortorder)
def putQMetaStuff(self, value, origType):
if self.qtVersion() >= 0x060000:
if self.qtVersionAtLeast(0x060000):
metaObjectPtr, handle = value.split('pp')
else:
metaObjectPtr, handle = value.split('pI')
if metaObjectPtr != 0:
if self.qtVersion() >= 0x060000:
if self.qtVersionAtLeast(0x060000):
if handle == 0:
self.putEmptyValue()
return
revision = 9
name, alias, flags, keyCount, data = self.split('IIIII', handle)
index = name
elif self.qtVersion() >= 0x050000:
elif self.qtVersionAtLeast(0x050000):
revision = 7
dataPtr = self.extract_pointer_at_address(metaObjectPtr + 2 * self.ptrSize())
index = self.extractInt(dataPtr + 4 * handle)
@@ -2024,7 +2080,7 @@ class DumperBase():
def extractDataPtr(someMetaObjectPtr):
# dataPtr = metaObjectPtr['d']['data']
if self.qtVersion() >= 0x60000 and self.isWindowsTarget():
if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget():
offset = 3
else:
offset = 2
@@ -2054,13 +2110,13 @@ class DumperBase():
extraData = 0
if qobjectPtr:
dd = self.extract_pointer_at_address(qobjectPtr + ptrSize)
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
(dvtablePtr, qptr, parent, children, bindingStorageData, bindingStatus,
flags, postedEvents, dynMetaObjectPtr, # Up to here QObjectData.
extraData, threadDataPtr, connectionListsPtr,
sendersPtr, currentSenderPtr) \
= self.split('pp{@QObject*}{@QList<@QObject *>}ppIIp' + 'ppppp', dd)
elif self.qtVersion() >= 0x50000:
elif self.qtVersionAtLeast(0x50000):
(dvtablePtr, qptr, parent, children, flags, postedEvents,
dynMetaObjectPtr, # Up to here QObjectData.
extraData, threadDataPtr, connectionListsPtr,
@@ -2186,7 +2242,7 @@ typename))
with Children(self):
# Static properties.
for i in range(propertyCount):
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
t = self.split('IIIII', dataPtr + properties * 4 + 20 * i)
else:
t = self.split('III', dataPtr + properties * 4 + 12 * i)
@@ -2239,18 +2295,18 @@ typename))
data += inner_size
variant_typeid = self.cheap_typeid_from_name('@QVariant')
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
values = vectorGenerator(extraData + 3 * ptrSize, variant_typeid)
elif self.qtVersion() >= 0x50600:
elif self.qtVersionAtLeast(0x50600):
values = vectorGenerator(extraData + 2 * ptrSize, variant_typeid)
elif self.qtVersion() >= 0x50000:
elif self.qtVersionAtLeast(0x50000):
values = list5Generator(extraData + 2 * ptrSize, variant_typeid)
else:
variantptr_typeid = self.cheap_typeid_from_name('@QVariant')
values = list5Generator(extraData + 2 * ptrSize, variantptr_typeid)
bytearray_typeid = self.cheap_typeid_from_name('@QByteArray')
if self.qtVersion() >= 0x60000:
if self.qtVersionAtLeast(0x60000):
names = list6Generator(extraData, bytearray_typeid)
else:
names = list5Generator(extraData + ptrSize, bytearray_typeid)
@@ -3427,9 +3483,9 @@ typename))
):
return True
if strippedName == 'QStringList':
return self.dumper.qtVersion() >= 0x050000
return self.dumper.qtVersionAtLeast(0x050000)
if strippedName == 'QList':
return self.dumper.qtVersion() >= 0x050600
return self.dumper.qtVersionAtLeast(0x050600)
return False
class Field:
@@ -3550,7 +3606,7 @@ typename))
if typename.startswith('QList<') or typename.startswith('QVector<'):
typeid = self.typeid_for_string(typename)
if typeid:
size = 3 * self.ptrSize() if self.qtVersion() >= 0x060000 else self.ptrSize()
size = 3 * self.ptrSize() if self.qtVersionAtLeast(0x060000) else self.ptrSize()
self.type_code_cache[typeid] = TypeCode.Struct
self.type_size_cache[typeid] = size
return typeid

View File

@@ -874,6 +874,36 @@ class Dumper(DumperBase):
except:
return '0x%x' % address
def qtVersionString(self):
try:
return str(gdb.lookup_symbol('qVersion')[0].value()())
except:
pass
try:
ns = self.qtNamespace()
return str(gdb.parse_and_eval("((const char*(*)())'%sqVersion')()" % ns))
except:
pass
return None
def extractQtVersion(self):
try:
# Only available with Qt 5.3+
return int(str(gdb.parse_and_eval('((void**)&qtHookData)[2]')), 16)
except:
pass
try:
version = self.qtVersionString()
(major, minor, patch) = version[version.find('"') + 1:version.rfind('"')].split('.')
qtversion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
self.qtVersion = lambda: qtversion
return qtversion
except:
# Use fallback until we have a better answer.
return None
def createSpecialBreakpoints(self, args):
self.specialBreakpoints = []

View File

@@ -783,6 +783,54 @@ class Dumper(DumperBase):
self.fetchInternalFunctions = lambda: None
def extractQtVersion(self):
for func in self.target.FindFunctions('qVersion'):
name = func.GetSymbol().GetName()
if name == None:
continue
if name.endswith('()'):
name = name[:-2]
if name.count(':') > 2:
continue
#qtNamespace = name[:name.find('qVersion')]
#self.qtNamespace = lambda: qtNamespace
options = lldb.SBExpressionOptions()
res = self.target.EvaluateExpression(name + '()', options)
if not res.IsValid() or not res.GetType().IsPointerType():
exp = '((const char*())%s)()' % name
res = self.target.EvaluateExpression(exp, options)
if not res.IsValid() or not res.GetType().IsPointerType():
exp = '((const char*())_Z8qVersionv)()'
res = self.target.EvaluateExpression(exp, options)
if not res.IsValid() or not res.GetType().IsPointerType():
continue
version = str(res)
if version.count('.') != 2:
continue
version.replace("'", '"') # Both seem possible
version = version[version.find('"') + 1:version.rfind('"')]
(major, minor, patch) = version.split('.')
qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
return qtVersion
try:
versionValue = self.target.EvaluateExpression('qtHookData[2]').GetNonSyntheticValue()
if versionValue.IsValid():
return versionValue.unsigned
except:
pass
return None
def handleCommand(self, command):
result = lldb.SBCommandReturnObject()
self.debugger.GetCommandInterpreter().HandleCommand(command, result)

View File

@@ -33,7 +33,8 @@ def qedit__QByteArray(d, value, data):
def qdump__QByteArray(d, value):
if d.qtVersion() >= 0x60000:
d.qtVersionPing(value.typeid)
if d.qtVersionAtLeast(0x060000):
dd, data, length = value.split('ppi')
if dd:
_, _, alloc = d.split('iii', dd)
@@ -76,7 +77,8 @@ def qdump__QByteArray(d, value):
def qdump__QBitArray(d, value):
if d.qtVersion() >= 0x60000:
d.qtVersionPing(value.typeid)
if d.qtVersionAtLeast(0x060000):
_, data, basize = value.split('ppi')
else:
data, basize, _ = d.qArrayData(value['d'])
@@ -232,13 +234,13 @@ def qdump__QStandardItem(d, value):
#d.createType('@QStandardItem*')
vtable, dptr = value.split('pp')
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
model, parent, values, children, rows, cols, item = \
d.split('pp{@QList<@QStandardItemData>}{@QList<@QStandardItem *>}IIp', dptr)
else:
# There used to be a virtual destructor that got removed in
# 88b6abcebf29b455438 on Apr 18 17:01:22 2017
if d.qtVersion() < 0x050900 and not d.isMsvcTarget():
if not d.qtVersionAtLeast(0x050900) and not d.isMsvcTarget():
dptr += d.ptrSize();
model, parent, values, children, rows, cols, item = \
d.split('pp{@QVector<@QStandardItemData>}{@QVector<@QStandardItem *>}IIp', dptr)
@@ -266,7 +268,7 @@ def qdump__QDate(d, value):
d.enumExpression('DateFormat', 'TextDate'))
d.putCallItem('(ISO)', '@QString', value, 'toString',
d.enumExpression('DateFormat', 'ISODate'))
if d.qtVersion() < 0x060000:
if not d.qtVersionAtLeast(0x060000):
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
d.enumExpression('DateFormat', 'SystemLocaleDate'))
d.putCallItem('(Locale)', '@QString', value, 'toString',
@@ -286,7 +288,7 @@ def qdump__QTime(d, value):
d.enumExpression('DateFormat', 'TextDate'))
d.putCallItem('(ISO)', '@QString', value, 'toString',
d.enumExpression('DateFormat', 'ISODate'))
if d.canCallLocale() and d.qtVersion() < 0x060000:
if d.canCallLocale() and not d.qtVersionAtLeast(0x060000):
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
d.enumExpression('DateFormat', 'SystemLocaleDate'))
d.putCallItem('(Locale)', '@QString', value, 'toString',
@@ -305,13 +307,12 @@ def qdump__QTimeZone(d, value):
def qdump__QDateTime(d, value):
qtVersion = d.qtVersion()
isValid = False
# This relies on the Qt4/Qt5 internal structure layout:
# {sharedref(4), ...
base = d.extractPointer(value)
is32bit = d.ptrSize() == 4
if qtVersion >= 0x050200:
if qtVersionAtLeast(0x050200):
tiVersion = d.qtTypeInfoVersion()
#DumperBase.warn('TI VERSION: %s' % tiVersion)
if tiVersion is None:
@@ -384,9 +385,9 @@ def qdump__QDateTime(d, value):
# - [QTime time;]
# - - uint mds;
# - Spec spec;
dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint
dateSize = 8 if qtVersionAtLeast(0x050000) else 4 # Qt5: qint64, Qt4 uint
# 4 byte padding after 4 byte QAtomicInt if we are on 64 bit and QDate is 64 bit
refPlusPadding = 8 if qtVersion >= 0x050000 and d.ptrSize() == 8 else 4
refPlusPadding = 8 if qtVersionAtLeast(0x050000) and d.ptrSize() == 8 else 4
dateBase = base + refPlusPadding
timeBase = dateBase + dateSize
mds = d.extractInt(timeBase)
@@ -410,7 +411,7 @@ def qdump__QDateTime(d, value):
d.enumExpression('DateFormat', 'ISODate'))
d.putCallItem('toUTC', '@QDateTime', value, 'toTimeSpec',
d.enumExpression('TimeSpec', 'UTC'))
if d.qtVersion() < 0x060000:
if not d.qtVersionAtLeast(0x060000):
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
d.enumExpression('DateFormat', 'SystemLocaleDate'))
d.putCallItem('(Locale)', '@QString', value, 'toString',
@@ -756,7 +757,6 @@ def qdump__QFile(d, value):
def qdump__QFileInfo(d, value):
privAddress = d.extractPointer(value)
#bit32 = d.ptrSize() == 4
#qt5 = d.qtVersion() >= 0x050000
#try:
# d.putStringValue(value['d_ptr']['d'].dereference()['fileNames'][3])
#except:
@@ -876,7 +876,7 @@ def qdump__QVariantHash(d, value):
def qdumpHelper_QHash(d, value, keyType, valueType):
if d.qtVersion() >= 0x60000:
if d.qtVersionAtLeast(0x060000):
qdumpHelper_QHash_6(d, value, keyType, valueType)
else:
qdumpHelper_QHash_5(d, value, keyType, valueType)
@@ -918,7 +918,7 @@ def qdumpHelper_QHash_5(d, value, keyType, valueType):
d.putItemCount(size)
if d.isExpanded():
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
with Children(d, size):
node = hashDataFirstNode()
for i in d.childRange():
@@ -994,7 +994,7 @@ def qHashIteratorHelper(d, value):
if d.isExpanded():
with Children(d):
node = d.extractPointer(value)
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
if isShort:
typeCode = 'P{%s}@{%s}' % (keyType.name, valueType.name)
(pnext, key, padding2, val) = d.split(typeCode, node)
@@ -1015,9 +1015,8 @@ def qdump__QHash__iterator(d, value):
def qdump__QHostAddress(d, value):
dd = d.extractPointer(value)
qtVersion = d.qtVersion()
tiVersion = d.qtTypeInfoVersion()
#DumperBase.warn('QT: %x, TI: %s' % (qtVersion, tiVersion))
#DumperBase.warn('QT: %x, TI: %s' % (d.qtVersion(), tiVersion))
mayNeedParse = True
if tiVersion is not None:
if tiVersion >= 16:
@@ -1032,14 +1031,14 @@ def qdump__QHostAddress(d, value):
else:
(ipString, scopeId, a4, pad, a6, protocol, isParsed) \
= d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd)
elif qtVersion >= 0x050600: # 5.6.0 at f3aabb42
elif qtVersionAtLeast(0x050600): # 5.6.0 at f3aabb42
if d.ptrSize() == 8 or d.isWindowsTarget():
(ipString, scopeId, a4, pad, a6, protocol, isParsed) \
= d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd)
else:
(ipString, scopeId, a4, a6, protocol, isParsed) \
= d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd)
elif qtVersion >= 0x050000: # 5.2.0 at 62feb088
elif qtVersionAtLeast(0x050000): # 5.2.0 at 62feb088
(ipString, scopeId, a4, a6, protocol, isParsed) \
= d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd)
else: # 4.8.7 at b05d05f
@@ -1104,7 +1103,8 @@ def qdumpHelper_QList(d, value, inner_typish):
data, size = d.listData(value, check=True)
d.putItemCount(size)
if d.qtVersion() >= 0x60000:
d.qtVersionPing(value.typeid)
if d.qtVersionAtLeast(0x060000):
d.putPlotData(data, size, innerType)
return
@@ -1145,9 +1145,9 @@ def qform__QImage():
def qdump__QImage(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
vtbl, painters, image_data = value.split('ppp')
elif d.qtVersion() >= 0x050000:
elif d.qtVersionAtLeast(0x050000):
vtbl, painters, reserved, image_data = value.split('pppp')
else:
vtbl, painters, image_data = value.split('ppp')
@@ -1161,12 +1161,12 @@ def qdump__QImage(d, value):
d.putExpandable()
if d.isExpanded():
if d.qtVersion() < 0x060000:
(ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable,
bits, iformat) = d.split('iiiii@dppi', image_data)
else:
if d.qtVersionAtLeast(0x060000):
(ref, width, height, depth, nbytes, pad, devicePixelRatio, _, _, _,
bits, iformat) = d.split('iiiii@dppppi', image_data)
else:
(ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable,
bits, iformat) = d.split('iiiii@dppi', image_data)
with Children(d):
d.putIntItem('width', width)
d.putIntItem('height', height)
@@ -1222,8 +1222,7 @@ def qdump__QLocale(d, value):
# index = int(value['d']['d']['m_data']...)
#d.check(index >= 0)
#d.check(index <= qqLocalesCount)
qtVersion = d.qtVersion()
if qtVersion < 0x50000:
if not d.qtVersionAtLeast(0x50000):
d.putStringValue(d.call('const char *', value, 'name'))
d.putPlainChildren(value)
return
@@ -1240,7 +1239,7 @@ def qdump__QLocale(d, value):
prefix = ns + 'QLocale::'
try:
if qtVersion >= 0x060700:
if qtVersionAtLeast(0x060700):
res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
else:
res = d.call('const char *', value, 'name')
@@ -1347,9 +1346,9 @@ def qdump__QMap(d, value):
def qdumpHelper_QMap(d, value, keyType, valueType):
if d.qtVersion() >= 0x60000:
if d.qtVersionAtLeast(0x060000):
qdumpHelper_Qt6_QMap(d, value, keyType, valueType)
elif d.qtVersion() >= 0x50000:
elif d.qtVersionAtLeast(0x50000):
qdumpHelper_Qt5_QMap(d, value, keyType, valueType)
else:
qdumpHelper_Qt4_QMap(d, value, keyType, valueType)
@@ -1369,7 +1368,7 @@ def qdumpHelper_Qt6_QMultiMap(d, value, keyType, valueType):
d.putBetterType('@QMultiMap<%s, %s>' % (keyType.name, valueType.name))
def qdump__QMultiMap(d, value):
if d.qtVersion() >= 0x60000:
if d.qtVersionAtLeast(0x060000):
qdumpHelper_Qt6_QMultiMap(d, value, value.type[0], value.type[1])
else:
qdump__QMap(d, value)
@@ -1449,9 +1448,9 @@ def qdump__QProcEnvKey(d, value):
def qdump__QPixmap(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
vtbl, painters, data = value.split('ppp')
elif d.qtVersion() >= 0x050000:
elif d.qtVersionAtLeast(0x050000):
vtbl, painters, reserved, data = s = d.split('pppp', value)
else:
vtbl, painters, data = value.split('ppp')
@@ -1518,15 +1517,15 @@ def qdump__QRegion(d, value):
if d_ptr == 0:
d.putSpecialValue('empty')
else:
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
ref, _, rgn = d.split('i@p', d_ptr)
numRects, innerArea, rects, extents, innerRect = \
d.split('ii{@QList<@QRect>}{@QRect}{@QRect}', rgn)
elif d.qtVersion() >= 0x050400: # Padding removed in ee324e4ed
elif d.qtVersionAtLeast(0x050400): # Padding removed in ee324e4ed
ref, _, rgn = d.split('i@p', d_ptr)
numRects, innerArea, rects, extents, innerRect = \
d.split('ii{@QVector<@QRect>}{@QRect}{@QRect}', rgn)
elif d.qtVersion() >= 0x050000:
elif d.qtVersionAtLeast(0x050000):
ref, _, rgn = d.split('i@p', d_ptr)
numRects, _, rects, extents, innerRect, innerArea = \
d.split('i@{@QVector<@QRect>}{@QRect}{@QRect}i', rgn)
@@ -1564,7 +1563,7 @@ def qdump__QScopedPointer(d, value):
def qdump__QSet(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
qdumpHelper_QSet6(d, value)
else:
qdumpHelper_QSet45(d, value)
@@ -1637,7 +1636,7 @@ def qdumpHelper_QSet45(d, value):
d.putItemCount(length)
if d.isExpanded():
keyType = value.type[0]
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
with Children(d, length, childType=keyType):
node = hashDataFirstNode()
for i in d.childRange():
@@ -1714,7 +1713,7 @@ def qform__QStack():
def qdump__QStack(d, value):
if d.qtVersion() >= 0x60000:
if d.qtVersionVersionAtLeast(0x060000):
qdump__QList(d, value)
else:
qdump__QVector(d, value)
@@ -1734,7 +1733,7 @@ def qdump__QPolygon(d, value):
def qdump__QGraphicsPolygonItem(d, value):
(vtbl, dptr) = value.split('pp')
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
if d.ptrSize() == 8:
offset = 424 # sizeof(QGraphicsPolygonItemPrivate), the base
else:
@@ -1764,6 +1763,7 @@ def qform__QString():
def qdump__QString(d, value):
d.qtVersionPing(value.typeid)
d.putStringValue(value)
data, length, _ = d.stringData(value)
displayFormat = d.currentItemFormat()
@@ -1924,7 +1924,7 @@ def qdump__QUrl(d, value):
d.putValue('<invalid>')
return
if d.qtVersion() < 0x050000:
if not d.qtVersionAtLeast(0x050000):
d.call('void', value, 'port') # Warm up internal cache.
d.call('void', value, 'path')
st = '{@QString}'
@@ -2154,7 +2154,8 @@ qdumpHelper_QVariants_F = [
def qdump__QVariant(d, value):
if d.qtVersion() >= 0x060000:
d.qtVersionPing(value.typeid, 2 * d.ptrSize())
if d.qtVersionAtLeast(0x060000):
qdumpHelper__QVariant6(d, value)
else:
qdumpHelper__QVariant45(d, value)
@@ -2208,12 +2209,12 @@ def qdumpHelper__QVariant45(d, value):
return None
# Extended Core type (Qt 5)
if variantType >= 31 and variantType <= 38 and d.qtVersion() >= 0x050000:
if variantType >= 31 and variantType <= 38 and d.qtVersionAtLeast(0x050000):
qdumpHelper_QVariants_D[variantType - 31](d, value)
return None
# Extended Core type (Qt 4)
if variantType >= 128 and variantType <= 135 and d.qtVersion() < 0x050000:
if variantType >= 128 and variantType <= 135 and not d.qtVersionAtLeast(0x050000):
if variantType == 128:
d.putBetterType('@QVariant (void *)')
d.putValue('0x%x' % value.extractPointer())
@@ -2234,7 +2235,7 @@ def qdumpHelper__QVariant45(d, value):
innert = qdumpHelper_QVariants_B[variantType - 7]
elif variantType <= 74:
innert = qdumpHelper_QVariants_E[variantType - 64]
elif d.qtVersion() < 0x050000:
elif not d.qtVersionAtLeast(0x050000):
innert = qdumpHelper_QVariants_F[variantType - 76]
else:
innert = qdumpHelper_QVariants_F[variantType - 75]
@@ -2308,7 +2309,8 @@ def qform__QVector():
def qdump__QVector(d, value):
if d.qtVersion() >= 0x060000:
d.qtVersionPing(value.typeid)
if d.qtVersionAtLeast(0x060000):
data, length = d.listData(value)
d.putItemCount(length)
d.putPlotData(data, length, value.type.target()[0])
@@ -2330,7 +2332,7 @@ if False:
def qdump__QVarLengthArray(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
cap, length, data = value.split('QQp')
else:
cap, length, data = value.split('iip')
@@ -2366,7 +2368,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak, innerType=None):
d.putValue('<invalid>')
return
if d.qtVersion() >= 0x050000:
if d.qtVersionAtLeast(0x050000):
(weakref, strongref) = d.split('ii', d_ptr)
else:
(vptr, weakref, strongref) = d.split('pii', d_ptr)
@@ -2872,7 +2874,7 @@ def qdump__QJSValue(d, value):
if d.ptrSize() == 4:
qdump_32__QJSValue(d, value)
else:
if d.qtVersion() >= 0x60000:
if d.qtVersionAtLeast(0x060000):
qdump_64__QJSValue_6(d, value)
else:
qdump_64__QJSValue_5(d, value)
@@ -2906,7 +2908,7 @@ def qdump_64__QJSValue_6(d, value):
if dd == 0:
d.putValue('(undefined)')
d.putType(value.type.name + ' (undefined)')
if d.qtVersion() < 0x60500:
if not d.qtVersionAtLeast(0x60500):
typ = dd >> 47
if typ == 5:
d.putValue('(null)')
@@ -3326,7 +3328,7 @@ def qdumpHelper_QJsonObject(d, data, obj):
def qdump__QJsonValue(d, value):
(data, dd, t) = value.split('QpI')
if d.qtVersion() >= 0x050f00:
if d.qtVersionAtLeast(0x050f00):
value = d.createProxyValue((data, dd, t, False), 'QCborValue_proxy')
d.putItem(value)
return
@@ -3361,13 +3363,13 @@ def qdump__QJsonValue(d, value):
def qdump__QJsonArray(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
dptr = d.extractPointer(value)
if not dptr:
d.putItemCount(0)
else:
qdumpHelper_QCbor_array(d, dptr, False)
elif d.qtVersion() >= 0x050f00:
elif d.qtVersionAtLeast(0x050f00):
_, container_ptr = value.split('pp')
qdumpHelper_QCbor_array(d, container_ptr, False)
else:
@@ -3375,13 +3377,13 @@ def qdump__QJsonArray(d, value):
def qdump__QJsonObject(d, value):
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
dptr = d.extractPointer(value)
if not dptr:
d.putItemCount(0)
else:
qdumpHelper_QCbor_map(d, dptr, False)
elif d.qtVersion() >= 0x050f00:
elif d.qtVersionAtLeast(0x050f00):
_, container_ptr = value.split('pp')
qdumpHelper_QCbor_map(d, container_ptr, False)
else:
@@ -3456,15 +3458,15 @@ def qdump__qfloat16(d, value):
def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes):
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
# so be explicit:
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
elements_data_ptr, elements_size = d.vectorData(elements_pos)
element_at_n_addr = elements_data_ptr + element_index * 16 # sizeof(QtCbor::Element) == 16
element_value, _, element_flags = d.split('qII', element_at_n_addr)
enc = 'latin1' if is_bytes or (element_flags & 8) else 'utf16'
bytedata, _, _ = d.qArrayData(data_pos)
bytedata += element_value
if d.qtVersion() >= 0x060000:
if d.qtVersionAtLeast(0x060000):
bytedata_len = d.extractInt64(bytedata)
bytedata_data = bytedata + 8
else:
@@ -3493,8 +3495,8 @@ def qdumpHelper_QCbor_array(d, container_ptr, is_cbor):
return
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
# so be explicit:
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
elements_data_ptr, elements_size = d.vectorData(elements_pos)
d.putItemCount(elements_size)
if d.isExpanded():
@@ -3515,8 +3517,8 @@ def qdumpHelper_QCbor_map(d, container_ptr, is_cbor):
return
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
# so be explicit:
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
elements_data_ptr, elements_size = d.vectorData(elements_pos)
elements_size = int(elements_size / 2)
d.putItemCount(elements_size)