Merge lp:~zeitgeist/plank/zeitgeist into lp:plank
- zeitgeist
- Merge into trunk
Proposed by
Rico Tzschichholz
Status: | Work in progress |
---|---|
Proposed branch: | lp:~zeitgeist/plank/zeitgeist |
Merge into: | lp:plank |
Diff against target: |
322 lines (+189/-3) 5 files modified
configure.ac (+29/-0) lib/Items/ApplicationDockItemProvider.vala (+141/-1) lib/Items/DefaultApplicationDockItemProvider.vala (+11/-2) lib/Items/TransientDockItem.vala (+5/-0) lib/libplank.symbols (+3/-0) |
To merge this branch: | bzr merge lp:~zeitgeist/plank/zeitgeist |
Related bugs: | |
Related blueprints: |
dock-sort
(Undefined)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Docky Core | Pending | ||
Review via email: mp+282842@code.launchpad.net |
This proposal supersedes a proposal from 2014-01-27.
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote : Posted in a previous version of this proposal | # |
lp:~zeitgeist/plank/zeitgeist
updated
- 1489. By Rico Tzschichholz
-
preferenceswindow: Allow changing the backing DockController
- 1490. By Rico Tzschichholz
-
unity: Expose API to handle LauncherEntry DBus clients
- 1491. By Rico Tzschichholz
-
po: Update translations
- 1492. By Rico Tzschichholz
-
Cast callbacks to GLib.SourceFunc where possible
Unmerged revisions
- 1493. By Rico Tzschichholz
-
WIP Add zeitgeist support for adding suggested applications
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'configure.ac' | |||
2 | --- configure.ac 2015-11-03 12:01:37 +0000 | |||
3 | +++ configure.ac 2016-01-30 20:46:42 +0000 | |||
4 | @@ -265,6 +265,34 @@ | |||
5 | 265 | fi | 265 | fi |
6 | 266 | AM_CONDITIONAL([HAVE_DBUSMENU], [test "x$enable_dbusmenu" = "xyes"]) | 266 | AM_CONDITIONAL([HAVE_DBUSMENU], [test "x$enable_dbusmenu" = "xyes"]) |
7 | 267 | 267 | ||
8 | 268 | # Support suggested applications provided with zeitgeist | ||
9 | 269 | ZEITGEIST_MIN_VERSION=0.3 | ||
10 | 270 | ZEITGEIST_PKGS="zeitgeist-1.0 >= $ZEITGEIST_MIN_VERSION" | ||
11 | 271 | ZEITGEIST2_PKGS="zeitgeist-2.0 >= $ZEITGEIST_MIN_VERSION" | ||
12 | 272 | AC_ARG_ENABLE([zeitgeist], | ||
13 | 273 | AS_HELP_STRING([--enable-zeitgeist], | ||
14 | 274 | [Enable suggested applications provided with zeitgeist-1.0]), | ||
15 | 275 | [enable_zeitgeist=$enableval], [enable_zeitgeist=no]) | ||
16 | 276 | AC_ARG_ENABLE([zeitgeist2], | ||
17 | 277 | AS_HELP_STRING([--enable-zeitgeist2], | ||
18 | 278 | [Enable suggested applications provided with zeitgeist-2.0]), | ||
19 | 279 | [enable_zeitgeist2=$enableval], | ||
20 | 280 | [PKG_CHECK_MODULES(ZEITGEIST, $ZEITGEIST2_PKGS, [enable_zeitgeist2=yes], [enable_zeitgeist2=no])]) | ||
21 | 281 | if test "x$enable_zeitgeist" = "xyes" -a "x$enable_zeitgeist2" = "xyes" ; then | ||
22 | 282 | AC_MSG_ERROR([Not possible to build against both, zeitgeist-1.0 and zeitgeist-2.0.]) | ||
23 | 283 | fi | ||
24 | 284 | if test "x$enable_zeitgeist" = "xyes" -a "x$enable_zeitgeist2" = "xno" ; then | ||
25 | 285 | PLANK_CORE_OPTIONAL_PKGS="$PLANK_CORE_OPTIONAL_PKGS $ZEITGEIST_PKGS" | ||
26 | 286 | PLANK_CORE_VALA_PKGS="$PLANK_CORE_VALA_PKGS --pkg zeitgeist-1.0" | ||
27 | 287 | VALAFLAGS="$VALAFLAGS --define HAVE_ZEITGEIST" | ||
28 | 288 | fi | ||
29 | 289 | if test "x$enable_zeitgeist" = "xno" -a "x$enable_zeitgeist2" = "xyes" ; then | ||
30 | 290 | PLANK_CORE_OPTIONAL_PKGS="$PLANK_CORE_OPTIONAL_PKGS $ZEITGEIST2_PKGS" | ||
31 | 291 | PLANK_CORE_VALA_PKGS="$PLANK_CORE_VALA_PKGS --pkg zeitgeist-2.0" | ||
32 | 292 | VALAFLAGS="$VALAFLAGS --define HAVE_ZEITGEIST2" | ||
33 | 293 | enable_zeitgeist=yes | ||
34 | 294 | fi | ||
35 | 295 | AM_CONDITIONAL([HAVE_ZEITGEIST], [test "x$enable_zeitgeist" = "xyes" -o "x$enable_zeitgeist2" = "xyes"]) | ||
36 | 268 | 296 | ||
37 | 269 | 297 | ||
38 | 270 | AC_SUBST(PLANK_CORE_OPTIONAL_PKGS) | 298 | AC_SUBST(PLANK_CORE_OPTIONAL_PKGS) |
39 | @@ -426,6 +454,7 @@ | |||
40 | 426 | Use gee-0.8.................: ${enable_gee_0_8} | 454 | Use gee-0.8.................: ${enable_gee_0_8} |
41 | 427 | Dbusmenu support............: ${enable_dbusmenu} | 455 | Dbusmenu support............: ${enable_dbusmenu} |
42 | 428 | HiDPI support...............: ${enable_hidpi} | 456 | HiDPI support...............: ${enable_hidpi} |
43 | 457 | Zeitgeist support...........: ${enable_zeitgeist} | ||
44 | 429 | XInput Barriers support.....: ${enable_barriers} | 458 | XInput Barriers support.....: ${enable_barriers} |
45 | 430 | 459 | ||
46 | 431 | Apport support..............: ${enable_apport} | 460 | Apport support..............: ${enable_apport} |
47 | 432 | 461 | ||
48 | === modified file 'lib/Items/ApplicationDockItemProvider.vala' | |||
49 | --- lib/Items/ApplicationDockItemProvider.vala 2016-01-30 12:08:11 +0000 | |||
50 | +++ lib/Items/ApplicationDockItemProvider.vala 2016-01-30 20:46:42 +0000 | |||
51 | @@ -34,6 +34,11 @@ | |||
52 | 34 | bool delay_items_monitor_handle = false; | 34 | bool delay_items_monitor_handle = false; |
53 | 35 | Gee.ArrayList<GLib.File> queued_files; | 35 | Gee.ArrayList<GLib.File> queued_files; |
54 | 36 | 36 | ||
55 | 37 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
56 | 38 | Zeitgeist.Log zglog = Zeitgeist.Log.get_default(); | ||
57 | 39 | Gee.ArrayList<TransientDockItem> suggested_app_items = new Gee.ArrayList<TransientDockItem> (); | ||
58 | 40 | #endif | ||
59 | 41 | |||
60 | 37 | /** | 42 | /** |
61 | 38 | * Creates a new container for dock items. | 43 | * Creates a new container for dock items. |
62 | 39 | * | 44 | * |
63 | @@ -61,12 +66,32 @@ | |||
64 | 61 | } catch (Error e) { | 66 | } catch (Error e) { |
65 | 62 | critical ("Unable to watch the launchers directory. (%s)", e.message); | 67 | critical ("Unable to watch the launchers directory. (%s)", e.message); |
66 | 63 | } | 68 | } |
67 | 69 | |||
68 | 70 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
69 | 71 | // FIXME Workaround to have an initialized PositionManager | ||
70 | 72 | Idle.add (() => { | ||
71 | 73 | // FIXME | ||
72 | 74 | //controller.position_manager.notify["MaxItemCount"].connect (update_suggested_apps); | ||
73 | 75 | update_suggested_apps (); | ||
74 | 76 | return false; | ||
75 | 77 | }); | ||
76 | 78 | |||
77 | 79 | // FIXME Update suggested apps in a "proper" interval | ||
78 | 80 | Timeout.add_seconds (3600, () => { | ||
79 | 81 | update_suggested_apps (); | ||
80 | 82 | return true; | ||
81 | 83 | }); | ||
82 | 84 | #endif | ||
83 | 64 | } | 85 | } |
84 | 65 | 86 | ||
85 | 66 | ~ApplicationDockItemProvider () | 87 | ~ApplicationDockItemProvider () |
86 | 67 | { | 88 | { |
87 | 68 | queued_files = null; | 89 | queued_files = null; |
88 | 69 | 90 | ||
89 | 91 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
90 | 92 | // FIXME | ||
91 | 93 | //controller.position_manager.notify["MaxItemCount"].disconnect (update_suggested_apps); | ||
92 | 94 | #endif | ||
93 | 70 | Matcher.get_default ().application_opened.disconnect (app_opened); | 95 | Matcher.get_default ().application_opened.disconnect (app_opened); |
94 | 71 | 96 | ||
95 | 72 | if (items_monitor != null) { | 97 | if (items_monitor != null) { |
96 | @@ -198,6 +223,84 @@ | |||
97 | 198 | return item_list.to_array (); | 223 | return item_list.to_array (); |
98 | 199 | } | 224 | } |
99 | 200 | 225 | ||
100 | 226 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
101 | 227 | public void update_suggested_apps () | ||
102 | 228 | { | ||
103 | 229 | Logger.verbose ("ApplicationDockItemProvider.update_suggested_apps ()"); | ||
104 | 230 | |||
105 | 231 | // FIXME | ||
106 | 232 | //var max_item_count = controller.position_manager.MaxItemCount; | ||
107 | 233 | var max_item_count = 15; | ||
108 | 234 | //var max_item_count = controller.position_manager.MaxItemCount; | ||
109 | 235 | var num_events = 3; | ||
110 | 236 | if (get_n_items (true, suggested_app_items) >= max_item_count - num_events) | ||
111 | 237 | return; | ||
112 | 238 | |||
113 | 239 | Logger.verbose ("ApplicationDockItemProvider.update_suggested_apps ().run (%i)", num_events); | ||
114 | 240 | |||
115 | 241 | #if HAVE_ZEITGEIST | ||
116 | 242 | var templates = new PtrArray (); | ||
117 | 243 | #else | ||
118 | 244 | var templates = new GenericArray<Zeitgeist.Event> (); | ||
119 | 245 | #endif | ||
120 | 246 | // Consider used applications within the last 2 months | ||
121 | 247 | var now = new DateTime.now_local ().to_unix () * 1000; | ||
122 | 248 | var start = now - 60 * 86400000; | ||
123 | 249 | var time_range = new Zeitgeist.TimeRange (start, now); | ||
124 | 250 | |||
125 | 251 | var event = new Zeitgeist.Event (); | ||
126 | 252 | #if HAVE_ZEITGEIST | ||
127 | 253 | var subject = new Zeitgeist.Subject (); | ||
128 | 254 | subject.set_uri ("application://*"); | ||
129 | 255 | #else | ||
130 | 256 | var subject = new Zeitgeist.Subject.full ("application://*"); | ||
131 | 257 | #endif | ||
132 | 258 | event.add_subject (subject); | ||
133 | 259 | templates.add (event); | ||
134 | 260 | |||
135 | 261 | zglog.find_events.begin (time_range, templates, Zeitgeist.StorageState.ANY, num_events, | ||
136 | 262 | Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS, null, (obj, res) => { | ||
137 | 263 | Zeitgeist.ResultSet events = zglog.find_events.end (res); | ||
138 | 264 | var new_suggested_app_items = new Gee.ArrayList<TransientDockItem> (); | ||
139 | 265 | foreach (var e in events) { | ||
140 | 266 | #if HAVE_ZEITGEIST | ||
141 | 267 | var app_uri = e.get_subject (0).get_uri (); | ||
142 | 268 | #else | ||
143 | 269 | var app_uri = e.subjects[0].uri; | ||
144 | 270 | #endif | ||
145 | 271 | |||
146 | 272 | // Find a matching desktop-file and create new TransientDockItem | ||
147 | 273 | var desktop_file = desktop_file_for_application_uri (app_uri); | ||
148 | 274 | if (desktop_file == null) | ||
149 | 275 | continue; | ||
150 | 276 | |||
151 | 277 | var launcher_uri = desktop_file.get_uri (); | ||
152 | 278 | DockItem? current_item = item_for_uri (launcher_uri); | ||
153 | 279 | if (current_item == null) { | ||
154 | 280 | current_item = new TransientDockItem.with_launcher (launcher_uri); | ||
155 | 281 | add (current_item); | ||
156 | 282 | Logger.verbose ("SuggestedApp added: %s[%s, %i]", current_item.Text, current_item.Launcher, (int)current_item); | ||
157 | 283 | new_suggested_app_items.add (current_item as TransientDockItem); | ||
158 | 284 | } else if (current_item is TransientDockItem) { | ||
159 | 285 | Logger.verbose ("SuggestedApp confirmed: %s[%s, %i]", current_item.Text, current_item.Launcher, (int)current_item); | ||
160 | 286 | new_suggested_app_items.add (current_item as TransientDockItem); | ||
161 | 287 | } | ||
162 | 288 | } | ||
163 | 289 | |||
164 | 290 | suggested_app_items.remove_all (new_suggested_app_items); | ||
165 | 291 | foreach (var item in suggested_app_items) { | ||
166 | 292 | if (!can_remove_transient_item (item)) | ||
167 | 293 | return; | ||
168 | 294 | |||
169 | 295 | Logger.verbose ("SuggestedApp removed: %s[%s, %i]", item.Text, item.Launcher, (int)item); | ||
170 | 296 | remove (item); | ||
171 | 297 | } | ||
172 | 298 | |||
173 | 299 | suggested_app_items = new_suggested_app_items; | ||
174 | 300 | }); | ||
175 | 301 | } | ||
176 | 302 | #endif | ||
177 | 303 | |||
178 | 201 | protected virtual void app_opened (Bamf.Application app) | 304 | protected virtual void app_opened (Bamf.Application app) |
179 | 202 | { | 305 | { |
180 | 203 | // Make sure internal window-list of Wnck is most up to date | 306 | // Make sure internal window-list of Wnck is most up to date |
181 | @@ -260,6 +363,12 @@ | |||
182 | 260 | } | 363 | } |
183 | 261 | 364 | ||
184 | 262 | queued_files.clear (); | 365 | queued_files.clear (); |
185 | 366 | |||
186 | 367 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
187 | 368 | // Update suggested applications while it is possible the | ||
188 | 369 | // added application(s) were | ||
189 | 370 | update_suggested_apps (); | ||
190 | 371 | #endif | ||
191 | 263 | } | 372 | } |
192 | 264 | 373 | ||
193 | 265 | [CCode (instance_pos = -1)] | 374 | [CCode (instance_pos = -1)] |
194 | @@ -291,6 +400,37 @@ | |||
195 | 291 | process_queued_files (); | 400 | process_queued_files (); |
196 | 292 | } | 401 | } |
197 | 293 | 402 | ||
198 | 403 | public bool can_remove_transient_item (TransientDockItem item) | ||
199 | 404 | { | ||
200 | 405 | return (item != null | ||
201 | 406 | && item.App == null | ||
202 | 407 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
203 | 408 | && !suggested_app_items.contains (item) | ||
204 | 409 | #endif | ||
205 | 410 | && !item.has_unity_info ()); | ||
206 | 411 | } | ||
207 | 412 | |||
208 | 413 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
209 | 414 | int get_n_items (bool visible_only, Gee.List<DockElement>? ignore = null) | ||
210 | 415 | { | ||
211 | 416 | unowned Gee.List<DockElement> elements = (visible_only ? visible_elements : internal_elements); | ||
212 | 417 | var elements_count = elements.size; | ||
213 | 418 | |||
214 | 419 | //foreach (var item in items) | ||
215 | 420 | // if (item.is_virtual ()); | ||
216 | 421 | // items_count--; | ||
217 | 422 | |||
218 | 423 | if (ignore == null) | ||
219 | 424 | return elements_count; | ||
220 | 425 | |||
221 | 426 | foreach (var element in ignore) | ||
222 | 427 | if (elements.contains (element)) | ||
223 | 428 | elements_count--; | ||
224 | 429 | |||
225 | 430 | return elements_count; | ||
226 | 431 | } | ||
227 | 432 | #endif | ||
228 | 433 | |||
229 | 294 | protected override void connect_element (DockElement element) | 434 | protected override void connect_element (DockElement element) |
230 | 295 | { | 435 | { |
231 | 296 | base.connect_element (element); | 436 | base.connect_element (element); |
232 | @@ -332,7 +472,7 @@ | |||
233 | 332 | // Remove item which only exists because of the presence of | 472 | // Remove item which only exists because of the presence of |
234 | 333 | // this removed LauncherEntry interface | 473 | // this removed LauncherEntry interface |
235 | 334 | unowned TransientDockItem? transient_item = item as TransientDockItem; | 474 | unowned TransientDockItem? transient_item = item as TransientDockItem; |
237 | 335 | if (transient_item != null && transient_item.App == null) | 475 | if (can_remove_transient_item (transient_item)) |
238 | 336 | remove (transient_item); | 476 | remove (transient_item); |
239 | 337 | 477 | ||
240 | 338 | break; | 478 | break; |
241 | 339 | 479 | ||
242 | === modified file 'lib/Items/DefaultApplicationDockItemProvider.vala' | |||
243 | --- lib/Items/DefaultApplicationDockItemProvider.vala 2015-11-03 10:37:19 +0000 | |||
244 | +++ lib/Items/DefaultApplicationDockItemProvider.vala 2016-01-30 20:46:42 +0000 | |||
245 | @@ -1,5 +1,6 @@ | |||
246 | 1 | // | 1 | // |
247 | 2 | // Copyright (C) 2013 Rico Tzschichholz | 2 | // Copyright (C) 2013 Rico Tzschichholz |
248 | 3 | // Copyright (C) 2013 Seif Lotfy | ||
249 | 3 | // | 4 | // |
250 | 4 | // This file is part of Plank. | 5 | // This file is part of Plank. |
251 | 5 | // | 6 | // |
252 | @@ -124,8 +125,9 @@ | |||
253 | 124 | 125 | ||
254 | 125 | void app_closed (DockItem item) | 126 | void app_closed (DockItem item) |
255 | 126 | { | 127 | { |
258 | 127 | if (item is TransientDockItem | 128 | unowned TransientDockItem transient_item = (item as TransientDockItem); |
259 | 128 | && !(((TransientDockItem) item).has_unity_info ())) | 129 | transient_item.App = null; |
260 | 130 | if (can_remove_transient_item (transient_item)) | ||
261 | 129 | remove (item); | 131 | remove (item); |
262 | 130 | } | 132 | } |
263 | 131 | 133 | ||
264 | @@ -222,7 +224,14 @@ | |||
265 | 222 | app = ((ApplicationDockItem) item).App; | 224 | app = ((ApplicationDockItem) item).App; |
266 | 223 | 225 | ||
267 | 224 | if (app == null || !app.is_running ()) { | 226 | if (app == null || !app.is_running ()) { |
268 | 227 | // TODO Replace the item if it is a suggested appliction | ||
269 | 225 | remove (item); | 228 | remove (item); |
270 | 229 | |||
271 | 230 | #if HAVE_ZEITGEIST || HAVE_ZEITGEIST2 | ||
272 | 231 | // Update suggested applications while it is possible the | ||
273 | 232 | // removed application is one | ||
274 | 233 | update_suggested_apps (); | ||
275 | 234 | #endif | ||
276 | 226 | return; | 235 | return; |
277 | 227 | } | 236 | } |
278 | 228 | 237 | ||
279 | 229 | 238 | ||
280 | === modified file 'lib/Items/TransientDockItem.vala' | |||
281 | --- lib/Items/TransientDockItem.vala 2015-11-03 10:37:19 +0000 | |||
282 | +++ lib/Items/TransientDockItem.vala 2016-01-30 20:46:42 +0000 | |||
283 | @@ -95,6 +95,11 @@ | |||
284 | 95 | return false; | 95 | return false; |
285 | 96 | } | 96 | } |
286 | 97 | 97 | ||
287 | 98 | public bool is_virtual () | ||
288 | 99 | { | ||
289 | 100 | return (App == null); | ||
290 | 101 | } | ||
291 | 102 | |||
292 | 98 | /** | 103 | /** |
293 | 99 | * {@inheritDoc} | 104 | * {@inheritDoc} |
294 | 100 | */ | 105 | */ |
295 | 101 | 106 | ||
296 | === modified file 'lib/libplank.symbols' | |||
297 | --- lib/libplank.symbols 2016-01-30 12:08:11 +0000 | |||
298 | +++ lib/libplank.symbols 2016-01-30 20:46:42 +0000 | |||
299 | @@ -49,6 +49,7 @@ | |||
300 | 49 | plank_application_dock_item_new_with_dockitem_filename | 49 | plank_application_dock_item_new_with_dockitem_filename |
301 | 50 | plank_application_dock_item_parse_launcher | 50 | plank_application_dock_item_parse_launcher |
302 | 51 | plank_application_dock_item_provider_app_opened | 51 | plank_application_dock_item_provider_app_opened |
303 | 52 | plank_application_dock_item_provider_can_remove_transient_item | ||
304 | 52 | plank_application_dock_item_provider_construct | 53 | plank_application_dock_item_provider_construct |
305 | 53 | plank_application_dock_item_provider_delay_items_monitor | 54 | plank_application_dock_item_provider_delay_items_monitor |
306 | 54 | plank_application_dock_item_provider_get_item_list_string | 55 | plank_application_dock_item_provider_get_item_list_string |
307 | @@ -57,6 +58,7 @@ | |||
308 | 57 | plank_application_dock_item_provider_item_for_application | 58 | plank_application_dock_item_provider_item_for_application |
309 | 58 | plank_application_dock_item_provider_new | 59 | plank_application_dock_item_provider_new |
310 | 59 | plank_application_dock_item_provider_resume_items_monitor | 60 | plank_application_dock_item_provider_resume_items_monitor |
311 | 61 | plank_application_dock_item_provider_update_suggested_apps | ||
312 | 60 | plank_application_dock_item_set_urgent | 62 | plank_application_dock_item_set_urgent |
313 | 61 | plank_application_dock_item_unity_reset | 63 | plank_application_dock_item_unity_reset |
314 | 62 | plank_application_dock_item_unity_update | 64 | plank_application_dock_item_unity_update |
315 | @@ -679,6 +681,7 @@ | |||
316 | 679 | plank_transient_dock_item_construct | 681 | plank_transient_dock_item_construct |
317 | 680 | plank_transient_dock_item_construct_with_launcher | 682 | plank_transient_dock_item_construct_with_launcher |
318 | 681 | plank_transient_dock_item_get_type | 683 | plank_transient_dock_item_get_type |
319 | 684 | plank_transient_dock_item_is_virtual | ||
320 | 682 | plank_transient_dock_item_new | 685 | plank_transient_dock_item_new |
321 | 683 | plank_transient_dock_item_new_with_launcher | 686 | plank_transient_dock_item_new_with_launcher |
322 | 684 | plank_unity_add_client | 687 | plank_unity_add_client |
I like the idea, but I'm worried about things just popping up unexpectedly. I think it might make sense to wait for the user to open one of the suggested apps and then "smart-pin" it at that time. In this way, we're not actually adding the item, we're just not removing it :p