Merge lp:~pete-woods/unity-action-api/automatic-quit-action into lp:unity-action-api

Proposed by Pete Woods on 2014-01-22
Status: Merged
Approved by: Antti Kaijanmäki on 2014-01-30
Approved revision: 40
Merged at revision: 32
Proposed branch: lp:~pete-woods/unity-action-api/automatic-quit-action
Merge into: lp:unity-action-api
Diff against target: 484 lines (+217/-24)
9 files modified
CMakeLists.txt (+5/-0)
debian/changelog (+7/-0)
include/unity/action/unity-action-manager.h (+2/-0)
qml/Ubuntu/Unity/Action/plugin.cpp (+7/-1)
src/CMakeLists.txt (+1/-1)
src/unity-action-manager.cpp (+59/-7)
test/cpp/tst_actionmanager.cpp (+14/-14)
test/qml/CMakeLists.txt (+14/-1)
test/qml/tst_api1.1.qml (+108/-0)
To merge this branch: bzr merge lp:~pete-woods/unity-action-api/automatic-quit-action
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve on 2014-01-30
Antti Kaijanmäki (community) 2014-01-22 Approve on 2014-01-30
Review via email: mp+202653@code.launchpad.net

Commit message

Add automatic quit action to HUD toolbar

Description of the change

Add automatic quit action to HUD toolbar

To post a comment you must log in.
34. By Pete Woods on 2014-01-22

Increment minor version number for QML action manager

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
35. By Pete Woods on 2014-01-22

Add extra check target that prints the log on fail

36. By Pete Woods on 2014-01-22

Make the CPP tests pass

37. By Pete Woods on 2014-01-22

Make the QML tests pass

38. By Pete Woods on 2014-01-23

Handle global actions with specialisation

39. By Pete Woods on 2014-01-30

Rename the _quit() signal to quit()

40. By Pete Woods on 2014-01-30

Missed the test case!

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Antti Kaijanmäki (kaijanmaki) wrote :

