Skip to content

Commit

Permalink
cxx-qt-lib: add QTimeZone
Browse files Browse the repository at this point in the history
Related to KDAB#291
  • Loading branch information
ahayzen-kdab committed Mar 7, 2023
1 parent c650dcf commit 61e5896
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Register QML types at build time: `#[cxxqt::qobject(qml_uri = "foo.bar", qml_version = "1.0")]`
- Register QRC resources at build time in Cargo builds (don't need to call initialization function from Rust `main` function)
- Support for container types: `QSet<T>`, `QHash<K, V>`, `QList<T>`, `QMap<K, V>`, `QVector<T>`
- Support for further types: `QByteArray`, `QCoreApplication`, `QGuiApplication`, `QMargins`, `QMarginsF`, `QModelIndex`, `QPersistentModelIndex`, `QQmlApplicationEngine`, `QQmlEngine`, `QStringList`, `QVector2D`, `QVector3D`, `QVector4D`
- Support for further types: `QByteArray`, `QCoreApplication`, `QGuiApplication`, `QMargins`, `QMarginsF`, `QModelIndex`, `QPersistentModelIndex`, `QQmlApplicationEngine`, `QQmlEngine`, `QStringList`, `QTimeZone`, `QVector2D`, `QVector3D`, `QVector4D`
- Support for nesting objects in properties, invokables, and signals with `*mut T`
- Allow for marking signals as existing in the base class
- Support for conversions to types in third-party crates: `bytes`, `http`, `rgb`, `url`
Expand Down
37 changes: 37 additions & 0 deletions crates/cxx-qt-lib-headers/include/core/qtimezone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// clang-format off
// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Andrew Hayzen <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <cinttypes>
#include <memory>

#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QTimeZone>

namespace rust {
namespace cxxqtlib1 {

QList<QByteArray>
qtimezoneAvailableTimeZoneIds();
::std::unique_ptr<QTimeZone>
qtimezoneClone(const QTimeZone& timezone);
::std::unique_ptr<QTimeZone>
qtimezoneDefault();
::std::unique_ptr<QTimeZone>
qtimezoneFromOffsetSeconds(::std::int32_t offsetSeconds);
::std::unique_ptr<QTimeZone>
qtimezoneFromIana(const QByteArray& ianaId);
::std::unique_ptr<QTimeZone>
qtimezoneSystemTimeZone();
QByteArray
qtimezoneSystemTimeZoneId();
::std::unique_ptr<QTimeZone>
qtimezoneUtc();

}
}
1 change: 1 addition & 0 deletions crates/cxx-qt-lib-headers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub fn write_headers(directory: impl AsRef<Path>) {
),
(include_str!("../include/core/qt.h"), "qt.h"),
(include_str!("../include/core/qtime.h"), "qtime.h"),
(include_str!("../include/core/qtimezone.h"), "qtimezone.h"),
(include_str!("../include/core/qurl.h"), "qurl.h"),
(include_str!("../include/core/qvariant.h"), "qvariant.h"),
(include_str!("../include/core/qvector.h"), "qvector.h"),
Expand Down
2 changes: 2 additions & 0 deletions crates/cxx-qt-lib/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fn main() {
"core/qstringlist",
"core/qt",
"core/qtime",
"core/qtimezone",
"core/qurl",
"core/qvariant/mod",
"core/qvariant/qvariant_bool",
Expand Down Expand Up @@ -203,6 +204,7 @@ fn main() {
"core/qstring",
"core/qstringlist",
"core/qtime",
"core/qtimezone",
"core/qurl",
"core/qvariant/qvariant",
"core/qvector/qvector",
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt-lib/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub use qt::{AspectRatioMode, CaseSensitivity, DateFormat, SplitBehaviorFlags};
mod qtime;
pub use qtime::QTime;

mod qtimezone;
pub use qtimezone::QTimeZone;

mod qpoint;
pub use qpoint::QPoint;

Expand Down
61 changes: 61 additions & 0 deletions crates/cxx-qt-lib/src/core/qtimezone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// clang-format off
// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Andrew Hayzen <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#include "cxx-qt-lib/qtimezone.h"

namespace rust {
namespace cxxqtlib1 {

QList<QByteArray>
qtimezoneAvailableTimeZoneIds()
{
return QTimeZone::availableTimeZoneIds();
}

::std::unique_ptr<QTimeZone>
qtimezoneClone(const QTimeZone& timezone)
{
return ::std::make_unique<QTimeZone>(timezone);
}

::std::unique_ptr<QTimeZone>
qtimezoneDefault()
{
return ::std::make_unique<QTimeZone>();
}

::std::unique_ptr<QTimeZone>
qtimezoneFromOffsetSeconds(::std::int32_t offsetSeconds)
{
return ::std::make_unique<QTimeZone>(static_cast<int>(offsetSeconds));
}

::std::unique_ptr<QTimeZone>
qtimezoneFromIana(const QByteArray& ianaId)
{
return ::std::make_unique<QTimeZone>(ianaId);
}

::std::unique_ptr<QTimeZone>
qtimezoneSystemTimeZone()
{
return ::std::make_unique<QTimeZone>(QTimeZone::systemTimeZone());
}

QByteArray
qtimezoneSystemTimeZoneId()
{
return QTimeZone::systemTimeZoneId();
}

::std::unique_ptr<QTimeZone>
qtimezoneUtc()
{
return ::std::make_unique<QTimeZone>(QTimeZone::utc());
}

}
}
180 changes: 180 additions & 0 deletions crates/cxx-qt-lib/src/core/qtimezone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// SPDX-FileContributor: Andrew Hayzen <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::fmt;

#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("cxx-qt-lib/qbytearray.h");
type QByteArray = crate::QByteArray;
include!("cxx-qt-lib/qdatetime.h");
type QDateTime = crate::QDateTime;
include!("cxx-qt-lib/qlist.h");
type QList_QByteArray = crate::QList<crate::QByteArray>;
include!("cxx-qt-lib/qstring.h");
type QString = crate::QString;

include!("cxx-qt-lib/qtimezone.h");
/// The QTimeZone class converts between UTC and local time in a specific time zone.
//
// QTimeZone only has a copy-constructor and not a move-constructor, which means that the following is true
// "When the move constructor is not implicitly declared or explicitly supplied, expressions
// that otherwise would have invoked the move constructor may instead invoke a copy constructor."
//
// Therefore the internal QSharedDataPointer is incremented causing a memory leak, so use an opaque type.
type QTimeZone;

/// Returns the time zone abbreviation at the given atDateTime. The abbreviation may change depending on DST or even historical events.
fn abbreviation(self: &QTimeZone, atDateTime: &QDateTime) -> QString;

/// Returns any comment for the time zone.
fn comment(self: &QTimeZone) -> QString;

/// Returns the daylight-saving time offset at the given atDateTime,
/// i.e. the number of seconds to add to the standard time offset to obtain the local daylight-saving time.
#[rust_name = "daylight_time_offset"]
fn daylightTimeOffset(self: &QTimeZone, atDateTime: &QDateTime) -> i32;

/// Returns true if the time zone has practiced daylight-saving at any time.
#[rust_name = "has_daylight_time"]
fn hasDaylightTime(self: &QTimeZone) -> bool;

/// Returns true if the system backend supports obtaining transitions.
#[rust_name = "has_transitions"]
fn hasTransitions(self: &QTimeZone) -> bool;

/// Returns the IANA ID for the time zone.
fn id(self: &QTimeZone) -> QByteArray;

/// Returns true if daylight-saving was in effect at the given atDateTime.
#[rust_name = "is_daylight_time"]
fn isDaylightTime(self: &QTimeZone, atDateTime: &QDateTime) -> bool;

/// Returns true if this time zone is valid.
#[rust_name = "is_valid"]
fn isValid(self: &QTimeZone) -> bool;

/// Returns the total effective offset at the given atDateTime, i.e. the number of seconds to add to UTC to obtain the local time.
/// This includes any DST offset that may be in effect, i.e. it is the sum of standardTimeOffset() and daylightTimeOffset() for the given datetime.
#[rust_name = "offset_from_utc"]
fn offsetFromUtc(self: &QTimeZone, atDateTime: &QDateTime) -> i32;

/// Returns the standard time offset at the given atDateTime, i.e. the number of seconds to add to UTC to obtain the local Standard Time.
/// This excludes any DST offset that may be in effect.
#[rust_name = "standard_time_offset"]
fn standardTimeOffset(self: &QTimeZone, atDateTime: &QDateTime) -> i32;
}

#[namespace = "rust::cxxqtlib1"]
unsafe extern "C++" {
#[doc(hidden)]
#[rust_name = "qtimezone_available_time_zone_ids"]
fn qtimezoneAvailableTimeZoneIds() -> QList_QByteArray;
#[doc(hidden)]
#[rust_name = "qtimezone_clone"]
fn qtimezoneClone(timezone: &QTimeZone) -> UniquePtr<QTimeZone>;
#[doc(hidden)]
#[rust_name = "qtimezone_default"]
fn qtimezoneDefault() -> UniquePtr<QTimeZone>;
#[doc(hidden)]
#[rust_name = "qtimezone_from_offset_seconds"]
fn qtimezoneFromOffsetSeconds(offset_seconds: i32) -> UniquePtr<QTimeZone>;
#[doc(hidden)]
#[rust_name = "qtimezone_from_iana"]
fn qtimezoneFromIana(iana_id: &QByteArray) -> UniquePtr<QTimeZone>;
#[doc(hidden)]
#[rust_name = "qtimezone_system_time_zone"]
fn qtimezoneSystemTimeZone() -> UniquePtr<QTimeZone>;
#[doc(hidden)]
#[rust_name = "qtimezone_system_time_zone_id"]
fn qtimezoneSystemTimeZoneId() -> QByteArray;
#[doc(hidden)]
#[rust_name = "qtimezone_utc"]
fn qtimezoneUtc() -> UniquePtr<QTimeZone>;
}

#[namespace = "rust::cxxqtlib1"]
unsafe extern "C++" {
include!("cxx-qt-lib/common.h");

#[doc(hidden)]
#[rust_name = "qtimezone_eq"]
fn operatorEq(a: &QTimeZone, b: &QTimeZone) -> bool;
#[doc(hidden)]
#[rust_name = "qtimezone_to_qstring"]
fn toQString(value: &QTimeZone) -> QString;
}

// QTimeZone only has a copy-constructor and not a move-constructor, which means that the following is true
// "When the move constructor is not implicitly declared or explicitly supplied, expressions
// that otherwise would have invoked the move constructor may instead invoke a copy constructor."
//
// Therefore the internal QSharedDataPointer is incremented causing a memory leak, so use an opaque type.
impl UniquePtr<QTimeZone> {}
}

pub use ffi::QTimeZone;

impl QTimeZone {
/// Returns a list of all available IANA time zone IDs on this system.
pub fn available_time_zone_ids() -> ffi::QList_QByteArray {
ffi::qtimezone_available_time_zone_ids()
}

/// Creates an instance of a time zone with the requested Offset from UTC of offsetSeconds.
pub fn from_offset_seconds(offset_seconds: i32) -> cxx::UniquePtr<Self> {
ffi::qtimezone_from_offset_seconds(offset_seconds)
}

/// Creates an instance of the requested time zone ianaId.
pub fn from_iana(iana_id: &ffi::QByteArray) -> cxx::UniquePtr<Self> {
ffi::qtimezone_from_iana(iana_id)
}

/// Create a null/invalid time zone instance.
pub fn new() -> cxx::UniquePtr<Self> {
ffi::qtimezone_default()
}

/// Returns a QTimeZone object that refers to the local system time, as specified by systemTimeZoneId().
pub fn system_time_zone() -> cxx::UniquePtr<Self> {
ffi::qtimezone_system_time_zone()
}

/// Returns the current system time zone IANA ID.
pub fn system_time_zone_id() -> ffi::QByteArray {
ffi::qtimezone_system_time_zone_id()
}

/// Copy constructor, create a copy of the QTimeZone.
pub fn to_owned(&self) -> cxx::UniquePtr<Self> {
ffi::qtimezone_clone(self)
}

/// Returns a QTimeZone object that refers to UTC (Universal Time Coordinated).
pub fn utc() -> cxx::UniquePtr<Self> {
ffi::qtimezone_utc()
}
}

impl std::cmp::PartialEq for QTimeZone {
fn eq(&self, other: &Self) -> bool {
ffi::qtimezone_eq(self, other)
}
}

impl std::cmp::Eq for QTimeZone {}

impl fmt::Display for QTimeZone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", ffi::qtimezone_to_qstring(self))
}
}

