From 4b507e8257243e36f40089d57099c2d668c5884d Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 5 Jan 2017 16:28:53 -0800 Subject: Add conversion functions for QTimeZone and CFTimeZone/NSTimeZone Change-Id: I3a2e18d69577296bf612e13e40414bce1daa6a71 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcore_foundation.mm | 68 ++++++++++++++++++++++ src/corelib/tools/qtimezone.h | 12 ++++ src/corelib/tools/qtimezoneprivate_mac.mm | 5 ++ src/corelib/tools/qtimezoneprivate_p.h | 12 ++-- tests/auto/corelib/tools/qtimezone/qtimezone.pro | 5 ++ .../auto/corelib/tools/qtimezone/tst_qtimezone.cpp | 11 ++++ .../tools/qtimezone/tst_qtimezone_darwin.mm | 68 ++++++++++++++++++++++ 7 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm index f5ccd1c1f2..8b6be9b08e 100644 --- a/src/corelib/kernel/qcore_foundation.mm +++ b/src/corelib/kernel/qcore_foundation.mm @@ -46,6 +46,13 @@ #include #include +#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE) +#include +#include +#include +#endif + +#import #import #if defined(QT_PLATFORM_UIKIT) @@ -422,6 +429,67 @@ NSDate *QDateTime::toNSDate() const // ---------------------------------------------------------------------------- +#if QT_CONFIG(timezone) && !defined(QT_NO_SYSTEMLOCALE) +/*! + \since 5.9 + + Constructs a new QTimeZone containing a copy of the CFTimeZone \a timeZone. + + \sa toCFTimeZone() +*/ +QTimeZone QTimeZone::fromCFTimeZone(CFTimeZoneRef timeZone) +{ + if (!timeZone) + return QTimeZone(); + return QTimeZone(QString::fromCFString(CFTimeZoneGetName(timeZone)).toLatin1()); +} + +/*! + \since 5.9 + + Creates a CFTimeZone from a QTimeZone. The caller owns the CFTimeZone object + and is responsible for releasing it. + + \sa fromCFTimeZone() +*/ +CFTimeZoneRef QTimeZone::toCFTimeZone() const +{ +#ifndef QT_NO_DYNAMIC_CAST + Q_ASSERT(dynamic_cast(d.data())); +#endif + const QMacTimeZonePrivate *p = static_cast(d.data()); + return reinterpret_cast([p->nsTimeZone() copy]); +} + +/*! + \since 5.9 + + Constructs a new QTimeZone containing a copy of the NSTimeZone \a timeZone. + + \sa toNSTimeZone() +*/ +QTimeZone QTimeZone::fromNSTimeZone(const NSTimeZone *timeZone) +{ + if (!timeZone) + return QTimeZone(); + return QTimeZone(QString::fromNSString(timeZone.name).toLatin1()); +} + +/*! + \since 5.9 + + Creates an NSTimeZone from a QTimeZone. The NSTimeZone object is autoreleased. + + \sa fromNSTimeZone() +*/ +NSTimeZone *QTimeZone::toNSTimeZone() const +{ + return [static_cast(toCFTimeZone()) autorelease]; +} +#endif + +// ---------------------------------------------------------------------------- + /*! \since 5.8 diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h index 083f87f39f..bd87139f5b 100644 --- a/src/corelib/tools/qtimezone.h +++ b/src/corelib/tools/qtimezone.h @@ -47,6 +47,11 @@ QT_REQUIRE_CONFIG(timezone); +#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE) +Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone); +Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone); +#endif + QT_BEGIN_NAMESPACE class QTimeZonePrivate; @@ -142,6 +147,13 @@ public: static QList windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country); +#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE) + static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone); + CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED; + static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone); + NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED; +#endif + private: QTimeZone(QTimeZonePrivate &dd); #ifndef QT_NO_DATASTREAM diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index 5dfffeaf36..0c2dbe6fef 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -273,4 +273,9 @@ QList QMacTimeZonePrivate::availableTimeZoneIds() const return list; } +NSTimeZone *QMacTimeZonePrivate::nsTimeZone() const +{ + return m_nstz; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index c397c18aac..682edd3996 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -60,13 +60,9 @@ #include #endif -#ifdef Q_OS_MAC -#ifdef __OBJC__ -@class NSTimeZone; -#else -class NSTimeZone; -#endif // __OBJC__ -#endif // Q_OS_MAC +#ifdef Q_OS_DARWIN +Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone); +#endif // Q_OS_DARWIN #ifdef Q_OS_WIN #include @@ -380,6 +376,8 @@ public: QList availableTimeZoneIds() const Q_DECL_OVERRIDE; + NSTimeZone *nsTimeZone() const; + private: void init(const QByteArray &zoneId); diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/tools/qtimezone/qtimezone.pro index afc4c59dfe..19ebc13306 100644 --- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro +++ b/tests/auto/corelib/tools/qtimezone/qtimezone.pro @@ -5,3 +5,8 @@ SOURCES = tst_qtimezone.cpp qtConfig(icu) { DEFINES += QT_USE_ICU } + +darwin { + OBJECTIVE_SOURCES += tst_qtimezone_darwin.mm + LIBS += -framework Foundation +} diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index 38aaff0edc..abb5b50229 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -56,6 +56,7 @@ private slots: void icuTest(); void tzTest(); void macTest(); + void darwinTypes(); void winTest(); private: @@ -955,6 +956,16 @@ void tst_QTimeZone::macTest() #endif // Q_OS_MAC } +void tst_QTimeZone::darwinTypes() +{ +#ifndef Q_OS_DARWIN + QSKIP("This is an Apple-only test"); +#else + extern void tst_QTimeZone_darwinTypes(); // in tst_qtimezone_darwin.mm + tst_QTimeZone_darwinTypes(); +#endif +} + void tst_QTimeZone::winTest() { #if defined(QT_BUILD_INTERNAL) && defined(Q_OS_WIN) diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm b/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm new file mode 100644 index 0000000000..de801e55d0 --- /dev/null +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include + +void tst_QTimeZone_darwinTypes() +{ +#if !defined(QT_NO_SYSTEMLOCALE) + // QTimeZone <-> CFTimeZone + { + QTimeZone qtTimeZone("America/Los_Angeles"); + const CFTimeZoneRef cfTimeZone = qtTimeZone.toCFTimeZone(); + QCOMPARE(QTimeZone::fromCFTimeZone(cfTimeZone), qtTimeZone); + CFRelease(cfTimeZone); + } + { + CFTimeZoneRef cfTimeZone = CFTimeZoneCreateWithName(kCFAllocatorDefault, + CFSTR("America/Los_Angeles"), false); + const QTimeZone qtTimeZone = QTimeZone::fromCFTimeZone(cfTimeZone); + QVERIFY(CFEqual(qtTimeZone.toCFTimeZone(), cfTimeZone)); + CFRelease(cfTimeZone); + } + // QTimeZone <-> NSTimeZone + { + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QTimeZone qtTimeZone("America/Los_Angeles"); + const NSTimeZone *nsTimeZone = qtTimeZone.toNSTimeZone(); + QCOMPARE(QTimeZone::fromNSTimeZone(nsTimeZone), qtTimeZone); + [autoreleasepool release]; + } + { + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + NSTimeZone *nsTimeZone = [NSTimeZone timeZoneWithName:@"America/Los_Angeles"]; + const QTimeZone qtTimeZone = QTimeZone::fromNSTimeZone(nsTimeZone); + QVERIFY([qtTimeZone.toNSTimeZone() isEqual:nsTimeZone]); + [autoreleasepool release]; + } +#endif +} -- cgit v1.2.3