From 242cb179191c2fa5c88561b4d28b693868fbd4b8 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 30 Nov 2013 23:46:25 +0100 Subject: [PATCH] Debugger: Adjust QDateTime dumper for Qt 5.2 Change-Id: I53a5701c9d1791e2705eafb258ff440f97e53b87 Reviewed-by: John Layt Reviewed-by: hjk --- share/qtcreator/debugger/dumper.py | 2 +- share/qtcreator/debugger/qttypes.py | 24 +++-- src/plugins/debugger/debuggerprotocol.cpp | 88 +++++++++++++++++-- src/plugins/debugger/debuggerprotocol.h | 2 +- .../debugger/simple/simple_test_app.cpp | 3 + 5 files changed, 103 insertions(+), 16 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 74e1fb75515..4fc58280de1 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -816,7 +816,7 @@ Hex2EncodedFloat4, \ Hex2EncodedFloat8, \ IPv6AddressAndHexScopeId, \ Hex2EncodedUtf8WithoutQuotes, \ -MillisecondsSinceEpoch \ +DateTimeInternal \ = range(30) # Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 19f8cfc9e66..be6bfad8641 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -239,11 +239,25 @@ def qdump__QDateTime(d, value): base = d.dereferenceValue(value) if qtVersion >= 0x050200: dateBase = base + d.ptrSize() # Only QAtomicInt, but will be padded. - ms = d.extractInt64(dateBase) - offset = d.extractInt(dateBase + 12) - isValid = ms > 0 - if isValid: - d.putValue("%s" % (ms - offset * 1000), MillisecondsSinceEpoch) + # qint64 m_msecs + # Qt::TimeSpec m_spec + # int m_offsetFromUtc + # QTimeZone m_timeZone // only #ifndef QT_BOOTSTRAPPED + # StatusFlags m_status + status = d.extractInt(dateBase + 16 + d.ptrSize()) + if int(status & 0x10): # ValidDateTime + isValid = True + msecs = d.extractInt64(dateBase) + spec = d.extractInt(dateBase + 8) + offset = d.extractInt(dateBase + 12) + tzp = d.dereference(dateBase + 16) + if tzp == 0: + tz = "" + else: + idBase = tzp + 2 * d.ptrSize() # [QSharedData] + [vptr] + tz = d.encodeByteArrayHelper(d.dereference(idBase)) + d.putValue("%s/%s/%s/%s/%s" % (msecs, spec, offset, tz, status), + DateTimeInternal) else: # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp index a65f4f2997b..7f673ab8e27 100644 --- a/src/plugins/debugger/debuggerprotocol.cpp +++ b/src/plugins/debugger/debuggerprotocol.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -503,6 +504,53 @@ static QTime timeFromData(int ms) return ms == -1 ? QTime() : QTime(0, 0, 0, 0).addMSecs(ms); } +// Stolen and adapted from qdatetime.cpp +static void getDateTime(qint64 msecs, int status, QDate *date, QTime *time) +{ + enum { + SECS_PER_DAY = 86400, + MSECS_PER_DAY = 86400000, + SECS_PER_HOUR = 3600, + MSECS_PER_HOUR = 3600000, + SECS_PER_MIN = 60, + MSECS_PER_MIN = 60000, + TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC + JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1) + }; + + // Status of date/time + enum StatusFlag { + NullDate = 0x01, + NullTime = 0x02, + ValidDate = 0x04, + ValidTime = 0x08, + ValidDateTime = 0x10, + TimeZoneCached = 0x20, + SetToStandardTime = 0x40, + SetToDaylightTime = 0x80 + }; + + qint64 jd = JULIAN_DAY_FOR_EPOCH; + qint64 ds = 0; + + if (qAbs(msecs) >= MSECS_PER_DAY) { + jd += (msecs / MSECS_PER_DAY); + msecs %= MSECS_PER_DAY; + } + + if (msecs < 0) { + ds = MSECS_PER_DAY - msecs - 1; + jd -= ds / MSECS_PER_DAY; + ds = ds % MSECS_PER_DAY; + ds = MSECS_PER_DAY - ds - 1; + } else { + ds = msecs; + } + + *date = (status & NullDate) ? QDate() : QDate::fromJulianDay(jd); + *time = (status & NullTime) ? QTime() : QTime::fromMSecsSinceStartOfDay(ds); +} + QString decodeData(const QByteArray &ba, int encoding) { switch (encoding) { @@ -629,15 +677,37 @@ QString decodeData(const QByteArray &ba, int encoding) const QByteArray decodedBa = QByteArray::fromHex(ba); return QString::fromUtf8(decodedBa); } - case MillisecondsSinceEpoch: { - bool ok = false; - const qint64 ms = ba.toLongLong(&ok); - if (!ok) - return QLatin1String(ba); - QDateTime d; - d.setTimeSpec(Qt::UTC); - d.setMSecsSinceEpoch(ms); - return d.isValid() ? d.toString(Qt::TextDate) : QLatin1String("(invalid)"); + case DateTimeInternal: { // 29, DateTimeInternal: msecs, spec, offset, tz, status + int p0 = ba.indexOf('/'); + int p1 = ba.indexOf('/', p0 + 1); + int p2 = ba.indexOf('/', p1 + 1); + int p3 = ba.indexOf('/', p2 + 1); + + qint64 msecs = ba.left(p0).toLongLong(); + ++p0; + Qt::TimeSpec spec = Qt::TimeSpec(ba.mid(p0, p1 - p0).toInt()); + ++p1; + qulonglong offset = ba.mid(p1, p2 - p1).toInt(); + ++p2; + QByteArray timeZoneId = QByteArray::fromHex(ba.mid(p2, p3 - p2)); + ++p3; + int status = ba.mid(p3).toInt(); + + QDate date; + QTime time; + getDateTime(msecs, status, &date, &time); + + QDateTime dateTime; + if (spec == Qt::OffsetFromUTC) { + dateTime = QDateTime(date, time, spec, offset); + } else if (spec == Qt::TimeZone) { + if (!QTimeZone::isTimeZoneIdAvailable(timeZoneId)) + return QLatin1String(""); + dateTime = QDateTime(date, time, QTimeZone(timeZoneId)); + } else { + dateTime = QDateTime(date, time, spec); + } + return dateTime.toString(); } } qDebug() << "ENCODING ERROR: " << encoding; diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h index a71bb6f1331..bf90dd226e6 100644 --- a/src/plugins/debugger/debuggerprotocol.h +++ b/src/plugins/debugger/debuggerprotocol.h @@ -205,7 +205,7 @@ enum DebuggerEncoding Hex2EncodedFloat8 = 26, IPv6AddressAndHexScopeId = 27, Hex2EncodedUtf8WithoutQuotes = 28, - MillisecondsSinceEpoch = 29 + DateTimeInternal = 29 }; // Keep in sync with dumper.py, symbolgroupvalue.cpp of CDB diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index f7ce97ed5fc..ddadcea05c0 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -5475,8 +5475,11 @@ namespace basic { void testLongEvaluation1() { + QTimeZone tz("UTC+05:00"); QDateTime time = QDateTime::currentDateTime(); const int N = 10000; + QDateTime x = time; + x.setTimeZone(tz); QDateTime bigv[N]; for (int i = 0; i < 10000; ++i) { bigv[i] = time;