Implement new system time api

This commit is contained in:
Michael Zanetti 2019-12-15 12:43:14 +01:00
parent 1513f79910
commit 187d306a0b
9 changed files with 676 additions and 120 deletions

View File

@ -32,8 +32,6 @@ void NymeaConfiguration::init()
m_webSocketServerConfigurations->clear();
m_mqttServerConfigurations->clear();
m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse");
m_client->sendCommand("Configuration.GetAvailableLanguages", this, "getAvailableLanguagesResponse");
m_client->sendCommand("Configuration.GetTimeZones", this, "getTimezonesResponse");
m_client->sendCommand("Configuration.GetMqttServerConfigurations", this, "getMqttServerConfigsReply");
m_client->sendCommand("Configuration.GetMqttPolicies", this, "getMqttPoliciesReply");
}
@ -50,38 +48,11 @@ void NymeaConfiguration::setServerName(const QString &serverName)
m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse");
}
QString NymeaConfiguration::language() const
{
return m_language;
}
void NymeaConfiguration::setLanguage(const QString &language)
{
QVariantMap params;
params.insert("language", language);
m_client->sendCommand("Configuration.SetLanguage", params);
}
QStringList NymeaConfiguration::availableLanguages() const
{
return m_availableLanguages;
}
QString NymeaConfiguration::timezone() const
{
return m_timezone;
}
void NymeaConfiguration::setTimezone(const QString &timezone)
{
QVariantMap params;
params.insert("timeZone", timezone);
m_client->sendCommand("Configuration.SetTimeZone", params, this, "setTimezoneResponse");
}
QStringList NymeaConfiguration::timezones() const
{
return m_timezones;
m_client->sendCommand("System.SetTimeZone", params, this, "setTimezoneResponse");
}
bool NymeaConfiguration::debugServerEnabled() const
@ -259,10 +230,6 @@ void NymeaConfiguration::getConfigurationsResponse(const QVariantMap &params)
emit debugServerEnabledChanged();
m_serverName = basicConfig.value("serverName").toString();
emit serverNameChanged();
m_language = basicConfig.value("language").toString();
emit languageChanged();
m_timezone = basicConfig.value("timeZone").toString();
emit timezoneChanged();
QVariantMap cloudConfig = params.value("params").toMap().value("cloud").toMap();
m_cloudEnabled = cloudConfig.value("enabled").toBool();
emit cloudEnabledChanged();
@ -290,25 +257,6 @@ void NymeaConfiguration::getConfigurationsResponse(const QVariantMap &params)
}
}
void NymeaConfiguration::getAvailableLanguagesResponse(const QVariantMap &params)
{
// qDebug() << "available languages" << params;
m_availableLanguages = params.value("params").toMap().value("languages").toStringList();
emit availableLanguagesChanged();
}
void NymeaConfiguration::getTimezonesResponse(const QVariantMap &params)
{
// qDebug() << "Get timezones response" << params;
m_timezones = params.value("params").toMap().value("timeZones").toStringList();
emit timezonesChanged();
}
void NymeaConfiguration::setTimezoneResponse(const QVariantMap &params)
{
qDebug() << "Set timezones response" << params;
}
void NymeaConfiguration::setServerNameResponse(const QVariantMap &params)
{
qDebug() << "Server name set:" << params;
@ -416,10 +364,6 @@ void NymeaConfiguration::notificationReceived(const QVariantMap &notification)
emit debugServerEnabledChanged();
m_serverName = params.value("serverName").toString();
emit serverNameChanged();
m_language = params.value("language").toString();
emit languageChanged();
m_timezone = params.value("timeZone").toString();
emit timezoneChanged();
return;
}
if (notif == "Configuration.CloudConfigurationChanged") {

View File

@ -19,12 +19,6 @@ class NymeaConfiguration : public JsonHandler
Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged)
Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged)
Q_PROPERTY(QStringList availableLanguages READ availableLanguages NOTIFY availableLanguagesChanged)
Q_PROPERTY(QString timezone READ timezone WRITE setTimezone NOTIFY timezoneChanged)
Q_PROPERTY(QStringList timezones READ timezones NOTIFY timezonesChanged)
Q_PROPERTY(bool cloudEnabled READ cloudEnabled WRITE setCloudEnabled NOTIFY cloudEnabledChanged)
Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged)
@ -87,9 +81,6 @@ private:
Q_INVOKABLE void setDebugServerEnabledResponse(const QVariantMap &params);
Q_INVOKABLE void setServerNameResponse(const QVariantMap &params);
Q_INVOKABLE void setCloudEnabledResponse(const QVariantMap &params);
Q_INVOKABLE void getAvailableLanguagesResponse(const QVariantMap &params);
Q_INVOKABLE void getTimezonesResponse(const QVariantMap &params);
Q_INVOKABLE void setTimezoneResponse(const QVariantMap &params);
Q_INVOKABLE void setTcpConfigReply(const QVariantMap &params);
Q_INVOKABLE void deleteTcpConfigReply(const QVariantMap &params);
Q_INVOKABLE void setWebSocketConfigReply(const QVariantMap &params);
@ -108,10 +99,6 @@ private:
signals:
void debugServerEnabledChanged();
void serverNameChanged();
void languageChanged();
void availableLanguagesChanged();
void timezoneChanged();
void timezonesChanged();
void cloudEnabledChanged();
private:
@ -119,10 +106,6 @@ private:
bool m_debugServerEnabled = false;
QString m_serverName;
QString m_language;
QStringList m_availableLanguages;
QString m_timezone;
QStringList m_timezones;
bool m_cloudEnabled = false;
ServerConfigurations *m_tcpServerConfigurations = nullptr;

