on xenial help sign in
battery/network status indicators for the wizard
commit55846088945541b92ccd107258c67c4357f8bbfb authorLukáš Tinkl <lukas.tinkl@canonical.com> dateTue 8 Sep 2015, 15:33 (11 years ago) parentc823f1a
9 files changed+292−4
plugins/Wizard/CMakeLists.txt+1 plugins/Wizard/Status.cpp+147 plugins/Wizard/Status.h+60 plugins/Wizard/System.cpp+1−1 plugins/Wizard/System.h+2−1 plugins/Wizard/plugin.cpp+9 qml/Wizard/Page.qml+61−1 tests/mocks/Wizard/CMakeLists.txt+2−1 tests/mocks/Wizard/mockplugin.cpp+9
plugins/Wizard/CMakeLists.txt+1
@@ -4,6 +4,7 @@ add_library(Wizard-qml MODULE
44 System.cpp
55 LocalePlugin.cpp
66 timezonemodel.cpp
7+ Status.cpp
78)
89
910qt5_use_modules(Wizard-qml DBus Qml)
plugins/Wizard/Status.cppnew file+147
@@ -0,0 +1,147 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QDebug>
18+#include <QDBusConnection>
19+
20+#include "Status.h"
21+
22+Status::Status()
23+{
24+ initNM();
25+ initUPower();
26+}
27+
28+void Status::initNM()
29+{
30+ m_nmIface = new QDBusInterface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager",
31+ QDBusConnection::systemBus(), this);
32+
33+ QDBusConnection::systemBus().connect("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "PropertiesChanged",
34+ this, SLOT(onNMPropertiesChanged(QVariantMap)));
35+}
36+
37+void Status::onNMPropertiesChanged(const QVariantMap &changedProps)
38+{
39+ if (changedProps.contains("State") || changedProps.contains("Connectivity")) {
40+ Q_EMIT onlineChanged();
41+ Q_EMIT networkIconChanged();
42+ }
43+
44+ if (changedProps.contains("PrimaryConnection") || changedProps.contains("SpecificObject") || changedProps.contains("Strength")) {
45+ Q_EMIT networkIconChanged();
46+ }
47+}
48+
49+bool Status::online() const
50+{
51+ if (!m_nmIface->isValid())
52+ return false;
53+
54+ return m_nmIface->property("State").toUInt() == 70;
55+}
56+
57+QString Status::networkIcon()
58+{
59+ QString iconName = QStringLiteral("nm-no-connection");
60+
61+ if (!online()) {
62+ return iconName;
63+ }
64+
65+ const QString primaryConn = m_nmIface->property("PrimaryConnection").value<QDBusObjectPath>().path();
66+ const QString primaryConnType = m_nmIface->property("PrimaryConnectionType").toString();
67+
68+ qDebug() << "NM init, primary connection type:" << primaryConnType << ", connection:" << primaryConn;
69+
70+ if (primaryConn.isEmpty()) {
71+ qWarning() << "Empty primary connection";
72+ return iconName;
73+ }
74+
75+ if (primaryConnType == "802-11-wireless") {
76+ QDBusInterface activeConn("org.freedesktop.NetworkManager", primaryConn, "org.freedesktop.NetworkManager.Connection.Active", QDBusConnection::systemBus());
77+
78+ if (activeConn.isValid()) {
79+ const QString apPath = activeConn.property("SpecificObject").value<QDBusObjectPath>().path();
80+ qDebug() << "AP path:" << apPath;
81+
82+ if (apPath.isEmpty()) {
83+ qWarning() << "No AP path";
84+ return iconName;
85+ }
86+
87+ QDBusConnection::systemBus().connect("org.freedesktop.NetworkManager", primaryConn, "org.freedesktop.NetworkManager.Connection.Active", "PropertiesChanged",
88+ this, SLOT(onNMPropertiesChanged(QVariantMap)));
89+
90+ QDBusInterface ap("org.freedesktop.NetworkManager", apPath, "org.freedesktop.NetworkManager.AccessPoint", QDBusConnection::systemBus());
91+
92+ if (!ap.isValid()) {
93+ qWarning() << "Invalid AP";
94+ return iconName;
95+ }
96+
97+ QDBusConnection::systemBus().connect("org.freedesktop.NetworkManager", apPath, "org.freedesktop.NetworkManager.AccessPoint", "PropertiesChanged",
98+ this, SLOT(onNMPropertiesChanged(QVariantMap)));
99+
100+ const uint strength = ap.property("Strength").toUInt();
101+ const uint flags = ap.property("Flags").toUInt();
102+ qDebug() << "Strength:" << strength;
103+ qDebug() << "Flags:" << flags;
104+
105+ if (strength == 0) {
106+ iconName = "nm-signal-00";
107+ } else if (strength <= 25) {
108+ iconName = "nm-signal-25";
109+ } else if (strength <= 50) {
110+ iconName = "nm-signal-50";
111+ } else if (strength <= 75) {
112+ iconName = "nm-signal-75";
113+ }
114+
115+ if (flags >= 1) {
116+ iconName += "-secure";
117+ }
118+ }
119+ }
120+
121+ return iconName;
122+}
123+
124+void Status::initUPower()
125+{
126+ m_upowerIface = new QDBusInterface("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/DisplayDevice", "org.freedesktop.UPower.Device",
127+ QDBusConnection::systemBus(), this);
128+ QDBusConnection::systemBus().connect("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/DisplayDevice", "org.freedesktop.DBus.Properties",
129+ "PropertiesChanged", this, SLOT(onUPowerPropertiesChanged(QString,QVariantMap,QStringList)));
130+}
131+
132+void Status::onUPowerPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps)
133+{
134+ Q_UNUSED(iface)
135+ Q_UNUSED(invalidatedProps)
136+
137+ if (changedProps.contains("IconName")) {
138+ Q_EMIT batteryIconChanged();
139+ }
140+}
141+
142+QString Status::batteryIcon() const
143+{
144+ const QString iconName = m_upowerIface->property("IconName").toString();
145+ qDebug() << "UPower icon name:" << iconName;
146+ return iconName;
147+}
plugins/Wizard/Status.hnew file+60
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef WIZARD_STATUS_H
18+#define WIZARD_STATUS_H
19+
20+#include <QObject>
21+#include <QString>
22+#include <QDBusInterface>
23+
24+class Status: public QObject
25+{
26+ Q_OBJECT
27+ Q_PROPERTY(bool online READ online NOTIFY onlineChanged)
28+ Q_PROPERTY(QString networkIcon READ networkIcon NOTIFY networkIconChanged)
29+ Q_PROPERTY(QString batteryIcon READ batteryIcon NOTIFY batteryIconChanged)
30+public:
31+ Status();
32+ ~Status() = default;
33+
34+ bool online() const;
35+ QString networkIcon();
36+
37+ QString batteryIcon() const;
38+
39+Q_SIGNALS:
40+ void networkIconChanged();
41+ void onlineChanged();
42+ void batteryIconChanged();
43+
44+private Q_SLOTS:
45+ void onNMPropertiesChanged(const QVariantMap &changedProps);
46+ void onUPowerPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps);
47+
48+private:
49+ Q_DISABLE_COPY(Status)
50+
51+ // network status
52+ void initNM();
53+ QDBusInterface * m_nmIface = nullptr;
54+
55+ // battery status
56+ void initUPower();
57+ QDBusInterface * m_upowerIface = nullptr;
58+};
59+
60+#endif
plugins/Wizard/System.cpp+1−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical Ltd.
2+ * Copyright (C) 2014-2015 Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU General Public License version 3, as published
plugins/Wizard/System.h+2−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014 Canonical Ltd.
2+ * Copyright (C) 2014-2015 Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU General Public License version 3, as published
@@ -28,6 +28,7 @@ class System : public QObject
2828
2929public:
3030 System();
31+ ~System() = default;
3132
3233 bool wizardEnabled() const;
3334 void setWizardEnabled(bool enabled);
plugins/Wizard/plugin.cpp+9
@@ -19,6 +19,7 @@
1919#include "System.h"
2020#include "timezonemodel.h"
2121#include "LocalePlugin.h"
22+#include "Status.h"
2223
2324#include <QtQml/qqml.h>
2425
@@ -29,11 +30,19 @@ static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2930 return new System();
3031}
3132
33+static QObject *status_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
34+{
35+ Q_UNUSED(engine)
36+ Q_UNUSED(scriptEngine)
37+ return new Status();
38+}
39+
3240void WizardPlugin::registerTypes(const char *uri)
3341{
3442 Q_ASSERT(uri == QLatin1String("Wizard"));
3543 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3644 qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
45+ qmlRegisterSingletonType<Status>(uri, 0, 1, "Status", status_provider);
3746 qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
3847 qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
3948 qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");
qml/Wizard/Page.qml+61−1
@@ -17,6 +17,7 @@
1717import QtQuick 2.3
1818import Ubuntu.Components 1.2
1919import MeeGo.QOfono 0.2
20+import Wizard 0.1
2021
2122Item {
2223 readonly property real buttonMargin: units.gu(3)
@@ -33,7 +34,7 @@ Item {
3334 // colors
3435 readonly property color backgroundColor: "#fdfdfd"
3536 readonly property color dividerColor: "#cdcdcd"
36− readonly property color textColor: "#525252"
37+ readonly property color textColor: "#5d5d5d"
3738 readonly property color errorColor: "#e14141"
3839 readonly property color okColor: "#3fb24f"
3940
@@ -99,6 +100,17 @@ Item {
99100 }
100101 }
101102
103+ Timer {
104+ id: indicatorTimer
105+ running: true
106+ interval: 1000
107+ triggeredOnStart: true
108+ repeat: true
109+ onTriggered: {
110+ indicatorTime.text = Qt.formatTime(new Date(), "h:mm")
111+ }
112+ }
113+
102114 // title
103115 Image {
104116 id: titleRect
@@ -127,6 +139,54 @@ Item {
127139 color: customTitle ? textColor : backgroundColor
128140 fontSize: "x-large"
129141 }
142+
143+ Row {
144+ id: indicatorRow
145+ visible: !customTitle
146+ anchors {
147+ top: parent.top
148+ right: parent.right
149+ topMargin: units.gu(.5)
150+ rightMargin: units.gu(.5)
151+ }
152+ height: units.gu(2)
153+ spacing: units.gu(.5)
154+
155+ Icon {
156+ id: indicatorSim
157+ anchors.verticalCenter: parent.verticalCenter
158+ name: "no-simcard"
159+ height: parent.height
160+ width: height
161+ visible: !(simManager0.present || simManager1.present)
162+ color: "white"
163+ }
164+
165+ Icon {
166+ id: indicatorNet
167+ anchors.verticalCenter: parent.verticalCenter
168+ name: Status.networkIcon
169+ height: parent.height
170+ width: height
171+ color: "white"
172+ }
173+
174+ Icon {
175+ id: indicatorBattery
176+ anchors.verticalCenter: parent.verticalCenter
177+ name: Status.batteryIcon
178+ height: parent.height
179+ width: height * 1.4 // the battery icon is not rectangular :/
180+ color: "white"
181+ }
182+
183+ Label {
184+ id: indicatorTime
185+ anchors.verticalCenter: parent.verticalCenter
186+ color: "white"
187+ fontSize: "small"
188+ }
189+ }
130190 }
131191
132192 // content
tests/mocks/Wizard/CMakeLists.txt+2−1
@@ -8,7 +8,8 @@ add_library(MockWizard-qml MODULE
88 ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
99 ${CMAKE_SOURCE_DIR}/plugins/Wizard/timezonemodel.cpp
1010 ${CMAKE_SOURCE_DIR}/plugins/Wizard/LocalePlugin.cpp
11+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/Status.cpp
1112)
1213
13−qt5_use_modules(MockWizard-qml Qml)
14+qt5_use_modules(MockWizard-qml DBus Qml)
1415add_unity8_mock(Wizard 0.1 Wizard TARGETS MockWizard-qml)
tests/mocks/Wizard/mockplugin.cpp+9
@@ -19,6 +19,7 @@
1919#include "PageList.h"
2020#include "timezonemodel.h"
2121#include "LocalePlugin.h"
22+#include "Status.h"
2223
2324#include <QtQml/qqml.h>
2425
@@ -29,11 +30,19 @@ static QObject *system_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2930 return new MockSystem();
3031}
3132
33+static QObject *status_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
34+{
35+ Q_UNUSED(engine)
36+ Q_UNUSED(scriptEngine)
37+ return new Status();
38+}
39+
3240void MockWizardPlugin::registerTypes(const char *uri)
3341{
3442 Q_ASSERT(uri == QLatin1String("Wizard"));
3543 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3644 qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
45+ qmlRegisterSingletonType<Status>(uri, 0, 1, "Status", status_provider);
3746 qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
3847 qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
3948 qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");