Merge lp:~mzanetti/unity-api/application-api into lp:unity-api

Proposed by Michael Zanetti
Status: Merged
Approved by: Gerry Boland
Approved revision: 100
Merged at revision: 91
Proposed branch: lp:~mzanetti/unity-api/application-api
Merge into: lp:unity-api
Diff against target: 1024 lines (+936/-0)
15 files modified
include/unity/shell/CMakeLists.txt (+1/-0)
include/unity/shell/application/ApplicationInfoInterface.h (+165/-0)
include/unity/shell/application/ApplicationManagerInterface.h (+168/-0)
include/unity/shell/application/CMakeLists.txt (+22/-0)
test/qmltest/mocks/CMakeLists.txt (+1/-0)
test/qmltest/mocks/plugins/Unity/Application/CMakeLists.txt (+37/-0)
test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.cpp (+97/-0)
test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.h (+59/-0)
test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.cpp (+107/-0)
test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.h (+57/-0)
test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.cpp (+45/-0)
test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.h (+35/-0)
test/qmltest/mocks/plugins/Unity/Application/qmldir (+2/-0)
test/qmltest/unity/shell/CMakeLists.txt (+1/-0)
test/qmltest/unity/shell/application/tst_Application.qml (+139/-0)
To merge this branch: bzr merge lp:~mzanetti/unity-api/application-api
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Gerry Boland (community) Approve
Review via email: mp+182692@code.launchpad.net

Commit message

Add Ubuntu.Application API, including tests and a mock implementation

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote :

This is amazing, thanks Michael!! My comments:

3 nested namespaces, can't we reduce that?

+ ApplicationInfoInterface

First off I think we can be ruthless and get rid of deprecated stuff.

Launcher doesn't care if application is fullscreen, and technically a surface is fullscreen, not an application. Please leave that out until I decide what to do there. Also screenshots are made available by an image loader, with URI based on the appId - so that 'screenshot' API is going away

So I'd propose simplifying this interface to include only those things we both need to share: appId, name, comment, icon, stage, state, focused.

Next I think these properties should be read only. I expect to implement this interface by adding a constructor which takes app_id and then sets these properties from the correct desktop file. I don't see these needing to be set by shell. But if the desktop file changes, want to notify shell of those property changes.

Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged)
QUrl better? Will this will return things like file:///usr/share/icons/whatever.png or gicon:///network-enabled, if so I'd like to use QUrl.

States enum will also need "Suspended", "Stopped" for process management (Stopped means process killed, but its state was written to disk, so can be respawned and resume itself). Maybe also desktop-y things like "Wants Attention" ?

+ ApplicationListModelInterface

The only reason ApplicationListModelInterface was useful was for when we had 2 separate lists for main stage and side stage applications. But we agreed it is best to combine these into one master list. So is it worth having this class at all, we could instead making the ApplicationManager class an QAbstractListModel?

Pet peeve: QAbstractListModel doesn't have a "count" property, unlike javascript models. It would be nice to add it :)

+ ApplicationManagerInterface

+ Application* startProcess(QString desktopFile, ExecFlags flags, QStringList arguments)
your correct in your comment that this needs to change a lot. Yes it should use appId. Flags should go away too. Thus can remove that enum.

+ void unfocusCurrentApplication(StageHint stageHint);
I think this best replaced with unfocusCurrentApplication()

+Q_SIGNALS:
415 + // TODO: needed?
416 + void mainStageFocusedApplicationChanged();
417 + void sideStageFocusedApplicationChanged();

Can combine these into one focusedApplicationChanged() signal

418 + void focusRequested(FavoriteApplication favoriteApplication)
I believe upstart will handle this, so shell won't need to care. Can leave it out completely.

Revision history for this message
Michael Zanetti (mzanetti) wrote :
Download full text (3.5 KiB)

> 3 nested namespaces, can't we reduce that?

It's not my personal preference either, but more important is to keep consistency between the apis. As lp:unity-api has been defined with this namespace structure, we need to adopt it. Note that you don't need to use them in the actual implementation. Just "using namespace unity::shell:application" once in your header should be enough to not have to care about it all any more. Check out the launcher implementation in lp:unity8 plugins/Unity/Launcher/.

>
> + ApplicationInfoInterface
>
> First off I think we can be ruthless and get rid of deprecated stuff.
>
> Launcher doesn't care if application is fullscreen, and technically a surface
> is fullscreen, not an application. Please leave that out until I decide what
> to do there. Also screenshots are made available by an image loader, with URI
> based on the appId - so that 'screenshot' API is going away
>
> So I'd propose simplifying this interface to include only those things we both
> need to share: appId, name, comment, icon, stage, state, focused.

Done.

>
> Next I think these properties should be read only. I expect to implement this
> interface by adding a constructor which takes app_id and then sets these
> properties from the correct desktop file. I don't see these needing to be set
> by shell. But if the desktop file changes, want to notify shell of those
> property changes.

Done.

>
> Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged)
> QUrl better? Will this will return things like
> file:///usr/share/icons/whatever.png or gicon:///network-enabled, if so I'd
> like to use QUrl.

Done.

>
> States enum will also need "Suspended", "Stopped" for process management
> (Stopped means process killed, but its state was written to disk, so can be
> respawned and resume itself). Maybe also desktop-y things like "Wants
> Attention" ?

Added Suspended and Stopped. I don't think "Wants Attention" or the like belongs in here. Just because an app wants attention it is still one of the other states (e.g. running). I'd probably even create a separate boolean property for "Wants attention".

>
> + ApplicationListModelInterface
>
> The only reason ApplicationListModelInterface was useful was for when we had 2
> separate lists for main stage and side stage applications. But we agreed it is
> best to combine these into one master list. So is it worth having this class
> at all, we could instead making the ApplicationManager class an
> QAbstractListModel?

Done. This matches the Launcher api now very closely :)

>
> Pet peeve: QAbstractListModel doesn't have a "count" property, unlike
> javascript models. It would be nice to add it :)

added.

>
>
> + ApplicationManagerInterface
>
> + Application* startProcess(QString desktopFile, ExecFlags flags, QStringList
> arguments)
> your correct in your comment that this needs to change a lot. Yes it should
> use appId. Flags should go away too. Thus can remove that enum.

done

>
> + void unfocusCurrentApplication(StageHint stageHint);
> I think this best replaced with unfocusCurrentApplication()

done

>
>
> +Q_SIGNALS:
> 415 + // TODO: needed?
> 416 + void mainStageFocuse...

Read more...

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

> > 3 nested namespaces, can't we reduce that?
>
> It's not my personal preference either, but more important is to keep
> consistency between the apis. As lp:unity-api has been defined with this
> namespace structure, we need to adopt it. Note that you don't need to use
> them in the actual implementation. Just "using namespace
> unity::shell:application" once in your header should be enough to not have
> to care about it all any more. Check out the launcher implementation in
> lp:unity8 plugins/Unity/Launcher/.

Ok, I'll accept for consistency with what's already in unity-api. But we should have a chat about it later on.

+ * @bried The currently focused application.
Typo: "brief"

startProcess & stopProcess - sorry I just realized that the names are next exactly correct, as an application may launch several processes (e.g. webbrowser-app spawns a QWebProcess for each tab). Perhaps rename to just "start" and "stop", or "startApplication" and "stopApplication"

Only other issue is in your tests, that "Ubuntu.Application" is not a clear name for the plugin. I'm using "Unity.ApplicationManager" in unity-mir which is hopefully more descriptive.

Otherwise, it's excellent!

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> + * @bried The currently focused application.
> Typo: "brief"

fixed.

>
> startProcess & stopProcess - sorry I just realized that the names are next
> exactly correct, as an application may launch several processes (e.g.
> webbrowser-app spawns a QWebProcess for each tab). Perhaps rename to just
> "start" and "stop", or "startApplication" and "stopApplication"

renamed to start/stopApplication

>
> Only other issue is in your tests, that "Ubuntu.Application" is not a clear
> name for the plugin. I'm using "Unity.ApplicationManager" in unity-mir which
> is hopefully more descriptive.

As discussed in IRC, renamed to Unity.Application.

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

Works great, and I approve of the API

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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 'include/unity/shell/CMakeLists.txt'
2--- include/unity/shell/CMakeLists.txt 2013-05-17 10:10:20 +0000
3+++ include/unity/shell/CMakeLists.txt 2013-08-29 12:55:03 +0000
4@@ -1,5 +1,6 @@
5 add_subdirectory(notifications)
6 add_subdirectory(launcher)
7+add_subdirectory(application)
8
9 file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
10 file(GLOB internal_headers "${CMAKE_CURRENT_SOURCE_DIR}/internal/*.h")
11
12=== added directory 'include/unity/shell/application'
13=== added file 'include/unity/shell/application/ApplicationInfoInterface.h'
14--- include/unity/shell/application/ApplicationInfoInterface.h 1970-01-01 00:00:00 +0000
15+++ include/unity/shell/application/ApplicationInfoInterface.h 2013-08-29 12:55:03 +0000
16@@ -0,0 +1,165 @@
17+/*
18+ * Copyright 2013 Canonical Ltd.
19+ *
20+ * This program is free software; you can redistribute it and/or modify
21+ * it under the terms of the GNU Lesser General Public License as published by
22+ * the Free Software Foundation; version 3.
23+ *
24+ * This program is distributed in the hope that it will be useful,
25+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ * GNU Lesser General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU Lesser General Public License
30+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
31+ *
32+ * Authors:
33+ * Michael Zanetti <michael.zanetti@canonical.com>
34+ */
35+
36+#ifndef UNITY_SHELL_APPLICATION_APPLICATIONINFOINTERFACE_H
37+#define UNITY_SHELL_APPLICATION_APPLICATIONINFOINTERFACE_H
38+
39+#include <unity/SymbolExport.h>
40+
41+#include <QtCore/QObject>
42+#include <QtCore/QUrl>
43+
44+namespace unity
45+{
46+namespace shell
47+{
48+namespace application
49+{
50+
51+/**
52+ * @brief A class that holds information about applications
53+ *
54+ * The items hold all the information required for the visual representation
55+ * in the launcher.
56+ */
57+
58+class UNITY_API ApplicationInfoInterface: public QObject
59+{
60+ Q_OBJECT
61+
62+ Q_ENUMS(Stage)
63+ Q_ENUMS(State)
64+
65+ /**
66+ * @brief The appId of the application.
67+ *
68+ * Holds the appId for the application. For example (com.ubuntu.camera-app).
69+ * The appId is derived from the filename of the .desktop file.
70+ */
71+ Q_PROPERTY(QString appId READ appId CONSTANT)
72+
73+ /**
74+ * @brief The name of the application.
75+ *
76+ * Holds the name of the application. Localized to current language.
77+ */
78+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
79+
80+ /**
81+ * @brief The comment for the application.
82+ *
83+ * Holds the comment of the application as obtained from the .desktop file. Localized
84+ * to current language.
85+ */
86+ Q_PROPERTY(QString comment READ comment NOTIFY commentChanged)
87+
88+ /**
89+ * @brief The application's icon.
90+ *
91+ * Holds a path to the icon for the application. Can be a file or a gicon url.
92+ */
93+ Q_PROPERTY(QUrl icon READ icon NOTIFY iconChanged)
94+
95+ /**
96+ * @brief The application's stage.
97+ *
98+ * Holds the stage where this application is currently located.
99+ */
100+ Q_PROPERTY(Stage stage READ stage NOTIFY stageChanged)
101+
102+ /**
103+ * @brief The application's state.
104+ *
105+ * Holds the current application state.
106+ */
107+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
108+
109+ /**
110+ * @brief The application's focus state.
111+ *
112+ * Holds the current application focus state. True if focused, false otherwise.
113+ */
114+ Q_PROPERTY(bool focused READ focused NOTIFY focusedChanged)
115+
116+protected:
117+ /// @cond
118+ ApplicationInfoInterface(const QString &appId, QObject* parent = 0): QObject(parent) { Q_UNUSED(appId) }
119+ /// @endcond
120+
121+public:
122+ /**
123+ * @brief A enum that defines a stage.
124+ *
125+ * MainStage: The main stage, which is the normal place for applications in
126+ * traditional desktop environments.
127+ * SideStage: The side stage, a panel on the right to place phone form factor
128+ * applications.
129+ */
130+ enum Stage {
131+ MainStage,
132+ SideStage
133+ };
134+
135+ /**
136+ * @brief An application's state.
137+ *
138+ * Starting: The application was launched and is currently starting up.
139+ * Running: The application is running and ready to be used.
140+ * Suspended: The application is in the background and has been suspended by
141+ * the system in order to save resources.
142+ * Stopped: The application is in the background and has been stopped by
143+ * the system in order to save resources. From a programmers point of view,
144+ * the application is closed, but it's state has been stored to disk and
145+ * can be restored upon next launch.
146+ */
147+ enum State {
148+ Starting,
149+ Running,
150+ Suspended,
151+ Stopped
152+ };
153+
154+ /// @cond
155+ virtual ~ApplicationInfoInterface() {}
156+
157+ virtual QString appId() const = 0;
158+ virtual QString name() const = 0;
159+ virtual QString comment() const = 0;
160+ virtual QUrl icon() const = 0;
161+ virtual Stage stage() const = 0;
162+ virtual State state() const = 0;
163+ virtual bool focused() const = 0;
164+ /// @endcond
165+
166+Q_SIGNALS:
167+ /// @cond
168+ void nameChanged(const QString &name);
169+ void commentChanged(const QString &comment);
170+ void iconChanged(const QUrl &icon);
171+ void stageChanged(Stage stage);
172+ void stateChanged(State state);
173+ void focusedChanged(bool focused);
174+ /// @endcond
175+};
176+
177+} // namespace application
178+} // namespace shell
179+} // namespace unity
180+
181+#endif // UNITY_SHELL_APPLICATIONMANAGER_APPLICATIONINFOINTERFACE_H
182
183=== added file 'include/unity/shell/application/ApplicationManagerInterface.h'
184--- include/unity/shell/application/ApplicationManagerInterface.h 1970-01-01 00:00:00 +0000
185+++ include/unity/shell/application/ApplicationManagerInterface.h 2013-08-29 12:55:03 +0000
186@@ -0,0 +1,168 @@
187+/*
188+ * Copyright 2013 Canonical Ltd.
189+ *
190+ * This program is free software; you can redistribute it and/or modify
191+ * it under the terms of the GNU Lesser General Public License as published by
192+ * the Free Software Foundation; version 3.
193+ *
194+ * This program is distributed in the hope that it will be useful,
195+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
196+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197+ * GNU Lesser General Public License for more details.
198+ *
199+ * You should have received a copy of the GNU Lesser General Public License
200+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
201+ *
202+ * Authors:
203+ * Michael Zanetti <michael.zanetti@canonical.com>
204+ */
205+
206+#ifndef UNITY_SHELL_APPLICATION_APPLICATIONMANAGERINTERFACE_H
207+#define UNITY_SHELL_APPLICATION_APPLICATIONMANAGERINTERFACE_H
208+
209+#include <unity/SymbolExport.h>
210+
211+#include <QtCore/QObject>
212+#include <QtCore/QAbstractListModel>
213+
214+namespace unity
215+{
216+namespace shell
217+{
218+namespace application
219+{
220+
221+class ApplicationInfoInterface;
222+
223+/**
224+ * @brief The Application manager
225+ *
226+ * This is the main class to interact with Applications
227+ */
228+
229+class UNITY_API ApplicationManagerInterface: public QAbstractListModel
230+{
231+ Q_OBJECT
232+
233+ /**
234+ * @brief The count of the applications known to the manager.
235+ *
236+ * This is the same as rowCount, added in order to keep compatibility with QML ListModels.
237+ */
238+ Q_PROPERTY(int count READ count NOTIFY countChanged)
239+
240+ /**
241+ * @brief The currently focused application.
242+ *
243+ * Use focusApplication() and unfocusCurrentApplication() to modify this.
244+ */
245+ Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* focusedApplication READ focusedApplication NOTIFY focusedApplicationChanged)
246+
247+protected:
248+ /// @cond
249+ ApplicationManagerInterface(QObject* parent = 0): QAbstractListModel(parent)
250+ {
251+ m_roleNames.insert(RoleAppId, "appId");
252+ m_roleNames.insert(RoleName, "name");
253+ m_roleNames.insert(RoleComment, "comment");
254+ m_roleNames.insert(RoleIcon, "icon");
255+ m_roleNames.insert(RoleStage, "stage");
256+ m_roleNames.insert(RoleState, "state");
257+ m_roleNames.insert(RoleFocused, "focused");
258+
259+ connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), SIGNAL(countChanged()));
260+ connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), SIGNAL(countChanged()));
261+ connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
262+ connect(this, SIGNAL(layoutChanged()), SIGNAL(countChanged()));
263+ }
264+ /// @endcond
265+
266+public:
267+ /**
268+ * @brief The Roles supported by the model
269+ *
270+ * See ApplicationInfoInterface properties for details.
271+ */
272+ enum Roles {
273+ RoleAppId = Qt::UserRole,
274+ RoleName,
275+ RoleComment,
276+ RoleIcon,
277+ RoleStage,
278+ RoleState,
279+ RoleFocused,
280+ };
281+
282+ /// @cond
283+ virtual ~ApplicationManagerInterface() {}
284+
285+ virtual QHash<int, QByteArray> roleNames() const
286+ {
287+ return m_roleNames;
288+ }
289+
290+ int count() const {
291+ return rowCount();
292+ }
293+
294+ virtual unity::shell::application::ApplicationInfoInterface *focusedApplication() const = 0;
295+ /// @endcond
296+
297+ /**
298+ * @brief Get an ApplicationInfo item.
299+ *
300+ * Note: QML requires the full namespace in the return value.
301+ *
302+ * @param index the index of the item to get
303+ * @returns The item.
304+ */
305+ Q_INVOKABLE virtual unity::shell::application::ApplicationInfoInterface *get(int index) const = 0;
306+
307+ /**
308+ * @brief Focus the given application.
309+ *
310+ * @param application The application to be focused.
311+ */
312+ Q_INVOKABLE virtual void focusApplication(ApplicationInfoInterface *application) = 0;
313+
314+ /**
315+ * @brief Unfocus the currently focused application.
316+ */
317+ Q_INVOKABLE virtual void unfocusCurrentApplication() = 0;
318+
319+ /**
320+ * @brief Start an application.
321+ *
322+ * @param appId The appId for the application to be spawned.
323+ * @param arguments Any arguments to be passed to the process.
324+ */
325+ Q_INVOKABLE virtual unity::shell::application::ApplicationInfoInterface* startApplication(const QString &appId, const QStringList &arguments) = 0;
326+
327+ /**
328+ * @brief Stops an application.
329+ *
330+ * @param application The application to be stopped.
331+ */
332+ Q_INVOKABLE virtual void stopApplication(ApplicationInfoInterface* application) = 0;
333+
334+Q_SIGNALS:
335+ /// @cond
336+ void countChanged();
337+ /// @endcond
338+
339+ /**
340+ * @brief Will be emitted whenever the focused application changes.
341+ */
342+ void focusedApplicationChanged();
343+
344+protected:
345+ /// @cond
346+ QHash<int, QByteArray> m_roleNames;
347+ /// @endcond
348+};
349+
350+} // namespace application
351+} // namespace shell
352+} // namespace unity
353+
354+#endif // UNITY_SHELL_APPLICATIONMANAGER_APPLICATIONINFO_H
355
356=== added file 'include/unity/shell/application/CMakeLists.txt'
357--- include/unity/shell/application/CMakeLists.txt 1970-01-01 00:00:00 +0000
358+++ include/unity/shell/application/CMakeLists.txt 2013-08-29 12:55:03 +0000
359@@ -0,0 +1,22 @@
360+set(INCLUDE_INSTALL_DIR include/unity/shell/application)
361+
362+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
363+file(GLOB internal_headers "${CMAKE_CURRENT_SOURCE_DIR}/internal/*.h")
364+
365+install(FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR})
366+
367+set(UNITY_API_LIB_HDRS ${UNITY_API_LIB_HDRS} ${headers} ${internal_headers} PARENT_SCOPE)
368+
369+set(VERSION 1)
370+set(PKGCONFIG_NAME "unity-shell-appliction")
371+set(PKGCONFIG_DESCRIPTION "Unity shell Application APIs")
372+set(PKGCONFIG_REQUIRES "Qt5Core")
373+set(PKGCONFIG_FILE unity-shell-application.pc)
374+
375+configure_file(${CMAKE_SOURCE_DIR}/data/unity-shell-api.pc.in
376+ ${CMAKE_BINARY_DIR}/data/${PKGCONFIG_FILE} @ONLY
377+)
378+
379+install(FILES ${CMAKE_BINARY_DIR}/data/${PKGCONFIG_FILE}
380+ DESTINATION ${LIB_INSTALL_PREFIX}/pkgconfig
381+)
382
383=== modified file 'test/qmltest/mocks/CMakeLists.txt'
384--- test/qmltest/mocks/CMakeLists.txt 2013-06-05 13:07:49 +0000
385+++ test/qmltest/mocks/CMakeLists.txt 2013-08-29 12:55:03 +0000
386@@ -1,2 +1,3 @@
387 add_subdirectory(plugins/Unity/Notifications)
388 add_subdirectory(plugins/Unity/Launcher)
389+add_subdirectory(plugins/Unity/Application)
390
391=== added directory 'test/qmltest/mocks/plugins/Unity/Application'
392=== added file 'test/qmltest/mocks/plugins/Unity/Application/CMakeLists.txt'
393--- test/qmltest/mocks/plugins/Unity/Application/CMakeLists.txt 1970-01-01 00:00:00 +0000
394+++ test/qmltest/mocks/plugins/Unity/Application/CMakeLists.txt 2013-08-29 12:55:03 +0000
395@@ -0,0 +1,37 @@
396+include_directories(
397+ ${CMAKE_SOURCE_DIR}/include/unity/shell/application
398+ ${CMAKE_CURRENT_SOURCE_DIR}
399+)
400+
401+add_definitions(-DQT_NO_KEYWORDS)
402+set(CMAKE_AUTOMOC ON)
403+
404+find_package(Qt5Core REQUIRED)
405+find_package(Qt5Quick REQUIRED)
406+find_package(Qt5Qml REQUIRED)
407+
408+set(ApplicationMocks_SOURCES
409+ ${CMAKE_SOURCE_DIR}/include/unity/shell/application/ApplicationManagerInterface.h
410+ ${CMAKE_SOURCE_DIR}/include/unity/shell/application/ApplicationInfoInterface.h
411+ Mocks/MockApplicationManager.cpp
412+ Mocks/MockApplicationInfo.cpp
413+)
414+
415+add_library(ApplicationMocks SHARED ${ApplicationMocks_SOURCES})
416+
417+qt5_use_modules(ApplicationMocks Core)
418+
419+set(TestApplicationPlugin_SOURCES
420+ TestApplicationPlugin.cpp
421+)
422+
423+add_library(TestApplicationPlugin MODULE ${TestApplicationPlugin_SOURCES})
424+
425+qt5_use_modules(TestApplicationPlugin Core Quick)
426+
427+target_link_libraries(TestApplicationPlugin ApplicationMocks)
428+
429+add_custom_target(TestApplicationPluginQmldir ALL
430+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" "${CMAKE_CURRENT_BINARY_DIR}"
431+ DEPENDS qmldir
432+)
433
434=== added directory 'test/qmltest/mocks/plugins/Unity/Application/Mocks'
435=== added file 'test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.cpp'
436--- test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.cpp 1970-01-01 00:00:00 +0000
437+++ test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.cpp 2013-08-29 12:55:03 +0000
438@@ -0,0 +1,97 @@
439+/*
440+ * Copyright 2013 Canonical Ltd.
441+ *
442+ * This program is free software; you can redistribute it and/or modify
443+ * it under the terms of the GNU Lesser General Public License as published by
444+ * the Free Software Foundation; version 3.
445+ *
446+ * This program is distributed in the hope that it will be useful,
447+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
448+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
449+ * GNU Lesser General Public License for more details.
450+ *
451+ * You should have received a copy of the GNU Lesser General Public License
452+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
453+ *
454+ * Authors:
455+ * Michael Zanetti <michael.zanetti@canonical.com>
456+ */
457+
458+#include <Mocks/MockApplicationInfo.h>
459+
460+using namespace unity::shell::application;
461+
462+MockApplicationInfo::MockApplicationInfo(const QString &appId, const QString& comment, const QString& name, const QUrl& icon, QObject* parent):
463+ ApplicationInfoInterface(appId, parent),
464+ m_appId(appId),
465+ m_name(name),
466+ m_comment(comment),
467+ m_icon(icon),
468+ m_stage(MainStage),
469+ m_state(Running),
470+ m_focused(false)
471+{
472+
473+}
474+
475+QString MockApplicationInfo::appId() const
476+{
477+ return m_appId;
478+}
479+
480+QString MockApplicationInfo::comment() const
481+{
482+ return m_comment;
483+}
484+
485+QString MockApplicationInfo::name() const
486+{
487+ return m_name;
488+}
489+
490+QUrl MockApplicationInfo::icon() const
491+{
492+ return m_icon;
493+}
494+
495+ApplicationInfoInterface::Stage MockApplicationInfo::stage() const
496+{
497+ return m_stage;
498+}
499+
500+void MockApplicationInfo::setStage(ApplicationInfoInterface::Stage stage)
501+{
502+ if (m_stage != stage)
503+ {
504+ m_stage = stage;
505+ Q_EMIT stageChanged(m_stage);
506+ }
507+}
508+
509+ApplicationInfoInterface::State MockApplicationInfo::state() const
510+{
511+ return m_state;
512+}
513+
514+void MockApplicationInfo::setState(ApplicationInfoInterface::State state)
515+{
516+ if (m_state != state)
517+ {
518+ m_state = state;
519+ Q_EMIT stateChanged(m_state);
520+ }
521+}
522+
523+bool MockApplicationInfo::focused() const
524+{
525+ return m_focused;
526+}
527+
528+void MockApplicationInfo::setFocused(bool focused)
529+{
530+ if (m_focused != focused)
531+ {
532+ m_focused = focused;
533+ Q_EMIT focusedChanged(focused);
534+ }
535+}
536
537=== added file 'test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.h'
538--- test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.h 1970-01-01 00:00:00 +0000
539+++ test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationInfo.h 2013-08-29 12:55:03 +0000
540@@ -0,0 +1,59 @@
541+/*
542+ * Copyright 2013 Canonical Ltd.
543+ *
544+ * This program is free software; you can redistribute it and/or modify
545+ * it under the terms of the GNU Lesser General Public License as published by
546+ * the Free Software Foundation; version 3.
547+ *
548+ * This program is distributed in the hope that it will be useful,
549+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
550+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
551+ * GNU Lesser General Public License for more details.
552+ *
553+ * You should have received a copy of the GNU Lesser General Public License
554+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
555+ *
556+ * Authors:
557+ * Michael Zanetti <michael.zanetti@canonical.com>
558+ */
559+
560+#ifndef MOCKAPPLICATIONINFO_H
561+#define MOCKAPPLICATIONINFO_H
562+
563+#include <ApplicationInfoInterface.h>
564+
565+#include <QUrl>
566+
567+using namespace unity::shell::application;
568+
569+class UNITY_API MockApplicationInfo: public ApplicationInfoInterface
570+{
571+ Q_OBJECT
572+public:
573+ MockApplicationInfo(const QString &appId, const QString& name, const QString& comment, const QUrl& icon, QObject* parent = 0);
574+
575+ QString appId() const;
576+ QString name() const;
577+ QString comment() const;
578+ QUrl icon() const;
579+
580+ ApplicationInfoInterface::Stage stage() const;
581+ void setStage(ApplicationInfoInterface::Stage stage);
582+
583+ ApplicationInfoInterface::State state() const;
584+ void setState(ApplicationInfoInterface::State state);
585+
586+ bool focused() const;
587+ void setFocused(bool focused);
588+
589+private:
590+ QString m_appId;
591+ QString m_name;
592+ QString m_comment;
593+ QUrl m_icon;
594+ ApplicationInfoInterface::Stage m_stage;
595+ ApplicationInfoInterface::State m_state;
596+ bool m_focused;
597+};
598+
599+#endif // MOCKAPPLICATIONINFO_H
600
601=== added file 'test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.cpp'
602--- test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.cpp 1970-01-01 00:00:00 +0000
603+++ test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.cpp 2013-08-29 12:55:03 +0000
604@@ -0,0 +1,107 @@
605+/*
606+ * Copyright 2013 Canonical Ltd.
607+ *
608+ * This program is free software; you can redistribute it and/or modify
609+ * it under the terms of the GNU Lesser General Public License as published by
610+ * the Free Software Foundation; version 3.
611+ *
612+ * This program is distributed in the hope that it will be useful,
613+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
614+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
615+ * GNU Lesser General Public License for more details.
616+ *
617+ * You should have received a copy of the GNU Lesser General Public License
618+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
619+ *
620+ * Authors:
621+ * Michael Zanetti <michael.zanetti@canonical.com>
622+ */
623+
624+#include <Mocks/MockApplicationManager.h>
625+#include <Mocks/MockApplicationInfo.h>
626+
627+using namespace unity::shell::application;
628+
629+MockApplicationManager::MockApplicationManager(QObject* parent): ApplicationManagerInterface(parent)
630+{
631+ MockApplicationInfo *item = new MockApplicationInfo("phone-app", "Phone App", "Telephony application", QUrl("/usr/share/pixmaps/some/icon.png"));
632+ m_list.append(item);
633+ item = new MockApplicationInfo("camera-app", "Camera App", "Lets you take pictures with the camera.", QUrl("/usr/share/pixmaps/some/icon.png"));
634+ m_list.append(item);
635+ item = new MockApplicationInfo("calendar-app", "Calendar App", "5 missed reminders", QUrl("/usr/share/pixmaps/some/icon.png"));
636+ m_list.append(item);
637+}
638+
639+MockApplicationManager::~MockApplicationManager()
640+{
641+ while (!m_list.empty())
642+ {
643+ m_list.takeFirst()->deleteLater();
644+ }
645+}
646+
647+// cppcheck-suppress unusedFunction
648+int MockApplicationManager::rowCount(const QModelIndex& parent) const
649+{
650+ Q_UNUSED(parent)
651+ return m_list.count();
652+}
653+
654+QVariant MockApplicationManager::data(const QModelIndex& index, int role) const
655+{
656+ ApplicationInfoInterface *item = m_list.at(index.row());
657+ switch(role)
658+ {
659+ case RoleAppId:
660+ return item->appId();
661+ case RoleName:
662+ return item->name();
663+ case RoleComment:
664+ return item->comment();
665+ case RoleIcon:
666+ return item->icon();
667+ case RoleStage:
668+ return item->stage();
669+ case RoleState:
670+ return item->state();
671+ case RoleFocused:
672+ return item->focused();
673+ }
674+
675+ return QVariant();
676+}
677+
678+unity::shell::application::ApplicationInfoInterface *MockApplicationManager::get(int index) const
679+{
680+ if (index < 0 || index >= m_list.count())
681+ {
682+ return 0;
683+ }
684+ return m_list.at(index);
685+}
686+
687+unity::shell::application::ApplicationInfoInterface *MockApplicationManager::focusedApplication() const
688+{
689+ return m_list.first();
690+}
691+
692+void MockApplicationManager::focusApplication(ApplicationInfoInterface *application)
693+{
694+ Q_UNUSED(application)
695+}
696+
697+void MockApplicationManager::unfocusCurrentApplication()
698+{
699+}
700+
701+unity::shell::application::ApplicationInfoInterface *MockApplicationManager::startApplication(const QString &appId, const QStringList &arguments)
702+{
703+ Q_UNUSED(appId)
704+ Q_UNUSED(arguments)
705+ return 0;
706+}
707+
708+void MockApplicationManager::stopApplication(unity::shell::application::ApplicationInfoInterface *application)
709+{
710+ Q_UNUSED(application)
711+}
712
713=== added file 'test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.h'
714--- test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.h 1970-01-01 00:00:00 +0000
715+++ test/qmltest/mocks/plugins/Unity/Application/Mocks/MockApplicationManager.h 2013-08-29 12:55:03 +0000
716@@ -0,0 +1,57 @@
717+/*
718+ * Copyright 2013 Canonical Ltd.
719+ *
720+ * This program is free software; you can redistribute it and/or modify
721+ * it under the terms of the GNU Lesser General Public License as published by
722+ * the Free Software Foundation; version 3.
723+ *
724+ * This program is distributed in the hope that it will be useful,
725+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
726+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
727+ * GNU Lesser General Public License for more details.
728+ *
729+ * You should have received a copy of the GNU Lesser General Public License
730+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
731+ *
732+ * Authors:
733+ * Michael Zanetti <michael.zanetti@canonical.com>
734+ */
735+
736+#ifndef MOCKAPPLICATIONMANAGER_H
737+#define MOCKAPPLICATIONMANAGER_H
738+
739+#include <ApplicationManagerInterface.h>
740+
741+using namespace unity::shell::application;
742+
743+class MockApplicationInfo;
744+
745+class UNITY_API MockApplicationManager: public ApplicationManagerInterface
746+{
747+ Q_OBJECT
748+
749+public:
750+ MockApplicationManager(QObject* parent = 0);
751+ ~MockApplicationManager();
752+
753+ int rowCount(const QModelIndex& parent) const;
754+
755+ QVariant data(const QModelIndex& index, int role) const;
756+
757+ unity::shell::application::ApplicationInfoInterface *focusedApplication() const;
758+
759+ Q_INVOKABLE unity::shell::application::ApplicationInfoInterface *get(int index) const;
760+
761+ Q_INVOKABLE void focusApplication(unity::shell::application::ApplicationInfoInterface *application);
762+
763+ Q_INVOKABLE void unfocusCurrentApplication();
764+
765+ Q_INVOKABLE unity::shell::application::ApplicationInfoInterface *startApplication(const QString &appId, const QStringList &arguments);
766+
767+ Q_INVOKABLE void stopApplication(unity::shell::application::ApplicationInfoInterface *application);
768+
769+private:
770+ QList<MockApplicationInfo*> m_list;
771+};
772+
773+#endif // MOCKAPPLICATIONMANAGER_H
774
775=== added file 'test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.cpp'
776--- test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.cpp 1970-01-01 00:00:00 +0000
777+++ test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.cpp 2013-08-29 12:55:03 +0000
778@@ -0,0 +1,45 @@
779+/*
780+ * Copyright 2013 Canonical Ltd.
781+ *
782+ * This program is free software; you can redistribute it and/or modify
783+ * it under the terms of the GNU Lesser General Public License as published by
784+ * the Free Software Foundation; version 3.
785+ *
786+ * This program is distributed in the hope that it will be useful,
787+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
788+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
789+ * GNU Lesser General Public License for more details.
790+ *
791+ * You should have received a copy of the GNU Lesser General Public License
792+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
793+ *
794+ * Authors:
795+ * Michael Zanetti <michael.zanetti@canonical.com>
796+ */
797+
798+#include <TestApplicationPlugin.h>
799+#include <Mocks/MockApplicationManager.h>
800+#include <Mocks/MockApplicationInfo.h>
801+
802+#include <ApplicationManagerInterface.h>
803+#include <ApplicationInfoInterface.h>
804+
805+#include <QtQml/qqml.h>
806+
807+using namespace unity::shell::application;
808+
809+static QObject* modelProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
810+{
811+ return new MockApplicationManager();
812+}
813+
814+// cppcheck-suppress unusedFunction
815+void TestApplicationPlugin::registerTypes(const char* uri)
816+{
817+ // @uri Unity.Application
818+ qmlRegisterUncreatableType<ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Interface for the ApplicationManager");
819+ qmlRegisterUncreatableType<ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Interface for the ApplicationInfo");
820+
821+ qmlRegisterSingletonType<MockApplicationManager>(uri, 0, 1, "ApplicationManager", modelProvider);
822+ qmlRegisterUncreatableType<MockApplicationInfo>(uri, 0, 1, "ApplicationInfo", "Can't create ApplicationInfos in QML. Get them from the ApplicationManager");
823+}
824
825=== added file 'test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.h'
826--- test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.h 1970-01-01 00:00:00 +0000
827+++ test/qmltest/mocks/plugins/Unity/Application/TestApplicationPlugin.h 2013-08-29 12:55:03 +0000
828@@ -0,0 +1,35 @@
829+/*
830+ * Copyright 2013 Canonical Ltd.
831+ *
832+ * This program is free software; you can redistribute it and/or modify
833+ * it under the terms of the GNU Lesser General Public License as published by
834+ * the Free Software Foundation; version 3.
835+ *
836+ * This program is distributed in the hope that it will be useful,
837+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
838+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
839+ * GNU Lesser General Public License for more details.
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+ * Michael Zanetti <michael.zanetti@canonical.com>
846+ */
847+
848+
849+#ifndef TESTAPPLICATION_PLUGIN_H
850+#define TESTAPPLICATION_PLUGIN_H
851+
852+#include <QtQml/QQmlExtensionPlugin>
853+
854+class TestApplicationPlugin : public QQmlExtensionPlugin
855+{
856+ Q_OBJECT
857+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
858+
859+public:
860+ void registerTypes(const char* uri);
861+};
862+
863+#endif // TESTAPPLICATION_PLUGIN_H
864
865=== added file 'test/qmltest/mocks/plugins/Unity/Application/qmldir'
866--- test/qmltest/mocks/plugins/Unity/Application/qmldir 1970-01-01 00:00:00 +0000
867+++ test/qmltest/mocks/plugins/Unity/Application/qmldir 2013-08-29 12:55:03 +0000
868@@ -0,0 +1,2 @@
869+module Unity.Application
870+plugin TestApplicationPlugin
871
872=== modified file 'test/qmltest/unity/shell/CMakeLists.txt'
873--- test/qmltest/unity/shell/CMakeLists.txt 2013-06-05 13:07:49 +0000
874+++ test/qmltest/unity/shell/CMakeLists.txt 2013-08-29 12:55:03 +0000
875@@ -8,3 +8,4 @@
876
877 add_qml_test(notifications Notifications)
878 add_qml_test(launcher Launcher)
879+add_qml_test(application Application)
880
881=== added directory 'test/qmltest/unity/shell/application'
882=== added file 'test/qmltest/unity/shell/application/tst_Application.qml'
883--- test/qmltest/unity/shell/application/tst_Application.qml 1970-01-01 00:00:00 +0000
884+++ test/qmltest/unity/shell/application/tst_Application.qml 2013-08-29 12:55:03 +0000
885@@ -0,0 +1,139 @@
886+/*
887+ * Copyright 2013 Canonical Ltd.
888+ *
889+ * This program is free software; you can redistribute it and/or modify
890+ * it under the terms of the GNU Lesser General Public License as published by
891+ * the Free Software Foundation; version 3.
892+ *
893+ * This program is distributed in the hope that it will be useful,
894+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
895+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
896+ * GNU Lesser General Public License for more details.
897+ *
898+ * You should have received a copy of the GNU Lesser General Public License
899+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
900+ *
901+ * Authors:
902+ * Michael Zanetti <michael.zanetti@canonical.com>
903+ */
904+
905+import QtQuick 2.0
906+import QtTest 1.0
907+import TestUtil 0.1
908+import Unity.Application 0.1
909+
910+Item {
911+
912+ SignalSpy {
913+ id: signalSpy
914+ }
915+
916+ Verifier {
917+ id: checkModelVerifier
918+
919+ property var model: ApplicationManager
920+
921+ function test_model_data() {
922+ return [
923+ { tag: "ApplicationManager[object]", type: "object" },
924+ { tag: "ApplicationManager[ApplicationManagerInterface]", type: "unity::shell::application::ApplicationManagerInterface" },
925+ ];
926+ }
927+
928+ function test_model(data) {
929+ object = model;
930+ name = "ApplicationManager"
931+
932+ verifyData(data);
933+ }
934+ }
935+
936+ Verifier {
937+ when: checkModelVerifier.completed
938+
939+ Repeater {
940+ id: repeater
941+ model: ApplicationManager
942+ delegate: Item {
943+ property var roles: model
944+ }
945+ }
946+
947+ /* make sure all the required roles are exposed on ApplicationManager */
948+ function test_model_roles_data() {
949+ return [
950+ { tag: "ApplicationManager.roles[appId]", role: "appId", type: "string" },
951+ { tag: "ApplicationManager.roles[name]", role: "name", type: "string" },
952+ { tag: "ApplicationManager.roles[comment]", role: "comment", type: "string" },
953+ { tag: "ApplicationManager.roles[icon]", role: "icon", type: "object" },
954+ { tag: "ApplicationManager.roles[stage]", role: "stage", type: "number" },
955+ { tag: "ApplicationManager.roles[state]", role: "state", type: "number" },
956+ { tag: "ApplicationManager.roles[focused]", role: "focused", type: "boolean" },
957+ ];
958+ }
959+
960+ function test_model_roles(data) {
961+ name = "ApplicationManager"
962+ try {
963+ object = repeater.itemAt(0).roles;
964+ } catch(err) {
965+ object = undefined;
966+ }
967+
968+ verifyData(data);
969+ }
970+
971+ function test_model_methods_data() {
972+ return [
973+ { tag: "ApplicationManager.methods[get]", method: "get" },
974+ { tag: "ApplicationManager.methods[focusApplication]", method: "focusApplication" },
975+ { tag: "ApplicationManager.methods[unfocusCurrentApplication]", method: "unfocusCurrentApplication" },
976+ { tag: "ApplicationManager.methods[startApplication]", method: "startApplication" },
977+ { tag: "ApplicationManager.methods[stopApplication]", method: "stopApplication" },
978+ ];
979+ }
980+
981+ function test_model_methods(data) {
982+ name = "ApplicationManager";
983+ object = ApplicationManager;
984+ verifyData(data);
985+ }
986+
987+ function test_model_properties_data() {
988+ return [
989+ { tag: "ApplicationManager.count", property: "count", type: "number" },
990+ { tag: "ApplicationManager.focusedApplication", property: "focusedApplication", type: "unity::shell::application::ApplicationInfoInterface" },
991+ ];
992+ }
993+
994+ function test_model_properties(data) {
995+ name = "ApplicationManager";
996+ object = ApplicationManager;
997+ verifyData(data);
998+ }
999+
1000+ function test_item_properties_data() {
1001+ return [
1002+ { tag: "ApplicationInfo.properties[appId]", constant: "appId", type: "string" },
1003+ { tag: "ApplicationInfo.properties[name]", property: "name", type: "string" },
1004+ { tag: "ApplicationInfo.properties[comment]", property: "comment", type: "string" },
1005+ { tag: "ApplicationInfo.properties[icon]", property: "icon", type: "object" },
1006+ { tag: "ApplicationInfo.properties[stage]", property: "stage", type: "number" },
1007+ { tag: "ApplicationInfo.properties[state]", property: "state", type: "number" },
1008+ { tag: "ApplicationInfo.properties[focused]", property: "focused", type: "boolean" },
1009+ ];
1010+ }
1011+
1012+ function test_item_properties(data) {
1013+ name = "ApplicationInfo"
1014+ try {
1015+ object = ApplicationManager.get(0)
1016+ } catch(err) {
1017+ object = undefined;
1018+ print(err)
1019+ }
1020+
1021+ verifyData(data)
1022+ }
1023+ }
1024+}

Subscribers

People subscribed via source and target branches

to all changes: