Merge lp:~dobey/ubuntu-printing-app/add-notifier-daemon into lp:ubuntu-printing-app
- add-notifier-daemon
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrew Hayzen |
Approved revision: | 50 |
Merged at revision: | 32 |
Proposed branch: | lp:~dobey/ubuntu-printing-app/add-notifier-daemon |
Merge into: | lp:ubuntu-printing-app |
Prerequisite: | lp:~ahayzen/ubuntu-printing-app/add-ubuntu-printing-app |
Diff against target: |
2180 lines (+1994/-0) 32 files modified
.bzrignore (+5/-0) CMakeLists.txt (+4/-0) debian/control (+11/-0) notifier/CMakeLists.txt (+49/-0) notifier/TESTING (+37/-0) notifier/data/CMakeLists.txt (+48/-0) notifier/data/printing-notifier.conf.in (+23/-0) notifier/data/printing-notifier.override (+1/-0) notifier/data/printing-notifier.service.in (+8/-0) notifier/src/CMakeLists.txt (+62/-0) notifier/src/actions.cpp (+42/-0) notifier/src/actions.h (+43/-0) notifier/src/client.h (+56/-0) notifier/src/cups-client.cpp (+337/-0) notifier/src/cups-client.h (+65/-0) notifier/src/dbus-names.h (+27/-0) notifier/src/job.h (+50/-0) notifier/src/main.cpp (+61/-0) notifier/src/notification.cpp (+185/-0) notifier/src/notification.h (+61/-0) notifier/src/notify-engine.cpp (+204/-0) notifier/src/notify-engine.h (+57/-0) notifier/src/org.cups.cupsd.Notifier.xml (+147/-0) notifier/src/printer.h (+45/-0) notifier/src/utils.cpp (+37/-0) notifier/src/utils.h (+32/-0) notifier/tests/CMakeLists.txt (+28/-0) notifier/tests/actions-mock.h (+42/-0) notifier/tests/client-mock.h (+54/-0) notifier/tests/mock-notification.h (+52/-0) notifier/tests/test_notify-engine.cpp (+88/-0) notifier/tests/test_utils.cpp (+33/-0) |
To merge this branch: | bzr merge lp:~dobey/ubuntu-printing-app/add-notifier-daemon |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Hayzen (community) | Approve | ||
Review via email: mp+315637@code.launchpad.net |
Commit message
Add notifier daemon.
Description of the change
dobey (dobey) wrote : | # |
I've added a document to the tree to describe how to test it (as testing cups notifications can be a bit weird to do). I would recommend avoiding having the daemon running in unity 7 as it's not meant for it, and meant to replace the printing indicator for unity 8 session only. (The notification service under unity7 creates a GTK+ dialog that has some additional buttons, for the printer error notifications.)
As for the translations, I had set up the po/ dir already in my branch prior to adding it in yours, and I removed what I had to avoid the conflict. At this point, I think it's probably better to fix that in another branch on top of these (perhaps after they land, as I don't want to get into a weird situation where we keep adding conflicts). There's also some improvements that can be taken from my work here, and applied to the rest of the project tree, now that I see you've added more testing there, but I think that cleanup should happen in another branch too at this point.
Andrew Hayzen (ahayzen) wrote : | # |
So I've been testing this a bit further and have been able to generate notifications. One thing that I noticed is if the job title is empty then the notification looks a bit strange, it comes up with the following: "" has printed . I'm going to improve the printing app to ensure that it always has some form of title, but I wonder if the notification should also have a fallback ?
Andrew Hayzen (ahayzen) wrote : | # |
The change fixes the deadlock I was having, and I've now been able to confirm notifications appear when using the printing app as well :-)
Andrew Hayzen (ahayzen) wrote : | # |
This looks good, once the perquisite branch has landed we can land this. I agree that the folder structure of the project can be improved (it came from the SDK template when I only thought the printing-app would be in the code nothing else), we can discuss these improvements after these two branches land.
One thing to note is that the current WIP designs for the printer queue state that on a mobile device when a job is sent to the printer a notification with "Printing on Printer Name" will appear, tapping on that will launch the queue. This is different on desktop, where no notification will be used and just the launcher alert as the queue starts. However these designs are still WIP, so this can be done in a future branch.
dobey (dobey) wrote : | # |
> One thing to note is that the current WIP designs for the printer queue state
> that on a mobile device when a job is sent to the printer a notification with
> "Printing on Printer Name" will appear, tapping on that will launch the queue.
> This is different on desktop, where no notification will be used and just the
> launcher alert as the queue starts. However these designs are still WIP, so
> this can be done in a future branch.
I've seen no indication that we should have these notifications in one form factor but not another. Nor does it make any sense for that to be the case, IMO, and would be a divergent experience, not a convergent one.
Andrew Hayzen (ahayzen) wrote : | # |
@dobey, would you mind doing a pull of trunk to bring in the new changes?
Also when trying to get this to build in a silo I got "No package 'properties-cpp' found", which suggests the package libproperties-
Furthermore when discussing with Bill we have a few changes (these can be done in this branch or a further branch):
1) Currently the text in the notification doesn't wrap, so you only see the first part. Both the design specifications show this (#1.2 in [0] and in [1]). Is this a limitation of the notifications in unity8? or an issue in this notifier code?
2) We don't think there is an API yet for adding an entry for the printer queue into the launcher of unity8 when something is printing without launching an app (what design wants). So for now can you show a notification when something is sent to the printer ("Printing on printerName"), as shown in the design #1.1 in [0]
3) If the user clicks on the notification when something is sent to the printer, this should show the queue dialog. I'm currently building the queue dialog in another branch, not decided on the launcher name yet - will let you know (probably something like ubuntu-
0 - https:/
1 - https:/
dobey (dobey) wrote : | # |
On Fri, 2017-03-17 at 15:56 +0000, Andrew Hayzen wrote:
> Review: Needs Fixing
>
> @dobey, would you mind doing a pull of trunk to bring in the new
> changes?
I'll get it updated.
> Also when trying to get this to build in a silo I got "No package
> 'properties-cpp' found", which suggests the package libproperties-
> cpp-dev should be added to the build-deps?
I'll see what's going on there.
> Furthermore when discussing with Bill we have a few changes (these
> can be done in this branch or a further branch):
> 1) Currently the text in the notification doesn't wrap, so you only
> see the first part. Both the design specifications show this (#1.2 in
> [0] and in [1]). Is this a limitation of the notifications in unity8?
> or an issue in this notifier code?
This would be an issue on the renderer's side. We have no way to know
what the width of the notification will be on the client (notifier
daemon) side, so we can't do anything about it there. It seems there is
no way to specify how this should be handled, from the client side.
> 2) We don't think there is an API yet for adding an entry for the
> printer queue into the launcher of unity8 when something is printing
> without launching an app (what design wants). So for now can you show
> a notification when something is sent to the printer ("Printing on
> printerName"), as shown in the design #1.1 in [0]
We can't really do this from notifier daemon which listens to cups for
status, no. It would really need to be a notification sent by the
printing app I think, but in 99.9999% of cases will be immediately
followed by the '"foo" has printed." notification. So there's no good
reason to pop a '"foo" is printing." notification immediately prior to.
> 3) If the user clicks on the notification when something is sent to
> the printer, this should show the queue dialog. I'm currently
> building the queue dialog in another branch, not decided on the
> launcher name yet - will let you know (probably something like
> ubuntu-
> it?).
There is no way to implement this as "when the user clicks on the
notification." The design is wrong. To do this would require making the
notification interactive instead, and adding a "View print queue"
button to it.
However, looking at the doc, this is only specified for errors, and
it's specified to go to the printer's page in settings. The notifier
already adds a button to open settings on printer errors, which goes to
settings:
in system-settings, then I think this is already implemented.
- 43. By dobey
-
Merge trunk.
- 44. By dobey
-
Need properties-cpp.
- 45. By dobey
-
Use the gdbus module from cmake-extras.
- 46. By dobey
-
Remove extraneous comment and cmake directory inclusion.
- 47. By dobey
-
GDbus package is required.
- 48. By dobey
-
fix typo.
- 49. By dobey
-
Move the comment to avoid confusing translators.
Andrew Hayzen (ahayzen) wrote : | # |
OK, thanks for your responses for 1,2,3. I'm going to discuss with Bill our options for them.
I've found one more missing depends that needs to be added, after adding the following package I've been able to build in pbuilder and in a silo :-)
- libnotify-dev
Once the missing depends is fixed, I think this branch is ready and any further changes can be done in further branches :-)
Andrew Hayzen (ahayzen) wrote : | # |
Thanks, this looks good now.
Preview Diff
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2017-03-20 13:16:02 +0000 |
4 | @@ -0,0 +1,5 @@ |
5 | +CMakeLists.txt.user* |
6 | +/build |
7 | +/po/Makefile.in.in |
8 | +/po/POTFILES.in |
9 | + |
10 | |
11 | === modified file 'CMakeLists.txt' |
12 | --- CMakeLists.txt 2017-03-07 15:01:56 +0000 |
13 | +++ CMakeLists.txt 2017-03-20 13:16:02 +0000 |
14 | @@ -1,6 +1,9 @@ |
15 | project(ubuntu-printing-app) |
16 | cmake_minimum_required(VERSION 2.8.9) |
17 | |
18 | +# Always Be Testing |
19 | +enable_testing() |
20 | + |
21 | # Load translation tools |
22 | find_program(INTLTOOL_MERGE intltool-merge) |
23 | if(NOT INTLTOOL_MERGE) |
24 | @@ -51,6 +54,7 @@ |
25 | |
26 | # Add subdirs |
27 | add_subdirectory(backend) |
28 | +add_subdirectory(notifier) |
29 | add_subdirectory(runner) |
30 | add_subdirectory(ubuntu-printing-app) |
31 | |
32 | |
33 | === modified file 'debian/control' |
34 | --- debian/control 2017-03-07 15:16:02 +0000 |
35 | +++ debian/control 2017-03-20 13:16:02 +0000 |
36 | @@ -3,10 +3,21 @@ |
37 | Priority: optional |
38 | Maintainer: Andrew Hayzen <andrew.hayzen@canonical.com> |
39 | Build-Depends: cmake (>= 2.8.9), |
40 | + cmake-extras (>= 1.3), |
41 | debhelper (>=9), |
42 | dh-apparmor, |
43 | dh-translations, |
44 | + gcovr, |
45 | + googletest | google-mock, |
46 | + intltool, |
47 | + lcov, |
48 | + libboost-dev, |
49 | + libcups2-dev, |
50 | + libglib2.0-dev (>= 2.35.4), |
51 | + libnotify-dev, |
52 | libpoppler-qt5-dev, |
53 | + libproperties-cpp-dev, |
54 | + liburl-dispatcher1-dev, |
55 | qmlscene, |
56 | qml-module-qtquick2, |
57 | qml-module-qtquick-layouts, |
58 | |
59 | === added directory 'notifier' |
60 | === added file 'notifier/CMakeLists.txt' |
61 | --- notifier/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
62 | +++ notifier/CMakeLists.txt 2017-03-20 13:16:02 +0000 |
63 | @@ -0,0 +1,49 @@ |
64 | +### Install path variables |
65 | +include (GNUInstallDirs) |
66 | +if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian |
67 | + set (CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBDIR}") |
68 | + set (CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_FULL_LIBDIR}") |
69 | +endif () |
70 | +set (CMAKE_INSTALL_PKGLIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}") |
71 | +set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}") |
72 | + |
73 | +### Always Be Testing |
74 | +enable_testing() |
75 | + |
76 | +### Set variables for our binary build targets |
77 | +set(SERVICE_LIB_NAME "printing-notifier") |
78 | +set(SERVICE_EXEC_NAME "printing-notifier-service") |
79 | + |
80 | +### Some default compile flags |
81 | +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC") |
82 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -g -Wextra -Wall -Werror -Werror=conversion-null -Wno-ignored-qualifiers -fPIC") |
83 | + |
84 | +### Find deps |
85 | +find_package(PkgConfig REQUIRED) |
86 | +find_package(Threads) |
87 | + |
88 | +pkg_check_modules(SERVICE_DEPS REQUIRED |
89 | + gio-unix-2.0>=2.36 |
90 | + glib-2.0>=2.36 |
91 | + libnotify>=0.7.6 |
92 | + properties-cpp |
93 | + url-dispatcher-1 |
94 | +) |
95 | + |
96 | +### Find libcups |
97 | +find_program(CUPS_CONFIG cups-config) |
98 | +execute_process(COMMAND ${CUPS_CONFIG} --cflags OUTPUT_VARIABLE CUPS_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) |
99 | +execute_process(COMMAND ${CUPS_CONFIG} --libs OUTPUT_VARIABLE CUPS_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) |
100 | + |
101 | +### Add sub-directories |
102 | +add_subdirectory(data) |
103 | +add_subdirectory(src) |
104 | +add_subdirectory(tests) |
105 | + |
106 | +### Enable coverage reporting |
107 | +find_package(CoverageReport) |
108 | +ENABLE_COVERAGE_REPORT( |
109 | + TARGETS ${SERVICE_LIB_NAME} ${SERVICE_EXEC_NAME} |
110 | + TESTS test-${SERVICE_LIB_NAME} |
111 | + FILTER /usr/include ${CMAKE_BINARY_DIR}/* |
112 | +) |
113 | |
114 | === added file 'notifier/TESTING' |
115 | --- notifier/TESTING 1970-01-01 00:00:00 +0000 |
116 | +++ notifier/TESTING 2017-03-20 13:16:02 +0000 |
117 | @@ -0,0 +1,37 @@ |
118 | +This subtree contains the daemon for notifying of successful print jobs, |
119 | +and of issues with the printer when jobs are printed, under Unity 8. |
120 | +This document describes how to test some notifications. |
121 | + |
122 | + |
123 | +Testing |
124 | + |
125 | +0) Make sure the notifier daemon is running: |
126 | + |
127 | + $: ./build/notifier/src/printing-notifier-service |
128 | + |
129 | +1) Add a null printer, if one is not already configured, and enable it: |
130 | + |
131 | + $: lpadmin -p nulldevice -E -v file:///dev/null |
132 | + $: cupsenable nulldevice |
133 | + |
134 | +2) Print a test page: |
135 | + |
136 | + $: lpr -P nulldevice -J "Test Page" /usr/share/cups/data/default-testpage.pdf |
137 | + |
138 | + The document should "print" immediately, and you should get a notification |
139 | + that reads '"Test Page" has printed." |
140 | + |
141 | +3) Pause the printer, print another test page, and emit the PrinterStateChanged |
142 | + signal over dbus: |
143 | + |
144 | + $: cupsdisable nulldevice |
145 | + $: lpr -P nulldevice -J "Test Page" /usr/share/cups/data/default-testpage.pdf |
146 | + $: gdbus emit -y -o /org/cups/cupsd/Notifier \ |
147 | + -s org.cups.cupsd.Notifier.PrinterStateChanged \ |
148 | + "Some text" "cups://nulldevice" "nulldevice" 'uint32 0' "toner-low" true |
149 | + |
150 | + You should see a notification for the toner being low, with one job |
151 | + queued on the printer. Clicking the OK button should close the notification |
152 | + and perform no further actions. Clicking the "Settings…" button should |
153 | + cause system-settings to open to the settings page for that particular |
154 | + printer. |
155 | |
156 | === added directory 'notifier/data' |
157 | === added file 'notifier/data/CMakeLists.txt' |
158 | --- notifier/data/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
159 | +++ notifier/data/CMakeLists.txt 2017-03-20 13:16:02 +0000 |
160 | @@ -0,0 +1,48 @@ |
161 | +## |
162 | +## Systemd Unit File |
163 | +## |
164 | + |
165 | +# where to install |
166 | +set (SYSTEMD_USER_DIR "${CMAKE_INSTALL_LIBDIR}/systemd/user") |
167 | +message (STATUS "${SYSTEMD_USER_DIR} is the systemd user unit file install dir") |
168 | + |
169 | +set (SYSTEMD_USER_NAME "${SERVICE_LIB_NAME}.service") |
170 | +set (SYSTEMD_USER_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SYSTEMD_USER_NAME}") |
171 | +set (SYSTEMD_USER_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${SYSTEMD_USER_NAME}.in") |
172 | + |
173 | +# build it |
174 | +set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}") |
175 | +configure_file ("${SYSTEMD_USER_FILE_IN}" "${SYSTEMD_USER_FILE}") |
176 | + |
177 | +# install it |
178 | +install (FILES "${SYSTEMD_USER_FILE}" |
179 | + DESTINATION "${SYSTEMD_USER_DIR}") |
180 | + |
181 | +## |
182 | +## Upstart systemd override Job File |
183 | +## |
184 | + |
185 | +set (UPSTART_SYSTEMD_OVERRIDE_DIR "${CMAKE_INSTALL_FULL_DATADIR}/upstart/systemd-session/upstart") |
186 | +message (STATUS "${UPSTART_SYSTEMD_OVERRIDE_DIR} is the Upstart override Job File for systemd dir") |
187 | + |
188 | +install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/${SERVICE_LIB_NAME}.override" |
189 | + DESTINATION "${UPSTART_SYSTEMD_OVERRIDE_DIR}") |
190 | + |
191 | +## |
192 | +## Upstart Job File |
193 | +## |
194 | + |
195 | +# where to install |
196 | +set (UPSTART_JOB_DIR "${CMAKE_INSTALL_FULL_DATADIR}/upstart/sessions") |
197 | +message (STATUS "${UPSTART_JOB_DIR} is the Upstart Job File install dir") |
198 | + |
199 | +set (UPSTART_JOB_NAME "${SERVICE_LIB_NAME}.conf") |
200 | +set (UPSTART_JOB_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_JOB_NAME}") |
201 | +set (UPSTART_JOB_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_JOB_NAME}.in") |
202 | + |
203 | +# build it |
204 | +configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}") |
205 | + |
206 | +# install it |
207 | +install (FILES "${UPSTART_JOB_FILE}" |
208 | + DESTINATION "${UPSTART_JOB_DIR}") |
209 | |
210 | === added file 'notifier/data/printing-notifier.conf.in' |
211 | --- notifier/data/printing-notifier.conf.in 1970-01-01 00:00:00 +0000 |
212 | +++ notifier/data/printing-notifier.conf.in 2017-03-20 13:16:02 +0000 |
213 | @@ -0,0 +1,23 @@ |
214 | +description "Printing Notification Service" |
215 | + |
216 | +# NOTE: Limiting only to Unity 8 right now as it's still using |
217 | +# dbusmenu. That can be lifted after it is ported to GMenu |
218 | + |
219 | +start on indicator-services-start |
220 | +stop on desktop-end or indicator-services-end |
221 | + |
222 | +respawn |
223 | +respawn limit 2 10 |
224 | + |
225 | +pre-start script |
226 | + # NOTE: Only used on Unity8 today, not 7 |
227 | + # Still allows manual starting |
228 | + if [ "x$DESKTOP_SESSION" != "xubuntu-touch" ] && |
229 | + [ "x$DESKTOP_SESSION" != "xunity8" ]; then |
230 | + if [ "x$UPSTART_EVENTS" != "x" ] ; then |
231 | + stop; exit 0 |
232 | + fi |
233 | + fi |
234 | +end script |
235 | + |
236 | +exec $SNAP@pkglibexecdir@/@SERVICE_EXEC_NAME@ |
237 | |
238 | === added file 'notifier/data/printing-notifier.override' |
239 | --- notifier/data/printing-notifier.override 1970-01-01 00:00:00 +0000 |
240 | +++ notifier/data/printing-notifier.override 2017-03-20 13:16:02 +0000 |
241 | @@ -0,0 +1,1 @@ |
242 | +manual |
243 | |
244 | === added file 'notifier/data/printing-notifier.service.in' |
245 | --- notifier/data/printing-notifier.service.in 1970-01-01 00:00:00 +0000 |
246 | +++ notifier/data/printing-notifier.service.in 2017-03-20 13:16:02 +0000 |
247 | @@ -0,0 +1,8 @@ |
248 | +[Unit] |
249 | +Description=Printing Notification Service |
250 | +PartOf=graphical-session.target |
251 | +After=indicators-pre.target |
252 | + |
253 | +[Service] |
254 | +ExecStart=@pkglibexecdir@/@SERVICE_EXEC_NAME@ |
255 | +Restart=on-failure |
256 | |
257 | === added directory 'notifier/src' |
258 | === added file 'notifier/src/CMakeLists.txt' |
259 | --- notifier/src/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
260 | +++ notifier/src/CMakeLists.txt 2017-03-20 13:16:02 +0000 |
261 | @@ -0,0 +1,62 @@ |
262 | +add_definitions( |
263 | + -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\" |
264 | + -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\" |
265 | + -DG_LOG_DOMAIN=\"${CMAKE_PROJECT_NAME}\" |
266 | +) |
267 | + |
268 | +include_directories( |
269 | + ${CMAKE_CURRENT_SOURCE_DIR} |
270 | + ${CMAKE_CURRENT_BINARY_DIR} |
271 | + ${SERVICE_DEPS_INCLUDE_DIRS} |
272 | +) |
273 | +link_directories( |
274 | + ${SERVICE_DEPS_LIBRARY_DIRS} |
275 | +) |
276 | + |
277 | +find_package(GDbus REQUIRED) |
278 | +add_gdbus_codegen( |
279 | + SERVICE_GENERATED_SOURCES |
280 | + cups-cupsd-notifier |
281 | + org.cups.cupsd |
282 | + ${CMAKE_CURRENT_SOURCE_DIR}/org.cups.cupsd.Notifier.xml) |
283 | + |
284 | +add_library(${SERVICE_LIB_NAME} STATIC |
285 | + actions.cpp |
286 | + actions.h |
287 | + client.h |
288 | + cups-client.cpp |
289 | + cups-client.h |
290 | + job.h |
291 | + notification.cpp |
292 | + notification.h |
293 | + notify-engine.cpp |
294 | + notify-engine.h |
295 | + printer.h |
296 | + utils.cpp |
297 | + utils.h |
298 | + ${SERVICE_GENERATED_SOURCES} |
299 | +) |
300 | + |
301 | +target_link_libraries(${SERVICE_LIB_NAME} |
302 | + ${SERVICE_DEPS_LIBRARIES} |
303 | + ${CUPS_LIBS} |
304 | +) |
305 | + |
306 | + |
307 | +add_executable(${SERVICE_EXEC_NAME} |
308 | + main.cpp |
309 | +) |
310 | + |
311 | +target_link_libraries(${SERVICE_EXEC_NAME} |
312 | + ${SERVICE_LIB_NAME} |
313 | + ${SERVICE_DEPS_LIBRARIES} |
314 | + ${CUPS_LIBS} |
315 | + |
316 | + ${CMAKE_THREAD_LIBS_INIT} |
317 | +) |
318 | + |
319 | +install( |
320 | + TARGETS ${SERVICE_EXEC_NAME} |
321 | + RUNTIME |
322 | + DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/${PROJECT_NAME} |
323 | +) |
324 | |
325 | === added file 'notifier/src/actions.cpp' |
326 | --- notifier/src/actions.cpp 1970-01-01 00:00:00 +0000 |
327 | +++ notifier/src/actions.cpp 2017-03-20 13:16:02 +0000 |
328 | @@ -0,0 +1,42 @@ |
329 | +/* |
330 | + * Copyright 2017 Canonical Ltd. |
331 | + * |
332 | + * This program is free software: you can redistribute it and/or modify it |
333 | + * under the terms of the GNU General Public License version 3, as published |
334 | + * by the Free Software Foundation. |
335 | + * |
336 | + * This program is distributed in the hope that it will be useful, but |
337 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
338 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
339 | + * PURPOSE. See the GNU General Public License for more details. |
340 | + * |
341 | + * You should have received a copy of the GNU General Public License along |
342 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
343 | + */ |
344 | + |
345 | +#include "actions.h" |
346 | + |
347 | +#include <glib.h> |
348 | +#include <url-dispatcher.h> |
349 | + |
350 | +namespace ubuntu { |
351 | +namespace printing { |
352 | +namespace notifier { |
353 | + |
354 | +Actions::Actions() |
355 | +{ |
356 | +} |
357 | + |
358 | +Actions::~Actions() |
359 | +{ |
360 | +} |
361 | + |
362 | +void Actions::open_settings_app(const std::string& url) |
363 | +{ |
364 | + g_debug("Dispatching url '%s'", url.c_str()); |
365 | + url_dispatch_send(url.c_str(), nullptr, nullptr); |
366 | +} |
367 | + |
368 | +} // notifier |
369 | +} // printing |
370 | +} // ubuntu |
371 | |
372 | === added file 'notifier/src/actions.h' |
373 | --- notifier/src/actions.h 1970-01-01 00:00:00 +0000 |
374 | +++ notifier/src/actions.h 2017-03-20 13:16:02 +0000 |
375 | @@ -0,0 +1,43 @@ |
376 | +/* |
377 | + * Copyright 2017 Canonical Ltd. |
378 | + * |
379 | + * This program is free software: you can redistribute it and/or modify it |
380 | + * under the terms of the GNU General Public License version 3, as published |
381 | + * by the Free Software Foundation. |
382 | + * |
383 | + * This program is distributed in the hope that it will be useful, but |
384 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
385 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
386 | + * PURPOSE. See the GNU General Public License for more details. |
387 | + * |
388 | + * You should have received a copy of the GNU General Public License along |
389 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
390 | + */ |
391 | + |
392 | +#pragma once |
393 | + |
394 | +#include <string> |
395 | + |
396 | +namespace ubuntu { |
397 | +namespace printing { |
398 | +namespace notifier { |
399 | + |
400 | +/** |
401 | + * \brief Interface for all the actions that can be activated by users. |
402 | + * |
403 | + * This is a simple C++ wrapper around our GActionGroup that gets exported |
404 | + * onto the bus. Subclasses implement the actual code that should be run |
405 | + * when a particular action is triggered. |
406 | + */ |
407 | +class Actions |
408 | +{ |
409 | +public: |
410 | + Actions(); |
411 | + virtual ~Actions(); |
412 | + |
413 | + virtual void open_settings_app(const std::string& url); |
414 | +}; |
415 | + |
416 | +} // notifier |
417 | +} // printing |
418 | +} // ubuntu |
419 | |
420 | === added file 'notifier/src/client.h' |
421 | --- notifier/src/client.h 1970-01-01 00:00:00 +0000 |
422 | +++ notifier/src/client.h 2017-03-20 13:16:02 +0000 |
423 | @@ -0,0 +1,56 @@ |
424 | +/* |
425 | + * Copyright 2016-2017 Canonical Ltd. |
426 | + * |
427 | + * This program is free software: you can redistribute it and/or modify it |
428 | + * under the terms of the GNU General Public License version 3, as published |
429 | + * by the Free Software Foundation. |
430 | + * |
431 | + * This program is distributed in the hope that it will be useful, but |
432 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
433 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
434 | + * PURPOSE. See the GNU General Public License for more details. |
435 | + * |
436 | + * You should have received a copy of the GNU General Public License along |
437 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
438 | + */ |
439 | + |
440 | +#pragma once |
441 | + |
442 | +#include "job.h" |
443 | +#include "printer.h" |
444 | + |
445 | +#include <core/signal.h> |
446 | + |
447 | + |
448 | +namespace ubuntu { |
449 | +namespace printing { |
450 | +namespace notifier { |
451 | + |
452 | + class Client { |
453 | + public: |
454 | + Client() = default; |
455 | + virtual ~Client() = default; |
456 | + |
457 | + // Signals corresponding to printers |
458 | + virtual core::Signal<const Printer&>& printer_state_changed() = 0; |
459 | + |
460 | + // Signals corresponding to jobs |
461 | + virtual core::Signal<const Job&>& job_state_changed() = 0; |
462 | + |
463 | + // Methods to manage notification monitoring |
464 | + virtual void create_subscription() = 0; |
465 | + virtual void renew_subscription() = 0; |
466 | + virtual void cancel_subscription() = 0; |
467 | + |
468 | + // To iniitalize the notifier with current jobs |
469 | + virtual void refresh() = 0; |
470 | + |
471 | + private: |
472 | + // disable copying |
473 | + Client(const Client&) = delete; |
474 | + Client& operator=(const Client&) = delete; |
475 | + }; |
476 | + |
477 | +} // notifier |
478 | +} // printing |
479 | +} // ubuntu |
480 | |
481 | === added file 'notifier/src/cups-client.cpp' |
482 | --- notifier/src/cups-client.cpp 1970-01-01 00:00:00 +0000 |
483 | +++ notifier/src/cups-client.cpp 2017-03-20 13:16:02 +0000 |
484 | @@ -0,0 +1,337 @@ |
485 | +/* |
486 | + * Copyright 2016-2017 Canonical Ltd. |
487 | + * |
488 | + * This program is free software: you can redistribute it and/or modify it |
489 | + * under the terms of the GNU General Public License version 3, as published |
490 | + * by the Free Software Foundation. |
491 | + * |
492 | + * This program is distributed in the hope that it will be useful, but |
493 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
494 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
495 | + * PURPOSE. See the GNU General Public License for more details. |
496 | + * |
497 | + * You should have received a copy of the GNU General Public License along |
498 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
499 | + */ |
500 | + |
501 | +#include "cups-client.h" |
502 | +#include "cups-cupsd-notifier.h" |
503 | + |
504 | +#include <cups/cups.h> |
505 | + |
506 | +#include <stdexcept> |
507 | + |
508 | +namespace ubuntu { |
509 | +namespace printing { |
510 | +namespace notifier { |
511 | + |
512 | +#define NOTIFY_LEASE_DURATION (24 * 60 * 60) |
513 | + |
514 | + |
515 | +class CupsClient::Impl { |
516 | +public: |
517 | + Impl() |
518 | + { |
519 | + GError *error = nullptr; |
520 | + |
521 | + m_notifier_proxy = notifier_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, |
522 | + G_DBUS_PROXY_FLAGS_NONE, |
523 | + nullptr, |
524 | + CUPS_DBUS_PATH, |
525 | + nullptr, |
526 | + &error); |
527 | + |
528 | + if (error != nullptr) { |
529 | + std::string msg{"Error creating cups notifier proxy: "}; |
530 | + throw std::runtime_error(msg + error->message); |
531 | + g_clear_error(&error); |
532 | + } |
533 | + |
534 | + g_object_connect(m_notifier_proxy, |
535 | + "signal::job-created", on_job_changed, this, |
536 | + "signal::job-state", on_job_changed, this, |
537 | + "signal::job-completed", on_job_changed, this, |
538 | + "signal::printer-state-changed", on_printer_state_changed, this, |
539 | + nullptr); |
540 | + } |
541 | + |
542 | + ~Impl() |
543 | + { |
544 | + if (m_notifier_proxy != nullptr) { |
545 | + g_signal_handlers_disconnect_by_data(m_notifier_proxy, this); |
546 | + g_clear_object(&m_notifier_proxy); |
547 | + } |
548 | + |
549 | + // Cancel the subscription from cups, so its notifier can exit. |
550 | + cancel_subscription(); |
551 | + } |
552 | + |
553 | + // Signals to propagate |
554 | + core::Signal<const Printer&>& printer_state_changed() |
555 | + { |
556 | + return m_printer_state_changed; |
557 | + } |
558 | + |
559 | + core::Signal<const Job&>& job_state_changed() |
560 | + { |
561 | + return m_job_state_changed; |
562 | + } |
563 | + |
564 | + void create_subscription() |
565 | + { |
566 | + ipp_t *req; |
567 | + ipp_t *resp; |
568 | + ipp_attribute_t *attr; |
569 | + |
570 | + req = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION); |
571 | + ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, |
572 | + "printer-uri", NULL, "/"); |
573 | + ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, |
574 | + "notify-events", NULL, "all"); |
575 | + ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, |
576 | + "notify-recipient-uri", NULL, "dbus://"); |
577 | + ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, |
578 | + "notify-lease-duration", NOTIFY_LEASE_DURATION); |
579 | + |
580 | + resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); |
581 | + if (!resp || cupsLastError() != IPP_OK) { |
582 | + g_warning ("Error subscribing to CUPS notifications: %s\n", |
583 | + cupsLastErrorString ()); |
584 | + return; |
585 | + } |
586 | + |
587 | + attr = ippFindAttribute (resp, "notify-subscription-id", IPP_TAG_INTEGER); |
588 | + if (attr) { |
589 | + m_subscription_id = ippGetInteger (attr, 0); |
590 | + } else { |
591 | + g_warning ("ipp-create-printer-subscription response doesn't contain " |
592 | + "subscription id.\n"); |
593 | + } |
594 | + ippDelete (resp); |
595 | + |
596 | + // Set up to renew the subscription a minute before it expires |
597 | + g_timeout_add_seconds(NOTIFY_LEASE_DURATION - 60, |
598 | + on_subscription_timeout, |
599 | + this); |
600 | + } |
601 | + |
602 | + void renew_subscription() |
603 | + { |
604 | + ipp_t *req; |
605 | + ipp_t *resp; |
606 | + |
607 | + req = ippNewRequest (IPP_RENEW_SUBSCRIPTION); |
608 | + ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER, |
609 | + "notify-subscription-id", m_subscription_id); |
610 | + ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, |
611 | + "printer-uri", NULL, "/"); |
612 | + ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, |
613 | + "notify-recipient-uri", NULL, "dbus://"); |
614 | + ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, |
615 | + "notify-lease-duration", NOTIFY_LEASE_DURATION); |
616 | + |
617 | + resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); |
618 | + if (!resp || cupsLastError() != IPP_OK) { |
619 | + g_warning ("Error renewing CUPS subscription %d: %s\n", |
620 | + m_subscription_id, cupsLastErrorString ()); |
621 | + create_subscription(); |
622 | + } |
623 | + |
624 | + ippDelete (resp); |
625 | + } |
626 | + |
627 | + void cancel_subscription() |
628 | + { |
629 | + ipp_t *req; |
630 | + ipp_t *resp; |
631 | + |
632 | + if (m_subscription_id <= 0) { |
633 | + return; |
634 | + } |
635 | + |
636 | + req = ippNewRequest (IPP_CANCEL_SUBSCRIPTION); |
637 | + ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI, |
638 | + "printer-uri", NULL, "/"); |
639 | + ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER, |
640 | + "notify-subscription-id", m_subscription_id); |
641 | + |
642 | + resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/"); |
643 | + if (!resp || cupsLastError() != IPP_OK) { |
644 | + g_warning ("Error unsubscribing to CUPS notifications: %s\n", |
645 | + cupsLastErrorString ()); |
646 | + return; |
647 | + } |
648 | + |
649 | + ippDelete (resp); |
650 | + } |
651 | + |
652 | + void refresh() |
653 | + { |
654 | + int num_dests; |
655 | + cups_dest_t* dests; |
656 | + |
657 | + num_dests = cupsGetDests(&dests); |
658 | + for (int i = 0; i < num_dests; i++) { |
659 | + auto printer = get_printer_info(dests[i].name); |
660 | + |
661 | + cups_job_t* jobs; |
662 | + const auto num_jobs = cupsGetJobs(&jobs, dests[i].name, |
663 | + true, CUPS_WHICHJOBS_ACTIVE); |
664 | + for (int j = 0; j < num_jobs; j++) { |
665 | + Job job; |
666 | + job.id = jobs[j].id; |
667 | + job.state = static_cast<Job::State>(jobs[j].state); |
668 | + job.name = jobs[j].title; |
669 | + |
670 | + job.printer = printer; |
671 | + |
672 | + m_job_state_changed(job); |
673 | + } |
674 | + cupsFreeJobs(num_jobs, jobs); |
675 | + } |
676 | + cupsFreeDests(num_dests, dests); |
677 | + } |
678 | + |
679 | +private: |
680 | + // Method to get Printer object from the name |
681 | + Printer get_printer_info(const std::string& name) |
682 | + { |
683 | + int num_dests; |
684 | + cups_dest_t* dests; |
685 | + cups_dest_t* our_dest; |
686 | + Printer printer; |
687 | + printer.name = name; |
688 | + |
689 | + num_dests = cupsGetDests(&dests); |
690 | + our_dest = cupsGetDest(name.c_str(), nullptr, |
691 | + num_dests, dests); |
692 | + |
693 | + if (our_dest != nullptr) { |
694 | + // Get the printer's description |
695 | + auto description = cupsGetOption("printer-info", |
696 | + our_dest->num_options, |
697 | + our_dest->options); |
698 | + if (description != nullptr) { |
699 | + printer.description = description; |
700 | + } |
701 | + } |
702 | + |
703 | + cupsFreeDests(num_dests, dests); |
704 | + return printer; |
705 | + } |
706 | + |
707 | + static gboolean on_subscription_timeout(gpointer gthis) |
708 | + { |
709 | + static_cast<Impl*>(gthis)->renew_subscription(); |
710 | + return G_SOURCE_CONTINUE; |
711 | + } |
712 | + |
713 | + static void on_job_changed (Notifier*, |
714 | + const char* printer_text, |
715 | + const char* printer_uri, |
716 | + const char *printer_name, |
717 | + unsigned int printer_state, |
718 | + const char *printer_state_reasons, |
719 | + bool printer_is_accepting_jobs, |
720 | + unsigned int job_id, |
721 | + unsigned int job_state, |
722 | + const char *job_state_reasons, |
723 | + const char *job_name, |
724 | + unsigned int job_impressions_completed, |
725 | + gpointer gthis) |
726 | + { |
727 | + auto self = static_cast<Impl*>(gthis); |
728 | + |
729 | + auto printer = self->get_printer_info(printer_name); |
730 | + printer.state = static_cast<Printer::State>(printer_state); |
731 | + printer.text = printer_text; |
732 | + printer.uri = printer_uri; |
733 | + printer.state_reasons = printer_state_reasons; |
734 | + printer.accepting_jobs = printer_is_accepting_jobs; |
735 | + |
736 | + Job job; |
737 | + job.printer = printer; |
738 | + job.state = static_cast<Job::State>(job_state); |
739 | + job.id = job_id; |
740 | + job.name = job_name; |
741 | + job.state_reasons = job_state_reasons; |
742 | + job.impressions_completed = job_impressions_completed; |
743 | + |
744 | + self->m_job_state_changed(job); |
745 | + } |
746 | + |
747 | + static void on_printer_state_changed(Notifier*, |
748 | + const char* text, |
749 | + const char* uri, |
750 | + const char* name, |
751 | + unsigned int state, |
752 | + const char* state_reasons, |
753 | + bool is_accepting_jobs, |
754 | + gpointer gthis) |
755 | + { |
756 | + auto self = static_cast<Impl*>(gthis); |
757 | + |
758 | + auto printer = self->get_printer_info(name); |
759 | + printer.state = static_cast<Printer::State>(state); |
760 | + printer.text = text; |
761 | + printer.uri = uri; |
762 | + printer.state_reasons = state_reasons; |
763 | + printer.accepting_jobs = is_accepting_jobs; |
764 | + |
765 | + // Get the number of jobs currently active on the printer |
766 | + cups_job_t* jobs; |
767 | + printer.num_jobs = cupsGetJobs(&jobs, name, true, |
768 | + CUPS_WHICHJOBS_ACTIVE); |
769 | + cupsFreeJobs(printer.num_jobs, jobs); |
770 | + |
771 | + self->m_printer_state_changed(printer); |
772 | + } |
773 | + |
774 | + int m_subscription_id = 0; |
775 | + Notifier* m_notifier_proxy = nullptr; |
776 | + core::Signal<const Printer&> m_printer_state_changed; |
777 | + core::Signal<const Job&> m_job_state_changed; |
778 | +}; |
779 | + |
780 | +CupsClient::CupsClient() : |
781 | + p(new Impl()) |
782 | +{ |
783 | +} |
784 | + |
785 | +CupsClient::~CupsClient() |
786 | +{ |
787 | +} |
788 | + |
789 | +core::Signal<const Printer&>& CupsClient::printer_state_changed() |
790 | +{ |
791 | + return p->printer_state_changed(); |
792 | +} |
793 | + |
794 | +core::Signal<const Job&>& CupsClient::job_state_changed() |
795 | +{ |
796 | + return p->job_state_changed(); |
797 | +} |
798 | + |
799 | +void CupsClient::create_subscription() |
800 | +{ |
801 | + p->create_subscription(); |
802 | +} |
803 | + |
804 | +void CupsClient::renew_subscription() |
805 | +{ |
806 | + p->renew_subscription(); |
807 | +} |
808 | + |
809 | +void CupsClient::cancel_subscription() |
810 | +{ |
811 | + p->cancel_subscription(); |
812 | +} |
813 | + |
814 | +void CupsClient::refresh() |
815 | +{ |
816 | + p->refresh(); |
817 | +} |
818 | + |
819 | +} // notifier |
820 | +} // printing |
821 | +} // ubuntu |
822 | |
823 | === added file 'notifier/src/cups-client.h' |
824 | --- notifier/src/cups-client.h 1970-01-01 00:00:00 +0000 |
825 | +++ notifier/src/cups-client.h 2017-03-20 13:16:02 +0000 |
826 | @@ -0,0 +1,65 @@ |
827 | +/* |
828 | + * Copyright 2016-2017 Canonical Ltd. |
829 | + * |
830 | + * This program is free software: you can redistribute it and/or modify it |
831 | + * under the terms of the GNU General Public License version 3, as published |
832 | + * by the Free Software Foundation. |
833 | + * |
834 | + * This program is distributed in the hope that it will be useful, but |
835 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
836 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
837 | + * PURPOSE. See the GNU General Public License for more details. |
838 | + * |
839 | + * You should have received a copy of the GNU General Public License along |
840 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
841 | + */ |
842 | + |
843 | +#pragma once |
844 | + |
845 | +#include "client.h" |
846 | +#include "job.h" |
847 | +#include "printer.h" |
848 | + |
849 | +#include <core/signal.h> |
850 | + |
851 | +#include <memory> |
852 | + |
853 | +namespace ubuntu { |
854 | +namespace printing { |
855 | +namespace notifier { |
856 | + |
857 | +#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier" |
858 | +#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier" |
859 | +#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier" |
860 | + |
861 | + class CupsClient : public Client { |
862 | + public: |
863 | + CupsClient(); |
864 | + virtual ~CupsClient(); |
865 | + |
866 | + // Signals corresponding to notifier |
867 | + core::Signal<const Printer&>& printer_state_changed() override; |
868 | + |
869 | + // Signals corresponding to jobs |
870 | + core::Signal<const Job&>& job_state_changed() override; |
871 | + |
872 | + // Methods to manage notification monitoring |
873 | + virtual void create_subscription() override; |
874 | + virtual void renew_subscription() override; |
875 | + virtual void cancel_subscription() override; |
876 | + |
877 | + // To initialize the printing with current jobs |
878 | + virtual void refresh() override; |
879 | + |
880 | + private: |
881 | + class Impl; |
882 | + std::unique_ptr<Impl> p; |
883 | + |
884 | + // disable copying |
885 | + CupsClient(const CupsClient&) = delete; |
886 | + CupsClient& operator=(const CupsClient&) = delete; |
887 | + }; |
888 | + |
889 | +} // notifier |
890 | +} // printing |
891 | +} // ubuntu |
892 | |
893 | === added file 'notifier/src/dbus-names.h' |
894 | --- notifier/src/dbus-names.h 1970-01-01 00:00:00 +0000 |
895 | +++ notifier/src/dbus-names.h 2017-03-20 13:16:02 +0000 |
896 | @@ -0,0 +1,27 @@ |
897 | +/* |
898 | + * Copyright 2012 Canonical Ltd. |
899 | + * |
900 | + * Authors: Lars Uebernickel <lars.uebernickel@canonical.com> |
901 | + * |
902 | + * This program is free software: you can redistribute it and/or modify it |
903 | + * under the terms of the GNU General Public License version 3, as published |
904 | + * by the Free Software Foundation. |
905 | + * |
906 | + * This program is distributed in the hope that it will be useful, but |
907 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
908 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
909 | + * PURPOSE. See the GNU General Public License for more details. |
910 | + * |
911 | + * You should have received a copy of the GNU General Public License along |
912 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
913 | + */ |
914 | + |
915 | +#ifndef DBUS_NAMES_H |
916 | +#define DBUS_NAMES_H |
917 | + |
918 | +#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier" |
919 | +#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier" |
920 | +#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier" |
921 | + |
922 | +#endif |
923 | + |
924 | |
925 | === added file 'notifier/src/job.h' |
926 | --- notifier/src/job.h 1970-01-01 00:00:00 +0000 |
927 | +++ notifier/src/job.h 2017-03-20 13:16:02 +0000 |
928 | @@ -0,0 +1,50 @@ |
929 | +/* |
930 | + * Copyright 2016-2017 Canonical Ltd. |
931 | + * |
932 | + * This program is free software: you can redistribute it and/or modify it |
933 | + * under the terms of the GNU General Public License version 3, as published |
934 | + * by the Free Software Foundation. |
935 | + * |
936 | + * This program is distributed in the hope that it will be useful, but |
937 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
938 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
939 | + * PURPOSE. See the GNU General Public License for more details. |
940 | + * |
941 | + * You should have received a copy of the GNU General Public License along |
942 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
943 | + */ |
944 | + |
945 | +#pragma once |
946 | + |
947 | +#include "printer.h" |
948 | + |
949 | +#include <string> |
950 | + |
951 | +namespace ubuntu { |
952 | +namespace printing { |
953 | +namespace notifier { |
954 | + |
955 | + struct Job { |
956 | + // State to match ipp_jstate_t from cups.h |
957 | + typedef enum { |
958 | + PENDING = 3, |
959 | + HELD, |
960 | + PROCESSING, |
961 | + STOPPED, |
962 | + CANCELED, |
963 | + ABORTED, |
964 | + COMPLETED |
965 | + } State; |
966 | + State state = PENDING; |
967 | + |
968 | + uint32_t id = 0; |
969 | + std::string name; |
970 | + std::string state_reasons; |
971 | + uint32_t impressions_completed = 0; |
972 | + |
973 | + Printer printer; |
974 | + }; |
975 | + |
976 | +} // notifier |
977 | +} // printing |
978 | +} // ubuntu |
979 | |
980 | === added file 'notifier/src/main.cpp' |
981 | --- notifier/src/main.cpp 1970-01-01 00:00:00 +0000 |
982 | +++ notifier/src/main.cpp 2017-03-20 13:16:02 +0000 |
983 | @@ -0,0 +1,61 @@ |
984 | +/* |
985 | + * Copyright 2016-2017 Canonical Ltd. |
986 | + * |
987 | + * This program is free software: you can redistribute it and/or modify it |
988 | + * under the terms of the GNU General Public License version 3, as published |
989 | + * by the Free Software Foundation. |
990 | + * |
991 | + * This program is distributed in the hope that it will be useful, but |
992 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
993 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
994 | + * PURPOSE. See the GNU General Public License for more details. |
995 | + * |
996 | + * You should have received a copy of the GNU General Public License along |
997 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
998 | + */ |
999 | + |
1000 | +#include "actions.h" |
1001 | +#include "cups-client.h" |
1002 | +#include "notify-engine.h" |
1003 | +#include "utils.h" |
1004 | + |
1005 | +#include <glib/gi18n.h> |
1006 | +#include <gio/gio.h> |
1007 | +#include <libnotify/notify.h> |
1008 | + |
1009 | +using namespace ubuntu::printing::notifier; |
1010 | + |
1011 | +int main(int /* argc */, char** argv) |
1012 | +{ |
1013 | + // Work around a deadlock in glib's type initialization. |
1014 | + // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed. |
1015 | + g_type_ensure(G_TYPE_DBUS_CONNECTION); |
1016 | + |
1017 | + // boilerplate i18n |
1018 | + setlocale(LC_ALL, ""); |
1019 | + |
1020 | + // Need to prepend $SNAP to properly load translations |
1021 | + auto localedir = Utilities::prepend_snap_path(GETTEXT_LOCALEDIR); |
1022 | + bindtextdomain(GETTEXT_PACKAGE, localedir.c_str()); |
1023 | + textdomain(GETTEXT_PACKAGE); |
1024 | + |
1025 | + // set up us the machine |
1026 | + auto loop = g_main_loop_new(nullptr, false); |
1027 | + |
1028 | + // Initialize notifications, and use program name for app name |
1029 | + if (!notify_init(basename(argv[0]))) { |
1030 | + g_critical("Unable to initialize libnotify."); |
1031 | + } |
1032 | + |
1033 | + // create the client and set up the signal handling |
1034 | + auto client = std::make_shared<CupsClient>(); |
1035 | + auto actions = std::make_shared<Actions>(); |
1036 | + auto engine = std::make_shared<NotifyEngine>(client, actions); |
1037 | + |
1038 | + g_main_loop_run(loop); |
1039 | + |
1040 | + // cleanup |
1041 | + notify_uninit(); |
1042 | + g_main_loop_unref(loop); |
1043 | + return 0; |
1044 | +} |
1045 | |
1046 | === added file 'notifier/src/notification.cpp' |
1047 | --- notifier/src/notification.cpp 1970-01-01 00:00:00 +0000 |
1048 | +++ notifier/src/notification.cpp 2017-03-20 13:16:02 +0000 |
1049 | @@ -0,0 +1,185 @@ |
1050 | +/* |
1051 | + * Copyright 2017 Canonical Ltd. |
1052 | + * |
1053 | + * This program is free software: you can redistribute it and/or modify it |
1054 | + * under the terms of the GNU General Public License version 3, as published |
1055 | + * by the Free Software Foundation. |
1056 | + * |
1057 | + * This program is distributed in the hope that it will be useful, but |
1058 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1059 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1060 | + * PURPOSE. See the GNU General Public License for more details. |
1061 | + * |
1062 | + * You should have received a copy of the GNU General Public License along |
1063 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1064 | + */ |
1065 | + |
1066 | +#include "notification.h" |
1067 | + |
1068 | +#include <libnotify/notification.h> |
1069 | +#include <libnotify/notify.h> |
1070 | + |
1071 | +namespace ubuntu { |
1072 | +namespace printing { |
1073 | +namespace notifier { |
1074 | + |
1075 | +class Notification::Impl |
1076 | +{ |
1077 | +public: |
1078 | + Impl(const std::string& summary, |
1079 | + const std::string& body, |
1080 | + const std::string& icon_name): |
1081 | + m_summary(summary), |
1082 | + m_body(body), |
1083 | + m_icon_name(icon_name) |
1084 | + { |
1085 | + m_nn.reset(notify_notification_new(m_summary.c_str(), |
1086 | + m_body.c_str(), |
1087 | + m_icon_name.c_str()), |
1088 | + [this](NotifyNotification* n) { |
1089 | + g_signal_handlers_disconnect_by_data(n, this); |
1090 | + g_object_unref(n); |
1091 | + }); |
1092 | + |
1093 | + g_signal_connect(m_nn.get(), "closed", |
1094 | + G_CALLBACK(on_notification_closed), this); |
1095 | + } |
1096 | + |
1097 | + ~Impl() |
1098 | + { |
1099 | + } |
1100 | + |
1101 | + core::Signal<const std::string&>& activated() |
1102 | + { |
1103 | + return m_activated; |
1104 | + } |
1105 | + |
1106 | + core::Signal<>& closed() |
1107 | + { |
1108 | + return m_closed; |
1109 | + } |
1110 | + |
1111 | + void add_action(const std::string& action, const std::string& label) |
1112 | + { |
1113 | + notify_notification_add_action(m_nn.get(), |
1114 | + action.c_str(), label.c_str(), |
1115 | + on_notify_activated, |
1116 | + this, nullptr); |
1117 | + } |
1118 | + |
1119 | + void set_hint(const std::string& hint, const std::string& value) |
1120 | + { |
1121 | + notify_notification_set_hint_string(m_nn.get(), |
1122 | + hint.c_str(), value.c_str()); |
1123 | + } |
1124 | + |
1125 | + void close() |
1126 | + { |
1127 | + if (!notify_is_initted()) { |
1128 | + g_warning("Tried to close a notification without notify_init()."); |
1129 | + return; |
1130 | + } |
1131 | + |
1132 | + GError* error = nullptr; |
1133 | + notify_notification_close(m_nn.get(), &error); |
1134 | + |
1135 | + if (error != nullptr) { |
1136 | + g_critical("Error closing notification: %s", error->message); |
1137 | + g_clear_error(&error); |
1138 | + } |
1139 | + } |
1140 | + |
1141 | + void show() |
1142 | + { |
1143 | + if (!notify_is_initted()) { |
1144 | + g_critical("Unable to display notifications without notify_init()."); |
1145 | + return; |
1146 | + } |
1147 | + |
1148 | + if (m_summary.empty()) { |
1149 | + g_critical("Attempting to show notification with no summary!"); |
1150 | + return; |
1151 | + } |
1152 | + |
1153 | + GError* error = nullptr; |
1154 | + notify_notification_show(m_nn.get(), &error); |
1155 | + |
1156 | + if (error != nullptr) { |
1157 | + g_critical("Error showing notification: %s", error->message); |
1158 | + g_clear_error(&error); |
1159 | + } |
1160 | + } |
1161 | + |
1162 | +private: |
1163 | + static void on_notify_activated(NotifyNotification*, |
1164 | + char* action, |
1165 | + gpointer gthis) |
1166 | + { |
1167 | + auto self = static_cast<Impl*>(gthis); |
1168 | + self->m_activated(action); |
1169 | + } |
1170 | + |
1171 | + static void on_notification_closed(NotifyNotification*, |
1172 | + gpointer gthis) |
1173 | + { |
1174 | + auto self = static_cast<Impl*>(gthis); |
1175 | + g_debug("Notification was closed."); |
1176 | + self->m_closed(); |
1177 | + } |
1178 | + |
1179 | + std::shared_ptr<NotifyNotification> m_nn; |
1180 | + |
1181 | + std::string m_summary; |
1182 | + std::string m_body; |
1183 | + std::string m_icon_name; |
1184 | + |
1185 | + core::Signal<const std::string&> m_activated; |
1186 | + core::Signal<> m_closed; |
1187 | +}; |
1188 | + |
1189 | +Notification::Notification(const std::string& summary, |
1190 | + const std::string& body, |
1191 | + const std::string& icon_name): |
1192 | + p(new Impl(summary, body, icon_name)) |
1193 | +{ |
1194 | +} |
1195 | + |
1196 | +Notification::~Notification() |
1197 | +{ |
1198 | +} |
1199 | + |
1200 | +core::Signal<const std::string&>& Notification::activated() |
1201 | +{ |
1202 | + return p->activated(); |
1203 | +} |
1204 | + |
1205 | +core::Signal<>& Notification::closed() |
1206 | +{ |
1207 | + return p->closed(); |
1208 | +} |
1209 | + |
1210 | +void Notification::add_action(const std::string& action, |
1211 | + const std::string& label) |
1212 | +{ |
1213 | + p->add_action(action, label); |
1214 | +} |
1215 | + |
1216 | +void Notification::set_hint(const std::string& hint, |
1217 | + const std::string& value) |
1218 | +{ |
1219 | + p->set_hint(hint, value); |
1220 | +} |
1221 | + |
1222 | +void Notification::close() |
1223 | +{ |
1224 | + p->close(); |
1225 | +} |
1226 | + |
1227 | +void Notification::show() |
1228 | +{ |
1229 | + p->show(); |
1230 | +} |
1231 | + |
1232 | +} // notifier |
1233 | +} // printing |
1234 | +} // ubuntu |
1235 | |
1236 | === added file 'notifier/src/notification.h' |
1237 | --- notifier/src/notification.h 1970-01-01 00:00:00 +0000 |
1238 | +++ notifier/src/notification.h 2017-03-20 13:16:02 +0000 |
1239 | @@ -0,0 +1,61 @@ |
1240 | +/* |
1241 | + * Copyright 2017 Canonical Ltd. |
1242 | + * |
1243 | + * This program is free software: you can redistribute it and/or modify it |
1244 | + * under the terms of the GNU General Public License version 3, as published |
1245 | + * by the Free Software Foundation. |
1246 | + * |
1247 | + * This program is distributed in the hope that it will be useful, but |
1248 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1249 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1250 | + * PURPOSE. See the GNU General Public License for more details. |
1251 | + * |
1252 | + * You should have received a copy of the GNU General Public License along |
1253 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1254 | + */ |
1255 | + |
1256 | +#pragma once |
1257 | + |
1258 | +#include <string> |
1259 | + |
1260 | +#include <core/signal.h> |
1261 | + |
1262 | +namespace ubuntu { |
1263 | +namespace printing { |
1264 | +namespace notifier { |
1265 | + |
1266 | + class Notification { |
1267 | + public: |
1268 | + Notification(const std::string& summary, |
1269 | + const std::string& body, |
1270 | + const std::string& icon_name); |
1271 | + virtual ~Notification(); |
1272 | + |
1273 | + // Signal for activation of actions in notification |
1274 | + virtual core::Signal<const std::string&>& activated(); |
1275 | + |
1276 | + // Signal for forced closing of notification |
1277 | + virtual core::Signal<>& closed(); |
1278 | + |
1279 | + virtual void add_action(const std::string& action, |
1280 | + const std::string& label); |
1281 | + |
1282 | + // For hints |
1283 | + virtual void set_hint(const std::string& hint, |
1284 | + const std::string& value); |
1285 | + |
1286 | + virtual void close(); |
1287 | + virtual void show(); |
1288 | + |
1289 | + private: |
1290 | + class Impl; |
1291 | + std::unique_ptr<Impl> p; |
1292 | + |
1293 | + // disable copying |
1294 | + Notification(const Notification&) = delete; |
1295 | + Notification& operator=(const Notification&) = delete; |
1296 | + }; |
1297 | + |
1298 | +} // notifier |
1299 | +} // printing |
1300 | +} // ubuntu |
1301 | |
1302 | === added file 'notifier/src/notify-engine.cpp' |
1303 | --- notifier/src/notify-engine.cpp 1970-01-01 00:00:00 +0000 |
1304 | +++ notifier/src/notify-engine.cpp 2017-03-20 13:16:02 +0000 |
1305 | @@ -0,0 +1,204 @@ |
1306 | +/* |
1307 | + * Copyright 2017 Canonical Ltd. |
1308 | + * |
1309 | + * This program is free software: you can redistribute it and/or modify it |
1310 | + * under the terms of the GNU General Public License version 3, as published |
1311 | + * by the Free Software Foundation. |
1312 | + * |
1313 | + * This program is distributed in the hope that it will be useful, but |
1314 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1315 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1316 | + * PURPOSE. See the GNU General Public License for more details. |
1317 | + * |
1318 | + * You should have received a copy of the GNU General Public License along |
1319 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1320 | + */ |
1321 | + |
1322 | +#include "notify-engine.h" |
1323 | + |
1324 | +#include <map> |
1325 | +#include <regex> |
1326 | +#include <unordered_set> |
1327 | + |
1328 | +#include <boost/algorithm/string.hpp> |
1329 | +#include <boost/format.hpp> |
1330 | + |
1331 | +#include <glib/gi18n.h> |
1332 | +#include <libnotify/notify.h> |
1333 | + |
1334 | +namespace ubuntu { |
1335 | +namespace printing { |
1336 | +namespace notifier { |
1337 | + |
1338 | +class NotifyEngine::Impl |
1339 | +{ |
1340 | + struct notification_data |
1341 | + { |
1342 | + std::shared_ptr<Notification> notification; |
1343 | + std::unordered_set<std::shared_ptr<Notification>> notifications; |
1344 | + }; |
1345 | + |
1346 | +public: |
1347 | + Impl(const std::shared_ptr<Client>& client, |
1348 | + const std::shared_ptr<Actions>& actions): |
1349 | + m_client(client), |
1350 | + m_actions(actions), |
1351 | + // NOTE: sorted alphabetically by state |
1352 | + m_reasons({ |
1353 | + {"cover-open", _("A cover is open on the printer “%s”.")}, |
1354 | + {"cups-missing-filter", _("The printer “%s” can’t be used, because required software is missing.")}, |
1355 | + {"door-open-report", _("A door is open on the printer “%s”.")}, |
1356 | + {"media-empty", _("The printer “%s” is out of paper.")}, |
1357 | + {"media-low", _("The printer “%s” is low on paper.")}, |
1358 | + {"offline", _("The printer “%s” is currently off-line.")}, |
1359 | + {"other", _("The printer “%s” has an unknown problem.")}, |
1360 | + {"toner-empty", _("The printer “%s” is out of toner.")}, |
1361 | + {"toner-low", _("The printer “%s” is low on toner.")}, |
1362 | + }) |
1363 | + { |
1364 | + } |
1365 | + |
1366 | + ~Impl() |
1367 | + { |
1368 | + } |
1369 | + |
1370 | + std::string get_displayable_reason(const std::string& reason) |
1371 | + { |
1372 | + return m_reasons[reason]; |
1373 | + } |
1374 | + |
1375 | + std::unordered_set<std::string> get_notified_reasons(const Printer& printer) |
1376 | + { |
1377 | + return m_notified[printer.name]; |
1378 | + } |
1379 | + |
1380 | + void set_notified_reasons(const Printer& printer, |
1381 | + std::unordered_set<std::string> reasons) |
1382 | + { |
1383 | + m_notified[printer.name] = reasons; |
1384 | + } |
1385 | + |
1386 | + void show_notification(const std::shared_ptr<Notification>& notification) |
1387 | + { |
1388 | + if (notification.get() == nullptr) { |
1389 | + return; |
1390 | + } |
1391 | + |
1392 | + notification->activated().connect([this](const std::string& action) { |
1393 | + static const std::regex actionsettings{"^settings:///.*"}; |
1394 | + if (std::regex_match(action, actionsettings)) { |
1395 | + m_actions->open_settings_app(action); |
1396 | + } |
1397 | + // Otherwise we just ignore the action. |
1398 | + }); |
1399 | + notification->closed().connect([this, ¬ification]() { |
1400 | + g_debug("Closed notification."); |
1401 | + auto data = new notification_data({notification, m_notifications}); |
1402 | + g_idle_add(on_delete_later, data); |
1403 | + }); |
1404 | + m_notifications.emplace(notification); |
1405 | + notification->show(); |
1406 | + } |
1407 | + |
1408 | +private: |
1409 | + static gboolean on_delete_later(gpointer gdata) |
1410 | + { |
1411 | + auto data = static_cast<notification_data*>(gdata); |
1412 | + data->notifications.erase(data->notification); |
1413 | + return G_SOURCE_REMOVE; |
1414 | + } |
1415 | + |
1416 | + std::shared_ptr<Client> m_client; |
1417 | + std::shared_ptr<Actions> m_actions; |
1418 | + |
1419 | + // The set of current notifications |
1420 | + std::unordered_set<std::shared_ptr<Notification>> m_notifications; |
1421 | + |
1422 | + // The map of "printer" -> set of notified notified states |
1423 | + std::map<std::string, std::unordered_set<std::string>> m_notified; |
1424 | + |
1425 | + // The map of "reason" -> _("Translated displayable reason") strings |
1426 | + std::map<std::string, std::string> m_reasons; |
1427 | +}; // class Impl |
1428 | + |
1429 | + |
1430 | +NotifyEngine::NotifyEngine(const std::shared_ptr<Client>& client, |
1431 | + const std::shared_ptr<Actions>& actions): |
1432 | + p(new Impl(client, actions)) |
1433 | +{ |
1434 | + client->job_state_changed().connect([this](const Job& job) { |
1435 | + const auto& printer = job.printer; |
1436 | + g_debug("State changed for job %u '%s` on printer '%s' and reasons were '%s'", |
1437 | + job.id, |
1438 | + job.name.c_str(), |
1439 | + printer.description.empty() ? printer.name.c_str() : printer.description.c_str(), |
1440 | + job.state_reasons.c_str()); |
1441 | + if (job.state == Job::State::COMPLETED) { |
1442 | + auto notification = build_job_notification(job); |
1443 | + p->show_notification(notification); |
1444 | + } |
1445 | + }); |
1446 | + client->printer_state_changed().connect([this](const Printer& printer) { |
1447 | + g_debug("Printer state changed for reasons: '%s'", |
1448 | + printer.state_reasons.c_str()); |
1449 | + if (printer.num_jobs > 0) { |
1450 | + auto notified = p->get_notified_reasons(printer); |
1451 | + std::unordered_set<std::string> reasons; |
1452 | + boost::split(reasons, printer.state_reasons, boost::is_any_of(",")); |
1453 | + for (const auto& reason: reasons) { |
1454 | + if (notified.count(reason) == 0) { |
1455 | + auto notification = build_printer_notification(printer, reason); |
1456 | + p->show_notification(notification); |
1457 | + } |
1458 | + } |
1459 | + p->set_notified_reasons(printer, reasons); |
1460 | + } |
1461 | + }); |
1462 | +} |
1463 | + |
1464 | +NotifyEngine::~NotifyEngine() |
1465 | +{ |
1466 | +} |
1467 | + |
1468 | +std::shared_ptr<Notification> NotifyEngine::build_job_notification(const Job& job) |
1469 | +{ |
1470 | + std::shared_ptr<Notification> notification; |
1471 | + |
1472 | + auto summary = boost::format(_("“%s” has printed.")) % job.name; |
1473 | + notification.reset(new Notification(summary.str(), "", NOTIFY_PRINTER_ICON)); |
1474 | + |
1475 | + return notification; |
1476 | +} |
1477 | + |
1478 | +std::shared_ptr<Notification> NotifyEngine::build_printer_notification(const Printer& printer, |
1479 | + const std::string& reason) |
1480 | +{ |
1481 | + std::shared_ptr<Notification> notification; |
1482 | + |
1483 | + const auto& displayname = printer.description.empty() ? printer.description : printer.name; |
1484 | + |
1485 | + // Get the reason text and add summary/body if valid |
1486 | + auto untranslated = p->get_displayable_reason(reason); |
1487 | + if (!untranslated.empty()) { |
1488 | + auto summary = boost::format(untranslated) % displayname; |
1489 | + |
1490 | + auto jobtext = ngettext("You have %d job queued to print on this printer.", |
1491 | + "You have %d jobs queued to print on this printer.", |
1492 | + printer.num_jobs); |
1493 | + auto body = boost::format(jobtext) % printer.num_jobs; |
1494 | + |
1495 | + notification.reset(new Notification(summary.str(), body.str(), NOTIFY_ERROR_ICON)); |
1496 | + |
1497 | + notification->set_hint(NOTIFY_HINT_SNAP, "true"); |
1498 | + notification->add_action("PRINTER_ACTION_IGNORE", _("OK")); |
1499 | + std::string settings_url{"settings:///system/printers/"}; |
1500 | + notification->add_action(settings_url + printer.name, _("Settings…")); |
1501 | + } |
1502 | + |
1503 | + return notification; |
1504 | +} |
1505 | + |
1506 | + |
1507 | +} //notifier |
1508 | +} // printing |
1509 | +} // ubuntu |
1510 | |
1511 | === added file 'notifier/src/notify-engine.h' |
1512 | --- notifier/src/notify-engine.h 1970-01-01 00:00:00 +0000 |
1513 | +++ notifier/src/notify-engine.h 2017-03-20 13:16:02 +0000 |
1514 | @@ -0,0 +1,57 @@ |
1515 | +/* |
1516 | + * Copyright 2017 Canonical Ltd. |
1517 | + * |
1518 | + * This program is free software: you can redistribute it and/or modify it |
1519 | + * under the terms of the GNU General Public License version 3, as published |
1520 | + * by the Free Software Foundation. |
1521 | + * |
1522 | + * This program is distributed in the hope that it will be useful, but |
1523 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1524 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1525 | + * PURPOSE. See the GNU General Public License for more details. |
1526 | + * |
1527 | + * You should have received a copy of the GNU General Public License along |
1528 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1529 | + */ |
1530 | + |
1531 | +#pragma once |
1532 | + |
1533 | +#include "actions.h" |
1534 | +#include "client.h" |
1535 | +#include "notification.h" |
1536 | + |
1537 | +#include <memory> |
1538 | + |
1539 | +namespace ubuntu { |
1540 | +namespace printing { |
1541 | +namespace notifier { |
1542 | + |
1543 | + // Icons for notifications |
1544 | + static constexpr const char* NOTIFY_PRINTER_ICON{"printer-symbolic"}; |
1545 | + static constexpr const char* NOTIFY_ERROR_ICON{"printer-error-symbolic"}; |
1546 | + |
1547 | + // Hints for notifications |
1548 | + static constexpr const char* NOTIFY_HINT_SNAP{"x-canonical-snap-decisions"}; |
1549 | + |
1550 | + class NotifyEngine { |
1551 | + public: |
1552 | + NotifyEngine(const std::shared_ptr<Client>& client, |
1553 | + const std::shared_ptr<Actions>& actions); |
1554 | + virtual ~NotifyEngine(); |
1555 | + |
1556 | + virtual std::shared_ptr<Notification> build_job_notification(const Job& job); |
1557 | + virtual std::shared_ptr<Notification> build_printer_notification(const Printer& printer, |
1558 | + const std::string& reason); |
1559 | + |
1560 | + private: |
1561 | + class Impl; |
1562 | + std::unique_ptr<Impl> p; |
1563 | + |
1564 | + // disable copying |
1565 | + NotifyEngine(const NotifyEngine&) = delete; |
1566 | + NotifyEngine& operator=(const NotifyEngine&) = delete; |
1567 | + }; |
1568 | + |
1569 | +} // notifier |
1570 | +} // printing |
1571 | +} // ubuntu |
1572 | |
1573 | === added file 'notifier/src/org.cups.cupsd.Notifier.xml' |
1574 | --- notifier/src/org.cups.cupsd.Notifier.xml 1970-01-01 00:00:00 +0000 |
1575 | +++ notifier/src/org.cups.cupsd.Notifier.xml 2017-03-20 13:16:02 +0000 |
1576 | @@ -0,0 +1,147 @@ |
1577 | +<node> |
1578 | + |
1579 | + <interface name="org.cups.cupsd.Notifier"> |
1580 | + |
1581 | + <signal name="ServerStarted"> |
1582 | + <arg type="s" name="text" /> |
1583 | + </signal> |
1584 | + |
1585 | + <signal name="ServerRestarted"> |
1586 | + <arg type="s" name="text" /> |
1587 | + </signal> |
1588 | + |
1589 | + <signal name="ServerStopped"> |
1590 | + <arg type="s" name="text" /> |
1591 | + </signal> |
1592 | + |
1593 | + <signal name="ServerAudit"> |
1594 | + <arg type="s" name="text" /> |
1595 | + </signal> |
1596 | + |
1597 | + <signal name="PrinterAdded"> |
1598 | + <arg type="s" name="text" /> |
1599 | + <arg type="s" name="printer_uri" /> |
1600 | + <arg type="s" name="printer_name" /> |
1601 | + <arg type="u" name="printer_state" /> |
1602 | + <arg type="s" name="printer_state_reasons" /> |
1603 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1604 | + </signal> |
1605 | + |
1606 | + <signal name="PrinterDeleted"> |
1607 | + <arg type="s" name="text" /> |
1608 | + <arg type="s" name="printer_uri" /> |
1609 | + <arg type="s" name="printer_name" /> |
1610 | + <arg type="u" name="printer_state" /> |
1611 | + <arg type="s" name="printer_state_reasons" /> |
1612 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1613 | + </signal> |
1614 | + |
1615 | + <signal name="PrinterModified"> |
1616 | + <arg type="s" name="text" /> |
1617 | + <arg type="s" name="printer_uri" /> |
1618 | + <arg type="s" name="printer_name" /> |
1619 | + <arg type="u" name="printer_state" /> |
1620 | + <arg type="s" name="printer_state_reasons" /> |
1621 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1622 | + </signal> |
1623 | + |
1624 | + <signal name="PrinterRestarted"> |
1625 | + <arg type="s" name="text" /> |
1626 | + <arg type="s" name="printer_uri" /> |
1627 | + <arg type="s" name="printer_name" /> |
1628 | + <arg type="u" name="printer_state" /> |
1629 | + <arg type="s" name="printer_state_reasons" /> |
1630 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1631 | + </signal> |
1632 | + |
1633 | + <signal name="PrinterStopped"> |
1634 | + <arg type="s" name="text" /> |
1635 | + <arg type="s" name="printer_uri" /> |
1636 | + <arg type="s" name="printer_name" /> |
1637 | + <arg type="u" name="printer_state" /> |
1638 | + <arg type="s" name="printer_state_reasons" /> |
1639 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1640 | + </signal> |
1641 | + |
1642 | + <signal name="PrinterShutdown"> |
1643 | + <arg type="s" name="text" /> |
1644 | + <arg type="s" name="printer_uri" /> |
1645 | + <arg type="s" name="printer_name" /> |
1646 | + <arg type="u" name="printer_state" /> |
1647 | + <arg type="s" name="printer_state_reasons" /> |
1648 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1649 | + </signal> |
1650 | + |
1651 | + <signal name="PrinterStateChanged"> |
1652 | + <arg type="s" name="text" /> |
1653 | + <arg type="s" name="printer_uri" /> |
1654 | + <arg type="s" name="printer_name" /> |
1655 | + <arg type="u" name="printer_state" /> |
1656 | + <arg type="s" name="printer_state_reasons" /> |
1657 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1658 | + </signal> |
1659 | + |
1660 | + <signal name="PrinterFinishingsChanged"> |
1661 | + <arg type="s" name="text" /> |
1662 | + <arg type="s" name="printer_uri" /> |
1663 | + <arg type="s" name="printer_name" /> |
1664 | + <arg type="u" name="printer_state" /> |
1665 | + <arg type="s" name="printer_state_reasons" /> |
1666 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1667 | + </signal> |
1668 | + |
1669 | + <signal name="PrinterMediaChanged"> |
1670 | + <arg type="s" name="text" /> |
1671 | + <arg type="s" name="printer_uri" /> |
1672 | + <arg type="s" name="printer_name" /> |
1673 | + <arg type="u" name="printer_state" /> |
1674 | + <arg type="s" name="printer_state_reasons" /> |
1675 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1676 | + </signal> |
1677 | + |
1678 | + <signal name="JobCreated"> |
1679 | + <arg type="s" name="text" /> |
1680 | + <arg type="s" name="printer_uri" /> |
1681 | + <arg type="s" name="printer_name" /> |
1682 | + <arg type="u" name="printer_state" /> |
1683 | + <arg type="s" name="printer_state_reasons" /> |
1684 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1685 | + <arg type="u" name="job_id" /> |
1686 | + <arg type="u" name="job_state" /> |
1687 | + <arg type="s" name="job_state_reasons" /> |
1688 | + <arg type="s" name="job_name" /> |
1689 | + <arg type="u" name="job_impressions_completed" /> |
1690 | + </signal> |
1691 | + |
1692 | + <signal name="JobCompleted"> |
1693 | + <arg type="s" name="text" /> |
1694 | + <arg type="s" name="printer_uri" /> |
1695 | + <arg type="s" name="printer_name" /> |
1696 | + <arg type="u" name="printer_state" /> |
1697 | + <arg type="s" name="printer_state_reasons" /> |
1698 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1699 | + <arg type="u" name="job_id" /> |
1700 | + <arg type="u" name="job_state" /> |
1701 | + <arg type="s" name="job_state_reasons" /> |
1702 | + <arg type="s" name="job_name" /> |
1703 | + <arg type="u" name="job_impressions_completed" /> |
1704 | + </signal> |
1705 | + |
1706 | + <signal name="JobState"> |
1707 | + <arg type="s" name="text" /> |
1708 | + <arg type="s" name="printer_uri" /> |
1709 | + <arg type="s" name="printer_name" /> |
1710 | + <arg type="u" name="printer_state" /> |
1711 | + <arg type="s" name="printer_state_reasons" /> |
1712 | + <arg type="b" name="printer_is_accepting_jobs" /> |
1713 | + <arg type="u" name="job_id" /> |
1714 | + <arg type="u" name="job_state" /> |
1715 | + <arg type="s" name="job_state_reasons" /> |
1716 | + <arg type="s" name="job_name" /> |
1717 | + <arg type="u" name="job_impressions_completed" /> |
1718 | + </signal> |
1719 | + |
1720 | + </interface> |
1721 | + |
1722 | +</node> |
1723 | + |
1724 | |
1725 | === added file 'notifier/src/printer.h' |
1726 | --- notifier/src/printer.h 1970-01-01 00:00:00 +0000 |
1727 | +++ notifier/src/printer.h 2017-03-20 13:16:02 +0000 |
1728 | @@ -0,0 +1,45 @@ |
1729 | +/* |
1730 | + * Copyright 2016-2017 Canonical Ltd. |
1731 | + * |
1732 | + * This program is free software: you can redistribute it and/or modify it |
1733 | + * under the terms of the GNU General Public License version 3, as published |
1734 | + * by the Free Software Foundation. |
1735 | + * |
1736 | + * This program is distributed in the hope that it will be useful, but |
1737 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1738 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1739 | + * PURPOSE. See the GNU General Public License for more details. |
1740 | + * |
1741 | + * You should have received a copy of the GNU General Public License along |
1742 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1743 | + */ |
1744 | + |
1745 | +#pragma once |
1746 | + |
1747 | +#include <string> |
1748 | + |
1749 | +namespace ubuntu { |
1750 | +namespace printing { |
1751 | +namespace notifier { |
1752 | + |
1753 | + struct Printer { |
1754 | + // State to match ipp_jstate_t from cups.h |
1755 | + typedef enum { |
1756 | + IDLE = 3, |
1757 | + PROCESSING, |
1758 | + STOPPED |
1759 | + } State; |
1760 | + State state = IDLE; |
1761 | + |
1762 | + std::string name; |
1763 | + std::string description; |
1764 | + std::string text; |
1765 | + std::string uri; |
1766 | + std::string state_reasons; |
1767 | + bool accepting_jobs = false; |
1768 | + uint32_t num_jobs = 0; |
1769 | + }; |
1770 | + |
1771 | +} // notifier |
1772 | +} // printing |
1773 | +} // ubuntu |
1774 | |
1775 | === added file 'notifier/src/utils.cpp' |
1776 | --- notifier/src/utils.cpp 1970-01-01 00:00:00 +0000 |
1777 | +++ notifier/src/utils.cpp 2017-03-20 13:16:02 +0000 |
1778 | @@ -0,0 +1,37 @@ |
1779 | +/* |
1780 | + * Copyright 2016-2017 Canonical Ltd. |
1781 | + * |
1782 | + * This program is free software: you can redistribute it and/or modify it |
1783 | + * under the terms of the GNU General Public License version 3, as published |
1784 | + * by the Free Software Foundation. |
1785 | + * |
1786 | + * This program is distributed in the hope that it will be useful, but |
1787 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1788 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1789 | + * PURPOSE. See the GNU General Public License for more details. |
1790 | + * |
1791 | + * You should have received a copy of the GNU General Public License along |
1792 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1793 | + */ |
1794 | + |
1795 | +#include "utils.h" |
1796 | + |
1797 | +namespace ubuntu { |
1798 | +namespace printing { |
1799 | +namespace notifier { |
1800 | + |
1801 | +std::string Utilities::prepend_snap_path(const std::string& path) |
1802 | +{ |
1803 | + auto get_snap_path = []() { |
1804 | + const char* env_snap = getenv("SNAP"); |
1805 | + if (env_snap == nullptr) { |
1806 | + return ""; |
1807 | + } |
1808 | + return env_snap; |
1809 | + }; |
1810 | + return get_snap_path() + path; |
1811 | +} |
1812 | + |
1813 | +} // notifier |
1814 | +} // printing |
1815 | +} // ubuntu |
1816 | |
1817 | === added file 'notifier/src/utils.h' |
1818 | --- notifier/src/utils.h 1970-01-01 00:00:00 +0000 |
1819 | +++ notifier/src/utils.h 2017-03-20 13:16:02 +0000 |
1820 | @@ -0,0 +1,32 @@ |
1821 | +/* |
1822 | + * Copyright 2016-2017 Canonical Ltd. |
1823 | + * |
1824 | + * This program is free software: you can redistribute it and/or modify it |
1825 | + * under the terms of the GNU General Public License version 3, as published |
1826 | + * by the Free Software Foundation. |
1827 | + * |
1828 | + * This program is distributed in the hope that it will be useful, but |
1829 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1830 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1831 | + * PURPOSE. See the GNU General Public License for more details. |
1832 | + * |
1833 | + * You should have received a copy of the GNU General Public License along |
1834 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1835 | + */ |
1836 | + |
1837 | +#pragma once |
1838 | + |
1839 | +#include <string> |
1840 | + |
1841 | +namespace ubuntu { |
1842 | +namespace printing { |
1843 | +namespace notifier { |
1844 | + |
1845 | + class Utilities { |
1846 | + public: |
1847 | + static std::string prepend_snap_path(const std::string& path); |
1848 | + }; |
1849 | + |
1850 | +} // notifier |
1851 | +} // printing |
1852 | +} // ubuntu |
1853 | |
1854 | === added directory 'notifier/tests' |
1855 | === added file 'notifier/tests/CMakeLists.txt' |
1856 | --- notifier/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1857 | +++ notifier/tests/CMakeLists.txt 2017-03-20 13:16:02 +0000 |
1858 | @@ -0,0 +1,28 @@ |
1859 | +find_package(GMock REQUIRED) |
1860 | + |
1861 | +include_directories( |
1862 | + ${CMAKE_SOURCE_DIR}/notifier/src |
1863 | + ${SERVICE_DEPS_INCLUDE_DIRS} |
1864 | +) |
1865 | +link_directories( |
1866 | + ${SERVICE_DEPS_LIBRARY_DIRS} |
1867 | +) |
1868 | + |
1869 | +add_executable(test-${SERVICE_LIB_NAME} |
1870 | + actions-mock.h |
1871 | + client-mock.h |
1872 | + mock-notification.h |
1873 | + test_notify-engine.cpp |
1874 | + test_utils.cpp |
1875 | +) |
1876 | +target_link_libraries(test-${SERVICE_LIB_NAME} |
1877 | + ${SERVICE_LIB_NAME} |
1878 | + ${SERVICE_DEPS_LIBRARIES} |
1879 | + ${CUPS_LIBS} |
1880 | + |
1881 | + ${GTEST_LIBRARIES} |
1882 | + ${GMOCK_LIBRARIES} |
1883 | + |
1884 | + ${CMAKE_THREAD_LIBS_INIT} |
1885 | +) |
1886 | +add_test(test-${SERVICE_LIB_NAME} test-${SERVICE_LIB_NAME}) |
1887 | |
1888 | === added file 'notifier/tests/actions-mock.h' |
1889 | --- notifier/tests/actions-mock.h 1970-01-01 00:00:00 +0000 |
1890 | +++ notifier/tests/actions-mock.h 2017-03-20 13:16:02 +0000 |
1891 | @@ -0,0 +1,42 @@ |
1892 | +/* |
1893 | + * Copyright 2017 Canonical Ltd. |
1894 | + * |
1895 | + * This program is free software: you can redistribute it and/or modify it |
1896 | + * under the terms of the GNU General Public License version 3, as published |
1897 | + * by the Free Software Foundation. |
1898 | + * |
1899 | + * This program is distributed in the hope that it will be useful, but |
1900 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1901 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1902 | + * PURPOSE. See the GNU General Public License for more details. |
1903 | + * |
1904 | + * You should have received a copy of the GNU General Public License along |
1905 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1906 | + */ |
1907 | + |
1908 | +#pragma once |
1909 | + |
1910 | +#include "actions.h" |
1911 | + |
1912 | +#include <gmock/gmock.h> |
1913 | + |
1914 | +namespace ubuntu { |
1915 | +namespace printing { |
1916 | +namespace notifier { |
1917 | + |
1918 | + class MockActions: public Actions |
1919 | + { |
1920 | + public: |
1921 | + MockActions(): |
1922 | + Actions() |
1923 | + { |
1924 | + } |
1925 | + |
1926 | + ~MockActions() = default; |
1927 | + |
1928 | + MOCK_METHOD1(open_settings_app, void(const std::string&)); |
1929 | + }; |
1930 | + |
1931 | +} // notifier |
1932 | +} // printing |
1933 | +} // ubuntu |
1934 | |
1935 | === added file 'notifier/tests/client-mock.h' |
1936 | --- notifier/tests/client-mock.h 1970-01-01 00:00:00 +0000 |
1937 | +++ notifier/tests/client-mock.h 2017-03-20 13:16:02 +0000 |
1938 | @@ -0,0 +1,54 @@ |
1939 | +/* |
1940 | + * Copyright 2016-2017 Canonical Ltd. |
1941 | + * |
1942 | + * This program is free software: you can redistribute it and/or modify it |
1943 | + * under the terms of the GNU General Public License version 3, as published |
1944 | + * by the Free Software Foundation. |
1945 | + * |
1946 | + * This program is distributed in the hope that it will be useful, but |
1947 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1948 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1949 | + * PURPOSE. See the GNU General Public License for more details. |
1950 | + * |
1951 | + * You should have received a copy of the GNU General Public License along |
1952 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1953 | + */ |
1954 | + |
1955 | +#pragma once |
1956 | + |
1957 | +#include "client.h" |
1958 | + |
1959 | +#include <core/signal.h> |
1960 | +#include <gmock/gmock.h> |
1961 | + |
1962 | +namespace ubuntu { |
1963 | +namespace printing { |
1964 | +namespace notifier { |
1965 | + |
1966 | + class MockClient: public Client |
1967 | + { |
1968 | + public: |
1969 | + explicit MockClient(): Client() {} |
1970 | + ~MockClient() = default; |
1971 | + |
1972 | + core::Signal<const Printer&>& printer_state_changed() |
1973 | + { |
1974 | + return m_printer_state_changed; |
1975 | + } |
1976 | + core::Signal<const Job&>& job_state_changed() |
1977 | + { |
1978 | + return m_job_state_changed; |
1979 | + } |
1980 | + |
1981 | + MOCK_METHOD0(create_subscription, void()); |
1982 | + MOCK_METHOD0(renew_subscription, void()); |
1983 | + MOCK_METHOD0(cancel_subscription, void()); |
1984 | + MOCK_METHOD0(refresh, void()); |
1985 | + |
1986 | + core::Signal<const Printer&> m_printer_state_changed; |
1987 | + core::Signal<const Job&> m_job_state_changed; |
1988 | + }; |
1989 | + |
1990 | +} // notifier |
1991 | +} // printing |
1992 | +} // ubuntu |
1993 | |
1994 | === added file 'notifier/tests/mock-notification.h' |
1995 | --- notifier/tests/mock-notification.h 1970-01-01 00:00:00 +0000 |
1996 | +++ notifier/tests/mock-notification.h 2017-03-20 13:16:02 +0000 |
1997 | @@ -0,0 +1,52 @@ |
1998 | +/* |
1999 | + * Copyright 2017 Canonical Ltd. |
2000 | + * |
2001 | + * This program is free software: you can redistribute it and/or modify it |
2002 | + * under the terms of the GNU General Public License version 3, as published |
2003 | + * by the Free Software Foundation. |
2004 | + * |
2005 | + * This program is distributed in the hope that it will be useful, but |
2006 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2007 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2008 | + * PURPOSE. See the GNU General Public License for more details. |
2009 | + * |
2010 | + * You should have received a copy of the GNU General Public License along |
2011 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2012 | + */ |
2013 | + |
2014 | +#include "notification.h" |
2015 | + |
2016 | +#include <core/signal.h> |
2017 | +#include <gmock/gmock.h> |
2018 | + |
2019 | +namespace ubuntu { |
2020 | +namespace printing { |
2021 | +namespace notifier { |
2022 | + |
2023 | +class MockNotification: public Notification |
2024 | +{ |
2025 | + public: |
2026 | + MockNotification(const std::string& summary, const std::string& body, |
2027 | + const std::string& icon_name): |
2028 | + Notification(summary, body, icon_name) |
2029 | + { |
2030 | + } |
2031 | + |
2032 | + ~MockNotification() |
2033 | + { |
2034 | + } |
2035 | + |
2036 | + core::Signal<>& closed() |
2037 | + { |
2038 | + return m_closed; |
2039 | + } |
2040 | + |
2041 | + MOCK_METHOD0(close, void()); |
2042 | + MOCK_METHOD0(show, void()); |
2043 | + |
2044 | + core::Signal<> m_closed; |
2045 | +}; |
2046 | + |
2047 | +} // notifier |
2048 | +} // printing |
2049 | +} // ubuntu |
2050 | |
2051 | === added file 'notifier/tests/test_notify-engine.cpp' |
2052 | --- notifier/tests/test_notify-engine.cpp 1970-01-01 00:00:00 +0000 |
2053 | +++ notifier/tests/test_notify-engine.cpp 2017-03-20 13:16:02 +0000 |
2054 | @@ -0,0 +1,88 @@ |
2055 | +/* |
2056 | + * Copyright 2017 Canonical Ltd. |
2057 | + * |
2058 | + * This program is free software: you can redistribute it and/or modify it |
2059 | + * under the terms of the GNU General Public License version 3, as published |
2060 | + * by the Free Software Foundation. |
2061 | + * |
2062 | + * This program is distributed in the hope that it will be useful, but |
2063 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2064 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2065 | + * PURPOSE. See the GNU General Public License for more details. |
2066 | + * |
2067 | + * You should have received a copy of the GNU General Public License along |
2068 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2069 | + */ |
2070 | + |
2071 | +#include "actions-mock.h" |
2072 | +#include "client-mock.h" |
2073 | +#include "mock-notification.h" |
2074 | +#include "notify-engine.h" |
2075 | + |
2076 | +#include <memory> |
2077 | + |
2078 | +#include <gmock/gmock.h> |
2079 | + |
2080 | +using namespace ubuntu::printing::notifier; |
2081 | +using namespace ::testing; |
2082 | + |
2083 | +class EngineFixture: public ::testing::Test |
2084 | +{ |
2085 | +}; |
2086 | + |
2087 | +class MockEngine: public NotifyEngine |
2088 | +{ |
2089 | +public: |
2090 | + MockEngine(const std::shared_ptr<Client>& client, |
2091 | + const std::shared_ptr<Actions>& actions): |
2092 | + NotifyEngine(client, actions) |
2093 | + { |
2094 | + } |
2095 | + |
2096 | + ~MockEngine() |
2097 | + { |
2098 | + } |
2099 | + |
2100 | + MOCK_METHOD1(build_job_notification, |
2101 | + std::shared_ptr<Notification>(const Job&)); |
2102 | + MOCK_METHOD2(build_printer_notification, |
2103 | + std::shared_ptr<Notification>(const Printer&, |
2104 | + const std::string&)); |
2105 | +}; |
2106 | + |
2107 | +TEST_F(EngineFixture, NotifyEngine) |
2108 | +{ |
2109 | + auto client = std::make_shared<MockClient>(); |
2110 | + auto actions = std::make_shared<MockActions>(); |
2111 | + |
2112 | + // Test for initialization |
2113 | + auto engine = std::make_shared<NotifyEngine>(client, actions); |
2114 | + ASSERT_FALSE(nullptr == engine); |
2115 | + |
2116 | + // Test refresh |
2117 | + EXPECT_CALL(*client, refresh()).Times(1) |
2118 | + .WillOnce(Invoke([&client](){ |
2119 | + // Notify a printer state change |
2120 | + Printer printer; |
2121 | + printer.name = "a-printer"; |
2122 | + printer.description = "A Printer"; |
2123 | + printer.accepting_jobs = true; |
2124 | + printer.num_jobs = 1; |
2125 | + printer.state_reasons = "door-open-report"; |
2126 | + client->m_printer_state_changed(printer); |
2127 | + |
2128 | + // Now with 2 reasons |
2129 | + printer.state_reasons = "door-open-report,something-else"; |
2130 | + client->m_printer_state_changed(printer); |
2131 | + |
2132 | + // Notify a COMPLETED job |
2133 | + Job fake_job; |
2134 | + fake_job.id = 42; |
2135 | + fake_job.state = Job::State::COMPLETED; |
2136 | + fake_job.name = "Life, The Universe, and Everything"; |
2137 | + fake_job.printer.description = "Deep Thought"; |
2138 | + fake_job.printer.name = "deep-thought"; |
2139 | + client->m_job_state_changed(fake_job); |
2140 | + })); |
2141 | + client->refresh(); |
2142 | +} |
2143 | |
2144 | === added file 'notifier/tests/test_utils.cpp' |
2145 | --- notifier/tests/test_utils.cpp 1970-01-01 00:00:00 +0000 |
2146 | +++ notifier/tests/test_utils.cpp 2017-03-20 13:16:02 +0000 |
2147 | @@ -0,0 +1,33 @@ |
2148 | +/* |
2149 | + * Copyright 2016-2017 Canonical Ltd. |
2150 | + * |
2151 | + * This program is free software: you can redistribute it and/or modify it |
2152 | + * under the terms of the GNU General Public License version 3, as published |
2153 | + * by the Free Software Foundation. |
2154 | + * |
2155 | + * This program is distributed in the hope that it will be useful, but |
2156 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2157 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2158 | + * PURPOSE. See the GNU General Public License for more details. |
2159 | + * |
2160 | + * You should have received a copy of the GNU General Public License along |
2161 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2162 | + */ |
2163 | + |
2164 | +#include "utils.h" |
2165 | + |
2166 | +#include <gtest/gtest.h> |
2167 | + |
2168 | +using namespace ubuntu::printing::notifier; |
2169 | + |
2170 | + |
2171 | +TEST(Utilities, testPrependSnapPathSet) { |
2172 | + ASSERT_EQ(0, setenv("SNAP", "/snap", 1)); |
2173 | + EXPECT_EQ("/snap/bar", Utilities::prepend_snap_path("/bar")); |
2174 | + ASSERT_EQ(0, unsetenv("SNAP")); |
2175 | +} |
2176 | + |
2177 | +TEST(Utilities, testPrependSnapPathUnset) { |
2178 | + ASSERT_EQ(0, unsetenv("SNAP")); |
2179 | + EXPECT_EQ("/bar", Utilities::prepend_snap_path("/bar")); |
2180 | +} |
Thanks for submitting this!
It looks like translation pot generation was missed, would you be able to add the parts the parts to po/CMakeLists.txt. It looks that all is required is to add --keyword=_ and provide the list of source files.
I've not yet been successful in creating a notification (on both unity7 and unity8), would you be able to provide instructions for how you are testing this?