diff options
-rw-r--r-- | src/corelib/io/qurl.cpp | 53 | ||||
-rw-r--r-- | src/corelib/tools/qdatetimeparser.cpp | 32 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 2 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp | 145 | ||||
-rw-r--r-- | src/widgets/widgets/qmainwindowlayout.cpp | 23 | ||||
-rw-r--r-- | tests/auto/corelib/io/qurl/tst_qurl.cpp | 25 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 185 | ||||
-rw-r--r-- | tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp | 2 |
9 files changed, 319 insertions, 154 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 775a870a27..b51119c7ad 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -556,6 +556,7 @@ public: inline bool hasFragment() const { return sectionIsPresent & Fragment; } inline bool isLocalFile() const { return flags & IsLocalFile; } + QString toLocalFile(QUrl::FormattingOptions options) const; QString mergePaths(const QString &relativePath) const; @@ -1460,6 +1461,33 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode validateComponent(Fragment, url, hash + 1, len); } +QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const +{ + QString tmp; + QString ourPath; + appendPath(ourPath, options, QUrlPrivate::Path); + + // magic for shared drive on windows + if (!host.isEmpty()) { + tmp = QStringLiteral("//") + host; +#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. + if (scheme == webDavScheme()) + tmp += webDavSslTag(); +#endif + if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/'))) + tmp += QLatin1Char('/'); + tmp += ourPath; + } else { + tmp = ourPath; +#ifdef Q_OS_WIN + // magic for drives on windows + if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) + tmp.remove(0, 1); +#endif + } + return tmp; +} + /* From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths @@ -3257,7 +3285,7 @@ QString QUrl::toString(FormattingOptions options) const && (!d->hasQuery() || options.testFlag(QUrl::RemoveQuery)) && (!d->hasFragment() || options.testFlag(QUrl::RemoveFragment)) && isLocalFile()) { - return path(options); + return d->toLocalFile(options); } QString url; @@ -3820,28 +3848,7 @@ QString QUrl::toLocalFile() const if (!isLocalFile()) return QString(); - QString tmp; - QString ourPath = path(QUrl::FullyDecoded); - - // magic for shared drive on windows - if (!d->host.isEmpty()) { - tmp = QStringLiteral("//") + host(); -#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. - if (scheme() == webDavScheme()) - tmp += webDavSslTag(); -#endif - if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/'))) - tmp += QLatin1Char('/'); - tmp += ourPath; - } else { - tmp = ourPath; -#ifdef Q_OS_WIN - // magic for drives on windows - if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) - tmp.remove(0, 1); -#endif - } - return tmp; + return d->toLocalFile(QUrl::FullyDecoded); } /*! diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index eaa695ef27..9ca2e1ffc0 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -382,7 +382,7 @@ bool QDateTimeParser::parseFormat(const QString &newFormat) ++add; if (status != quote) { status = quote; - } else if (newFormat.at(i - 1) != slash) { + } else if (i > 0 && newFormat.at(i - 1) != slash) { status = zero; } } else if (status != quote) { @@ -494,15 +494,15 @@ bool QDateTimeParser::parseFormat(const QString &newFormat) } if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) { - const int max = newSectionNodes.size(); - for (int i=0; i<max; ++i) { + const int count = newSectionNodes.size(); + for (int i = 0; i < count; ++i) { SectionNode &node = newSectionNodes[i]; if (node.type == Hour12Section) node.type = Hour24Section; } } - if (index < newFormat.size()) { + if (index < max) { appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote); } else { newSeparators.append(QString()); @@ -765,8 +765,8 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } else { state = Intermediate; } - break; } - // fall through + break; + } // else: fall through case DaySection: case YearSection: case YearSection2Digits: @@ -889,17 +889,17 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos QDTPDEBUG << "parse" << input; { - int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits; + int year, month, day; currentValue.date().getDate(&year, &month, &day); - year2digits = year % 100; - hour = currentValue.time().hour(); - hour12 = -1; - minute = currentValue.time().minute(); - second = currentValue.time().second(); - msec = currentValue.time().msec(); - dayofweek = currentValue.date().dayOfWeek(); - - ampm = -1; + int year2digits = year % 100; + int hour = currentValue.time().hour(); + int hour12 = -1; + int minute = currentValue.time().minute(); + int second = currentValue.time().second(); + int msec = currentValue.time().msec(); + int dayofweek = currentValue.date().dayOfWeek(); + + int ampm = -1; Sections isSet = NoSection; int num; State tmpstate; diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 279ec36a28..af42d06991 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -108,11 +108,11 @@ public: ~QWeakPointer(); - QWeakPointer<T> operator=(const QWeakPointer<T> &other); - QWeakPointer<T> operator=(const QSharedPointer<T> &other); + QWeakPointer<T> &operator=(const QWeakPointer<T> &other); + QWeakPointer<T> &operator=(const QSharedPointer<T> &other); QWeakPointer(const QObject *other); - QWeakPointer<T> operator=(const QObject *other); + QWeakPointer<T> &operator=(const QObject *other); void swap(QWeakPointer<T> &other); diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index a3ffb5be66..8152c57ffd 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -198,7 +198,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) // current OS X versions is 22 points. Provide some future-proofing // by deriving the icon height from the menu height. const int padding = 4; - const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; const int maxImageHeight = menuHeight - padding; // Select pixmap based on the device pixel height. Ideally we would use diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index a50ee60975..bb4f4b1abd 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -520,13 +520,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, int margin, const QTransform &xform) { - glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform); - // This needs to be kept in sync with alphaMapBoundingBox - int width = (metrics.width + margin * 2).ceil().toInt() ; - int height = (metrics.height + margin * 2).ceil().toInt(); - UINT16 glyphIndex = t; - FLOAT glyphAdvance = metrics.xoff.toReal(); + FLOAT glyphAdvance = 0; DWRITE_GLYPH_OFFSET glyphOffset; glyphOffset.advanceOffset = 0; @@ -542,12 +537,9 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.bidiLevel = 0; glyphRun.glyphOffsets = &glyphOffset; - QFixed x = margin - metrics.x.floor() + subPixelPosition; - QFixed y = margin - metrics.y.floor(); - DWRITE_MATRIX transform; - transform.dx = x.toReal(); - transform.dy = y.toReal(); + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; transform.m11 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); @@ -571,46 +563,56 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, if (SUCCEEDED(hr)) { RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - int size = width * height * 3; - BYTE *alphaValues = new BYTE[size]; - memset(alphaValues, 0, size); + rect.left -= margin; + rect.top -= margin; + rect.right += margin; + rect.bottom += margin; - hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); + const int width = rect.right - rect.left; + const int height = rect.bottom - rect.top; - if (SUCCEEDED(hr)) { - QImage img(width, height, QImage::Format_RGB32); - img.fill(0xffffffff); + const int size = width * height * 3; + if (size > 0) { + BYTE *alphaValues = new BYTE[size]; + memset(alphaValues, 0, size); - for (int y=0; y<height; ++y) { - uint *dest = reinterpret_cast<uint *>(img.scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; + hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, + &rect, + alphaValues, + size); - for (int x=0; x<width; ++x) { - dest[x] = *(src) << 16 - | *(src + 1) << 8 - | *(src + 2); + if (SUCCEEDED(hr)) { + QImage img(width, height, QImage::Format_RGB32); + img.fill(0xffffffff); - src += 3; + for (int y=0; y<height; ++y) { + uint *dest = reinterpret_cast<uint *>(img.scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; + + for (int x=0; x<width; ++x) { + dest[x] = *(src) << 16 + | *(src + 1) << 8 + | *(src + 2); + + src += 3; + } } - } - delete[] alphaValues; - glyphAnalysis->Release(); + delete[] alphaValues; + glyphAnalysis->Release(); + + return img; + } else { + delete[] alphaValues; + glyphAnalysis->Release(); - return img; + qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + } } else { - delete[] alphaValues; glyphAnalysis->Release(); - - qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + qWarning("%s: Glyph has no bounds", __FUNCTION__); } } else { @@ -724,16 +726,65 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN return QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString(); } -glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) +glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, + QFixed subPixelPosition, + const QTransform &matrix, + GlyphFormat format) { - Q_UNUSED(pos); Q_UNUSED(format); + glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance + + UINT16 glyphIndex = glyph; + FLOAT glyphAdvance = 0; + + DWRITE_GLYPH_OFFSET glyphOffset; + glyphOffset.advanceOffset = 0; + glyphOffset.ascenderOffset = 0; + + DWRITE_GLYPH_RUN glyphRun; + glyphRun.fontFace = m_directWriteFontFace; + glyphRun.fontEmSize = fontDef.pixelSize; + glyphRun.glyphCount = 1; + glyphRun.glyphIndices = &glyphIndex; + glyphRun.glyphAdvances = &glyphAdvance; + glyphRun.isSideways = false; + glyphRun.bidiLevel = 0; + glyphRun.glyphOffsets = &glyphOffset; + + DWRITE_MATRIX transform; + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; + transform.m11 = matrix.m11(); + transform.m12 = matrix.m12(); + transform.m21 = matrix.m21(); + transform.m22 = matrix.m22(); + + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; + HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( + &glyphRun, + 1.0f, + &transform, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, + 0.0, 0.0, + &glyphAnalysis + ); - int margin = glyphMargin(QFontEngine::Format_A32); - glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix); - gm.width += margin * 2; - gm.height += margin * 2; - return gm; + if (SUCCEEDED(hr)) { + RECT rect; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); + glyphAnalysis->Release(); + + int margin = glyphMargin(QFontEngine::Format_A32); + + return glyph_metrics_t(rect.left, + rect.top, + rect.right - rect.left + margin * 2, + rect.bottom - rect.top + margin * 2, + bbox.xoff, bbox.yoff); + } else { + return glyph_metrics_t(); + } } QT_END_NAMESPACE diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 54e956c4cf..1bb8496505 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -2252,17 +2252,18 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget) QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) { #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_TABBAR) - QDockWidgetGroupWindow *floatingParent = qobject_cast<QDockWidgetGroupWindow *>(widget->parentWidget()); - if (group && floatingParent && !widget->isWindow()) { - // We are just dragging a floating window as it, not need to do anything, we just have to - // look up the corresponding QWidgetItem* if it exists - QList<int> tabbedWindowPath = layoutState.indexOf(widget->parentWidget()); - return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath); - } else if (floatingParent) { - // We are unplugging a dock widget from a floating window. - if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { - dw->d_func()->unplug(widget->geometry()); - return 0; + if (!widget->isWindow() && qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget())) { + if (group) { + // We are just dragging a floating window as it, not need to do anything, we just have to + // look up the corresponding QWidgetItem* if it exists + QList<int> tabbedWindowPath = layoutState.indexOf(widget->parentWidget()); + return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath); + } else { + // We are unplugging a dock widget from a floating window. + if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { + dw->d_func()->unplug(widget->geometry()); + return 0; + } } } #endif diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 031a35b380..519b05f492 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -69,6 +69,8 @@ private slots: void resolving(); void toString_data(); void toString(); + void toString_PreferLocalFile_data(); + void toString_PreferLocalFile(); void toString_constructed_data(); void toString_constructed(); void toAndFromStringList_data(); @@ -1050,6 +1052,29 @@ void tst_QUrl::toString() QCOMPARE(url.adjusted(opt).toString(), string); } +void tst_QUrl::toString_PreferLocalFile_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QString>("string"); + +#ifdef Q_OS_WIN + QTest::newRow("win-drive") << QUrl(QString::fromLatin1("file:///c:/windows/regedit.exe")) + << QString::fromLatin1("c:/windows/regedit.exe"); + QTest::newRow("win-share") << QUrl(QString::fromLatin1("//Anarki/homes")) + << QString::fromLatin1("//anarki/homes"); +#else + QTest::newRow("unix-path") << QUrl(QString::fromLatin1("file:///tmp")) + << QString::fromLatin1("/tmp"); +#endif +} + +void tst_QUrl::toString_PreferLocalFile() +{ + QFETCH(QUrl, url); + QFETCH(QString, string); + + QCOMPARE(url.toString(QUrl::PreferLocalFile), string); +} void tst_QUrl::toAndFromStringList_data() { diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 228ce73c6b..6d88b24eda 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -155,7 +155,7 @@ private slots: private: enum { LocalTimeIsUtc = 0, LocalTimeAheadOfUtc = 1, LocalTimeBehindUtc = -1} localTimeType; - bool europeanTimeZone; + bool zoneIsCET; QDate defDate() const { return QDate(1900, 1, 1); } QTime defTime() const { return QTime(0, 0, 0); } QDateTime defDateTime() const { return QDateTime(defDate(), defTime()); } @@ -171,21 +171,70 @@ Q_DECLARE_METATYPE(Qt::DateFormat) tst_QDateTime::tst_QDateTime() { - uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t(); - uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t(); - europeanTimeZone = (x1 == 631148400 && x2 == 644191200); - - QDateTime dt1 = QDateTime::fromTime_t(0); - QDateTime dt2 = QDateTime::fromTime_t(181 * 86400); // six months later, Jul 1 - if (dt1.date().year() < 1970 || dt2.date().month() < 7) { - localTimeType = LocalTimeBehindUtc; - } else if (dt1.time().hour() > 0 || dt1.date().day() > 1) { - localTimeType = LocalTimeAheadOfUtc; - } else if (dt2.time().hour() > 0 || dt2.date().day() > 1) { - localTimeType = LocalTimeAheadOfUtc; - } else { - localTimeType = LocalTimeIsUtc; + /* + Due to some jurisdictions changing their zones and rules, it's possible + for a non-CET zone to accidentally match CET at a few tested moments but + be different a few years later or earlier. This would lead to tests + failing if run in the partially-aliasing zone (e.g. Algeria, Lybia). So + test thoroughly; ideally at every mid-winter or mid-summer in whose + half-year any test below assumes zoneIsCET means what it says. (Tests at + or near a DST transition implicate both of the half-years that meet + there.) Years outside the 1970--2038 range, however, are likely not + properly handled by the TZ-database; and QDateTime explicitly handles them + differently, so don't probe them here. + */ + const uint day = 24 * 3600; // in seconds + zoneIsCET = (QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7)).toTime_t() == 0x7fffffff + // Entries a year apart robustly differ by multiples of day. + && QDateTime(QDate(2015, 7, 1), QTime()).toTime_t() == 1435701600 + && QDateTime(QDate(2015, 1, 1), QTime()).toTime_t() == 1420066800 + && QDateTime(QDate(2013, 7, 1), QTime()).toTime_t() == 1372629600 + && QDateTime(QDate(2013, 1, 1), QTime()).toTime_t() == 1356994800 + && QDateTime(QDate(2012, 7, 1), QTime()).toTime_t() == 1341093600 + && QDateTime(QDate(2012, 1, 1), QTime()).toTime_t() == 1325372400 + && QDateTime(QDate(2008, 7, 1), QTime()).toTime_t() == 1214863200 + && QDateTime(QDate(2004, 1, 1), QTime()).toTime_t() == 1072911600 + && QDateTime(QDate(2000, 1, 1), QTime()).toTime_t() == 946681200 + && QDateTime(QDate(1990, 7, 1), QTime()).toTime_t() == 646783200 + && QDateTime(QDate(1990, 1, 1), QTime()).toTime_t() == 631148400 + && QDateTime(QDate(1979, 1, 1), QTime()).toTime_t() == 283993200 + // .toTime_t() returns -1 for everything before this: + && QDateTime(QDate(1970, 1, 1), QTime(1, 0, 0)).toTime_t() == 0); + // Use .toMSecsSinceEpoch() if you really need to test anything earlier. + + /* + Again, rule changes can cause a TZ to look like UTC at some sample dates + but deviate at some date relevant to a test using localTimeType. These + tests mostly use years outside the 1970--2038 range for which TZ data is + credible, so we can't helpfully be exhaustive. So scan a sample of years' + starts and middles. + */ + const int sampled = 3; + // UTC starts of months in 2004, 2038 and 1970: + uint jans[sampled] = { 12418 * day, 24837 * day, 0 }; + uint juls[sampled] = { 12600 * day, 25018 * day, 181 * day }; + localTimeType = LocalTimeIsUtc; + for (int i = sampled; i-- > 0; ) { + QDateTime jan = QDateTime::fromTime_t(jans[i]); + QDateTime jul = QDateTime::fromTime_t(juls[i]); + if (jan.date().year() < 1970 || jul.date().month() < 7) { + localTimeType = LocalTimeBehindUtc; + break; + } else if (jan.time().hour() > 0 || jul.time().hour() > 0 + || jan.date().day() > 1 || jul.date().day() > 1) { + localTimeType = LocalTimeAheadOfUtc; + break; + } } + /* + Even so, TZ=Africa/Algiers will fail fromMSecsSinceEpoch(-1) because it + switched from WET without DST (i.e. UTC) in the late 1960s to WET with DST + for all of 1970 - so they had a DST transition *on the epoch*. They've + since switched to CET with no DST, making life simple; but our tests for + mistakes around the epoch can't tell the difference between what Algeria + really did and the symptoms we can believe a bug might produce: there's + not much we can do about that, that wouldn't hide real bugs. + */ } void tst_QDateTime::initTestCase() @@ -201,7 +250,7 @@ void tst_QDateTime::initTestCase() break; case LocalTimeAheadOfUtc: typemsg1 = "ahead of"; - typemsg2 = europeanTimeZone ? "and is" : "but isn't"; + typemsg2 = zoneIsCET ? "and is" : "but isn't"; break; } @@ -245,7 +294,7 @@ void tst_QDateTime::ctor() QCOMPARE(dt3.timeSpec(), Qt::UTC); QVERIFY(dt1 == dt2); - if (europeanTimeZone) { + if (zoneIsCET) { QVERIFY(dt1 != dt3); QVERIFY(dt1 < dt3); QVERIFY(dt1.addSecs(3600).toUTC() == dt3); @@ -492,7 +541,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(123456); QCOMPARE(dt1, QDateTime(QDate(1970, 1, 2), QTime(10, 17, 36), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(123456); QCOMPARE(dt2, QDateTime(QDate(1970, 1, 2), QTime(11, 17, 36), Qt::LocalTime)); @@ -500,7 +549,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t((uint)(quint32)-123456); QCOMPARE(dt1, QDateTime(QDate(2106, 2, 5), QTime(20, 10, 40), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t((uint)(quint32)-123456); QCOMPARE(dt2, QDateTime(QDate(2106, 2, 5), QTime(21, 10, 40), Qt::LocalTime)); @@ -508,7 +557,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(1214567890); QCOMPARE(dt1, QDateTime(QDate(2008, 6, 27), QTime(11, 58, 10), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(1214567890); QCOMPARE(dt2, QDateTime(QDate(2008, 6, 27), QTime(13, 58, 10), Qt::LocalTime)); @@ -516,7 +565,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(0x7FFFFFFF); QCOMPARE(dt1, QDateTime(QDate(2038, 1, 19), QTime(3, 14, 7), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(0x7FFFFFFF); QCOMPARE(dt2, QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7), Qt::LocalTime)); @@ -533,7 +582,7 @@ void tst_QDateTime::setMSecsSinceEpoch_data() { QTest::addColumn<qint64>("msecs"); QTest::addColumn<QDateTime>("utc"); - QTest::addColumn<QDateTime>("european"); + QTest::addColumn<QDateTime>("cet"); QTest::newRow("zero") << Q_INT64_C(0) @@ -584,7 +633,7 @@ void tst_QDateTime::setMSecsSinceEpoch() { QFETCH(qint64, msecs); QFETCH(QDateTime, utc); - QFETCH(QDateTime, european); + QFETCH(QDateTime, cet); QDateTime dt; dt.setTimeSpec(Qt::UTC); @@ -595,8 +644,8 @@ void tst_QDateTime::setMSecsSinceEpoch() QCOMPARE(dt.time(), utc.time()); QCOMPARE(dt.timeSpec(), Qt::UTC); - if (europeanTimeZone) { - QCOMPARE(dt.toLocalTime(), european); + if (zoneIsCET) { + QCOMPARE(dt.toLocalTime(), cet); // Test converting from LocalTime to UTC back to LocalTime. QDateTime localDt; @@ -613,13 +662,13 @@ void tst_QDateTime::setMSecsSinceEpoch() QDateTime dt2; dt2.setTimeZone(europe); dt2.setMSecsSinceEpoch(msecs); - QCOMPARE(dt2.date(), european.date()); + QCOMPARE(dt2.date(), cet.date()); // don't compare the time if the date is too early or too late: prior // to 1916, timezones in Europe were not standardised and some OS APIs // have hard limits. Let's restrict it to the 32-bit Unix range if (dt2.date().year() >= 1970 && dt2.date().year() <= 2037) - QCOMPARE(dt2.time(), european.time()); + QCOMPARE(dt2.time(), cet.time()); QCOMPARE(dt2.timeSpec(), Qt::TimeZone); QCOMPARE(dt2.timeZone(), europe); } @@ -643,7 +692,7 @@ void tst_QDateTime::fromMSecsSinceEpoch() { QFETCH(qint64, msecs); QFETCH(QDateTime, utc); - QFETCH(QDateTime, european); + QFETCH(QDateTime, cet); QDateTime dtLocal = QDateTime::fromMSecsSinceEpoch(msecs, Qt::LocalTime); QDateTime dtUtc = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC); @@ -665,10 +714,10 @@ void tst_QDateTime::fromMSecsSinceEpoch() if (msecs != std::numeric_limits<qint64>::max()) QCOMPARE(dtOffset.time(), utc.time().addMSecs(60*60*1000)); - if (europeanTimeZone) { - QCOMPARE(dtLocal.toLocalTime(), european); - QCOMPARE(dtUtc.toLocalTime(), european); - QCOMPARE(dtOffset.toLocalTime(), european); + if (zoneIsCET) { + QCOMPARE(dtLocal.toLocalTime(), cet); + QCOMPARE(dtUtc.toLocalTime(), cet); + QCOMPARE(dtOffset.toLocalTime(), cet); } else { QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo"); } @@ -793,7 +842,7 @@ void tst_QDateTime::toString_rfcDate_data() QTest::addColumn<QDateTime>("dt"); QTest::addColumn<QString>("formatted"); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("localtime") << QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34)) << QString("09 Nov 1978 13:28:34 +0100"); @@ -1050,7 +1099,7 @@ void tst_QDateTime::addSecs_data() QTest::newRow("utc9") << QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC) << 0 << QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("cet0") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << 86400 << QDateTime(QDate(2004, 1, 2), standardTime, Qt::LocalTime); QTest::newRow("cet1") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << (86400 * 185) @@ -1162,7 +1211,7 @@ void tst_QDateTime::toTimeSpec_data() << QDateTime(QDate(-271821, 4, 20), QTime(23, 0, 0), Qt::UTC) << QDateTime(QDate(-271821, 4, 21), QTime(0, 0, 0), Qt::LocalTime); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("summer1") << QDateTime(QDate(2004, 6, 30), utcTime, Qt::UTC) << QDateTime(QDate(2004, 6, 30), localDaylightTime, Qt::LocalTime); QTest::newRow("summer2") << QDateTime(QDate(1760, 6, 30), utcTime, Qt::UTC) @@ -1185,7 +1234,7 @@ void tst_QDateTime::toTimeSpec_data() void tst_QDateTime::toTimeSpec() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1240,7 +1289,7 @@ void tst_QDateTime::toTimeSpec() QCOMPARE(localToOffset.time(), fromUtc.time()); QCOMPARE(localToOffset.timeSpec(), Qt::UTC); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } } @@ -1251,7 +1300,7 @@ void tst_QDateTime::toLocalTime_data() void tst_QDateTime::toLocalTime() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1262,7 +1311,7 @@ void tst_QDateTime::toLocalTime() QCOMPARE(fromUtc.toLocalTime(), fromLocal); QCOMPARE(fromUtc.toLocalTime(), fromLocal.toLocalTime()); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } } @@ -1273,7 +1322,7 @@ void tst_QDateTime::toUTC_data() void tst_QDateTime::toUTC() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1284,7 +1333,7 @@ void tst_QDateTime::toUTC() QCOMPARE(fromLocal.toUTC(), fromUtc); QCOMPARE(fromUtc.toUTC(), fromLocal.toUTC()); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } QDateTime dt = QDateTime::currentDateTime(); @@ -1614,12 +1663,44 @@ void tst_QDateTime::springForward_data() QTest::addColumn<int>("step"); // days to step; +ve from before, -ve from after QTest::addColumn<int>("adjust"); // minutes ahead of UTC on day stepped from - if (europeanTimeZone) { - QTest::newRow("Europe from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; - QTest::newRow("Europe from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; - // } else if (otherZone) { + /* + Zone tests compare a summer and winter moment's time_t to known values. + This could in principle be flawed (two DST-using zones in the same + hemisphere with the same DST and standard times but different transition + times) but no actual example is known where this is a problem. Please + document any such conflicts, if discovered. + + See http://www.timeanddate.com/time/zones/ for data on more candidates to + test. + */ + + uint winter = QDateTime(QDate(2015, 1, 1), QTime()).toTime_t(); + uint summer = QDateTime(QDate(2015, 7, 1), QTime()).toTime_t(); + + if (winter == 1420066800 && summer == 1435701600) { + QTest::newRow("CET from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; + QTest::newRow("CET from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; + } else if (winter == 1420063200 && summer == 1435698000) { + // e.g. Finland, where our CI runs ... + QTest::newRow("EET from day before") << QDate(2015, 3, 29) << QTime(3, 30, 0) << 1 << 120; + QTest::newRow("EET from day after") << QDate(2015, 3, 29) << QTime(3, 30, 0) << -1 << 180; + } else if (winter == 1420070400 && summer == 1435705200) { + // Western European Time, WET/WEST; a.k.a. GMT/BST + QTest::newRow("WET from day before") << QDate(2015, 3, 29) << QTime(1, 30, 0) << 1 << 0; + QTest::newRow("WET from day after") << QDate(2015, 3, 29) << QTime(1, 30, 0) << -1 << 60; + } else if (winter == 1420099200 && summer == 1435734000) { + // Western USA, Canada: Pacific Time (e.g. US/Pacific) + QTest::newRow("PT from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -480; + QTest::newRow("PT from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -420; + } else if (winter == 1420088400 && summer == 1435723200) { + // Eastern USA, Canada: Eastern Time (e.g. US/Eastern) + QTest::newRow("ET from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -300; + QTest::newRow("ET from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -240; } else { - QSKIP("No spring forward test data for this TZ"); + // Includes the numbers you need to test for your zone, as above: + QString msg(QString::fromLatin1("No spring forward test data for this TZ (%1, %2)" + ).arg(winter).arg(summer)); + QSKIP(qPrintable(msg)); } } @@ -1687,7 +1768,7 @@ void tst_QDateTime::operator_eqeq_data() QTest::newRow("invalid == invalid") << invalidDateTime() << invalidDateTime() << true << false; QTest::newRow("invalid == valid #1") << invalidDateTime() << dateTime1 << false << false; - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("data14") << QDateTime(QDate(2004, 1, 2), QTime(2, 2, 3), Qt::LocalTime) << QDateTime(QDate(2004, 1, 2), QTime(1, 2, 3), Qt::UTC) << true << true; } @@ -1719,7 +1800,7 @@ void tst_QDateTime::operator_eqeq() if (equal) QVERIFY(qHash(dt1) == qHash(dt2)); - if (checkEuro && europeanTimeZone) { + if (checkEuro && zoneIsCET) { QVERIFY(dt1.toUTC() == dt2); QVERIFY(dt1 == dt2.toLocalTime()); } @@ -2233,7 +2314,7 @@ void tst_QDateTime::offsetFromUtc() QCOMPARE(dt2.offsetFromUtc(), 0); // LocalTime should vary - if (europeanTimeZone) { + if (zoneIsCET) { // Time definitely in Standard Time so 1 hour ahead QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); QCOMPARE(dt3.offsetFromUtc(), 1 * 60 * 60); @@ -2358,7 +2439,7 @@ void tst_QDateTime::timeZoneAbbreviation() QCOMPARE(dt3.timeZoneAbbreviation(), QString("UTC")); // LocalTime should vary - if (europeanTimeZone) { + if (zoneIsCET) { // Time definitely in Standard Time QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); #ifdef Q_OS_WIN @@ -2482,7 +2563,7 @@ void tst_QDateTime::isDaylightTime() const QDateTime offset2(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::OffsetFromUTC, 1 * 60 * 60); QVERIFY(!offset2.isDaylightTime()); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime cet1(QDate(2012, 1, 1), QTime(0, 0, 0)); QVERIFY(!cet1.isDaylightTime()); QDateTime cet2(QDate(2012, 6, 1), QTime(0, 0, 0)); @@ -2494,7 +2575,7 @@ void tst_QDateTime::isDaylightTime() const void tst_QDateTime::daylightTransitions() const { - if (europeanTimeZone) { + if (zoneIsCET) { // CET transitions occur at 01:00:00 UTC on last Sunday in March and October // 2011-03-27 02:00:00 CET became 03:00:00 CEST at msecs = 1301187600000 // 2011-10-30 03:00:00 CEST became 02:00:00 CET at msecs = 1319936400000 diff --git a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp index f59f542a2b..6a14928219 100644 --- a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp +++ b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp @@ -319,7 +319,7 @@ void tst_QTextDocumentLayout::blockVisibility() for (int i = 0; i < 10; ++i) { if (!doc->isEmpty()) cursor.insertBlock(); - cursor.insertText(QString::number(i)); + cursor.insertText("A"); } qreal margin = doc->documentMargin(); |