View File

@ -5,6 +5,8 @@
#include "types/packages.h"
#include "types/repositories.h"
#include <QTimeZone>
SystemController::SystemController(JsonRpcClient *jsonRpcClient, QObject *parent):
JsonHandler(parent),
m_jsonRpcClient(jsonRpcClient)
@ -12,6 +14,8 @@ SystemController::SystemController(JsonRpcClient *jsonRpcClient, QObject *parent
m_jsonRpcClient->registerNotificationHandler(this, "notificationReceived");
m_packages = new Packages(this);
m_repositories = new Repositories(this);
startTimer(1000, Qt::VeryCoarseTimer);
}
void SystemController::init()
@ -22,6 +26,8 @@ void SystemController::init()
m_jsonRpcClient->sendCommand("System.GetCapabilities", this, "getCapabilitiesResponse");
} else {
m_powerManagementAvailable = false;
m_updateManagementAvailable = false;
m_timeManagementAvailable = false;
}
}
@ -101,6 +107,63 @@ int SystemController::enableRepository(const QString &id, bool enabled)
return m_jsonRpcClient->sendCommand("System.EnableRepository", params, this, "enableRepositoryResponse");
}
bool SystemController::timeManagementAvailable() const
{
return m_timeManagementAvailable;
}
QDateTime SystemController::serverTime() const
{
return m_serverTime;
}
void SystemController::setServerTime(const QDateTime &serverTime)
{
QVariantMap params;
params.insert("automaticTime", false);
params.insert("time", serverTime.toSecsSinceEpoch());
params.insert("timeZone", serverTime.timeZone().id());
m_jsonRpcClient->sendCommand("System.SetTime", params, this, "setTimeResponse");
}
QStringList SystemController::timeZones() const
{
QStringList ret;
foreach (const QByteArray &tzId, QTimeZone::availableTimeZoneIds()) {
ret << tzId;
}
return ret;
}
QString SystemController::serverTimeZone() const
{
return m_serverTime.timeZone().id();
}
void SystemController::setServerTimeZone(const QString &serverTimeZone)
{
QVariantMap params;
params.insert("timeZone", serverTimeZone);
m_jsonRpcClient->sendCommand("System.SetTime", params, this, "setTimeResponse");
}
bool SystemController::automaticTimeAvailable() const
{
return m_automaticTimeAvailable;
}
bool SystemController::automaticTime() const
{
return m_automaticTime;
}
void SystemController::setAutomaticTime(bool automaticTime)
{
QVariantMap params;
params.insert("automaticTime", automaticTime);
m_jsonRpcClient->sendCommand("System.SetTime", params, this, "setTimeResponse");
}
void SystemController::getCapabilitiesResponse(const QVariantMap &data)
{
qDebug() << "capabilities received" << data;
@ -110,11 +173,18 @@ void SystemController::getCapabilitiesResponse(const QVariantMap &data)
m_updateManagementAvailable = data.value("params").toMap().value("updateManagement").toBool();
emit updateManagementAvailableChanged();
m_timeManagementAvailable = data.value("params").toMap().value("timeManagement").toBool();
emit timeManagementAvailableChanged();
if (m_updateManagementAvailable) {
m_jsonRpcClient->sendCommand("System.GetUpdateStatus", this, "getUpdateStatusResponse");
m_jsonRpcClient->sendCommand("System.GetPackages", this, "getPackagesResponse");
m_jsonRpcClient->sendCommand("System.GetRepositories", this, "getRepositoriesResponse");
}
// if (m_jsonRpcClient->ensureServerVersion("4.1")) {
m_jsonRpcClient->sendCommand("System.GetTime", this, "getServerTimeResponse");
// }
}
void SystemController::getUpdateStatusResponse(const QVariantMap &data)
@ -164,6 +234,24 @@ void SystemController::enableRepositoryResponse(const QVariantMap &params)
emit enableRepositoryFinished(params.value("id").toInt(), params.value("params").toMap().value("success").toBool());
}
void SystemController::getServerTimeResponse(const QVariantMap &params)
{
qDebug() << "Server time" << params;
m_serverTime = QDateTime::fromSecsSinceEpoch(params.value("params").toMap().value("time").toUInt());
m_serverTime.setTimeZone(QTimeZone(params.value("params").toMap().value("timeZone").toString().toUtf8()));
emit serverTimeChanged();
emit serverTimeZoneChanged();
m_automaticTimeAvailable = params.value("params").toMap().value("automaticTimeAvailable").toBool();
emit automaticTimeAvailableChanged();
m_automaticTime = params.value("params").toMap().value("automaticTime").toBool();
emit automaticTimeChanged();
}
void SystemController::setTimeResponse(const QVariantMap &params)
{
qDebug() << "set time response" << params;
}
void SystemController::notificationReceived(const QVariantMap &data)
{
QString notification = data.value("notification").toString();
@ -233,7 +321,24 @@ void SystemController::notificationReceived(const QVariantMap &data)
qWarning() << "System capabilites changed: power management:" << m_powerManagementAvailable << "update management:" << m_updateManagementAvailable;
emit powerManagementAvailableChanged();
emit updateManagementAvailableChanged();
} else if (notification == "System.TimeConfigurationChanged") {
qDebug() << "System time configuration changed";
m_serverTime = QDateTime::fromSecsSinceEpoch(data.value("params").toMap().value("time").toUInt());
m_serverTime.setTimeZone(QTimeZone(data.value("params").toMap().value("timeZone").toByteArray()));
emit serverTimeChanged();
emit serverTimeZoneChanged();
m_automaticTimeAvailable = data.value("params").toMap().value("automaticTimeAvailable").toBool();
emit automaticTimeAvailableChanged();
m_automaticTime = data.value("params").toMap().value("automaticTime").toBool();
emit automaticTimeChanged();
} else {
qWarning() << "Unhandled System Notification" << data.value("notification");
}
}
void SystemController::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event)
m_serverTime = m_serverTime.addSecs(1);
emit serverTimeChanged();
}

