Merge lp:~larsu/indicator-messages/draw-lozenges into lp:indicator-messages/12.10
- draw-lozenges
- Merge into trunk.12.10
Status: | Merged |
---|---|
Approved by: | Lars Karlitski |
Approved revision: | 310 |
Merged at revision: | 307 |
Proposed branch: | lp:~larsu/indicator-messages/draw-lozenges |
Merge into: | lp:indicator-messages/12.10 |
Diff against target: |
623 lines (+484/-62) 4 files modified
src/Makefile.am (+2/-0) src/ido-detail-label.c (+396/-0) src/ido-detail-label.h (+59/-0) src/im-source-menu-item.c (+27/-62) |
To merge this branch: | bzr merge lp:~larsu/indicator-messages/draw-lozenges |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
jenkins (community) | continuous-integration | Needs Fixing | |
Charles Kerr (community) | Approve | ||
Review via email: mp+122522@code.launchpad.net |
Commit message
Draw counts as lozenges again.
Introduces IdoDetailLabel, a GtkWidget that renders detail strings (e.g. as lozenges) on the right side of a menu item.
Description of the change
Put lozenges back into the messaging menu.
I factored lozenge drawing out into its own widget IdoDetailLabel. It draws both lozenges and other detail labels, so that the text inside lozenges and the text of other labels line up on the right side.
jenkins (martin-mrazik+qa) wrote : | # |
Charles Kerr (charlesk) wrote : | # |
Adding a separate widget is a much cleaner approach than the previous numbers_draw_cb(). Nice work. :)
Needs Fixing:
* ido_detail_
* ido_detail_
Comment:
* ido_detail_
static void
ido_detail_
{
IdoDetailLabe
g_clear_object (&priv->layout);
g_free (priv->text);
priv->text = g_strdup (text);
priv-
g_object_
gtk_widget_
}
void
ido_detail_
{
g_return_if_fail (IDO_IS_
gchar * text = g_strdup_printf ("%d", count);
ido_detail_
g_free (text);
}
void
ido_detail_
{
g_return_if_fail (IDO_IS_
gchar * str = collapse_whitespace (text);
ido_detail_
g_free (str);
}
Lars Karlitski (larsu) wrote : | # |
> Needs Fixing:
>
> * ido_detail_
>
> * ido_detail_
Argh, fixed in r309.
> Comment:
> * ido_detail_
> duplicate code from _set_text() and _set_count(), but it leaves the widget in an odd state
> (dangling pointer) and, more importantly, there's still a lot of duplicated code in
> _set_text() and _set_count(). How about something like this:
Yeah, *much* better. Implemented as suggested (with minor style changes to keep it consistent) in r310.
Thank you!
Charles Kerr (charlesk) : | # |
jenkins (martin-mrazik+qa) wrote : | # |
FAILED: Continuous integration, rev:310
http://
Executed test runs:
FAILURE: http://
jenkins (martin-mrazik+qa) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
jenkins (martin-mrazik+qa) wrote : | # |
PASSED: Continuous integration, rev:310
http://
Executed test runs:
SUCCESS: http://
jenkins (martin-mrazik+qa) wrote : | # |
FAILED: Autolanding.
No commit message was specified.
http://
Preview Diff
1 | === modified file 'src/Makefile.am' |
2 | --- src/Makefile.am 2012-08-27 13:38:04 +0000 |
3 | +++ src/Makefile.am 2012-09-04 17:24:18 +0000 |
4 | @@ -21,6 +21,8 @@ |
5 | im-app-menu-item.h \ |
6 | im-source-menu-item.c \ |
7 | im-source-menu-item.h \ |
8 | + ido-detail-label.c \ |
9 | + ido-detail-label.h \ |
10 | indicator-messages-service.c \ |
11 | indicator-messages-service.h |
12 | dbus-data.h |
13 | |
14 | === added file 'src/ido-detail-label.c' |
15 | --- src/ido-detail-label.c 1970-01-01 00:00:00 +0000 |
16 | +++ src/ido-detail-label.c 2012-09-04 17:24:18 +0000 |
17 | @@ -0,0 +1,396 @@ |
18 | +/* |
19 | + * Copyright 2012 Canonical Ltd. |
20 | + * |
21 | + * This program is free software: you can redistribute it and/or modify it |
22 | + * under the terms of the GNU General Public License version 3, as published |
23 | + * by the Free Software Foundation. |
24 | + * |
25 | + * This program is distributed in the hope that it will be useful, but |
26 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
27 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
28 | + * PURPOSE. See the GNU General Public License for more details. |
29 | + * |
30 | + * You should have received a copy of the GNU General Public License along |
31 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
32 | + * |
33 | + * Authors: |
34 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
35 | + */ |
36 | + |
37 | +#include "ido-detail-label.h" |
38 | + |
39 | +#include <math.h> |
40 | + |
41 | +G_DEFINE_TYPE (IdoDetailLabel, ido_detail_label, GTK_TYPE_WIDGET) |
42 | + |
43 | +struct _IdoDetailLabelPrivate |
44 | +{ |
45 | + gchar *text; |
46 | + PangoLayout *layout; |
47 | + gboolean draw_lozenge; |
48 | +}; |
49 | + |
50 | +enum |
51 | +{ |
52 | + PROP_0, |
53 | + PROP_TEXT, |
54 | + NUM_PROPERTIES |
55 | +}; |
56 | + |
57 | +static GParamSpec *properties[NUM_PROPERTIES]; |
58 | + |
59 | +static void |
60 | +ido_detail_label_get_property (GObject *object, |
61 | + guint property_id, |
62 | + GValue *value, |
63 | + GParamSpec *pspec) |
64 | +{ |
65 | + IdoDetailLabel *self = IDO_DETAIL_LABEL (object); |
66 | + |
67 | + switch (property_id) |
68 | + { |
69 | + case PROP_TEXT: |
70 | + g_value_set_string (value, self->priv->text); |
71 | + break; |
72 | + |
73 | + default: |
74 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
75 | + } |
76 | +} |
77 | + |
78 | +static void |
79 | +ido_detail_label_set_property (GObject *object, |
80 | + guint property_id, |
81 | + const GValue *value, |
82 | + GParamSpec *pspec) |
83 | +{ |
84 | + IdoDetailLabel *self = IDO_DETAIL_LABEL (object); |
85 | + |
86 | + switch (property_id) |
87 | + { |
88 | + case PROP_TEXT: |
89 | + ido_detail_label_set_text (self, g_value_get_string (value)); |
90 | + break; |
91 | + |
92 | + default: |
93 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
94 | + } |
95 | +} |
96 | + |
97 | + |
98 | +static void |
99 | +ido_detail_label_finalize (GObject *object) |
100 | +{ |
101 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv; |
102 | + |
103 | + g_free (priv->text); |
104 | + |
105 | + G_OBJECT_CLASS (ido_detail_label_parent_class)->finalize (object); |
106 | +} |
107 | + |
108 | +static void |
109 | +ido_detail_label_dispose (GObject *object) |
110 | +{ |
111 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv; |
112 | + |
113 | + g_clear_object (&priv->layout); |
114 | + |
115 | + G_OBJECT_CLASS (ido_detail_label_parent_class)->dispose (object); |
116 | +} |
117 | + |
118 | +static void |
119 | +ido_detail_label_ensure_layout (IdoDetailLabel *label) |
120 | +{ |
121 | + IdoDetailLabelPrivate *priv = label->priv; |
122 | + |
123 | + if (priv->layout == NULL) |
124 | + { |
125 | + priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), priv->text); |
126 | + pango_layout_set_alignment (priv->layout, PANGO_ALIGN_CENTER); |
127 | + pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END); |
128 | + pango_layout_set_height (priv->layout, -1); |
129 | + |
130 | + // TODO update layout on "style-updated" and "direction-changed" |
131 | + } |
132 | +} |
133 | + |
134 | +static void |
135 | +cairo_lozenge (cairo_t *cr, |
136 | + double x, |
137 | + double y, |
138 | + double w, |
139 | + double h, |
140 | + double radius) |
141 | +{ |
142 | + double x1 = x + w - radius; |
143 | + double x2 = x + radius; |
144 | + double y1 = y + radius; |
145 | + double y2 = y + h - radius; |
146 | + |
147 | + cairo_move_to (cr, x + radius, y); |
148 | + cairo_arc (cr, x1, y1, radius, G_PI * 1.5, G_PI * 2); |
149 | + cairo_arc (cr, x1, y2, radius, 0, G_PI * 0.5); |
150 | + cairo_arc (cr, x2, y2, radius, G_PI * 0.5, G_PI); |
151 | + cairo_arc (cr, x2, y1, radius, G_PI, G_PI * 1.5); |
152 | +} |
153 | + |
154 | +static PangoFontMetrics * |
155 | +gtk_widget_get_font_metrics (GtkWidget *widget, |
156 | + PangoContext *context) |
157 | +{ |
158 | + const PangoFontDescription *font; |
159 | + |
160 | + font = gtk_style_context_get_font (gtk_widget_get_style_context (widget), |
161 | + gtk_widget_get_state_flags (widget)); |
162 | + |
163 | + return pango_context_get_metrics (context, |
164 | + font, |
165 | + pango_context_get_language (context)); |
166 | +} |
167 | + |
168 | +static gint |
169 | +ido_detail_label_get_minimum_text_width (IdoDetailLabel *label) |
170 | +{ |
171 | + IdoDetailLabelPrivate *priv = label->priv; |
172 | + PangoContext *context; |
173 | + PangoFontMetrics *metrics; |
174 | + gint char_width; |
175 | + gint w; |
176 | + |
177 | + context = pango_layout_get_context (priv->layout); |
178 | + metrics = gtk_widget_get_font_metrics (GTK_WIDGET (label), context); |
179 | + char_width = pango_font_metrics_get_approximate_digit_width (metrics); |
180 | + |
181 | + w = 2 * char_width / PANGO_SCALE; |
182 | + pango_font_metrics_unref (metrics); |
183 | + return w; |
184 | +} |
185 | + |
186 | +static gboolean |
187 | +ido_detail_label_draw (GtkWidget *widget, |
188 | + cairo_t *cr) |
189 | +{ |
190 | + IdoDetailLabel *label = IDO_DETAIL_LABEL (widget); |
191 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
192 | + PangoRectangle extents; |
193 | + GtkAllocation allocation; |
194 | + double x, w, h, radius; |
195 | + GdkRGBA color; |
196 | + |
197 | + if (!priv->text || !*priv->text) |
198 | + return TRUE; |
199 | + |
200 | + gtk_widget_get_allocation (widget, &allocation); |
201 | + |
202 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
203 | + |
204 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
205 | + pango_extents_to_pixels (&extents, NULL); |
206 | + |
207 | + h = MIN (allocation.height, extents.height); |
208 | + radius = floor (h / 2.0); |
209 | + w = MAX (ido_detail_label_get_minimum_text_width (label), extents.width) + 2.0 * radius; |
210 | + x = allocation.width - w; |
211 | + |
212 | + pango_layout_set_width (priv->layout, (allocation.width - 2 * radius) * PANGO_SCALE); |
213 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
214 | + pango_extents_to_pixels (&extents, NULL); |
215 | + |
216 | + gtk_style_context_get_color (gtk_widget_get_style_context (widget), |
217 | + gtk_widget_get_state_flags (widget), |
218 | + &color); |
219 | + gdk_cairo_set_source_rgba (cr, &color); |
220 | + |
221 | + cairo_set_line_width (cr, 1.0); |
222 | + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); |
223 | + |
224 | + if (priv->draw_lozenge) |
225 | + cairo_lozenge (cr, x, 0.0, w, h, radius); |
226 | + |
227 | + cairo_move_to (cr, x + radius, (allocation.height - extents.height) / 2.0); |
228 | + pango_cairo_layout_path (cr, priv->layout); |
229 | + cairo_fill (cr); |
230 | + |
231 | + return TRUE; |
232 | +} |
233 | + |
234 | +static void |
235 | +ido_detail_label_get_preferred_width (GtkWidget *widget, |
236 | + gint *minimum, |
237 | + gint *natural) |
238 | +{ |
239 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
240 | + PangoRectangle extents; |
241 | + double radius; |
242 | + |
243 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
244 | + |
245 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
246 | + pango_extents_to_pixels (&extents, NULL); |
247 | + |
248 | + radius = floor (extents.height / 2.0); |
249 | + |
250 | + *minimum = ido_detail_label_get_minimum_text_width (IDO_DETAIL_LABEL (widget)) + 2.0 * radius; |
251 | + *natural = MAX (*minimum, extents.width + 2.0 * radius); |
252 | +} |
253 | + |
254 | +static void |
255 | +ido_detail_label_get_preferred_height (GtkWidget *widget, |
256 | + gint *minimum, |
257 | + gint *natural) |
258 | +{ |
259 | + IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv; |
260 | + PangoContext *context; |
261 | + PangoFontMetrics *metrics; |
262 | + PangoRectangle extents; |
263 | + |
264 | + ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); |
265 | + |
266 | + pango_layout_get_extents (priv->layout, NULL, &extents); |
267 | + pango_extents_to_pixels (&extents, NULL); |
268 | + context = pango_layout_get_context (priv->layout); |
269 | + metrics = gtk_widget_get_font_metrics (widget, context); |
270 | + |
271 | + *minimum = *natural = (pango_font_metrics_get_ascent (metrics) + |
272 | + pango_font_metrics_get_descent (metrics)) / PANGO_SCALE; |
273 | + |
274 | + pango_font_metrics_unref (metrics); |
275 | +} |
276 | + |
277 | +static void |
278 | +ido_detail_label_class_init (IdoDetailLabelClass *klass) |
279 | +{ |
280 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
281 | + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
282 | + |
283 | + object_class->get_property = ido_detail_label_get_property; |
284 | + object_class->set_property = ido_detail_label_set_property; |
285 | + object_class->finalize = ido_detail_label_finalize; |
286 | + object_class->dispose = ido_detail_label_dispose; |
287 | + |
288 | + widget_class->draw = ido_detail_label_draw; |
289 | + widget_class->get_preferred_width = ido_detail_label_get_preferred_width; |
290 | + widget_class->get_preferred_height = ido_detail_label_get_preferred_height; |
291 | + |
292 | + g_type_class_add_private (klass, sizeof (IdoDetailLabelPrivate)); |
293 | + |
294 | + properties[PROP_TEXT] = g_param_spec_string ("text", |
295 | + "Text", |
296 | + "The text of the label", |
297 | + NULL, |
298 | + G_PARAM_READWRITE | |
299 | + G_PARAM_STATIC_STRINGS); |
300 | + |
301 | + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); |
302 | +} |
303 | + |
304 | +static void |
305 | +ido_detail_label_init (IdoDetailLabel *self) |
306 | +{ |
307 | + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, |
308 | + IDO_TYPE_DETAIL_LABEL, |
309 | + IdoDetailLabelPrivate); |
310 | + |
311 | + gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); |
312 | +} |
313 | + |
314 | +GtkWidget * |
315 | +ido_detail_label_new (const gchar *label) |
316 | +{ |
317 | + return g_object_new (IDO_TYPE_DETAIL_LABEL, |
318 | + "text", label, |
319 | + NULL); |
320 | +} |
321 | + |
322 | +const gchar * |
323 | +ido_detail_label_get_text (IdoDetailLabel *label) |
324 | +{ |
325 | + g_return_val_if_fail (IDO_IS_DETAIL_LABEL (label), NULL); |
326 | + return label->priv->text; |
327 | +} |
328 | + |
329 | +/* collapse_whitespace: |
330 | + * @str: the source string |
331 | + * |
332 | + * Collapses all occurences of consecutive whitespace charactes in @str |
333 | + * into a single space. |
334 | + * |
335 | + * Returns: (transfer full): a newly-allocated string |
336 | + */ |
337 | +static gchar * |
338 | +collapse_whitespace (const gchar *str) |
339 | +{ |
340 | + GString *result; |
341 | + gboolean in_space = FALSE; |
342 | + |
343 | + if (str == NULL) |
344 | + return NULL; |
345 | + |
346 | + result = g_string_new (""); |
347 | + |
348 | + while (*str) |
349 | + { |
350 | + gunichar c = g_utf8_get_char_validated (str, -1); |
351 | + |
352 | + if (c < 0) |
353 | + break; |
354 | + |
355 | + if (!g_unichar_isspace (c)) |
356 | + { |
357 | + g_string_append_unichar (result, c); |
358 | + in_space = FALSE; |
359 | + } |
360 | + else if (!in_space) |
361 | + { |
362 | + g_string_append_c (result, ' '); |
363 | + in_space = TRUE; |
364 | + } |
365 | + |
366 | + str = g_utf8_next_char (str); |
367 | + } |
368 | + |
369 | + return g_string_free (result, FALSE); |
370 | +} |
371 | + |
372 | +static void |
373 | +ido_detail_label_set_text_impl (IdoDetailLabel *label, |
374 | + const gchar *text, |
375 | + gboolean draw_lozenge) |
376 | +{ |
377 | + IdoDetailLabelPrivate * priv = label->priv; |
378 | + |
379 | + g_clear_object (&priv->layout); |
380 | + g_free (priv->text); |
381 | + |
382 | + priv->text = g_strdup (text); |
383 | + priv->draw_lozenge = draw_lozenge; |
384 | + |
385 | + g_object_notify_by_pspec (G_OBJECT (label), properties[PROP_TEXT]); |
386 | + gtk_widget_queue_resize (GTK_WIDGET (label)); |
387 | +} |
388 | + |
389 | +void |
390 | +ido_detail_label_set_text (IdoDetailLabel *label, |
391 | + const gchar *text) |
392 | +{ |
393 | + gchar *str; |
394 | + |
395 | + g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); |
396 | + |
397 | + str = collapse_whitespace (text); |
398 | + ido_detail_label_set_text_impl (label, str, FALSE); |
399 | + g_free (str); |
400 | +} |
401 | + |
402 | +void |
403 | +ido_detail_label_set_count (IdoDetailLabel *label, |
404 | + gint count) |
405 | +{ |
406 | + gchar *text; |
407 | + |
408 | + g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); |
409 | + |
410 | + text = g_strdup_printf ("%d", count); |
411 | + ido_detail_label_set_text_impl (label, text, TRUE); |
412 | + g_free (text); |
413 | +} |
414 | |
415 | === added file 'src/ido-detail-label.h' |
416 | --- src/ido-detail-label.h 1970-01-01 00:00:00 +0000 |
417 | +++ src/ido-detail-label.h 2012-09-04 17:24:18 +0000 |
418 | @@ -0,0 +1,59 @@ |
419 | +/* |
420 | + * Copyright 2012 Canonical Ltd. |
421 | + * |
422 | + * This program is free software: you can redistribute it and/or modify it |
423 | + * under the terms of the GNU General Public License version 3, as published |
424 | + * by the Free Software Foundation. |
425 | + * |
426 | + * This program is distributed in the hope that it will be useful, but |
427 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
428 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
429 | + * PURPOSE. See the GNU General Public License for more details. |
430 | + * |
431 | + * You should have received a copy of the GNU General Public License along |
432 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
433 | + * |
434 | + * Authors: |
435 | + * Lars Uebernickel <lars.uebernickel@canonical.com> |
436 | + */ |
437 | + |
438 | +#ifndef __IDO_DETAIL_LABEL_H__ |
439 | +#define __IDO_DETAIL_LABEL_H__ |
440 | + |
441 | +#include <gtk/gtk.h> |
442 | + |
443 | +#define IDO_TYPE_DETAIL_LABEL (ido_detail_label_get_type()) |
444 | +#define IDO_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabel)) |
445 | +#define IDO_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) |
446 | +#define IDO_IS_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_DETAIL_LABEL)) |
447 | +#define IDO_IS_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_DETAIL_LABEL)) |
448 | +#define IDO_DETAIL_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) |
449 | + |
450 | +typedef struct _IdoDetailLabel IdoDetailLabel; |
451 | +typedef struct _IdoDetailLabelClass IdoDetailLabelClass; |
452 | +typedef struct _IdoDetailLabelPrivate IdoDetailLabelPrivate; |
453 | + |
454 | +struct _IdoDetailLabel |
455 | +{ |
456 | + GtkWidget parent; |
457 | + IdoDetailLabelPrivate *priv; |
458 | +}; |
459 | + |
460 | +struct _IdoDetailLabelClass |
461 | +{ |
462 | + GtkWidgetClass parent_class; |
463 | +}; |
464 | + |
465 | +GType ido_detail_label_get_type (void) G_GNUC_CONST; |
466 | + |
467 | +GtkWidget * ido_detail_label_new (const gchar *str); |
468 | + |
469 | +const gchar * ido_detail_label_get_text (IdoDetailLabel *label); |
470 | + |
471 | +void ido_detail_label_set_text (IdoDetailLabel *label, |
472 | + const gchar *text); |
473 | + |
474 | +void ido_detail_label_set_count (IdoDetailLabel *label, |
475 | + gint count); |
476 | + |
477 | +#endif |
478 | |
479 | === modified file 'src/im-source-menu-item.c' |
480 | --- src/im-source-menu-item.c 2012-08-27 14:42:05 +0000 |
481 | +++ src/im-source-menu-item.c 2012-09-04 17:24:18 +0000 |
482 | @@ -20,6 +20,7 @@ |
483 | #include "im-source-menu-item.h" |
484 | |
485 | #include <libintl.h> |
486 | +#include "ido-detail-label.h" |
487 | |
488 | struct _ImSourceMenuItemPrivate |
489 | { |
490 | @@ -59,11 +60,13 @@ |
491 | gtk_widget_set_margin_left (priv->icon, icon_width + 6); |
492 | |
493 | priv->label = g_object_ref (gtk_label_new ("")); |
494 | + gtk_label_set_max_width_chars (GTK_LABEL (priv->label), 40); |
495 | + gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END); |
496 | + gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5); |
497 | |
498 | - priv->detail = g_object_ref (gtk_label_new ("")); |
499 | + priv->detail = g_object_ref (ido_detail_label_new ("")); |
500 | gtk_widget_set_halign (priv->detail, GTK_ALIGN_END); |
501 | gtk_widget_set_hexpand (priv->detail, TRUE); |
502 | - gtk_misc_set_alignment (GTK_MISC (priv->label), 1.0, 0.5); |
503 | gtk_style_context_add_class (gtk_widget_get_style_context (priv->detail), "accelerator"); |
504 | |
505 | grid = gtk_grid_new (); |
506 | @@ -77,49 +80,6 @@ |
507 | G_OBJECT_CLASS (im_source_menu_item_parent_class)->constructed (object); |
508 | } |
509 | |
510 | -/* collapse_whitespace: |
511 | - * @str: the source string |
512 | - * |
513 | - * Collapses all occurences of consecutive whitespace charactes in @str |
514 | - * into a single space. |
515 | - * |
516 | - * Returns: (transfer full): a newly-allocated string |
517 | - */ |
518 | -static gchar * |
519 | -collapse_whitespace (const gchar *str) |
520 | -{ |
521 | - GString *result; |
522 | - gboolean in_space = FALSE; |
523 | - |
524 | - if (str == NULL) |
525 | - return NULL; |
526 | - |
527 | - result = g_string_new (""); |
528 | - |
529 | - while (*str) |
530 | - { |
531 | - gunichar c = g_utf8_get_char_validated (str, -1); |
532 | - |
533 | - if (c < 0) |
534 | - break; |
535 | - |
536 | - if (!g_unichar_isspace (c)) |
537 | - { |
538 | - g_string_append_unichar (result, c); |
539 | - in_space = FALSE; |
540 | - } |
541 | - else if (!in_space) |
542 | - { |
543 | - g_string_append_c (result, ' '); |
544 | - in_space = TRUE; |
545 | - } |
546 | - |
547 | - str = g_utf8_next_char (str); |
548 | - } |
549 | - |
550 | - return g_string_free (result, FALSE); |
551 | -} |
552 | - |
553 | static gchar * |
554 | im_source_menu_item_time_span_string (gint64 timestamp) |
555 | { |
556 | @@ -146,16 +106,28 @@ |
557 | return str; |
558 | } |
559 | |
560 | +static void |
561 | +im_source_menu_item_set_detail_time (ImSourceMenuItem *self, |
562 | + gint64 time) |
563 | +{ |
564 | + ImSourceMenuItemPrivate *priv = self->priv; |
565 | + gchar *str; |
566 | + |
567 | + priv->time = time; |
568 | + |
569 | + str = im_source_menu_item_time_span_string (priv->time); |
570 | + ido_detail_label_set_text (IDO_DETAIL_LABEL (priv->detail), str); |
571 | + |
572 | + g_free (str); |
573 | +} |
574 | + |
575 | static gboolean |
576 | im_source_menu_item_update_time (gpointer data) |
577 | { |
578 | ImSourceMenuItem *self = data; |
579 | - gchar *str; |
580 | - |
581 | - str = im_source_menu_item_time_span_string (self->priv->time); |
582 | - gtk_label_set_text (GTK_LABEL (self->priv->detail), str); |
583 | - |
584 | - g_free (str); |
585 | + |
586 | + im_source_menu_item_set_detail_time (self, self->priv->time); |
587 | + |
588 | return TRUE; |
589 | } |
590 | |
591 | @@ -167,7 +139,6 @@ |
592 | guint32 count; |
593 | gint64 time; |
594 | const gchar *str; |
595 | - gchar *detail; |
596 | |
597 | if (priv->timer_id != 0) |
598 | { |
599 | @@ -180,21 +151,15 @@ |
600 | g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL); |
601 | |
602 | if (count != 0) |
603 | - detail = g_strdup_printf ("%d", count); |
604 | + ido_detail_label_set_count (IDO_DETAIL_LABEL (priv->detail), count); |
605 | else if (time != 0) |
606 | { |
607 | - priv->time = time; |
608 | - detail = im_source_menu_item_time_span_string (time); |
609 | + im_source_menu_item_set_detail_time (self, time); |
610 | priv->timer_id = g_timeout_add_seconds (59, im_source_menu_item_update_time, self); |
611 | } |
612 | else if (str != NULL && *str) |
613 | - detail = collapse_whitespace (str); |
614 | - else |
615 | - detail = NULL; |
616 | - |
617 | - gtk_label_set_text (GTK_LABEL (priv->detail), detail ? detail : ""); |
618 | - |
619 | - g_free (detail); |
620 | + ido_detail_label_set_text (IDO_DETAIL_LABEL (priv->detail), str); |
621 | + |
622 | return TRUE; |
623 | } |
624 |
FAILED: Continuous integration, rev:308 jenkins. qa.ubuntu. com/job/ indicator- messages- ci/6/ jenkins. qa.ubuntu. com/job/ indicator- messages- ci/./label= quantal/ 6/console
http://
Executed test runs:
FAILURE: http://