From bdfb797c4180a6d97d2b6e67e646325f4d25e5de Mon Sep 17 00:00:00 2001 From: reionwong Date: Fri, 13 Aug 2021 03:18:05 +0800 Subject: [PATCH] Add datetime module --- CMakeLists.txt | 5 + src/application.cpp | 3 + src/datetime/org.freedesktop.timedate1.xml | 42 +++ src/datetime/timedated_interface.cpp | 25 ++ src/datetime/timedated_interface.h | 103 ++++++ src/datetime/timezonedata.h | 17 + src/datetime/timezonemap.cpp | 179 ++++++++++ src/datetime/timezonemap.h | 61 ++++ src/images/dark/world.svg | 383 +++++++++++++++++++++ src/images/light/world.svg | 383 +++++++++++++++++++++ src/images/sidebar/dark/datetime.svg | 9 + src/qml/Appearance/Main.qml | 2 + src/qml/Cursor/Main.qml | 31 +- src/qml/DateTime/Main.qml | 71 ++++ src/qml/DateTime/TimeZoneDialog.qml | 179 ++++++++++ src/qml/ItemPage.qml | 6 +- src/qml/RoundedItem.qml | 4 +- src/qml/SideBar.qml | 15 +- src/resources.qrc | 5 + src/timezonedata.h | 4 + translations/en_US.ts | 34 +- translations/zh_CN.ts | 38 +- 22 files changed, 1569 insertions(+), 30 deletions(-) create mode 100644 src/datetime/org.freedesktop.timedate1.xml create mode 100644 src/datetime/timedated_interface.cpp create mode 100644 src/datetime/timedated_interface.h create mode 100644 src/datetime/timezonedata.h create mode 100644 src/datetime/timezonemap.cpp create mode 100644 src/datetime/timezonemap.h create mode 100644 src/images/dark/world.svg create mode 100644 src/images/light/world.svg create mode 100644 src/images/sidebar/dark/datetime.svg create mode 100644 src/qml/DateTime/Main.qml create mode 100644 src/qml/DateTime/TimeZoneDialog.qml create mode 100644 src/timezonedata.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6db568e..8856b54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,9 @@ set(SRCS src/cursor/cursorthememodel.cpp src/cursor/cursortheme.cpp src/cursor/mouse.cpp + src/datetime/timezonedata.h + src/datetime/timezonemap.cpp + src/datetime/timedated_interface.cpp ) set(RESOURCES @@ -56,6 +59,8 @@ qt5_add_dbus_adaptor(DBUS_SOURCES src/application.h Application) set_source_files_properties(${DBUS_SOURCES} PROPERTIES SKIP_AUTOGEN ON) +# qt5_add_dbus_interface(DBUS_SOURCES src/datetime/org.freedesktop.timedate1.xml timedated_interface) + add_executable(${PROJECT_NAME} ${DBUS_SOURCES} ${SRCS} ${RESOURCES}) target_link_libraries(${PROJECT_NAME} Qt5::Core diff --git a/src/application.cpp b/src/application.cpp index 833d583..7caba1c 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -20,6 +20,8 @@ #include "cursor/cursorthememodel.h" #include "cursor/mouse.h" +#include "datetime/timezonemap.h" + static QObject *passwordSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine); @@ -69,6 +71,7 @@ Application::Application(int &argc, char **argv) qmlRegisterType(uri, 1, 0, "Fonts"); qmlRegisterType(uri, 1, 0, "PowerManager"); qmlRegisterType(uri, 1, 0, "Mouse"); + qmlRegisterType(uri, 1, 0, "TimeZoneMap"); qmlRegisterSingletonType(uri, 1, 0, "Password", passwordSingleton); qmlRegisterType(); diff --git a/src/datetime/org.freedesktop.timedate1.xml b/src/datetime/org.freedesktop.timedate1.xml new file mode 100644 index 0000000..587fd21 --- /dev/null +++ b/src/datetime/org.freedesktop.timedate1.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/datetime/timedated_interface.cpp b/src/datetime/timedated_interface.cpp new file mode 100644 index 0000000..9979004 --- /dev/null +++ b/src/datetime/timedated_interface.cpp @@ -0,0 +1,25 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -m -p timedated_interface /home/cutefish/CutefishOS/settings/src/datetime/org.freedesktop.timedate1.xml + * + * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "timedated_interface.h" + +/* + * Implementation of interface class OrgFreedesktopTimedate1Interface + */ + +OrgFreedesktopTimedate1Interface::OrgFreedesktopTimedate1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgFreedesktopTimedate1Interface::~OrgFreedesktopTimedate1Interface() +{ +} diff --git a/src/datetime/timedated_interface.h b/src/datetime/timedated_interface.h new file mode 100644 index 0000000..98d2e29 --- /dev/null +++ b/src/datetime/timedated_interface.h @@ -0,0 +1,103 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -m -p timedated_interface /home/cutefish/CutefishOS/settings/src/datetime/org.freedesktop.timedate1.xml + * + * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef TIMEDATED_INTERFACE_H +#define TIMEDATED_INTERFACE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Proxy class for interface org.freedesktop.timedate1 + */ +class OrgFreedesktopTimedate1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.timedate1"; } + +public: + OrgFreedesktopTimedate1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgFreedesktopTimedate1Interface(); + + Q_PROPERTY(bool CanNTP READ canNTP) + inline bool canNTP() const + { return qvariant_cast< bool >(property("CanNTP")); } + + Q_PROPERTY(bool LocalRTC READ localRTC) + inline bool localRTC() const + { return qvariant_cast< bool >(property("LocalRTC")); } + + Q_PROPERTY(bool NTP READ nTP) + inline bool nTP() const + { return qvariant_cast< bool >(property("NTP")); } + + Q_PROPERTY(bool NTPSynchronized READ nTPSynchronized) + inline bool nTPSynchronized() const + { return qvariant_cast< bool >(property("NTPSynchronized")); } + + Q_PROPERTY(qulonglong RTCTimeUSec READ rTCTimeUSec) + inline qulonglong rTCTimeUSec() const + { return qvariant_cast< qulonglong >(property("RTCTimeUSec")); } + + Q_PROPERTY(qulonglong TimeUSec READ timeUSec) + inline qulonglong timeUSec() const + { return qvariant_cast< qulonglong >(property("TimeUSec")); } + + Q_PROPERTY(QString Timezone READ timezone) + inline QString timezone() const + { return qvariant_cast< QString >(property("Timezone")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> SetLocalRTC(bool in0, bool in1, bool in2) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("SetLocalRTC"), argumentList); + } + + inline QDBusPendingReply<> SetNTP(bool in0, bool in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("SetNTP"), argumentList); + } + + inline QDBusPendingReply<> SetTime(qlonglong in0, bool in1, bool in2) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("SetTime"), argumentList); + } + + inline QDBusPendingReply<> SetTimezone(const QString &in0, bool in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("SetTimezone"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace freedesktop { + typedef ::OrgFreedesktopTimedate1Interface timedate1; + } +} +#endif diff --git a/src/datetime/timezonedata.h b/src/datetime/timezonedata.h new file mode 100644 index 0000000..771b19f --- /dev/null +++ b/src/datetime/timezonedata.h @@ -0,0 +1,17 @@ +#ifndef TIMEZONEDATA_H +#define TIMEZONEDATA_H + +#include + +class TimeZoneData +{ +public: + QString id; + QString region; + QString city; + QString comment; + bool checked; + int offsetFromUtc; +}; + +#endif // TIMEZONEDATA_H diff --git a/src/datetime/timezonemap.cpp b/src/datetime/timezonemap.cpp new file mode 100644 index 0000000..0bfd667 --- /dev/null +++ b/src/datetime/timezonemap.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2021 CutefishOS Team. + * + * Author: Reion Wong + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "timezonemap.h" +#include "timedated_interface.h" + +#include +#include +#include + +#include + +// gnome-control-center: cc-timezone-map.c +static double radians(double degrees) { + return (degrees / 360.0) * M_PI * 2; +} + +static double convert_latitude_to_y(double latitude) { + const double bottom_lat = -59; + const double top_lat = 81; + const double full_range = 4.6068250867599998; + double top_per, y, top_offset, map_range; + + top_per = top_lat / 180.0; + y = 1.25 * log(tan(M_PI_4 + 0.4 * radians(latitude))); + top_offset = full_range * top_per; + map_range = fabs(1.25 * log(tan(M_PI_4 + 0.4 * radians(bottom_lat))) - top_offset); + y = fabs(y - top_offset); + y = y / map_range; + + return y; +} + +static double convert_longitude_to_x(double longitude) { + const double xdeg_offset = -6; + return ((180.0 + longitude) / 360.0 + xdeg_offset / 180.0); +} + +// Parse latitude and longitude of the zone's principal location. +// See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +// |pos| is in ISO 6709 sign-degrees-minutes-seconds format, +// either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS. +// |digits| 2 for latitude, 3 for longitude. +double convert_pos(const QString &pos, int digits) { + if (pos.length() < 4 || digits > 9) { + return 0.0; + } + + const QString integer = pos.left(digits + 1); + const QString fraction = pos.mid(digits + 1); + const double t1 = integer.toDouble(); + const double t2 = fraction.toDouble(); + if (t1 > 0.0) { + return t1 + t2 / pow(10.0, fraction.length()); + } else { + return t1 - t2 / pow(10.0, fraction.length()); + } +} + +TimeZoneMap::TimeZoneMap(QObject *parent) + : QObject(parent) +{ + initDatas(); +} + +void TimeZoneMap::clicked(int x, int y, int width, int height) +{ + double minimum_distance = width * width + height * height; + int nearest_zone_index = -1; + + QList items; + + for (int i = 0; i < m_list.size(); ++i) { + TimeZoneItem *item = m_list.at(i); + const double point_x = convert_longitude_to_x(item->longitude) * width; + const double point_y = convert_latitude_to_y(item->latitude) * height; + const double dx = point_x - x; + const double dy = point_y - y; + const double distance = dx * dx + dy * dy; + + if (distance < minimum_distance) { + minimum_distance = distance; + nearest_zone_index = i; + } + + if (distance <= 20) { + items << item; + } + } + + if (items.isEmpty() && nearest_zone_index != -1) { + items.append(m_list.at(nearest_zone_index)); + } + + m_currentList.clear(); + for (TimeZoneItem *item : items) { + m_currentList.append(item->timeZone); + } + + std::sort(m_currentList.begin(), m_currentList.end()); + + emit availableListChanged(); +} + +void TimeZoneMap::setTimeZone(QString value) +{ + OrgFreedesktopTimedate1Interface timedateIface(QStringLiteral("org.freedesktop.timedate1"), + QStringLiteral("/org/freedesktop/timedate1"), + QDBusConnection::systemBus()); + + timedateIface.SetTimezone(value, true); + m_currentTimeZone = QTimeZone(value.toLatin1()).id(); + emit currentTimeZoneChanged(); +} + +QString TimeZoneMap::currentTimeZone() const +{ + return m_currentTimeZone; +} + +QStringList TimeZoneMap::availableList() +{ + return m_currentList; +} + +void TimeZoneMap::initDatas() +{ + QFile zoneTab("/usr/share/zoneinfo/zone.tab"); + if (!zoneTab.open(QIODevice::ReadOnly)) { + return; + } + + const auto lines = QString::fromUtf8(zoneTab.readAll()).split(QLatin1Char('\n')); + for (const QString &line : lines) { + if (line.startsWith('#')) + continue; + + const QStringList parts = line.split('\t'); + if (parts.size() < 3) + continue; + + const QString coordinates = parts.at(1); + int index = coordinates.indexOf('+', 3); + if (index == -1) { + index = coordinates.indexOf('-', 3); + } + + const double latitude = convert_pos(coordinates.left(index), 2); + const double longitude = convert_pos(coordinates.mid(index), 3); + + TimeZoneItem *item = new TimeZoneItem; + item->country = parts.at(0); + item->timeZone = parts.at(2); + item->latitude = latitude; + item->longitude = longitude; + m_list.append(item); + } + std::sort(m_list.begin(), m_list.end()); + + // currentTimeZoneChanged + m_currentTimeZone = QTimeZone(QTimeZone::systemTimeZoneId()).id(); + emit currentTimeZoneChanged(); +} diff --git a/src/datetime/timezonemap.h b/src/datetime/timezonemap.h new file mode 100644 index 0000000..20f4e4d --- /dev/null +++ b/src/datetime/timezonemap.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 CutefishOS Team. + * + * Author: revenmartin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TIMEZONEMAP_H +#define TIMEZONEMAP_H + +#include + +class TimeZoneItem { +public: + QString country; + QString timeZone; + double latitude; + double longitude; +}; + +class TimeZoneMap : public QObject +{ + Q_OBJECT + Q_PROPERTY(QStringList availableList READ availableList NOTIFY availableListChanged) + Q_PROPERTY(QString currentTimeZone READ currentTimeZone NOTIFY currentTimeZoneChanged) + +public: + explicit TimeZoneMap(QObject *parent = nullptr); + + Q_INVOKABLE void clicked(int x, int y, int width, int height); + Q_INVOKABLE void setTimeZone(QString value); + + QString currentTimeZone() const; + QStringList availableList(); + +signals: + void availableListChanged(); + void currentTimeZoneChanged(); + +private: + void initDatas(); + +private: + QList m_list; + QString m_currentTimeZone; + QStringList m_currentList; +}; + +#endif // TIMEZONEMAP_H diff --git a/src/images/dark/world.svg b/src/images/dark/world.svg new file mode 100644 index 0000000..60506de --- /dev/null +++ b/src/images/dark/world.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/images/light/world.svg b/src/images/light/world.svg new file mode 100644 index 0000000..7434124 --- /dev/null +++ b/src/images/light/world.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/images/sidebar/dark/datetime.svg b/src/images/sidebar/dark/datetime.svg new file mode 100644 index 0000000..5c85d56 --- /dev/null +++ b/src/images/sidebar/dark/datetime.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/qml/Appearance/Main.qml b/src/qml/Appearance/Main.qml index 90655e4..19c0392 100644 --- a/src/qml/Appearance/Main.qml +++ b/src/qml/Appearance/Main.qml @@ -68,6 +68,8 @@ ItemPage { } } + HorizontalDivider {} + RowLayout { spacing: FishUI.Units.largeSpacing diff --git a/src/qml/Cursor/Main.qml b/src/qml/Cursor/Main.qml index 3d53ddb..15b6252 100644 --- a/src/qml/Cursor/Main.qml +++ b/src/qml/Cursor/Main.qml @@ -150,14 +150,17 @@ ItemPage { interactive: false visible: _view.count > 0 + leftMargin: 0 + rightMargin: 0 + cellHeight: itemHeight cellWidth: calcExtraSpacing(itemWidth, _view.width) + itemWidth currentIndex: cursorModel.themeIndex(cursorModel.currentTheme) property int rowCount: _view.width / itemWidth - property int itemWidth: 250 - property int itemHeight: 170 + property int itemWidth: 150 + property int itemHeight: 150 function calcExtraSpacing(cellSize, containerSize) { var availableColumns = Math.floor(containerSize / cellSize) @@ -186,7 +189,7 @@ ItemPage { MouseArea { id: _mouseArea anchors.fill: parent - anchors.margins: FishUI.Units.largeSpacing + anchors.margins: FishUI.Units.smallSpacing onClicked: { _view.currentIndex = index cursorModel.currentTheme = model.id @@ -196,8 +199,8 @@ ItemPage { Rectangle { anchors.fill: parent - anchors.margins: FishUI.Units.largeSpacing + FishUI.Units.smallSpacing - color: FishUI.Theme.darkMode ? "" : "#FAFAFA" + anchors.margins: FishUI.Units.smallSpacing + color: FishUI.Theme.darkMode ? "#3C3C3C" : "#FAFAFA" radius: FishUI.Theme.mediumRadius z: -1 @@ -207,7 +210,15 @@ ItemPage { ColumnLayout { anchors.fill: parent - anchors.margins: FishUI.Units.largeSpacing + anchors.margins: FishUI.Units.smallSpacing + + Item { + Layout.fillHeight: true + } + + Item { + height: FishUI.Units.largeSpacing + } FishUI.IconItem { width: 24 @@ -217,11 +228,19 @@ ItemPage { Layout.alignment: Qt.AlignHCenter } + Item { + Layout.fillHeight: true + } + Label { text: model.name Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom bottomPadding: FishUI.Units.largeSpacing } + + Item { + Layout.fillHeight: true + } } } } diff --git a/src/qml/DateTime/Main.qml b/src/qml/DateTime/Main.qml new file mode 100644 index 0000000..cf58600 --- /dev/null +++ b/src/qml/DateTime/Main.qml @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 CutefishOS Team. + * + * Author: revenmartin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import FishUI 1.0 as FishUI +import Cutefish.Settings 1.0 +import "../" + +ItemPage { + headerTitle: qsTr("Date & Time") + + TimeZoneDialog { + id: timeZoneDialog + } + + TimeZoneMap { + id: timeZoneMap + } + + Scrollable { + anchors.fill: parent + contentHeight: layout.implicitHeight + + ColumnLayout { + id: layout + anchors.fill: parent + + StandardButton { + Layout.fillWidth: true + text: "" + onClicked: timeZoneDialog.visibility = "Maximized" + + RowLayout { + anchors.fill: parent + anchors.leftMargin: FishUI.Units.largeSpacing + anchors.rightMargin: FishUI.Units.largeSpacing + + Label { + text: qsTr("Time Zone") + } + + Item { + Layout.fillWidth: true + } + + Label { + text: timeZoneMap.currentTimeZone + } + } + } + } + } +} diff --git a/src/qml/DateTime/TimeZoneDialog.qml b/src/qml/DateTime/TimeZoneDialog.qml new file mode 100644 index 0000000..32da3ee --- /dev/null +++ b/src/qml/DateTime/TimeZoneDialog.qml @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2021 CutefishOS Team. + * + * Author: Reion Wong + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 2.12 +import QtQuick.Window 2.12 +import QtQuick.Layouts 1.12 +import FishUI 1.0 as FishUI + +FishUI.Window { + id: control + title: "Hello World" + width: 900 + height: 600 + visible: false + + background.opacity: 0.5 + contentTopMargin: 0 + + onWidthChanged: control.reset() + onHeightChanged: control.reset() + + function reset() { + _popupItem.opacity = 0 + dot.visible = false + } + + onVisibleChanged: { + if (!visible) + control.reset() + } + + FishUI.WindowBlur { + view: control + geometry: Qt.rect(control.x, control.y, control.width, control.height) + windowRadius: control.background.radius + enabled: true + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onPressed: { + if (_popupItem.opacity === 1) { + control.reset() + return + } + + timeZoneMap.clicked(mouse.x, mouse.y, control.width, control.height) + _popupItem.x = mouse.x + _popupItem.y = mouse.y + _popupItem.opacity = 1 + dot.show(mouse.x, mouse.y) + } + } + + Image { + anchors.fill: parent + source: FishUI.Theme.darkMode ? "qrc:/images/dark/world.svg" : "qrc:/images/light/world.svg" + sourceSize: Qt.size(width, height) + fillMode: Image.PreserveAspectFit + } + + Rectangle { + id: dot + width: 20 + height: 20 + radius: height / 2 + color: FishUI.Theme.highlightColor + z: 99 + visible: false + border.width: 5 + border.color: Qt.rgba(FishUI.Theme.highlightColor.r, + FishUI.Theme.highlightColor.g, + FishUI.Theme.highlightColor.b, 0.5) + + function show(x, y) { + dot.x = x - dot.width / 2 + dot.y = y - dot.height / 2 + dot.visible = true + } + } + + Item { + id: _popupItem + width: 200 + height: _popupLayout.implicitHeight + FishUI.Units.largeSpacing + z: 100 + + opacity: _view.count > 0 ? 1.0 : 0.0 + + Behavior on opacity { + NumberAnimation { duration: 200 } + } + + Rectangle { + anchors.fill: parent + color: FishUI.Theme.secondBackgroundColor + radius: FishUI.Theme.mediumRadius + border.width: 1 + border.color: Qt.rgba(FishUI.Theme.textColor.r, + FishUI.Theme.textColor.g, + FishUI.Theme.textColor.b, 0.2) + } + + ColumnLayout { + id: _popupLayout + anchors.fill: parent + anchors.margins: FishUI.Units.smallSpacing + + ListView { + id: _view + clip: true + Layout.fillWidth: true + Layout.preferredHeight: itemSize * _view.count + model: timeZoneMap.availableList + + property int itemSize: 30 + + delegate: Item { + id: _item + width: ListView.view.width + height: _view.itemSize + + Rectangle { + anchors.fill: parent + radius: FishUI.Theme.mediumRadius + color: FishUI.Theme.highlightColor + visible: index === _view.currentIndex + opacity: 0.8 + } + + MouseArea { + anchors.fill: parent + anchors.margins: 2 + onClicked: _view.currentIndex = index + } + + RowLayout { + anchors.fill: parent + + Label { + Layout.alignment: Qt.AlignCenter + elide: Label.ElideRight + text: modelData + color: index === _view.currentIndex ? FishUI.Theme.highlightedTextColor : FishUI.Theme.textColor + } + } + } + } + + Button { + Layout.preferredHeight: _view.itemSize + Layout.fillWidth: true + text: qsTr("Set") + onClicked: { + _popupItem.opacity = 0 + timeZoneMap.setTimeZone(timeZoneMap.availableList[_view.currentIndex]) + } + } + } + } +} diff --git a/src/qml/ItemPage.qml b/src/qml/ItemPage.qml index e05a5b8..9484b7e 100644 --- a/src/qml/ItemPage.qml +++ b/src/qml/ItemPage.qml @@ -35,10 +35,10 @@ Page { height: rootWindow.header.height Label { - anchors.horizontalCenter: parent.horizontalCenter +// anchors.horizontalCenter: parent.horizontalCenter -// anchors.fill: parent -// leftPadding: FishUI.Units.largeSpacing * 2 + anchors.fill: parent + leftPadding: FishUI.Units.largeSpacing * 3 topPadding: FishUI.Units.largeSpacing bottomPadding: 0 font.pointSize: 12 diff --git a/src/qml/RoundedItem.qml b/src/qml/RoundedItem.qml index 5c17bf5..2414b1e 100644 --- a/src/qml/RoundedItem.qml +++ b/src/qml/RoundedItem.qml @@ -38,8 +38,8 @@ Rectangle { ColumnLayout { id: _mainLayout anchors.fill: parent - anchors.leftMargin: FishUI.Units.largeSpacing - anchors.rightMargin: FishUI.Units.largeSpacing + anchors.leftMargin: FishUI.Units.largeSpacing * 1.5 + anchors.rightMargin: FishUI.Units.largeSpacing * 1.5 anchors.topMargin: FishUI.Units.largeSpacing anchors.bottomMargin: FishUI.Units.largeSpacing spacing: FishUI.Units.largeSpacing diff --git a/src/qml/SideBar.qml b/src/qml/SideBar.qml index 4ded3e5..1604087 100644 --- a/src/qml/SideBar.qml +++ b/src/qml/SideBar.qml @@ -139,10 +139,10 @@ Item { ListElement { title: qsTr("Mouse") - name: "cursor" + name: "mouse" page: "qrc:/qml/Cursor/Main.qml" iconSource: "cursor.svg" - iconColor: "#0D9BF1" + iconColor: "#3385FF" category: qsTr("System") } @@ -155,6 +155,15 @@ Item { // category: qsTr("System") // } + ListElement { + title: qsTr("Date & Time") + name: "datetime" + page: "qrc:/qml/DateTime/Main.qml" + iconSource: "datetime.svg" + iconColor: "#418CFF" + category: qsTr("System") + } + ListElement { title: qsTr("Language") name: "language" @@ -309,7 +318,7 @@ Item { source: "qrc:/images/sidebar/dark/" + model.iconSource sourceSize: Qt.size(width, height) Layout.alignment: Qt.AlignVCenter - antialiasing: true + antialiasing: false smooth: false } } diff --git a/src/resources.qrc b/src/resources.qrc index ad22d43..3b244a3 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -110,5 +110,10 @@ qml/Application/Main.qml qml/Cursor/Main.qml images/sidebar/dark/cursor.svg + qml/DateTime/Main.qml + qml/DateTime/TimeZoneDialog.qml + images/light/world.svg + images/dark/world.svg + images/sidebar/dark/datetime.svg diff --git a/src/timezonedata.h b/src/timezonedata.h new file mode 100644 index 0000000..314a302 --- /dev/null +++ b/src/timezonedata.h @@ -0,0 +1,4 @@ +#ifndef TIMEZONEDATA_H +#define TIMEZONEDATA_H + +#endif // TIMEZONEDATA_H diff --git a/translations/en_US.ts b/translations/en_US.ts index 4566365..bc8dfc1 100644 --- a/translations/en_US.ts +++ b/translations/en_US.ts @@ -132,12 +132,12 @@ - + Dim the wallpaper in dark theme - + Accent color @@ -518,6 +518,16 @@ Pointer speed + + + Date & Time + + + + + Time Zone + + QObject @@ -616,30 +626,44 @@ + System - Language + Date & Time - Battery + Language - Power + Battery + Power + + + + About + + TimeZoneDialog + + + Set + + + UserDelegateItem diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index d7cbccb..4c4ce9e 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -132,12 +132,12 @@ 深色模式 - + Dim the wallpaper in dark theme 在深色模式下调暗壁纸 - + Accent color 强调色 @@ -390,10 +390,6 @@ Power Save 省电模式 - - Balance - 均衡 - Performance @@ -523,8 +519,14 @@ 指针速度 - Speed - 鼠标速度 + + Date & Time + 日期和时间 + + + + Time Zone + 时区 @@ -624,30 +626,44 @@ + System 系统 + Date & Time + 日期和时间 + + + Language 语言 - + Battery 电池 - + Power 电源 - + About 关于 + + TimeZoneDialog + + + Set + 设置 + + UserDelegateItem