View File

@ -14,12 +14,19 @@ class SystemController : public JsonHandler
Q_PROPERTY(bool powerManagementAvailable READ powerManagementAvailable NOTIFY powerManagementAvailableChanged)
// Whether the update mechanism is available in the connected core
Q_PROPERTY(bool updateManagementAvailable READ updateManagementAvailable NOTIFY updateManagementAvailableChanged)
Q_PROPERTY(bool timeManagementAvailable READ timeManagementAvailable NOTIFY timeManagementAvailableChanged)
Q_PROPERTY(bool updateManagementBusy READ updateManagementBusy NOTIFY updateManagementBusyChanged)
Q_PROPERTY(bool updateRunning READ updateRunning NOTIFY updateRunningChanged)
Q_PROPERTY(Packages* packages READ packages CONSTANT)
Q_PROPERTY(Repositories* repositories READ repositories CONSTANT)
Q_PROPERTY(QDateTime serverTime READ serverTime WRITE setServerTime NOTIFY serverTimeChanged)
Q_PROPERTY(QString serverTimeZone READ serverTimeZone WRITE setServerTimeZone NOTIFY serverTimeZoneChanged)
Q_PROPERTY(QStringList timeZones READ timeZones CONSTANT)
Q_PROPERTY(bool automaticTimeAvailable READ automaticTimeAvailable NOTIFY automaticTimeAvailableChanged)
Q_PROPERTY(bool automaticTime READ automaticTime WRITE setAutomaticTime NOTIFY automaticTimeChanged)
public:
explicit SystemController(JsonRpcClient *jsonRpcClient, QObject *parent = nullptr);
@ -27,29 +34,40 @@ public:
QString nameSpace() const override;
bool powerManagementAvailable() const;
bool updateManagementAvailable() const;
Q_INVOKABLE void reboot();
Q_INVOKABLE void shutdown();
bool updateManagementAvailable() const;
bool updateManagementBusy() const;
bool updateRunning() const;
Q_INVOKABLE void checkForUpdates();
Packages* packages() const;
Q_INVOKABLE void updatePackages(const QString packageId = QString());
Q_INVOKABLE void removePackages(const QString packageId = QString());
Repositories* repositories() const;
Q_INVOKABLE int enableRepository(const QString &id, bool enabled);
bool timeManagementAvailable() const;
QDateTime serverTime() const;
void setServerTime(const QDateTime &serverTime);
QStringList timeZones() const;
QString serverTimeZone() const;
void setServerTimeZone(const QString &serverTimeZone);
bool automaticTimeAvailable() const;
bool automaticTime() const;
void setAutomaticTime(bool automaticTime);
signals:
void powerManagementAvailableChanged();
void updateManagementAvailableChanged();
void timeManagementAvailableChanged();
void updateManagementBusyChanged();
void updateRunningChanged();
void enableRepositoryFinished(int id, bool success);
void serverTimeChanged();
void serverTimeZoneChanged();
void automaticTimeAvailableChanged();
void automaticTimeChanged();
private slots:
void getCapabilitiesResponse(const QVariantMap &data);
@ -58,19 +76,31 @@ private slots:
void getRepositoriesResponse(const QVariantMap &data);
void removePackageResponse(const QVariantMap &params);
void enableRepositoryResponse(const QVariantMap &params);
void getServerTimeResponse(const QVariantMap &params);
void setTimeResponse(const QVariantMap &params);
void notificationReceived(const QVariantMap &data);
protected:
void timerEvent(QTimerEvent *event) override;
private:
JsonRpcClient *m_jsonRpcClient = nullptr;
bool m_powerManagementAvailable = false;
bool m_updateManagementAvailable = false;
bool m_timeManagementAvailable = false;
bool m_updateManagementBusy = false;
bool m_updateRunning = false;
Packages *m_packages = nullptr;
Repositories *m_repositories = nullptr;
QDateTime m_serverTime;
QStringList m_timeZones;
bool m_automaticTimeAvailable = false;
bool m_automaticTime = false;
};
#endif // SYSTEMCONTROLLER_H

