diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index c16467915a0..ce88c903a77 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -76,7 +76,9 @@ class Dumper(DumperBase): self.outputLock = threading.Lock() self.isCdb = True - #FIXME + #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] diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index c2580880f55..58525df2f29 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -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): - return self.qtversion + 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() - size = 8 * p6 + s + 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 > 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 diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 5e2957b1812..ee25520bced 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -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 = [] diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 7cd3bef77e0..96c149ea025 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -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) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index af99534c9b4..a9220636855 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -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('') 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('') 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)