diff options
author | hjk <hjk@theqtcompany.com> | 2015-03-20 16:03:59 +0100 |
---|---|---|
committer | hjk <hjk@theqtcompany.com> | 2015-03-23 14:12:43 +0000 |
commit | 48ac7c186b0228f13bbd8a0f00ab39300765dc4a (patch) | |
tree | 73c36fc0dee1f7e922473f71b3ac8418dece7bb1 | |
parent | b727c15a534ce337e8cfcd49a0b091aee5462bf3 (diff) | |
download | qt-creator-48ac7c186b0228f13bbd8a0f00ab39300765dc4a.tar.gz |
Debugger: Re-organize passing of display formats
The current setup (dumper->gui: list of descriptions,
gui->dumper: index in list) is fragile and not easily
i18n'able. Go with an enum based approach now.
Change-Id: Ie78c596065a8b2ba87ad725274da29d4be3a6da4
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
-rw-r--r-- | share/qtcreator/debugger/dumper.py | 148 | ||||
-rw-r--r-- | share/qtcreator/debugger/gdbbridge.py | 31 | ||||
-rw-r--r-- | share/qtcreator/debugger/lldbbridge.py | 11 | ||||
-rw-r--r-- | share/qtcreator/debugger/qttypes.py | 59 | ||||
-rw-r--r-- | share/qtcreator/debugger/stdtypes.py | 5 | ||||
-rw-r--r-- | src/plugins/debugger/cdb/cdbengine.cpp | 14 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerdialogs.cpp | 13 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerdialogs.h | 7 | ||||
-rw-r--r-- | src/plugins/debugger/watchhandler.cpp | 87 | ||||
-rw-r--r-- | src/plugins/debugger/watchhandler.h | 102 | ||||
-rw-r--r-- | src/plugins/debugger/watchwindow.cpp | 20 |
11 files changed, 221 insertions, 276 deletions
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 6fa45a43c7..52e475e27f 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -67,9 +67,15 @@ StartRemoteProcess, \ # Known special formats. Keep in sync with DisplayFormat in watchhandler.h -KnownDumperFormatBase, \ +AutomaticFormat, \ +RawFormat, \ +SimpleFormat, \ +EnhancedFormat, \ +SeparateFormat, \ Latin1StringFormat, \ +SeparateLatin1StringFormat, \ Utf8StringFormat, \ +SeparateUtf8StringFormat, \ Local8BitStringFormat, \ Utf16StringFormat, \ Ucs4StringFormat, \ @@ -77,9 +83,11 @@ Array10Format, \ Array100Format, \ Array1000Format, \ Array10000Format, \ -SeparateLatin1StringFormat, \ -SeparateUtf8StringFormat \ - = range(100, 112) +ArrayPlotFormat, \ +CompactMapFormat, \ +DirectQListStorageFormat, \ +IndirectQListStorageFormat, \ + = range(0, 20) # Breakpoints. Keep synchronized with BreakpointType in breakpoint.h UnknownType, \ @@ -171,10 +179,10 @@ if hasSubprocess and hasPlot: def arrayForms(): global hasPlot - return "Normal,Plot" if hasPlot else "Normal" + return [ArrayPlotFormat] if hasPlot else [] def mapForms(): - return "Normal,Compact" + return [CompactMapFormat] class ReportItem: @@ -583,12 +591,13 @@ class DumperBase: elided, shown = self.computeLimit(size, limit) return elided, self.readMemory(data, shown) - def putStdStringHelper(self, data, size, charSize, format = None): + def putStdStringHelper(self, data, size, charSize, displayFormat = AutomaticFormat): bytelen = size * charSize elided, shown = self.computeLimit(bytelen, self.displayStringLimit) mem = self.readMemory(data, shown) if charSize == 1: - if format == 1 or format == 2: + if displayFormat == Latin1StringFormat \ + or displayFormat == SeparateLatin1StringFormat: encodingType = Hex2EncodedLatin1 else: encodingType = Hex2EncodedUtf8 @@ -603,9 +612,11 @@ class DumperBase: self.putNumChild(0) self.putValue(mem, encodingType, elided=elided) - if format == 1 or format == 3: + if displayFormat == Latin1StringFormat \ + or displayFormat == Utf8StringFormat: self.putDisplay(StopDisplay) - elif format == 2 or format == 4: + elif displayFormat == SeparateLatin1StringFormat \ + or displayFormat == SeparateUtf8StringFormat: self.putField("editformat", displayType) elided, shown = self.computeLimit(bytelen, 100000) self.putField("editvalue", self.readMemory(data, shown)) @@ -801,9 +812,8 @@ class DumperBase: self.putFields(value, dumpBase) def isMapCompact(self, keyType, valueType): - format = self.currentItemFormat() - if format == 2: - return True # Compact. + if self.currentItemFormat() == CompactMapFormat: + return True return self.isSimpleType(keyType) and self.isSimpleType(valueType) @@ -920,13 +930,13 @@ class DumperBase: except: p = None - itemFormat = self.currentItemFormat() + displayFormat = self.currentItemFormat() n = int(arrayType.sizeof / ts) - if p and self.tryPutSimpleFormattedPointer(p, str(arrayType), itemFormat, arrayType.sizeof): + if p and self.tryPutSimpleFormattedPointer(p, str(arrayType), displayFormat, arrayType.sizeof): self.putNumChild(n) pass - elif itemFormat is None: + elif displayFormat is None: innerTypeName = str(innerType.unqualified()) blob = self.readMemory(self.addressOf(value), arrayType.sizeof) if innerTypeName == "char": @@ -969,6 +979,31 @@ class DumperBase: pass return str(addr) + def tryPutPrettyItem(self, typeName, value): + if self.useFancy and self.currentItemFormat() != RawFormat: + self.putType(typeName) + + nsStrippedType = self.stripNamespaceFromType(typeName)\ + .replace("::", "__") + + # The following block is only needed for D. + if nsStrippedType.startswith("_A"): + # DMD v2.058 encodes string[] as _Array_uns long long. + # With spaces. + if nsStrippedType.startswith("_Array_"): + qdump_Array(self, value) + return True + if nsStrippedType.startswith("_AArray_"): + qdump_AArray(self, value) + return True + + dumper = self.qqDumpers.get(nsStrippedType) + if not dumper is None: + dumper(self, value) + return True + + return False + def tryPutArrayContents(self, base, n, innerType): enc = self.simpleEncoding(innerType) if not enc: @@ -991,8 +1026,8 @@ class DumperBase: data = self.readMemory(base, shown) self.putValue(data, Hex2EncodedLatin1, elided=elided) - def putDisplay(self, format, value = None, cmd = None): - self.put('editformat="%s",' % format) + def putDisplay(self, editFormat, value = None, cmd = None): + self.put('editformat="%s",' % editFormat) if cmd is None: if not value is None: self.put('editvalue="%s",' % value) @@ -1000,8 +1035,8 @@ class DumperBase: self.put('editvalue="%s|%s",' % (cmd, value)) # This is shared by pointer and array formatting. - def tryPutSimpleFormattedPointer(self, value, typeName, itemFormat, limit): - if itemFormat == None and typeName == "char": + def tryPutSimpleFormattedPointer(self, value, typeName, displayFormat, limit): + if displayFormat == AutomaticFormat and typeName == "char": # Use Latin1 as default for char *. self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) @@ -1009,56 +1044,49 @@ class DumperBase: self.putDisplay(StopDisplay) return True - if itemFormat == Latin1StringFormat: - # Explicitly requested Latin1 formatting. + if displayFormat == Latin1StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLatin1, elided=elided) self.putDisplay(StopDisplay) return True - if itemFormat == SeparateLatin1StringFormat: - # Explicitly requested Latin1 formatting in separate window. + if displayFormat == SeparateLatin1StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLatin1, elided=elided) self.putDisplay(DisplayLatin1String, data) return True - if itemFormat == Utf8StringFormat: - # Explicitly requested UTF-8 formatting. + if displayFormat == Utf8StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedUtf8, elided=elided) self.putDisplay(StopDisplay) return True - if itemFormat == SeparateUtf8StringFormat: - # Explicitly requested UTF-8 formatting in separate window. + if displayFormat == SeparateUtf8StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedUtf8, elided=elided) self.putDisplay(DisplayUtf8String, data) return True - if itemFormat == Local8BitStringFormat: - # Explicitly requested local 8 bit formatting. + if displayFormat == Local8BitStringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLocal8Bit, elided=elided) self.putDisplay(StopDisplay) return True - if itemFormat == Utf16StringFormat: - # Explicitly requested UTF-16 formatting. + if displayFormat == Utf16StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 2, limit) self.putValue(data, Hex4EncodedLittleEndian, elided=elided) self.putDisplay(StopDisplay) return True - if itemFormat == Ucs4StringFormat: - # Explicitly requested UCS-4 formatting. + if displayFormat == Ucs4StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 4, limit) self.putValue(data, Hex8EncodedLittleEndian, elided=elided) @@ -1091,16 +1119,16 @@ class DumperBase: self.putNumChild(0) return - format = self.currentItemFormat(value.type) + displayFormat = self.currentItemFormat(value.type) if innerTypeName == "void": - #warn("VOID POINTER: %s" % format) + #warn("VOID POINTER: %s" % displayFormat) self.putType(typeName) self.putValue(str(value)) self.putNumChild(0) return - if format == 0: + if displayFormat == RawFormat: # Explicitly requested bald pointer. self.putType(typeName) self.putValue(self.hexencode(str(value)), Hex2EncodedUtf8WithoutQuotes) @@ -1112,16 +1140,15 @@ class DumperBase: return limit = self.displayStringLimit - if format == DisplayLatin1String or format == DisplayUtf8String: + if displayFormat == SeparateLatin1StringFormat \ + or displayFormat == SeparateUtf8StringFormat: limit = 1000000 - if self.tryPutSimpleFormattedPointer(value, typeName, format, limit): + if self.tryPutSimpleFormattedPointer(value, typeName, displayFormat, limit): self.putNumChild(0) return - if not format is None \ - and format >= Array10Format and format <= Array1000Format: - # Explicitly requested formatting as array of n items. - n = (10, 100, 1000, 10000)[format - Array10Format] + if Array10Format <= displayFormat and displayFormat <= Array1000Format: + n = (10, 100, 1000, 10000)[displayFormat - Array10Format] self.putType(typeName) self.putItemCount(n) self.putArrayData(value, n, innerType) @@ -1141,9 +1168,7 @@ class DumperBase: #warn("AUTODEREF: %s" % self.autoDerefPointers) #warn("INAME: %s" % self.currentIName) if self.autoDerefPointers or self.currentIName.endswith('.this'): - ## Generic pointer type with format None - #warn("GENERIC AUTODEREF POINTER: %s AT %s TO %s" - # % (type, value.address, innerTypeName)) + # Generic pointer type with AutomaticFormat. # Never dereference char types. if innerTypeName != "char" \ and innerTypeName != "signed char" \ @@ -1491,13 +1516,13 @@ class DumperBase: return typeName == "QStringList" and self.qtVersion() >= 0x050000 def currentItemFormat(self, type = None): - format = self.formats.get(self.currentIName) - if format is None: + displayFormat = self.formats.get(self.currentIName, AutomaticFormat) + if displayFormat == AutomaticFormat: if type is None: type = self.currentType.value needle = self.stripForFormat(str(type)) - format = self.typeformats.get(needle) - return format + displayFormat = self.typeformats.get(needle, AutomaticFormat) + return displayFormat def putArrayData(self, base, n, innerType = None, childNumChild = None, maxNumChild = 10000): @@ -1511,19 +1536,19 @@ class DumperBase: i = toInteger(i) self.putSubItem(i, (base + i).dereference()) - def putArrayItem(self, name, addr, n, typeName, plotFormat = 2): + def putArrayItem(self, name, addr, n, typeName): with SubItem(self, name): self.putEmptyValue() self.putType("%s [%d]" % (typeName, n)) self.putArrayData(addr, n, self.lookupType(typeName)) self.putAddress(addr) - def putPlotData(self, base, n, typeobj, plotFormat = 2): + def putPlotData(self, base, n, typeobj): if self.isExpanded(): self.putArrayData(base, n, typeobj) if hasPlot: if self.isSimpleType(typeobj): - show = self.currentItemFormat() == plotFormat + show = self.currentItemFormat() == ArrayPlotFormat iname = self.currentIName data = [] if show: @@ -1688,15 +1713,13 @@ class DumperBase: if funcname.startswith("qdump__"): typename = funcname[7:] self.qqDumpers[typename] = function - self.qqFormats[typename] = self.qqFormats.get(typename, "") + self.qqFormats[typename] = self.qqFormats.get(typename, []) elif funcname.startswith("qform__"): typename = funcname[7:] - formats = "" try: - formats = function() + self.qqFormats[typename] = function() except: - pass - self.qqFormats[typename] = formats + self.qqFormats[typename] = [] elif funcname.startswith("qedit__"): typename = funcname[7:] try: @@ -1721,15 +1744,14 @@ class DumperBase: msg = "dumpers=[" for key, value in self.qqFormats.items(): - if key in self.qqEditable: - msg += '{type="%s",formats="%s",editable="true"},' % (key, value) - else: - msg += '{type="%s",formats="%s"},' % (key, value) + editable = ',editable="true"' if key in self.qqEditable else '' + formats = (',formats=\"%s\"' % str(value)[1:-1]) if len(value) else '' + msg += '{type="%s"%s%s},' % (key, editable, formats) msg += ']' self.reportDumpers(msg) def reportDumpers(self, msg): - raise NotImplementedError # Pure + raise NotImplementedError def reloadDumpers(self, args): for mod in self.dumpermodules: diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 089c4ae461..f22bd37b1d 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1075,35 +1075,8 @@ class Dumper(DumperBase): self.putItem(self.expensiveDowncast(value), False) return - format = self.currentItemFormat(typeName) - - if self.useFancy and (format is None or format >= 1): - self.putType(typeName) - - nsStrippedType = self.stripNamespaceFromType(typeName)\ - .replace("::", "__") - - # The following block is only needed for D. - if nsStrippedType.startswith("_A"): - # DMD v2.058 encodes string[] as _Array_uns long long. - # With spaces. - if nsStrippedType.startswith("_Array_"): - qdump_Array(self, value) - return - if nsStrippedType.startswith("_AArray_"): - qdump_AArray(self, value) - return - - #warn(" STRIPPED: %s" % nsStrippedType) - #warn(" DUMPERS: %s" % self.qqDumpers) - #warn(" DUMPERS: %s" % (nsStrippedType in self.qqDumpers)) - dumper = self.qqDumpers.get(nsStrippedType, None) - if not dumper is None: - if tryDynamic: - dumper(self, self.expensiveDowncast(value)) - else: - dumper(self, value) - return + if self.tryPutPrettyItem(typeName, value): + return # D arrays, gdc compiled. if typeName.endswith("[]"): diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 4d81422388..fdf70468a8 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -1063,15 +1063,8 @@ class Dumper(DumperBase): #warn("VALUE: %s" % value) #warn("FANCY: %s" % self.useFancy) - if self.useFancy: - stripped = self.stripNamespaceFromType(typeName).replace("::", "__") - #warn("STRIPPED: %s" % stripped) - #warn("DUMPABLE: %s" % (stripped in self.qqDumpers)) - if stripped in self.qqDumpers: - self.putType(typeName) - self.context = value - self.qqDumpers[stripped](self, value) - return + if self.tryPutPrettyItem(typeName, value): + return # Normal value #numchild = 1 if value.MightHaveChildren() else 0 diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index cff457ae44..f640786cef 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -53,24 +53,25 @@ def qdump__QAtomicPointer(d, value): d.putSubItem("_q_value", q.dereference()) def qform__QByteArray(): - return "Latin1 String,Latin1 String in Separate Window,UTF-8 String,UTF-8 String in Separate Window" + return [Latin1StringFormat, SeparateLatin1StringFormat, + Utf8StringFormat, SeparateUtf8StringFormat ] def qdump__QByteArray(d, value): data, size, alloc = d.byteArrayData(value) d.putNumChild(size) elided, p = d.encodeByteArrayHelper(d.extractPointer(value), d.displayStringLimit) - format = d.currentItemFormat() - if format == 1 or format is None: + displayFormat = d.currentItemFormat() + if displayFormat == AutomaticFormat or displayFormat == Latin1StringFormat: d.putDisplay(StopDisplay) d.putValue(p, Hex2EncodedLatin1, elided=elided) - elif format == 2: + elif displayFormat == SeparateLatin1StringFormat: d.putValue(p, Hex2EncodedLatin1, elided=elided) d.putField("editformat", DisplayLatin1String) d.putField("editvalue", d.encodeByteArray(value, limit=100000)) - elif format == 3: + elif displayFormat == Utf8StringFormat: d.putDisplay(StopDisplay) d.putValue(p, Hex2EncodedUtf8, elided=elided) - elif format == 4: + elif displayFormat == SeparateUtf8StringFormat: d.putValue(p, Hex2EncodedUtf8, elided=elided) d.putField("editformat", DisplayUtf8String) d.putField("editvalue", d.encodeByteArray(value, limit=100000)) @@ -92,14 +93,14 @@ def qdump__QChar(d, value): def qform__QAbstractItemModel(): - return "Normal,Enhanced" + return [SimpleFormat, EnhancedFormat] def qdump__QAbstractItemModel(d, value): - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == SimpleFormat: d.putPlainChildren(value) return - #format == 2: + #displayFormat == EnhancedFormat: # Create a default-constructed QModelIndex on the stack. try: ri = d.makeValue(d.qtNamespace() + "QModelIndex", "-1, -1, 0, 0") @@ -134,11 +135,11 @@ def qdump__QAbstractItemModel(d, value): #gdb.execute("call free($ri)") def qform__QModelIndex(): - return "Normal,Enhanced" + return [SimpleFormat, EnhancedFormat] def qdump__QModelIndex(d, value): - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == SimpleFormat: d.putPlainChildren(value) return r = value["r"] @@ -768,7 +769,7 @@ def qdump__QIPv6Address(d, value): d.putPlainChildren(c) def qform__QList(): - return "Assume Direct Storage,Assume Indirect Storage" + return [DirectQListStorageFormat, IndirectQListStorageFormat] def qdump__QList(d, value): base = d.extractPointer(value) @@ -794,10 +795,10 @@ def qdump__QList(d, value): # but this data is available neither in the compiled binary nor # in the frontend. # So as first approximation only do the 'isLarge' check: - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == DirectQListStorageFormat: isInternal = True - elif format == 2: + elif displayFormat == IndirectQListStorageFormat: isInternal = False else: isInternal = innerSize <= stepSize and d.isMovableType(innerType) @@ -818,7 +819,7 @@ def qdump__QList(d, value): d.putSubItem(i, x) def qform__QImage(): - return "Normal,Displayed" + return [SimpleFormat, SeparateFormat] def qdump__QImage(d, value): # This relies on current QImage layout: @@ -861,10 +862,10 @@ def qdump__QImage(d, value): d.putNumChild(0) d.putType("void *") - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == SimpleFormat: d.putDisplay(StopDisplay) - elif format == 2: + elif displayFormat == SeparateFormat: # This is critical for performance. Writing to an external # file using the following is faster when using GDB. # file = tempfile.mkstemp(prefix="gdbpy_") @@ -1751,16 +1752,16 @@ def qedit__QString(d, value, data): d.setValues(base, "short", [ord(c) for c in data]) def qform__QString(): - return "Inline,Separate Window" + return [SimpleFormat, SeparateFormat] def qdump__QString(d, value): d.putStringValue(value) data, size, alloc = d.stringData(value) d.putNumChild(size) - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == SimpleFormat: d.putDisplay(StopDisplay) - elif format == 2: + elif displayFormat == SeparateFormat: d.putField("editformat", DisplayUtf16String) d.putField("editvalue", d.encodeString(value, limit=100000)) if d.isExpanded(): @@ -1847,7 +1848,7 @@ def qdump__QTextDocument(d, value): def qform__QUrl(): - return "Inline,Separate Window" + return [SimpleFormat, SeparateFormat] def qdump__QUrl(d, value): if d.qtVersion() < 0x050000: @@ -1911,10 +1912,10 @@ def qdump__QUrl(d, value): url += path d.putValue(url, Hex4EncodedLittleEndian) - format = d.currentItemFormat() - if format == 1: + displayFormat = d.currentItemFormat() + if displayFormat == SimpleFormat: d.putDisplay(StopDisplay) - elif format == 2: + elif displayFormat == SeparateFormat: d.putField("editformat", DisplayUtf16String) d.putField("editvalue", url) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 88e60f5228..54a6cc34d7 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -398,7 +398,8 @@ def qdump__std____debug__stack(d, value): qdump__std__stack(d, value) def qform__std__string(): - return "Latin1 String,Latin1 String in Separate Window,UTF-8 String,UTF-8 String in Separate Window" + return [Latin1StringFormat, SeparateLatin1StringFormat, + Utf8StringFormat, SeparateUtf8StringFormat ] def qdump__std__string(d, value): qdump__std__stringHelper1(d, value, 1, d.currentItemFormat()) @@ -787,7 +788,7 @@ def qdump__string(d, value): qdump__std__string(d, value) def qform__std__wstring(): - return "Inline String,String in Separate Window" + return [SimpleFormat, SeparateFormat] def qdump__std__wstring(d, value): charSize = d.lookupType('wchar_t').sizeof diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 5522b7794b..c9c4920084 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -576,17 +576,21 @@ void CdbEngine::setupEngine() STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupFailed") notifyEngineSetupFailed(); } - const QString normalFormat = tr("Normal"); - const QStringList stringFormats = QStringList() - << normalFormat << tr("Separate Window"); + + DisplayFormats stringFormats; + stringFormats.append(SimpleFormat); + stringFormats.append(SeparateFormat); + WatchHandler *wh = watchHandler(); wh->addTypeFormats("QString", stringFormats); wh->addTypeFormats("QString *", stringFormats); wh->addTypeFormats("QByteArray", stringFormats); wh->addTypeFormats("QByteArray *", stringFormats); wh->addTypeFormats("std__basic_string", stringFormats); // Python dumper naming convention for std::[w]string - const QStringList imageFormats = QStringList() - << normalFormat << tr("Image"); + + DisplayFormats imageFormats; + imageFormats.append(SimpleFormat); + imageFormats.append(EnhancedFormat); wh->addTypeFormats("QImage", imageFormats); wh->addTypeFormats("QImage *", imageFormats); } diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 7b724bad3d..066323c193 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -807,7 +807,7 @@ public: } void addTypeFormats(const QString &type, - const QStringList &typeFormats, int current) + const DisplayFormats &typeFormats, int current) { const int row = m_layout->rowCount(); int column = 0; @@ -815,7 +815,8 @@ public: m_layout->addWidget(new QLabel(type), row, column++); for (int i = -1; i != typeFormats.size(); ++i) { QRadioButton *choice = new QRadioButton(this); - choice->setText(i == -1 ? TypeFormatsDialog::tr("Reset") : typeFormats.at(i)); + choice->setText(i == -1 ? TypeFormatsDialog::tr("Reset") + : WatchHandler::nameForFormat(typeFormats.at(i))); m_layout->addWidget(choice, row, column++); if (i == current) choice->setChecked(true); @@ -868,7 +869,6 @@ private: // /////////////////////////////////////////////////////////////////////// - TypeFormatsDialog::TypeFormatsDialog(QWidget *parent) : QDialog(parent), m_ui(new TypeFormatsDialogUi(this)) { @@ -888,7 +888,7 @@ TypeFormatsDialog::~TypeFormatsDialog() } void TypeFormatsDialog::addTypeFormats(const QString &type0, - const QStringList &typeFormats, int current) + const DisplayFormats &typeFormats, int current) { QString type = type0; type.replace(QLatin1String("__"), QLatin1String("::")); @@ -900,10 +900,5 @@ void TypeFormatsDialog::addTypeFormats(const QString &type0, m_ui->pages[pos]->addTypeFormats(type, typeFormats, current); } -DumperTypeFormats TypeFormatsDialog::typeFormats() const -{ - return DumperTypeFormats(); -} - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index eee9ee11c4..9b0ddc4673 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -31,6 +31,8 @@ #ifndef DEBUGGER_DIALOGS_H #define DEBUGGER_DIALOGS_H +#include "watchhandler.h" + #include <projectexplorer/kitchooser.h> #include <projectexplorer/abi.h> @@ -162,8 +164,6 @@ private: QDialogButtonBox *m_box; }; -typedef QHash<QString, QStringList> DumperTypeFormats; - class StartRemoteEngineDialog : public QDialog { Q_OBJECT @@ -191,9 +191,8 @@ public: explicit TypeFormatsDialog(QWidget *parent); ~TypeFormatsDialog(); - void addTypeFormats(const QString &type, const QStringList &formats, + void addTypeFormats(const QString &type, const DisplayFormats &formats, int currentFormat); - DumperTypeFormats typeFormats() const; private: TypeFormatsDialogUi *m_ui; diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index a3177c30e9..cfcc0466c0 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -40,6 +40,7 @@ #include "simplifytype.h" #include "imageviewer.h" #include "watchutils.h" +#include "cdb/cdbengine.h" // Remove after string freeze #include <coreplugin/icore.h> @@ -239,7 +240,7 @@ public: QSet<QByteArray> m_expandedINames; QTimer m_requestUpdateTimer; - DumperTypeFormats m_reportedTypeFormats; + QHash<QString, DisplayFormats> m_reportedTypeFormats; // Type name -> Dumper Formats QHash<QByteArray, QString> m_valueCache; }; @@ -943,22 +944,31 @@ static inline QString msgArrayFormat(int n) QString WatchModel::nameForFormat(int format) { switch (format) { + case AutomaticFormat: return QLatin1String(""); + case RawFormat: return tr("Raw Data"); + case SimpleFormat: return CdbEngine::tr("Normal"); // FIXME: String + case EnhancedFormat: return QLatin1String("Enhanced"); // FIXME: String + case SeparateFormat: return CdbEngine::tr("Separate Window"); // FIXME: String + case Latin1StringFormat: return tr("Latin1 String"); + case SeparateLatin1StringFormat: return tr("Latin1 String in Separate Window"); case Utf8StringFormat: return tr("UTF-8 String"); + case SeparateUtf8StringFormat: return tr("UTF-8 String in Separate Window"); case Local8BitStringFormat: return tr("Local 8-Bit String"); case Utf16StringFormat: return tr("UTF-16 String"); case Ucs4StringFormat: return tr("UCS-4 String"); + case Array10Format: return msgArrayFormat(10); case Array100Format: return msgArrayFormat(100); case Array1000Format: return msgArrayFormat(1000); case Array10000Format: return msgArrayFormat(10000); - case SeparateLatin1StringFormat: return tr("Latin1 String in Separate Window"); - case SeparateUtf8StringFormat: return tr("UTF-8 String in Separate Window"); + case DecimalIntegerFormat: return tr("Decimal Integer"); case HexadecimalIntegerFormat: return tr("Hexadecimal Integer"); case BinaryIntegerFormat: return tr("Binary Integer"); case OctalIntegerFormat: return tr("Octal Integer"); + case CompactFloatFormat: return tr("Compact Float"); case ScientificFloatFormat: return tr("Scientific Float"); } @@ -967,9 +977,9 @@ QString WatchModel::nameForFormat(int format) return QString(); } -TypeFormatList WatchItem::typeFormatList() const +DisplayFormats WatchItem::typeFormatList() const { - TypeFormatList formats; + DisplayFormats formats; // Types supported by dumpers: // Hack: Compensate for namespaces. @@ -981,9 +991,7 @@ TypeFormatList WatchItem::typeFormatList() const if (pos >= 0) t.truncate(pos); t.replace(QLatin1Char(':'), QLatin1Char('_')); - QStringList reported = watchModel()->m_reportedTypeFormats.value(t); - for (int i = 0, n = reported.size(); i != n; ++i) - formats.append(TypeFormatItem(reported.at(i), i)); + formats << watchModel()->m_reportedTypeFormats.value(t); // Fixed artificial string and pointer types. if (origaddr || isPointerType(type)) { @@ -1531,6 +1539,11 @@ int WatchHandler::format(const QByteArray &iname) const return result; } +QString WatchHandler::nameForFormat(int format) +{ + return WatchModel::nameForFormat(format); +} + QByteArray WatchHandler::typeFormatRequests() const { QByteArray ba; @@ -1539,7 +1552,7 @@ QByteArray WatchHandler::typeFormatRequests() const while (it.hasNext()) { it.next(); const int format = it.value(); - if (format >= RawFormat && format < ArtificialFormatBase) { + if (format != AutomaticFormat) { ba.append(it.key().toHex()); ba.append('='); ba.append(QByteArray::number(format)); @@ -1559,7 +1572,7 @@ QByteArray WatchHandler::individualFormatRequests() const while (it.hasNext()) { it.next(); const int format = it.value(); - if (format >= RawFormat && format < ArtificialFormatBase) { + if (format != AutomaticFormat) { ba.append(it.key()); ba.append('='); ba.append(QByteArray::number(it.value())); @@ -1588,7 +1601,7 @@ void WatchHandler::appendFormatRequests(DebuggerCommand *cmd) while (it.hasNext()) { it.next(); const int format = it.value(); - if (format >= RawFormat && format < ArtificialFormatBase) + if (format != AutomaticFormat) cmd->arg(it.key(), format); } cmd->endGroup(); @@ -1598,7 +1611,7 @@ void WatchHandler::appendFormatRequests(DebuggerCommand *cmd) while (it2.hasNext()) { it2.next(); const int format = it2.value(); - if (format >= RawFormat && format < ArtificialFormatBase) + if (format != AutomaticFormat) cmd->arg(it2.key(), format); } cmd->endGroup(); @@ -1607,20 +1620,18 @@ void WatchHandler::appendFormatRequests(DebuggerCommand *cmd) void WatchHandler::addDumpers(const GdbMi &dumpers) { foreach (const GdbMi &dumper, dumpers.children()) { - QStringList formats(tr("Raw structure")); - foreach (const QByteArray &format, dumper["formats"].data().split(',')) { - if (format == "Normal") - formats.append(tr("Normal")); - else if (format == "Displayed") - formats.append(tr("Displayed")); - else if (!format.isEmpty()) - formats.append(QString::fromLatin1(format)); + DisplayFormats formats; + formats.append(RawFormat); + QByteArray reportedFormats = dumper["formats"].data(); + foreach (const QByteArray &format, reportedFormats.split(',')) { + if (int f = format.toInt()) + formats.append(DisplayFormat(f)); } addTypeFormats(dumper["type"].data(), formats); } } -void WatchHandler::addTypeFormats(const QByteArray &type, const QStringList &formats) +void WatchHandler::addTypeFormats(const QByteArray &type, const DisplayFormats &formats) { m_model->m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats); } @@ -1643,16 +1654,6 @@ QString WatchHandler::editorContents() return contents; } -void WatchHandler::setTypeFormats(const DumperTypeFormats &typeFormats) -{ - m_model->m_reportedTypeFormats = typeFormats; -} - -DumperTypeFormats WatchHandler::typeFormats() const -{ - return m_model->m_reportedTypeFormats; -} - void WatchHandler::scheduleResetLocation() { m_model->m_contentsValid = false; @@ -1698,30 +1699,6 @@ QSet<QByteArray> WatchHandler::expandedINames() const return m_model->m_expandedINames; } - -//////////////////////////////////////////////////////////////////// -// -// TypeFormatItem/List -// -//////////////////////////////////////////////////////////////////// - -TypeFormatItem::TypeFormatItem(const QString &display, int format) - : display(display), format(format) -{} - -void TypeFormatList::append(int format) -{ - append(TypeFormatItem(WatchModel::nameForFormat(format), format)); -} - -TypeFormatItem TypeFormatList::find(int format) const -{ - for (int i = 0; i != size(); ++i) - if (at(i).format == format) - return at(i); - return TypeFormatItem(); -} - //////////////////////////////////////////////////////////////////// // // WatchItem diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 971cacda05..c505853d6d 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -44,24 +44,49 @@ class DebuggerCommand; class DebuggerEngine; class WatchModel; -class TypeFormatItem +// Special formats. Keep in sync with dumper.py. +enum DisplayFormat { -public: - TypeFormatItem() : format(-1) {} - TypeFormatItem(const QString &display, int format); + AutomaticFormat, // Based on type for individuals, dumper default for types. + RawFormat, - QString display; - int format; -}; + SimpleFormat, // Typical simple format (e.g. for QModelIndex row/column) + EnhancedFormat, // Enhanced format (e.g. for QModelIndex with resolved display) + SeparateFormat, // Display in separate Window -class TypeFormatList : public QVector<TypeFormatItem> -{ -public: - using QVector::append; - void append(int format); - TypeFormatItem find(int format) const; + Latin1StringFormat, + SeparateLatin1StringFormat, + Utf8StringFormat, + SeparateUtf8StringFormat, + Local8BitStringFormat, + Utf16StringFormat, + Ucs4StringFormat, + + Array10Format, + Array100Format, + Array1000Format, + Array10000Format, + ArrayPlotFormat, + + CompactMapFormat, + DirectQListStorageFormat, + IndirectQListStorageFormat, + + // Not used in *.py. + BoolTextFormat, + BoolIntegerFormat, + + DecimalIntegerFormat, + HexadecimalIntegerFormat, + BinaryIntegerFormat, + OctalIntegerFormat, + + CompactFloatFormat, + ScientificFloatFormat, }; +typedef QVector<DisplayFormat> DisplayFormats; + class WatchItem : public Utils::TreeItem, public WatchData { public: @@ -91,7 +116,7 @@ private: WatchItem *parentItem() const; const WatchModel *watchModel() const; WatchModel *watchModel(); - TypeFormatList typeFormatList() const; + DisplayFormats typeFormatList() const; bool canFetchMore() const; QVariant data(int column, int role) const; @@ -101,46 +126,6 @@ private: bool fetchTriggered; }; -// Special formats. Keep in sync with dumper.py. -enum DisplayFormat -{ - AutomaticFormat = -1, // Based on type for individuals, dumper default for types. - RawFormat = 0, - - // Values between 1 and 99 refer to dumper provided custom formats. - - // Values between 100 and 199 refer to well-known formats handled in dumpers. - KnownDumperFormatBase = 100, - Latin1StringFormat, - Utf8StringFormat, - Local8BitStringFormat, - Utf16StringFormat, - Ucs4StringFormat, - - Array10Format, - Array100Format, - Array1000Format, - Array10000Format, - - SeparateLatin1StringFormat, - SeparateUtf8StringFormat, - - - // Values above 200 refer to format solely handled in the WatchHandler code - ArtificialFormatBase = 200, - - BoolTextFormat, - BoolIntegerFormat, - - DecimalIntegerFormat, - HexadecimalIntegerFormat, - BinaryIntegerFormat, - OctalIntegerFormat, - - CompactFloatFormat, - ScientificFloatFormat, -}; - class UpdateParameters { public: @@ -150,8 +135,6 @@ public: QByteArray varList; }; -typedef QHash<QString, QStringList> DumperTypeFormats; // Type name -> Dumper Formats - class WatchModelBase : public Utils::TreeModel { Q_OBJECT @@ -201,11 +184,10 @@ public: QByteArray individualFormatRequests() const; int format(const QByteArray &iname) const; + static QString nameForFormat(int format); void addDumpers(const GdbMi &dumpers); - void addTypeFormats(const QByteArray &type, const QStringList &formats); - void setTypeFormats(const DumperTypeFormats &typeFormats); - DumperTypeFormats typeFormats() const; + void addTypeFormats(const QByteArray &type, const DisplayFormats &formats); void setUnprintableBase(int base); static int unprintableBase(); @@ -237,6 +219,6 @@ private: } // namespace Debugger Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters) -Q_DECLARE_METATYPE(Debugger::Internal::TypeFormatList) +Q_DECLARE_METATYPE(Debugger::Internal::DisplayFormats) #endif // DEBUGGER_WATCHHANDLER_H diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index c82a3fa5b9..c8f145fb29 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -554,12 +554,10 @@ void WatchTreeView::fillFormatMenu(QMenu *formatMenu, const QModelIndex &mi) const QModelIndex mi2 = mi.sibling(mi.row(), 2); const QString type = mi2.data().toString(); - const TypeFormatList alternativeFormats = - mi.data(LocalsTypeFormatListRole).value<TypeFormatList>(); - int typeFormat = - mi.data(LocalsTypeFormatRole).toInt(); - const int individualFormat = - mi.data(LocalsIndividualFormatRole).toInt(); + const DisplayFormats alternativeFormats = + mi.data(LocalsTypeFormatListRole).value<DisplayFormats>(); + const int typeFormat = mi.data(LocalsTypeFormatRole).toInt(); + const int individualFormat = mi.data(LocalsIndividualFormatRole).toInt(); const int unprintableBase = WatchHandler::unprintableBase(); QAction *showUnprintableUnicode = 0; @@ -595,7 +593,7 @@ void WatchTreeView::fillFormatMenu(QMenu *formatMenu, const QModelIndex &mi) dummy->setEnabled(false); QString msg = (individualFormat == AutomaticFormat && typeFormat != AutomaticFormat) ? tr("Use Format for Type (Currently %1)") - .arg(alternativeFormats.find(typeFormat).display) + .arg(WatchHandler::nameForFormat(typeFormat)) : tr("Use Display Format Based on Type") + QLatin1Char(' '); QAction *clearIndividualFormatAction = formatMenu->addAction(spacer + msg); @@ -608,8 +606,8 @@ void WatchTreeView::fillFormatMenu(QMenu *formatMenu, const QModelIndex &mi) }); for (int i = 0; i != alternativeFormats.size(); ++i) { - const QString display = spacer + alternativeFormats.at(i).display; - const int format = alternativeFormats.at(i).format; + const int format = alternativeFormats.at(i); + const QString display = spacer + WatchHandler::nameForFormat(format); QAction *act = new QAction(display, formatMenu); act->setCheckable(true); act->setChecked(format == individualFormat); @@ -633,9 +631,9 @@ void WatchTreeView::fillFormatMenu(QMenu *formatMenu, const QModelIndex &mi) }); for (int i = 0; i != alternativeFormats.size(); ++i) { - const QString display = spacer + alternativeFormats.at(i).display; + const int format = alternativeFormats.at(i); + const QString display = spacer + WatchHandler::nameForFormat(format); QAction *act = new QAction(display, formatMenu); - const int format = alternativeFormats.at(i).format; act->setCheckable(true); act->setChecked(format == typeFormat); formatMenu->addAction(act); |