View File

@ -80,7 +80,7 @@ void PlatformHelperAndroid::vibrate(PlatformHelper::HapticsFeedback feedbackType
int duration;
switch (feedbackType) {
case HapticsFeedbackSelection:
duration = 20;
duration = 10;
break;
case HapticsFeedbackImpact:
duration = 30;

View File

@ -201,5 +201,7 @@
<file>ui/mainviews/GroupsView.qml</file>
<file>ui/grouping/GroupPage.qml</file>
<file>ui/delegates/ThingTile.qml</file>
<file>ui/components/TimePicker.qml</file>
<file>ui/components/DatePicker.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,134 @@
import QtQuick 2.3
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import Nymea 1.0
ColumnLayout {
id: root
property date date
RowLayout {
Layout.fillWidth: true
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "../images/back.svg"
MouseArea {
anchors.fill: parent
onClicked: {
var newDate = new Date(root.date)
newDate.setMonth(root.date.getMonth() - 1)
root.date = newDate
}
}
}
Label {
text: root.date.toLocaleDateString()
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
}
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
name: "../images/next.svg"
MouseArea {
anchors.fill: parent
onClicked: {
var newDate = new Date(root.date)
newDate.setMonth(root.date.getMonth() + 1)
root.date = newDate
}
}
}
}
ThinDivider {}
ListModel {
id: monthModel
ListElement { text: qsTr("January"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("February"); days: 28; leapYearDays: 29 }
ListElement { text: qsTr("March"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("April"); days: 30; leapYearDays: 30 }
ListElement { text: qsTr("May"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("June"); days: 30; leapYearDays: 30 }
ListElement { text: qsTr("July"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("August"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("September"); days: 30; leapYearDays: 30 }
ListElement { text: qsTr("October"); days: 31; leapYearDays: 31 }
ListElement { text: qsTr("November"); days: 30; leapYearDays: 30 }
ListElement { text: qsTr("December"); days: 31; leapYearDays: 31 }
}
ListModel {
id: weekModel
ListElement { text: qsTr("Mon") }
ListElement { text: qsTr("Tue") }
ListElement { text: qsTr("Wed") }
ListElement { text: qsTr("Thu") }
ListElement { text: qsTr("Fri") }
ListElement { text: qsTr("Sat") }
ListElement { text: qsTr("Sun") }
}
RowLayout {
Repeater {
model: weekModel
Item {
Layout.fillWidth: true
Layout.preferredHeight: width
Label {
anchors.centerIn: parent
text: model.text
}
}
}
}
GridLayout {
id: daysGrid
Layout.fillWidth: true
Layout.fillHeight: true
columns: 7
columnSpacing: 0
rowSpacing: 0
property date firstOfMonth: new Date(root.date.getFullYear(), root.date.getMonth(), 1)
property int offset: ((firstOfMonth.getDay() - 1) % 7 + 7) % 7
property bool isLeapYear: false
property int daysInMonth: isLeapYear ? monthModel.get(root.date.getMonth()).leapDays : monthModel.get(root.date.getMonth()).days
property int daysInPreviousMonth: isLeapYear ? monthModel.get((root.date.getMonth() + 11) % 12).leapDays : monthModel.get((root.date.getMonth() + 11) % 12).days
Repeater {
model: 6 * 7
delegate: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: width
radius: width / 2
property int dayOfMonth: index - daysGrid.offset + 1
property bool isPreviousMonth: dayOfMonth < 1
property bool isNextMonth: dayOfMonth > daysGrid.daysInMonth
property int correctedDayOfMonth: isPreviousMonth ? daysGrid.daysInPreviousMonth + dayOfMonth
: isNextMonth ? dayOfMonth - daysGrid.daysInMonth : dayOfMonth
color: !isPreviousMonth && !isNextMonth && correctedDayOfMonth == root.date.getDate() ? app.accentColor : "transparent"
Label {
anchors.centerIn: parent
opacity: isPreviousMonth || isNextMonth ? 0.6 : 1
text: correctedDayOfMonth
}
MouseArea {
anchors.fill: parent
onClicked: {
var newDate = new Date(root.date)
newDate.setDate(dayOfMonth)
root.date = newDate
}
}
}
}
}
}

View File

@ -0,0 +1,261 @@
import QtQuick 2.3
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import Nymea 1.0
ColumnLayout {
id: root
spacing: app.margins
property int hour: 0
property int minute: 0
function selectHours() {
d.mode = "hours"
}
function selectMinutes() {
d.mode = "minutes"
}
Component.onCompleted: {
initTimer.start();
}
Timer {
id: initTimer
interval: 1
onTriggered: selectHours();
}
Row {
Layout.alignment: Qt.AlignHCenter
Label {
text: app.pad(root.hour, 2)
font.pixelSize: app.largeFont * 2
opacity: d.mode == "hours" ? 1 : .6
Behavior on opacity { NumberAnimation {duration: 250 } }
MouseArea {
anchors.fill: parent
onClicked: selectHours()
}
}
Label {
text: ":"
font.pixelSize: app.largeFont * 2
}
Label {
text: app.pad(root.minute, 2)
font.pixelSize: app.largeFont * 2
opacity: d.mode == "minutes" ? 1 : .6
Behavior on opacity { NumberAnimation {duration: 250 } }
MouseArea {
anchors.fill: parent
onClicked: selectMinutes()
}
}
}
Item {
id: d
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredHeight: width
property string mode: "none"
Item {
id: dial
height: Math.min(parent.height, parent.width)
width: height
anchors.centerIn: parent
Repeater {
id: hours12
model: 12
delegate: Item {
id: delegate
visible: d.mode == "hours"
anchors.centerIn: parent
height: parent.height
rotation: (360 / 12) * (index + 1)
width: 30
property alias field: fieldItem
Item {
id: fieldItem
anchors { left: parent.left; top: parent.top; right: parent.right }
height: width
Label {
anchors.centerIn: parent
text: index + 1
rotation: -delegate.rotation
}
}
}
}
Repeater {
id: hours24
property int selectedIndex: root.hour - 12
model: 12
delegate: Item {
id: delegate
visible: d.mode == "hours"
anchors.centerIn: parent
height: parent.height - 80
rotation: (360 / 12) * (index + 12)
width: 30
property alias field: fieldItem
Item {
id: fieldItem
anchors { left: parent.left; top: parent.top; right: parent.right }
height: width
Label {
anchors.centerIn: parent
text: index + 12 == 12 ? "00" : index + 12
rotation: -delegate.rotation
opacity: .8
}
}
}
}
Repeater {
id: minutes
property int selectedIndex: 0
readonly property int selectedMinute: selectedIndex
model: 60
delegate: Item {
id: delegate
visible: d.mode == "minutes"
anchors.centerIn: parent
height: parent.height
rotation: (360 / 60) * (index)
width: 30
property alias field: fieldItem
Item {
id: fieldItem
anchors { left: parent.left; top: parent.top; right: parent.right }
height: width
Label {
anchors.centerIn: parent
text: index
rotation: -delegate.rotation
visible: index % 5 == 0
}
}
}
}
Item {
id: newDot
height: (parent.height + 10) - (d.mode == "hours" && (root.hour == 0 || root.hour > 12) ? 80 : 0)
width: 40
anchors.centerIn: parent
z: -1
rotation: {
if (d.mode == "hours") {
if (root.hour > 0 && root.hour < 13) {
return root.hour * 360 / 12
}
return (root.hour - 12 % 12) * 360 / 12
}
return root.minute * 360 / 60
}
Behavior on height { NumberAnimation { duration: 100 } }
Behavior on rotation { RotationAnimation { duration: 100; direction: RotationAnimation.Shortest } }
Rectangle {
anchors { left: parent.left; top: parent.top; right: parent.right }
height: width
color: app.accentColor
radius: width / 2
}
Rectangle {
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: 5
height: parent.height / 2
color: app.accentColor
radius: width / 2
}
}
MouseArea {
anchors.fill: parent
onPressed: {
update();
}
onPositionChanged: update();
onReleased: {
if (d.mode == "hours") {
selectMinutes();
}
}
function update() {
var angle = calculateAngle(mouseX, mouseY);
var items = d.mode == "hours" ? 12 : 60
// angle : 360 = num : 12
var selected = Math.round(angle * items / 360) % items;
if (d.mode == "hours") {
if (calculateDistanceToCenter(mouseX, mouseY) < (width / 2) - 40) {
selected = selected + 12
}
// swap 12 and 00
if (selected === 12) {
selected = 0
} else if (selected === 0) {
selected = 12
}
if (root.hour !== selected) {
root.hour = selected
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
}
} else {
if (root.minute !== selected) {
root.minute = selected
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
}
}
}
function calculateAngle(mouseX, mouseY) {
// transform coords to center of dial
mouseX -= width / 2
mouseY -= height / 2
var rad = Math.atan(mouseY / mouseX);
var angle = rad * 180 / Math.PI
angle += 90;
if (mouseX < 0 && mouseY >= 0) angle = 180 + angle;
if (mouseX < 0 && mouseY < 0) angle = 180 + angle;
return angle;
}
function calculateDistanceToCenter(mouseX, mouseY) {
var a = mouseY - (height / 2)
var b = mouseX - (width / 2)
var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2))
return c;
}
}
}
}
}

View File

@ -8,20 +8,18 @@ import "../components"
Page {
id: root
header: NymeaHeader {
text: qsTr("Box settings")
text: qsTr("General settings")
backButtonVisible: true
onBackPressed: pageStack.pop()
}
ColumnLayout {
id: settingsColumn
anchors { left: parent.left; right: parent.right; top: parent.top }
id: settingsGrid
anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; margins: app.margins }
width: Math.min(500, parent.width - app.margins * 2)
RowLayout {
Layout.fillWidth: true
Layout.topMargin: app.margins
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
spacing: app.margins
Label {
text: qsTr("Name")
@ -40,63 +38,119 @@ Page {
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
spacing: app.margins
visible: engine.systemController.automaticTimeAvailable
Label {
text: qsTr("Set date and time automatically")
Layout.fillWidth: true
text: qsTr("Language")
}
ComboBox {
id: languageBox
Layout.fillWidth: true
model: engine.nymeaConfiguration.availableLanguages
currentIndex: model.indexOf(engine.nymeaConfiguration.language)
contentItem: Label {
leftPadding: app.margins / 2
text: Qt.locale(languageBox.displayText).nativeLanguageName + " (" + Qt.locale(languageBox.displayText).nativeCountryName + ")"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
delegate: ItemDelegate {
width: languageBox.width
contentItem: Label {
text: Qt.locale(modelData).nativeLanguageName + " (" + Qt.locale(modelData).nativeCountryName + ")"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: languageBox.highlightedIndex === index
}
onActivated: {
engine.nymeaConfiguration.language = currentText;
CheckBox {
checked: engine.systemController.automaticTime
onClicked: {
engine.systemController.automaticTime = checked
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
spacing: app.margins
Layout.preferredHeight: dateButton.implicitHeight
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
Label {
text: qsTr("Date")
Layout.fillWidth: true
}
Label {
text: engine.systemController.serverTime.toLocaleDateString()
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
}
Button {
id: dateButton
visible: !engine.systemController.automaticTime && engine.systemController.timeManagementAvailable
contentItem: Item {
ColorIcon {
name: "../images/edit.svg"
color: app.foregroundColor
anchors.centerIn: parent
height: parent.height
width: height
}
}
onClicked: {
var popup = datePickerComponent.createObject(root, {dateTime: engine.systemController.serverTime})
popup.accepted.connect(function() {
print("setting new date", popup.dateTime)
engine.systemController.serverTime = popup.dateTime
})
popup.open();
}
}
}
RowLayout {
Layout.fillWidth: true
spacing: app.margins
Layout.preferredHeight: timeButton.implicitHeight
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
Label {
text: qsTr("Time")
Layout.fillWidth: true
}
Label {
text: engine.systemController.serverTime.toLocaleTimeString(/*Locale.ShortTimeString*/)
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
}
Button {
id: timeButton
visible: !engine.systemController.automaticTime && engine.systemController.timeManagementAvailable
contentItem: Item {
ColorIcon {
name: "../images/edit.svg"
color: app.foregroundColor
anchors.centerIn: parent
height: parent.height
width: height
}
}
onClicked: {
var popup = timePickerComponent.createObject(root, {hour: engine.systemController.serverTime.getHours(), minute: engine.systemController.serverTime.getMinutes()})
popup.accepted.connect(function() {
var date = new Date(engine.systemController.serverTime)
date.setHours(popup.hour);
date.setMinutes(popup.minute)
engine.systemController.serverTime = date;
})
popup.open();
}
}
}
RowLayout {
Layout.fillWidth: true
spacing: app.margins
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
Label {
Layout.fillWidth: true
text: qsTr("Time zone")
}
ComboBox {
Layout.minimumWidth: 200
model: engine.nymeaConfiguration.timezones
currentIndex: model.indexOf(engine.nymeaConfiguration.timezone)
model: engine.systemController.timeZones
currentIndex: model.indexOf(engine.systemController.serverTimeZone)
onActivated: {
engine.nymeaConfiguration.timezone = currentText;
engine.systemController.serverTimeZone = currentText;
}
}
}
Button {
Layout.fillWidth: true
Layout.margins: app.margins
text: qsTr("Reboot %1:core").arg(app.systemName)
visible: engine.systemController.powerManagementAvailable
onClicked: {
@ -117,7 +171,6 @@ Page {
}
Button {
Layout.fillWidth: true
Layout.margins: app.margins
text: qsTr("Shutdown %1:core").arg(app.systemName)
visible: engine.systemController.powerManagementAvailable
onClicked: {
@ -137,4 +190,48 @@ Page {
}
}
}
Component {
id: timePickerComponent
Dialog {
id: timePicker
property int maxSize: Math.min(parent.width, parent.height)
property int size: Math.min(maxSize, 500)
property alias hour: p.hour
property alias minute: p.minute
width: size - 80
height: size
x: (parent.width - width) / 2
y: (parent.height - height) / 2
TimePicker {
id: p
width: parent.width
height: parent.height
}
standardButtons: Dialog.Ok | Dialog.Cancel
}
}
Component {
id: datePickerComponent
Dialog {
id: datePicker
property int maxSize: Math.min(parent.width, parent.height)
property int size: Math.min(maxSize, 500)
property alias dateTime: p.date
width: size - 80
height: size
x: (parent.width - width) / 2
y: (parent.height - height) / 2
DatePicker {
id: p
width: parent.width
height: parent.height
date: datePicker.dateTime
}
standardButtons: Dialog.Ok | Dialog.Cancel
}
}
}