Merge lp:~unity-team/unity-notifications/extended-snap-decisions into lp:unity-notifications
- extended-snap-decisions
- Merge into trunk
Proposed by
Michael Zanetti
Status: | Work in progress |
---|---|
Proposed branch: | lp:~unity-team/unity-notifications/extended-snap-decisions |
Merge into: | lp:unity-notifications |
Diff against target: |
1420 lines (+952/-20) 23 files modified
CMakeLists.txt (+5/-1) cmake/FindGIO.cmake (+71/-0) com.canonical.snapdecisions.feedback.xml (+9/-0) create-feedback-dbus-interface-sources.sh (+7/-0) examples/export-model.py (+91/-0) examples/render-model.qml (+137/-0) examples/sd-example-incoming-call.py (+4/-3) examples/test-system-dialog-hint.py (+60/-0) include/Feedback.h (+24/-0) include/FeedbackInterface.h (+56/-0) include/FeedbackInterfaceAdaptor.h (+51/-0) include/Notification.h (+12/-2) include/NotificationModel.h (+6/-3) include/NotificationServer.h (+17/-1) include/notify-backend.h.in (+9/-1) src/CMakeLists.txt (+10/-0) src/Feedback.cpp (+32/-0) src/FeedbackInterface.cpp (+26/-0) src/FeedbackInterfaceAdaptor.cpp (+43/-0) src/Notification.cpp (+32/-0) src/NotificationClient.cpp (+1/-1) src/NotificationModel.cpp (+54/-0) src/NotificationServer.cpp (+195/-8) |
To merge this branch: | bzr merge lp:~unity-team/unity-notifications/extended-snap-decisions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity API Team | Pending | ||
Review via email: mp+183921@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Unmerged revisions
- 185. By Michael Zanetti
-
merge trunk
- 184. By Mirco Müller
-
Add some helping debug-printf()s, make menu-model teardown more robust, change system-dialog-hint example to use a timeout for demo-purposes
- 183. By Mirco Müller
-
Improved the tear-down of menu-models used by extended snap-decisions.
- 182. By Mirco Müller
-
Make DBus-method collect() more robust
- 181. By Mirco Müller
-
Trying to get passing data from frontend to backend working.
- 180. By Mirco Müller
-
Made creation and teardown of menu-model better... act on-demand.
- 179. By Mirco Müller
-
Stripped old code from system-dialog example.
- 178. By Mirco Müller
-
Got linking to gio working... system-dialog hint now exports menu-model via DBus
- 177. By Mirco Müller
-
Make compiling and linking against gio work
- 176. By Mirco Müller
-
Added stand-alone example pulling/rendering menu-model
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-07-02 16:18:31 +0000 |
3 | +++ CMakeLists.txt 2013-09-04 16:15:41 +0000 |
4 | @@ -9,13 +9,15 @@ |
5 | message(FATAL_ERROR "In-tree build attempt detected, aborting. Set your build dir outside your source dir, delete CMakeCache.txt from source root and try again.") |
6 | endif() |
7 | |
8 | + |
9 | option(basic_warnings "Basic compiler warnings." ON) |
10 | option(build_tools "Build developer tools." OFF) |
11 | option(private_dbus "Use private dbus namespace to prevent clashes during development." OFF) |
12 | |
13 | include(cmake/coverage.cmake) |
14 | +include(cmake/FindGIO.cmake) |
15 | include(FindPkgConfig) |
16 | -include (GNUInstallDirs) |
17 | +include(GNUInstallDirs) |
18 | |
19 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x") |
20 | add_definitions(-DQT_NO_KEYWORDS) |
21 | @@ -32,6 +34,8 @@ |
22 | # Workaround for https://bugreports.qt-project.org/browse/QTBUG-29987 |
23 | set(QT_IMPORTS_DIR "${CMAKE_INSTALL_LIBDIR}/qt5/qml") |
24 | |
25 | +include_directories(${GIO_INCLUDE_DIR}) |
26 | + |
27 | include_directories(include) |
28 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) |
29 | add_subdirectory(include) |
30 | |
31 | === added file 'cmake/FindGIO.cmake' |
32 | --- cmake/FindGIO.cmake 1970-01-01 00:00:00 +0000 |
33 | +++ cmake/FindGIO.cmake 2013-09-04 16:15:41 +0000 |
34 | @@ -0,0 +1,71 @@ |
35 | +# - Try to find the GIO libraries |
36 | +# Once done this will define |
37 | +# |
38 | +# GIO_FOUND - system has GIO |
39 | +# GIO_INCLUDE_DIR - the GIO include directory |
40 | +# GIO_LIBRARIES - GIO library |
41 | +# |
42 | +# Copyright (c) 2010 Dario Freddi <drf@kde.org> |
43 | +# |
44 | +# Redistribution and use is allowed according to the terms of the BSD license. |
45 | +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. |
46 | + |
47 | +if(GIO_INCLUDE_DIR AND GIO_LIBRARIES) |
48 | + # Already in cache, be silent |
49 | + set(GIO_FIND_QUIETLY TRUE) |
50 | +endif(GIO_INCLUDE_DIR AND GIO_LIBRARIES) |
51 | + |
52 | +if (NOT WIN32) |
53 | + include(UsePkgConfig) |
54 | + pkgconfig(gio-2.0 _LibGIOIncDir _LibGIOLinkDir _LibGIOLinkFlags _LibGIOCflags) |
55 | +endif(NOT WIN32) |
56 | + |
57 | +MESSAGE(STATUS "gio include dir: ${_LibGIOIncDir}") |
58 | + |
59 | +# first try without default paths to respect PKG_CONFIG_PATH |
60 | + |
61 | +find_path(GIO_MAIN_INCLUDE_DIR glib.h |
62 | + PATH_SUFFIXES glib-2.0 |
63 | + PATHS ${_LibGIOIncDir} |
64 | + NO_DEFAULT_PATH) |
65 | + |
66 | +find_path(GIO_MAIN_INCLUDE_DIR glib.h |
67 | + PATH_SUFFIXES glib-2.0 |
68 | + PATHS ${_LibGIOIncDir} ) |
69 | + |
70 | +MESSAGE(STATUS "found gio main include dir: ${GIO_MAIN_INCLUDE_DIR}") |
71 | + |
72 | +# search the glibconfig.h include dir under the same root where the library is found |
73 | +find_library(GIO_LIBRARIES |
74 | + NAMES gio-2.0 |
75 | + PATHS ${_LibGIOLinkDir} |
76 | + NO_DEFAULT_PATH) |
77 | + |
78 | +find_library(GIO_LIBRARIES |
79 | + NAMES gio-2.0 |
80 | + PATHS ${_LibGIOLinkDir}) |
81 | + |
82 | + |
83 | +get_filename_component(GIOLibDir "${GIO_LIBRARIES}" PATH) |
84 | + |
85 | +find_path(GIO_INTERNAL_INCLUDE_DIR glibconfig.h |
86 | + PATH_SUFFIXES glib-2.0/include |
87 | + PATHS ${_LibGIOIncDir} "${GIOLibDir}" ${CMAKE_SYSTEM_LIBRARY_PATH} |
88 | + NO_DEFAULT_PATH) |
89 | + |
90 | +find_path(GIO_INTERNAL_INCLUDE_DIR glibconfig.h |
91 | + PATH_SUFFIXES glib-2.0/include |
92 | + PATHS ${_LibGIOIncDir} "${GIOLibDir}" ${CMAKE_SYSTEM_LIBRARY_PATH}) |
93 | + |
94 | +set(GIO_INCLUDE_DIR "${GIO_MAIN_INCLUDE_DIR}") |
95 | + |
96 | +# not sure if this include dir is optional or required |
97 | +# for now it is optional |
98 | +if(GIO_INTERNAL_INCLUDE_DIR) |
99 | + set(GIO_INCLUDE_DIR ${GIO_INCLUDE_DIR} "${GIO_INTERNAL_INCLUDE_DIR}") |
100 | +endif(GIO_INTERNAL_INCLUDE_DIR) |
101 | + |
102 | +include(FindPackageHandleStandardArgs) |
103 | +find_package_handle_standard_args(GIO DEFAULT_MSG GIO_LIBRARIES GIO_MAIN_INCLUDE_DIR) |
104 | + |
105 | +mark_as_advanced(GIO_INCLUDE_DIR GIO_LIBRARIES) |
106 | |
107 | === added file 'com.canonical.snapdecisions.feedback.xml' |
108 | --- com.canonical.snapdecisions.feedback.xml 1970-01-01 00:00:00 +0000 |
109 | +++ com.canonical.snapdecisions.feedback.xml 2013-09-04 16:15:41 +0000 |
110 | @@ -0,0 +1,9 @@ |
111 | +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
112 | +<node> |
113 | + <interface name="com.canonical.snapdecisions.feedback"> |
114 | + <method name="collect"> |
115 | + <arg type="as" direction="out"/> |
116 | + <arg name="id" type="u" direction="in"/> |
117 | + </method> |
118 | + </interface> |
119 | +</node> |
120 | |
121 | === added file 'create-feedback-dbus-interface-sources.sh' |
122 | --- create-feedback-dbus-interface-sources.sh 1970-01-01 00:00:00 +0000 |
123 | +++ create-feedback-dbus-interface-sources.sh 2013-09-04 16:15:41 +0000 |
124 | @@ -0,0 +1,7 @@ |
125 | +#!/bin/sh |
126 | + |
127 | +XML_FILE=com.canonical.snapdecisions.feedback.xml |
128 | + |
129 | +qdbuscpp2xml -M -s include/Feedback.h -o $XML_FILE |
130 | +qdbusxml2cpp -v -c FeedbackInterface -p include/FeedbackInterface.h:src/FeedbackInterface.cpp $XML_FILE |
131 | +qdbusxml2cpp -c FeedbackInterfaceAdaptor -a include/FeedbackInterfaceAdaptor.h:src/FeedbackInterfaceAdaptor.cpp $XML_FILE |
132 | |
133 | === added file 'examples/export-model.py' |
134 | --- examples/export-model.py 1970-01-01 00:00:00 +0000 |
135 | +++ examples/export-model.py 2013-09-04 16:15:41 +0000 |
136 | @@ -0,0 +1,91 @@ |
137 | +#!/usr/bin/env python3 |
138 | + |
139 | +import sys |
140 | + |
141 | +from gi.repository import Gio, GLib, Notify |
142 | + |
143 | +BUS_NAME = 'com.canonical.snapdecisions.systemdialog' |
144 | +BUS_OBJECT_PATH = '/com/canonical/snapdecisions/systemdialog' |
145 | + |
146 | +def activate_cancel(action, data): |
147 | + print('Called cancel (%s)' % action.get_name()) |
148 | + |
149 | +def activate_connect(action, data): |
150 | + print('Called connect (%s)' % action.get_name()) |
151 | + print('passed: %s' % data) |
152 | + |
153 | +def bus_acquired(bus, name): |
154 | + menu = Gio.Menu() |
155 | + |
156 | + item = Gio.MenuItem.new('Connect to \"Calamari\"', None) |
157 | + item.set_attribute_value('x-canonical-type', GLib.Variant.new_string('com.canonical.snapdecision.title')) |
158 | + menu.append_item(item) |
159 | + |
160 | + item2 = Gio.MenuItem.new('Login name:', None) |
161 | + item2.set_attribute_value('x-canonical-type', GLib.Variant.new_string('com.canonical.snapdecision.textfield')) |
162 | + item2.set_attribute_value('x-echo-mode-password', GLib.Variant.new_boolean(False)) |
163 | + menu.append_item(item2) |
164 | + |
165 | + item3 = Gio.MenuItem.new('Password:', None) |
166 | + item3.set_attribute_value('x-canonical-type', GLib.Variant.new_string('com.canonical.snapdecision.textfield')) |
167 | + item3.set_attribute_value('x-echo-mode-password', GLib.Variant.new_boolean(True)) |
168 | + menu.append_item(item3) |
169 | + |
170 | + item4 = Gio.MenuItem.new('Cancel', None) |
171 | + item4.set_attribute_value('x-canonical-type', GLib.Variant.new_string('com.canonical.snapdecision.button')) |
172 | + item4.set_attribute_value('x-tint-button', GLib.Variant.new_boolean(False)) |
173 | + menu.append_item(item4) |
174 | + |
175 | + item5 = Gio.MenuItem.new('Connect', None) |
176 | + item5.set_attribute_value('x-canonical-type', GLib.Variant.new_string('com.canonical.snapdecision.button')) |
177 | + item5.set_attribute_value('x-tint-button', GLib.Variant.new_boolean(True)) |
178 | + menu.append_item(item5) |
179 | + |
180 | + actions = Gio.SimpleActionGroup.new() |
181 | + cancel = Gio.SimpleAction.new("cancel", None) |
182 | + actions.insert(cancel) |
183 | + cancel.connect('activate', activate_cancel) |
184 | + connect = Gio.SimpleAction.new("connect", None) #GLib.VariantType.new("ss")) |
185 | + actions.insert(connect) |
186 | + connect.connect('activate', activate_connect) |
187 | + bus.export_action_group(BUS_OBJECT_PATH, actions) |
188 | + |
189 | + bus.export_menu_model(BUS_OBJECT_PATH, menu) |
190 | + |
191 | +def quit_callback(notification): |
192 | + GLib.MainLoop().quit() |
193 | + |
194 | +def connect_callback(notification, action, data): |
195 | + if action == "connect_id": |
196 | + print("Triggering Connect") |
197 | + else: |
198 | + print("That should not have happened (connect_id)!") |
199 | + |
200 | +def cancel_callback(notification, action, data): |
201 | + if action == "cancel_id": |
202 | + print("Triggering Cancel") |
203 | + else: |
204 | + print("That should not have happened (cancel_id)!") |
205 | + |
206 | +def pushNotification (): |
207 | + n = Notify.Notification.new("Connect to \"Calamari\"", "dummy", "totem"); |
208 | + n.add_action ("connect_id", "Connect", connect_callback, None, None) |
209 | + n.add_action ("cancel_id", "Cancel", cancel_callback, None, None) |
210 | + n.set_hint_string ("x-canonical-snap-decisions", "true") |
211 | + n.set_hint_string ("x-canonical-private-button-tint", "true") |
212 | + variant_password = GLib.Variant('as', ["Login name:", "Password:"]) |
213 | + variant_listview = GLib.Variant('as', ["wifi-medium", "BTOpenZone", "sec-wep", "wifi-low", "Calamari", "sec-wpa"]) |
214 | + #variant_feedback = GLib.Variant('as', [DBUS_NAME, DBUS_PATH, DBUS_METHOD]) |
215 | + #n.set_hint ("x-canonical-private-system-dialog-password", variant_password) |
216 | + #n.set_hint ("x-canonical-private-system-dialog-listview", variant_listview) |
217 | + #n.set_hint ("x-canonical-private-system-dialog-feedback", variant_feedback) |
218 | + n.set_hint_string ("x-canonical-private-system-dialog", "user-auth") |
219 | + return n |
220 | + |
221 | +if __name__ == '__main__': |
222 | + Gio.bus_own_name(Gio.BusType.SESSION, BUS_NAME, 0, bus_acquired, None, None) |
223 | + #Notify.init("password-dialog-test") |
224 | + #n = pushNotification() |
225 | + #n.connect('closed', quit_callback) |
226 | + #n.show () |
227 | + GLib.MainLoop().run() |
228 | |
229 | === added file 'examples/render-model.qml' |
230 | --- examples/render-model.qml 1970-01-01 00:00:00 +0000 |
231 | +++ examples/render-model.qml 2013-09-04 16:15:41 +0000 |
232 | @@ -0,0 +1,137 @@ |
233 | +import QtQuick 2.0 |
234 | +import QMenuModel 0.1 |
235 | +import Ubuntu.Components 0.1 |
236 | + |
237 | +Rectangle { |
238 | + id: root |
239 | + |
240 | + width: units.gu(40) |
241 | + height: units.gu(71) |
242 | + |
243 | + Image { |
244 | + id: background |
245 | + |
246 | + source: "/home/mirco/Desktop/Bilder/Fotos/wheelie-kurve.jpg" |
247 | + fillMode: Image.PreserveAspectCrop |
248 | + } |
249 | + |
250 | + UnityMenuModel { |
251 | + id: menu |
252 | + |
253 | + busName: "com.canonical.snapdecisions.systemdialog" |
254 | + actions: { "connect": "/com/canonical/snapdecision/systemdialog" } |
255 | + menuObjectPath: "/com/canonical/snapdecisions/systemdialog" |
256 | + } |
257 | + |
258 | + UbuntuShape { |
259 | + color: Qt.rgba(0, 0, 0, 0.85) |
260 | + |
261 | + anchors { |
262 | + left: parent.left |
263 | + right: parent.right |
264 | + top: parent.top |
265 | + bottom: parent.bottom |
266 | + margins: units.gu(2) |
267 | + } |
268 | + |
269 | + ListView { |
270 | + id: listview |
271 | + |
272 | + spacing: units.gu(2) |
273 | + |
274 | + property string login |
275 | + property string passwd |
276 | + |
277 | + anchors { |
278 | + fill: parent |
279 | + margins: units.gu(2) |
280 | + } |
281 | + |
282 | + model: menu |
283 | + |
284 | + delegate: Loader { |
285 | + sourceComponent: { |
286 | + if (type == "com.canonical.snapdecision.title") { |
287 | + return title |
288 | + } |
289 | + else if (type == "com.canonical.snapdecision.textfield") { |
290 | + listview.model.loadExtendedAttributes(index, {'x-echo-mode-password': 'bool'}); |
291 | + return textfield |
292 | + } |
293 | + else if (type == "com.canonical.snapdecision.button") { |
294 | + listview.model.loadExtendedAttributes(index, {'x-tint-button': 'bool'}); |
295 | + return button |
296 | + } |
297 | + } |
298 | + |
299 | + Component { |
300 | + id: title |
301 | + |
302 | + Label { |
303 | + id: titleLabel |
304 | + |
305 | + anchors.horizontalCenter: parent.horizontalCenter |
306 | + fontSize: "medium" |
307 | + font.bold: true |
308 | + color: "white" |
309 | + text: label |
310 | + } |
311 | + } |
312 | + |
313 | + Component { |
314 | + id: textfield |
315 | + |
316 | + Column { |
317 | + spacing: units.gu(.5) |
318 | + anchors { |
319 | + left: parent.left |
320 | + right: parent.right |
321 | + } |
322 | + |
323 | + Label { |
324 | + anchors.left: parent.left |
325 | + |
326 | + fontSize: "medium" |
327 | + color: "white" |
328 | + text: label |
329 | + } |
330 | + |
331 | + TextField { |
332 | + echoMode: ext.xEchoModePassword ? TextInput.Password : TextInput.Normal |
333 | + onAccepted: { |
334 | + if(echoMode == TextInput.Password) { |
335 | + listview.passwd = text |
336 | + } else { |
337 | + listview.login = text |
338 | + } |
339 | + } |
340 | + } |
341 | + } |
342 | + } |
343 | + |
344 | + Component { |
345 | + id: button |
346 | + |
347 | + Button { |
348 | + text: label |
349 | + gradient: ext.xTintButton ? UbuntuColors.orangeGradient : UbuntuColors.greyGradient |
350 | + onClicked: { |
351 | + print("Clicked on \"",label,"\"") |
352 | + print("Login:", listview.login) |
353 | + print("Password:", listview.passwd) |
354 | + print("") |
355 | + model.action.activate() |
356 | + //if(model.action.name == "button.cancel") { |
357 | + // model.action.activate(index) |
358 | + //} |
359 | + //if(model.action.name == "button.connect") { |
360 | + // model.target = listview.login |
361 | + // model.action.activate() |
362 | + //} |
363 | + } |
364 | + } |
365 | + } |
366 | + } |
367 | + } |
368 | + } |
369 | +} |
370 | |
371 | === modified file 'examples/sd-example-incoming-call.py' |
372 | --- examples/sd-example-incoming-call.py 2013-05-17 14:57:48 +0000 |
373 | +++ examples/sd-example-incoming-call.py 2013-09-04 16:15:41 +0000 |
374 | @@ -74,12 +74,13 @@ |
375 | # always comes first! |
376 | n.add_action ("action_accept", "Accept", action_accept); |
377 | n.add_action ("action_decline_1", "Decline", action_decline_1); |
378 | - #n.add_action ("action_decline_2", "\"Can't talk now, what's up?\"", action_decline_2); |
379 | - #n.add_action ("action_decline_3", "\"I call you back.\"", action_decline_3); |
380 | - #n.add_action ("action_decline_4", "Send custom message...", action_decline_4); |
381 | + n.add_action ("action_decline_2", "\"Can't talk now, what's up?\"", action_decline_2); |
382 | + n.add_action ("action_decline_3", "\"I call you back.\"", action_decline_3); |
383 | + n.add_action ("action_decline_4", "Send custom message...", action_decline_4); |
384 | |
385 | # indicate to the notification-daemon, that we want to use snap-decisions |
386 | n.set_hint_string ("x-canonical-snap-decisions", "true"); |
387 | + n.set_hint_string ("x-canonical-private-button-tint", "true"); |
388 | n.set_hint_string ("x-canonical-secondary-icon", os.getcwd() + "/assets/icon_phone.png"); |
389 | |
390 | n.show () |
391 | |
392 | === added file 'examples/test-system-dialog-hint.py' |
393 | --- examples/test-system-dialog-hint.py 1970-01-01 00:00:00 +0000 |
394 | +++ examples/test-system-dialog-hint.py 2013-09-04 16:15:41 +0000 |
395 | @@ -0,0 +1,60 @@ |
396 | +#!/usr/bin/python |
397 | + |
398 | +import os |
399 | +import sys |
400 | +from gi.repository import Gio, GLib, Notify |
401 | +import dbus |
402 | +import dbus.service |
403 | + |
404 | +DBUS_NAME="com.canonical.snapdecisions.feedback" |
405 | +DBUS_PATH="/com/canonical/snapdecisions/feedback" |
406 | +DBUS_METHOD="collect" |
407 | + |
408 | +def collect_feedback(id): |
409 | + print "collect_feedback() called" |
410 | + interface = dbus.Interface(dbus.SessionBus().get_object(DBUS_NAME, DBUS_PATH), DBUS_NAME) |
411 | + result = interface.collect(id) |
412 | + if len(result) != 0: |
413 | + print "Got reply: " |
414 | + for index in range(len(result)): |
415 | + print "\t%s" % result[index] |
416 | + #return False |
417 | + else: |
418 | + print "result was empty" |
419 | + return True |
420 | + |
421 | +def quit_callback(notification): |
422 | + print "quit_callback() called" |
423 | + loop.quit() |
424 | + |
425 | +def connect_callback(notification, action, data): |
426 | + print "connect_callback() called" |
427 | + if action == "connect_id": |
428 | + print "Triggering Connect" |
429 | + #collect_feedback(notification.get_property("id")) |
430 | + else: |
431 | + print "That should not have happened (connect_id)!" |
432 | + |
433 | +def cancel_callback(notification, action, data): |
434 | + if action == "cancel_id": |
435 | + print "Triggering Cancel" |
436 | + else: |
437 | + print "That should not have happened (cancel_id)!" |
438 | + |
439 | +def pushNotification (): |
440 | + n = Notify.Notification.new("Connect to \"Calamari\"", "dummy", "totem"); |
441 | + n.add_action ("connect_id", "Connect", connect_callback, None, None) |
442 | + n.add_action ("cancel_id", "Cancel", cancel_callback, None, None) |
443 | + n.set_hint_string ("x-canonical-snap-decisions", "true") |
444 | + n.set_hint_string ("x-canonical-private-button-tint", "true") |
445 | + #n.set_hint_string ("x-canonical-private-system-dialog", "user-auth") |
446 | + n.set_hint_string ("x-canonical-private-system-dialog", "wifi-auth") |
447 | + return n |
448 | + |
449 | +loop = GLib.MainLoop.new(None, False) |
450 | +Notify.init("password-dialog-test") |
451 | +n = pushNotification() |
452 | +n.connect('closed', quit_callback) |
453 | +n.show () |
454 | +GLib.timeout_add(1000, collect_feedback, n.get_property("id")) |
455 | +loop.run() |
456 | |
457 | === added file 'include/Feedback.h' |
458 | --- include/Feedback.h 1970-01-01 00:00:00 +0000 |
459 | +++ include/Feedback.h 2013-09-04 16:15:41 +0000 |
460 | @@ -0,0 +1,24 @@ |
461 | +#include <QString> |
462 | +#include <QObject> |
463 | +#include <QtDBus> |
464 | + |
465 | +#define FEEDBACK_DBUS_NAME "com.canonical.snapdecisions.feedback" |
466 | +#define FEEDBACK_DBUS_PATH "/com/canonical/snapdecisions/feedback" |
467 | +#define FEEDBACK_DBUS_METHOD "collect" |
468 | + |
469 | +class NotificationModel; |
470 | + |
471 | +class Feedback : public QObject |
472 | +{ |
473 | + Q_OBJECT |
474 | + Q_CLASSINFO("D-Bus Interface", FEEDBACK_DBUS_NAME) |
475 | + |
476 | + public: |
477 | + Feedback(NotificationModel& m, QObject* parent = 0); |
478 | + |
479 | + public Q_SLOTS: |
480 | + QStringList collect(const unsigned int id); |
481 | + |
482 | + private: |
483 | + NotificationModel& model; |
484 | +}; |
485 | |
486 | === added file 'include/FeedbackInterface.h' |
487 | --- include/FeedbackInterface.h 1970-01-01 00:00:00 +0000 |
488 | +++ include/FeedbackInterface.h 2013-09-04 16:15:41 +0000 |
489 | @@ -0,0 +1,56 @@ |
490 | +/* |
491 | + * This file was generated by qdbusxml2cpp version 0.8 |
492 | + * Command line was: qdbusxml2cpp -v -c FeedbackInterface -p include/FeedbackInterface.h:src/FeedbackInterface.cpp com.canonical.snapdecisions.feedback.xml |
493 | + * |
494 | + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
495 | + * |
496 | + * This is an auto-generated file. |
497 | + * Do not edit! All changes made to it will be lost. |
498 | + */ |
499 | + |
500 | +#ifndef FEEDBACKINTERFACE_H_1376659323 |
501 | +#define FEEDBACKINTERFACE_H_1376659323 |
502 | + |
503 | +#include <QtCore/QObject> |
504 | +#include <QtCore/QByteArray> |
505 | +#include <QtCore/QList> |
506 | +#include <QtCore/QMap> |
507 | +#include <QtCore/QString> |
508 | +#include <QtCore/QStringList> |
509 | +#include <QtCore/QVariant> |
510 | +#include <QtDBus/QtDBus> |
511 | + |
512 | +/* |
513 | + * Proxy class for interface com.canonical.snapdecisions.feedback |
514 | + */ |
515 | +class FeedbackInterface: public QDBusAbstractInterface |
516 | +{ |
517 | + Q_OBJECT |
518 | +public: |
519 | + static inline const char *staticInterfaceName() |
520 | + { return "com.canonical.snapdecisions.feedback"; } |
521 | + |
522 | +public: |
523 | + FeedbackInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); |
524 | + |
525 | + ~FeedbackInterface(); |
526 | + |
527 | +public Q_SLOTS: // METHODS |
528 | + inline QDBusPendingReply<QStringList> collect(uint id) |
529 | + { |
530 | + QList<QVariant> argumentList; |
531 | + argumentList << QVariant::fromValue(id); |
532 | + return asyncCallWithArgumentList(QLatin1String("collect"), argumentList); |
533 | + } |
534 | + |
535 | +Q_SIGNALS: // SIGNALS |
536 | +}; |
537 | + |
538 | +namespace com { |
539 | + namespace canonical { |
540 | + namespace snapdecisions { |
541 | + typedef ::FeedbackInterface feedback; |
542 | + } |
543 | + } |
544 | +} |
545 | +#endif |
546 | |
547 | === added file 'include/FeedbackInterfaceAdaptor.h' |
548 | --- include/FeedbackInterfaceAdaptor.h 1970-01-01 00:00:00 +0000 |
549 | +++ include/FeedbackInterfaceAdaptor.h 2013-09-04 16:15:41 +0000 |
550 | @@ -0,0 +1,51 @@ |
551 | +/* |
552 | + * This file was generated by qdbusxml2cpp version 0.8 |
553 | + * Command line was: qdbusxml2cpp -c FeedbackInterfaceAdaptor -a include/FeedbackInterfaceAdaptor.h:src/FeedbackInterfaceAdaptor.cpp com.canonical.snapdecisions.feedback.xml |
554 | + * |
555 | + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
556 | + * |
557 | + * This is an auto-generated file. |
558 | + * This file may have been hand-edited. Look for HAND-EDIT comments |
559 | + * before re-generating it. |
560 | + */ |
561 | + |
562 | +#ifndef FEEDBACKINTERFACEADAPTOR_H_1376659323 |
563 | +#define FEEDBACKINTERFACEADAPTOR_H_1376659323 |
564 | + |
565 | +#include <QtCore/QObject> |
566 | +#include <QtDBus/QtDBus> |
567 | +QT_BEGIN_NAMESPACE |
568 | +class QByteArray; |
569 | +template<class T> class QList; |
570 | +template<class Key, class Value> class QMap; |
571 | +class QString; |
572 | +class QStringList; |
573 | +class QVariant; |
574 | +QT_END_NAMESPACE |
575 | + |
576 | +/* |
577 | + * Adaptor class for interface com.canonical.snapdecisions.feedback |
578 | + */ |
579 | +class FeedbackInterfaceAdaptor: public QDBusAbstractAdaptor |
580 | +{ |
581 | + Q_OBJECT |
582 | + Q_CLASSINFO("D-Bus Interface", "com.canonical.snapdecisions.feedback") |
583 | + Q_CLASSINFO("D-Bus Introspection", "" |
584 | +" <interface name=\"com.canonical.snapdecisions.feedback\">\n" |
585 | +" <method name=\"collect\">\n" |
586 | +" <arg direction=\"out\" type=\"as\"/>\n" |
587 | +" <arg direction=\"in\" type=\"u\" name=\"id\"/>\n" |
588 | +" </method>\n" |
589 | +" </interface>\n" |
590 | + "") |
591 | +public: |
592 | + FeedbackInterfaceAdaptor(QObject *parent); |
593 | + virtual ~FeedbackInterfaceAdaptor(); |
594 | + |
595 | +public: // PROPERTIES |
596 | +public Q_SLOTS: // METHODS |
597 | + QStringList collect(uint id); |
598 | +Q_SIGNALS: // SIGNALS |
599 | +}; |
600 | + |
601 | +#endif |
602 | |
603 | === modified file 'include/Notification.h' |
604 | --- include/Notification.h 2013-09-03 12:41:34 +0000 |
605 | +++ include/Notification.h 2013-09-04 16:15:41 +0000 |
606 | @@ -37,6 +37,7 @@ |
607 | Q_ENUMS(Urgency) |
608 | Q_ENUMS(Type) |
609 | Q_ENUMS(Hint) |
610 | + Q_ENUMS(SystemDialog) |
611 | Q_PROPERTY(QString summary READ getSummary WRITE setSummary NOTIFY summaryChanged) |
612 | Q_PROPERTY(QString body READ getBody WRITE setBody NOTIFY bodyChanged) |
613 | Q_PROPERTY(NotificationID id READ getID) |
614 | @@ -46,6 +47,8 @@ |
615 | Q_PROPERTY(Urgency urgency READ getUrgency WRITE setUrgency NOTIFY urgencyChanged) |
616 | Q_PROPERTY(Type type READ getType WRITE setType NOTIFY typeChanged) |
617 | Q_PROPERTY(ActionModel* actions READ getActions NOTIFY actionsChanged) |
618 | + Q_PROPERTY(QStringList entries READ getEntries WRITE setEntries NOTIFY entriesChanged) |
619 | + Q_PROPERTY(SystemDialog systemDialog READ getSystemDialog NOTIFY systemDialogChanged) |
620 | Q_PROPERTY(int hints READ getHints WRITE setHints NOTIFY hintsChanged) |
621 | |
622 | private: |
623 | @@ -53,8 +56,9 @@ |
624 | |
625 | public: |
626 | enum Urgency { Low, Normal, Critical }; |
627 | - enum Type { Confirmation, Ephemeral, Interactive, SnapDecision, PlaceHolder }; |
628 | - enum Hint { None = 0, ButtonTint = 1 << 1, IconOnly = 1 << 2 }; |
629 | + enum Type { Confirmation, Ephemeral, Interactive, SnapDecision, Dialog, PlaceHolder }; |
630 | + enum Hint { None = 0, ButtonTint = 1 << 1, IconOnly = 1 << 2, Truncation = 1 << 3, Sync = 1 << 4 }; |
631 | + enum SystemDialog { WifiSelect, WifiAuth, UserAuth }; |
632 | |
633 | Q_SIGNALS: |
634 | void bodyChanged(QString text); |
635 | @@ -64,6 +68,8 @@ |
636 | void valueChanged(int value); |
637 | void urgencyChanged(Urgency urg); |
638 | void typeChanged(Type type); |
639 | + void entriesChanged(QStringList entries); |
640 | + void systemDialogChanged(SystemDialog systemDialog); |
641 | void actionsChanged(QStringList actions); |
642 | void hintsChanged(int hints); |
643 | |
644 | @@ -109,8 +115,12 @@ |
645 | void setUrgency(Urgency urg); |
646 | Type getType() const; |
647 | void setType(Type type); |
648 | + QStringList getEntries() const; |
649 | + void setEntries(QStringList entries); |
650 | ActionModel* getActions() const; |
651 | void setActions(QStringList actions); |
652 | + SystemDialog getSystemDialog() const; |
653 | + void setSystemDialog(SystemDialog systemDialog); |
654 | |
655 | int getHints() const; |
656 | void setHints(int hints); |
657 | |
658 | === modified file 'include/NotificationModel.h' |
659 | --- include/NotificationModel.h 2013-09-03 12:41:34 +0000 |
660 | +++ include/NotificationModel.h 2013-09-04 16:15:41 +0000 |
661 | @@ -39,9 +39,11 @@ |
662 | RoleValue = Qt::UserRole + 6, |
663 | RoleIcon = Qt::UserRole + 7, |
664 | RoleSecondaryIcon = Qt::UserRole + 8, |
665 | - RoleActions = Qt::UserRole + 9, |
666 | - RoleHints = Qt::UserRole + 10, |
667 | - RoleNotification = Qt::UserRole + 11 |
668 | + RoleEntries = Qt::UserRole + 9, |
669 | + RoleActions = Qt::UserRole + 10, |
670 | + RoleHints = Qt::UserRole + 11, |
671 | + RoleNotification = Qt::UserRole + 12, |
672 | + RoleSystemDialog = Qt::UserRole + 13 |
673 | }; |
674 | |
675 | class NotificationModel : public QAbstractListModel { |
676 | @@ -96,6 +98,7 @@ |
677 | void insertEphemeral(QSharedPointer<Notification> n); |
678 | void insertConfirmation(QSharedPointer<Notification> n); |
679 | void insertInteractive(QSharedPointer<Notification> n); |
680 | + void insertDialog(QSharedPointer<Notification> n); |
681 | void insertSnap(QSharedPointer<Notification> n); |
682 | void insertToVisible(QSharedPointer<Notification> n, int location=-1); |
683 | void deleteFromVisible(int loc); |
684 | |
685 | === modified file 'include/NotificationServer.h' |
686 | --- include/NotificationServer.h 2013-09-03 12:41:34 +0000 |
687 | +++ include/NotificationServer.h 2013-09-04 16:15:41 +0000 |
688 | @@ -20,6 +20,8 @@ |
689 | #ifndef NOTIFICATIONSERVER_H |
690 | #define NOTIFICATIONSERVER_H |
691 | |
692 | +#include <gio/gio.h> |
693 | + |
694 | #include "notify-backend.h" |
695 | |
696 | /* http://www.galago-project.org/specs/notification/0.9/x408.html#commands |
697 | @@ -72,11 +74,25 @@ |
698 | void ActionInvoked(unsigned int id, QString action_key); |
699 | void dataChanged(unsigned int id); |
700 | |
701 | +public: |
702 | + GDBusConnection* wifiAuthConnection; |
703 | + unsigned int wifiAuthBusName; |
704 | + unsigned int wifiAuthModel; |
705 | + GDBusConnection* wifiSelectConnection; |
706 | + unsigned int wifiSelectBusName; |
707 | + unsigned int wifiSelectModel; |
708 | + GDBusConnection* userAuthConnection; |
709 | + unsigned int userAuthBusName; |
710 | + unsigned int userAuthModel; |
711 | + |
712 | private: |
713 | + void exportWifiAuthModel(); |
714 | + void exportWifiSelectModel(); |
715 | + void exportUserAuthModel(); |
716 | + void teardownMenuModels(); |
717 | Notification* buildNotification(NotificationID id, const Hints &hints); |
718 | NotificationModel &model; |
719 | unsigned int idCounter; |
720 | - |
721 | }; |
722 | |
723 | #endif |
724 | |
725 | === modified file 'include/notify-backend.h.in' |
726 | --- include/notify-backend.h.in 2013-09-03 12:41:34 +0000 |
727 | +++ include/notify-backend.h.in 2013-09-04 16:15:41 +0000 |
728 | @@ -55,9 +55,17 @@ |
729 | #define DBUS_PATH "/org/freedesktop/Notifications" |
730 | #endif |
731 | |
732 | +#define SYSTEM_DIALOG_TYPE_WIFI_AUTH "wifi-auth" |
733 | +#define SYSTEM_DIALOG_TYPE_WIFI_SELECT "wifi-select" |
734 | +#define SYSTEM_DIALOG_TYPE_USER_AUTH "user-auth" |
735 | + |
736 | #define URGENCY_HINT "urgency" |
737 | -#define SYNCH_HINT "x-canonical-private-synchronous" |
738 | +#define SYNC_HINT "x-canonical-private-synchronous" |
739 | #define SNAP_HINT "x-canonical-snap-decisions" |
740 | +#define DIALOG_HINT "x-canonical-private-system-dialog" |
741 | +#define DIALOG_PASSWORD_HINT "x-canonical-private-system-dialog-password" |
742 | +#define DIALOG_LISTVIEW_HINT "x-canonical-private-system-dialog-listview" |
743 | +#define DIALOG_FEEDBACK_HINT "x-canonical-private-system-dialog-feedback" |
744 | #define INTERACTIVE_HINT "x-canonical-switch-to-application" |
745 | #define SECONDARY_ICON_HINT "x-canonical-secondary-icon" |
746 | #define ICON_ONLY_HINT "x-canonical-private-icon-only" |
747 | |
748 | === modified file 'src/CMakeLists.txt' |
749 | --- src/CMakeLists.txt 2013-06-18 08:36:08 +0000 |
750 | +++ src/CMakeLists.txt 2013-09-04 16:15:41 +0000 |
751 | @@ -9,6 +9,12 @@ |
752 | ../include/NotificationServer.h |
753 | NotificationClient.cpp |
754 | ../include/NotificationClient.h |
755 | +Feedback.cpp |
756 | +../include/Feedback.h |
757 | +FeedbackInterface.cpp |
758 | +../include/FeedbackInterface.h |
759 | +FeedbackInterfaceAdaptor.cpp |
760 | +../include/FeedbackInterfaceAdaptor.h |
761 | ) |
762 | |
763 | # Build everything twice. Since we have only a few |
764 | @@ -20,12 +26,16 @@ |
765 | ${CORE_SRCS} |
766 | ) |
767 | |
768 | +target_link_libraries(notifybackend ${GIO_LIBRARIES}) |
769 | + |
770 | add_library(notifyplugin MODULE |
771 | ${CORE_SRCS} |
772 | NotificationPlugin.cpp |
773 | ../include/NotificationPlugin.h |
774 | ) |
775 | |
776 | +target_link_libraries(notifyplugin ${GIO_LIBRARIES}) |
777 | + |
778 | set_target_properties(notifyplugin PROPERTIES |
779 | SOVERSION ${SONAME} |
780 | VERSION ${SOVERSION} |
781 | |
782 | === added file 'src/Feedback.cpp' |
783 | --- src/Feedback.cpp 1970-01-01 00:00:00 +0000 |
784 | +++ src/Feedback.cpp 2013-09-04 16:15:41 +0000 |
785 | @@ -0,0 +1,32 @@ |
786 | +#include <QString> |
787 | +#include <QObject> |
788 | +#include <QtDBus> |
789 | +#include <QSharedPointer> |
790 | + |
791 | +#include "Feedback.h" |
792 | +#include "FeedbackInterfaceAdaptor.h" |
793 | +#include "NotificationModel.h" |
794 | +#include "Notification.h" |
795 | + |
796 | +Feedback::Feedback(NotificationModel& m, QObject *parent) : QObject(parent), model(m) { |
797 | + new FeedbackInterfaceAdaptor(this); |
798 | + QDBusConnection connection = QDBusConnection::sessionBus(); |
799 | + connection.registerObject(FEEDBACK_DBUS_PATH, this); |
800 | + connection.registerService(FEEDBACK_DBUS_NAME); |
801 | +} |
802 | + |
803 | +QStringList Feedback::collect(const unsigned int id) { |
804 | + fprintf(stderr, "Feedback::collect()\n"); |
805 | + QStringList list; |
806 | + QSharedPointer<Notification> notification; |
807 | + |
808 | + notification = model.getNotification(id); |
809 | + if(!notification.isNull()) { |
810 | + list = notification->getEntries(); |
811 | + } |
812 | + else { |
813 | + fprintf(stderr, "Feedback::collect() - could not get notification"); |
814 | + } |
815 | + |
816 | + return list; |
817 | +} |
818 | |
819 | === added file 'src/FeedbackInterface.cpp' |
820 | --- src/FeedbackInterface.cpp 1970-01-01 00:00:00 +0000 |
821 | +++ src/FeedbackInterface.cpp 2013-09-04 16:15:41 +0000 |
822 | @@ -0,0 +1,26 @@ |
823 | +/* |
824 | + * This file was generated by qdbusxml2cpp version 0.8 |
825 | + * Command line was: qdbusxml2cpp -v -c FeedbackInterface -p include/FeedbackInterface.h:src/FeedbackInterface.cpp com.canonical.snapdecisions.feedback.xml |
826 | + * |
827 | + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
828 | + * |
829 | + * This is an auto-generated file. |
830 | + * This file may have been hand-edited. Look for HAND-EDIT comments |
831 | + * before re-generating it. |
832 | + */ |
833 | + |
834 | +#include "FeedbackInterface.h" |
835 | + |
836 | +/* |
837 | + * Implementation of interface class FeedbackInterface |
838 | + */ |
839 | + |
840 | +FeedbackInterface::FeedbackInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) |
841 | + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) |
842 | +{ |
843 | +} |
844 | + |
845 | +FeedbackInterface::~FeedbackInterface() |
846 | +{ |
847 | +} |
848 | + |
849 | |
850 | === added file 'src/FeedbackInterfaceAdaptor.cpp' |
851 | --- src/FeedbackInterfaceAdaptor.cpp 1970-01-01 00:00:00 +0000 |
852 | +++ src/FeedbackInterfaceAdaptor.cpp 2013-09-04 16:15:41 +0000 |
853 | @@ -0,0 +1,43 @@ |
854 | +/* |
855 | + * This file was generated by qdbusxml2cpp version 0.8 |
856 | + * Command line was: qdbusxml2cpp -c FeedbackInterfaceAdaptor -a include/FeedbackInterfaceAdaptor.h:src/FeedbackInterfaceAdaptor.cpp com.canonical.snapdecisions.feedback.xml |
857 | + * |
858 | + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
859 | + * |
860 | + * This is an auto-generated file. |
861 | + * Do not edit! All changes made to it will be lost. |
862 | + */ |
863 | + |
864 | +#include "FeedbackInterfaceAdaptor.h" |
865 | +#include <QtCore/QMetaObject> |
866 | +#include <QtCore/QByteArray> |
867 | +#include <QtCore/QList> |
868 | +#include <QtCore/QMap> |
869 | +#include <QtCore/QString> |
870 | +#include <QtCore/QStringList> |
871 | +#include <QtCore/QVariant> |
872 | + |
873 | +/* |
874 | + * Implementation of adaptor class FeedbackInterfaceAdaptor |
875 | + */ |
876 | + |
877 | +FeedbackInterfaceAdaptor::FeedbackInterfaceAdaptor(QObject *parent) |
878 | + : QDBusAbstractAdaptor(parent) |
879 | +{ |
880 | + // constructor |
881 | + setAutoRelaySignals(true); |
882 | +} |
883 | + |
884 | +FeedbackInterfaceAdaptor::~FeedbackInterfaceAdaptor() |
885 | +{ |
886 | + // destructor |
887 | +} |
888 | + |
889 | +QStringList FeedbackInterfaceAdaptor::collect(uint id) |
890 | +{ |
891 | + // handle method call com.canonical.snapdecisions.feedback.collect |
892 | + QStringList out0; |
893 | + QMetaObject::invokeMethod(parent(), "collect", Q_RETURN_ARG(QStringList, out0), Q_ARG(uint, id)); |
894 | + return out0; |
895 | +} |
896 | + |
897 | |
898 | === modified file 'src/Notification.cpp' |
899 | --- src/Notification.cpp 2013-09-03 12:41:34 +0000 |
900 | +++ src/Notification.cpp 2013-09-04 16:15:41 +0000 |
901 | @@ -35,6 +35,8 @@ |
902 | QString icon; |
903 | QString secondaryIcon; |
904 | QStringList actions; |
905 | + QStringList entries; |
906 | + Notification::SystemDialog systemDialog; |
907 | ActionModel* actionsModel; |
908 | int hints; |
909 | int displayTime; |
910 | @@ -174,6 +176,7 @@ |
911 | if(p->urg != urg) { |
912 | p->urg = urg; |
913 | Q_EMIT urgencyChanged(p->urg); |
914 | + Q_EMIT dataChanged(p->id); |
915 | } |
916 | } |
917 | |
918 | @@ -181,6 +184,32 @@ |
919 | if(p->type != p->type) { |
920 | p->type = type; |
921 | Q_EMIT typeChanged(p->type); |
922 | + Q_EMIT dataChanged(p->id); |
923 | + } |
924 | +} |
925 | + |
926 | +QStringList Notification::getEntries() const { |
927 | + fprintf(stderr, "Notification::getEntries()\n"); |
928 | + return p->entries; |
929 | +} |
930 | + |
931 | +void Notification::setEntries(QStringList entries) { |
932 | + if(p->entries != entries) { |
933 | + p->entries = entries; |
934 | + Q_EMIT entriesChanged(p->entries); |
935 | + Q_EMIT dataChanged(p->id); |
936 | + } |
937 | +} |
938 | + |
939 | +Notification::SystemDialog Notification::getSystemDialog() const { |
940 | + return p->systemDialog; |
941 | +} |
942 | + |
943 | +void Notification::setSystemDialog(SystemDialog systemDialog) { |
944 | + if (p->systemDialog != systemDialog) { |
945 | + p->systemDialog = systemDialog; |
946 | + Q_EMIT systemDialogChanged(p->systemDialog); |
947 | + Q_EMIT dataChanged(p->id); |
948 | } |
949 | } |
950 | |
951 | @@ -192,6 +221,7 @@ |
952 | if(p->actions != actions) { |
953 | p->actions = actions; |
954 | Q_EMIT actionsChanged(p->actions); |
955 | + Q_EMIT dataChanged(p->id); |
956 | |
957 | for (int i = 0; i < p->actions.size(); i += 2) { |
958 | p->actionsModel->insertAction(p->actions[i], p->actions[i+1]); |
959 | @@ -206,6 +236,7 @@ |
960 | void Notification::setHints(int hints) { |
961 | p->hints = hints; |
962 | Q_EMIT hintsChanged(p->hints); |
963 | + Q_EMIT dataChanged(p->id); |
964 | } |
965 | |
966 | void Notification::onHovered() { |
967 | @@ -217,6 +248,7 @@ |
968 | } |
969 | |
970 | void Notification::invokeAction(const QString action) { |
971 | + fprintf(stderr, "Notification::invokeAction()\n"); |
972 | for(int i=0; i<p->actions.size(); i++) { |
973 | if(p->actions[i] == action) { |
974 | p->server->invokeAction(p->id, action); |
975 | |
976 | === modified file 'src/NotificationClient.cpp' |
977 | --- src/NotificationClient.cpp 2013-09-03 12:41:34 +0000 |
978 | +++ src/NotificationClient.cpp 2013-09-04 16:15:41 +0000 |
979 | @@ -40,7 +40,7 @@ |
980 | hints["urgency"] = (char)urg; |
981 | |
982 | if(ntype == Notification::Type::Confirmation) { |
983 | - hints[SYNCH_HINT] = "yes"; |
984 | + hints[SYNC_HINT] = "yes"; |
985 | } |
986 | if(ntype == Notification::Type::SnapDecision) { |
987 | QStringList snaps; |
988 | |
989 | === modified file 'src/NotificationModel.cpp' |
990 | --- src/NotificationModel.cpp 2013-09-03 12:41:34 +0000 |
991 | +++ src/NotificationModel.cpp 2013-09-04 16:15:41 +0000 |
992 | @@ -32,6 +32,7 @@ |
993 | QVector<QSharedPointer<Notification> > ephemeralQueue; |
994 | QVector<QSharedPointer<Notification> > interactiveQueue; |
995 | QVector<QSharedPointer<Notification> > snapQueue; |
996 | + QVector<QSharedPointer<Notification> > dialogQueue; |
997 | QMap<NotificationID, int> displayTimes; |
998 | }; |
999 | |
1000 | @@ -82,6 +83,9 @@ |
1001 | case RoleSecondaryIcon: |
1002 | return QVariant(p->displayedNotifications[index.row()]->getSecondaryIcon()); |
1003 | |
1004 | + case RoleEntries: |
1005 | + return QVariant::fromValue(p->displayedNotifications[index.row()]->getEntries()); |
1006 | + |
1007 | case RoleActions: |
1008 | return QVariant::fromValue(p->displayedNotifications[index.row()]->getActions()); |
1009 | |
1010 | @@ -91,6 +95,9 @@ |
1011 | case RoleNotification: |
1012 | return QVariant(p->displayedNotifications[index.row()]); |
1013 | |
1014 | + case RoleSystemDialog: |
1015 | + return QVariant(p->displayedNotifications[index.row()]->getSystemDialog()); |
1016 | + |
1017 | default: |
1018 | return QVariant(); |
1019 | } |
1020 | @@ -108,6 +115,7 @@ |
1021 | case Notification::Type::Confirmation : insertConfirmation(n); break; |
1022 | case Notification::Type::Interactive : insertInteractive(n); break; |
1023 | case Notification::Type::SnapDecision : insertSnap(n); break; |
1024 | + case Notification::Type::Dialog : insertDialog(n); break; |
1025 | default: |
1026 | printf("Unknown notification type, I should probably throw an exception here.\n"); |
1027 | break; |
1028 | @@ -119,6 +127,7 @@ |
1029 | } |
1030 | |
1031 | QSharedPointer<Notification> NotificationModel::getNotification(NotificationID id) const { |
1032 | + fprintf(stderr, "NotificationModel::getNotification()\n"); |
1033 | for(int i=0; i<p->ephemeralQueue.size(); i++) { |
1034 | if(p->ephemeralQueue[i]->getID() == id) { |
1035 | return p->ephemeralQueue[i]; |
1036 | @@ -134,6 +143,11 @@ |
1037 | return p->snapQueue[i]; |
1038 | } |
1039 | } |
1040 | + for(int i=0; i<p->dialogQueue.size(); i++) { |
1041 | + if(p->dialogQueue[i]->getID() == id) { |
1042 | + return p->dialogQueue[i]; |
1043 | + } |
1044 | + } |
1045 | for(int i=0; i<p->displayedNotifications.size(); i++) { |
1046 | if(p->displayedNotifications[i]->getID() == id) { |
1047 | return p->displayedNotifications[i]; |
1048 | @@ -175,6 +189,7 @@ |
1049 | } |
1050 | |
1051 | void NotificationModel::removeNotification(const NotificationID id) { |
1052 | + fprintf(stderr, "NotificationModel::removeNotification()\n"); |
1053 | for(int i=0; i<p->ephemeralQueue.size(); i++) { |
1054 | if(p->ephemeralQueue[i]->getID() == id) { |
1055 | p->ephemeralQueue.erase(p->ephemeralQueue.begin() + i); |
1056 | @@ -191,6 +206,14 @@ |
1057 | } |
1058 | } |
1059 | |
1060 | + for(int i=0; i<p->dialogQueue.size(); i++) { |
1061 | + if(p->dialogQueue[i]->getID() == id) { |
1062 | + p->dialogQueue.erase(p->dialogQueue.begin() + i); |
1063 | + Q_EMIT queueSizeChanged(queued()); |
1064 | + return; |
1065 | + } |
1066 | + } |
1067 | + |
1068 | for(int i=0; i<p->interactiveQueue.size(); i++) { |
1069 | if(p->interactiveQueue[i]->getID() == id) { |
1070 | p->interactiveQueue.erase(p->interactiveQueue.begin() + i); |
1071 | @@ -292,6 +315,7 @@ |
1072 | for(int i=p->displayedNotifications.size()-1; i>=0; i--) { |
1073 | QSharedPointer<Notification> n = p->displayedNotifications[i]; |
1074 | switch(n->getType()) { |
1075 | + case Notification::Type::Dialog : break; |
1076 | case Notification::Type::SnapDecision : break; |
1077 | case Notification::Type::Confirmation : deleteFromVisible(i); break; |
1078 | case Notification::Type::Ephemeral : deleteFromVisible(i); p->ephemeralQueue.push_front(n); queueSizeChanged(queued()); break; |
1079 | @@ -409,6 +433,34 @@ |
1080 | } |
1081 | } |
1082 | |
1083 | +void NotificationModel::insertDialog(QSharedPointer<Notification> n) { |
1084 | + Q_ASSERT(n->getType() == Notification::Type::Dialog); |
1085 | + removeNonSnap(); |
1086 | + int showing = countShowing(n->getType()); |
1087 | + if(showing >= maxSnapsShown) { |
1088 | + int loc = findFirst(Notification::Type::SnapDecision); |
1089 | + bool replaced = false; |
1090 | + for(int i=0; i<showing; i++) { |
1091 | + if(p->displayedNotifications[loc+i]->getUrgency() < n->getUrgency()) { |
1092 | + QSharedPointer<Notification> lastShowing = p->displayedNotifications[loc+showing-1]; |
1093 | + deleteFromVisible(loc+showing-1); |
1094 | + insertToVisible(n, loc+i); |
1095 | + p->dialogQueue.push_front(lastShowing); |
1096 | + replaced = true; |
1097 | + break; |
1098 | + } |
1099 | + } |
1100 | + if(!replaced) { |
1101 | + p->dialogQueue.push_back(n); |
1102 | + } |
1103 | + qStableSort(p->dialogQueue.begin(), p->dialogQueue.end(), notificationCompare); |
1104 | + Q_EMIT queueSizeChanged(queued()); |
1105 | + } else { |
1106 | + int loc = insertionPoint(n); |
1107 | + insertToVisible(n, loc); |
1108 | + } |
1109 | +} |
1110 | + |
1111 | int NotificationModel::insertionPoint(const QSharedPointer<Notification> n) const { |
1112 | int i=0; |
1113 | if(n->getType() == Notification::Type::SnapDecision) { |
1114 | @@ -514,9 +566,11 @@ |
1115 | roles.insert(RoleValue, "value"); |
1116 | roles.insert(RoleIcon, "icon"); |
1117 | roles.insert(RoleSecondaryIcon, "secondaryIcon"); |
1118 | + roles.insert(RoleEntries, "entries"); |
1119 | roles.insert(RoleActions, "actions"); |
1120 | roles.insert(RoleHints, "hints"); |
1121 | roles.insert(RoleNotification, "notification"); |
1122 | + roles.insert(RoleSystemDialog, "systemDialog"); |
1123 | |
1124 | return roles; |
1125 | } |
1126 | |
1127 | === modified file 'src/NotificationServer.cpp' |
1128 | --- src/NotificationServer.cpp 2013-09-03 12:41:34 +0000 |
1129 | +++ src/NotificationServer.cpp 2013-09-04 16:15:41 +0000 |
1130 | @@ -20,30 +20,62 @@ |
1131 | #include "NotificationModel.h" |
1132 | #include "NotificationServer.h" |
1133 | #include "Notification.h" |
1134 | +#include "Feedback.h" |
1135 | + |
1136 | #include <QDBusMetaType> |
1137 | #include <QSharedPointer> |
1138 | |
1139 | +#define DIALOG_MODEL_DBUS_NAME "com.canonical.snapdecisions.systemdialog" |
1140 | +#define DIALOG_MODEL_DBUS_OBJECTPATH "/com/canonical/snapdecisions/systemdialog" |
1141 | + |
1142 | NotificationServer::NotificationServer(NotificationModel &m, QObject *parent) : |
1143 | QDBusAbstractAdaptor(parent), model(m), idCounter(1) { |
1144 | qDBusRegisterMetaType<Hints>(); |
1145 | |
1146 | connect(this, SIGNAL(dataChanged(unsigned int)), &m, SLOT(onDataChanged(unsigned int))); |
1147 | + Feedback* feedback = new Feedback(m); |
1148 | + |
1149 | + wifiAuthConnection = NULL; |
1150 | + wifiAuthBusName = 0; |
1151 | + wifiAuthModel = 0; |
1152 | + |
1153 | + wifiSelectConnection = NULL; |
1154 | + wifiSelectBusName = 0; |
1155 | + wifiSelectModel = 0; |
1156 | + |
1157 | + userAuthConnection = NULL; |
1158 | + userAuthBusName = 0; |
1159 | + userAuthModel = 0; |
1160 | +} |
1161 | + |
1162 | +void NotificationServer::teardownMenuModels() { |
1163 | + if(wifiAuthBusName > 0) { |
1164 | + g_bus_unown_name(wifiAuthBusName); |
1165 | + g_dbus_connection_unexport_menu_model(wifiAuthConnection, wifiAuthModel); |
1166 | + } |
1167 | + |
1168 | + if(wifiSelectBusName > 0) { |
1169 | + g_bus_unown_name(wifiSelectBusName); |
1170 | + g_dbus_connection_unexport_menu_model(wifiSelectConnection, wifiSelectModel); |
1171 | + } |
1172 | + |
1173 | + if(userAuthBusName) |
1174 | + { |
1175 | + g_bus_unown_name(userAuthBusName); |
1176 | + g_dbus_connection_unexport_menu_model(userAuthConnection, userAuthModel); |
1177 | + } |
1178 | } |
1179 | |
1180 | NotificationServer::~NotificationServer() { |
1181 | - |
1182 | } |
1183 | |
1184 | void NotificationServer::invokeAction(unsigned int id, QString action) { |
1185 | + fprintf(stderr, "NotificationServer::invokeAction()\n"); |
1186 | Q_EMIT ActionInvoked(id, action); |
1187 | } |
1188 | |
1189 | - |
1190 | #define INTERACTIVE_HINT "x-canonical-switch-to-application" |
1191 | |
1192 | - |
1193 | - |
1194 | - |
1195 | QStringList NotificationServer::GetCapabilities() const { |
1196 | QStringList capabilities; |
1197 | capabilities.push_back("actions"); |
1198 | @@ -52,12 +84,16 @@ |
1199 | capabilities.push_back("icon-static"); |
1200 | capabilities.push_back("image/svg+xml"); |
1201 | capabilities.push_back(URGENCY_HINT); |
1202 | - capabilities.push_back(SYNCH_HINT); |
1203 | + capabilities.push_back(SYNC_HINT); |
1204 | capabilities.push_back(APPEND_HINT); |
1205 | capabilities.push_back(ICON_ONLY_HINT); |
1206 | capabilities.push_back(BUTTON_TINT_HINT); |
1207 | capabilities.push_back(TRUNCATION_HINT); |
1208 | capabilities.push_back(SNAP_HINT); |
1209 | + capabilities.push_back(DIALOG_HINT); |
1210 | + capabilities.push_back(DIALOG_PASSWORD_HINT); |
1211 | + capabilities.push_back(DIALOG_LISTVIEW_HINT); |
1212 | + capabilities.push_back(DIALOG_FEEDBACK_HINT); |
1213 | capabilities.push_back(SECONDARY_ICON_HINT); |
1214 | |
1215 | return capabilities; |
1216 | @@ -76,7 +112,7 @@ |
1217 | } |
1218 | Notification::Type ntype = Notification::Type::Ephemeral; |
1219 | expireTimeout = 5000; |
1220 | - if(hints.find(SYNCH_HINT) != hints.end()) { |
1221 | + if(hints.find(SYNC_HINT) != hints.end()) { |
1222 | expireTimeout = 3000; |
1223 | ntype = Notification::Type::Confirmation; |
1224 | } else if (hints.find(SNAP_HINT) != hints.end()) { |
1225 | @@ -87,6 +123,20 @@ |
1226 | expireTimeout = 5000; |
1227 | } |
1228 | |
1229 | + if(hints.find(DIALOG_HINT) != hints.end()) { |
1230 | + expireTimeout = 60000; |
1231 | + ntype = Notification::Type::Dialog; |
1232 | + } |
1233 | + |
1234 | + // only allow the combination DIALOG_PASSWORD_HINT + DIALOG_FEEDBACK_HINT or |
1235 | + // DIALOG_LISTVIEW_HINT + DIALOG_FEEDBACK_HINT |
1236 | + /*if((hints.find(DIALOG_PASSWORD_HINT) != hints.end() || |
1237 | + hints.find(DIALOG_LISTVIEW_HINT) != hints.end()) && |
1238 | + hints.find(DIALOG_FEEDBACK_HINT) != hints.end()) { |
1239 | + expireTimeout = 60000; |
1240 | + ntype = Notification::Type::Dialog; |
1241 | + }*/ |
1242 | + |
1243 | Notification* n = new Notification(id, expireTimeout, urg, ntype, this); |
1244 | connect(n, SIGNAL(dataChanged(unsigned int)), this, SLOT(onDataChanged(unsigned int))); |
1245 | connect(n, SIGNAL(completed(unsigned int)), this, SLOT(onCompleted(unsigned int))); |
1246 | @@ -100,7 +150,6 @@ |
1247 | const unsigned int FAILURE = 0; // Is this correct? |
1248 | const int minActions = 4; |
1249 | const int maxActions = 12; |
1250 | - //QImage icon(app_icon); |
1251 | int currentId = idCounter; |
1252 | QSharedPointer<Notification> notification; |
1253 | if(replaces_id != 0) { |
1254 | @@ -148,6 +197,30 @@ |
1255 | idCounter = 1; |
1256 | } |
1257 | |
1258 | + if(hints.find(SYNC_HINT) != hints.end()) { |
1259 | + int hints = notification->getHints(); |
1260 | + hints |= Notification::Hint::Sync; |
1261 | + notification->setHints(hints); |
1262 | + } |
1263 | + |
1264 | + if(hints.find(ICON_ONLY_HINT) != hints.end()) { |
1265 | + int hints = notification->getHints(); |
1266 | + hints |= Notification::Hint::IconOnly; |
1267 | + notification->setHints(hints); |
1268 | + } |
1269 | + |
1270 | + if(hints.find(BUTTON_TINT_HINT) != hints.end()) { |
1271 | + int hints = notification->getHints(); |
1272 | + hints |= Notification::Hint::ButtonTint; |
1273 | + notification->setHints(hints); |
1274 | + } |
1275 | + |
1276 | + if(hints.find(TRUNCATION_HINT) != hints.end()) { |
1277 | + int hints = notification->getHints(); |
1278 | + hints |= Notification::Hint::Truncation; |
1279 | + notification->setHints(hints); |
1280 | + } |
1281 | + |
1282 | if(notification->getType() == Notification::Type::Interactive) { |
1283 | int numActions = actions.size(); |
1284 | if(numActions != 2) { |
1285 | @@ -157,6 +230,32 @@ |
1286 | notification->setActions(actions); |
1287 | } |
1288 | |
1289 | + if(notification->getType() == Notification::Type::Dialog) { |
1290 | + int numActions = actions.size(); |
1291 | + if(numActions != 4) { |
1292 | + fprintf(stderr, "Wrong number of actions for an system-dialog notification. Has %d, requires %d.\n", numActions, 4); |
1293 | + return FAILURE; |
1294 | + } |
1295 | + notification->setActions(actions); |
1296 | + |
1297 | + if(hints.find(DIALOG_HINT) != hints.end()) { |
1298 | + QVariant variant = hints[DIALOG_HINT].variant(); |
1299 | + if(variant.canConvert<QString>()) { |
1300 | + QString type = variant.toString(); |
1301 | + if(type == SYSTEM_DIALOG_TYPE_WIFI_AUTH) { |
1302 | + notification->setSystemDialog(Notification::SystemDialog::WifiAuth); |
1303 | + exportWifiAuthModel(); |
1304 | + } else if (type == SYSTEM_DIALOG_TYPE_WIFI_SELECT) { |
1305 | + notification->setSystemDialog(Notification::SystemDialog::WifiSelect); |
1306 | + exportWifiSelectModel(); |
1307 | + } else if (type == SYSTEM_DIALOG_TYPE_USER_AUTH) { |
1308 | + notification->setSystemDialog(Notification::SystemDialog::UserAuth); |
1309 | + exportUserAuthModel(); |
1310 | + } |
1311 | + } |
1312 | + } |
1313 | + } |
1314 | + |
1315 | // Do this first because it can fail. In case we are updating an |
1316 | // existing notification exiting now means all old state is |
1317 | // preserved. |
1318 | @@ -190,8 +289,10 @@ |
1319 | } |
1320 | |
1321 | void NotificationServer::CloseNotification (unsigned int id) { |
1322 | + fprintf(stderr, "NotificationServer::CloseNotification()\n"); |
1323 | Q_EMIT NotificationClosed(id, 1); |
1324 | model.removeNotification(id); |
1325 | + teardownMenuModels(); |
1326 | } |
1327 | |
1328 | void NotificationServer::GetServerInformation (QString &name, QString &vendor, QString &version, QString &specVersion) const { |
1329 | @@ -206,5 +307,91 @@ |
1330 | } |
1331 | |
1332 | void NotificationServer::onCompleted(unsigned int id) { |
1333 | + fprintf(stderr, "NotificationServer::onCompleted()\n"); |
1334 | CloseNotification(id); |
1335 | } |
1336 | + |
1337 | +void busAcquiredWifiAuthModel(GDBusConnection* connection, |
1338 | + const gchar* name, |
1339 | + gpointer data) { |
1340 | + NotificationServer* self = (NotificationServer*) data; |
1341 | + GMenu* menu = g_menu_new(); |
1342 | + GMenuItem* item = g_menu_item_new("Password:", NULL); |
1343 | + g_menu_item_set_attribute_value(item, "x-canonical-type", |
1344 | + g_variant_new_string("com.canonical.snapdecision.textfield")); |
1345 | + g_menu_item_set_attribute_value(item, "x-echo-mode-password", |
1346 | + g_variant_new_boolean(true)); |
1347 | + g_menu_append_item(menu, item); |
1348 | + |
1349 | + self->wifiAuthConnection = connection; |
1350 | + self->wifiAuthModel = g_dbus_connection_export_menu_model(connection, |
1351 | + DIALOG_MODEL_DBUS_OBJECTPATH, |
1352 | + (GMenuModel*) menu, |
1353 | + NULL); |
1354 | +} |
1355 | + |
1356 | +void busAcquiredWifiSelectModel(GDBusConnection* connection, |
1357 | + const gchar* name, |
1358 | + gpointer data) { |
1359 | + NotificationServer* self = (NotificationServer*) data; |
1360 | + self->wifiSelectConnection = connection; |
1361 | +} |
1362 | + |
1363 | +void busAcquiredUserAuthModel(GDBusConnection* connection, |
1364 | + const gchar* name, |
1365 | + gpointer data) { |
1366 | + NotificationServer* self = (NotificationServer*) data; |
1367 | + GMenu* menu = g_menu_new(); |
1368 | + GMenuItem* item1 = g_menu_item_new("Login name:", NULL); |
1369 | + g_menu_item_set_attribute_value(item1, "x-canonical-type", |
1370 | + g_variant_new_string("com.canonical.snapdecision.textfield")); |
1371 | + g_menu_item_set_attribute_value(item1, "x-echo-mode-password", |
1372 | + g_variant_new_boolean(false)); |
1373 | + g_menu_append_item(menu, item1); |
1374 | + |
1375 | + GMenuItem* item2 = g_menu_item_new("Password:", NULL); |
1376 | + g_menu_item_set_attribute_value(item2, "x-canonical-type", |
1377 | + g_variant_new_string("com.canonical.snapdecision.textfield")); |
1378 | + g_menu_item_set_attribute_value(item2, "x-echo-mode-password", |
1379 | + g_variant_new_boolean(true)); |
1380 | + g_menu_append_item(menu, item2); |
1381 | + |
1382 | + self->userAuthConnection = connection; |
1383 | + self->userAuthModel = g_dbus_connection_export_menu_model(connection, |
1384 | + DIALOG_MODEL_DBUS_OBJECTPATH, |
1385 | + (GMenuModel*) menu, |
1386 | + NULL); |
1387 | +} |
1388 | + |
1389 | +void NotificationServer::exportWifiAuthModel() { |
1390 | + wifiAuthBusName = g_bus_own_name(G_BUS_TYPE_SESSION, |
1391 | + DIALOG_MODEL_DBUS_NAME, |
1392 | + (GBusNameOwnerFlags) 0, |
1393 | + busAcquiredWifiAuthModel, |
1394 | + NULL, |
1395 | + NULL, |
1396 | + this, |
1397 | + NULL); |
1398 | +} |
1399 | + |
1400 | +void NotificationServer::exportWifiSelectModel() { |
1401 | + wifiSelectBusName = g_bus_own_name(G_BUS_TYPE_SESSION, |
1402 | + DIALOG_MODEL_DBUS_NAME, |
1403 | + (GBusNameOwnerFlags) 0, |
1404 | + busAcquiredWifiSelectModel, |
1405 | + NULL, |
1406 | + NULL, |
1407 | + this, |
1408 | + NULL); |
1409 | +} |
1410 | + |
1411 | +void NotificationServer::exportUserAuthModel() { |
1412 | + userAuthBusName = g_bus_own_name(G_BUS_TYPE_SESSION, |
1413 | + DIALOG_MODEL_DBUS_NAME, |
1414 | + (GBusNameOwnerFlags) 0, |
1415 | + busAcquiredUserAuthModel, |
1416 | + NULL, |
1417 | + NULL, |
1418 | + this, |
1419 | + NULL); |
1420 | +} |