Merge lp:~indicator-applet-developers/ido/add-messaging-menu into lp:ido/13.10
- add-messaging-menu
- Merge into trunk.13.10
Status: | Merged |
---|---|
Approved by: | Ted Gould |
Approved revision: | 148 |
Merged at revision: | 145 |
Proposed branch: | lp:~indicator-applet-developers/ido/add-messaging-menu |
Merge into: | lp:ido/13.10 |
Diff against target: |
1163 lines (+1044/-2) 11 files modified
debian/libido3-0.1-0.symbols (+10/-0) src/Makefile.am (+8/-2) src/idoactionhelper.c (+24/-0) src/idoactionhelper.h (+3/-0) src/idoapplicationmenuitem.c (+195/-0) src/idoapplicationmenuitem.h (+36/-0) src/idodetaillabel.c (+401/-0) src/idodetaillabel.h (+59/-0) src/idomenuitemfactory.c (+8/-0) src/idosourcemenuitem.c (+264/-0) src/idosourcemenuitem.h (+36/-0) |
To merge this branch: | bzr merge lp:~indicator-applet-developers/ido/add-messaging-menu |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Ted Gould (community) | Approve | ||
Review via email: mp+179962@code.launchpad.net |
Commit message
Add widgets for messaging menu
Description of the change
Adds the widgets needed for messaging menu integration. Might be broken, getting a diff and Jenkins comment right now while doing further testing.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:147
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
Fixed a couple of little things. But this seems sane.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:148
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'debian/libido3-0.1-0.symbols' |
2 | --- debian/libido3-0.1-0.symbols 2013-07-31 02:02:53 +0000 |
3 | +++ debian/libido3-0.1-0.symbols 2013-08-13 20:56:02 +0000 |
4 | @@ -1,11 +1,14 @@ |
5 | libido3-0.1.so.0 libido3-0.1-0 #MINVER# |
6 | ido_action_helper_activate@Base 13.10.0daily13.06.19 |
7 | + ido_action_helper_activate_with_parameter@Base 0replaceme |
8 | ido_action_helper_change_action_state@Base 13.10.0daily13.06.19 |
9 | ido_action_helper_get_action_target@Base 13.10.0daily13.06.19 |
10 | ido_action_helper_get_type@Base 13.10.0daily13.06.19 |
11 | ido_action_helper_get_widget@Base 13.10.0daily13.06.19 |
12 | ido_action_helper_new@Base 13.10.0daily13.06.19 |
13 | ido_alarm_menu_item_new_from_model@Base 13.10.0+13.10.20130731 |
14 | + ido_application_menu_item_get_type@Base 0replaceme |
15 | + ido_application_menu_item_new_from_model@Base 0replaceme |
16 | ido_appointment_menu_item_new_from_model@Base 13.10.0daily13.06.19 |
17 | ido_basic_menu_item_get_type@Base 13.10.0+13.10.20130731 |
18 | ido_basic_menu_item_new@Base 13.10.0+13.10.20130731 |
19 | @@ -24,6 +27,11 @@ |
20 | ido_calendar_menu_item_set_date@Base 0.2.2 |
21 | ido_calendar_menu_item_set_display_options@Base 0.2.1 |
22 | ido_calendar_menu_item_unmark_day@Base 0.2.1 |
23 | + ido_detail_label_get_text@Base 0replaceme |
24 | + ido_detail_label_get_type@Base 0replaceme |
25 | + ido_detail_label_new@Base 0replaceme |
26 | + ido_detail_label_set_count@Base 0replaceme |
27 | + ido_detail_label_set_text@Base 0replaceme |
28 | ido_entry_menu_item_get_entry@Base 0.1.0 |
29 | ido_entry_menu_item_get_type@Base 0.1.0 |
30 | ido_entry_menu_item_new@Base 0.1.0 |
31 | @@ -57,6 +65,8 @@ |
32 | ido_scale_menu_item_set_secondary_label@Base 0.1.9 |
33 | ido_scale_menu_item_set_style@Base 0.1.9 |
34 | ido_scale_menu_item_style_get_type@Base 0.1.9 |
35 | + ido_source_menu_item_get_type@Base 0replaceme |
36 | + ido_source_menu_item_new_from_menu_model@Base 0replaceme |
37 | ido_switch_menu_item_get_content_area@Base 12.10.0 |
38 | ido_switch_menu_item_get_type@Base 12.10.0 |
39 | ido_switch_menu_item_new@Base 12.10.0 |
40 | |
41 | === modified file 'src/Makefile.am' |
42 | --- src/Makefile.am 2013-07-25 23:53:48 +0000 |
43 | +++ src/Makefile.am 2013-08-13 20:56:02 +0000 |
44 | @@ -27,7 +27,10 @@ |
45 | libido.h \ |
46 | idoactionhelper.h \ |
47 | idomediaplayermenuitem.h \ |
48 | - idoplaybackmenuitem.h |
49 | + idoplaybackmenuitem.h \ |
50 | + idoapplicationmenuitem.h \ |
51 | + idodetaillabel.h \ |
52 | + idosourcemenuitem.h |
53 | |
54 | EXTRA_DIST = \ |
55 | ido.list \ |
56 | @@ -86,7 +89,10 @@ |
57 | idoappointmentmenuitem.c \ |
58 | idobasicmenuitem.c \ |
59 | idotimestampmenuitem.c \ |
60 | - idolocationmenuitem.c |
61 | + idolocationmenuitem.c \ |
62 | + idoapplicationmenuitem.c \ |
63 | + idodetaillabel.c \ |
64 | + idosourcemenuitem.c |
65 | |
66 | libido3_0_1_la_SOURCES = $(libido_0_1_la_SOURCES) |
67 | |
68 | |
69 | === modified file 'src/idoactionhelper.c' |
70 | --- src/idoactionhelper.c 2013-05-31 22:50:09 +0000 |
71 | +++ src/idoactionhelper.c 2013-08-13 20:56:02 +0000 |
72 | @@ -403,6 +403,30 @@ |
73 | } |
74 | |
75 | /** |
76 | + * ido_action_helper_activate_with_parameter: |
77 | + * @helper: an #IdoActionHelper |
78 | + * @parameter: a #GVariant containing the parameter |
79 | + * |
80 | + * Activates the action that is associated with this helper passing |
81 | + * @parameter instead the "target" associated with the menu item this |
82 | + * helper is bound to. |
83 | + */ |
84 | +void |
85 | +ido_action_helper_activate_with_parameter (IdoActionHelper *helper, |
86 | + GVariant *parameter) |
87 | +{ |
88 | + g_return_if_fail (IDO_IS_ACTION_HELPER (helper)); |
89 | + g_return_if_fail (parameter != NULL); |
90 | + |
91 | + g_variant_ref_sink (parameter); |
92 | + |
93 | + if (helper->actions && helper->action_name) |
94 | + g_action_group_activate_action (helper->actions, helper->action_name, parameter); |
95 | + |
96 | + g_variant_unref (parameter); |
97 | +} |
98 | + |
99 | +/** |
100 | * ido_action_helper_change_action_state: |
101 | * @helper: an #IdoActionHelper |
102 | * @state: the proposed new state of the action |
103 | |
104 | === modified file 'src/idoactionhelper.h' |
105 | --- src/idoactionhelper.h 2013-05-31 22:50:09 +0000 |
106 | +++ src/idoactionhelper.h 2013-08-13 20:56:02 +0000 |
107 | @@ -41,6 +41,9 @@ |
108 | |
109 | void ido_action_helper_activate (IdoActionHelper *helper); |
110 | |
111 | +void ido_action_helper_activate_with_parameter (IdoActionHelper *helper, |
112 | + GVariant *parameter); |
113 | + |
114 | void ido_action_helper_change_action_state (IdoActionHelper *helper, |
115 | GVariant *state); |
116 | |
117 | |
118 | === added file 'src/idoapplicationmenuitem.c' |
119 | --- src/idoapplicationmenuitem.c 1970-01-01 00:00:00 +0000 |
120 | +++ src/idoapplicationmenuitem.c 2013-08-13 20:56:02 +0000 |
121 | @@ -0,0 +1,195 @@ |
122 | +/* |
123 | + * Copyright 2013 Canonical Ltd. |
124 | + * |
125 | + * This program is free software: you can redistribute it and/or modify it |
126 | + * under the terms of the GNU General Public License version 3, as published |
127 | + * by the Free Software Foundation. |
128 | + * |
129 | + * This program is distributed in the hope that it will be useful, but |
130 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
131 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
132 | + * PURPOSE. See the GNU General Public License for more details. |
133 | + * |
134 | + * You should have received a copy of the GNU General Public License along |
135 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
136 | + * |
137 | + * Authors: |
138 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
139 | + */ |
140 | + |
141 | +#include "idoapplicationmenuitem.h" |
142 | +#include "idoactionhelper.h" |
143 | + |
144 | +typedef GtkMenuItemClass IdoApplicationMenuItemClass; |
145 | + |
146 | +struct _IdoApplicationMenuItem |
147 | +{ |
148 | + GtkMenuItem parent; |
149 | + |
150 | + gboolean is_running; |
151 | + |
152 | + GtkWidget *icon; |
153 | + GtkWidget *label; |
154 | +}; |
155 | + |
156 | +G_DEFINE_TYPE (IdoApplicationMenuItem, ido_application_menu_item, GTK_TYPE_MENU_ITEM); |
157 | + |
158 | +static void |
159 | +ido_application_menu_item_constructed (GObject *object) |
160 | +{ |
161 | + IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (object); |
162 | + GtkWidget *grid; |
163 | + |
164 | + item->icon = g_object_ref (gtk_image_new ()); |
165 | + gtk_widget_set_margin_right (item->icon, 6); |
166 | + |
167 | + item->label = g_object_ref (gtk_label_new ("")); |
168 | + |
169 | + grid = gtk_grid_new (); |
170 | + gtk_grid_attach (GTK_GRID (grid), item->icon, 0, 0, 1, 1); |
171 | + gtk_grid_attach (GTK_GRID (grid), item->label, 1, 0, 1, 1); |
172 | + |
173 | + gtk_container_add (GTK_CONTAINER (object), grid); |
174 | + gtk_widget_show_all (grid); |
175 | + |
176 | + G_OBJECT_CLASS (ido_application_menu_item_parent_class)->constructed (object); |
177 | +} |
178 | + |
179 | +static void |
180 | +ido_application_menu_item_dispose (GObject *object) |
181 | +{ |
182 | + IdoApplicationMenuItem *self = IDO_APPLICATION_MENU_ITEM (object); |
183 | + |
184 | + g_clear_object (&self->icon); |
185 | + g_clear_object (&self->label); |
186 | + |
187 | + G_OBJECT_CLASS (ido_application_menu_item_parent_class)->dispose (object); |
188 | +} |
189 | + |
190 | +static gboolean |
191 | +ido_application_menu_item_draw (GtkWidget *widget, |
192 | + cairo_t *cr) |
193 | +{ |
194 | + IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (widget); |
195 | + |
196 | + GTK_WIDGET_CLASS (ido_application_menu_item_parent_class)->draw (widget, cr); |
197 | + |
198 | + if (item->is_running) |
199 | + { |
200 | + const int arrow_width = 5; |
201 | + const double half_arrow_height = 4.5; |
202 | + GtkAllocation alloc; |
203 | + GdkRGBA color; |
204 | + double center; |
205 | + |
206 | + gtk_widget_get_allocation (widget, &alloc); |
207 | + |
208 | + gtk_style_context_get_color (gtk_widget_get_style_context (widget), |
209 | + gtk_widget_get_state_flags (widget), |
210 | + &color); |
211 | + gdk_cairo_set_source_rgba (cr, &color); |
212 | + |
213 | + center = alloc.height / 2 + 0.5; |
214 | + |
215 | + cairo_move_to (cr, 0, center - half_arrow_height); |
216 | + cairo_line_to (cr, 0, center + half_arrow_height); |
217 | + cairo_line_to (cr, arrow_width, center); |
218 | + cairo_close_path (cr); |
219 | + |
220 | + cairo_fill (cr); |
221 | + } |
222 | + |
223 | + return FALSE; |
224 | +} |
225 | + |
226 | +void |
227 | +ido_application_menu_item_class_init (IdoApplicationMenuItemClass *klass) |
228 | +{ |
229 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
230 | + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
231 | + |
232 | + object_class->constructed = ido_application_menu_item_constructed; |
233 | + object_class->dispose = ido_application_menu_item_dispose; |
234 | + |
235 | + widget_class->draw = ido_application_menu_item_draw; |
236 | +} |
237 | + |
238 | +static void |
239 | +ido_application_menu_item_init (IdoApplicationMenuItem *self) |
240 | +{ |
241 | +} |
242 | + |
243 | +static void |
244 | +ido_application_menu_item_set_label (IdoApplicationMenuItem *item, |
245 | + const gchar *label) |
246 | +{ |
247 | + gtk_label_set_label (GTK_LABEL (item->label), label); |
248 | +} |
249 | + |
250 | +static void |
251 | +ido_application_menu_item_set_icon (IdoApplicationMenuItem *item, |
252 | + GIcon *icon) |
253 | +{ |
254 | + gtk_image_set_from_gicon (GTK_IMAGE (item->icon), icon, GTK_ICON_SIZE_MENU); |
255 | +} |
256 | + |
257 | +static void |
258 | +ido_application_menu_item_state_changed (IdoActionHelper *helper, |
259 | + GVariant *state, |
260 | + gpointer user_data) |
261 | +{ |
262 | + IdoApplicationMenuItem *item = user_data; |
263 | + |
264 | + item->is_running = g_variant_get_boolean (state); |
265 | + gtk_widget_queue_draw (GTK_WIDGET (item)); |
266 | +} |
267 | + |
268 | +GtkMenuItem * |
269 | +ido_application_menu_item_new_from_model (GMenuItem *menuitem, |
270 | + GActionGroup *actions) |
271 | +{ |
272 | + GtkMenuItem *item; |
273 | + gchar *label; |
274 | + GVariant *serialized_icon; |
275 | + gchar *action; |
276 | + |
277 | + item = g_object_new (IDO_TYPE_APPLICATION_MENU_ITEM, NULL); |
278 | + |
279 | + if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) |
280 | + { |
281 | + ido_application_menu_item_set_label (IDO_APPLICATION_MENU_ITEM (item), label); |
282 | + g_free (label); |
283 | + } |
284 | + |
285 | + serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL); |
286 | + if (serialized_icon) |
287 | + { |
288 | + GIcon *icon; |
289 | + |
290 | + icon = g_icon_deserialize (serialized_icon); |
291 | + if (icon) |
292 | + { |
293 | + ido_application_menu_item_set_icon (IDO_APPLICATION_MENU_ITEM (item), icon); |
294 | + g_object_unref (icon); |
295 | + } |
296 | + |
297 | + g_variant_unref (serialized_icon); |
298 | + } |
299 | + |
300 | + if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) |
301 | + { |
302 | + IdoActionHelper *helper; |
303 | + |
304 | + helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL); |
305 | + g_signal_connect (helper, "action-state-changed", |
306 | + G_CALLBACK (ido_application_menu_item_state_changed), item); |
307 | + g_signal_connect_object (item, "activate", |
308 | + G_CALLBACK (ido_action_helper_activate), helper, |
309 | + G_CONNECT_SWAPPED); |
310 | + g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); |
311 | + |
312 | + g_free (action); |
313 | + } |
314 | + |
315 | + return item; |
316 | +} |
317 | |
318 | === added file 'src/idoapplicationmenuitem.h' |
319 | --- src/idoapplicationmenuitem.h 1970-01-01 00:00:00 +0000 |
320 | +++ src/idoapplicationmenuitem.h 2013-08-13 20:56:02 +0000 |
321 | @@ -0,0 +1,36 @@ |
322 | +/* |
323 | + * Copyright 2013 Canonical Ltd. |
324 | + * |
325 | + * This program is free software: you can redistribute it and/or modify it |
326 | + * under the terms of the GNU General Public License version 3, as published |
327 | + * by the Free Software Foundation. |
328 | + * |
329 | + * This program is distributed in the hope that it will be useful, but |
330 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
331 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
332 | + * PURPOSE. See the GNU General Public License for more details. |
333 | + * |
334 | + * You should have received a copy of the GNU General Public License along |
335 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
336 | + * |
337 | + * Authors: |
338 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
339 | + */ |
340 | + |
341 | +#ifndef __IDO_APPLICATION_MENU_ITEM_H__ |
342 | +#define __IDO_APPLICATION_MENU_ITEM_H__ |
343 | + |
344 | +#include <gtk/gtk.h> |
345 | + |
346 | +#define IDO_TYPE_APPLICATION_MENU_ITEM (ido_application_menu_item_get_type ()) |
347 | +#define IDO_APPLICATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_APPLICATION_MENU_ITEM, IdoApplicationMenuItem)) |
348 | +#define IS_IDO_APPLICATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_APPLICATION_MENU_ITEM)) |
349 | + |
350 | +typedef struct _IdoApplicationMenuItem IdoApplicationMenuItem; |
351 | + |
352 | +GType ido_application_menu_item_get_type (void); |
353 | + |
354 | +GtkMenuItem * ido_application_menu_item_new_from_model (GMenuItem *item, |
355 | + GActionGroup *actions); |
356 | + |
357 | +#endif |
358 | |
359 | === added file 'src/idodetaillabel.c' |
360 | --- src/idodetaillabel.c 1970-01-01 00:00:00 +0000 |
361 | +++ src/idodetaillabel.c 2013-08-13 20:56:02 +0000 |
362 | @@ -0,0 +1,401 @@ |
363 | +/* |
364 | + * Copyright 2012 Canonical Ltd. |
365 | + * |
366 | + * This program is free software: you can redistribute it and/or modify it |
367 | + * under the terms of the GNU General Public License version 3, as published |
368 | + * by the Free Software Foundation. |
369 | + * |
370 | + * This program is distributed in the hope that it will be useful, but |
371 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
372 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
373 | + * PURPOSE. See the GNU General Public License for more details. |
374 | + * |
375 | + * You should have received a copy of the GNU General Public License along |
376 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
377 | + * |
378 | + * Authors: |
379 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
380 | + */ |
381 | + |
382 | +#include "idodetaillabel.h" |
383 | + |
384 | +#include <math.h> |
385 | + |
386 | +G_DEFINE_TYPE (IdoDetailLabel, ido_detail_label, GTK_TYPE_WIDGET) |
387 | + |
388 | +struct _IdoDetailLabelPrivate |
389 | +{ |
390 | + gchar *text; |
391 | + PangoLayout *layout; |
392 | + gboolean draw_lozenge; |
393 | +}; |
394 | + |
395 | +enum |
396 | +{ |
397 | + PROP_0, |
398 | + PROP_TEXT, |
399 | + NUM_PROPERTIES |
400 | +}; |
401 | + |
402 | +static GParamSpec *properties[NUM_PROPERTIES]; |
403 | + |
404 | +static void |
405 | +ido_detail_label_get_property (GObject *object, |
406 | + guint property_id, |
407 | + GValue *value, |
408 | + GParamSpec *pspec) |
409 | +{ |
410 | + IdoDetailLabel *self = IDO_DETAIL_LABEL (object); |
411 | + |
412 | + switch (property_id) |
413 | + { |
414 | + case PROP_TEXT: |
415 | + g_value_set_string (value, self->priv->text); |
416 | + break; |
417 | + |
418 | + default: |
419 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
420 | + } |
421 | +} |
422 | + |
423 | +static void |
424 | +ido_detail_label_set_property (GObject *object, |
425 | + guint property_id, |
426 | + const GValue *value, |
427 | + GParamSpec *pspec) |
428 | +{ |
429 | + IdoDetailLabel *self = IDO_DETAIL_LABEL (object); |
430 | + |
431 | + switch (property_id) |
432 | + { |
433 | + case PROP_TEXT: |
434 | + ido_detail_label_set_text (self, g_value_get_string (value)); |
435 | + break; |
436 | + |
437 | + default: |
438 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
439 | + } |
440 | +} |
441 | + |
442 | + |
443 | +static void |
444 | +ido_detail_label_finalize (GObject *object) |
445 | +{ |
446 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv; |
447 | + |
448 | + g_free (priv->text); |
449 | + |
450 | + G_OBJECT_CLASS (ido_detail_label_parent_class)->finalize (object); |
451 | +} |
452 | + |
453 | +static void |
454 | +ido_detail_label_dispose (GObject *object) |
455 | +{ |
456 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv; |
457 | + |
458 | + g_clear_object (&priv->layout); |
459 | + |
460 | + G_OBJECT_CLASS (ido_detail_label_parent_class)->dispose (object); |
461 | +} |
462 | + |
463 | +static void |
464 | +ido_detail_label_ensure_layout (IdoDetailLabel *label) |
465 | +{ |
466 | + IdoDetailLabelPrivate *priv = label->priv; |
467 | + |
468 | + if (priv->layout == NULL) |
469 | + { |
470 | + priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), priv->text); |
471 | + pango_layout_set_alignment (priv->layout, PANGO_ALIGN_CENTER); |
472 | + pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END); |
473 | + pango_layout_set_height (priv->layout, -1); |
474 | + |
475 | + // TODO update layout on "style-updated" and "direction-changed" |
476 | + } |
477 | +} |
478 | + |
479 | +static void |
480 | +cairo_lozenge (cairo_t *cr, |
481 | + double x, |
482 | + double y, |
483 | + double w, |
484 | + double h, |
485 | + double radius) |
486 | +{ |
487 | + double x1 = x + w - radius; |
488 | + double x2 = x + radius; |
489 | + double y1 = y + radius; |
490 | + double y2 = y + h - radius; |
491 | + |
492 | + cairo_move_to (cr, x + radius, y); |
493 | + cairo_arc (cr, x1, y1, radius, G_PI * 1.5, G_PI * 2); |
494 | + cairo_arc (cr, x1, y2, radius, 0, G_PI * 0.5); |
495 | + cairo_arc (cr, x2, y2, radius, G_PI * 0.5, G_PI); |
496 | + cairo_arc (cr, x2, y1, radius, G_PI, G_PI * 1.5); |
497 | +} |
498 | + |
499 | +static PangoFontMetrics * |
500 | +gtk_widget_get_font_metrics (GtkWidget *widget, |
501 | + PangoContext *context) |
502 | +{ |
503 | + PangoFontDescription *font; |
504 | + PangoFontMetrics *metrics; |
505 | + |
506 | + gtk_style_context_get (gtk_widget_get_style_context (widget), |
507 | + gtk_widget_get_state_flags (widget), |
508 | + "font", &font, NULL); |
509 | + |
510 | + metrics = pango_context_get_metrics (context, |
511 | + font, |
512 | + pango_context_get_language (context)); |
513 | + |
514 | + pango_font_description_free (font); |
515 | + return metrics; |
516 | +} |
517 | + |
518 | +static gint |
519 | +ido_detail_label_get_minimum_text_width (IdoDetailLabel *label) |
520 | +{ |
521 | + IdoDetailLabelPrivate *priv = label->priv; |
522 | + PangoContext *context; |
523 | + PangoFontMetrics *metrics; |
524 | + gint char_width; |
525 | + gint w; |
526 | + |
527 | + context = pango_layout_get_context (priv->layout); |
528 | + metrics = gtk_widget_get_font_metrics (GTK_WIDGET (label), context); |
529 | + char_width = pango_font_metrics_get_approximate_digit_width (metrics); |
530 | + |
531 | + w = 2 * char_width / PANGO_SCALE; |
532 | + pango_font_metrics_unref (metrics); |
533 | + return w; |
534 | +} |
535 | + |
536 | +static gboolean |
537 | +ido_detail_label_draw (GtkWidget *widget, |
538 | + cairo_t *cr) |
539 | +{ |
540 | + IdoDetailLabel *label = IDO_DETAIL_LABEL (widget); |
541 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
542 | + PangoRectangle extents; |
543 | + GtkAllocation allocation; |
544 | + double x, w, h, radius; |
545 | + GdkRGBA color; |
546 | + |
547 | + if (!priv->text || !*priv->text) |
548 | + return TRUE; |
549 | + |
550 | + gtk_widget_get_allocation (widget, &allocation); |
551 | + |
552 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
553 | + |
554 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
555 | + pango_extents_to_pixels (&extents, NULL); |
556 | + |
557 | + h = MIN (allocation.height, extents.height); |
558 | + radius = floor (h / 2.0); |
559 | + w = MAX (ido_detail_label_get_minimum_text_width (label), extents.width) + 2.0 * radius; |
560 | + x = allocation.width - w; |
561 | + |
562 | + pango_layout_set_width (priv->layout, (allocation.width - 2 * radius) * PANGO_SCALE); |
563 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
564 | + pango_extents_to_pixels (&extents, NULL); |
565 | + |
566 | + gtk_style_context_get_color (gtk_widget_get_style_context (widget), |
567 | + gtk_widget_get_state_flags (widget), |
568 | + &color); |
569 | + gdk_cairo_set_source_rgba (cr, &color); |
570 | + |
571 | + cairo_set_line_width (cr, 1.0); |
572 | + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); |
573 | + |
574 | + if (priv->draw_lozenge) |
575 | + cairo_lozenge (cr, x, 0.0, w, h, radius); |
576 | + |
577 | + cairo_move_to (cr, x + radius, (allocation.height - extents.height) / 2.0); |
578 | + pango_cairo_layout_path (cr, priv->layout); |
579 | + cairo_fill (cr); |
580 | + |
581 | + return TRUE; |
582 | +} |
583 | + |
584 | +static void |
585 | +ido_detail_label_get_preferred_width (GtkWidget *widget, |
586 | + gint *minimum, |
587 | + gint *natural) |
588 | +{ |
589 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
590 | + PangoRectangle extents; |
591 | + double radius; |
592 | + |
593 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
594 | + |
595 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
596 | + pango_extents_to_pixels (&extents, NULL); |
597 | + |
598 | + radius = floor (extents.height / 2.0); |
599 | + |
600 | + *minimum = ido_detail_label_get_minimum_text_width (IDO_DETAIL_LABEL (widget)) + 2.0 * radius; |
601 | + *natural = MAX (*minimum, extents.width + 2.0 * radius); |
602 | +} |
603 | + |
604 | +static void |
605 | +ido_detail_label_get_preferred_height (GtkWidget *widget, |
606 | + gint *minimum, |
607 | + gint *natural) |
608 | +{ |
609 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
610 | + PangoContext *context; |
611 | + PangoFontMetrics *metrics; |
612 | + PangoRectangle extents; |
613 | + |
614 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
615 | + |
616 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
617 | + pango_extents_to_pixels (&extents, NULL); |
618 | + context = pango_layout_get_context (priv->layout); |
619 | + metrics = gtk_widget_get_font_metrics (widget, context); |
620 | + |
621 | + *minimum = *natural = (pango_font_metrics_get_ascent (metrics) + |
622 | + pango_font_metrics_get_descent (metrics)) / PANGO_SCALE; |
623 | + |
624 | + pango_font_metrics_unref (metrics); |
625 | +} |
626 | + |
627 | +static void |
628 | +ido_detail_label_class_init (IdoDetailLabelClass *klass) |
629 | +{ |
630 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
631 | + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
632 | + |
633 | + object_class->get_property = ido_detail_label_get_property; |
634 | + object_class->set_property = ido_detail_label_set_property; |
635 | + object_class->finalize = ido_detail_label_finalize; |
636 | + object_class->dispose = ido_detail_label_dispose; |
637 | + |
638 | + widget_class->draw = ido_detail_label_draw; |
639 | + widget_class->get_preferred_width = ido_detail_label_get_preferred_width; |
640 | + widget_class->get_preferred_height = ido_detail_label_get_preferred_height; |
641 | + |
642 | + g_type_class_add_private (klass, sizeof (IdoDetailLabelPrivate)); |
643 | + |
644 | + properties[PROP_TEXT] = g_param_spec_string ("text", |
645 | + "Text", |
646 | + "The text of the label", |
647 | + NULL, |
648 | + G_PARAM_READWRITE | |
649 | + G_PARAM_STATIC_STRINGS); |
650 | + |
651 | + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); |
652 | +} |
653 | + |
654 | +static void |
655 | +ido_detail_label_init (IdoDetailLabel *self) |
656 | +{ |
657 | + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, |
658 | + IDO_TYPE_DETAIL_LABEL, |
659 | + IdoDetailLabelPrivate); |
660 | + |
661 | + gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); |
662 | +} |
663 | + |
664 | +GtkWidget * |
665 | +ido_detail_label_new (const gchar *label) |
666 | +{ |
667 | + return g_object_new (IDO_TYPE_DETAIL_LABEL, |
668 | + "text", label, |
669 | + NULL); |
670 | +} |
671 | + |
672 | +const gchar * |
673 | +ido_detail_label_get_text (IdoDetailLabel *label) |
674 | +{ |
675 | + g_return_val_if_fail (IDO_IS_DETAIL_LABEL (label), NULL); |
676 | + return label->priv->text; |
677 | +} |
678 | + |
679 | +/* collapse_whitespace: |
680 | + * @str: the source string |
681 | + * |
682 | + * Collapses all occurences of consecutive whitespace charactes in @str |
683 | + * into a single space. |
684 | + * |
685 | + * Returns: (transfer full): a newly-allocated string |
686 | + */ |
687 | +static gchar * |
688 | +collapse_whitespace (const gchar *str) |
689 | +{ |
690 | + GString *result; |
691 | + gboolean in_space = FALSE; |
692 | + |
693 | + if (str == NULL) |
694 | + return NULL; |
695 | + |
696 | + result = g_string_new (""); |
697 | + |
698 | + while (*str) |
699 | + { |
700 | + gunichar c = g_utf8_get_char_validated (str, -1); |
701 | + |
702 | + if (c == (gunichar) -1) |
703 | + break; |
704 | + |
705 | + if (!g_unichar_isspace (c)) |
706 | + { |
707 | + g_string_append_unichar (result, c); |
708 | + in_space = FALSE; |
709 | + } |
710 | + else if (!in_space) |
711 | + { |
712 | + g_string_append_c (result, ' '); |
713 | + in_space = TRUE; |
714 | + } |
715 | + |
716 | + str = g_utf8_next_char (str); |
717 | + } |
718 | + |
719 | + return g_string_free (result, FALSE); |
720 | +} |
721 | + |
722 | +static void |
723 | +ido_detail_label_set_text_impl (IdoDetailLabel *label, |
724 | + const gchar *text, |
725 | + gboolean draw_lozenge) |
726 | +{ |
727 | + IdoDetailLabelPrivate * priv = label->priv; |
728 | + |
729 | + g_clear_object (&priv->layout); |
730 | + g_free (priv->text); |
731 | + |
732 | + priv->text = g_strdup (text); |
733 | + priv->draw_lozenge = draw_lozenge; |
734 | + |
735 | + g_object_notify_by_pspec (G_OBJECT (label), properties[PROP_TEXT]); |
736 | + gtk_widget_queue_resize (GTK_WIDGET (label)); |
737 | +} |
738 | + |
739 | +void |
740 | +ido_detail_label_set_text (IdoDetailLabel *label, |
741 | + const gchar *text) |
742 | +{ |
743 | + gchar *str; |
744 | + |
745 | + g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); |
746 | + |
747 | + str = collapse_whitespace (text); |
748 | + ido_detail_label_set_text_impl (label, str, FALSE); |
749 | + g_free (str); |
750 | +} |
751 | + |
752 | +void |
753 | +ido_detail_label_set_count (IdoDetailLabel *label, |
754 | + gint count) |
755 | +{ |
756 | + gchar *text; |
757 | + |
758 | + g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); |
759 | + |
760 | + text = g_strdup_printf ("%d", count); |
761 | + ido_detail_label_set_text_impl (label, text, TRUE); |
762 | + g_free (text); |
763 | +} |
764 | |
765 | === added file 'src/idodetaillabel.h' |
766 | --- src/idodetaillabel.h 1970-01-01 00:00:00 +0000 |
767 | +++ src/idodetaillabel.h 2013-08-13 20:56:02 +0000 |
768 | @@ -0,0 +1,59 @@ |
769 | +/* |
770 | + * Copyright 2012 Canonical Ltd. |
771 | + * |
772 | + * This program is free software: you can redistribute it and/or modify it |
773 | + * under the terms of the GNU General Public License version 3, as published |
774 | + * by the Free Software Foundation. |
775 | + * |
776 | + * This program is distributed in the hope that it will be useful, but |
777 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
778 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
779 | + * PURPOSE. See the GNU General Public License for more details. |
780 | + * |
781 | + * You should have received a copy of the GNU General Public License along |
782 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
783 | + * |
784 | + * Authors: |
785 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
786 | + */ |
787 | + |
788 | +#ifndef __IDO_DETAIL_LABEL_H__ |
789 | +#define __IDO_DETAIL_LABEL_H__ |
790 | + |
791 | +#include <gtk/gtk.h> |
792 | + |
793 | +#define IDO_TYPE_DETAIL_LABEL (ido_detail_label_get_type()) |
794 | +#define IDO_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabel)) |
795 | +#define IDO_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) |
796 | +#define IDO_IS_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_DETAIL_LABEL)) |
797 | +#define IDO_IS_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_DETAIL_LABEL)) |
798 | +#define IDO_DETAIL_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) |
799 | + |
800 | +typedef struct _IdoDetailLabel IdoDetailLabel; |
801 | +typedef struct _IdoDetailLabelClass IdoDetailLabelClass; |
802 | +typedef struct _IdoDetailLabelPrivate IdoDetailLabelPrivate; |
803 | + |
804 | +struct _IdoDetailLabel |
805 | +{ |
806 | + GtkWidget parent; |
807 | + IdoDetailLabelPrivate *priv; |
808 | +}; |
809 | + |
810 | +struct _IdoDetailLabelClass |
811 | +{ |
812 | + GtkWidgetClass parent_class; |
813 | +}; |
814 | + |
815 | +GType ido_detail_label_get_type (void) G_GNUC_CONST; |
816 | + |
817 | +GtkWidget * ido_detail_label_new (const gchar *str); |
818 | + |
819 | +const gchar * ido_detail_label_get_text (IdoDetailLabel *label); |
820 | + |
821 | +void ido_detail_label_set_text (IdoDetailLabel *label, |
822 | + const gchar *text); |
823 | + |
824 | +void ido_detail_label_set_count (IdoDetailLabel *label, |
825 | + gint count); |
826 | + |
827 | +#endif |
828 | |
829 | === modified file 'src/idomenuitemfactory.c' |
830 | --- src/idomenuitemfactory.c 2013-07-25 23:53:48 +0000 |
831 | +++ src/idomenuitemfactory.c 2013-08-13 20:56:02 +0000 |
832 | @@ -29,6 +29,8 @@ |
833 | #include "idousermenuitem.h" |
834 | #include "idomediaplayermenuitem.h" |
835 | #include "idoplaybackmenuitem.h" |
836 | +#include "idoapplicationmenuitem.h" |
837 | +#include "idosourcemenuitem.h" |
838 | |
839 | #define IDO_TYPE_MENU_ITEM_FACTORY (ido_menu_item_factory_get_type ()) |
840 | #define IDO_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_MENU_ITEM_FACTORY, IdoMenuItemFactory)) |
841 | @@ -83,6 +85,12 @@ |
842 | else if (g_str_equal (type, "com.canonical.unity.playback-item")) |
843 | item = ido_playback_menu_item_new_from_model (menuitem, actions); |
844 | |
845 | + else if (g_str_equal (type, "com.canonical.application")) |
846 | + item = ido_application_menu_item_new_from_model (menuitem, actions); |
847 | + |
848 | + else if (g_str_equal (type, "com.canonical.indicator.messages.source")) |
849 | + item = ido_source_menu_item_new_from_menu_model (menuitem, actions); |
850 | + |
851 | return item; |
852 | } |
853 | |
854 | |
855 | === added file 'src/idosourcemenuitem.c' |
856 | --- src/idosourcemenuitem.c 1970-01-01 00:00:00 +0000 |
857 | +++ src/idosourcemenuitem.c 2013-08-13 20:56:02 +0000 |
858 | @@ -0,0 +1,264 @@ |
859 | +/* |
860 | + * Copyright 2013 Canonical Ltd. |
861 | + * |
862 | + * This program is free software: you can redistribute it and/or modify it |
863 | + * under the terms of the GNU General Public License version 3, as published |
864 | + * by the Free Software Foundation. |
865 | + * |
866 | + * This program is distributed in the hope that it will be useful, but |
867 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
868 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
869 | + * PURPOSE. See the GNU General Public License for more details. |
870 | + * |
871 | + * You should have received a copy of the GNU General Public License along |
872 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
873 | + * |
874 | + * Authors: |
875 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
876 | + */ |
877 | + |
878 | +#include "idosourcemenuitem.h" |
879 | + |
880 | +#include <libintl.h> |
881 | +#include "idodetaillabel.h" |
882 | +#include "idoactionhelper.h" |
883 | + |
884 | +typedef GtkMenuItemClass IdoSourceMenuItemClass; |
885 | + |
886 | +struct _IdoSourceMenuItem |
887 | +{ |
888 | + GtkMenuItem parent; |
889 | + |
890 | + GtkWidget *icon; |
891 | + GtkWidget *label; |
892 | + GtkWidget *detail; |
893 | + |
894 | + gint64 time; |
895 | + guint timer_id; |
896 | +}; |
897 | + |
898 | +G_DEFINE_TYPE (IdoSourceMenuItem, ido_source_menu_item, GTK_TYPE_MENU_ITEM); |
899 | + |
900 | +static void |
901 | +ido_source_menu_item_constructed (GObject *object) |
902 | +{ |
903 | + IdoSourceMenuItem *item = IDO_SOURCE_MENU_ITEM (object); |
904 | + GtkWidget *grid; |
905 | + gint icon_width; |
906 | + |
907 | + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, NULL); |
908 | + |
909 | + item->icon = g_object_ref (gtk_image_new ()); |
910 | + gtk_widget_set_margin_left (item->icon, icon_width); |
911 | + gtk_widget_set_margin_right (item->icon, 6); |
912 | + |
913 | + item->label = g_object_ref (gtk_label_new ("")); |
914 | + gtk_label_set_max_width_chars (GTK_LABEL (item->label), 40); |
915 | + gtk_label_set_ellipsize (GTK_LABEL (item->label), PANGO_ELLIPSIZE_END); |
916 | + gtk_misc_set_alignment (GTK_MISC (item->label), 0.0, 0.5); |
917 | + |
918 | + item->detail = g_object_ref (ido_detail_label_new ("")); |
919 | + gtk_widget_set_halign (item->detail, GTK_ALIGN_END); |
920 | + gtk_widget_set_hexpand (item->detail, TRUE); |
921 | + gtk_style_context_add_class (gtk_widget_get_style_context (item->detail), "accelerator"); |
922 | + |
923 | + grid = gtk_grid_new (); |
924 | + gtk_grid_attach (GTK_GRID (grid), item->icon, 0, 0, 1, 1); |
925 | + gtk_grid_attach (GTK_GRID (grid), item->label, 1, 0, 1, 1); |
926 | + gtk_grid_attach (GTK_GRID (grid), item->detail, 2, 0, 1, 1); |
927 | + |
928 | + gtk_container_add (GTK_CONTAINER (object), grid); |
929 | + gtk_widget_show_all (grid); |
930 | + |
931 | + G_OBJECT_CLASS (ido_source_menu_item_parent_class)->constructed (object); |
932 | +} |
933 | + |
934 | +static gchar * |
935 | +ido_source_menu_item_time_span_string (gint64 timestamp) |
936 | +{ |
937 | + gchar *str; |
938 | + gint64 span; |
939 | + gint hours; |
940 | + gint minutes; |
941 | + |
942 | + span = MAX (g_get_real_time () - timestamp, 0) / G_USEC_PER_SEC; |
943 | + hours = span / 3600; |
944 | + minutes = (span / 60) % 60; |
945 | + |
946 | + if (hours == 0) |
947 | + { |
948 | + /* TRANSLATORS: number of minutes that have passed */ |
949 | + str = g_strdup_printf (ngettext ("%d min", "%d min", minutes), minutes); |
950 | + } |
951 | + else |
952 | + { |
953 | + /* TRANSLATORS: number of hours that have passed */ |
954 | + str = g_strdup_printf (ngettext ("%d h", "%d h", hours), hours); |
955 | + } |
956 | + |
957 | + return str; |
958 | +} |
959 | + |
960 | +static void |
961 | +ido_source_menu_item_set_detail_time (IdoSourceMenuItem *self, |
962 | + gint64 time) |
963 | +{ |
964 | + gchar *str; |
965 | + |
966 | + self->time = time; |
967 | + |
968 | + str = ido_source_menu_item_time_span_string (self->time); |
969 | + ido_detail_label_set_text (IDO_DETAIL_LABEL (self->detail), str); |
970 | + |
971 | + g_free (str); |
972 | +} |
973 | + |
974 | +static gboolean |
975 | +ido_source_menu_item_update_time (gpointer data) |
976 | +{ |
977 | + IdoSourceMenuItem *self = data; |
978 | + |
979 | + ido_source_menu_item_set_detail_time (self, self->time); |
980 | + |
981 | + return TRUE; |
982 | +} |
983 | + |
984 | +static void |
985 | +ido_source_menu_item_dispose (GObject *object) |
986 | +{ |
987 | + IdoSourceMenuItem *self = IDO_SOURCE_MENU_ITEM (object); |
988 | + |
989 | + if (self->timer_id != 0) |
990 | + { |
991 | + g_source_remove (self->timer_id); |
992 | + self->timer_id = 0; |
993 | + } |
994 | + |
995 | + g_clear_object (&self->icon); |
996 | + g_clear_object (&self->label); |
997 | + g_clear_object (&self->detail); |
998 | + |
999 | + G_OBJECT_CLASS (ido_source_menu_item_parent_class)->dispose (object); |
1000 | +} |
1001 | + |
1002 | +static void |
1003 | +ido_source_menu_item_class_init (IdoSourceMenuItemClass *klass) |
1004 | +{ |
1005 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1006 | + |
1007 | + object_class->constructed = ido_source_menu_item_constructed; |
1008 | + object_class->dispose = ido_source_menu_item_dispose; |
1009 | +} |
1010 | + |
1011 | +static void |
1012 | +ido_source_menu_item_init (IdoSourceMenuItem *self) |
1013 | +{ |
1014 | +} |
1015 | + |
1016 | +static void |
1017 | +ido_source_menu_item_set_label (IdoSourceMenuItem *item, |
1018 | + const gchar *label) |
1019 | +{ |
1020 | + gtk_label_set_label (GTK_LABEL (item->label), label ? label : ""); |
1021 | +} |
1022 | + |
1023 | +static void |
1024 | +ido_source_menu_item_set_icon (IdoSourceMenuItem *item, |
1025 | + GIcon *icon) |
1026 | +{ |
1027 | + if (icon) |
1028 | + gtk_image_set_from_gicon (GTK_IMAGE (item->icon), icon, GTK_ICON_SIZE_MENU); |
1029 | + else |
1030 | + gtk_image_clear (GTK_IMAGE (item->icon)); |
1031 | +} |
1032 | + |
1033 | + |
1034 | +static void |
1035 | +ido_source_menu_item_activate (GtkMenuItem *item, |
1036 | + gpointer user_data) |
1037 | +{ |
1038 | + IdoActionHelper *helper = user_data; |
1039 | + |
1040 | + /* The parameter signifies whether this source was activated (TRUE) or |
1041 | + * dismissed (FALSE). Since there's no UI to dismiss a gtkmenuitem, |
1042 | + * this always passes TRUE. */ |
1043 | + ido_action_helper_activate_with_parameter (helper, g_variant_new_boolean (TRUE)); |
1044 | +} |
1045 | + |
1046 | +static void |
1047 | +ido_source_menu_item_state_changed (IdoActionHelper *helper, |
1048 | + GVariant *state, |
1049 | + gpointer user_data) |
1050 | +{ |
1051 | + IdoSourceMenuItem *item = user_data; |
1052 | + guint32 count; |
1053 | + gint64 time; |
1054 | + const gchar *str; |
1055 | + |
1056 | + if (item->timer_id != 0) |
1057 | + { |
1058 | + g_source_remove (item->timer_id); |
1059 | + item->timer_id = 0; |
1060 | + } |
1061 | + |
1062 | + g_return_val_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")), FALSE); |
1063 | + |
1064 | + g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL); |
1065 | + |
1066 | + if (count != 0) |
1067 | + ido_detail_label_set_count (IDO_DETAIL_LABEL (item->detail), count); |
1068 | + else if (time != 0) |
1069 | + { |
1070 | + ido_source_menu_item_set_detail_time (item, time); |
1071 | + item->timer_id = g_timeout_add_seconds (59, ido_source_menu_item_update_time, item); |
1072 | + } |
1073 | + else if (str != NULL && *str) |
1074 | + ido_detail_label_set_text (IDO_DETAIL_LABEL (item->detail), str); |
1075 | +} |
1076 | + |
1077 | +GtkMenuItem * |
1078 | +ido_source_menu_item_new_from_menu_model (GMenuItem *menuitem, |
1079 | + GActionGroup *actions) |
1080 | +{ |
1081 | + GtkMenuItem *item; |
1082 | + GVariant *serialized_icon; |
1083 | + GIcon *icon = NULL; |
1084 | + gchar *label; |
1085 | + gchar *action = NULL; |
1086 | + |
1087 | + item = g_object_new (IDO_TYPE_SOURCE_MENU_ITEM, NULL); |
1088 | + |
1089 | + if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) |
1090 | + { |
1091 | + ido_source_menu_item_set_label (IDO_SOURCE_MENU_ITEM (item), label); |
1092 | + g_free (label); |
1093 | + } |
1094 | + |
1095 | + serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL); |
1096 | + if (serialized_icon) |
1097 | + { |
1098 | + icon = g_icon_deserialize (serialized_icon); |
1099 | + g_variant_unref (serialized_icon); |
1100 | + } |
1101 | + ido_source_menu_item_set_icon (IDO_SOURCE_MENU_ITEM (item), icon); |
1102 | + |
1103 | + if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) |
1104 | + { |
1105 | + IdoActionHelper *helper; |
1106 | + |
1107 | + helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL); |
1108 | + g_signal_connect (helper, "action-state-changed", |
1109 | + G_CALLBACK (ido_source_menu_item_state_changed), item); |
1110 | + g_signal_connect_object (item, "activate", |
1111 | + G_CALLBACK (ido_source_menu_item_activate), helper, |
1112 | + 0); |
1113 | + g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); |
1114 | + |
1115 | + g_free (action); |
1116 | + } |
1117 | + |
1118 | + if (icon) |
1119 | + g_object_unref (icon); |
1120 | + |
1121 | + return item; |
1122 | +} |
1123 | |
1124 | === added file 'src/idosourcemenuitem.h' |
1125 | --- src/idosourcemenuitem.h 1970-01-01 00:00:00 +0000 |
1126 | +++ src/idosourcemenuitem.h 2013-08-13 20:56:02 +0000 |
1127 | @@ -0,0 +1,36 @@ |
1128 | +/* |
1129 | + * Copyright 2013 Canonical Ltd. |
1130 | + * |
1131 | + * This program is free software: you can redistribute it and/or modify it |
1132 | + * under the terms of the GNU General Public License version 3, as published |
1133 | + * by the Free Software Foundation. |
1134 | + * |
1135 | + * This program is distributed in the hope that it will be useful, but |
1136 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1137 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1138 | + * PURPOSE. See the GNU General Public License for more details. |
1139 | + * |
1140 | + * You should have received a copy of the GNU General Public License along |
1141 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1142 | + * |
1143 | + * Authors: |
1144 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
1145 | + */ |
1146 | + |
1147 | +#ifndef __IDO_SOURCE_MENU_ITEM_H__ |
1148 | +#define __IDO_SOURCE_MENU_ITEM_H__ |
1149 | + |
1150 | +#include <gtk/gtk.h> |
1151 | + |
1152 | +#define IDO_TYPE_SOURCE_MENU_ITEM (ido_source_menu_item_get_type ()) |
1153 | +#define IDO_SOURCE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_SOURCE_MENU_ITEM, IdoSourceMenuItem)) |
1154 | +#define IDO_IS_SOURCE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_SOURCE_MENU_ITEM)) |
1155 | + |
1156 | +typedef struct _IdoSourceMenuItem IdoSourceMenuItem; |
1157 | + |
1158 | +GType ido_source_menu_item_get_type (void); |
1159 | + |
1160 | +GtkMenuItem * ido_source_menu_item_new_from_menu_model (GMenuItem *menuitem, |
1161 | + GActionGroup *actions); |
1162 | + |
1163 | +#endif |
FAILED: Continuous integration, rev:146 jenkins. qa.ubuntu. com/job/ ido-ci/ 32/ jenkins. qa.ubuntu. com/job/ ido-saucy- amd64-ci/ 31/console jenkins. qa.ubuntu. com/job/ ido-saucy- armhf-ci/ 14/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ ido-ci/ 32/rebuild
http://