evolution-3.6.4/widgets/misc/e-alert-bar.c

Location Tool Test ID Function Issue
e-alert-bar.c:289:2 clang-analyzer Value stored to 'container' is never read
e-alert-bar.c:289:2 clang-analyzer Value stored to 'container' is never read
  1 /*
  2  * e-alert-bar.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  */
 18 
 19 #include "e-alert-bar.h"
 20 
 21 #include <config.h>
 22 #include <glib/gi18n-lib.h>
 23 
 24 #define E_ALERT_BAR_GET_PRIVATE(obj) \
 25 	(G_TYPE_INSTANCE_GET_PRIVATE \
 26 	((obj), E_TYPE_ALERT_BAR, EAlertBarPrivate))
 27 
 28 #define E_ALERT_BAR_GET_PRIVATE(obj) \
 29 	(G_TYPE_INSTANCE_GET_PRIVATE \
 30 	((obj), E_TYPE_ALERT_BAR, EAlertBarPrivate))
 31 
 32 /* GTK_ICON_SIZE_DIALOG is a tad too big. */
 33 #define ICON_SIZE GTK_ICON_SIZE_DND
 34 
 35 /* Dismiss warnings automatically after 5 minutes. */
 36 #define WARNING_TIMEOUT_SECONDS (5 * 60)
 37 
 38 struct _EAlertBarPrivate {
 39 	GQueue alerts;
 40 	GtkWidget *image;		/* not referenced */
 41 	GtkWidget *primary_label;	/* not referenced */
 42 	GtkWidget *secondary_label;	/* not referenced */
 43 };
 44 
 45 G_DEFINE_TYPE (
 46 	EAlertBar,
 47 	e_alert_bar,
 48 	GTK_TYPE_INFO_BAR)
 49 
 50 static void
 51 alert_bar_response_close (EAlert *alert)
 52 {
 53 	e_alert_response (alert, GTK_RESPONSE_CLOSE);
 54 }
 55 
 56 static void
 57 alert_bar_show_alert (EAlertBar *alert_bar)
 58 {
 59 	GtkImage *image;
 60 	GtkInfoBar *info_bar;
 61 	GtkWidget *action_area;
 62 	GtkWidget *widget;
 63 	EAlert *alert;
 64 	GList *actions;
 65 	GList *children;
 66 	GtkMessageType message_type;
 67 	const gchar *primary_text;
 68 	const gchar *secondary_text;
 69 	const gchar *stock_id;
 70 	gboolean have_primary_text;
 71 	gboolean have_secondary_text;
 72 	gboolean visible;
 73 	gint response_id;
 74 	gchar *markup;
 75 
 76 	info_bar = GTK_INFO_BAR (alert_bar);
 77 	action_area = gtk_info_bar_get_action_area (info_bar);
 78 
 79 	alert = g_queue_peek_head (&alert_bar->priv->alerts);
 80 	g_return_if_fail (E_IS_ALERT (alert));
 81 
 82 	/* Remove all buttons from the previous alert. */
 83 	children = gtk_container_get_children (GTK_CONTAINER (action_area));
 84 	while (children != NULL) {
 85 		GtkWidget *child = GTK_WIDGET (children->data);
 86 		gtk_container_remove (GTK_CONTAINER (action_area), child);
 87 		children = g_list_delete_link (children, children);
 88 	}
 89 
 90 	/* Add alert-specific buttons. */
 91 	actions = e_alert_peek_actions (alert);
 92 	while (actions != NULL) {
 93 		/* These actions are already wired to trigger an
 94 		 * EAlert::response signal when activated, which
 95 		 * will in turn call gtk_info_bar_response(), so
 96 		 * we can add buttons directly to the action
 97 		 * area without knowning their response IDs. */
 98 
 99 		widget = gtk_button_new ();
100 
101 		gtk_activatable_set_related_action (
102 			GTK_ACTIVATABLE (widget),
103 			GTK_ACTION (actions->data));
104 
105 		gtk_box_pack_end (
106 			GTK_BOX (action_area), widget, FALSE, FALSE, 0);
107 
108 		actions = g_list_next (actions);
109 	}
110 
111 	/* Add a dismiss button. */
112 	widget = gtk_button_new ();
113 	gtk_button_set_image (
114 		GTK_BUTTON (widget),
115 		gtk_image_new_from_stock (
116 		GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
117 	gtk_button_set_relief (
118 		GTK_BUTTON (widget), GTK_RELIEF_NONE);
119 	gtk_widget_set_tooltip_text (
120 		widget, _("Close this message"));
121 	gtk_box_pack_end (
122 		GTK_BOX (action_area), widget, FALSE, FALSE, 0);
123 	gtk_button_box_set_child_non_homogeneous (
124 		GTK_BUTTON_BOX (action_area), widget, TRUE);
125 	gtk_widget_show (widget);
126 
127 	g_signal_connect_swapped (
128 		widget, "clicked",
129 		G_CALLBACK (alert_bar_response_close), alert);
130 
131 	primary_text = e_alert_get_primary_text (alert);
132 	secondary_text = e_alert_get_secondary_text (alert);
133 
134 	if (primary_text == NULL)
135 		primary_text = "";
136 
137 	if (secondary_text == NULL)
138 		secondary_text = "";
139 
140 	have_primary_text = (*primary_text != '\0');
141 	have_secondary_text = (*secondary_text != '\0');
142 
143 	response_id = e_alert_get_default_response (alert);
144 	gtk_info_bar_set_default_response (info_bar, response_id);
145 
146 	message_type = e_alert_get_message_type (alert);
147 	gtk_info_bar_set_message_type (info_bar, message_type);
148 
149 	widget = alert_bar->priv->primary_label;
150 	if (have_primary_text && have_secondary_text)
151 		markup = g_markup_printf_escaped (
152 			"<b>%s</b>", primary_text);
153 	else
154 		markup = g_markup_escape_text (primary_text, -1);
155 	gtk_label_set_markup (GTK_LABEL (widget), markup);
156 	gtk_widget_set_visible (widget, have_primary_text);
157 	g_free (markup);
158 
159 	widget = alert_bar->priv->secondary_label;
160 	if (have_primary_text && have_secondary_text)
161 		markup = g_markup_printf_escaped (
162 			"<small>%s</small>", secondary_text);
163 	else
164 		markup = g_markup_escape_text (secondary_text, -1);
165 	gtk_label_set_markup (GTK_LABEL (widget), markup);
166 	gtk_widget_set_visible (widget, have_secondary_text);
167 	g_free (markup);
168 
169 	stock_id = e_alert_get_stock_id (alert);
170 	image = GTK_IMAGE (alert_bar->priv->image);
171 	gtk_image_set_from_stock (image, stock_id, ICON_SIZE);
172 
173 	/* Avoid showing an image for one-line alerts,
174 	 * which are usually questions or informational. */
175 	visible = have_primary_text && have_secondary_text;
176 	gtk_widget_set_visible (alert_bar->priv->image, visible);
177 
178 	gtk_widget_show (GTK_WIDGET (alert_bar));
179 
180 	/* Warnings are generally meant for transient errors.
181 	 * No need to leave them up indefinitely.  Close them
182 	 * automatically if the user hasn't responded after a
183 	 * reasonable period of time has elapsed. */
184 	if (message_type == GTK_MESSAGE_WARNING)
185 		e_alert_start_timer (alert, WARNING_TIMEOUT_SECONDS);
186 }
187 
188 static void
189 alert_bar_response_cb (EAlert *alert,
190                        gint response_id,
191                        EAlertBar *alert_bar)
192 {
193 	GQueue *queue;
194 	EAlert *head;
195 	gboolean was_head;
196 
197 	queue = &alert_bar->priv->alerts;
198 	head = g_queue_peek_head (queue);
199 	was_head = (alert == head);
200 
201 	g_signal_handlers_disconnect_by_func (
202 		alert, alert_bar_response_cb, alert_bar);
203 
204 	if (g_queue_remove (queue, alert))
205 		g_object_unref (alert);
206 
207 	if (g_queue_is_empty (queue))
208 		gtk_widget_hide (GTK_WIDGET (alert_bar));
209 	else if (was_head) {
210 		GtkInfoBar *info_bar = GTK_INFO_BAR (alert_bar);
211 		gtk_info_bar_response (info_bar, response_id);
212 		alert_bar_show_alert (alert_bar);
213 	}
214 }
215 
216 static void
217 alert_bar_dispose (GObject *object)
218 {
219 	EAlertBarPrivate *priv;
220 
221 	priv = E_ALERT_BAR_GET_PRIVATE (object);
222 
223 	while (!g_queue_is_empty (&priv->alerts)) {
224 		EAlert *alert = g_queue_pop_head (&priv->alerts);
225 		g_signal_handlers_disconnect_by_func (
226 			alert, alert_bar_response_cb, object);
227 		g_object_unref (alert);
228 	}
229 
230 	/* Chain up to parent's dispose() method. */
231 	G_OBJECT_CLASS (e_alert_bar_parent_class)->dispose (object);
232 }
233 
234 static void
235 alert_bar_constructed (GObject *object)
236 {
237 	EAlertBarPrivate *priv;
238 	GtkInfoBar *info_bar;
239 	GtkWidget *action_area;
240 	GtkWidget *content_area;
241 	GtkWidget *container;
242 	GtkWidget *widget;
243 
244 	priv = E_ALERT_BAR_GET_PRIVATE (object);
245 
246 	/* Chain up to parent's constructed() method. */
247 	G_OBJECT_CLASS (e_alert_bar_parent_class)->constructed (object);
248 
249 	g_queue_init (&priv->alerts);
250 
251 	info_bar = GTK_INFO_BAR (object);
252 	action_area = gtk_info_bar_get_action_area (info_bar);
253 	content_area = gtk_info_bar_get_content_area (info_bar);
254 
255 	gtk_orientable_set_orientation (
256 		GTK_ORIENTABLE (action_area), GTK_ORIENTATION_HORIZONTAL);
257 	gtk_widget_set_valign (action_area, GTK_ALIGN_START);
258 
259 	container = content_area;
260 
261 	widget = gtk_image_new ();
262 	gtk_misc_set_alignment (GTK_MISC (widget), 0.5, 0.0);
263 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
264 	priv->image = widget;
265 	gtk_widget_show (widget);
266 
267 	widget = gtk_vbox_new (FALSE, 12);
268 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
269 	gtk_widget_show (widget);
270 
271 	container = widget;
272 
273 	widget = gtk_label_new (NULL);
274 	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
275 	gtk_label_set_selectable (GTK_LABEL (widget), TRUE);
276 	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
277 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
278 	priv->primary_label = widget;
279 	gtk_widget_show (widget);
280 
281 	widget = gtk_label_new (NULL);
282 	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
283 	gtk_label_set_selectable (GTK_LABEL (widget), TRUE);
284 	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
285 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
286 	priv->secondary_label = widget;
287 	gtk_widget_show (widget);
288 
289 	container = action_area;
Value stored to 'container' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Value stored to 'container' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

290 } 291 292 static GtkSizeRequestMode 293 alert_bar_get_request_mode (GtkWidget *widget) 294 { 295 /* GtkHBox does width-for-height by default. But we 296 * want the alert bar to be as short as possible. */ 297 return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; 298 } 299 300 static void 301 e_alert_bar_class_init (EAlertBarClass *class) 302 { 303 GObjectClass *object_class; 304 GtkWidgetClass *widget_class; 305 306 g_type_class_add_private (class, sizeof (EAlertBarPrivate)); 307 308 object_class = G_OBJECT_CLASS (class); 309 object_class->dispose = alert_bar_dispose; 310 object_class->constructed = alert_bar_constructed; 311 312 widget_class = GTK_WIDGET_CLASS (class); 313 widget_class->get_request_mode = alert_bar_get_request_mode; 314 } 315 316 static void 317 e_alert_bar_init (EAlertBar *alert_bar) 318 { 319 alert_bar->priv = E_ALERT_BAR_GET_PRIVATE (alert_bar); 320 } 321 322 GtkWidget * 323 e_alert_bar_new (void) 324 { 325 return g_object_new (E_TYPE_ALERT_BAR, NULL); 326 } 327 328 void 329 e_alert_bar_clear (EAlertBar *alert_bar) 330 { 331 GQueue *queue; 332 EAlert *alert; 333 334 g_return_if_fail (E_IS_ALERT_BAR (alert_bar)); 335 336 queue = &alert_bar->priv->alerts; 337 338 while ((alert = g_queue_pop_head (queue)) != NULL) 339 alert_bar_response_close (alert); 340 } 341 342 typedef struct { 343 gboolean found; 344 EAlert *looking_for; 345 } DuplicateData; 346 347 static void 348 alert_bar_find_duplicate_cb (EAlert *alert, 349 DuplicateData *dd) 350 { 351 g_return_if_fail (dd->looking_for != NULL); 352 353 dd->found |= ( 354 e_alert_get_message_type (alert) == 355 e_alert_get_message_type (dd->looking_for) && 356 g_strcmp0 ( 357 e_alert_get_primary_text (alert), 358 e_alert_get_primary_text (dd->looking_for)) == 0 && 359 g_strcmp0 ( 360 e_alert_get_secondary_text (alert), 361 e_alert_get_secondary_text (dd->looking_for)) == 0); 362 } 363 364 void 365 e_alert_bar_add_alert (EAlertBar *alert_bar, 366 EAlert *alert) 367 { 368 DuplicateData dd; 369 370 g_return_if_fail (E_IS_ALERT_BAR (alert_bar)); 371 g_return_if_fail (E_IS_ALERT (alert)); 372 373 dd.found = FALSE; 374 dd.looking_for = alert; 375 376 g_queue_foreach ( 377 &alert_bar->priv->alerts, 378 (GFunc) alert_bar_find_duplicate_cb, &dd); 379 380 if (dd.found) 381 return; 382 383 g_signal_connect ( 384 alert, "response", 385 G_CALLBACK (alert_bar_response_cb), alert_bar); 386 387 g_queue_push_head (&alert_bar->priv->alerts, g_object_ref (alert)); 388 389 alert_bar_show_alert (alert_bar); 390 }