Merge lp:~nick-dedekind/unity8/1390136.laggy-backends into lp:unity8

Proposed by Nick Dedekind on 2015-04-02
Status: Merged
Approved by: Michał Sawicz on 2015-04-07
Approved revision: 1671
Merged at revision: 1711
Proposed branch: lp:~nick-dedekind/unity8/1390136.laggy-backends
Merge into: lp:unity8
Prerequisite: lp:~dandrader/unity8/mouseClickSwitchesSurfaceFocus
Diff against target: 1370 lines (+839/-90)
29 files modified
CMakeLists.txt (+2/-0)
data/CMakeLists.txt (+2/-0)
data/indicators-client.desktop.in (+9/-0)
data/unity-mock-indicator-service.conf (+7/-0)
debian/control (+2/-2)
debian/indicators-client.install (+1/-0)
debian/unity8-autopilot.install (+3/-1)
include/paths.h.in (+1/-6)
plugins/Utils/CMakeLists.txt (+1/-0)
plugins/Utils/constants.cpp (+27/-0)
plugins/Utils/constants.h (+43/-0)
plugins/Utils/plugin.cpp (+9/-0)
qml/Panel/Indicators/MenuItemFactory.qml (+52/-56)
qml/Panel/Indicators/client/IndicatorsList.qml (+2/-2)
run.sh (+1/-1)
src/Panel/Indicators/client/CMakeLists.txt (+0/-2)
tests/autopilot/unity8/fixture_setup.py (+46/-1)
tests/autopilot/unity8/indicators/__init__.py (+90/-11)
tests/autopilot/unity8/indicators/tests/__init__.py (+7/-0)
tests/autopilot/unity8/indicators/tests/test_action_latency.py (+232/-0)
tests/autopilot/unity8/indicators/tests/test_display_indicator.py (+3/-1)
tests/autopilot/unity8/indicators/tests/test_indicators.py (+2/-2)
tests/mocks/CMakeLists.txt (+1/-0)
tests/mocks/data/unity/indicators/com.canonical.indicator.mock (+10/-0)
tests/mocks/indicator-service/CMakeLists.txt (+20/-0)
tests/mocks/indicator-service/mock-indicator-service.c (+261/-0)
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp (+0/-2)
tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp (+0/-2)
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml (+5/-1)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/1390136.laggy-backends
Reviewer Review Type Date Requested Status
Michał Sawicz Approve on 2015-04-07
PS Jenkins bot continuous-integration 2015-04-02 Needs Fixing on 2015-04-02
Andrea Cimitan 2015-04-02 Pending
Review via email: mp+255062@code.launchpad.net

This proposal supersedes a proposal from 2015-03-12.

Commit Message