LGTM!

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 2013-07-11 23:17:56 +0000
3+++ CMakeLists.txt 2014-01-30 13:56:31 +0000
4@@ -130,6 +130,11 @@
5 if(${ENABLE_TESTING})
6 enable_testing()
7 add_subdirectory(test)
8+
9+ ADD_CUSTOM_TARGET(
10+ check
11+ ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure
12+ )
13 endif()
14
15 include(EnableCoverageReport)
16
17=== modified file 'debian/changelog'
18--- debian/changelog 2013-07-16 08:42:31 +0000
19+++ debian/changelog 2014-01-30 13:56:31 +0000
20@@ -1,3 +1,10 @@
21+unity-action-api (1.1.0-0ubuntu1) UNRELEASED; urgency=medium
22+
23+ [ Pete Woods ]
24+ * Add automatic quit action to HUD toolbar.
25+
26+ -- Pete Woods <pete.woods@canonical.com> Wed, 22 Jan 2014 10:50:34 +0000
27+
28 unity-action-api (1.0.0+13.10.20130716-0ubuntu1) saucy; urgency=low
29
30 [ Antti Kaijanmäki ]
31
32=== modified file 'include/unity/action/unity-action-manager.h'
33--- include/unity/action/unity-action-manager.h 2013-07-11 13:57:36 +0000
34+++ include/unity/action/unity-action-manager.h 2014-01-30 13:56:31 +0000
35@@ -57,6 +57,8 @@
36 void localContextsChanged();
37 void actionsChanged();
38
39+ Q_REVISION(1) void quit();
40+
41 private:
42 class Private;
43 QScopedPointer<Private> d;
44
45=== modified file 'qml/Ubuntu/Unity/Action/plugin.cpp'
46--- qml/Ubuntu/Unity/Action/plugin.cpp 2013-07-12 12:55:39 +0000
47+++ qml/Ubuntu/Unity/Action/plugin.cpp 2014-01-30 13:56:31 +0000
48@@ -34,19 +34,25 @@
49
50 qmlRegisterType<unity::action::Action> ();
51 qmlRegisterType<unity::action::qml::Action> (uri, 1, 0, "Action");
52+ qmlRegisterType<unity::action::qml::Action> (uri, 1, 1, "Action");
53 qmlRegisterType<unity::action::PreviewAction> ();
54 qmlRegisterType<unity::action::qml::PreviewAction> (uri, 1, 0, "PreviewAction");
55+ qmlRegisterType<unity::action::qml::PreviewAction> (uri, 1, 1, "PreviewAction");
56
57 qmlRegisterType<unity::action::PreviewParameter> ();
58 qmlRegisterType<unity::action::PreviewRangeParameter> (uri, 1, 0, "PreviewRangeParameter");
59+ qmlRegisterType<unity::action::PreviewRangeParameter> (uri, 1, 1, "PreviewRangeParameter");
60
61 // Don't provide menu item just yet.
62 //qmlRegisterType<unity::action::MenuItem> (uri, 1, 0, "MenuItem");
63
64 qmlRegisterType<unity::action::ActionContext> ();
65 qmlRegisterType<unity::action::qml::ActionContext> (uri, 1, 0, "ActionContext");
66- qmlRegisterType<unity::action::ActionManager> ();
67+ qmlRegisterType<unity::action::qml::ActionContext> (uri, 1, 1, "ActionContext");
68+ qmlRegisterType<unity::action::ActionManager> (uri, 1, 0, "");
69+ qmlRegisterType<unity::action::ActionManager, 1> (uri, 1, 1, "");
70 qmlRegisterType<unity::action::qml::ActionManager> (uri, 1, 0, "ActionManager");
71+ qmlRegisterType<unity::action::qml::ActionManager, 1> (uri, 1, 1, "ActionManager");
72
73 }
74
75
76=== modified file 'src/CMakeLists.txt'
77--- src/CMakeLists.txt 2013-07-15 15:24:36 +0000
78+++ src/CMakeLists.txt 2014-01-30 13:56:31 +0000
79@@ -47,7 +47,7 @@
80
81
82 set(API_VERSION_MAJOR 1)
83-set(API_VERSION_MINOR 0)
84+set(API_VERSION_MINOR 1)
85
86 set(SO_VERSION ${API_VERSION_MAJOR})
87
88
89=== modified file 'src/unity-action-manager.cpp'
90--- src/unity-action-manager.cpp 2013-07-15 18:06:26 +0000
91+++ src/unity-action-manager.cpp 2014-01-30 13:56:31 +0000
92@@ -22,6 +22,9 @@
93
94 #include <QSet>
95 #include <QDebug>
96+#include <QCoreApplication>
97+
98+#include <libintl.h>
99
100 // needed for gio includes.
101 #undef signals
102@@ -198,6 +201,33 @@
103 a.desc == b.desc;
104 }
105
106+namespace {
107+class QuitAction: public Action {
108+ Q_OBJECT
109+};
110+
111+class GlobalActionContext: public ActionContext {
112+public:
113+ GlobalActionContext(QObject *parent = 0) :
114+ ActionContext(parent) {
115+ }
116+
117+ void addBuiltInAction(Action *action) {
118+ built_in_actions << action;
119+ }
120+
121+ QSet<Action *> allActions() {
122+ return actions() + built_in_actions;
123+ }
124+private:
125+ QSet<Action *> built_in_actions;
126+};
127+
128+static inline char * _(const char *__msgid) {
129+ return gettext(__msgid);
130+}
131+}
132+
133 //! \private
134 class Q_DECL_HIDDEN unity::action::ActionManager::Private : public QObject
135 {
136@@ -208,9 +238,11 @@
137
138 QSet<Action *> actions;
139
140- ActionContext *globalContext;
141+ GlobalActionContext *globalContext;
142 QSet<ActionContext *> localContexts;
143
144+ QScopedPointer<Action> quitAction;
145+
146 ActionContext *activeLocalContext;
147
148 QHash<ActionContext *, ContextData> contextData;
149@@ -225,7 +257,7 @@
150 Private(ActionManager *mgr)
151 : q(mgr)
152 {
153- globalContext = new ActionContext();
154+ globalContext = new GlobalActionContext();
155 hudManager = 0;
156 }
157 ~Private() {
158@@ -337,7 +369,14 @@
159
160 d->actionGroup = g_simple_action_group_new();
161
162+ d->quitAction.reset(new QuitAction());
163+ d->quitAction->setText(_("Quit"));
164+ d->quitAction->setDescription(_("Quit the application"));
165+ d->quitAction->setKeywords(_("Exit;Close"));
166+ connect(d->quitAction.data(), SIGNAL(triggered(QVariant)), this, SIGNAL(quit()));
167+
168 d->createContext(d->globalContext);
169+ d->globalContext->addBuiltInAction(d->quitAction.data());
170 d->updateContext(d->globalContext);
171 hud_manager_switch_window_context(d->hudManager,
172 d->contextData[d->globalContext].publisher);
173@@ -631,7 +670,7 @@
174 // current actions in global context and
175 // in the active local context
176
177- QSet<Action *> globalActions = globalContext->actions();
178+ QSet<Action *> globalActions = globalContext->allActions();
179 QSet<Action *> localActions;
180 if (activeLocalContext)
181 localActions = activeLocalContext->actions();
182@@ -704,7 +743,12 @@
183 ContextData &cdata = contextData[context];
184
185 QSet<Action *> oldActions = cdata.actions;
186- QSet<Action *> currentActions = context->actions();
187+ QSet<Action *> currentActions;
188+ if(context == globalContext) {
189+ currentActions = globalContext->allActions();
190+ } else {
191+ currentActions = context->actions();
192+ }
193 QSet<Action *> removedActions = oldActions - currentActions;
194
195 foreach (Action *action, currentActions) {
196@@ -774,7 +818,7 @@
197 const ContextData &cdata = contextData[context];
198
199
200- QSet<Action *> currentActions = context->actions() + globalContext->actions();
201+ QSet<Action *> currentActions = context->actions() + globalContext->allActions();
202 QSet<Action *> newActions = currentActions - oldActions;
203 QSet<Action *> removedActions = oldActions - currentActions;
204
205@@ -821,8 +865,9 @@
206 << "\tin the client code. ";
207 globalContext->disconnect(this);
208 destroyContext(globalContext);
209- globalContext = new ActionContext();
210+ globalContext = new GlobalActionContext();
211 createContext(globalContext);
212+ globalContext->addBuiltInAction(quitAction.data());
213 updateContext(globalContext);
214 connect(globalContext, SIGNAL(actionsChanged()), this, SLOT(contextActionsChanged()));
215 connect(globalContext, SIGNAL(activeChanged(bool)), this, SLOT(contextActiveChanged(bool)));
216@@ -1022,6 +1067,13 @@
217 "commitLabel",
218 g_variant_new_string(qPrintable(previewAction->commitLabel())));
219 }
220+
221+ QuitAction *quitAction = qobject_cast<QuitAction *>(action);
222+ if (quitAction != 0) {
223+ hud_action_description_set_attribute_value(desc,
224+ "hud-toolbar-item",
225+ g_variant_new_string("quit"));
226+ }
227 }
228
229 void
230@@ -1038,7 +1090,7 @@
231 g_signal_handlers_disconnect_by_data(G_OBJECT(adata.gaction), action);
232 g_clear_object(&adata.gaction);
233 adata.gaction = (GSimpleAction *)g_object_ref(tmpdata.gaction);
234- if (globalContext->actions().contains(action) ||
235+ if (globalContext->allActions().contains(action) ||
236 (activeLocalContext != 0 && activeLocalContext->actions().contains(action))) {
237 updateActionGroup();
238 }
239
240=== modified file 'test/cpp/tst_actionmanager.cpp'
241--- test/cpp/tst_actionmanager.cpp 2013-07-09 10:38:33 +0000
242+++ test/cpp/tst_actionmanager.cpp 2014-01-30 13:56:31 +0000
243@@ -59,8 +59,8 @@
244 TestActionManager::cleanup()
245 {
246 // after each test make sure the manager is left in a clean state
247- Q_ASSERT(manager->actions().isEmpty());
248- Q_ASSERT(manager->localContexts().isEmpty());
249+ QVERIFY(manager->actions().count() == 1);
250+ QVERIFY(manager->localContexts().isEmpty());
251 }
252
253
254@@ -168,7 +168,7 @@
255 manager->removeLocalContext(ctx1);
256 manager->removeLocalContext(ctx2);
257 manager->removeLocalContext(ctx3);
258- QVERIFY(manager->actions().count() == 0);
259+ QVERIFY(manager->actions().count() == 1);
260 }
261
262 void
263@@ -345,27 +345,27 @@
264 manager->addLocalContext(ctx2);
265
266 QSignalSpy spy(manager, SIGNAL(actionsChanged()));
267- QCOMPARE(manager->actions().count(), 5);
268+ QCOMPARE(manager->actions().count(), 6);
269
270 // delete action1 directly from globalContext
271 delete action1;
272 QCOMPARE(spy.count(), 1);
273 QVERIFY(!manager->actions().contains(action1));
274- QCOMPARE(manager->actions().count(), 4);
275+ QCOMPARE(manager->actions().count(), 5);
276 action1 = 0;
277
278 // delete action2 directly from ctx1
279 delete action2;
280 QCOMPARE(spy.count(), 2);
281 QVERIFY(!manager->actions().contains(action2));
282- QCOMPARE(manager->actions().count(), 3);
283+ QCOMPARE(manager->actions().count(), 4);
284 action2 = 0;
285
286 // remove action3 indirectly by destroying ctx1
287 delete ctx1;
288 QCOMPARE(spy.count(), 3);
289 QVERIFY(!manager->actions().contains(action3));
290- QCOMPARE(manager->actions().count(), 2);
291+ QCOMPARE(manager->actions().count(), 3);
292 ctx1 = 0;
293 action3 = 0;
294
295@@ -374,7 +374,7 @@
296 QCOMPARE(spy.count(), 5); // actionsChanged() gets called multiple times (once per each action in a context)
297 QVERIFY(!manager->actions().contains(action4));
298 QVERIFY(!manager->actions().contains(action5));
299- QCOMPARE(manager->actions().count(), 0);
300+ QCOMPARE(manager->actions().count(), 1);
301 QVERIFY(manager->localContexts().isEmpty());
302 ctx2 = 0;
303 action4 = 0;
304@@ -413,32 +413,32 @@
305
306 // 3 actions have been added in total
307 QCOMPARE(spy.count(), 3);
308- QCOMPARE(manager->actions().count(), 3);
309+ QCOMPARE(manager->actions().count(), 4);
310
311 spy.clear();
312 manager->removeLocalContext(ctx2); // removes only action3, action1 is shared.
313 QCOMPARE(spy.count(), 1);
314- QCOMPARE(manager->actions().count(), 2);
315+ QCOMPARE(manager->actions().count(), 3);
316 // and now add it back
317 manager->addLocalContext(ctx2);
318 QCOMPARE(spy.count(), 2);
319- QCOMPARE(manager->actions().count(), 3);
320+ QCOMPARE(manager->actions().count(), 4);
321
322 spy.clear();
323 gctx->removeAction(action1);
324 QCOMPARE(spy.count(), 0);
325- QCOMPARE(manager->actions().count(), 3);
326+ QCOMPARE(manager->actions().count(), 4);
327 QVERIFY(manager->actions().contains(action1));
328
329 ctx1->removeAction(action1);
330 QCOMPARE(spy.count(), 0);
331- QCOMPARE(manager->actions().count(), 3);
332+ QCOMPARE(manager->actions().count(), 4);
333 QVERIFY(manager->actions().contains(action1));
334
335 // remove the action from the last context
336 ctx2->removeAction(action1);
337 QCOMPARE(spy.count(), 1);
338- QCOMPARE(manager->actions().count(), 2);
339+ QCOMPARE(manager->actions().count(), 3);
340 QVERIFY(!manager->actions().contains(action1));
341
342 manager->removeLocalContext(ctx1);
343
344=== modified file 'test/qml/CMakeLists.txt'
345--- test/qml/CMakeLists.txt 2013-06-18 09:48:41 +0000
346+++ test/qml/CMakeLists.txt 2014-01-30 13:56:31 +0000
347@@ -1,4 +1,5 @@
348 add_custom_target(qmlunittests)
349+add_custom_target(qmlunittests_1_1)
350
351 find_program(qmltestrunner_exe qmltestrunner)
352
353@@ -16,4 +17,16 @@
354
355 add_custom_target(qmltest_api ${qmltest_command})
356 add_dependencies(qmlunittests qmltest_api)
357-add_test(qmlunittests ${qmltest_command})
358\ No newline at end of file
359+add_test(qmlunittests ${qmltest_command})
360+
361+set(qmltest1_1_command
362+ dbus-test-runner -t env -p "QT_QPA_PLATFORM=minimal"
363+ -p ${qmltestrunner_exe} -p -input -p ${CMAKE_CURRENT_SOURCE_DIR}/tst_api1.1.qml
364+ -p -import -p ${CMAKE_CURRENT_BINARY_DIR}/../../qml
365+ -p -o -p ${CMAKE_BINARY_DIR}/testapi.xml,xunitxml
366+ -p -o -p -,txt
367+)
368+
369+add_custom_target(qmltest_1_1_api ${qmltest1_1_command})
370+add_dependencies(qmlunittests_1_1 qmltest_1_1_api)
371+add_test(qmlunittests_1_1 ${qmltest1_1_command})
372
373=== added file 'test/qml/tst_api1.1.qml'
374--- test/qml/tst_api1.1.qml 1970-01-01 00:00:00 +0000
375+++ test/qml/tst_api1.1.qml 2014-01-30 13:56:31 +0000
376@@ -0,0 +1,108 @@
377+/* This file is part of unity-action-api
378+ * Copyright 2013 Canonical Ltd.
379+ *
380+ * unity-action-api is free software: you can redistribute it and/or modify it
381+ * under the terms of the GNU Lesser General Public License version 3,
382+ * as published by the Free Software Foundation.
383+ *
384+ * unity-action-api is distributed in the hope that it will be useful, but
385+ * WITHOUT ANY WARRANTY; without even the implied warranties of
386+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
387+ * PURPOSE. See the GNU Lesser General Public License for more details.
388+ *
389+ * You should have received a copy of the GNU Lesser General Public License
390+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
391+ */
392+
393+import Ubuntu.Unity.Action 1.1
394+import QtQuick 2.0
395+import QtTest 1.0
396+
397+/* This test will make sure there are no unintentional changes to the
398+ * schemantics of the API (default properties work as expected, etc)
399+ * so that any files written to the prior release of the library
400+ * will not bail out when loaded resulting in client applications failing
401+ * to start.
402+ */
403+Item {
404+
405+ ActionManager {
406+ id: manager
407+
408+ localContexts: [ctx1, ctx2]
409+
410+ onQuit: {}
411+
412+ Action {
413+ id: globalaction
414+ name: "NewMessage"
415+ text: "Write New Message"
416+ iconName: "email-new-message"
417+ description: "Write a new Message"
418+ keywords: "Compose;Send"
419+ enabled: true
420+ parameterType: Action.String
421+ onTriggered: {}
422+ }
423+ }
424+
425+ ActionContext {
426+ id: ctx1
427+
428+ Action {
429+ id: myaction1
430+ text: "Foo"
431+ onTriggered: {}
432+ }
433+ }
434+
435+ ActionContext {
436+ id: ctx2
437+
438+ PreviewAction {
439+ id: previewaction
440+ text: "Color Balance"
441+ commitLabel: "Apply"
442+
443+ onStarted: {}
444+ onResetted: {}
445+ onCancelled: {}
446+ onTriggered: {}
447+
448+ PreviewRangeParameter {
449+ text: "lorem ipsum"
450+ value: 0
451+ minimumValue: -100
452+ maximumValue: 100
453+ onValueChanged: {}
454+ }
455+ }
456+ }
457+
458+
459+/*
460+ MenuItem {
461+ action: myaction1
462+ text: "New Message"
463+ iconName: "menu-new-message"
464+ target: "user@corporation.tld"
465+ visible: true
466+ enabled: false
467+ }
468+*/
469+
470+ Component.onCompleted: {
471+ ctx2.active = true
472+ }
473+
474+
475+ TestCase {
476+ name: "API Test"
477+ id: test_api
478+
479+ function test_api() {
480+ // just make sure this file can be loaded properly by the QmlEngine.
481+ verify(1)
482+ }
483+ }
484+}

Subscribers

People subscribed via source and target branches

to all changes: