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

Proposed by Pete Woods
Status: Merged
Approved by: Antti Kaijanmäki
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
Antti Kaijanmäki (community) Approve
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

Increment minor version number for QML action manager

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
35. By Pete Woods

Add extra check target that prints the log on fail

36. By Pete Woods

Make the CPP tests pass

37. By Pete Woods

Make the QML tests pass

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
38. By Pete Woods

Handle global actions with specialisation

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
39. By Pete Woods

Rename the _quit() signal to quit()

40. By Pete Woods

Missed the test case!

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

LGTM!

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

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: