Merge lp:~saviq/unity-api/add-shell-notifications-api into lp:unity-api

Proposed by Michał Sawicz
Status: Merged
Approved by: Michi Henning
Approved revision: 53
Merged at revision: 45
Proposed branch: lp:~saviq/unity-api/add-shell-notifications-api
Merge into: lp:unity-api
Prerequisite: lp:~saviq/unity-api/add-qmltest-utils
Diff against target: 1758 lines (+1578/-2)
31 files modified
data/unity-shell-api.pc.in (+9/-0)
debian/libunity-api-dev.install (+1/-1)
doc/Doxyfile.in (+1/-1)
include/unity/CMakeLists.txt (+1/-0)
include/unity/shell/CMakeLists.txt (+8/-0)
include/unity/shell/notifications/CMakeLists.txt (+22/-0)
include/unity/shell/notifications/Enums.h (+125/-0)
include/unity/shell/notifications/ModelInterface.h (+90/-0)
include/unity/shell/notifications/NotificationInterface.h (+92/-0)
include/unity/shell/notifications/SourceInterface.h (+86/-0)
test/qmltest/CMakeLists.txt (+2/-0)
test/qmltest/mocks/CMakeLists.txt (+1/-0)
test/qmltest/mocks/plugins/Unity/Notifications/CMakeLists.txt (+41/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/CMakeLists.txt (+14/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.cpp (+69/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.h (+55/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.cpp (+215/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.h (+81/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.cpp (+29/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.h (+56/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.cpp (+36/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.h (+35/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.cpp (+70/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.h (+66/-0)
test/qmltest/mocks/plugins/Unity/Notifications/Mocks/qmldir (+2/-0)
test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.cpp (+58/-0)
test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.h (+35/-0)
test/qmltest/mocks/plugins/Unity/Notifications/qmldir (+2/-0)
test/qmltest/unity/CMakeLists.txt (+1/-0)
test/qmltest/unity/shell/CMakeLists.txt (+9/-0)
test/qmltest/unity/shell/notifications/tst_Notifications.qml (+266/-0)
To merge this branch: bzr merge lp:~saviq/unity-api/add-shell-notifications-api
Reviewer Review Type Date Requested Status
Michi Henning (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+163557@code.launchpad.net

Commit message

add shell Notifications API and tests

To post a comment you must log in.
Revision history for this message
Michał Sawicz (saviq) wrote :

This will fail due to Qt in headers, we need somehow to whitelist Qt for the shell interface.

40. By Michał Sawicz

merge fix-packaging

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

A few minor nitpicks due to style issues (https://launchpad.net/canonical-client-development-guidelines and https://wiki.ubuntu.com/DesktopTeam/Specs/CPlusPlusGuide):

In source.h:

#include SOURCE_H

should be

#include UNITY_SHELL_NOTIFICATIONS_SOURCE_H

The include guard should include the namespace hierarchy.

This affects enums.h, model.h, and notification.h as well.

- In source.h (and other headers):

namespace unity {
namespace shell {
namespace notifications {

The style guide requires braces to go on their own line. For readability, I would suggest to add a newline:

namespace unity
{

namespace shell
{

namespace notifications
{

- I don't want to get into religious wars about placement of curly braces. (Personally, I can live with either K&R style or braces on separate lines.) But it would be really nice if we could be consistent at least. For example, testutil.cpp uses K&R style but elsewhere in the project, we have braces on separate lines. (The style guide suggests braces on separate lines, if only by example.)

The easiest thing might be to just run astyle over the source?

- For a class called TestUtilPlugin, please call the source/header files TestUtilPlugin.h and TestUtilPlugin.cpp, so we have consistent spelling everywhere. Similarly, model.h should be called ModelInterface.h, seeing that it only defines that one class. (The same comment applies throughout, such as for the files underneath test/mocks.)

- We have mocks/plugins/Unity/Notifications, but the corresponding namespaces are called "unity" and "notifications". Therefore, the corresponding directories also should be called "unity" and "notifications"?

review: Needs Fixing
41. By Michał Sawicz

merge add-qmltest-utils

42. By Michał Sawicz

fix c++ and naming style

43. By Michał Sawicz

merge add-qmltest-utils

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

W dniu 14.05.2013 03:20, Michi Henning pisze:
> should be
>
> #include UNITY_SHELL_NOTIFICATIONS_SOURCE_H
>
> The include guard should include the namespace hierarchy.
>
> This affects enums.h, model.h, and notification.h as well.

Done.

> - In source.h (and other headers):
>
> namespace unity {
> namespace shell {
> namespace notifications {
>
> The style guide requires braces to go on their own line. For readability, I would suggest to add a newline:
>
> namespace unity
> {
>
> namespace shell
> {
>
> namespace notifications
> {
>
> - I don't want to get into religious wars about placement of curly braces. (Personally, I can live with either K&R style or braces on separate lines.) But it would be really nice if we could be consistent at least. For example, testutil.cpp uses K&R style but elsewhere in the project, we have braces on separate lines. (The style guide suggests braces on separate lines, if only by example.)
>
> The easiest thing might be to just run astyle over the source?

I must say IMO it reduces readability, but style is style - done.

> - For a class called TestUtilPlugin, please call the source/header files TestUtilPlugin.h and TestUtilPlugin.cpp, so we have consistent spelling everywhere. Similarly, model.h should be called ModelInterface.h, seeing that it only defines that one class. (The same comment applies throughout, such as for the files underneath test/mocks.)

Done.

> - We have mocks/plugins/Unity/Notifications, but the corresponding namespaces are called "unity" and "notifications". Therefore, the corresponding directories also should be called "unity" and "notifications"?

The "Unity/Notifications" part is not directly corresponding to the
namespaces (at least not QML ones). "import Unity.Notifications 0.1" in
QML means "look for a plugin under
$QML2_IMPORT_PATH/Unity/Notifications". We need to keep the import names
CamelCase (although we might need to move them under org/ubuntu/ to
comply with Qt recommendations) for consistency in QML. We would have to
do some hoops to keep them lowercase in the tree but build into CamelCase.

I'm just thinking things under "imports", "plugins", "modules" are
QML-specific and should just reflect the actual QML import path.

--
Michał Sawicz <email address hidden>
Canonical Services Ltd.

Revision history for this message
Michi Henning (michihenning) wrote :

> Done.

Thanks!

> > - We have mocks/plugins/Unity/Notifications, but the corresponding
> namespaces are called "unity" and "notifications". Therefore, the
> corresponding directories also should be called "unity" and "notifications"?
>
> The "Unity/Notifications" part is not directly corresponding to the
> namespaces (at least not QML ones). "import Unity.Notifications 0.1" in
> QML means "look for a plugin under
> $QML2_IMPORT_PATH/Unity/Notifications". We need to keep the import names
> CamelCase (although we might need to move them under org/ubuntu/ to
> comply with Qt recommendations) for consistency in QML. We would have to
> do some hoops to keep them lowercase in the tree but build into CamelCase.

I suspected that this was due to a Qt issue, so I guess we just have to live with that. (The style guide requires namespace names to be lower case--I have no idea why. But, as you say, style is style...)

> I'm just thinking things under "imports", "plugins", "modules" are
> QML-specific and should just reflect the actual QML import path.

Sounds sensible to me!

review: Approve
44. By Michał Sawicz

merge add-testutil-module

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
45. By Michał Sawicz

merge add-qmltest-util

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: Needs Fixing (continuous-integration)
46. By Michał Sawicz

send hovered and displayed values to onHovered / onDisplayed and add documentation

47. By Michał Sawicz

convert the slots to signals to ensure asynchronicity

Revision history for this message
Michał Sawicz (saviq) wrote :

OK, this now has docs as well.

Should be good for review/merging after lp:~michihenning/unity-api/improve-include-checker lands.

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

> OK, this now has docs as well.
>
> Should be good for review/merging after lp:~michihenning/unity-api/improve-
> include-checker lands.

For classes that only have signals (NotificationInterface) and, therefore, don't have pure virtual functions, should the constructor be protected to prevent instantiation of the abstract base class?

Some minor doc fixes here:

https://pastebin.canonical.com/91076/

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

One more thing: "make cppcheck" reports one function that is never called (see below). The tests should exercise it, I would think?

For those functions that we truly don't want to exercise (any?), an inline suppression can be used, such as:

void
// cppcheck-suppress unusedFunction
Myclass::
foo()
{
}

I'll submit a separate MR to change the way cppcheck is called to include the name of the error in the output, so it's easy to add a suppression if we need one.

$ make cppcheck
/home/michi/src/add-shell-notifications-api/test/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.cpp ( 36 ) : style ( unusedFunction ) : The function 'rowCount' is never used.
Built target cppcheck

review: Needs Fixing
48. By Michał Sawicz

merge add-qmltest-util

49. By Michał Sawicz

merge trunk

50. By Michał Sawicz

add cppcheck suppression to MockActionModel::rowCount

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
51. By Michi Henning

doc fixes

52. By Michał Sawicz

Protect NotificationInterface constructor and tweak doxygen comments

Revision history for this message
Michał Sawicz (saviq) wrote :

W dniu 16.05.2013 01:41, Michi Henning pisze:
> For classes that only have signals (NotificationInterface) and, therefore, don't have pure virtual functions, should the constructor be protected to prevent instantiation of the abstract base class?

Indeed. Fixed. Should the others (SourceInterface, ModelInterface)
follow the same, even though it's not necessary due to pure virtuals?

> One more thing: "make cppcheck" reports one function that is never called (see below). The tests should exercise it, I would think?

They do, actually - but indirectly - it's used internally by QML in
tst_Notificaions.qml. That's probably why cppcheck thinks otherwise?

> I'll submit a separate MR to change the way cppcheck is called to include the name of the error in the output, so it's easy to add a suppression if we need one.

I resubmitted it without the prerequisite because of conflicts and will
merge when CI says it's fine.
--
Michał Sawicz <email address hidden>
Canonical Services Ltd.

Revision history for this message
Michał Sawicz (saviq) wrote :

W dniu 16.05.2013 10:01, Michał Sawicz pisze:
> Indeed. Fixed. Should the others (SourceInterface, ModelInterface)
> follow the same, even though it's not necessary due to pure virtuals?

What about pure virtual destructors? Should we make them so, too?

--
Michał Sawicz <email address hidden>
Canonical Services Ltd.

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

> W dniu 16.05.2013 10:01, Michał Sawicz pisze:
> > Indeed. Fixed. Should the others (SourceInterface, ModelInterface)
> > follow the same, even though it's not necessary due to pure virtuals?

For self-documentation purposes and clarity, it makes sense to make all the constructors protected, even if there are pure virtual methods elsewhere in the class.

> What about pure virtual destructors? Should we make them so, too?

No. Destructors should to remain public. There really is no point making the destructor in a base class protected. It would prevent stack allocation of the class (if it were not abstract). But, seeing the class is abstract already, there is no point in a protected destructor.

Revision history for this message
Michi Henning (michihenning) wrote :

> > One more thing: "make cppcheck" reports one function that is never called
> (see below). The tests should exercise it, I would think?
>
> They do, actually - but indirectly - it's used internally by QML in
> tst_Notificaions.qml. That's probably why cppcheck thinks otherwise?

Looks like it's fine now. Not sure why I saw this error even after I added builddir/test to cppcheck. Never mind. If this pops up again, we can deal with it separately.

> I resubmitted it without the prerequisite because of conflicts and will
> merge when CI says it's fine.

Thanks!

review: Approve
Revision history for this message
Michał Sawicz (saviq) wrote :

W dniu 16.05.2013 10:54, Michi Henning pisze:
> Looks like it's fine now. Not sure why I saw this error even after I added builddir/test to cppcheck. Never mind. If this pops up again, we can deal with it separately.

That's because I've added cppcheck-suppress for it...

> For self-documentation purposes and clarity, it makes sense to make all the constructors protected, even if there are pure virtual methods elsewhere in the class.

Yup, that's what I thought. Will do.

> No. Destructors should to remain public. There really is no point making the destructor in a base class protected. It would prevent stack allocation of the class (if it were not abstract). But, seeing the class is abstract already, there is no point in a protected destructor.

No no, I meant whether we should make them pure virtual - they're not,
currently.

--
Michał Sawicz <email address hidden>
Canonical Services Ltd.

53. By Michał Sawicz

protect ModelInterface and SourceInterface c'tors, too

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

> No no, I meant whether we should make them pure virtual - they're not,
> currently.

Ah, I see :-)

Hmmm... Pure virtual destructors are rarely used, if ever. They are a bit of a pain because you also need to write an out-of-line definition for a pure virtual destructor. (That's because the destructor *will* be called, despite being pure, so there has to be an implementation.)

Overall, I don't see any additional benefit. I guess it would make the class even more self-documenting. On the other hand, I doubt that the average C++ programmer would even know what a pure virtual destructor means...

Basically, the issue only arises for classes that are abstract and have at least one non-pure virtual function. In that case, making the constructor protected is effective. Making the destructor pure virtual is also effective. Doing both is effective as well, but one of the two is redudant.

If a class is abstract and does *not* have any virtual functions, then the only way to make it abstract is with a pure virtual destructor. But then, one has to ask the question "what's the point of an abstract base class that does not have a single virtual functions?" As far as I can see, there is none. In effect, such a class says "you must not instantiate me directly, but only via a derived class. The derived class is not obliged to do anything in particular, but it must have at least one virtual function. I don't care what that function is called or what it does." I simply can't see a use case for this...

Now, someone tell me again, why does C++ not have an abstract keyword so I could just write

abstract class X { ... }

So, overall, I'd be inclined to say there is no need for pure virtual destructor, but I don't feel all that strongly about it. The class is correct whether the destructor is pure virtual or just virtual.

Revision history for this message
Michał Sawicz (saviq) wrote :

W dniu 16.05.2013 12:52, Michi Henning pisze:
> So, overall, I'd be inclined to say there is no need for pure virtual destructor, but I don't feel all that strongly about it. The class is correct whether the destructor is pure virtual or just virtual.

Cool!

OK so the only remaining thing might be the cppcheck suppression - shall
I leave it in or do we want to investigate why it's wrongly marked as
unused?
--
Michał Sawicz <email address hidden>
Canonical Services Ltd.

Revision history for this message
Michi Henning (michihenning) wrote :

> OK so the only remaining thing might be the cppcheck suppression - shall
> I leave it in or do we want to investigate why it's wrongly marked as
> unused?

After doing a build and running

find . -name '*.cpp' | xargs egrep rowCount

from the top directory, I get only two hits, one in MockActionModel.cpp, and one in MockModel.cpp. Both are definitions of the method.

The complaint from cppcheck is for the one in MockActionModel.cpp. What's strange is that, despite there being no call site for either of them in any .cpp or .h file, we get a complaint for only one of them. I would have expected two complaints for this, one for each definition.

At any rate, I'm happy to let this go. It's probably not worth the effort of tracking down what's going on here.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'data'
2=== added file 'data/unity-shell-api.pc.in'
3--- data/unity-shell-api.pc.in 1970-01-01 00:00:00 +0000
4+++ data/unity-shell-api.pc.in 2013-05-16 10:27:27 +0000
5@@ -0,0 +1,9 @@
6+prefix=@CMAKE_INSTALL_PREFIX@
7+includedir=${prefix}/include
8+
9+Name: @PKGCONFIG_NAME@
10+Description: @PKGCONFIG_NAME@
11+Version: @VERSION@
12+
13+Requires: @PKGCONFIG_REQUIRES@
14+Cflags: -I${includedir}
15
16=== modified file 'debian/libunity-api-dev.install'
17--- debian/libunity-api-dev.install 2013-05-16 10:27:26 +0000
18+++ debian/libunity-api-dev.install 2013-05-16 10:27:27 +0000
19@@ -1,3 +1,3 @@
20 usr/include/unity/*
21 usr/lib/*/libunity-api.so
22-usr/lib/*/pkgconfig/libunity-api.pc
23+usr/lib/*/pkgconfig/*.pc
24
25=== modified file 'doc/Doxyfile.in'
26--- doc/Doxyfile.in 2013-05-13 11:39:49 +0000
27+++ doc/Doxyfile.in 2013-05-16 10:27:27 +0000
28@@ -203,7 +203,7 @@
29 # will result in a user-defined paragraph with heading "Side Effects:".
30 # You can put \n's in the value part of an alias to insert newlines.
31
32-ALIASES =
33+ALIASES = "accessors=\par Accessors:\n" "notifier=\par Notifier:\n"
34
35 # This tag can be used to specify a number of word-keyword mappings (TCL only).
36 # A mapping has the form "name=value". For example adding
37
38=== modified file 'include/unity/CMakeLists.txt'
39--- include/unity/CMakeLists.txt 2013-05-15 02:05:18 +0000
40+++ include/unity/CMakeLists.txt 2013-05-16 10:27:27 +0000
41@@ -1,4 +1,5 @@
42 add_subdirectory(api)
43+add_subdirectory(shell)
44 add_subdirectory(util)
45
46 file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
47
48=== added directory 'include/unity/shell'
49=== added file 'include/unity/shell/CMakeLists.txt'
50--- include/unity/shell/CMakeLists.txt 1970-01-01 00:00:00 +0000
51+++ include/unity/shell/CMakeLists.txt 2013-05-16 10:27:27 +0000
52@@ -0,0 +1,8 @@
53+add_subdirectory(notifications)
54+
55+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
56+file(GLOB internal_headers "${CMAKE_CURRENT_SOURCE_DIR}/internal/*.h")
57+
58+install(FILES ${headers} DESTINATION ${HDR_INSTALL_DIR}/unity/shell)
59+
60+set(UNITY_API_LIB_HDRS ${UNITY_API_LIB_HDRS} ${headers} ${internal_headers} PARENT_SCOPE)
61
62=== added directory 'include/unity/shell/notifications'
63=== added file 'include/unity/shell/notifications/CMakeLists.txt'
64--- include/unity/shell/notifications/CMakeLists.txt 1970-01-01 00:00:00 +0000
65+++ include/unity/shell/notifications/CMakeLists.txt 2013-05-16 10:27:27 +0000
66@@ -0,0 +1,22 @@
67+set(INCLUDE_INSTALL_DIR include/unity/shell/notifications)
68+
69+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
70+file(GLOB internal_headers "${CMAKE_CURRENT_SOURCE_DIR}/internal/*.h")
71+
72+install(FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR})
73+
74+set(UNITY_API_LIB_HDRS ${UNITY_API_LIB_HDRS} ${headers} ${internal_headers} PARENT_SCOPE)
75+
76+set(VERSION 1)
77+set(PKGCONFIG_NAME "unity-shell-notifications")
78+set(PKGCONFIG_DESCRIPTION "Unity shell Notifications APIs")
79+set(PKGCONFIG_REQUIRES "Qt5Core")
80+set(PKGCONFIG_FILE unity-shell-notifications.pc)
81+
82+configure_file(${CMAKE_SOURCE_DIR}/data/unity-shell-api.pc.in
83+ ${CMAKE_BINARY_DIR}/data/${PKGCONFIG_FILE} @ONLY
84+)
85+
86+install(FILES ${CMAKE_BINARY_DIR}/data/${PKGCONFIG_FILE}
87+ DESTINATION ${LIB_INSTALL_PREFIX}/pkgconfig
88+)
89
90=== added file 'include/unity/shell/notifications/Enums.h'
91--- include/unity/shell/notifications/Enums.h 1970-01-01 00:00:00 +0000
92+++ include/unity/shell/notifications/Enums.h 2013-05-16 10:27:27 +0000
93@@ -0,0 +1,125 @@
94+/*
95+ * Copyright 2013 Canonical Ltd.
96+ *
97+ * This program is free software; you can redistribute it and/or modify
98+ * it under the terms of the GNU Lesser General Public License as published by
99+ * the Free Software Foundation; version 3.
100+ *
101+ * This program is distributed in the hope that it will be useful,
102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104+ * GNU Lesser General Public License for more details.
105+ *
106+ * You should have received a copy of the GNU Lesser General Public License
107+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
108+ *
109+ * Authors:
110+ * Michał Sawicz <michal.sawicz@canonical.com>
111+ */
112+
113+
114+#ifndef UNITY_SHELL_NOTIFICATIONS_ENUMS_H
115+#define UNITY_SHELL_NOTIFICATIONS_ENUMS_H
116+
117+#include <unity/config.h>
118+
119+#include <QtCore/QObject>
120+
121+namespace unity
122+{
123+
124+namespace shell
125+{
126+
127+namespace notifications
128+{
129+
130+/**
131+\brief Wraps NotificationInterface's urgency enumeration.
132+*/
133+
134+class UNITY_API Urgency : public QObject
135+{
136+ Q_OBJECT
137+
138+ Q_ENUMS(UrgencyEnum)
139+
140+public:
141+ /**
142+ \brief NotificationInterface's urgency enumeration.
143+
144+ This determines the order in which notifications are displayed.
145+ */
146+ enum class UrgencyEnum
147+ {
148+ Invalid = 0,
149+ Low, /**< Displayed last. */
150+ Normal, /**< Displayed before Low, after Critical. */
151+ Critical /**< Displayed before Low and Normal. */
152+ };
153+};
154+
155+
156+/**
157+\brief Wraps NotificationInterface's type enumeration.
158+*/
159+
160+class UNITY_API Type : public QObject
161+{
162+ Q_OBJECT
163+
164+ Q_ENUMS(TypeEnum)
165+
166+public:
167+ /**
168+ \brief NotificationInterface's type enumeration.
169+
170+ This determines the visual and interaction behavior of the displayed notification.
171+ */
172+ enum class TypeEnum
173+ {
174+ Invalid = 0,
175+ Confirmation, /**< Confirmation (synchronous). */
176+ Ephemeral, /**< Ephemeral (input-transparent). */
177+ Interactive, /**< Interactive (clickable). */
178+ SnapDecision, /**< Snap decision (multi-button). */
179+ Placeholder /**< Non-visible placeholder of default size. */
180+ };
181+};
182+
183+
184+/**
185+\brief Wraps NotificationInterface's hint flags.
186+*/
187+
188+class UNITY_API Hint : public QObject
189+{
190+ Q_OBJECT
191+
192+ Q_FLAGS(HintEnum)
193+
194+public:
195+ /**
196+ \brief NotificationInterface's hint flags.
197+
198+ This modifies some visual and interactive behavior of the displayed notification.
199+ */
200+ enum HintEnum
201+ {
202+ Invalid = 1 << 0,
203+ ButtonTint = 1 << 1, /**< Use a colour tint on the positive button in a snap decision. */
204+ IconOnly = 1 << 2 /**< Only display the icon, no summary or body. */
205+ };
206+
207+ Q_DECLARE_FLAGS(Hints, HintEnum)
208+};
209+
210+Q_DECLARE_OPERATORS_FOR_FLAGS(Hint::Hints)
211+
212+} // namespace notifications
213+
214+} // namespace shell
215+
216+} // namespace unity
217+
218+#endif // UNITY_SHELL_NOTIFICATIONS_ENUMS_H
219
220=== added file 'include/unity/shell/notifications/ModelInterface.h'
221--- include/unity/shell/notifications/ModelInterface.h 1970-01-01 00:00:00 +0000
222+++ include/unity/shell/notifications/ModelInterface.h 2013-05-16 10:27:27 +0000
223@@ -0,0 +1,90 @@
224+/*
225+ * Copyright 2013 Canonical Ltd.
226+ *
227+ * This program is free software; you can redistribute it and/or modify
228+ * it under the terms of the GNU Lesser General Public License as published by
229+ * the Free Software Foundation; version 3.
230+ *
231+ * This program is distributed in the hope that it will be useful,
232+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
233+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
234+ * GNU Lesser General Public License for more details.
235+ *
236+ * You should have received a copy of the GNU Lesser General Public License
237+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
238+ *
239+ * Authors:
240+ * Michał Sawicz <michal.sawicz@canonical.com>
241+ */
242+
243+
244+#ifndef UNITY_SHELL_NOTIFICATIONS_MODELINTERFACE_H
245+#define UNITY_SHELL_NOTIFICATIONS_MODELINTERFACE_H
246+
247+#include <unity/config.h>
248+
249+#include <QtCore/QAbstractListModel>
250+
251+namespace unity
252+{
253+
254+namespace shell
255+{
256+
257+namespace notifications
258+{
259+
260+
261+/**
262+\brief A list of notifications to be displayed
263+
264+This model exposes all the notifications that are currently supposed to be on screen.
265+Not all of them might actually get on screen due to screen size, in which case the
266+NotificationInterface::displayed() signal will only be emitted after the notification was
267+actually displayed.
268+*/
269+
270+class UNITY_API ModelInterface : public QAbstractListModel
271+{
272+ Q_OBJECT
273+
274+ /**
275+ \brief Whether a placeholder for confirmation should be kept at the beginning
276+
277+ When this is true, the model should hold a Placeholder type notification at the top
278+ and update its data when an incoming Confirmation type notification is sent.
279+
280+ \accessors %confirmationPlaceholder(), setConfirmationPlaceholder(bool confirmationPlaceholder)
281+ \notifier confirmationPlaceholderChanged(bool confirmationPlaceholder)
282+ */
283+ Q_PROPERTY(bool confirmationPlaceholder READ confirmationPlaceholder WRITE setConfirmationPlaceholder NOTIFY confirmationPlaceholderChanged)
284+
285+protected:
286+ /// @cond
287+ explicit ModelInterface(QObject* parent = 0) : QAbstractListModel(parent) { }
288+ /// @endcond
289+
290+public:
291+ virtual ~ModelInterface() { }
292+
293+ /// @cond
294+ virtual bool confirmationPlaceholder() const = 0;
295+ virtual void setConfirmationPlaceholder(bool confirmationPlaceholder) = 0;
296+ /// @endcond
297+
298+Q_SIGNALS:
299+ /**
300+ Emitted when value of the confirmationPlaceholder property has changed.
301+
302+ \param confirmationPlaceholder New value of the confirmationPlaceholder property.
303+ */
304+ void confirmationPlaceholderChanged(bool confirmationPlaceholder);
305+};
306+
307+} // namespace notifications
308+
309+} // namespace shell
310+
311+} // namespace unity
312+
313+#endif // UNITY_SHELL_NOTIFICATIONS_MODELINTERFACE_H
314
315=== added file 'include/unity/shell/notifications/NotificationInterface.h'
316--- include/unity/shell/notifications/NotificationInterface.h 1970-01-01 00:00:00 +0000
317+++ include/unity/shell/notifications/NotificationInterface.h 2013-05-16 10:27:27 +0000
318@@ -0,0 +1,92 @@
319+/*
320+ * Copyright 2013 Canonical Ltd.
321+ *
322+ * This program is free software; you can redistribute it and/or modify
323+ * it under the terms of the GNU Lesser General Public License as published by
324+ * the Free Software Foundation; version 3.
325+ *
326+ * This program is distributed in the hope that it will be useful,
327+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
328+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
329+ * GNU Lesser General Public License for more details.
330+ *
331+ * You should have received a copy of the GNU Lesser General Public License
332+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
333+ *
334+ * Authors:
335+ * Michał Sawicz <michal.sawicz@canonical.com>
336+ */
337+
338+
339+#ifndef UNITY_SHELL_NOTIFICATIONS_NOTIFICATIONINTERFACE_H
340+#define UNITY_SHELL_NOTIFICATIONS_NOTIFICATIONINTERFACE_H
341+
342+#include <unity/config.h>
343+
344+#include <QtCore/QObject>
345+
346+namespace unity
347+{
348+
349+namespace shell
350+{
351+
352+namespace notifications
353+{
354+
355+/**
356+\brief A Notification object
357+
358+This class exposes signals used by the UI to communicate the state
359+of a notification.
360+*/
361+
362+class UNITY_API NotificationInterface : public QObject
363+{
364+ Q_OBJECT
365+
366+protected:
367+ /// @cond
368+ explicit NotificationInterface(QObject* parent = 0) : QObject(parent) { }
369+ /// @endcond
370+
371+public:
372+ virtual ~NotificationInterface() { }
373+
374+Q_SIGNALS:
375+ /**
376+ Will be called whenever the mouse hover status of a notification changes.
377+
378+ \param hovered Mouse hover status of this notification.
379+ */
380+ void hovered(bool hovered);
381+
382+ /**
383+ Will be called whenever the display status of a notification changes.
384+
385+ \param displayed Visible/hidden status of this notification.
386+ */
387+ void displayed(bool displayed);
388+
389+ /**
390+ Will be called whenever the notification was dismissed. This can be called internally
391+ by the notification implementation (e.g. timeout) or from the UI when the user dismisses
392+ a notification.
393+ */
394+ void dismissed();
395+
396+ /**
397+ Will be called whenever an action of this notification is to be invoked.
398+
399+ \param id Id of the invoked action.
400+ */
401+ void actionInvoked(const QString& id);
402+};
403+
404+} // namespace notifications
405+
406+} // namespace shell
407+
408+} // namespace unity
409+
410+#endif // UNITY_SHELL_NOTIFICATIONS_NOTIFICATIONINTERFACE_H
411
412=== added file 'include/unity/shell/notifications/SourceInterface.h'
413--- include/unity/shell/notifications/SourceInterface.h 1970-01-01 00:00:00 +0000
414+++ include/unity/shell/notifications/SourceInterface.h 2013-05-16 10:27:27 +0000
415@@ -0,0 +1,86 @@
416+/*
417+ * Copyright 2013 Canonical Ltd.
418+ *
419+ * This program is free software; you can redistribute it and/or modify
420+ * it under the terms of the GNU Lesser General Public License as published by
421+ * the Free Software Foundation; version 3.
422+ *
423+ * This program is distributed in the hope that it will be useful,
424+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
425+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
426+ * GNU Lesser General Public License for more details.
427+ *
428+ * You should have received a copy of the GNU Lesser General Public License
429+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
430+ *
431+ * Authors:
432+ * Michał Sawicz <michal.sawicz@canonical.com>
433+ */
434+
435+
436+#ifndef UNITY_SHELL_NOTIFICATIONS_SOURCEINTERFACE_H
437+#define UNITY_SHELL_NOTIFICATIONS_SOURCEINTERFACE_H
438+
439+#include <unity/config.h>
440+
441+#include <QtCore/QObject>
442+
443+namespace unity
444+{
445+
446+namespace shell
447+{
448+
449+namespace notifications
450+{
451+
452+
453+class ModelInterface;
454+
455+/**
456+\brief A source of notifications
457+
458+This should feed the model with new notifications from an implementation-specific
459+source.
460+*/
461+class UNITY_API SourceInterface : public QObject
462+{
463+ Q_OBJECT
464+
465+ /**
466+ \brief The model to which to send incoming notifications.
467+
468+ \accessors %model(), setModel(ModelInterface* model)
469+ \notifier modelChanged(ModelInterface* model)
470+ */
471+ Q_PROPERTY(unity::shell::notifications::ModelInterface* model READ model WRITE setModel NOTIFY modelChanged)
472+
473+protected:
474+ /// @cond
475+ explicit SourceInterface(QObject* parent = 0) : QObject(parent) { }
476+ /// @endcond
477+
478+public:
479+ virtual ~SourceInterface() { }
480+
481+ /// @cond
482+ virtual ModelInterface* model() const = 0;
483+ virtual void setModel(ModelInterface* model) = 0;
484+ /// @endcond
485+
486+Q_SIGNALS:
487+ /**
488+ Emitted when value of the model property has changed.
489+
490+ \param model New value of the model property.
491+ */
492+ void modelChanged(ModelInterface* model);
493+};
494+
495+} // namespace notifications
496+
497+} // namespace shell
498+
499+} // namespace unity
500+
501+#endif // UNITY_SHELL_NOTIFICATIONS_SOURCEINTERFACE_H
502
503=== modified file 'test/qmltest/CMakeLists.txt'
504--- test/qmltest/CMakeLists.txt 2013-05-16 10:27:26 +0000
505+++ test/qmltest/CMakeLists.txt 2013-05-16 10:27:27 +0000
506@@ -1,1 +1,3 @@
507 add_subdirectory(modules)
508+add_subdirectory(mocks)
509+add_subdirectory(unity)
510
511=== added directory 'test/qmltest/mocks'
512=== added file 'test/qmltest/mocks/CMakeLists.txt'
513--- test/qmltest/mocks/CMakeLists.txt 1970-01-01 00:00:00 +0000
514+++ test/qmltest/mocks/CMakeLists.txt 2013-05-16 10:27:27 +0000
515@@ -0,0 +1,1 @@
516+add_subdirectory(plugins/Unity/Notifications)
517
518=== added directory 'test/qmltest/mocks/plugins'
519=== added directory 'test/qmltest/mocks/plugins/Unity'
520=== added directory 'test/qmltest/mocks/plugins/Unity/Notifications'
521=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/CMakeLists.txt'
522--- test/qmltest/mocks/plugins/Unity/Notifications/CMakeLists.txt 1970-01-01 00:00:00 +0000
523+++ test/qmltest/mocks/plugins/Unity/Notifications/CMakeLists.txt 2013-05-16 10:27:27 +0000
524@@ -0,0 +1,41 @@
525+include_directories(
526+ ${CMAKE_CURRENT_SOURCE_DIR}
527+)
528+
529+add_definitions(-DQT_NO_KEYWORDS)
530+set(CMAKE_AUTOMOC ON)
531+
532+find_package(Qt5Core REQUIRED)
533+find_package(Qt5Quick REQUIRED)
534+
535+set(NotificationsMocks_SOURCES
536+ ${CMAKE_SOURCE_DIR}/include/unity/shell/notifications/Enums.h
537+ ${CMAKE_SOURCE_DIR}/include/unity/shell/notifications/ModelInterface.h
538+ ${CMAKE_SOURCE_DIR}/include/unity/shell/notifications/SourceInterface.h
539+ ${CMAKE_SOURCE_DIR}/include/unity/shell/notifications/NotificationInterface.h
540+ Mocks/MockModel.cpp
541+ Mocks/MockSource.cpp
542+ Mocks/MockNotification.cpp
543+ Mocks/MockActionModel.cpp
544+)
545+
546+add_library(NotificationsMocks SHARED ${NotificationsMocks_SOURCES})
547+
548+qt5_use_modules(NotificationsMocks Core)
549+
550+set(TestNotificationsPlugin_SOURCES
551+ TestNotificationsPlugin.cpp
552+)
553+
554+add_library(TestNotificationsPlugin MODULE ${TestNotificationsPlugin_SOURCES})
555+
556+qt5_use_modules(TestNotificationsPlugin Core Quick)
557+
558+target_link_libraries(TestNotificationsPlugin NotificationsMocks)
559+
560+add_custom_target(TestNotificationsPluginQmldir ALL
561+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" "${CMAKE_CURRENT_BINARY_DIR}"
562+ DEPENDS qmldir
563+)
564+
565+add_subdirectory(Mocks)
566
567=== added directory 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks'
568=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/CMakeLists.txt'
569--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/CMakeLists.txt 1970-01-01 00:00:00 +0000
570+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/CMakeLists.txt 2013-05-16 10:27:27 +0000
571@@ -0,0 +1,14 @@
572+set(MockNotificationsPlugin_SOURCES
573+ MockNotificationsPlugin.cpp
574+)
575+
576+add_library(MockNotificationsPlugin MODULE ${MockNotificationsPlugin_SOURCES})
577+
578+qt5_use_modules(MockNotificationsPlugin Core Quick)
579+
580+target_link_libraries(MockNotificationsPlugin NotificationsMocks)
581+
582+add_custom_target(MockNotificationsPluginQmldir ALL
583+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" "${CMAKE_CURRENT_BINARY_DIR}"
584+ DEPENDS qmldir
585+)
586
587=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.cpp'
588--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.cpp 1970-01-01 00:00:00 +0000
589+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.cpp 2013-05-16 10:27:27 +0000
590@@ -0,0 +1,69 @@
591+/*
592+ * Copyright 2013 Canonical Ltd.
593+ *
594+ * This program is free software; you can redistribute it and/or modify
595+ * it under the terms of the GNU General Public License as published by
596+ * the Free Software Foundation; version 3.
597+ *
598+ * This program is distributed in the hope that it will be useful,
599+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
600+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
601+ * GNU Lesser General Public License for more details.
602+ *
603+ * You should have received a copy of the GNU Lesser General Public License
604+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
605+ *
606+ * Authors:
607+ * Michał Sawicz <michal.sawicz@canonical.com>
608+ */
609+
610+
611+#include <Mocks/MockActionModel.h>
612+#include <Mocks/MockNotification.h>
613+
614+#include <QtCore/QVariantList>
615+#include <QtCore/QVariantMap>
616+
617+MockActionModel::MockActionModel(QObject* parent)
618+ : QAbstractListModel(parent)
619+ , m_notification(qobject_cast<MockNotification*>(parent))
620+{
621+ m_roles.insert(Label, "label");
622+ m_roles.insert(Id, "id");
623+}
624+
625+int
626+// cppcheck-suppress unusedFunction
627+MockActionModel::rowCount(const QModelIndex& /* parent */) const
628+{
629+ if (m_notification && m_notification->m_data.contains("actions"))
630+ {
631+ QVariantList actions = m_notification->m_data["actions"].value<QVariantList>();
632+ return actions.count();
633+ }
634+ return 0;
635+}
636+
637+QVariant
638+MockActionModel::data(const QModelIndex &index, int role) const
639+{
640+ QVariantMap action = m_notification->m_data["actions"].value<QVariantList>()[index.row()].value<QVariantMap>();
641+ if (role == Label)
642+ {
643+ return action["label"];
644+ }
645+ else if (role == Id)
646+ {
647+ return action["id"];
648+ }
649+ else
650+ {
651+ return QVariant();
652+ }
653+}
654+
655+QHash<int, QByteArray>
656+MockActionModel::roleNames() const
657+{
658+ return m_roles;
659+}
660
661=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.h'
662--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.h 1970-01-01 00:00:00 +0000
663+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockActionModel.h 2013-05-16 10:27:27 +0000
664@@ -0,0 +1,55 @@
665+/*
666+ * Copyright 2013 Canonical Ltd.
667+ *
668+ * This program is free software; you can redistribute it and/or modify
669+ * it under the terms of the GNU General Public License as published by
670+ * the Free Software Foundation; version 3.
671+ *
672+ * This program is distributed in the hope that it will be useful,
673+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
674+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
675+ * GNU Lesser General Public License for more details.
676+ *
677+ * You should have received a copy of the GNU Lesser General Public License
678+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
679+ *
680+ * Authors:
681+ * Michał Sawicz <michal.sawicz@canonical.com>
682+ */
683+
684+
685+#ifndef MOCKACTIONMODEL_H
686+#define MOCKACTIONMODEL_H
687+
688+#include <unity/config.h>
689+
690+#include <QtCore/QAbstractListModel>
691+
692+class MockNotification;
693+
694+class UNITY_API MockActionModel : public QAbstractListModel
695+{
696+ Q_OBJECT
697+
698+ Q_ENUMS(RoleEnum)
699+public:
700+ explicit MockActionModel(QObject *parent = 0);
701+
702+ int rowCount(const QModelIndex& parent) const;
703+ QVariant data(const QModelIndex &index, int role) const;
704+ QHash<int, QByteArray> roleNames() const;
705+
706+ enum RoleEnum
707+ {
708+ Label = Qt::DisplayRole,
709+ Id = Qt::UserRole
710+ };
711+
712+private:
713+ QHash<int, QByteArray> m_roles;
714+ MockNotification* m_notification;
715+};
716+
717+Q_DECLARE_METATYPE(MockActionModel*)
718+
719+#endif // MOCKACTIONMODEL_H
720
721=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.cpp'
722--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.cpp 1970-01-01 00:00:00 +0000
723+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.cpp 2013-05-16 10:27:27 +0000
724@@ -0,0 +1,215 @@
725+/*
726+ * Copyright 2013 Canonical Ltd.
727+ *
728+ * This program is free software; you can redistribute it and/or modify
729+ * it under the terms of the GNU General Public License as published by
730+ * the Free Software Foundation; version 3.
731+ *
732+ * This program is distributed in the hope that it will be useful,
733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
735+ * GNU Lesser General Public License for more details.
736+ *
737+ * You should have received a copy of the GNU Lesser General Public License
738+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
739+ *
740+ * Authors:
741+ * Michał Sawicz <michal.sawicz@canonical.com>
742+ */
743+
744+
745+#include <Mocks/MockModel.h>
746+#include <Mocks/MockNotification.h>
747+#include <Mocks/MockActionModel.h>
748+
749+#include <unity/shell/notifications/Enums.h>
750+#include <unity/shell/notifications/SourceInterface.h>
751+#include <unity/shell/notifications/NotificationInterface.h>
752+
753+#include <QtCore/QUrl>
754+
755+using namespace unity::shell::notifications;
756+
757+MockModel::MockModel(QObject* parent)
758+ : ModelInterface(parent)
759+{
760+ m_roles.insert(Summary, "summary");
761+ m_roles.insert(Notification, "notification");
762+ m_roles.insert(Id, "id");
763+ m_roles.insert(Type, "type");
764+ m_roles.insert(Urgency, "urgency");
765+ m_roles.insert(Body, "body");
766+ m_roles.insert(Value, "value");
767+ m_roles.insert(Icon, "icon");
768+ m_roles.insert(SecondaryIcon, "secondaryIcon");
769+ m_roles.insert(Hints, "hints");
770+ m_roles.insert(Actions, "actions");
771+}
772+
773+int
774+MockModel::rowCount(const QModelIndex &parent) const
775+{
776+ Q_UNUSED(parent);
777+
778+ return m_list.count();
779+}
780+
781+QVariant
782+MockModel::data(const QModelIndex &index, int role) const
783+{
784+ if (!index.isValid())
785+ {
786+ return QVariant();
787+ }
788+
789+ MockNotification* notification = m_list.at(index.row());
790+
791+ if (role == Summary)
792+ {
793+ return QVariant("");
794+ }
795+ else if (role == Notification)
796+ {
797+ return QVariant::fromValue(notification);
798+ }
799+ else if (role == Id)
800+ {
801+ return QVariant(index.row());
802+ }
803+ else if (role == Type)
804+ {
805+ if (notification->m_data.contains("type"))
806+ {
807+ return notification->m_data["type"];
808+ }
809+ else
810+ {
811+ return QVariant((int)unity::shell::notifications::Type::TypeEnum::Invalid);
812+ }
813+ }
814+ else if (role == Urgency)
815+ {
816+ return QVariant((int)unity::shell::notifications::Urgency::UrgencyEnum::Invalid);
817+ }
818+ else if (role == Body)
819+ {
820+ return QVariant("");
821+ }
822+ else if (role == Value)
823+ {
824+ return QVariant(0);
825+ }
826+ else if (role == Icon)
827+ {
828+ return QVariant::fromValue(QUrl(""));
829+ }
830+ else if (role == SecondaryIcon)
831+ {
832+ return QVariant::fromValue(QUrl(""));
833+ }
834+ else if (role == Hints)
835+ {
836+ return QVariant(unity::shell::notifications::Hint::Invalid);
837+ }
838+ else if (role == Actions)
839+ {
840+ return QVariant::fromValue(notification->m_actions);
841+ }
842+
843+ return QVariant();
844+}
845+
846+QHash<int, QByteArray>
847+MockModel::roleNames() const
848+{
849+ return m_roles;
850+}
851+
852+void
853+MockModel::setConfirmationPlaceholder(bool confirmationPlaceholder)
854+{
855+ if (m_confirmationPlaceholder != confirmationPlaceholder)
856+ {
857+ m_confirmationPlaceholder = confirmationPlaceholder;
858+
859+ if (m_confirmationPlaceholder)
860+ {
861+ MockNotification* notification = new MockNotification(this);
862+
863+ notification->m_data.insert("type", (int)unity::shell::notifications::Type::TypeEnum::Placeholder);
864+ connect(notification, SIGNAL(dismissed()), SLOT(onDismissed()));
865+
866+ beginInsertRows(QModelIndex(), 0, 0);
867+ m_list.insert(0, notification);
868+ endInsertRows();
869+ }
870+ else
871+ {
872+ if (m_list.count() > 0
873+ && m_list.at(0)->m_data.contains("type")
874+ && m_list.at(0)->m_data["type"] == (int)unity::shell::notifications::Type::TypeEnum::Placeholder)
875+ {
876+ MockNotification* notification = m_list.at(0);
877+ beginRemoveRows(QModelIndex(), 0, 0);
878+ m_list.removeAt(0);
879+ endRemoveRows();
880+ notification->deleteLater();
881+ }
882+ }
883+
884+ Q_EMIT confirmationPlaceholderChanged(m_confirmationPlaceholder);
885+ }
886+}
887+
888+void
889+MockModel::add(MockNotification* notification)
890+{
891+ connect(notification, SIGNAL(dismissed()), SLOT(onDismissed()));
892+ int row = -1;
893+ if (m_confirmationPlaceholder
894+ && notification->m_data.contains("type")
895+ && notification->m_data["type"] == (int)unity::shell::notifications::Type::TypeEnum::Confirmation)
896+ {
897+ MockNotification* placeholder = m_list.at(0);
898+ placeholder->m_data["type"] = (int)unity::shell::notifications::Type::TypeEnum::Confirmation;
899+ Q_EMIT dataChanged(index(0), index(0));
900+ }
901+ else if (m_confirmationPlaceholder)
902+ {
903+ row = 1;
904+ }
905+ else
906+ {
907+ row = 0;
908+ }
909+
910+ if (row >= 0)
911+ {
912+ beginInsertRows(QModelIndex(), row, row);
913+ m_list.insert(row, notification);
914+ endInsertRows();
915+ }
916+}
917+
918+void
919+MockModel::onDismissed()
920+{
921+ MockNotification* notification = qobject_cast<MockNotification*>(sender());
922+ int row = m_list.indexOf(notification);
923+ if (row >= 0)
924+ {
925+ if (m_confirmationPlaceholder
926+ && notification->m_data.contains("type")
927+ && notification->m_data["type"] == (int)unity::shell::notifications::Type::TypeEnum::Confirmation)
928+ {
929+ notification->m_data["type"] = (int)unity::shell::notifications::Type::TypeEnum::Placeholder;
930+ Q_EMIT dataChanged(index(0), index(0));
931+ }
932+ else
933+ {
934+ beginRemoveRows(QModelIndex(), row, row);
935+ m_list.removeAt(row);
936+ endRemoveRows();
937+ }
938+ }
939+}
940
941=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.h'
942--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.h 1970-01-01 00:00:00 +0000
943+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockModel.h 2013-05-16 10:27:27 +0000
944@@ -0,0 +1,81 @@
945+/*
946+ * Copyright 2013 Canonical Ltd.
947+ *
948+ * This program is free software; you can redistribute it and/or modify
949+ * it under the terms of the GNU General Public License as published by
950+ * the Free Software Foundation; version 3.
951+ *
952+ * This program is distributed in the hope that it will be useful,
953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
955+ * GNU Lesser General Public License for more details.
956+ *
957+ * You should have received a copy of the GNU Lesser General Public License
958+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
959+ *
960+ * Authors:
961+ * Michał Sawicz <michal.sawicz@canonical.com>
962+ */
963+
964+
965+#ifndef MOCKMODEL_H
966+#define MOCKMODEL_H
967+
968+#include <unity/config.h>
969+
970+#include <unity/shell/notifications/ModelInterface.h>
971+
972+#include <QtCore/QList>
973+#include <QtCore/QVariantMap>
974+
975+using namespace unity::shell::notifications;
976+
977+class MockNotification;
978+
979+class UNITY_API MockModel : public ModelInterface
980+{
981+ Q_OBJECT
982+
983+ Q_ENUMS(RoleEnum)
984+
985+public:
986+ MockModel(QObject* parent = 0);
987+
988+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
989+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
990+ QHash<int, QByteArray> roleNames() const;
991+
992+ bool confirmationPlaceholder() const
993+ {
994+ return m_confirmationPlaceholder;
995+ }
996+
997+ void setConfirmationPlaceholder(bool confirmationPlaceholder);
998+
999+ void add(MockNotification* notification);
1000+
1001+ enum RoleEnum
1002+ {
1003+ Summary = Qt::DisplayRole,
1004+ Notification = Qt::UserRole,
1005+ Id,
1006+ Type,
1007+ Urgency,
1008+ Body,
1009+ Value,
1010+ Icon,
1011+ SecondaryIcon,
1012+ Hints,
1013+ Actions
1014+ };
1015+
1016+private:
1017+ bool m_confirmationPlaceholder;
1018+ QHash<int, QByteArray> m_roles;
1019+ QList<MockNotification*> m_list;
1020+
1021+private Q_SLOTS:
1022+ void onDismissed();
1023+};
1024+
1025+#endif // MOCKMODEL_H
1026
1027=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.cpp'
1028--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.cpp 1970-01-01 00:00:00 +0000
1029+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.cpp 2013-05-16 10:27:27 +0000
1030@@ -0,0 +1,29 @@
1031+/*
1032+ * Copyright 2013 Canonical Ltd.
1033+ *
1034+ * This program is free software; you can redistribute it and/or modify
1035+ * it under the terms of the GNU General Public License as published by
1036+ * the Free Software Foundation; version 3.
1037+ *
1038+ * This program is distributed in the hope that it will be useful,
1039+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1040+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1041+ * GNU Lesser General Public License for more details.
1042+ *
1043+ * You should have received a copy of the GNU Lesser General Public License
1044+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1045+ *
1046+ * Authors:
1047+ * Michał Sawicz <michal.sawicz@canonical.com>
1048+ */
1049+
1050+
1051+#include <Mocks/MockNotification.h>
1052+#include <Mocks/MockActionModel.h>
1053+
1054+MockNotification::MockNotification(QObject* parent)
1055+ : NotificationInterface(parent)
1056+ , m_actions(new MockActionModel(this))
1057+{
1058+ connect(this, SIGNAL(dismissed()), SIGNAL(completed()));
1059+}
1060
1061=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.h'
1062--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.h 1970-01-01 00:00:00 +0000
1063+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotification.h 2013-05-16 10:27:27 +0000
1064@@ -0,0 +1,56 @@
1065+/*
1066+ * Copyright 2013 Canonical Ltd.
1067+ *
1068+ * This program is free software; you can redistribute it and/or modify
1069+ * it under the terms of the GNU General Public License as published by
1070+ * the Free Software Foundation; version 3.
1071+ *
1072+ * This program is distributed in the hope that it will be useful,
1073+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1074+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1075+ * GNU Lesser General Public License for more details.
1076+ *
1077+ * You should have received a copy of the GNU Lesser General Public License
1078+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1079+ *
1080+ * Authors:
1081+ * Michał Sawicz <michal.sawicz@canonical.com>
1082+ */
1083+
1084+
1085+#ifndef MOCKNOTIFICATION_H
1086+#define MOCKNOTIFICATION_H
1087+
1088+#include <unity/config.h>
1089+
1090+#include <unity/shell/notifications/NotificationInterface.h>
1091+
1092+#include <QtCore/QVariantMap>
1093+
1094+using namespace unity::shell::notifications;
1095+
1096+class MockSource;
1097+class MockModel;
1098+class MockActionModel;
1099+
1100+class UNITY_API MockNotification : public NotificationInterface
1101+{
1102+ friend class MockSource;
1103+ friend class MockModel;
1104+ friend class MockActionModel;
1105+
1106+ Q_OBJECT
1107+public:
1108+ explicit MockNotification(QObject *parent = 0);
1109+
1110+Q_SIGNALS:
1111+ void completed();
1112+
1113+private:
1114+ QVariantMap m_data;
1115+ MockActionModel* m_actions;
1116+};
1117+
1118+Q_DECLARE_METATYPE(MockNotification*)
1119+
1120+#endif // MOCKNOTIFICATION_H
1121
1122=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.cpp'
1123--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.cpp 1970-01-01 00:00:00 +0000
1124+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.cpp 2013-05-16 10:27:27 +0000
1125@@ -0,0 +1,36 @@
1126+/*
1127+ * Copyright 2013 Canonical Ltd.
1128+ *
1129+ * This program is free software; you can redistribute it and/or modify
1130+ * it under the terms of the GNU General Public License as published by
1131+ * the Free Software Foundation; version 3.
1132+ *
1133+ * This program is distributed in the hope that it will be useful,
1134+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1135+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1136+ * GNU Lesser General Public License for more details.
1137+ *
1138+ * You should have received a copy of the GNU Lesser General Public License
1139+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1140+ *
1141+ * Authors:
1142+ * Michał Sawicz <michal.sawicz@canonical.com>
1143+ */
1144+
1145+
1146+#include <Mocks/MockNotificationsPlugin.h>
1147+#include <Mocks/MockSource.h>
1148+
1149+#include <unity/shell/notifications/SourceInterface.h>
1150+
1151+#include <qqml.h>
1152+
1153+using namespace unity::shell::notifications;
1154+
1155+void MockNotificationsPlugin::registerTypes(const char *uri)
1156+{
1157+ // @uri Unity.Notifications.Mocks
1158+ qmlRegisterUncreatableType<SourceInterface>(uri, 0, 1, "SourceInterface", "SourceInterface is an abstract base class");
1159+
1160+ qmlRegisterType<MockSource>(uri, 0, 1, "MockSource");
1161+}
1162
1163=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.h'
1164--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.h 1970-01-01 00:00:00 +0000
1165+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockNotificationsPlugin.h 2013-05-16 10:27:27 +0000
1166@@ -0,0 +1,35 @@
1167+/*
1168+ * Copyright 2013 Canonical Ltd.
1169+ *
1170+ * This program is free software; you can redistribute it and/or modify
1171+ * it under the terms of the GNU General Public License as published by
1172+ * the Free Software Foundation; version 3.
1173+ *
1174+ * This program is distributed in the hope that it will be useful,
1175+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1176+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1177+ * GNU Lesser General Public License for more details.
1178+ *
1179+ * You should have received a copy of the GNU Lesser General Public License
1180+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1181+ *
1182+ * Authors:
1183+ * Michał Sawicz <michal.sawicz@canonical.com>
1184+ */
1185+
1186+
1187+#ifndef MOCKNOTIFICATIONSPLUGIN_H
1188+#define MOCKNOTIFICATIONSPLUGIN_H
1189+
1190+#include <QQmlExtensionPlugin>
1191+
1192+class MockNotificationsPlugin : public QQmlExtensionPlugin
1193+{
1194+ Q_OBJECT
1195+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1196+
1197+public:
1198+ void registerTypes(const char *uri);
1199+};
1200+
1201+#endif // MOCKNOTIFICATIONSPLUGIN_H
1202
1203=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.cpp'
1204--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.cpp 1970-01-01 00:00:00 +0000
1205+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.cpp 2013-05-16 10:27:27 +0000
1206@@ -0,0 +1,70 @@
1207+/*
1208+ * Copyright 2013 Canonical Ltd.
1209+ *
1210+ * This program is free software; you can redistribute it and/or modify
1211+ * it under the terms of the GNU General Public License as published by
1212+ * the Free Software Foundation; version 3.
1213+ *
1214+ * This program is distributed in the hope that it will be useful,
1215+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1216+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1217+ * GNU Lesser General Public License for more details.
1218+ *
1219+ * You should have received a copy of the GNU Lesser General Public License
1220+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1221+ *
1222+ * Authors:
1223+ * Michał Sawicz <michal.sawicz@canonical.com>
1224+ */
1225+
1226+
1227+#include <Mocks/MockSource.h>
1228+#include <Mocks/MockModel.h>
1229+#include <Mocks/MockNotification.h>
1230+
1231+#include <unity/shell/notifications/NotificationInterface.h>
1232+
1233+using namespace unity::shell::notifications;
1234+
1235+MockSource::MockSource(QObject *parent)
1236+ : SourceInterface(parent)
1237+ , m_model(0)
1238+{
1239+}
1240+
1241+ModelInterface*
1242+MockSource::model() const
1243+{
1244+ return m_model;
1245+}
1246+
1247+void
1248+MockSource::setModel(ModelInterface* model)
1249+{
1250+ MockModel* mockModel = qobject_cast<MockModel*>(model);
1251+ if (m_model != mockModel)
1252+ {
1253+ m_model = mockModel;
1254+ Q_EMIT modelChanged(m_model);
1255+ }
1256+}
1257+
1258+void
1259+MockSource::send(QVariantMap data)
1260+{
1261+ MockNotification* notification = new MockNotification(this);
1262+ notification->m_data = data;
1263+
1264+ connect(notification, SIGNAL(completed()), SLOT(onCompleted()));
1265+
1266+ if(m_model)
1267+ {
1268+ m_model->add(notification);
1269+ }
1270+}
1271+
1272+void
1273+MockSource::onCompleted()
1274+{
1275+ sender()->deleteLater();
1276+}
1277
1278=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.h'
1279--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.h 1970-01-01 00:00:00 +0000
1280+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/MockSource.h 2013-05-16 10:27:27 +0000
1281@@ -0,0 +1,66 @@
1282+/*
1283+ * Copyright 2013 Canonical Ltd.
1284+ *
1285+ * This program is free software; you can redistribute it and/or modify
1286+ * it under the terms of the GNU General Public License as published by
1287+ * the Free Software Foundation; version 3.
1288+ *
1289+ * This program is distributed in the hope that it will be useful,
1290+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1291+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1292+ * GNU Lesser General Public License for more details.
1293+ *
1294+ * You should have received a copy of the GNU Lesser General Public License
1295+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1296+ *
1297+ * Authors:
1298+ * Michał Sawicz <michal.sawicz@canonical.com>
1299+ */
1300+
1301+
1302+#ifndef MOCKSOURCE_H
1303+#define MOCKSOURCE_H
1304+
1305+#include <unity/config.h>
1306+
1307+#include <unity/shell/notifications/SourceInterface.h>
1308+
1309+#include <QtCore/QVariantMap>
1310+
1311+namespace unity
1312+{
1313+namespace shell
1314+{
1315+namespace notifications
1316+{
1317+
1318+class ModelInterface;
1319+
1320+} // namespace notifications
1321+} // namespace shell
1322+} // namespace unity
1323+
1324+class MockModel;
1325+
1326+using namespace unity::shell::notifications;
1327+
1328+class UNITY_API MockSource : public SourceInterface
1329+{
1330+ Q_OBJECT
1331+public:
1332+ explicit MockSource(QObject *parent = 0);
1333+
1334+ ModelInterface* model() const;
1335+
1336+ void setModel(ModelInterface* model);
1337+
1338+ Q_INVOKABLE void send(QVariantMap data);
1339+
1340+private Q_SLOTS:
1341+ void onCompleted();
1342+
1343+private:
1344+ MockModel* m_model;
1345+};
1346+
1347+#endif // MOCKSOURCE_H
1348
1349=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/Mocks/qmldir'
1350--- test/qmltest/mocks/plugins/Unity/Notifications/Mocks/qmldir 1970-01-01 00:00:00 +0000
1351+++ test/qmltest/mocks/plugins/Unity/Notifications/Mocks/qmldir 2013-05-16 10:27:27 +0000
1352@@ -0,0 +1,2 @@
1353+module Unity.Notifications.Mocks
1354+plugin MockNotificationsPlugin
1355
1356=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.cpp'
1357--- test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.cpp 1970-01-01 00:00:00 +0000
1358+++ test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.cpp 2013-05-16 10:27:27 +0000
1359@@ -0,0 +1,58 @@
1360+/*
1361+ * Copyright 2013 Canonical Ltd.
1362+ *
1363+ * This program is free software; you can redistribute it and/or modify
1364+ * it under the terms of the GNU General Public License as published by
1365+ * the Free Software Foundation; version 3.
1366+ *
1367+ * This program is distributed in the hope that it will be useful,
1368+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1369+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1370+ * GNU Lesser General Public License for more details.
1371+ *
1372+ * You should have received a copy of the GNU Lesser General Public License
1373+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1374+ *
1375+ * Authors:
1376+ * Michał Sawicz <michal.sawicz@canonical.com>
1377+ */
1378+
1379+
1380+#include <TestNotificationsPlugin.h>
1381+#include <Mocks/MockModel.h>
1382+#include <Mocks/MockSource.h>
1383+#include <Mocks/MockNotification.h>
1384+
1385+#include <unity/shell/notifications/Enums.h>
1386+#include <unity/shell/notifications/ModelInterface.h>
1387+#include <unity/shell/notifications/SourceInterface.h>
1388+#include <unity/shell/notifications/NotificationInterface.h>
1389+
1390+#include <qqml.h>
1391+
1392+using namespace unity::shell::notifications;
1393+
1394+static QObject* modelProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
1395+{
1396+ return new MockModel();
1397+}
1398+
1399+static QObject* sourceProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
1400+{
1401+ return new MockSource();
1402+}
1403+
1404+void TestNotificationsPlugin::registerTypes(const char *uri)
1405+{
1406+ // @uri Unity.Notifications
1407+ qmlRegisterUncreatableType<Urgency>(uri, 0, 1, "Urgency", "Urgency is just a enum wrapper");
1408+ qmlRegisterUncreatableType<Type>(uri, 0, 1, "Type", "Type is just a enum wrapper");
1409+ qmlRegisterUncreatableType<Hint>(uri, 0, 1, "Hint", "Hint is just a enum wrapper");
1410+ qmlRegisterUncreatableType<NotificationInterface>(uri, 0, 1, "NotificationInterface", "NotificationInterface is an abstract base class");
1411+ qmlRegisterUncreatableType<ModelInterface>(uri, 0, 1, "ModelInterface", "ModelInterface is an abstract base class");
1412+ qmlRegisterUncreatableType<SourceInterface>(uri, 0, 1, "SourceInterface", "SourceInterface is an abstract base class");
1413+
1414+ qmlRegisterUncreatableType<MockNotification>(uri, 0, 1, "Notification", "Notification objects can only be created by the plugin");
1415+ qmlRegisterSingletonType<MockSource>(uri, 0, 1, "Source", sourceProvider);
1416+ qmlRegisterSingletonType<MockModel>(uri, 0, 1, "Model", modelProvider);
1417+}
1418
1419=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.h'
1420--- test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.h 1970-01-01 00:00:00 +0000
1421+++ test/qmltest/mocks/plugins/Unity/Notifications/TestNotificationsPlugin.h 2013-05-16 10:27:27 +0000
1422@@ -0,0 +1,35 @@
1423+/*
1424+ * Copyright 2013 Canonical Ltd.
1425+ *
1426+ * This program is free software; you can redistribute it and/or modify
1427+ * it under the terms of the GNU General Public License as published by
1428+ * the Free Software Foundation; version 3.
1429+ *
1430+ * This program is distributed in the hope that it will be useful,
1431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1433+ * GNU Lesser General Public License for more details.
1434+ *
1435+ * You should have received a copy of the GNU Lesser General Public License
1436+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1437+ *
1438+ * Authors:
1439+ * Michał Sawicz <michal.sawicz@canonical.com>
1440+ */
1441+
1442+
1443+#ifndef TESTNOTIFICATIONS_PLUGIN_H
1444+#define TESTNOTIFICATIONS_PLUGIN_H
1445+
1446+#include <QQmlExtensionPlugin>
1447+
1448+class TestNotificationsPlugin : public QQmlExtensionPlugin
1449+{
1450+ Q_OBJECT
1451+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1452+
1453+public:
1454+ void registerTypes(const char *uri);
1455+};
1456+
1457+#endif // TESTNOTIFICATIONS_PLUGIN_H
1458
1459=== added file 'test/qmltest/mocks/plugins/Unity/Notifications/qmldir'
1460--- test/qmltest/mocks/plugins/Unity/Notifications/qmldir 1970-01-01 00:00:00 +0000
1461+++ test/qmltest/mocks/plugins/Unity/Notifications/qmldir 2013-05-16 10:27:27 +0000
1462@@ -0,0 +1,2 @@
1463+module Unity.Notifications
1464+plugin TestNotificationsPlugin
1465
1466=== added directory 'test/qmltest/unity'
1467=== added file 'test/qmltest/unity/CMakeLists.txt'
1468--- test/qmltest/unity/CMakeLists.txt 1970-01-01 00:00:00 +0000
1469+++ test/qmltest/unity/CMakeLists.txt 2013-05-16 10:27:27 +0000
1470@@ -0,0 +1,1 @@
1471+add_subdirectory(shell)
1472
1473=== added directory 'test/qmltest/unity/shell'
1474=== added file 'test/qmltest/unity/shell/CMakeLists.txt'
1475--- test/qmltest/unity/shell/CMakeLists.txt 1970-01-01 00:00:00 +0000
1476+++ test/qmltest/unity/shell/CMakeLists.txt 2013-05-16 10:27:27 +0000
1477@@ -0,0 +1,9 @@
1478+include(QmlTest)
1479+
1480+set(qmltest_DEFAULT_IMPORT_PATHS
1481+ ${CMAKE_BINARY_DIR}/test/qmltest/modules
1482+ ${CMAKE_BINARY_DIR}/test/qmltest/mocks/plugins
1483+)
1484+set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
1485+
1486+add_qml_test(notifications Notifications)
1487
1488=== added directory 'test/qmltest/unity/shell/notifications'
1489=== added file 'test/qmltest/unity/shell/notifications/tst_Notifications.qml'
1490--- test/qmltest/unity/shell/notifications/tst_Notifications.qml 1970-01-01 00:00:00 +0000
1491+++ test/qmltest/unity/shell/notifications/tst_Notifications.qml 2013-05-16 10:27:27 +0000
1492@@ -0,0 +1,266 @@
1493+/*
1494+ * Copyright 2013 Canonical Ltd.
1495+ *
1496+ * This program is free software; you can redistribute it and/or modify
1497+ * it under the terms of the GNU General Public License as published by
1498+ * the Free Software Foundation; version 3.
1499+ *
1500+ * This program is distributed in the hope that it will be useful,
1501+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1502+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1503+ * GNU General Public License for more details.
1504+ *
1505+ * You should have received a copy of the GNU General Public License
1506+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1507+ */
1508+
1509+import QtQuick 2.0
1510+import QtTest 1.0
1511+import TestUtil 0.1
1512+import Unity.Notifications 0.1
1513+import Unity.Notifications.Mocks 0.1 as Mocks
1514+
1515+Item {
1516+
1517+ Mocks.MockSource {
1518+ id: mockSource
1519+ }
1520+
1521+ Verifier {
1522+ id: typeTestCase
1523+
1524+ property var model: Model
1525+ property var source: Source
1526+
1527+ function cleanup() {
1528+ clear();
1529+ Source.model = null;
1530+ }
1531+
1532+ function test_types_data() {
1533+ return [
1534+ { name: "Urgency", tag: "Urgency.Invalid", enum: "Invalid" },
1535+ { name: "Urgency", tag: "Urgency.Low", enum: "Low" },
1536+ { name: "Urgency", tag: "Urgency.Normal", enum: "Normal" },
1537+ { name: "Urgency", tag: "Urgency.Critical", enum: "Critical" },
1538+ { name: "Type", tag: "Type.Invalid", enum: "Invalid" },
1539+ { name: "Type", tag: "Type.Confirmation", enum: "Confirmation" },
1540+ { name: "Type", tag: "Type.Ephemeral", enum: "Ephemeral" },
1541+ { name: "Type", tag: "Type.Interactive", enum: "Ephemeral" },
1542+ { name: "Type", tag: "Type.SnapDecision", enum: "SnapDecision" },
1543+ { name: "Type", tag: "Type.Placeholder", enum: "Placeholder" },
1544+ { name: "Hint", tag: "Hint.Invalid", enum: "Invalid" },
1545+ { name: "Hint", tag: "Hint.ButtonTint", enum: "ButtonTint" },
1546+ { name: "Hint", tag: "Hint.IconOnly", enum: "IconOnly" },
1547+ { name: "Notification", tag: "Notification" },
1548+ ];
1549+ }
1550+
1551+ function test_types(data) {
1552+ try {
1553+ object = eval(data.name);
1554+ } catch(err) {
1555+ object = undefined;
1556+ }
1557+ name = data.name;
1558+
1559+ verifyData(data);
1560+ }
1561+
1562+ function test_model_data() {
1563+ return [
1564+ { tag: "Model[object]", type: "object" },
1565+ { tag: "Model[ModelInterface]", type: "unity::shell::notifications::ModelInterface" },
1566+ { tag: "Model.confirmationPlaceholder", writable: "confirmationPlaceholder",
1567+ type: "boolean", value: !Model.confirmationPlaceholder }
1568+ ];
1569+ }
1570+
1571+ function test_model(data) {
1572+ object = model;
1573+ name = "Model"
1574+
1575+ verifyData(data);
1576+ }
1577+
1578+ function test_source_data() {
1579+ return [
1580+ { tag: "Source[object]", type: "object" },
1581+ { tag: "Source[SourceInterface]", type: "unity::shell::notifications::SourceInterface" },
1582+ { tag: "Source.model", writable: "model", type: "object", value: model },
1583+ ];
1584+ }
1585+
1586+ function test_source(data) {
1587+ object = source;
1588+ name = "Source"
1589+
1590+ verifyData(data);
1591+ }
1592+ }
1593+
1594+ Verifier {
1595+ when: typeTestCase.completed
1596+ optional: true
1597+
1598+ Repeater {
1599+ id: repeater
1600+ delegate: Item {
1601+ id: item
1602+ property var roles: model
1603+ property Repeater actionRepeater: actions
1604+
1605+ Repeater {
1606+ id: actions
1607+ model: parent.roles.actions
1608+ delegate: Item {
1609+ property var roles: model
1610+ }
1611+ }
1612+ }
1613+ }
1614+
1615+ SignalSpy {
1616+ id: dataSpy
1617+ signalName: "dataChanged"
1618+ }
1619+
1620+ function initTestCase() {
1621+ repeater.model = Model;
1622+ dataSpy.target = Model;
1623+ mockSource.model = Model;
1624+ }
1625+
1626+ function init() {
1627+ tryCompare(repeater, "count", 0);
1628+ }
1629+
1630+ function cleanup() {
1631+ Model.confirmationPlaceholder = false;
1632+ // dismiss all Notifications
1633+ for (var i = 0; i < repeater.count; i++) {
1634+ repeater.itemAt(i).roles.notification.dismissed()
1635+ }
1636+ dataSpy.clear()
1637+ tryCompare(repeater, "count", 0);
1638+ }
1639+
1640+ /* make sure all the required roles are exposed on Model */
1641+ function test_model_roles_data() {
1642+ return [
1643+ { tag: "Model.roles[notification]", role: "notification", type: "object" },
1644+ { tag: "Model.roles[type]", role: "type", type: "number" },
1645+ { tag: "Model.roles[urgency]", role: "urgency", type: "number" },
1646+ { tag: "Model.roles[id]", role: "id", type: "number" },
1647+ { tag: "Model.roles[summary]", role: "summary", type: "string" },
1648+ { tag: "Model.roles[body]", role: "body", type: "string" },
1649+ { tag: "Model.roles[value]", role: "value", type: "number" },
1650+ { tag: "Model.roles[icon]", role: "icon", type: "object" },
1651+ { tag: "Model.roles[secondaryIcon]", role: "secondaryIcon", type: "object" },
1652+ { tag: "Model.roles[actions]", role: "actions", type: "object" },
1653+ { tag: "Model.roles[hints]", role: "hints", type: "number" },
1654+ ];
1655+ }
1656+
1657+ function test_model_roles(data) {
1658+ mockSource.send({});
1659+ tryCompare(repeater, "count", 1);
1660+
1661+ try {
1662+ object = repeater.itemAt(0).roles;
1663+ } catch(err) {
1664+ object = undefined;
1665+ }
1666+ name = "Model";
1667+
1668+ verifyData(data);
1669+ }
1670+
1671+ /* make sure all the members of Notification objects are available */
1672+ function test_notification_members_data() {
1673+ return [
1674+ { tag: "Notification.dismissed", signal: "dismissed" },
1675+ { tag: "Notification.hovered", signal: "hovered" },
1676+ { tag: "Notification.displayed", signal: "displayed" },
1677+ { tag: "Notification.actionInvoked", signal: "actionInvoked" }
1678+ ];
1679+ }
1680+
1681+ function test_notification_members(data) {
1682+ mockSource.send({});
1683+ tryCompare(repeater, "count", 1);
1684+
1685+ try {
1686+ object = repeater.itemAt(0).roles.notification;
1687+ } catch(err) {
1688+ object = undefined;
1689+ }
1690+ name = "Notification";
1691+
1692+ verifyData(data);
1693+ }
1694+
1695+ /* make sure all the required roles for actions are exposed */
1696+ function test_action_members_data() {
1697+ return [
1698+ { tag: "actions.roles[label]", role: "label", type: "string" },
1699+ { tag: "actions.roles[id]", role: "id", type: "string" }
1700+ ];
1701+ }
1702+
1703+ function test_action_members(data) {
1704+ mockSource.send({
1705+ "actions": [
1706+ {"label": "test", "id": "test"}
1707+ ]
1708+ });
1709+ tryCompare(repeater, "count", 1);
1710+ tryCompare(repeater.itemAt(0).actionRepeater, "count", 1);
1711+
1712+ try {
1713+ object = repeater.itemAt(0).actionRepeater.itemAt(0).roles;
1714+ } catch(err) {
1715+ object = undefined;
1716+ }
1717+ name = "actions";
1718+
1719+ verifyData(data);
1720+ }
1721+
1722+ /* make sure the model is empty by default */
1723+ function test_empty() {
1724+ tryCompare(repeater, "count", 0);
1725+ }
1726+
1727+ /* make sure there is a placeholder item used as the first one when
1728+ confirmationPlaceholder is true and that any additional notification is added
1729+ after it */
1730+ function test_placeholder() {
1731+ Model.confirmationPlaceholder = true;
1732+ tryCompare(repeater, "count", 1);
1733+
1734+ compare(repeater.itemAt(0).roles.type, Type.Placeholder, "the notification should be of Placeholder type");
1735+ mockSource.send({
1736+ type: Type.Ephemeral
1737+ })
1738+ tryCompare(repeater, "count", 2);
1739+
1740+ compare(repeater.itemAt(0).roles.type, Type.Placeholder, "the first notification should be of Placeholder type");
1741+ compare(repeater.itemAt(1).roles.type, Type.Ephemeral, "the second notification should be of Ephemeral type");
1742+ }
1743+
1744+ /* make sure the placeholder item is updated with roles incoming in a Confirmation
1745+ notification */
1746+ function test_confirmation() {
1747+ Model.confirmationPlaceholder = true;
1748+ tryCompare(repeater, "count", 1);
1749+ mockSource.send({
1750+ "type": Type.Confirmation
1751+ });
1752+ tryCompare(repeater, "count", 1);
1753+ dataSpy.wait();
1754+ compare(repeater.count, 1, "there should be only one notification");
1755+ compare(repeater.itemAt(0).roles.type, Type.Confirmation, "the first notification should be of Confirmation type");
1756+ }
1757+ }
1758+}

Subscribers

People subscribed via source and target branches

to all changes: