Merge lp:~nick-dedekind/unity8/lp1385331.led into lp:unity8

Proposed by Nick Dedekind
Status: Merged
Approved by: Albert Astals Cid
Approved revision: 1378
Merged at revision: 1534
Proposed branch: lp:~nick-dedekind/unity8/lp1385331.led
Merge into: lp:unity8
Diff against target: 2016 lines (+1124/-312)
35 files modified
debian/control (+3/-3)
plugins/Lights/Lights.cpp (+9/-24)
plugins/Unity/Indicators/CMakeLists.txt (+3/-1)
plugins/Unity/Indicators/Indicators.qmltypes (+18/-7)
plugins/Unity/Indicators/actionrootstate.cpp (+97/-0)
plugins/Unity/Indicators/actionrootstate.h (+55/-0)
plugins/Unity/Indicators/modelactionrootstate.cpp (+127/-0)
plugins/Unity/Indicators/modelactionrootstate.h (+61/-0)
plugins/Unity/Indicators/plugin.cpp (+4/-2)
plugins/Unity/Indicators/rootstateparser.cpp (+75/-142)
plugins/Unity/Indicators/rootstateparser.h (+20/-36)
qml/Greeter/Clock.qml (+1/-1)
qml/Panel/IndicatorItem.qml (+0/-8)
qml/Panel/Indicators/IndicatorBase.qml (+1/-1)
qml/Panel/Indicators/IndicatorsLight.qml (+19/-1)
qml/Panel/IndicatorsMenu.qml (+5/-0)
tests/mocks/CMakeLists.txt (+1/-0)
tests/mocks/Lights/CMakeLists.txt (+8/-0)
tests/mocks/Lights/Lights.cpp (+84/-0)
tests/mocks/Lights/Lights.h (+66/-0)
tests/mocks/Lights/Lights.qmltypes (+45/-0)
tests/mocks/Lights/plugin.cpp (+33/-0)
tests/mocks/Lights/plugin.h (+32/-0)
tests/mocks/Lights/qmldir (+3/-0)
tests/mocks/QMenuModel/CMakeLists.txt (+1/-0)
tests/mocks/QMenuModel/QDBusActionGroup.qml (+21/-68)
tests/mocks/QMenuModel/actiondata.h (+52/-0)
tests/mocks/QMenuModel/plugin.cpp (+10/-0)
tests/mocks/Unity/Indicators/ActionRootState.qml (+46/-0)
tests/mocks/Unity/Indicators/qmldir (+2/-1)
tests/plugins/Unity/Indicators/rootactionstatetest.cpp (+4/-4)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml (+129/-0)
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml (+52/-1)
tests/qmltests/Wizard/tst_Wizard.qml (+36/-12)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/lp1385331.led
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Albert Astals Cid (community) Approve
Review via email: mp+241417@code.launchpad.net

Commit message

Unhook Lights interface from indicator widgets

Description of the change

Unhook Lights interface from indicator widgets

 * Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/qmenumodel/lp1385331.led/+merge/241422

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * Did you make sure that your branch does not contain spurious tags?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

 * If you changed the UI, has there been a design review?
N/A

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1374. By Nick Dedekind

removed author

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
1 conflicts encountered.

1375. By Nick Dedekind

merged with trunk

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Text conflict in debian/control
> 1 conflicts encountered.

Fixed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
Text conflict in tests/mocks/CMakeLists.txt
Text conflict in tests/mocks/QMenuModel/QDBusActionGroup.qml
3 conflicts encountered.

review: Needs Fixing
1376. By Nick Dedekind

merged with trunk

1377. By Nick Dedekind

better lights init

Revision history for this message
Albert Astals Cid (aacid) wrote :

Is there an easy way to reproduce the problem this is fixing?

review: Needs Information
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

1) kill unity8 when the light is blinking (new message + screen off)
2) clear messages (I use a messaging test script to add the new messages)
3) when unity8 restarts light will remain be blinking

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

/home/phablet/unity8-lp1385331.led/plugins/Unity/Indicators/modelactionrootstate.cpp: multiple new lines at end of file

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote :

 * Start messages.py
 * Led blinks forever
 * Kill unity8 (restarts itself)
 * Led blinks just one time more

I guess it should be still blinking forever?

review: Needs Information
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> * Start messages.py
> * Led blinks forever
> * Kill unity8 (restarts itself)
> * Led blinks just one time more
>
> I guess it should be still blinking forever?

hm. if the screen is off and there are messages, it should keep blinking. I'll have to check what's happening.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> > * Start messages.py
> > * Led blinks forever
> > * Kill unity8 (restarts itself)
> > * Led blinks just one time more
> >
> > I guess it should be still blinking forever?
>
> hm. if the screen is off and there are messages, it should keep blinking. I'll
> have to check what's happening.

Tested this and in my instance, this is because Powerd.status is coming up as "On" when unity8 is restarted from a kill (when the screen is off). :/
Needs some sorting out, but it's not related to this branch.

1378. By Nick Dedekind

removed whitespace

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> /home/phablet/unity8-lp1385331.led/plugins/Unity/Indicators/modelactionrootsta
> te.cpp: multiple new lines at end of file

Fixed.

Revision history for this message
Albert Astals Cid (aacid) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

 * Did CI run pass?
It needs a dependency

 * Did you make sure that the branch does not contain spurious tags?
Yes

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-12-08 18:15:11 +0000
3+++ debian/control 2014-12-17 11:19:14 +0000
4@@ -22,7 +22,7 @@
5 libpam0g-dev,
6 libpay2-dev,
7 libpulse-dev,
8- libqmenumodel-dev (>= 0.2.8),
9+ libqmenumodel-dev (>= 0.2.9),
10 libqt5xmlpatterns5-dev,
11 libsystemsettings-dev,
12 libunity-api-dev (>= 7.94),
13@@ -61,7 +61,7 @@
14
15 Package: indicators-client
16 Architecture: amd64 armhf i386
17-Depends: qmenumodel-qml (>= 0.2.8),
18+Depends: qmenumodel-qml (>= 0.2.9),
19 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
20 unity8 (= ${binary:Version}),
21 ${misc:Depends},
22@@ -85,7 +85,7 @@
23 Depends: gsettings-desktop-schemas,
24 libcap2-bin,
25 libglib2.0-bin,
26- qmenumodel-qml (>= 0.2.8),
27+ qmenumodel-qml (>= 0.2.9),
28 qml-module-qt-labs-folderlistmodel,
29 qml-module-qtquick-xmllistmodel,
30 qtdeclarative5-gsettings1.0,
31
32=== modified file 'plugins/Lights/Lights.cpp'
33--- plugins/Lights/Lights.cpp 2014-09-08 15:07:24 +0000
34+++ plugins/Lights/Lights.cpp 2014-12-17 11:19:14 +0000
35@@ -44,12 +44,20 @@
36
37 void Lights::setState(Lights::State newState)
38 {
39+ if (!init()) {
40+ qWarning() << "No lights device";
41+ return;
42+ }
43+
44 if (m_state != newState) {
45 if (newState == Lights::On) {
46 turnOn();
47 } else {
48 turnOff();
49 }
50+
51+ m_state = newState;
52+ Q_EMIT stateChanged(m_state);
53 }
54 }
55
56@@ -115,6 +123,7 @@
57 err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
58 if (err == 0) {
59 m_lightDevice = (light_device_t*)device;
60+ turnOff();
61 return true;
62 } else {
63 qWarning() << "Failed to access notification lights";
64@@ -127,15 +136,6 @@
65
66 void Lights::turnOn()
67 {
68- if (!init()) {
69- qWarning() << "No lights device";
70- return;
71- }
72-
73- if (m_state == Lights::On) {
74- return;
75- }
76-
77 // pulse
78 light_state_t state;
79 memset(&state, 0, sizeof(light_state_t));
80@@ -147,23 +147,11 @@
81
82 if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
83 qWarning() << "Failed to turn the light off";
84- } else {
85- m_state = Lights::On;
86- Q_EMIT stateChanged(m_state);
87 }
88 }
89
90 void Lights::turnOff()
91 {
92- if (!init()) {
93- qWarning() << "No lights device";
94- return;
95- }
96-
97- if (m_state == Lights::Off) {
98- return;
99- }
100-
101 light_state_t state;
102 memset(&state, 0, sizeof(light_state_t));
103 state.color = 0x00000000;
104@@ -174,8 +162,5 @@
105
106 if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
107 qWarning() << "Failed to turn the light off";
108- } else {
109- m_state = Lights::Off;
110- Q_EMIT stateChanged(m_state);
111 }
112 }
113
114=== modified file 'plugins/Unity/Indicators/CMakeLists.txt'
115--- plugins/Unity/Indicators/CMakeLists.txt 2014-10-03 10:53:02 +0000
116+++ plugins/Unity/Indicators/CMakeLists.txt 2014-12-17 11:19:14 +0000
117@@ -16,14 +16,16 @@
118 )
119
120 set(IndicatorsQML_SOURCES
121+ actionrootstate.cpp
122 indicator.cpp
123 indicators.h
124 indicatorsmanager.cpp
125 indicatorsmodel.cpp
126 menucontentactivator.cpp
127+ modelactionrootstate.cpp
128 modelprinter.cpp
129 plugin.cpp
130- rootactionstate.cpp
131+ rootstateparser.cpp
132 sharedunitymenumodel.cpp
133 unitymenumodelcache.cpp
134 unitymenumodelstack.cpp
135
136=== modified file 'plugins/Unity/Indicators/Indicators.qmltypes'
137--- plugins/Unity/Indicators/Indicators.qmltypes 2014-10-07 10:58:39 +0000
138+++ plugins/Unity/Indicators/Indicators.qmltypes 2014-12-17 11:19:14 +0000
139@@ -8,6 +8,14 @@
140
141 Module {
142 Component {
143+ name: "ActionRootState"
144+ prototype: "RootStateObject"
145+ exports: ["Unity.Indicators/ActionRootState 0.1"]
146+ exportMetaObjectRevisions: [0]
147+ Property { name: "actionGroup"; type: "QDBusActionGroup"; isPointer: true }
148+ Property { name: "actionName"; type: "string" }
149+ }
150+ Component {
151 name: "ActionState"
152 prototype: "QObject"
153 exports: ["Unity.Indicators/ActionState 0.1"]
154@@ -23,7 +31,6 @@
155 }
156 }
157 }
158- Component { name: "ActionStateParser"; prototype: "QObject" }
159 Component {
160 name: "FlatMenuProxyModelRole"
161 prototype: "QObject"
162@@ -147,6 +154,14 @@
163 Property { name: "active"; type: "bool"; isReadonly: true }
164 }
165 Component {
166+ name: "ModelActionRootState"
167+ prototype: "RootStateObject"
168+ exports: ["Unity.Indicators/ModelActionRootState 0.1"]
169+ exportMetaObjectRevisions: [0]
170+ Property { name: "menu"; type: "UnityMenuModel"; isPointer: true }
171+ Signal { name: "indexChanged" }
172+ }
173+ Component {
174 name: "ModelPrinter"
175 prototype: "QObject"
176 exports: ["Unity.Indicators/ModelPrinter 0.1"]
177@@ -192,11 +207,8 @@
178 }
179 Component { name: "QIdentityProxyModel"; prototype: "QAbstractProxyModel" }
180 Component {
181- name: "RootActionState"
182- prototype: "ActionStateParser"
183- exports: ["Unity.Indicators/RootActionState 0.1"]
184- exportMetaObjectRevisions: [0]
185- Property { name: "menu"; type: "UnityMenuModel"; isPointer: true }
186+ name: "RootStateObject"
187+ prototype: "QObject"
188 Property { name: "valid"; type: "bool"; isReadonly: true }
189 Property { name: "title"; type: "string"; isReadonly: true }
190 Property { name: "leftLabel"; type: "string"; isReadonly: true }
191@@ -205,7 +217,6 @@
192 Property { name: "accessibleName"; type: "string"; isReadonly: true }
193 Property { name: "visible"; type: "bool"; isReadonly: true }
194 Signal { name: "updated" }
195- Signal { name: "indexChanged" }
196 }
197 Component {
198 name: "SharedUnityMenuModel"
199
200=== added file 'plugins/Unity/Indicators/actionrootstate.cpp'
201--- plugins/Unity/Indicators/actionrootstate.cpp 1970-01-01 00:00:00 +0000
202+++ plugins/Unity/Indicators/actionrootstate.cpp 2014-12-17 11:19:14 +0000
203@@ -0,0 +1,97 @@
204+/*
205+ * Copyright 2014 Canonical Ltd.
206+ *
207+ * This program is free software; you can redistribute it and/or modify
208+ * it under the terms of the GNU Lesser General Public License as published by
209+ * the Free Software Foundation; version 3.
210+ *
211+ * This program is distributed in the hope that it will be useful,
212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
213+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
214+ * GNU Lesser General Public License for more details.
215+ *
216+ * You should have received a copy of the GNU Lesser General Public License
217+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
218+ */
219+
220+#include "actionrootstate.h"
221+
222+#include <qdbusactiongroup.h>
223+#include <QDebug>
224+
225+ActionRootState::ActionRootState(QObject *parent)
226+ : RootStateObject(parent)
227+ , m_actionGroup(nullptr)
228+{
229+}
230+
231+QDBusActionGroup *ActionRootState::actionGroup() const
232+{
233+ return m_actionGroup;
234+}
235+
236+void ActionRootState::setActionGroup(QDBusActionGroup *actionGroup)
237+{
238+ if (m_actionGroup != actionGroup) {
239+ bool wasValid = valid();
240+
241+ if (m_actionGroup) {
242+ disconnect(m_actionGroup, 0, this, 0);
243+ }
244+ m_actionGroup = actionGroup;
245+
246+ if (m_actionGroup) {
247+ connect(m_actionGroup, &QDBusActionGroup::statusChanged, this, [&](bool) { updateActionState(); });
248+ connect(m_actionGroup, &QDBusActionGroup::actionAppear, this, [&](const QString&) { updateActionState(); });
249+ connect(m_actionGroup, &QDBusActionGroup::actionVanish, this, [&](const QString&) { updateActionState(); });
250+ connect(m_actionGroup, &QDBusActionGroup::actionStateChanged, this, [&](QVariant) { updateActionState(); });
251+
252+ connect(m_actionGroup, &QObject::destroyed, this, [&](QObject*) { updateActionState(); });
253+ }
254+ updateActionState();
255+ Q_EMIT actionGroupChanged();
256+
257+ if (wasValid != valid()) Q_EMIT validChanged();
258+ }
259+}
260+
261+QString ActionRootState::actionName() const
262+{
263+ return m_actionName;
264+}
265+
266+void ActionRootState::setActionName(const QString &actionName)
267+{
268+ if (m_actionName != actionName) {
269+ bool wasValid = valid();
270+
271+ m_actionName = actionName;
272+ updateActionState();
273+
274+ Q_EMIT actionNameChanged();
275+
276+ if (wasValid != valid()) Q_EMIT validChanged();
277+ }
278+}
279+
280+bool ActionRootState::valid() const
281+{
282+ return m_actionGroup && m_actionGroup->status() == DBusEnums::Connected &&
283+ !m_actionName.isEmpty() && m_actionGroup->hasAction(m_actionName);
284+}
285+
286+void ActionRootState::updateActionState()
287+{
288+ if (valid()) {
289+ ActionStateParser* oldParser = m_actionGroup->actionStateParser();
290+ m_actionGroup->setActionStateParser(&m_parser);
291+
292+ QVariantMap state = m_actionGroup->actionState(m_actionName).toMap();
293+
294+ m_actionGroup->setActionStateParser(oldParser);
295+
296+ setCurrentState(state);
297+ } else {
298+ setCurrentState(QVariantMap());
299+ }
300+}
301
302=== added file 'plugins/Unity/Indicators/actionrootstate.h'
303--- plugins/Unity/Indicators/actionrootstate.h 1970-01-01 00:00:00 +0000
304+++ plugins/Unity/Indicators/actionrootstate.h 2014-12-17 11:19:14 +0000
305@@ -0,0 +1,55 @@
306+/*
307+ * Copyright 2014 Canonical Ltd.
308+ *
309+ * This program is free software; you can redistribute it and/or modify
310+ * it under the terms of the GNU Lesser General Public License as published by
311+ * the Free Software Foundation; version 3.
312+ *
313+ * This program is distributed in the hope that it will be useful,
314+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
315+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
316+ * GNU Lesser General Public License for more details.
317+ *
318+ * You should have received a copy of the GNU Lesser General Public License
319+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
320+ */
321+
322+#ifndef ACTIONROOTSTATE_H
323+#define ACTIONROOTSTATE_H
324+
325+#include "unityindicatorsglobal.h"
326+
327+#include "rootstateparser.h"
328+
329+class QDBusActionGroup;
330+
331+class UNITYINDICATORS_EXPORT ActionRootState : public RootStateObject
332+{
333+ Q_OBJECT
334+ Q_PROPERTY(QDBusActionGroup* actionGroup READ actionGroup WRITE setActionGroup NOTIFY actionGroupChanged)
335+ Q_PROPERTY(QString actionName READ actionName WRITE setActionName NOTIFY actionNameChanged)
336+
337+public:
338+ ActionRootState(QObject *parent = 0);
339+
340+ QDBusActionGroup *actionGroup() const;
341+ void setActionGroup(QDBusActionGroup *actionGroup);
342+
343+ QString actionName() const;
344+ void setActionName(const QString& actionName);
345+
346+ bool valid() const override;
347+
348+Q_SIGNALS:
349+ void actionGroupChanged();
350+ void actionNameChanged();
351+
352+private Q_SLOTS:
353+ void updateActionState();
354+
355+private:
356+ QDBusActionGroup* m_actionGroup;
357+ QString m_actionName;
358+};
359+
360+#endif // ACTIONROOTSTATE_H
361
362=== added file 'plugins/Unity/Indicators/modelactionrootstate.cpp'
363--- plugins/Unity/Indicators/modelactionrootstate.cpp 1970-01-01 00:00:00 +0000
364+++ plugins/Unity/Indicators/modelactionrootstate.cpp 2014-12-17 11:19:14 +0000
365@@ -0,0 +1,127 @@
366+/*
367+ * Copyright 2013 Canonical Ltd.
368+ *
369+ * This program is free software; you can redistribute it and/or modify
370+ * it under the terms of the GNU Lesser General Public License as published by
371+ * the Free Software Foundation; version 3.
372+ *
373+ * This program is distributed in the hope that it will be useful,
374+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
375+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
376+ * GNU Lesser General Public License for more details.
377+ *
378+ * You should have received a copy of the GNU Lesser General Public License
379+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
380+ *
381+ * Authors:
382+ * Nick Dedekind <nick.dedekind@canonical.com>
383+ */
384+
385+#include "modelactionrootstate.h"
386+#include "indicators.h"
387+
388+#include <unitymenumodel.h>
389+#include <QVariant>
390+#include <QIcon>
391+
392+extern "C" {
393+#include <glib.h>
394+#include <gio/gio.h>
395+}
396+
397+ModelActionRootState::ModelActionRootState(QObject *parent)
398+ : RootStateObject(parent),
399+ m_menu(nullptr)
400+{
401+}
402+
403+ModelActionRootState::~ModelActionRootState()
404+{
405+}
406+
407+UnityMenuModel* ModelActionRootState::menu() const
408+{
409+ return m_menu;
410+}
411+
412+void ModelActionRootState::setMenu(UnityMenuModel* menu)
413+{
414+ if (m_menu != menu) {
415+ bool wasValid = valid();
416+
417+ if (m_menu) {
418+ m_menu->disconnect(this);
419+ }
420+ m_menu = menu;
421+
422+ if (m_menu) {
423+ connect(m_menu, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(onModelRowsAdded(const QModelIndex&, int, int)));
424+ connect(m_menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
425+ connect(m_menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
426+
427+ connect(m_menu, SIGNAL(destroyed()), SLOT(reset()));
428+ }
429+ updateActionState();
430+ Q_EMIT menuChanged();
431+
432+ if (wasValid != valid())
433+ Q_EMIT validChanged();
434+ }
435+}
436+
437+bool ModelActionRootState::valid() const
438+{
439+ return m_menu && m_menu->rowCount() > 0;
440+}
441+
442+void ModelActionRootState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
443+{
444+ Q_UNUSED(parent);
445+ if (start == 0 && end >= 0) {
446+ updateActionState();
447+ }
448+}
449+
450+void ModelActionRootState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
451+{
452+ Q_UNUSED(parent);
453+ if (start == 0 && end >= 0) {
454+ updateActionState();
455+ }
456+}
457+
458+void ModelActionRootState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
459+{
460+ Q_UNUSED(roles);
461+ if (!topLeft.isValid() || !bottomRight.isValid()) {
462+ return;
463+ }
464+
465+ if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
466+ updateActionState();
467+ }
468+}
469+
470+void ModelActionRootState::reset()
471+{
472+ m_menu = nullptr;
473+
474+ Q_EMIT menuChanged();
475+ setCurrentState(QVariantMap());
476+}
477+
478+void ModelActionRootState::updateActionState()
479+{
480+ if (m_menu && m_menu->rowCount() > 0) {
481+ ActionStateParser* oldParser = m_menu->actionStateParser();
482+ m_menu->setActionStateParser(&m_parser);
483+
484+ QVariantMap state = m_menu->get(0, "actionState").toMap();
485+
486+ m_menu->setActionStateParser(oldParser);
487+
488+ setCurrentState(state);
489+ } else {
490+ setCurrentState(QVariantMap());
491+ }
492+}
493
494=== added file 'plugins/Unity/Indicators/modelactionrootstate.h'
495--- plugins/Unity/Indicators/modelactionrootstate.h 1970-01-01 00:00:00 +0000
496+++ plugins/Unity/Indicators/modelactionrootstate.h 2014-12-17 11:19:14 +0000
497@@ -0,0 +1,61 @@
498+/*
499+ * Copyright 2013 Canonical Ltd.
500+ *
501+ * This program is free software; you can redistribute it and/or modify
502+ * it under the terms of the GNU Lesser General Public License as published by
503+ * the Free Software Foundation; version 3.
504+ *
505+ * This program is distributed in the hope that it will be useful,
506+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
507+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
508+ * GNU Lesser General Public License for more details.
509+ *
510+ * You should have received a copy of the GNU Lesser General Public License
511+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
512+ *
513+ * Authors:
514+ * Nick Dedekind <nick.dedekind@canonical.com>
515+ */
516+
517+#ifndef MODELACTIONROOTSTATE_H
518+#define MODELACTIONROOTSTATE_H
519+
520+#include "unityindicatorsglobal.h"
521+
522+#include "rootstateparser.h"
523+
524+class UnityMenuModel;
525+
526+class UNITYINDICATORS_EXPORT ModelActionRootState : public RootStateObject
527+{
528+ Q_OBJECT
529+ Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
530+public:
531+ ModelActionRootState(QObject *parent = 0);
532+ virtual ~ModelActionRootState();
533+
534+ UnityMenuModel* menu() const;
535+ void setMenu(UnityMenuModel* menu);
536+
537+ int index() const;
538+ void setIndex(int index);
539+
540+ bool valid() const override;
541+
542+Q_SIGNALS:
543+ void menuChanged();
544+ void indexChanged();
545+
546+private Q_SLOTS:
547+ void onModelRowsAdded(const QModelIndex& parent, int start, int end);
548+ void onModelRowsRemoved(const QModelIndex& parent, int start, int end);
549+ void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>&);
550+ void reset();
551+
552+private:
553+ void updateActionState();
554+
555+ UnityMenuModel* m_menu;
556+};
557+
558+#endif // MODELACTIONROOTSTATE_H
559
560=== modified file 'plugins/Unity/Indicators/plugin.cpp'
561--- plugins/Unity/Indicators/plugin.cpp 2014-10-07 10:28:59 +0000
562+++ plugins/Unity/Indicators/plugin.cpp 2014-12-17 11:19:14 +0000
563@@ -24,12 +24,13 @@
564 #include "plugin.h"
565
566 // local
567+#include "actionrootstate.h"
568 #include "indicators.h"
569 #include "indicatorsmanager.h"
570 #include "indicatorsmodel.h"
571 #include "menucontentactivator.h"
572+#include "modelactionrootstate.h"
573 #include "modelprinter.h"
574-#include "rootactionstate.h"
575 #include "sharedunitymenumodel.h"
576 #include "unitymenumodelcache.h"
577 #include "unitymenumodelstack.h"
578@@ -51,7 +52,8 @@
579 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
580 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
581 qmlRegisterType<UnityMenuModelStack>(uri, 0, 1, "UnityMenuModelStack");
582- qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
583+ qmlRegisterType<ModelActionRootState>(uri, 0, 1, "ModelActionRootState");
584+ qmlRegisterType<ActionRootState>(uri, 0, 1, "ActionRootState");
585 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
586 qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
587 qmlRegisterType<SharedUnityMenuModel>(uri, 0, 1, "SharedUnityMenuModel");
588
589=== renamed file 'plugins/Unity/Indicators/rootactionstate.cpp' => 'plugins/Unity/Indicators/rootstateparser.cpp'
590--- plugins/Unity/Indicators/rootactionstate.cpp 2014-10-20 12:38:16 +0000
591+++ plugins/Unity/Indicators/rootstateparser.cpp 2014-12-17 11:19:14 +0000
592@@ -12,155 +12,18 @@
593 *
594 * You should have received a copy of the GNU Lesser General Public License
595 * along with this program. If not, see <http://www.gnu.org/licenses/>.
596- *
597- * Authors:
598- * Nick Dedekind <nick.dedekind@canonical.com>
599 */
600
601-#include "rootactionstate.h"
602-#include "indicators.h"
603-
604-#include <unitymenumodel.h>
605-#include <QVariant>
606-#include <QIcon>
607+#include "rootstateparser.h"
608
609 extern "C" {
610 #include <glib.h>
611 #include <gio/gio.h>
612 }
613
614-RootActionState::RootActionState(QObject *parent)
615- : ActionStateParser(parent),
616- m_menu(nullptr)
617-{
618-}
619-
620-RootActionState::~RootActionState()
621-{
622-}
623-
624-UnityMenuModel* RootActionState::menu() const
625-{
626- return m_menu;
627-}
628-
629-void RootActionState::setMenu(UnityMenuModel* menu)
630-{
631- if (m_menu != menu) {
632- if (m_menu) {
633- m_menu->disconnect(this);
634- }
635- m_menu = menu;
636-
637- if (m_menu) {
638- connect(m_menu, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(onModelRowsAdded(const QModelIndex&, int, int)));
639- connect(m_menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
640- connect(m_menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
641-
642- connect(m_menu, SIGNAL(destroyed()), SLOT(reset()));
643- }
644- updateActionState();
645- Q_EMIT menuChanged();
646- }
647-}
648-
649-void RootActionState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
650-{
651- Q_UNUSED(parent);
652- if (start == 0 && end >= 0) {
653- updateActionState();
654- }
655-}
656-
657-void RootActionState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
658-{
659- Q_UNUSED(parent);
660- if (start == 0 && end >= 0) {
661- updateActionState();
662- }
663-}
664-
665-void RootActionState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
666-{
667- Q_UNUSED(roles);
668- if (!topLeft.isValid() || !bottomRight.isValid()) {
669- return;
670- }
671-
672- if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
673- updateActionState();
674- }
675-}
676-
677-void RootActionState::reset()
678-{
679- m_cachedState.clear();
680- m_menu = nullptr;
681-
682- Q_EMIT menuChanged();
683- Q_EMIT updated();
684-}
685-
686-void RootActionState::updateActionState()
687-{
688- if (m_menu && m_menu->rowCount() > 0) {
689- ActionStateParser* oldParser = m_menu->actionStateParser();
690- m_menu->setActionStateParser(this);
691-
692- m_cachedState = m_menu->get(0, "actionState").toMap();
693-
694- m_menu->setActionStateParser(oldParser);
695- } else {
696- m_cachedState.clear();
697- }
698- Q_EMIT updated();
699-}
700-
701-bool RootActionState::isValid() const
702-{
703- return m_menu && m_menu->rowCount() > 0;
704-}
705-
706-QString RootActionState::title() const
707-{
708- if (!isValid()) return QString();
709-
710- return m_cachedState.value("title", QVariant::fromValue(QString())).toString();
711-}
712-
713-QString RootActionState::leftLabel() const
714-{
715- if (!isValid()) return QString();
716-
717- return m_cachedState.value("pre-label", QVariant::fromValue(QString())).toString();
718-}
719-
720-QString RootActionState::rightLabel() const
721-{
722- if (!isValid()) return QString();
723-
724- return m_cachedState.value("label", QVariant::fromValue(QString())).toString();
725-}
726-
727-QStringList RootActionState::icons() const
728-{
729- if (!isValid()) return QStringList();
730-
731- return m_cachedState.value("icons", QVariant::fromValue(QStringList())).toStringList();
732-}
733-
734-QString RootActionState::accessibleName() const
735-{
736- if (!isValid()) return QString();
737-
738- return m_cachedState.value("accessible-desc", QVariant::fromValue(QString())).toString();
739-}
740-
741-bool RootActionState::indicatorVisible() const
742-{
743- if (!isValid()) return false;
744-
745- return m_cachedState.value("visible", QVariant::fromValue(true)).toBool();
746+RootStateParser::RootStateParser(QObject* parent)
747+ : ActionStateParser(parent)
748+{
749 }
750
751 static QString iconUri(GIcon *icon)
752@@ -209,7 +72,7 @@
753 return uri;
754 }
755
756-QVariant RootActionState::toQVariant(GVariant* state) const
757+QVariant RootStateParser::toQVariant(GVariant* state) const
758 {
759 if (!state) {
760 return QVariant();
761@@ -296,3 +159,73 @@
762 }
763 return ActionStateParser::toQVariant(state);
764 }
765+
766+
767+RootStateObject::RootStateObject(QObject* parent)
768+ : QObject(parent)
769+{
770+}
771+
772+QString RootStateObject::title() const
773+{
774+ if (!valid()) return QString();
775+
776+ return m_currentState.value("title", QVariant::fromValue(QString())).toString();
777+}
778+
779+QString RootStateObject::leftLabel() const
780+{
781+ if (!valid()) return QString();
782+
783+ return m_currentState.value("pre-label", QVariant::fromValue(QString())).toString();
784+}
785+
786+QString RootStateObject::rightLabel() const
787+{
788+ if (!valid()) return QString();
789+
790+ return m_currentState.value("label", QVariant::fromValue(QString())).toString();
791+}
792+
793+QStringList RootStateObject::icons() const
794+{
795+ if (!valid()) return QStringList();
796+
797+ return m_currentState.value("icons", QVariant::fromValue(QStringList())).toStringList();
798+}
799+
800+QString RootStateObject::accessibleName() const
801+{
802+ if (!valid()) return QString();
803+
804+ return m_currentState.value("accessible-desc", QVariant::fromValue(QString())).toString();
805+}
806+
807+bool RootStateObject::indicatorVisible() const
808+{
809+ if (!valid()) return false;
810+
811+ return m_currentState.value("visible", QVariant::fromValue(true)).toBool();
812+}
813+
814+void RootStateObject::setCurrentState(const QVariantMap& newState)
815+{
816+ QString oldTitle = title();
817+ QString oldLeftLabel = leftLabel();
818+ QString oldRightLabel = rightLabel();
819+ QStringList oldIcons = icons();
820+ QString oldAccessibleName = accessibleName();
821+ bool oldIndicatorVisible = indicatorVisible();
822+
823+ if (m_currentState != newState) {
824+ m_currentState = newState;
825+ Q_EMIT updated();
826+
827+ if (oldTitle != title()) Q_EMIT titleChanged();
828+ if (oldLeftLabel != leftLabel()) Q_EMIT leftLabelChanged();
829+ if (oldRightLabel != rightLabel()) Q_EMIT rightLabelChanged();
830+ if (oldIcons != icons()) Q_EMIT iconsChanged();
831+ if (oldAccessibleName != accessibleName()) Q_EMIT accessibleNameChanged();
832+ if (oldIndicatorVisible != indicatorVisible()) Q_EMIT indicatorVisibleChanged();
833+ }
834+}
835
836=== renamed file 'plugins/Unity/Indicators/rootactionstate.h' => 'plugins/Unity/Indicators/rootstateparser.h'
837--- plugins/Unity/Indicators/rootactionstate.h 2014-10-20 12:38:16 +0000
838+++ plugins/Unity/Indicators/rootstateparser.h 2014-12-17 11:19:14 +0000
839@@ -12,26 +12,27 @@
840 *
841 * You should have received a copy of the GNU Lesser General Public License
842 * along with this program. If not, see <http://www.gnu.org/licenses/>.
843- *
844- * Authors:
845- * Nick Dedekind <nick.dedekind@canonical.com>
846 */
847
848-#ifndef ROOTACTIONSTATE_H
849-#define ROOTACTIONSTATE_H
850+#ifndef ROOTSTATEPARSER_H
851+#define ROOTSTATEPARSER_H
852
853 #include "unityindicatorsglobal.h"
854
855 #include <actionstateparser.h>
856
857-class UnityMenuModel;
858+class UNITYINDICATORS_EXPORT RootStateParser : public ActionStateParser
859+{
860+public:
861+ RootStateParser(QObject* parent = nullptr);
862+ virtual QVariant toQVariant(GVariant* state) const override;
863+};
864
865-class UNITYINDICATORS_EXPORT RootActionState : public ActionStateParser
866+class UNITYINDICATORS_EXPORT RootStateObject : public QObject
867 {
868 Q_OBJECT
869- Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
870
871- Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
872+ Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
873 Q_PROPERTY(QString title READ title NOTIFY titleChanged)
874 Q_PROPERTY(QString leftLabel READ leftLabel NOTIFY leftLabelChanged)
875 Q_PROPERTY(QString rightLabel READ rightLabel NOTIFY rightLabelChanged)
876@@ -39,16 +40,10 @@
877 Q_PROPERTY(QString accessibleName READ accessibleName NOTIFY accessibleNameChanged)
878 Q_PROPERTY(bool indicatorVisible READ indicatorVisible NOTIFY indicatorVisibleChanged)
879 public:
880- RootActionState(QObject *parent = 0);
881- virtual ~RootActionState();
882-
883- UnityMenuModel* menu() const;
884- void setMenu(UnityMenuModel* menu);
885-
886- int index() const;
887- void setIndex(int index);
888-
889- bool isValid() const;
890+ RootStateObject(QObject* parent = 0);
891+
892+ virtual bool valid() const = 0;
893+
894 QString title() const;
895 QString leftLabel() const;
896 QString rightLabel() const;
897@@ -56,15 +51,12 @@
898 QString accessibleName() const;
899 bool indicatorVisible() const;
900
901- // from ActionStateParser
902- virtual QVariant toQVariant(GVariant* state) const override;
903+ QVariantMap currentState() const { return m_currentState; }
904+ void setCurrentState(const QVariantMap& currentState);
905
906 Q_SIGNALS:
907 void updated();
908
909- void menuChanged();
910- void indexChanged();
911-
912 void validChanged();
913 void titleChanged();
914 void leftLabelChanged();
915@@ -73,17 +65,9 @@
916 void accessibleNameChanged();
917 void indicatorVisibleChanged();
918
919-private Q_SLOTS:
920- void onModelRowsAdded(const QModelIndex& parent, int start, int end);
921- void onModelRowsRemoved(const QModelIndex& parent, int start, int end);
922- void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>&);
923- void reset();
924-
925-private:
926- void updateActionState();
927-
928- UnityMenuModel* m_menu;
929- QVariantMap m_cachedState;
930+protected:
931+ RootStateParser m_parser;
932+ QVariantMap m_currentState;
933 };
934
935-#endif // ROOTACTIONSTATE_H
936+#endif // ROOTSTATEPARSER_H
937
938=== modified file 'qml/Greeter/Clock.qml'
939--- qml/Greeter/Clock.qml 2014-11-21 19:23:57 +0000
940+++ qml/Greeter/Clock.qml 2014-12-17 11:19:14 +0000
941@@ -53,7 +53,7 @@
942 menuObjectPath: clock.visible ? "/com/canonical/indicator/datetime/phone" : ""
943 }
944
945- Indicators.RootActionState {
946+ Indicators.ModelActionRootState {
947 menu: timeModel.model
948 onUpdated: {
949 if (timeLabel.text != rightLabel) {
950
951=== modified file 'qml/Panel/IndicatorItem.qml'
952--- qml/Panel/IndicatorItem.qml 2014-11-21 15:01:59 +0000
953+++ qml/Panel/IndicatorItem.qml 2014-12-17 11:19:14 +0000
954@@ -45,14 +45,6 @@
955 onClicked: parent.clicked()
956 }
957
958- // FIXME: For now we will enable led indicator support only for messaging indicator
959- // in the future we should export a led API insted of doing that,
960- Loader {
961- id: indicatorLed
962- // only load source Component if the icons contains the new message icon
963- source: (root.icons && (String(root.icons).indexOf("indicator-messages-new") != -1)) ? Qt.resolvedUrl("Indicators/IndicatorsLight.qml") : ""
964- }
965-
966 Item {
967 id: mainItems
968 anchors.centerIn: parent
969
970=== modified file 'qml/Panel/Indicators/IndicatorBase.qml'
971--- qml/Panel/Indicators/IndicatorBase.qml 2014-10-17 14:55:35 +0000
972+++ qml/Panel/Indicators/IndicatorBase.qml 2014-12-17 11:19:14 +0000
973@@ -40,7 +40,7 @@
974 menuObjectPath: indicatorItem.menuObjectPath
975 }
976
977- RootActionState {
978+ ModelActionRootState {
979 id: rootAction
980 menu: menuModel ? menuModel : null
981 onUpdated: indicatorItem.rootActionStateChanged()
982
983=== modified file 'qml/Panel/Indicators/IndicatorsLight.qml'
984--- qml/Panel/Indicators/IndicatorsLight.qml 2014-08-05 14:31:12 +0000
985+++ qml/Panel/Indicators/IndicatorsLight.qml 2014-12-17 11:19:14 +0000
986@@ -20,16 +20,34 @@
987 import QtQuick 2.0
988 import Powerd 0.1
989 import Lights 0.1
990+import QMenuModel 0.1 as QMenuModel
991+import Unity.Indicators 0.1 as Indicators
992
993 QtObject {
994 id: root
995
996+ property var _actionGroup: QMenuModel.QDBusActionGroup {
997+ busType: 1
998+ busName: "com.canonical.indicator.messages"
999+ objectPath: "/com/canonical/indicator/messages"
1000+ }
1001+
1002+ property var _rootState: Indicators.ActionRootState {
1003+ actionGroup: _actionGroup
1004+ actionName: "messages"
1005+ Component.onCompleted: actionGroup.start()
1006+
1007+ property bool hasMessages: valid && (String(icons).indexOf("indicator-messages-new") != -1)
1008+ }
1009+
1010 Component.onDestruction: Lights.state = Lights.Off
1011
1012 // QtObject does not have children
1013 property var _binding: Binding {
1014 target: Lights
1015 property: "state"
1016- value: (Powerd.status === Powerd.Off) ? Lights.On : Lights.Off
1017+ value: {
1018+ return (Powerd.status === Powerd.Off && _rootState.hasMessages) ? Lights.On : Lights.Off
1019+ }
1020 }
1021 }
1022
1023=== modified file 'qml/Panel/IndicatorsMenu.qml'
1024--- qml/Panel/IndicatorsMenu.qml 2014-10-21 19:32:03 +0000
1025+++ qml/Panel/IndicatorsMenu.qml 2014-12-17 11:19:14 +0000
1026@@ -18,6 +18,7 @@
1027 import Ubuntu.Components 1.1
1028 import Ubuntu.Gestures 0.1
1029 import "../Components"
1030+import "Indicators"
1031
1032 Showable {
1033 id: root
1034@@ -60,6 +61,10 @@
1035 onUnitProgressChanged: d.updateState()
1036 clip: root.partiallyOpened
1037
1038+ IndicatorsLight {
1039+ id: indicatorLights
1040+ }
1041+
1042 // eater
1043 MouseArea {
1044 anchors.fill: parent
1045
1046=== modified file 'tests/mocks/CMakeLists.txt'
1047--- tests/mocks/CMakeLists.txt 2014-11-21 19:28:16 +0000
1048+++ tests/mocks/CMakeLists.txt 2014-12-17 11:19:14 +0000
1049@@ -32,6 +32,7 @@
1050 add_subdirectory(GSettings.1.0)
1051 add_subdirectory(libusermetrics)
1052 add_subdirectory(LightDM)
1053+add_subdirectory(Lights)
1054 add_subdirectory(MeeGo)
1055 add_subdirectory(Powerd)
1056 add_subdirectory(QMenuModel)
1057
1058=== added directory 'tests/mocks/Lights'
1059=== added file 'tests/mocks/Lights/CMakeLists.txt'
1060--- tests/mocks/Lights/CMakeLists.txt 1970-01-01 00:00:00 +0000
1061+++ tests/mocks/Lights/CMakeLists.txt 2014-12-17 11:19:14 +0000
1062@@ -0,0 +1,8 @@
1063+add_library(MockLights-qml MODULE
1064+ plugin.cpp
1065+ Lights.cpp
1066+ )
1067+
1068+qt5_use_modules(MockLights-qml Qml Gui)
1069+
1070+add_unity8_mock(Lights 0.1 Lights TARGETS MockLights-qml)
1071
1072=== added file 'tests/mocks/Lights/Lights.cpp'
1073--- tests/mocks/Lights/Lights.cpp 1970-01-01 00:00:00 +0000
1074+++ tests/mocks/Lights/Lights.cpp 2014-12-17 11:19:14 +0000
1075@@ -0,0 +1,84 @@
1076+/*
1077+ * Copyright (C) 2014 Canonical, Ltd.
1078+ *
1079+ * This program is free software; you can redistribute it and/or modify
1080+ * it under the terms of the GNU General Public License as published by
1081+ * the Free Software Foundation; version 3.
1082+ *
1083+ * This program is distributed in the hope that it will be useful,
1084+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1085+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1086+ * GNU General Public License for more details.
1087+ *
1088+ * You should have received a copy of the GNU General Public License
1089+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1090+ */
1091+
1092+#include "Lights.h"
1093+
1094+#include <QDebug>
1095+
1096+Lights::Lights(QObject* parent)
1097+ : QObject(parent),
1098+ m_color("blue"),
1099+ m_state(Lights::Off),
1100+ m_onMs(1000),
1101+ m_offMs(3000)
1102+{
1103+}
1104+
1105+Lights::~Lights()
1106+{
1107+}
1108+
1109+void Lights::setState(Lights::State newState)
1110+{
1111+ if (m_state != newState) {
1112+ m_state = newState;
1113+ Q_EMIT stateChanged(m_state);
1114+ }
1115+}
1116+
1117+Lights::State Lights::state() const
1118+{
1119+ return m_state;
1120+}
1121+
1122+void Lights::setColor(const QColor &color)
1123+{
1124+ if (m_color != color) {
1125+ m_color = color;
1126+ Q_EMIT colorChanged(m_color);
1127+ }
1128+}
1129+
1130+QColor Lights::color() const
1131+{
1132+ return m_color;
1133+}
1134+
1135+int Lights::onMillisec() const
1136+{
1137+ return m_onMs;
1138+}
1139+
1140+void Lights::setOnMillisec(int onMs)
1141+{
1142+ if (m_onMs != onMs) {
1143+ m_onMs = onMs;
1144+ Q_EMIT onMillisecChanged(m_onMs);
1145+ }
1146+}
1147+
1148+int Lights::offMillisec() const
1149+{
1150+ return m_offMs;
1151+}
1152+
1153+void Lights::setOffMillisec(int offMs)
1154+{
1155+ if (m_offMs != offMs) {
1156+ m_offMs = offMs;
1157+ Q_EMIT offMillisecChanged(m_offMs);
1158+ }
1159+}
1160
1161=== added file 'tests/mocks/Lights/Lights.h'
1162--- tests/mocks/Lights/Lights.h 1970-01-01 00:00:00 +0000
1163+++ tests/mocks/Lights/Lights.h 2014-12-17 11:19:14 +0000
1164@@ -0,0 +1,66 @@
1165+/*
1166+ * Copyright (C) 2014 Canonical, Ltd.
1167+ *
1168+ * This program is free software; you can redistribute it and/or modify
1169+ * it under the terms of the GNU General Public License as published by
1170+ * the Free Software Foundation; version 3.
1171+ *
1172+ * This program is distributed in the hope that it will be useful,
1173+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1174+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1175+ * GNU General Public License for more details.
1176+ *
1177+ * You should have received a copy of the GNU General Public License
1178+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1179+ */
1180+
1181+#ifndef UNITY_MOCK_LIGHTS_H
1182+#define UNITY_MOCK_LIGHTS_H
1183+
1184+#include <QtCore/QObject>
1185+#include <QtGui/QColor>
1186+
1187+class Lights: public QObject
1188+{
1189+ Q_OBJECT
1190+ Q_ENUMS(State)
1191+ Q_PROPERTY(State state READ state WRITE setState NOTIFY stateChanged)
1192+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
1193+ Q_PROPERTY(int onMillisec READ onMillisec WRITE setOnMillisec NOTIFY onMillisecChanged)
1194+ Q_PROPERTY(int offMillisec READ offMillisec WRITE setOffMillisec NOTIFY offMillisecChanged)
1195+
1196+public:
1197+ enum State {
1198+ Off,
1199+ On,
1200+ };
1201+
1202+ explicit Lights(QObject *parent = 0);
1203+ ~Lights();
1204+
1205+ void setState(State newState);
1206+ State state() const;
1207+
1208+ void setColor(const QColor &color);
1209+ QColor color() const;
1210+
1211+ int onMillisec() const;
1212+ void setOnMillisec(int onMs);
1213+
1214+ int offMillisec() const;
1215+ void setOffMillisec(int offMs);
1216+
1217+Q_SIGNALS:
1218+ void stateChanged(State newState);
1219+ void colorChanged(const QColor &color);
1220+ void onMillisecChanged(int onMs);
1221+ void offMillisecChanged(int offMs);
1222+
1223+private:
1224+ QColor m_color;
1225+ State m_state;
1226+ int m_onMs;
1227+ int m_offMs;
1228+};
1229+
1230+#endif
1231
1232=== added file 'tests/mocks/Lights/Lights.qmltypes'
1233--- tests/mocks/Lights/Lights.qmltypes 1970-01-01 00:00:00 +0000
1234+++ tests/mocks/Lights/Lights.qmltypes 2014-12-17 11:19:14 +0000
1235@@ -0,0 +1,45 @@
1236+import QtQuick.tooling 1.1
1237+
1238+// This file describes the plugin-supplied types contained in the library.
1239+// It is used for QML tooling purposes only.
1240+//
1241+// This file was auto-generated by:
1242+// 'qmlplugindump -notrelocatable Lights 0.1 tests/mocks'
1243+
1244+Module {
1245+ Component {
1246+ name: "Lights"
1247+ prototype: "QObject"
1248+ exports: ["Lights/Lights 0.1"]
1249+ isCreatable: false
1250+ isSingleton: true
1251+ exportMetaObjectRevisions: [0]
1252+ Enum {
1253+ name: "State"
1254+ values: {
1255+ "Off": 0,
1256+ "On": 1
1257+ }
1258+ }
1259+ Property { name: "state"; type: "State" }
1260+ Property { name: "color"; type: "QColor" }
1261+ Property { name: "onMillisec"; type: "int" }
1262+ Property { name: "offMillisec"; type: "int" }
1263+ Signal {
1264+ name: "stateChanged"
1265+ Parameter { name: "newState"; type: "State" }
1266+ }
1267+ Signal {
1268+ name: "colorChanged"
1269+ Parameter { name: "color"; type: "QColor" }
1270+ }
1271+ Signal {
1272+ name: "onMillisecChanged"
1273+ Parameter { name: "onMs"; type: "int" }
1274+ }
1275+ Signal {
1276+ name: "offMillisecChanged"
1277+ Parameter { name: "offMs"; type: "int" }
1278+ }
1279+ }
1280+}
1281
1282=== added file 'tests/mocks/Lights/plugin.cpp'
1283--- tests/mocks/Lights/plugin.cpp 1970-01-01 00:00:00 +0000
1284+++ tests/mocks/Lights/plugin.cpp 2014-12-17 11:19:14 +0000
1285@@ -0,0 +1,33 @@
1286+/*
1287+ * Copyright (C) 2012,2013 Canonical, Ltd.
1288+ *
1289+ * This program is free software; you can redistribute it and/or modify
1290+ * it under the terms of the GNU General Public License as published by
1291+ * the Free Software Foundation; version 3.
1292+ *
1293+ * This program is distributed in the hope that it will be useful,
1294+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1295+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1296+ * GNU General Public License for more details.
1297+ *
1298+ * You should have received a copy of the GNU General Public License
1299+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1300+ */
1301+
1302+#include "plugin.h"
1303+#include "Lights.h"
1304+
1305+#include <QtQml/qqml.h>
1306+
1307+static QObject *lights_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
1308+{
1309+ Q_UNUSED(engine)
1310+ Q_UNUSED(scriptEngine)
1311+ return new Lights();
1312+}
1313+
1314+void PowerdPlugin::registerTypes(const char *uri)
1315+{
1316+ Q_ASSERT(uri == QLatin1String("Lights"));
1317+ qmlRegisterSingletonType<Lights>(uri, 0, 1, "Lights", lights_provider);
1318+}
1319
1320=== added file 'tests/mocks/Lights/plugin.h'
1321--- tests/mocks/Lights/plugin.h 1970-01-01 00:00:00 +0000
1322+++ tests/mocks/Lights/plugin.h 2014-12-17 11:19:14 +0000
1323@@ -0,0 +1,32 @@
1324+/*
1325+ * Copyright (C) 2012,2013 Canonical, Ltd.
1326+ *
1327+ * This program is free software; you can redistribute it and/or modify
1328+ * it under the terms of the GNU General Public License as published by
1329+ * the Free Software Foundation; version 3.
1330+ *
1331+ * This program is distributed in the hope that it will be useful,
1332+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1333+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1334+ * GNU General Public License for more details.
1335+ *
1336+ * You should have received a copy of the GNU General Public License
1337+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1338+ */
1339+
1340+#ifndef MOCK_POWER_PLUGIN_H
1341+#define MOCK_POWER_PLUGIN_H
1342+
1343+#include <QtQml/QQmlEngine>
1344+#include <QtQml/QQmlExtensionPlugin>
1345+
1346+class PowerdPlugin : public QQmlExtensionPlugin
1347+{
1348+ Q_OBJECT
1349+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1350+
1351+public:
1352+ void registerTypes(const char *uri);
1353+};
1354+
1355+#endif
1356
1357=== added file 'tests/mocks/Lights/qmldir'
1358--- tests/mocks/Lights/qmldir 1970-01-01 00:00:00 +0000
1359+++ tests/mocks/Lights/qmldir 2014-12-17 11:19:14 +0000
1360@@ -0,0 +1,3 @@
1361+module Lights
1362+plugin MockLights-qml
1363+typeinfo Lights.qmltypes
1364
1365=== modified file 'tests/mocks/QMenuModel/CMakeLists.txt'
1366--- tests/mocks/QMenuModel/CMakeLists.txt 2014-11-14 17:47:00 +0000
1367+++ tests/mocks/QMenuModel/CMakeLists.txt 2014-12-17 11:19:14 +0000
1368@@ -4,6 +4,7 @@
1369 )
1370
1371 set(QMenuModelQml_SOURCES
1372+ actiondata.h
1373 actionstateparser.cpp
1374 dbus-enums.h
1375 plugin.cpp
1376
1377=== modified file 'tests/mocks/QMenuModel/QDBusActionGroup.qml'
1378--- tests/mocks/QMenuModel/QDBusActionGroup.qml 2014-11-21 19:28:16 +0000
1379+++ tests/mocks/QMenuModel/QDBusActionGroup.qml 2014-12-17 11:19:14 +0000
1380@@ -19,81 +19,34 @@
1381
1382 import QtQuick 2.0
1383 import Ubuntu.Settings.Menus 0.1 as Menus
1384+import QMenuModel 0.1
1385
1386 QtObject {
1387 id: actionGroup
1388 property int busType
1389 property string busName
1390 property string objectPath
1391+ property var actions: ActionData ? ActionData.data : undefined
1392+
1393+ signal dataChanged
1394+
1395 function start() {}
1396+
1397 function action(actionName) {
1398- switch (actionName) {
1399- case "transfer-state.queued":
1400- return {
1401- 'valid': true,
1402- 'state': {
1403- 'state': Menus.TransferState.Queued,
1404- 'percent': 0.0
1405- }
1406- }
1407- case "transfer-state.running":
1408- return {
1409- 'valid': true,
1410- 'state': {
1411- 'state': Menus.TransferState.Running,
1412- 'seconds-left': 100,
1413- 'percent': 0.1
1414- }
1415- }
1416- case "transfer-state.paused":
1417- return {
1418- 'valid': true,
1419- 'state': {
1420- 'state': Menus.TransferState.Paused,
1421- 'seconds-left': 100,
1422- 'percent': 0.5
1423- }
1424- }
1425- case "transfer-state.cancelled":
1426- return {
1427- 'valid': true,
1428- 'state': {
1429- 'state': Menus.TransferState.Canceled,
1430- 'percent': 0.4
1431- }
1432- }
1433- case "transfer-state.finished": return {
1434- 'valid': true,
1435- 'state': {
1436- 'state': Menus.TransferState.Finished,
1437- 'seconds-left': 0,
1438- 'percent': 1.0
1439- }
1440- }
1441- case "transfer-state.error":
1442- return {
1443- 'valid': true,
1444- 'state': {
1445- 'state': Menus.TransferState.Error,
1446- 'seconds-left': 100,
1447- 'percent': 0.0
1448- }
1449- }
1450- case "gps-detection-enabled":
1451- case "location-detection-enabled":
1452- return Qt.createQmlObject("
1453-import QtQuick 2.3
1454-QtObject {
1455- property bool valid: true
1456- property bool state: false
1457- function activate() {
1458- state = !state;
1459- }
1460-}", actionGroup);
1461- default:
1462- break;
1463- }
1464-
1465- return null;
1466+ return Qt.createQmlObject("
1467+ import QtQuick 2.3
1468+ import QMenuModel 0.1
1469+
1470+ QtObject {
1471+ signal activated
1472+
1473+ property string actionName: \"" + actionName + "\"
1474+ property bool valid: ActionData.data[actionName] != undefined ? ActionData.data[actionName].valid : false
1475+ property var state: ActionData.data[actionName] != undefined ? ActionData.data[actionName].state : undefined
1476+
1477+ function activate() {
1478+ activated();
1479+ }
1480+ }", actionGroup);
1481 }
1482 }
1483
1484=== added file 'tests/mocks/QMenuModel/actiondata.h'
1485--- tests/mocks/QMenuModel/actiondata.h 1970-01-01 00:00:00 +0000
1486+++ tests/mocks/QMenuModel/actiondata.h 2014-12-17 11:19:14 +0000
1487@@ -0,0 +1,52 @@
1488+/*
1489+ * Copyright (C) 2013 Canonical, Ltd.
1490+ *
1491+ * This program is free software; you can redistribute it and/or modify
1492+ * it under the terms of the GNU General Public License as published by
1493+ * the Free Software Foundation; version 3.
1494+ *
1495+ * This program is distributed in the hope that it will be useful,
1496+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1497+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1498+ * GNU General Public License for more details.
1499+ *
1500+ * You should have received a copy of the GNU General Public License
1501+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1502+ *
1503+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
1504+ */
1505+
1506+#ifndef ACTIONDATA_H
1507+#define ACTIONDATA_H
1508+
1509+#include <QObject>
1510+#include <QVariant>
1511+
1512+typedef struct _GVariant GVariant;
1513+
1514+class Q_DECL_EXPORT ActionData : public QObject
1515+{
1516+ Q_OBJECT
1517+ Q_PROPERTY(QVariant data READ data WRITE setData NOTIFY dataChanged)
1518+public:
1519+ ActionData(QObject* parent = 0)
1520+ : QObject(parent)
1521+ {}
1522+
1523+ QVariant data() const { return m_data; }
1524+ void setData(const QVariant& data)
1525+ {
1526+ if (m_data != data) {
1527+ m_data = data;
1528+ Q_EMIT dataChanged();
1529+ }
1530+ }
1531+
1532+Q_SIGNALS:
1533+ void dataChanged();
1534+
1535+private:
1536+ QVariant m_data;
1537+};
1538+
1539+#endif // ACTIONDATA_H
1540
1541=== modified file 'tests/mocks/QMenuModel/plugin.cpp'
1542--- tests/mocks/QMenuModel/plugin.cpp 2014-11-14 17:47:00 +0000
1543+++ tests/mocks/QMenuModel/plugin.cpp 2014-12-17 11:19:14 +0000
1544@@ -18,11 +18,19 @@
1545
1546 #include "plugin.h"
1547 #include "unitymenumodel.h"
1548+#include "actiondata.h"
1549 #include "actionstateparser.h"
1550 #include "dbus-enums.h"
1551
1552 #include <QtQml/qqml.h>
1553
1554+static QObject* actionDataSingleton(QQmlEngine* engine, QJSEngine* scriptEngine)
1555+{
1556+ Q_UNUSED(engine);
1557+ Q_UNUSED(scriptEngine);
1558+ return new ActionData;
1559+}
1560+
1561 void QMenuModelPlugin::registerTypes(const char *uri)
1562 {
1563 Q_ASSERT(uri == QLatin1String("QMenuModel"));
1564@@ -30,4 +38,6 @@
1565 "DBus is only a namespace");
1566 qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
1567 qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
1568+
1569+ qmlRegisterSingletonType<ActionData>(uri, 0, 1, "ActionData", actionDataSingleton);
1570 }
1571
1572=== added file 'tests/mocks/Unity/Indicators/ActionRootState.qml'
1573--- tests/mocks/Unity/Indicators/ActionRootState.qml 1970-01-01 00:00:00 +0000
1574+++ tests/mocks/Unity/Indicators/ActionRootState.qml 2014-12-17 11:19:14 +0000
1575@@ -0,0 +1,46 @@
1576+/*
1577+ * Copyright 2013 Canonical Ltd.
1578+ *
1579+ * This program is free software; you can redistribute it and/or modify
1580+ * it under the terms of the GNU Lesser General Public License as published by
1581+ * the Free Software Foundation; version 3.
1582+ *
1583+ * This program is distributed in the hope that it will be useful,
1584+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1585+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1586+ * GNU Lesser General Public License for more details.
1587+ *
1588+ * You should have received a copy of the GNU Lesser General Public License
1589+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1590+ *
1591+ * Authors:
1592+ * Nick Dedekind <nick.dedekind@canonical.com>
1593+ */
1594+
1595+import QtQuick 2.0
1596+
1597+QtObject {
1598+ property var actionGroup
1599+ property var actionName
1600+
1601+ property var action: actionGroup ? actionGroup.actions[actionName] : undefined
1602+ property var state: action && action.hasOwnProperty("state") ? action.state : undefined
1603+
1604+ property bool valid: action && action.hasOwnProperty("valid") ? action.valid : false
1605+ property string title: state && state.hasOwnProperty("title") ? state["title"] : ""
1606+ property string leftLabel: state && state.hasOwnProperty("pre-label") ? state["pre-label"] : ""
1607+ property string rightLabel: state && state.hasOwnProperty("label") ? state["label"] : ""
1608+ property var icons: state && state.hasOwnProperty("icons") ? state["icons"] : []
1609+ property string accessibleName: state && state.hasOwnProperty("accessible-desc") ? state["accessible-desc"] : ""
1610+ property bool visible: state && state.hasOwnProperty("visible") ? state["visible"] : true
1611+
1612+ signal updated
1613+
1614+ onValidChanged: updated()
1615+ onTitleChanged: updated()
1616+ onLeftLabelChanged: updated()
1617+ onRightLabelChanged: updated()
1618+ onIconsChanged: updated()
1619+ onAccessibleNameChanged: updated()
1620+ onVisibleChanged: updated()
1621+}
1622
1623=== renamed file 'tests/mocks/Unity/Indicators/RootActionState.qml' => 'tests/mocks/Unity/Indicators/ModelActionRootState.qml'
1624=== modified file 'tests/mocks/Unity/Indicators/qmldir'
1625--- tests/mocks/Unity/Indicators/qmldir 2014-10-07 10:28:59 +0000
1626+++ tests/mocks/Unity/Indicators/qmldir 2014-12-17 11:19:14 +0000
1627@@ -2,5 +2,6 @@
1628 plugin IndicatorsFakeQml
1629 typeinfo Indicators.qmltypes
1630
1631+ActionRootState 0.1 ActionRootState.qml
1632 IndicatorsModel 0.1 IndicatorsModel.qml
1633-RootActionState 0.1 RootActionState.qml
1634+ModelActionRootState 0.1 ModelActionRootState.qml
1635
1636=== modified file 'tests/plugins/Unity/Indicators/rootactionstatetest.cpp'
1637--- tests/plugins/Unity/Indicators/rootactionstatetest.cpp 2014-08-26 08:14:44 +0000
1638+++ tests/plugins/Unity/Indicators/rootactionstatetest.cpp 2014-12-17 11:19:14 +0000
1639@@ -17,7 +17,7 @@
1640 * Nick Dedekind <nick.dedekind@canonical.com>
1641 */
1642
1643-#include "rootactionstate.h"
1644+#include "modelactionrootstate.h"
1645
1646 #include <unitymenumodel.h>
1647 #include <QtTest>
1648@@ -32,7 +32,7 @@
1649 {
1650 UnityMenuModel* menuModel = new UnityMenuModel();
1651 ActionStateParser* originalParser = menuModel->actionStateParser();
1652- RootActionState* rootState = new RootActionState();
1653+ ModelActionRootState* rootState = new ModelActionRootState();
1654
1655 rootState->setMenu(menuModel);
1656
1657@@ -44,7 +44,7 @@
1658 void testDeleteUnityMenuModel()
1659 {
1660 UnityMenuModel* menuModel = new UnityMenuModel();
1661- RootActionState* rootState = new RootActionState();
1662+ ModelActionRootState* rootState = new ModelActionRootState();
1663
1664 rootState->setMenu(menuModel);
1665
1666@@ -77,7 +77,7 @@
1667
1668 GVariant* params = g_variant_builder_end (&builderParams);
1669
1670- RootActionState rootState;
1671+ RootStateParser rootState;
1672 QVariant result = rootState.toQVariant(params);
1673 g_variant_unref(params);
1674
1675
1676=== modified file 'tests/qmltests/CMakeLists.txt'
1677--- tests/qmltests/CMakeLists.txt 2014-12-08 13:39:01 +0000
1678+++ tests/qmltests/CMakeLists.txt 2014-12-17 11:19:14 +0000
1679@@ -79,6 +79,7 @@
1680 add_qml_test(Panel MenuContent ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
1681 add_qml_test(Panel Panel ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
1682 add_qml_test(Panel SearchIndicator)
1683+add_qml_test(Panel/Indicators IndicatorsLight ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
1684 # These MenuItemFactory tests need the test/mocks/ to come before plugins/
1685 add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
1686 add_qml_test(Panel/Indicators MessageMenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
1687
1688=== added file 'tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml'
1689--- tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml 1970-01-01 00:00:00 +0000
1690+++ tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml 2014-12-17 11:19:14 +0000
1691@@ -0,0 +1,129 @@
1692+/*
1693+ * Copyright 2014 Canonical Ltd.
1694+ *
1695+ * This program is free software; you can redistribute it and/or modify
1696+ * it under the terms of the GNU General Public License as published by
1697+ * the Free Software Foundation; version 3.
1698+ *
1699+ * This program is distributed in the hope that it will be useful,
1700+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1701+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1702+ * GNU General Public License for more details.
1703+ *
1704+ * You should have received a copy of the GNU General Public License
1705+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1706+ */
1707+
1708+import QtQuick 2.0
1709+import QtQuick.Layouts 1.1
1710+import Unity.Test 0.1 as UT
1711+import Unity.Indicators 0.1 as Indicators
1712+import Ubuntu.Components 1.1
1713+import Powerd 0.1
1714+import Lights 0.1
1715+import QMenuModel 0.1
1716+import "../../../../qml/Panel/Indicators"
1717+
1718+Item {
1719+ id: root
1720+ width: units.gu(30)
1721+ height: units.gu(30)
1722+
1723+ property var newMessage: {
1724+ "messages" : {
1725+ 'valid': true,
1726+ 'state': {
1727+ 'icons': [ 'indicator-messages-new' ]
1728+ }
1729+ }
1730+ };
1731+ property var noNewMessage: {
1732+ "messages" : {
1733+ 'valid': true,
1734+ 'state': {
1735+ 'icons': [ 'indicator-messages' ]
1736+ }
1737+ }
1738+ };
1739+
1740+ Component {
1741+ id: light
1742+ IndicatorsLight {}
1743+ }
1744+
1745+ Loader {
1746+ id: loader
1747+ sourceComponent: light
1748+ }
1749+
1750+ Component.onCompleted: {
1751+ ActionData.data = newMessage;
1752+ Powerd.status = Powerd.On
1753+ }
1754+
1755+ RowLayout {
1756+ anchors.fill: parent
1757+ anchors.margins: units.gu(1)
1758+
1759+ Item {
1760+ Layout.fillWidth: true
1761+ Layout.fillHeight: true
1762+
1763+ Rectangle {
1764+ width: units.gu(4)
1765+ height: width
1766+ radius: width / 2
1767+ anchors.centerIn: parent
1768+
1769+ color: Lights.state === Lights.On ? Lights.color : "transparent"
1770+
1771+ border.color: "black"
1772+ border.width: 1
1773+ }
1774+ }
1775+
1776+ ColumnLayout {
1777+ Layout.alignment: Qt.AlignTop
1778+ Layout.fillWidth: false
1779+ Layout.preferredWidth: units.gu(15)
1780+
1781+ Button {
1782+ Layout.fillWidth: true
1783+ text: Powerd.status === Powerd.On ? "Power Off" : "Power On"
1784+ onClicked: {
1785+ if (Powerd.status === Powerd.On) Powerd.status = Powerd.Off;
1786+ else Powerd.status = Powerd.On;
1787+ }
1788+ }
1789+ }
1790+ }
1791+
1792+ UT.UnityTestCase {
1793+ name: "IndicatorsLight"
1794+ when: windowShown
1795+
1796+ function init() {
1797+ // reload
1798+ ActionData.data = noNewMessage;
1799+ loader.sourceComponent = undefined;
1800+ loader.sourceComponent = light;
1801+ Powerd.status = Powerd.On
1802+ }
1803+
1804+ function test_LightsStatus_data() {
1805+ return [
1806+ { tag: "Powerd.On with No Message", powerd: Powerd.On, actionData: noNewMessage, expected: Lights.Off },
1807+ { tag: "Powerd.Off with No Message", powerd: Powerd.Off, actionData: noNewMessage, expected: Lights.Off },
1808+ { tag: "Powerd.On with New Message", powerd: Powerd.On, actionData: newMessage, expected: Lights.Off },
1809+ { tag: "Powerd.Off with New Message", powerd: Powerd.Off, actionData: newMessage, expected: Lights.On },
1810+ ]
1811+ }
1812+
1813+ function test_LightsStatus(data) {
1814+ Powerd.status = data.powerd;
1815+ ActionData.data = data.actionData;
1816+
1817+ compare(Lights.state, data.expected, "Light does not match expected value");
1818+ }
1819+ }
1820+}
1821
1822=== modified file 'tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml'
1823--- tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2014-10-09 17:06:00 +0000
1824+++ tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2014-12-17 11:19:14 +0000
1825@@ -17,6 +17,7 @@
1826 import QtQuick 2.0
1827 import QtTest 1.0
1828 import Unity.Test 0.1 as UT
1829+import Ubuntu.Settings.Menus 0.1 as Menus
1830 import QMenuModel 0.1
1831 import Utils 0.1 as Utils
1832 import "../../../../qml/Panel/Indicators"
1833@@ -448,9 +449,59 @@
1834 }
1835
1836 function test_create_transferMenu(data) {
1837+ ActionData.data = {
1838+ "transfer-state.queued": {
1839+ 'valid': true,
1840+ 'state': {
1841+ 'state': Menus.TransferState.Queued,
1842+ 'percent': data.progress
1843+ }
1844+ },
1845+ "transfer-state.running": {
1846+ 'valid': true,
1847+ 'state': {
1848+ 'state': Menus.TransferState.Running,
1849+ 'seconds-left': 100,
1850+ 'percent': data.progress
1851+ }
1852+ },
1853+ "transfer-state.paused": {
1854+ 'valid': true,
1855+ 'state': {
1856+ 'state': Menus.TransferState.Paused,
1857+ 'seconds-left': 100,
1858+ 'percent': data.progress
1859+ }
1860+ },
1861+ "transfer-state.cancelled": {
1862+ 'valid': true,
1863+ 'state': {
1864+ 'state': Menus.TransferState.Canceled,
1865+ 'percent': data.progress
1866+ }
1867+ },
1868+ "transfer-state.finished": {
1869+ 'valid': true,
1870+ 'state': {
1871+ 'state': Menus.TransferState.Finished,
1872+ 'seconds-left': 0,
1873+ 'percent': data.progress
1874+ }
1875+ },
1876+ "transfer-state.error": {
1877+ 'valid': true,
1878+ 'state': {
1879+ 'state': Menus.TransferState.Error,
1880+ 'seconds-left': 100,
1881+ 'percent': data.progress
1882+ }
1883+ }
1884+ };
1885+
1886 menuData.type = "com.canonical.indicator.transfer";
1887 menuData.label = data.label;
1888 menuData.sensitive = data.enabled;
1889+ menuData.isToggled = data.active;
1890 menuData.icon = data.icon;
1891 menuData.ext = {
1892 'xCanonicalUid': data.tag
1893@@ -464,7 +515,7 @@
1894 compare(loader.item.text, data.label, "Label does not match data");
1895 compare(loader.item.iconSource, data.icon, "Icon does not match data");
1896 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
1897- compare(loader.item.progress, data.progress, "Icon does not match data");
1898+ compare(loader.item.progress, data.progress, "Progress does not match data");
1899 compare(loader.item.active, data.active, "Active does not match data");
1900 compare(loader.item.stateText, data.stateText, "State text does not match data");
1901 }
1902
1903=== modified file 'tests/qmltests/Wizard/tst_Wizard.qml'
1904--- tests/qmltests/Wizard/tst_Wizard.qml 2014-12-02 17:43:25 +0000
1905+++ tests/qmltests/Wizard/tst_Wizard.qml 2014-12-17 11:19:14 +0000
1906@@ -18,6 +18,7 @@
1907 import QtTest 1.0
1908 import AccountsService 0.1
1909 import MeeGo.QOfono 0.2
1910+import QMenuModel 0.1
1911 import Ubuntu.Components 1.1
1912 import Ubuntu.SystemSettings.SecurityPrivacy 1.0
1913 import Unity.Test 0.1 as UT
1914@@ -58,6 +59,16 @@
1915 signalName: "setSecurityCalled"
1916 }
1917
1918+ SignalSpy {
1919+ id: activateLocationSpy
1920+ signalName: "activated"
1921+ }
1922+
1923+ SignalSpy {
1924+ id: activateGPSSpy
1925+ signalName: "activated"
1926+ }
1927+
1928 function setup() {
1929 AccountsService.hereEnabled = false;
1930 AccountsService.hereLicensePath = Qt.resolvedUrl("licenses");
1931@@ -68,6 +79,19 @@
1932
1933 updateSessionLanguageSpy.clear();
1934 setSecuritySpy.clear();
1935+ activateLocationSpy.clear();
1936+ activateGPSSpy.clear();
1937+
1938+ ActionData.data = {
1939+ "location-detection-enabled": {
1940+ 'valid': true,
1941+ 'state': false
1942+ },
1943+ "gps-detection-enabled": {
1944+ 'valid': true,
1945+ 'state': false
1946+ }
1947+ };
1948 }
1949
1950 Component.onCompleted: {
1951@@ -360,8 +384,8 @@
1952 var nopeCheck = findChild(page, "nopeCheck");
1953
1954 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
1955- tryCompare(locationActionGroup.location, "state", false);
1956- tryCompare(locationActionGroup.gps, "state", false);
1957+ activateLocationSpy.target = locationActionGroup.location;
1958+ activateGPSSpy.target = locationActionGroup.gps;
1959
1960 tap(gpsCheck);
1961 tryCompare(gpsCheck, "checked", true);
1962@@ -370,8 +394,8 @@
1963
1964 tap(findChild(page, "forwardButton"));
1965 tryCompare(AccountsService, "hereEnabled", false);
1966- tryCompare(locationActionGroup.location, "state", true);
1967- tryCompare(locationActionGroup.gps, "state", true);
1968+ tryCompare(activateLocationSpy, "count", 1)
1969+ tryCompare(activateGPSSpy, "count", 1)
1970 }
1971
1972 function test_locationNope() {
1973@@ -381,8 +405,8 @@
1974 var nopeCheck = findChild(page, "nopeCheck");
1975
1976 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
1977- tryCompare(locationActionGroup.location, "state", false);
1978- tryCompare(locationActionGroup.gps, "state", false);
1979+ activateLocationSpy.target = locationActionGroup.location;
1980+ activateGPSSpy.target = locationActionGroup.gps;
1981
1982 tap(nopeCheck);
1983 tryCompare(gpsCheck, "checked", false);
1984@@ -391,8 +415,8 @@
1985
1986 tap(findChild(page, "forwardButton"));
1987 tryCompare(AccountsService, "hereEnabled", false);
1988- tryCompare(locationActionGroup.location, "state", false);
1989- tryCompare(locationActionGroup.gps, "state", false);
1990+ tryCompare(activateLocationSpy, "count", 0)
1991+ tryCompare(activateGPSSpy, "count", 0)
1992 }
1993
1994 function test_locationHere() {
1995@@ -402,8 +426,8 @@
1996 var nopeCheck = findChild(page, "nopeCheck");
1997
1998 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
1999- tryCompare(locationActionGroup.location, "state", false);
2000- tryCompare(locationActionGroup.gps, "state", false);
2001+ activateLocationSpy.target = locationActionGroup.location;
2002+ activateGPSSpy.target = locationActionGroup.gps;
2003
2004 // no tap because HERE is the default
2005 tryCompare(gpsCheck, "checked", false);
2006@@ -412,8 +436,8 @@
2007
2008 tap(findChild(page, "forwardButton"));
2009 tryCompare(AccountsService, "hereEnabled", true);
2010- tryCompare(locationActionGroup.location, "state", true);
2011- tryCompare(locationActionGroup.gps, "state", true);
2012+ tryCompare(activateLocationSpy, "count", 1)
2013+ tryCompare(activateGPSSpy, "count", 1)
2014 }
2015
2016 function test_locationHereTerms() {

Subscribers

People subscribed via source and target branches