Made improvements for laggy indicator backends (lp#1390136).

Description of the Change

 * Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/ubuntu-settings-components/1390136.laggy-backends/+merge/252754

 * 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.
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Text conflict in tests/autopilot/unity8/indicators/__init__.py
Text conflict in tests/autopilot/unity8/indicators/tests/__init__.py
2 conflicts encountered.

Andrea Cimitan (cimi) wrote : Posted in a previous version of this proposal

just coding style comments for now, still finishing to see if all code looks reasonable, tested and is fine... in progress.

Andrea Cimitan (cimi) wrote : Posted in a previous version of this proposal

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
 * Did CI run pass? If not, please explain why.
no, but passed locally
 * Did you make sure that the branch does not contain spurious tags?
yes

review: Approve
Michał Sawicz (saviq) :
review: Needs Fixing
Michał Sawicz (saviq) wrote :

You need a bumped dependency on settings components, otherwise we can get into unbootable:

file:///usr/share/unity8/Shell.qml:459:9: Type Panel unavailable
             Panel {
             ^
file:///usr/share/unity8/Panel/Panel.qml:119:9: Type IndicatorsMenu unavailable
             IndicatorsMenu {
             ^
file:///usr/share/unity8/Panel/IndicatorsMenu.qml:73:5: Type MenuContent unavailable
         MenuContent {
         ^
file:///usr/share/unity8/Panel/MenuContent.qml:66:30: Type IndicatorPage unavailable
                 sourceComponent: IndicatorPage {
                                  ^
file:///usr/share/unity8/Panel/IndicatorPage.qml:177:5: Type MenuItemFactory unavailable
         MenuItemFactory {
         ^
file:///usr/share/unity8/Panel/Indicators/MenuItemFactory.qml:127:13: ServerPropertySynchroniser is not a type
                 ServerPropertySynchroniser {
                 ^

review: Needs Fixing
1669. By Nick Dedekind on 2015-04-02

bumped version

Michał Sawicz (saviq) wrote :

Some inline comments.

review: Needs Fixing
Brendan Donegan (brendan-donegan) wrote :

Few small comments, nothing that needs fixing really

1670. By Nick Dedekind on 2015-04-07

review comments

Nick Dedekind (nick-dedekind) wrote :

> Some inline comments.

Done.

1671. By Nick Dedekind on 2015-04-07

revert re-order

Michał Sawicz (saviq) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-02-19 10:04:47 +0000
3+++ CMakeLists.txt 2015-04-07 11:50:57 +0000
4@@ -105,6 +105,8 @@
5 set(SHELL_APP unity8)
6 set(DASH_APP unity8-dash)
7 set(SCOPE_TOOL unity-scope-tool)
8+set(INDICATORS_CLIENT_APP indicators-client)
9+set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
10
11 include_directories(
12 ${CMAKE_SOURCE_DIR}/include
13
14=== modified file 'data/CMakeLists.txt'
15--- data/CMakeLists.txt 2015-02-17 17:15:53 +0000
16+++ data/CMakeLists.txt 2015-04-07 11:50:57 +0000
17@@ -1,11 +1,13 @@
18 # generate desktop files
19 configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
20 configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
21+configure_file(${INDICATORS_CLIENT_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop @ONLY)
22
23 # install desktop files
24 install(FILES
25 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
26 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
27+ ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
28 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
29 )
30
31
32=== added file 'data/indicators-client.desktop.in'
33--- data/indicators-client.desktop.in 1970-01-01 00:00:00 +0000
34+++ data/indicators-client.desktop.in 2015-04-07 11:50:57 +0000
35@@ -0,0 +1,9 @@
36+[Desktop Entry]
37+Type=Application
38+Name=Indicators Client
39+Comment=Application for testing the Indicators system
40+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/indicators-client
41+Terminal=false
42+Icon=
43+NoDisplay=false
44+X-Ubuntu-Touch=true
45
46=== added file 'data/unity-mock-indicator-service.conf'
47--- data/unity-mock-indicator-service.conf 1970-01-01 00:00:00 +0000
48+++ data/unity-mock-indicator-service.conf 2015-04-07 11:50:57 +0000
49@@ -0,0 +1,7 @@
50+description "Unity Shell v8 Mock Indicator"
51+author "Nick Dedekind <nick.dedekind@canonical.com>"
52+
53+respawn
54+respawn limit 2 10
55+
56+exec ${BINARY:-unity-mock-indicator-service} $ARGS
57
58=== modified file 'debian/control'
59--- debian/control 2015-03-18 10:18:05 +0000
60+++ debian/control 2015-04-07 11:50:57 +0000
61@@ -47,7 +47,7 @@
62 qtdeclarative5-dev-tools,
63 qtdeclarative5-private-dev (>= 5.2.1),
64 qtdeclarative5-qtmultimedia-plugin,
65- qtdeclarative5-ubuntu-settings-components (>= 0.5),
66+ qtdeclarative5-ubuntu-settings-components (>= 0.6),
67 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
68 qtdeclarative5-ubuntu-web-plugin,
69 ttf-ubuntu-font-family,
70@@ -119,7 +119,7 @@
71 Package: unity8-common
72 Architecture: all
73 Depends: qml-module-qtquick-layouts,
74- qtdeclarative5-ubuntu-settings-components (>= 0.4),
75+ qtdeclarative5-ubuntu-settings-components (>= 0.6),
76 qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
77 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
78 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
79
80=== modified file 'debian/indicators-client.install'
81--- debian/indicators-client.install 2013-06-12 08:44:40 +0000
82+++ debian/indicators-client.install 2015-04-07 11:50:57 +0000
83@@ -1,1 +1,2 @@
84+usr/share/applications/indicators-client.desktop
85 /usr/bin/indicators-client
86
87=== modified file 'debian/unity8-autopilot.install'
88--- debian/unity8-autopilot.install 2014-03-24 15:53:15 +0000
89+++ debian/unity8-autopilot.install 2015-04-07 11:50:57 +0000
90@@ -1,2 +1,4 @@
91+data/unity-mock-indicator-service.conf usr/share/upstart/sessions/
92+usr/bin/unity-mock-indicator-service
93 usr/lib/python*/*/unity*
94-usr/share/unity8/unlock-device
95+usr/share/unity8/unlock-device
96\ No newline at end of file
97
98=== modified file 'include/paths.h.in'
99--- include/paths.h.in 2014-11-14 17:47:00 +0000
100+++ include/paths.h.in 2015-04-07 11:50:57 +0000
101@@ -92,12 +92,7 @@
102
103 inline QStringList shellDataDirs() {
104 QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
105- if (!isRunningInstalled()) {
106- if (getenv("UNITY_TEST_ENV")==nullptr) {
107- dirs.prepend("@CMAKE_BINARY_DIR@/share");
108- }
109- }
110- else {
111+ if (isRunningInstalled()) {
112 // append so by default we use xdg files.
113 dirs.append(qmlDirectory());
114 }
115
116=== modified file 'plugins/Utils/CMakeLists.txt'
117--- plugins/Utils/CMakeLists.txt 2015-04-07 11:50:57 +0000
118+++ plugins/Utils/CMakeLists.txt 2015-04-07 11:50:57 +0000
119@@ -8,6 +8,7 @@
120 )
121
122 set(QMLPLUGIN_SRC
123+ constants.cpp
124 inputwatcher.cpp
125 qlimitproxymodelqml.cpp
126 unitysortfilterproxymodelqml.cpp
127
128=== added file 'plugins/Utils/constants.cpp'
129--- plugins/Utils/constants.cpp 1970-01-01 00:00:00 +0000
130+++ plugins/Utils/constants.cpp 2015-04-07 11:50:57 +0000
131@@ -0,0 +1,27 @@
132+/*
133+ * Copyright 2015 Canonical Ltd.
134+ *
135+ * This program is free software; you can redistribute it and/or modify
136+ * it under the terms of the GNU Lesser General Public License as published by
137+ * the Free Software Foundation; version 3.
138+ *
139+ * This program is distributed in the hope that it will be useful,
140+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
141+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
142+ * GNU Lesser General Public License for more details.
143+ *
144+ * You should have received a copy of the GNU Lesser General Public License
145+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
146+*/
147+
148+#include "constants.h"
149+
150+Constants::Constants(QObject *parent)
151+ : QObject(parent)
152+{
153+ if (qgetenv("QT_LOAD_TESTABILITY").isEmpty()) {
154+ m_indicatorValueTimeout = 30000;
155+ } else {
156+ m_indicatorValueTimeout = 5000;
157+ }
158+}
159
160=== added file 'plugins/Utils/constants.h'
161--- plugins/Utils/constants.h 1970-01-01 00:00:00 +0000
162+++ plugins/Utils/constants.h 2015-04-07 11:50:57 +0000
163@@ -0,0 +1,43 @@
164+/*
165+ * Copyright 2015 Canonical Ltd.
166+ *
167+ * This program is free software; you can redistribute it and/or modify
168+ * it under the terms of the GNU Lesser General Public License as published by
169+ * the Free Software Foundation; version 3.
170+ *
171+ * This program is distributed in the hope that it will be useful,
172+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
173+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
174+ * GNU Lesser General Public License for more details.
175+ *
176+ * You should have received a copy of the GNU Lesser General Public License
177+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
178+*/
179+
180+#ifndef CONSTANTS_H
181+#define CONSTANTS_H
182+
183+#include <QObject>
184+
185+/**
186+ * @brief The Constants class
187+ *
188+ * This singleton class exposes contants to Qml
189+ *
190+ */
191+
192+class Constants: public QObject
193+{
194+ Q_OBJECT
195+ Q_PROPERTY(int indicatorValueTimeout READ indicatorValueTimeout CONSTANT)
196+
197+public:
198+ Constants(QObject *parent = 0);
199+
200+ int indicatorValueTimeout() const { return m_indicatorValueTimeout; }
201+
202+private:
203+ int m_indicatorValueTimeout;
204+};
205+
206+#endif
207
208=== modified file 'plugins/Utils/plugin.cpp'
209--- plugins/Utils/plugin.cpp 2015-04-07 11:50:57 +0000
210+++ plugins/Utils/plugin.cpp 2015-04-07 11:50:57 +0000
211@@ -35,6 +35,7 @@
212 #include "windowkeysfilter.h"
213 #include "easingcurve.h"
214 #include "windowstatestorage.h"
215+#include "constants.h"
216
217 static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
218 {
219@@ -43,6 +44,13 @@
220 return new WindowStateStorage();
221 }
222
223+static QObject *createConstants(QQmlEngine *engine, QJSEngine *scriptEngine)
224+{
225+ Q_UNUSED(engine)
226+ Q_UNUSED(scriptEngine)
227+ return new Constants();
228+}
229+
230 void UtilsPlugin::registerTypes(const char *uri)
231 {
232 Q_ASSERT(uri == QLatin1String("Utils"));
233@@ -57,6 +65,7 @@
234 qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
235 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
236 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
237+ qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
238 }
239
240 void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
241
242=== modified file 'qml/Panel/Indicators/MenuItemFactory.qml'
243--- qml/Panel/Indicators/MenuItemFactory.qml 2014-10-10 15:54:50 +0000
244+++ qml/Panel/Indicators/MenuItemFactory.qml 2015-04-07 11:50:57 +0000
245@@ -19,6 +19,7 @@
246
247 import QtQuick 2.0
248 import Ubuntu.Settings.Menus 0.1 as Menus
249+import Ubuntu.Settings.Components 0.1
250 import QMenuModel 0.1
251 import Utils 0.1 as Utils
252 import Ubuntu.Components.ListItems 0.1 as ListItems
253@@ -84,6 +85,7 @@
254 id: sliderMenu;
255
256 Menus.SliderMenu {
257+ id: sliderItem
258 objectName: "sliderMenu"
259 property QtObject menuData: null
260 property var menuModel: menuFactory.menuModel
261@@ -113,15 +115,6 @@
262 onMenuIndexChanged: {
263 loadAttributes();
264 }
265- onServerValueChanged: {
266- // value can be changed by slider, so a binding won't work.
267- if (serverValue !== undefined) {
268- value = serverValue;
269- }
270- }
271- onUpdated: {
272- menuModel.changeState(menuIndex, value);
273- }
274
275 function loadAttributes() {
276 if (!menuModel || menuIndex == -1) return;
277@@ -130,6 +123,20 @@
278 'min-icon': 'icon',
279 'max-icon': 'icon'});
280 }
281+
282+ ServerPropertySynchroniser {
283+ objectName: "sync"
284+ syncTimeout: Utils.Constants.indicatorValueTimeout
285+ bufferedSyncTimeout: true
286+ maximumWaitBufferInterval: 16
287+
288+ serverTarget: sliderItem
289+ serverProperty: "serverValue"
290+ userTarget: sliderItem
291+ userProperty: "value"
292+
293+ onSyncTriggered: menuModel.changeState(menuIndex, value)
294+ }
295 }
296 }
297
298@@ -280,6 +287,7 @@
299 id: checkableMenu;
300
301 Menus.CheckableMenu {
302+ id: checkItem
303 objectName: "checkableMenu"
304 property QtObject menuData: null
305 property int menuIndex: -1
306@@ -290,26 +298,16 @@
307 checked: serverChecked
308 highlightWhenPressed: false
309
310- onServerCheckedChanged: updateFromServer()
311- onTriggered: {
312- menuModel.activate(menuIndex);
313- resyncTimer.restart();
314- }
315-
316- // value can be changed by menu, so a binding won't work.
317- function updateFromServer() {
318- resyncTimer.stop();
319- if (checked != serverChecked) {
320- checked = serverChecked;
321- }
322- }
323-
324- // Server value is not guaranteed to change to what we expect from an activation.
325- // In this case, we need to re-assert that we are presenting the UI with the set backend value.
326- Timer {
327- id: resyncTimer
328- interval: 1500
329- onTriggered: updateFromServer()
330+ ServerPropertySynchroniser {
331+ objectName: "sync"
332+ syncTimeout: Utils.Constants.indicatorValueTimeout
333+
334+ serverTarget: checkItem
335+ serverProperty: "serverChecked"
336+ userTarget: checkItem
337+ userProperty: "checked"
338+
339+ onSyncTriggered: menuModel.activate(checkItem.menuIndex)
340 }
341 }
342 }
343@@ -318,6 +316,7 @@
344 id: switchMenu;
345
346 Menus.SwitchMenu {
347+ id: switchItem
348 objectName: "switchMenu"
349 property QtObject menuData: null
350 property int menuIndex: -1
351@@ -329,26 +328,16 @@
352 checked: serverChecked
353 highlightWhenPressed: false
354
355- onServerCheckedChanged: updateFromServer()
356- onTriggered: {
357- menuModel.activate(menuIndex);
358- resyncTimer.restart();
359- }
360-
361- // value can be changed by menu, so a binding won't work.
362- function updateFromServer() {
363- resyncTimer.stop();
364- if (checked != serverChecked) {
365- checked = serverChecked;
366- }
367- }
368-
369- // Server value is not guaranteed to change to what we expect from an activation.
370- // In this case, we need to re-assert that we are presenting the UI with the set backend value.
371- Timer {
372- id: resyncTimer
373- interval: 1500
374- onTriggered: updateFromServer()
375+ ServerPropertySynchroniser {
376+ objectName: "sync"
377+ syncTimeout: Utils.Constants.indicatorValueTimeout
378+
379+ serverTarget: switchItem
380+ serverProperty: "serverChecked"
381+ userTarget: switchItem
382+ userProperty: "checked"
383+
384+ onSyncTriggered: menuModel.activate(switchItem.menuIndex);
385 }
386 }
387 }
388@@ -464,6 +453,7 @@
389 id: accessPoint;
390
391 Menus.AccessPointMenu {
392+ id: apItem
393 objectName: "accessPoint"
394 property QtObject menuData: null
395 property var menuModel: menuFactory.menuModel
396@@ -485,19 +475,12 @@
397 signalStrength: strengthAction.valid ? strengthAction.state : 0
398 highlightWhenPressed: false
399
400- onServerCheckedChanged: {
401- // value can be changed by menu, so a binding won't work.
402- active = serverChecked;
403- }
404 onMenuModelChanged: {
405 loadAttributes();
406 }
407 onMenuIndexChanged: {
408 loadAttributes();
409 }
410- onTriggered: {
411- menuModel.activate(menuIndex);
412- }
413
414 function loadAttributes() {
415 if (!menuModel || menuIndex == -1) return;
416@@ -505,6 +488,19 @@
417 'x-canonical-wifi-ap-is-secure': 'bool',
418 'x-canonical-wifi-ap-strength-action': 'string'});
419 }
420+
421+ ServerPropertySynchroniser {
422+ objectName: "sync"
423+ syncTimeout: Utils.Constants.indicatorValueTimeout
424+
425+ serverTarget: apItem
426+ serverProperty: "serverChecked"
427+ userTarget: apItem
428+ userProperty: "active"
429+ userTrigger: "onTriggered"
430+
431+ onSyncTriggered: menuModel.activate(apItem.menuIndex)
432+ }
433 }
434 }
435
436
437=== modified file 'qml/Panel/Indicators/client/IndicatorsList.qml'
438--- qml/Panel/Indicators/client/IndicatorsList.qml 2014-10-23 11:59:22 +0000
439+++ qml/Panel/Indicators/client/IndicatorsList.qml 2015-04-07 11:50:57 +0000
440@@ -31,8 +31,8 @@
441
442 Indicators.IndicatorsModel {
443 id: indicatorsModel
444-
445- Component.onCompleted: load(profile)
446+ profile: page.profile
447+ Component.onCompleted: load()
448 }
449
450 ListView {
451
452=== modified file 'run.sh'
453--- run.sh 2015-01-27 15:50:02 +0000
454+++ run.sh 2015-04-07 11:50:57 +0000
455@@ -65,6 +65,6 @@
456 echo "Unity8 is already running, please stop it first"
457 exit 1
458 fi
459- /sbin/initctl start unity8 BINARY="`readlink -f $QML_PHONE_SHELL_PATH` $QML_PHONE_SHELL_ARGS $@" QML2_IMPORT_PATH=$QML2_IMPORT_PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH
460+ /sbin/initctl start unity8 BINARY="`readlink -f $QML_PHONE_SHELL_PATH` $QML_PHONE_SHELL_ARGS $@" XDG_DATA_DIRS=$XDG_DATA_DIRS QML2_IMPORT_PATH=$QML2_IMPORT_PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH
461 tailf -n 0 ~/.cache/upstart/unity8.log
462 fi
463
464=== modified file 'src/Panel/Indicators/client/CMakeLists.txt'
465--- src/Panel/Indicators/client/CMakeLists.txt 2013-12-17 14:56:25 +0000
466+++ src/Panel/Indicators/client/CMakeLists.txt 2015-04-07 11:50:57 +0000
467@@ -1,5 +1,4 @@
468 project(indicators_client)
469-set(INDICATORS_CLIENT_APP indicators-client)
470
471 set(INDICATORS_CLIENT_SRC
472 main.cpp
473@@ -15,7 +14,6 @@
474 )
475
476 qt5_use_modules(${INDICATORS_CLIENT_APP} Core Widgets Quick)
477-set_target_properties(${INDICATORS_CLIENT_APP} PROPERTIES COMPILE_FLAGS -fPIC)
478
479 install(TARGETS ${INDICATORS_CLIENT_APP}
480 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
481
482=== modified file 'tests/autopilot/unity8/fixture_setup.py'
483--- tests/autopilot/unity8/fixture_setup.py 2015-02-23 17:29:04 +0000
484+++ tests/autopilot/unity8/fixture_setup.py 2015-04-07 11:50:57 +0000
485@@ -19,12 +19,17 @@
486
487 import fixtures
488 import subprocess
489+import logging
490
491 from autopilot import introspection
492
493-from unity8 import process_helpers
494+from unity8 import (
495+ get_binary_path,
496+ process_helpers
497+)
498 from unity8.shell import emulators
499
500+logger = logging.getLogger(__name__)
501
502 class LaunchDashApp(fixtures.Fixture):
503
504@@ -96,3 +101,43 @@
505 'rotation-lock', value_string
506 ]
507 subprocess.check_output(command)
508+
509+class LaunchMockIndicatorService(fixtures.Fixture):
510+
511+ """Fixture to launch the indicator test service."""
512+
513+ def __init__(self, action_delay, ensure_not_running=True):
514+ """Initialize an instance.
515+
516+ :param action_delay: The delay to use when activating actions.
517+ Measured in milliseconds. Value of -1 will result in infinite delay.
518+ :type action_delay: An integer.
519+ :param boolean ensure_not_running: Make sure service is not running
520+
521+ """
522+ super(LaunchMockIndicatorService, self).__init__()
523+ self.action_delay = action_delay
524+ self.ensure_not_running = ensure_not_running
525+
526+ def setUp(self):
527+ super(LaunchMockIndicatorService, self).setUp()
528+ if self.ensure_not_running:
529+ self.ensure_service_not_running()
530+ self.addCleanup(self.stop_service)
531+ self.application_proxy = self.launch_service()
532+
533+ def launch_service(self):
534+ logger.info("Starting unity-mock-indicator-service")
535+ binary_path = get_binary_path('unity-mock-indicator-service')
536+ binary_arg = 'BINARY={}'.format(binary_path)
537+ env_args = 'ARGS=-t {}'.format(self.action_delay)
538+ all_args = [binary_arg, env_args]
539+ process_helpers.start_job('unity-mock-indicator-service', *all_args)
540+
541+ def stop_service(self):
542+ logger.info("Stopping unity-mock-indicator-service")
543+ process_helpers.stop_job('unity-mock-indicator-service')
544+
545+ def ensure_service_not_running(self):
546+ if process_helpers.is_job_running('unity-mock-indicator-service'):
547+ self.stop_service()
548
549=== modified file 'tests/autopilot/unity8/indicators/__init__.py'
550--- tests/autopilot/unity8/indicators/__init__.py 2015-02-23 17:29:04 +0000
551+++ tests/autopilot/unity8/indicators/__init__.py 2015-04-07 11:50:57 +0000
552@@ -19,6 +19,7 @@
553 from autopilot import introspection
554
555 from unity8.shell import emulators
556+from unity8 import fixture_setup
557
558
559 class IndicatorPage(emulators.UnityEmulatorBase):
560@@ -33,26 +34,25 @@
561 def validate_dbus_object(cls, path, state):
562 return False
563
564-
565-class DisplayIndicator():
566-
567- def __init__(self, main_window):
568+class Indicator():
569+
570+ def __init__(self, main_window, name):
571 self._main_window = main_window
572+ self._name = name
573
574 def is_indicator_icon_visible(self):
575 panel_item = self._main_window.wait_select_single(
576- objectName='indicator-rotation-lock-panelItem')
577+ objectName=self._name+'-panelItem')
578 return panel_item.indicatorVisible
579
580 def open(self):
581- """Open the display indicator page.
582+ """Open the indicator page.
583
584- :return: The custom proxy object for the display indicator page.
585+ :return: The custom proxy object for the indicator page.
586
587 """
588 if self.is_indicator_icon_visible():
589- return self._main_window.open_indicator_page(
590- 'indicator-rotation-lock')
591+ return self._main_window.open_indicator_page(self._name)
592 else:
593 return self._open_indicator_with_icon_not_visible()
594
595@@ -61,10 +61,10 @@
596 self._main_window.open_indicator_page('indicator-datetime')
597 self._make_indicator_icon_visible()
598 indicator_rotation_icon = self._main_window.select_single(
599- objectName='indicator-rotation-lock-panelItem')
600+ objectName=self._name+'-panelItem')
601 self._main_window.pointing_device.click_object(indicator_rotation_icon)
602 return self._main_window.wait_select_single(
603- objectName='indicator-rotation-lock-page')
604+ objectName=self._name+'-page')
605
606 def _make_indicator_icon_visible(self):
607 indicators_bar_flickable = self._main_window.select_single(
608@@ -95,6 +95,13 @@
609 self._main_window.close_indicator_page()
610
611
612+class DisplayIndicator(Indicator):
613+
614+ def __init__(self, main_window):
615+ super(DisplayIndicator, self).__init__(main_window, 'indicator-rotation-lock')
616+ self._main_window = main_window
617+
618+
619 class DisplayIndicatorPage(IndicatorPage):
620
621 """Autopilot helper for the display indicator page."""
622@@ -122,3 +129,75 @@
623 switcher = self._get_switcher()
624 switcher.uncheck()
625 switcher.checked.wait_for(False)
626+
627+
628+class TestIndicator(Indicator):
629+
630+ def __init__(self, main_window):
631+ super(TestIndicator, self).__init__(main_window, 'indicator-mock')
632+ self._main_window = main_window
633+
634+
635+class TestIndicatorPage(IndicatorPage):
636+
637+ """Autopilot helper for the mock indicator page."""
638+
639+ @classmethod
640+ def validate_dbus_object(cls, path, state):
641+ name = introspection.get_classname_from_path(path)
642+ if name == b'IndicatorPage':
643+ if state['objectName'][1] == 'indicator-mock-page':
644+ return True
645+ return False
646+
647+ def get_switcher(self):
648+ return self.select_single(
649+ ubuntuuitoolkit.CheckBox, objectName='switcher')
650+
651+ def get_switch_menu(self):
652+ return self.select_single(
653+ 'SwitchMenu', objectName='indicator.action.switch')
654+
655+ def get_slider(self):
656+ return self.select_single(objectName='slider')
657+
658+ def get_slider_menu(self):
659+ return self.select_single(objectName='indicator.action.slider')
660+
661+
662+class Slider(emulators.UnityEmulatorBase):
663+
664+ """Autopilot helper for the Slider component."""
665+
666+ # XXX Because of https://bugs.launchpad.net/autopilot-qt/+bug/1341671
667+ # we need to make sure it does not match in any selection.
668+ # --elopio - 2015-01-20
669+
670+ @classmethod
671+ def validate_dbus_object(cls, path, state):
672+ name = introspection.get_classname_from_path(path)
673+ if name == b'Slider':
674+ return True
675+ return False
676+
677+ def slide_left(self, timeout=10):
678+ x, y, width, height = self.globalRect
679+
680+ rate = 5
681+ start_x = x + width/2
682+ start_y = stop_y = y + height/2
683+ stop_x = x
684+
685+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
686+ self.value.wait_for(self.minimumValue, timeout);
687+
688+ def slide_right(self, timeout=10):
689+ x, y, width, height = self.globalRect
690+
691+ rate = 5
692+ start_x = x + width/2
693+ start_y = stop_y = y + height/2
694+ stop_x = x + width
695+
696+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
697+ self.value.wait_for(self.maximumValue, timeout);
698
699=== modified file 'tests/autopilot/unity8/indicators/tests/__init__.py'
700--- tests/autopilot/unity8/indicators/tests/__init__.py 2015-02-23 17:29:04 +0000
701+++ tests/autopilot/unity8/indicators/tests/__init__.py 2015-04-07 11:50:57 +0000
702@@ -27,6 +27,13 @@
703 device_emulation_scenarios = tests._get_device_emulation_scenarios()
704
705 def setUp(self):
706+ super().setUp()
707+ self.unity_proxy = self.launch_unity()
708+ process_helpers.unlock_unity(self.unity_proxy)
709+
710+class DeviceIndicatorTestCase(IndicatorTestCase):
711+
712+ def setUp(self):
713 if platform.model() == 'Desktop':
714 self.skipTest('Test cannot be run on the desktop.')
715 super().setUp()
716
717=== added file 'tests/autopilot/unity8/indicators/tests/test_action_latency.py'
718--- tests/autopilot/unity8/indicators/tests/test_action_latency.py 1970-01-01 00:00:00 +0000
719+++ tests/autopilot/unity8/indicators/tests/test_action_latency.py 2015-04-07 11:50:57 +0000
720@@ -0,0 +1,232 @@
721+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
722+#
723+# Unity Indicators Autopilot Test Suite
724+# Copyright (C) 2015 Canonical
725+#
726+# This program is free software: you can redistribute it and/or modify
727+# it under the terms of the GNU General Public License as published by
728+# the Free Software Foundation, either version 3 of the License, or
729+# (at your option) any later version.
730+#
731+# This program is distributed in the hope that it will be useful,
732+# but WITHOUT ANY WARRANTY; without even the implied warranty of
733+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
734+# GNU General Public License for more details.
735+#
736+# You should have received a copy of the GNU General Public License
737+# along with this program. If not, see <http://www.gnu.org/licenses/>.
738+
739+from testscenarios import multiply_scenarios
740+
741+from unity8 import (
742+ fixture_setup,
743+ indicators,
744+ process_helpers
745+)
746+from unity8.shell import tests
747+from unity8.indicators import tests
748+
749+from autopilot.matchers import Eventually
750+from testtools.matchers import Equals, NotEquals
751+import time
752+
753+
754+class TestIndicatorBaseTestCase(tests.IndicatorTestCase):
755+
756+ scenarios = [ tests.IndicatorTestCase.device_emulation_scenarios[0] ]
757+
758+ def setUp(self):
759+ super(TestIndicatorBaseTestCase, self).setUp()
760+
761+ self.launch_indicator_service()
762+
763+ # wait for the indicator to appear in unity
764+ self.indicator = indicators.TestIndicator(self.main_window)
765+ self.assertThat(
766+ self.indicator.is_indicator_icon_visible(),
767+ Eventually(Equals(True), timeout=20)
768+ )
769+ self.indicator_page = self.indicator.open()
770+
771+ def launch_indicator_service(self):
772+ launch_service_fixture = fixture_setup.LaunchMockIndicatorService(self.action_delay)
773+ self.useFixture(launch_service_fixture)
774+
775+
776+class TestServerValueUpdate(TestIndicatorBaseTestCase):
777+
778+ """Test that an action causes the server to update"""
779+
780+ time_scenarios = [
781+ ('Low', {'action_delay': 0}),
782+ ('Medium', {'action_delay': 2500}),
783+ ('High', {'action_delay': 8000}),
784+ ]
785+ scenarios = multiply_scenarios(
786+ time_scenarios,
787+ TestIndicatorBaseTestCase.scenarios
788+ )
789+
790+ def test_switch_reaches_server_value(self):
791+ switch = self.indicator_page.get_switcher()
792+ switch_menu = self.indicator_page.get_switch_menu()
793+
794+ switch.change_state()
795+
796+ self.assertThat(
797+ switch_menu.serverChecked,
798+ Eventually(Equals(switch.checked), timeout=20)
799+ )
800+
801+ def test_slider_reaches_server_value(self):
802+ slider = self.indicator_page.get_slider()
803+ slider_menu = self.indicator_page.get_slider_menu()
804+
805+ old_value = slider.value
806+ slider.slide_left()
807+
808+ self.assertThat(
809+ slider_menu.serverValue,
810+ Eventually(NotEquals(old_value), timeout=20)
811+ )
812+
813+ self.assertThat(
814+ slider_menu.serverValue,
815+ Eventually(Equals(slider.value), timeout=20)
816+ )
817+
818+class TestBuffering(TestIndicatorBaseTestCase):
819+
820+ """Test that switching multiple times will buffer activations
821+
822+ See https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1390136 .
823+ """
824+ action_delay = 2500
825+
826+ def test_switch_buffers_actvations(self):
827+
828+ switch = self.indicator_page.get_switcher()
829+ switch.change_state()
830+ intermediate_value = switch.checked;
831+
832+ # will buffer change until it receives the change from server
833+ switch.change_state()
834+ final_value = switch.checked;
835+
836+ # backend will respond to first switch.
837+ switch_menu = self.indicator_page.get_switch_menu()
838+ self.assertThat(
839+ switch_menu.serverChecked,
840+ Eventually(Equals(intermediate_value), timeout=20)
841+ )
842+ # The buffered activation should have gone to server now.
843+
844+ # front-end should not change as a result of server update while it is buffered
845+ self.assertThat(
846+ switch.checked,
847+ Equals(final_value)
848+ )
849+
850+ # server will respond to the second activate
851+ self.assertThat(
852+ switch_menu.serverChecked,
853+ Eventually(Equals(final_value), timeout=20)
854+ )
855+
856+ # make sure we've got the server value set.
857+ self.assertThat(
858+ switch.checked,
859+ Equals(switch_menu.serverChecked)
860+ )
861+
862+ def test_slider_buffers_activations(self):
863+
864+ slider = self.indicator_page.get_slider()
865+ original_value = slider.value;
866+ slider.slide_left()
867+
868+ # will buffer change until it receives the change from server
869+ slider.slide_right()
870+ final_value = slider.value;
871+
872+ # backend will respond to first slider. Since it's a live slider it'll probably
873+ # be a random value along the slide.
874+ slider_menu = self.indicator_page.get_slider_menu()
875+ self.assertThat(
876+ slider_menu.serverValue,
877+ Eventually(NotEquals(original_value), timeout=20)
878+ )
879+ # It wont yet have reached the final value due to the buffering
880+ # Second activate should have gone out by now
881+ self.assertThat(
882+ slider_menu.serverValue,
883+ NotEquals(final_value)
884+ )
885+
886+ # front-end should not change as a result of server update while it is buffered
887+ self.assertThat(
888+ slider.value,
889+ Equals(final_value)
890+ )
891+
892+ # server will respond to the second activate
893+ self.assertThat(
894+ slider_menu.serverValue,
895+ Eventually(Equals(final_value), timeout=20)
896+ )
897+
898+ # make sure we've got the server value set.
899+ self.assertThat(
900+ slider.value,
901+ Equals(slider_menu.serverValue)
902+ )
903+
904+
905+class TestClientRevertsToServerValue(TestIndicatorBaseTestCase):
906+
907+ """Test that an action which does not respond in time will revert
908+ to original value if not actioned in time.
909+
910+ See https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1390136 .
911+ """
912+ action_delay = -1 # never action.
913+
914+ def test_switch_reverts_on_late_response(self):
915+
916+ switch = self.indicator_page.get_switcher()
917+ switch_menu = self.indicator_page.get_switch_menu()
918+
919+ original_value = switch.checked;
920+ switch.change_state()
921+
922+ # switch should revert to original value after 5 seconds (30 seconds in real usage)
923+ self.assertThat(
924+ switch.checked,
925+ Eventually(Equals(original_value), timeout=20)
926+ )
927+
928+ # make sure we've got the server value set.
929+ self.assertThat(
930+ switch.checked,
931+ Equals(switch_menu.serverChecked)
932+ )
933+
934+ def test_slider_reverts_on_late_response(self):
935+
936+ slider = self.indicator_page.get_slider()
937+ slider_menu = self.indicator_page.get_slider_menu()
938+
939+ original_value = slider.value;
940+ slider.slide_left()
941+
942+ # slider should revert to original value after 5 seconds (30 seconds in real usage)
943+ self.assertThat(
944+ slider.value,
945+ Eventually(Equals(original_value), timeout=20)
946+ )
947+
948+ # make sure we've got the server value set.
949+ self.assertThat(
950+ slider.value,
951+ Equals(slider_menu.serverValue)
952+ )
953
954=== modified file 'tests/autopilot/unity8/indicators/tests/test_display_indicator.py'
955--- tests/autopilot/unity8/indicators/tests/test_display_indicator.py 2015-03-01 16:17:08 +0000
956+++ tests/autopilot/unity8/indicators/tests/test_display_indicator.py 2015-04-07 11:50:57 +0000
957@@ -23,7 +23,9 @@
958 from unity8.indicators import tests
959
960
961-class DisplayIndicatorTestCase(tests.IndicatorTestCase):
962+class DisplayIndicatorTestCase(tests.DeviceIndicatorTestCase):
963+
964+ scenarios = tests.IndicatorTestCase.device_emulation_scenarios
965
966 def test_indicator_icon_must_be_visible_after_rotation_locked(self):
967 rotation_unlocked = fixture_setup.DisplayRotationLock(False)
968
969=== modified file 'tests/autopilot/unity8/indicators/tests/test_indicators.py'
970--- tests/autopilot/unity8/indicators/tests/test_indicators.py 2015-02-23 17:29:04 +0000
971+++ tests/autopilot/unity8/indicators/tests/test_indicators.py 2015-04-07 11:50:57 +0000
972@@ -23,7 +23,7 @@
973 from unity8.indicators import tests
974
975
976-class IndicatorExistsTestCase(tests.IndicatorTestCase):
977+class IndicatorExistsTestCase(tests.DeviceIndicatorTestCase):
978
979 indicator_scenarios = [
980 ('Bluetooth', dict(indicator_name='indicator-bluetooth')),
981@@ -51,7 +51,7 @@
982 )
983
984
985-class IndicatorPageTitleMatchesWidgetTestCase(tests.IndicatorTestCase):
986+class IndicatorPageTitleMatchesWidgetTestCase(tests.DeviceIndicatorTestCase):
987
988 indicator_scenarios = [
989 ('Bluetooth', dict(indicator_name='indicator-bluetooth',
990
991=== modified file 'tests/mocks/CMakeLists.txt'
992--- tests/mocks/CMakeLists.txt 2014-12-11 14:10:18 +0000
993+++ tests/mocks/CMakeLists.txt 2015-04-07 11:50:57 +0000
994@@ -30,6 +30,7 @@
995
996 add_subdirectory(AccountsService)
997 add_subdirectory(GSettings.1.0)
998+add_subdirectory(indicator-service)
999 add_subdirectory(libusermetrics)
1000 add_subdirectory(LightDM)
1001 add_subdirectory(Lights)
1002
1003=== added directory 'tests/mocks/data/unity'
1004=== added directory 'tests/mocks/data/unity/indicators'
1005=== added file 'tests/mocks/data/unity/indicators/com.canonical.indicator.mock'
1006--- tests/mocks/data/unity/indicators/com.canonical.indicator.mock 1970-01-01 00:00:00 +0000
1007+++ tests/mocks/data/unity/indicators/com.canonical.indicator.mock 2015-04-07 11:50:57 +0000
1008@@ -0,0 +1,10 @@
1009+[Indicator Service]
1010+Name=indicator-mock
1011+ObjectPath=/com/canonical/indicator/mock
1012+Position=0
1013+
1014+[phone]
1015+ObjectPath=/com/canonical/indicator/mock/desktop
1016+
1017+[desktop]
1018+ObjectPath=/com/canonical/indicator/mock/desktop
1019
1020=== added directory 'tests/mocks/indicator-service'
1021=== added file 'tests/mocks/indicator-service/CMakeLists.txt'
1022--- tests/mocks/indicator-service/CMakeLists.txt 1970-01-01 00:00:00 +0000
1023+++ tests/mocks/indicator-service/CMakeLists.txt 2015-04-07 11:50:57 +0000
1024@@ -0,0 +1,20 @@
1025+project(mock-indicator-service)
1026+pkg_search_module(GIO REQUIRED gio-2.0)
1027+
1028+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
1029+
1030+include_directories(
1031+ ${CMAKE_CURRENT_SOURCE_DIR}
1032+ ${GIO_INCLUDE_DIRS}
1033+)
1034+
1035+add_executable(${MOCK_INDICATOR_SERVICE_APP}
1036+ mock-indicator-service.c
1037+)
1038+
1039+target_link_libraries(${MOCK_INDICATOR_SERVICE_APP} ${GIO_LDFLAGS})
1040+
1041+set_target_properties(${MOCK_INDICATOR_SERVICE_APP} PROPERTIES COMPILE_FLAGS -fPIC)
1042+
1043+install(TARGETS ${MOCK_INDICATOR_SERVICE_APP}
1044+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
1045
1046=== added file 'tests/mocks/indicator-service/mock-indicator-service.c'
1047--- tests/mocks/indicator-service/mock-indicator-service.c 1970-01-01 00:00:00 +0000
1048+++ tests/mocks/indicator-service/mock-indicator-service.c 2015-04-07 11:50:57 +0000
1049@@ -0,0 +1,261 @@
1050+/*
1051+ * Copyright (C) 2015 Canonical Ltd.
1052+ *
1053+ * This program is free software: you can redistribute it and/or modify it
1054+ * under the terms of the GNU General Public License version 3, as published
1055+ * by the Free Software Foundation.
1056+ *
1057+ * This program is distributed in the hope that it will be useful, but
1058+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1059+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1060+ * PURPOSE. See the GNU General Public License for more details.
1061+ *
1062+ * You should have received a copy of the GNU General Public License along
1063+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1064+ */
1065+#include <gio/gio.h>
1066+#include <stdio.h>
1067+#include <stdlib.h>
1068+
1069+G_DEFINE_QUARK (SLIDER_VALUE, slider_value)
1070+
1071+typedef struct
1072+{
1073+ GSimpleActionGroup *actions;
1074+ GMenu *menu;
1075+
1076+ guint actions_export_id;
1077+ guint menu_export_id;
1078+ int action_delay;
1079+} IndicatorTestService;
1080+
1081+static void
1082+bus_acquired (GDBusConnection *connection,
1083+ const gchar *name,
1084+ gpointer user_data)
1085+{
1086+ (void) name;
1087+ IndicatorTestService *indicator = user_data;
1088+ GError *error = NULL;
1089+
1090+ indicator->actions_export_id = g_dbus_connection_export_action_group (connection,
1091+ "/com/canonical/indicator/mock",
1092+ G_ACTION_GROUP (indicator->actions),
1093+ &error);
1094+ if (indicator->actions_export_id == 0)
1095+ {
1096+ g_warning ("cannot export action group: %s", error->message);
1097+ g_error_free (error);
1098+ return;
1099+ }
1100+
1101+ indicator->menu_export_id = g_dbus_connection_export_menu_model (connection,
1102+ "/com/canonical/indicator/mock/desktop",
1103+ G_MENU_MODEL (indicator->menu),
1104+ &error);
1105+ if (indicator->menu_export_id == 0)
1106+ {
1107+ g_warning ("cannot export menu: %s", error->message);
1108+ g_error_free (error);
1109+ return;
1110+ }
1111+}
1112+
1113+static void
1114+name_lost (GDBusConnection *connection,
1115+ const gchar *name,
1116+ gpointer user_data)
1117+{
1118+ (void) name;
1119+ IndicatorTestService *indicator = user_data;
1120+
1121+ if (indicator->actions_export_id)
1122+ g_dbus_connection_unexport_action_group (connection, indicator->actions_export_id);
1123+
1124+ if (indicator->menu_export_id)
1125+ g_dbus_connection_unexport_menu_model (connection, indicator->menu_export_id);
1126+}
1127+
1128+static void
1129+activate_show (GSimpleAction *action,
1130+ GVariant *parameter,
1131+ gpointer user_data)
1132+{
1133+ (void) action;
1134+ (void) parameter;
1135+ (void) user_data;
1136+ g_message ("showing");
1137+}
1138+
1139+static gboolean
1140+actual_switch (gpointer user_data)
1141+{
1142+ GSimpleAction *action = user_data;
1143+
1144+ GVariant* v = g_action_get_state(G_ACTION(action));
1145+ gboolean state = g_variant_get_boolean (v);
1146+ GVariant *new_state = g_variant_new_boolean (state == TRUE ? FALSE : TRUE);
1147+
1148+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
1149+
1150+ g_variant_unref (v);
1151+ g_message ("switching");
1152+ return FALSE;
1153+}
1154+
1155+static void
1156+activate_switch (GSimpleAction *action,
1157+ GVariant *parameter,
1158+ gpointer user_data)
1159+{
1160+ (void) action;
1161+ (void) parameter;
1162+
1163+ IndicatorTestService *indicator = user_data;
1164+
1165+ g_timeout_add(indicator->action_delay, actual_switch, action);
1166+ g_message ("switch delay");
1167+}
1168+
1169+static gboolean
1170+actual_slide (gpointer user_data)
1171+{
1172+ GSimpleAction *action = user_data;
1173+
1174+ GVariant* new_state = g_object_get_qdata (G_OBJECT (action), slider_value_quark ());
1175+
1176+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
1177+
1178+ g_message ("switching");
1179+ return FALSE;
1180+}
1181+
1182+void change_slider (GSimpleAction *action,
1183+ GVariant *value,
1184+ gpointer user_data)
1185+{
1186+ IndicatorTestService *indicator = user_data;
1187+
1188+ g_object_set_qdata (G_OBJECT (action), slider_value_quark (), g_variant_ref(value));
1189+
1190+ g_timeout_add(indicator->action_delay, actual_slide, action);
1191+ g_message ("slide delay %.03f", g_variant_get_double(value));
1192+}
1193+
1194+int
1195+main (int argc, char **argv)
1196+{
1197+ IndicatorTestService indicator = { 0 };
1198+ indicator.action_delay = -1;
1199+ GMenuItem *item;
1200+ GMenu *submenu;
1201+ GActionEntry entries[] = {
1202+ { "_header", NULL, NULL, "{'title': <'Test'>,"
1203+ " 'label': <'Test'>,"
1204+ " 'visible': <true>,"
1205+ " 'accessible-desc': <'Test indicator'> }", NULL },
1206+ { "action.show", activate_show, NULL, NULL, NULL },
1207+ { "action.switch", activate_switch, NULL, "true", NULL },
1208+ { "action.checkbox", activate_switch, NULL, "true", NULL },
1209+ { "action.accessPoint", activate_switch, NULL, "false", NULL },
1210+ { "action.slider", NULL, NULL, "0.5", change_slider }
1211+ };
1212+ GMainLoop *loop;
1213+
1214+ int help = 0;
1215+ if (argc > 1)
1216+ {
1217+ int i;
1218+ for (i = 1; i < argc; i++) {
1219+ const char *arg = argv[i];
1220+
1221+ if (arg[0] == '-') {
1222+ switch (arg[1])
1223+ {
1224+ case 't':
1225+ {
1226+ arg += 2;
1227+ if (!arg[0] && i < argc-1) {
1228+ i++;
1229+ int delay = -1;
1230+
1231+ if (sscanf(argv[i], "%d", &delay) == 1) {
1232+ indicator.action_delay = delay;
1233+ } else {
1234+ printf("Invalid action delay value: %s\n", argv[i]);
1235+ help = 1;
1236+ }
1237+ } else {
1238+ printf("Invalid action delay value: %s\n", argv[i]);
1239+ help = 1;
1240+ }
1241+ break;
1242+ }
1243+ case 'h':
1244+ help = 1;
1245+ break;
1246+ }
1247+ }
1248+ }
1249+ }
1250+
1251+ if (help) {
1252+ printf("Usage: %s [<options>]\n"
1253+ " -t DELAY Action activation delay\n"
1254+ " -h Show this help text\n"
1255+ , argv[0]);
1256+ return 0;
1257+ }
1258+
1259+ indicator.actions = g_simple_action_group_new ();
1260+ g_action_map_add_action_entries (G_ACTION_MAP (indicator.actions), entries, G_N_ELEMENTS (entries), &indicator);
1261+
1262+ submenu = g_menu_new ();
1263+ g_menu_append (submenu, "Show", "indicator.action.show");
1264+
1265+ // Switch
1266+ item = g_menu_item_new("Switch", "indicator.action.switch");
1267+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.switch");
1268+ g_menu_append_item(submenu, item);
1269+
1270+ // Checkbox
1271+ item = g_menu_item_new("Checkbox", "indicator.action.checkbox");
1272+ g_menu_append_item(submenu, item);
1273+
1274+ // Slider
1275+ item = g_menu_item_new("Slider", "indicator.action.slider");
1276+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.slider");
1277+ g_menu_append_item(submenu, item);
1278+
1279+ // Access Point
1280+ item = g_menu_item_new("Access Point", "indicator.action.accessPoint");
1281+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "unity.widgets.systemsettings.tablet.accesspoint");
1282+ g_menu_append_item(submenu, item);
1283+
1284+
1285+ item = g_menu_item_new (NULL, "indicator._header");
1286+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.root");
1287+ g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));
1288+ indicator.menu = g_menu_new ();
1289+ g_menu_append_item (indicator.menu, item);
1290+
1291+ g_bus_own_name (G_BUS_TYPE_SESSION,
1292+ "com.canonical.indicator.mock",
1293+ G_BUS_NAME_OWNER_FLAGS_NONE,
1294+ bus_acquired,
1295+ NULL,
1296+ name_lost,
1297+ &indicator,
1298+ NULL);
1299+
1300+ loop = g_main_loop_new (NULL, FALSE);
1301+ g_main_loop_run (loop);
1302+
1303+ g_object_unref (submenu);
1304+ g_object_unref (item);
1305+ g_object_unref (indicator.actions);
1306+ g_object_unref (indicator.menu);
1307+ g_object_unref (loop);
1308+
1309+ return 1;
1310+}
1311
1312=== modified file 'tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp'
1313--- tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp 2015-02-10 16:05:44 +0000
1314+++ tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp 2015-04-07 11:50:57 +0000
1315@@ -31,13 +31,11 @@
1316
1317 void initTestCase()
1318 {
1319- setenv("UNITY_TEST_ENV", "1", 1);
1320 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
1321 }
1322
1323 void cleanupTestCase()
1324 {
1325- unsetenv("UNITY_TEST_ENV");
1326 }
1327
1328 /*
1329
1330=== modified file 'tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp'
1331--- tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp 2014-11-17 23:04:48 +0000
1332+++ tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp 2015-04-07 11:50:57 +0000
1333@@ -32,13 +32,11 @@
1334
1335 void initTestCase()
1336 {
1337- setenv("UNITY_TEST_ENV", "1", 1);
1338 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
1339 }
1340
1341 void cleanupTestCase()
1342 {
1343- unsetenv("UNITY_TEST_ENV");
1344 }
1345
1346 /*
1347
1348=== modified file 'tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml'
1349--- tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2014-12-11 14:10:18 +0000
1350+++ tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2015-04-07 11:50:57 +0000
1351@@ -230,7 +230,7 @@
1352 compare(loader.item.value, data.manualValue, "Slider value does not match manual set value");
1353
1354 menuData.actionState = data.value2;
1355- compare(loader.item.value, data.value2, "Value does not match new data");
1356+ tryCompare(loader.item, "value", data.value2, 10000, "Value does not match new data");
1357
1358 menuData.actionState = undefined;
1359 compare(loader.item.value, data.value2, "Undefined state should not update slider value");
1360@@ -819,6 +819,10 @@
1361 loader.data = menuData;
1362 loader.sourceComponent = factory.load(menuData);
1363
1364+ var sync = findInvisibleChild(loader.item, "sync");
1365+ verify(sync);
1366+ sync.syncTimeout = 500;
1367+
1368 compare(loader.item.checked, false, "Loader did not load check state");
1369 mouseClick(loader.item,
1370 loader.item.width / 2, loader.item.height / 2);

Subscribers

People subscribed via source and target branches