diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index a1b9c8ddbbe..9de1ed38e13 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -514,8 +514,9 @@ Hex2EncodedUInt8, \ Hex2EncodedFloat4, \ Hex2EncodedFloat8, \ IPv6AddressAndHexScopeId, \ -Hex2EncodedUtf8WithoutQuotes \ - = range(29) +Hex2EncodedUtf8WithoutQuotes, \ +MillisecondsSinceEpoch \ + = range(30) # Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h StopDisplay, \ diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index be26cfff95c..8a0bc863659 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1242,6 +1242,9 @@ class Dumper(DumperBase): #return long(gdb.Value(addr).cast(self.voidPtrType().pointer()).dereference()) return struct.unpack("P", self.readRawMemory(addr, self.ptrSize()))[0] + def extractInt64(self, addr): + return struct.unpack("q", self.readRawMemory(addr, 8))[0] + def extractInt(self, addr): #return long(gdb.Value(addr).cast(self.intPtrType()).dereference()) return struct.unpack("i", self.readRawMemory(addr, 4))[0] diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 2a0067deb67..d743f5e6888 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -221,24 +221,37 @@ def qdump__QTime(d, value): d.putNumChild(0) -# This relies on the Qt4/Qt5 internal structure layout: -# {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): + qtVersion = d.qtVersion() + isValid = False + # This relies on the Qt4/Qt5 internal structure layout: + # {sharedref(4), ... base = d.dereferenceValue(value) - # QDateTimePrivate: - # - QAtomicInt ref; (padded on 64 bit) - # - [QDate date;] - # - - uint jd in Qt 4, qint64 in Qt 5; padded on 64 bit - # - [QTime time;] - # - - uint mds; - # - Spec spec; - dateSize = 4 if d.qtVersion() < 0x050000 and d.is32bit() else 8 dateBase = base + d.ptrSize() # Only QAtomicInt, but will be padded. - timeBase = dateBase + dateSize - mds = d.extractInt(timeBase) - if mds >= 0: - jd = d.extractInt(dateBase) - d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) + if qtVersion >= 0x050200: + ms = d.extractInt64(dateBase) + offset = d.extractInt(dateBase + 12) + isValid = ms > 0 + if isValid: + d.putValue("%s" % (ms - offset * 1000), MillisecondsSinceEpoch) + else: + # This relies on the Qt4/Qt5 internal structure layout: + # {sharedref(4), date(8), time(4+x)} + # QDateTimePrivate: + # - QAtomicInt ref; (padded on 64 bit) + # - [QDate date;] + # - - uint jd in Qt 4, qint64 in Qt 5.0 and Qt 5.2; padded on 64 bit + # - [QTime time;] + # - - uint mds; + # - Spec spec; + dateSize = 4 if qtVersion < 0x050000 and d.is32bit() else 8 + timeBase = dateBase + dateSize + mds = d.extractInt(timeBase) + isValid = mds > 0 + if isValid: + jd = d.extractInt(dateBase) + d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) + if isValid: d.putNumChild(1) if d.isExpanded(): # FIXME: This improperly uses complex return values. diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp index 13335773326..1e50d13c3ac 100644 --- a/src/plugins/debugger/debuggerprotocol.cpp +++ b/src/plugins/debugger/debuggerprotocol.cpp @@ -628,6 +628,13 @@ QString decodeData(const QByteArray &ba, int encoding) const QByteArray decodedBa = QByteArray::fromHex(ba); return QString::fromUtf8(decodedBa); } + case MillisecondsSinceEpoch: { + const qint64 ms = ba.toLongLong(); + QDateTime d; + d.setTimeSpec(Qt::UTC); + d.setMSecsSinceEpoch(ms); + return d.toString(Qt::TextDate); + } } qDebug() << "ENCODING ERROR: " << encoding; return QCoreApplication::translate("Debugger", ""); diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h index 6bce7e1aec6..a71bb6f1331 100644 --- a/src/plugins/debugger/debuggerprotocol.h +++ b/src/plugins/debugger/debuggerprotocol.h @@ -204,7 +204,8 @@ enum DebuggerEncoding Hex2EncodedFloat4 = 25, Hex2EncodedFloat8 = 26, IPv6AddressAndHexScopeId = 27, - Hex2EncodedUtf8WithoutQuotes = 28 + Hex2EncodedUtf8WithoutQuotes = 28, + MillisecondsSinceEpoch = 29 }; // Keep in sync with dumper.py, symbolgroupvalue.cpp of CDB diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 9a79f4404a2..d582078aa22 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1226,12 +1226,15 @@ void tst_Dumpers::dumper_data() "QDateTime date(QDate(1980, 1, 1), QTime(13, 15, 32), Qt::UTC);\n" "unused(&date);\n") % CoreProfile() - % Check("date", "Tue Jan 1 13:15:32 1980", "@QDateTime") + % Check("date", Value4("Tue Jan 1 13:15:32 1980"), "@QDateTime") + % Check("date", Value5("Tue Jan 1 13:15:32 1980 GMT"), "@QDateTime") % Check("date.(ISO)", "\"1980-01-01T13:15:32Z\"", "@QString") % CheckType("date.(Locale)", "@QString") % CheckType("date.(SystemLocale)", "@QString") - % Check("date.toString", "\"Tue Jan 1 13:15:32 1980\"", "@QString") - % Check("date.toUTC", "Tue Jan 1 13:15:32 1980", "@QDateTime"); + % Check("date.toString", Value4("\"Tue Jan 1 13:15:32 1980\""), "@QString") + % Check("date.toString", Value5("\"Tue Jan 1 13:15:32 1980 GMT\""), "@QString") + % Check("date.toUTC", Value4("Tue Jan 1 13:15:32 1980"), "@QDateTime") + % Check("date.toUTC", Value5("Tue Jan 1 13:15:32 1980 GMT"), "@QDateTime"); #ifdef Q_OS_WIN QByteArray tempDir = "\"C:/Program Files\"";