impl fmt::Debug for QTimeZone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{self}")
}
}
1 change: 1 addition & 0 deletions tests/qt_types_standalone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ add_executable(${APP_NAME}
cpp/qstring.h
cpp/qstringlist.h
cpp/qtime.h
cpp/qtimezone.h
cpp/qurl.h
cpp/qvariant.h
cpp/qvector.h
Expand Down
2 changes: 2 additions & 0 deletions tests/qt_types_standalone/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "qstring.h"
#include "qstringlist.h"
#include "qtime.h"
#include "qtimezone.h"
#include "qurl.h"
#include "qvariant.h"
#include "qvector.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ main(int argc, char* argv[])
runTest(QScopedPointer<QObject>(new QStringTest));
runTest(QScopedPointer<QObject>(new QStringListTest));
runTest(QScopedPointer<QObject>(new QTimeTest));
runTest(QScopedPointer<QObject>(new QTimeZoneTest));
runTest(QScopedPointer<QObject>(new QUrlTest));
runTest(QScopedPointer<QObject>(new QVariantTest));
runTest(QScopedPointer<QObject>(new QVectorTest));
Expand Down
39 changes: 39 additions & 0 deletions tests/qt_types_standalone/cpp/qtimezone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// clang-format off
// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
// clang-format on
// SPDX-FileContributor: Andrew Hayzen <[email protected]>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <QtCore/QTimeZone>
#include <QtTest/QTest>

#include "cxx-qt-gen/qtimezone_cxx.cxx.h"

class QTimeZoneTest : public QObject
{
Q_OBJECT

private Q_SLOTS:
void construct()
{
auto t = construct_qtimezone();
QVERIFY(t != nullptr);
QCOMPARE(t->id(), QByteArrayLiteral("Europe/London"));
}

void read()
{
const auto t = QTimeZone(QByteArrayLiteral("Europe/London"));
QVERIFY(read_qtimezone(t));
}

void clone()
{
const auto t = QTimeZone(QByteArrayLiteral("Europe/London"));
auto c = clone_qtimezone(t);
QVERIFY(c != nullptr);
QCOMPARE(c->id(), QByteArrayLiteral("Europe/London"));
}
};
1 change: 1 addition & 0 deletions tests/qt_types_standalone/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn main() {
.file("src/qstring.rs")
.file("src/qstringlist.rs")
.file("src/qtime.rs")
.file("src/qtimezone.rs")
.file("src/qurl.rs")
.file("src/qvariant.rs")
.file("src/qvector.rs")
Expand Down
Loading

0 comments on commit 61e5896

Please sign in to comment.