1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) 2004 Naba Kumar <naba@gnome.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 59
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * SECTION:anjuta-status
23 * @short_description: Program status such as status message, progress etc.
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-status.h
32 #include <libanjuta/anjuta-status.h>
33 #include <libanjuta/anjuta-utils.h>
34 #include <libanjuta/anjuta-debug.h>
35 #include <libanjuta/resources.h>
36 #include <libanjuta/e-splash.h>
38 struct _AnjutaStatusPriv
40 GHashTable
*default_status_items
;
45 GtkWidget
*status_bar
;
51 GtkWidget
*progress_bar
;
57 gboolean disable_splash
;
59 gint splash_progress_position
;
70 static gpointer parent_class
= NULL
;
71 static guint status_signals
[LAST_SIGNAL
] = { 0 };
73 static void on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
);
76 anjuta_status_finalize (GObject
*widget
)
78 g_free(ANJUTA_STATUS(widget
)->priv
);
79 G_OBJECT_CLASS (parent_class
)->finalize (widget
);
83 foreach_widget_unref (gpointer key
, gpointer value
, gpointer data
)
85 g_object_weak_unref (G_OBJECT (key
), (GWeakNotify
) on_widget_destroy
, data
);
89 anjuta_status_dispose (GObject
*widget
)
93 status
= ANJUTA_STATUS (widget
);
95 if (status
->priv
->default_status_items
)
97 g_hash_table_destroy (status
->priv
->default_status_items
);
98 status
->priv
->default_status_items
= NULL
;
100 if (status
->priv
->splash
!= NULL
) {
101 gtk_widget_destroy (status
->priv
->splash
);
102 status
->priv
->splash
= NULL
;
104 if (status
->priv
->splash_file
)
106 g_free (status
->priv
->splash_file
);
107 status
->priv
->splash_file
= NULL
;
109 if (status
->priv
->push_values
)
111 g_list_free (status
->priv
->push_values
);
112 status
->priv
->push_values
= NULL
;
114 if (status
->priv
->widgets
)
116 g_hash_table_foreach (status
->priv
->widgets
,
117 foreach_widget_unref
, widget
);
118 g_hash_table_destroy (status
->priv
->widgets
);
119 status
->priv
->widgets
= NULL
;
121 if (status
->priv
->window
)
123 g_object_remove_weak_pointer (G_OBJECT (status
->priv
->window
),
124 (gpointer
*)(gpointer
)&status
->priv
->window
);
125 status
->priv
->window
= NULL
;
127 if (status
->priv
->progress_bar
)
129 g_object_remove_weak_pointer (G_OBJECT (status
->priv
->progress_bar
),
130 (gpointer
)&status
->priv
->progress_bar
);
131 gtk_widget_destroy (status
->priv
->progress_bar
);
132 status
->priv
->progress_bar
= NULL
;
134 if (status
->priv
->status_bar
)
136 g_object_remove_weak_pointer (G_OBJECT (status
->priv
->status_bar
),
137 (gpointer
)&status
->priv
->status_bar
);
138 gtk_widget_destroy (status
->priv
->status_bar
);
139 status
->priv
->status_bar
= NULL
;
142 G_OBJECT_CLASS (parent_class
)->dispose (widget
);
146 anjuta_status_instance_init (AnjutaStatus
*status
)
148 status
->priv
= g_new0 (AnjutaStatusPriv
, 1);
149 status
->priv
->progress_bar
= gtk_progress_bar_new ();
150 gtk_box_pack_start (GTK_BOX (status
), status
->priv
->progress_bar
, FALSE
, TRUE
, 0);
151 gtk_widget_show (status
->priv
->progress_bar
);
152 g_object_add_weak_pointer (G_OBJECT (status
->priv
->progress_bar
),
153 (gpointer
)&status
->priv
->progress_bar
);
154 status
->priv
->status_bar
= gtk_statusbar_new ();
155 gtk_box_pack_start (GTK_BOX (status
), status
->priv
->status_bar
, TRUE
, TRUE
, 0);
156 gtk_widget_show (status
->priv
->status_bar
);
157 g_object_add_weak_pointer (G_OBJECT(status
->priv
->status_bar
),
158 (gpointer
)&status
->priv
->status_bar
);
159 status
->priv
->status_message
= gtk_statusbar_get_context_id (GTK_STATUSBAR (status
->priv
->status_bar
),
161 status
->priv
->push_message
= gtk_statusbar_get_context_id (GTK_STATUSBAR (status
->priv
->status_bar
),
163 status
->priv
->push_values
= NULL
;
164 status
->priv
->splash_file
= NULL
;
165 status
->priv
->splash_progress_position
= 0;
166 status
->priv
->disable_splash
= FALSE
;
167 status
->priv
->total_ticks
= 0;
168 status
->priv
->current_ticks
= 0;
169 status
->priv
->splash
= NULL
;
170 status
->priv
->default_status_items
=
171 g_hash_table_new_full (g_str_hash
, g_str_equal
,
176 anjuta_status_class_init (AnjutaStatusClass
*class)
178 GObjectClass
*object_class
;
180 parent_class
= g_type_class_peek_parent (class);
181 object_class
= (GObjectClass
*) class;
182 object_class
->finalize
= anjuta_status_finalize
;
183 object_class
->dispose
= anjuta_status_dispose
;
185 status_signals
[BUSY
] =
186 g_signal_new ("busy",
189 G_STRUCT_OFFSET (AnjutaStatusClass
, busy
),
191 g_cclosure_marshal_VOID__BOOLEAN
,
197 anjuta_status_new (void)
201 status
= GTK_WIDGET (g_object_new (ANJUTA_TYPE_STATUS
, NULL
));
206 anjuta_status_set (AnjutaStatus
*status
, const gchar
* mesg
, ...)
211 g_return_if_fail (ANJUTA_IS_STATUS (status
));
212 g_return_if_fail (mesg
!= NULL
);
214 va_start (args
, mesg
);
215 message
= g_strdup_vprintf (mesg
, args
);
217 gtk_statusbar_pop (GTK_STATUSBAR (status
->priv
->status_bar
),
218 status
->priv
->status_message
);
219 gtk_statusbar_push (GTK_STATUSBAR (status
->priv
->status_bar
),
220 status
->priv
->status_message
, message
);
225 anjuta_status_push (AnjutaStatus
*status
, const gchar
* mesg
, ...)
231 g_return_if_fail (ANJUTA_IS_STATUS (status
));
232 g_return_if_fail (mesg
!= NULL
);
234 va_start (args
, mesg
);
235 message
= g_strdup_vprintf (mesg
, args
);
238 value
= gtk_statusbar_push (GTK_STATUSBAR (status
->priv
->status_bar
),
239 status
->priv
->push_message
, message
);
240 status
->priv
->push_values
= g_list_prepend (status
->priv
->push_values
,
241 GUINT_TO_POINTER (value
));
246 anjuta_status_pop (AnjutaStatus
*status
)
248 g_return_if_fail (ANJUTA_IS_STATUS (status
));
250 /* This can be called on a time out when the status object is destroyed */
251 if (status
->priv
->status_bar
!= NULL
)
253 gtk_statusbar_pop (GTK_STATUSBAR (status
->priv
->status_bar
),
254 status
->priv
->push_message
);
257 status
->priv
->push_values
= g_list_remove_link (status
->priv
->push_values
,
258 status
->priv
->push_values
);
262 anjuta_status_clear_stack (AnjutaStatus
*status
)
265 g_return_if_fail (ANJUTA_IS_STATUS (status
));
267 for (l
= status
->priv
->push_values
; l
!= NULL
; l
= g_list_next (l
))
269 guint value
= GPOINTER_TO_UINT (l
->data
);
270 gtk_statusbar_remove (GTK_STATUSBAR (status
->priv
->status_bar
),
271 status
->priv
->push_message
, value
);
273 g_list_free (status
->priv
->push_values
);
274 status
->priv
->push_values
= NULL
;
278 foreach_widget_set_cursor (gpointer widget
, gpointer value
, gpointer cursor
)
282 window
= gtk_widget_get_window (widget
);
284 gdk_window_set_cursor (window
, (GdkCursor
*)cursor
);
288 anjuta_status_busy_push (AnjutaStatus
*status
)
295 g_return_if_fail (ANJUTA_IS_STATUS (status
));
297 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
301 status
->priv
->busy_count
++;
303 DEBUG_PRINT ("Busy status: %d", status
->priv
->busy_count
);
305 if (status
->priv
->busy_count
> 1)
307 display
= gtk_widget_get_display (top
);
308 cursor
= gdk_cursor_new_for_display (display
, GDK_WATCH
);
309 window
= gtk_widget_get_window (top
);
311 gdk_window_set_cursor (window
, cursor
);
312 if (status
->priv
->widgets
)
313 g_hash_table_foreach (status
->priv
->widgets
,
314 foreach_widget_set_cursor
, cursor
);
315 g_object_unref (cursor
);
317 g_signal_emit_by_name (G_OBJECT (status
), "busy", TRUE
);
321 anjuta_status_busy_pop (AnjutaStatus
*status
)
326 g_return_if_fail (ANJUTA_IS_STATUS (status
));
328 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
332 status
->priv
->busy_count
--;
333 DEBUG_PRINT ("Busy status: %d", status
->priv
->busy_count
);
335 if (status
->priv
->busy_count
> 0)
338 status
->priv
->busy_count
= 0;
339 window
= gtk_widget_get_window (top
);
341 gdk_window_set_cursor (window
, NULL
);
342 if (status
->priv
->widgets
)
343 g_hash_table_foreach (status
->priv
->widgets
,
344 foreach_widget_set_cursor
, NULL
);
345 g_signal_emit_by_name (G_OBJECT (status
), "busy", FALSE
);
349 foreach_hash (gpointer key
, gpointer value
, gpointer userdata
)
351 GString
*str
= (GString
*)(userdata
);
352 const gchar
*divider
= ": ";
353 const gchar
*separator
= " ";
355 g_string_append (str
, separator
);
356 g_string_append (str
, (const gchar
*)key
);
357 g_string_append (str
, divider
);
358 g_string_append (str
, (const gchar
*)value
);
362 anjuta_status_set_default (AnjutaStatus
*status
, const gchar
*label
,
363 const gchar
*value_format
, ...)
368 g_return_if_fail (ANJUTA_IS_STATUS (status
));
369 g_return_if_fail (label
!= NULL
);
376 va_start (args
, value_format
);
377 value
= g_strdup_vprintf (value_format
, args
);
379 g_hash_table_replace (status
->priv
->default_status_items
,
380 g_strdup (label
), value
);
384 if (g_hash_table_lookup (status
->priv
->default_status_items
, label
))
386 g_hash_table_remove (status
->priv
->default_status_items
, label
);
390 /* Update default status */
391 str
= g_string_new (NULL
);
392 g_hash_table_foreach (status
->priv
->default_status_items
, foreach_hash
, str
);
393 status_str
= g_string_free (str
, FALSE
);
394 anjuta_status_set (status
, status_str
, NULL
);
399 on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
)
401 if (g_hash_table_lookup (status
->priv
->widgets
, widget
))
402 g_hash_table_remove (status
->priv
->widgets
, widget
);
406 anjuta_status_add_widget (AnjutaStatus
*status
, GtkWidget
*widget
)
408 g_return_if_fail (ANJUTA_IS_STATUS (status
));
409 g_return_if_fail (GTK_IS_WIDGET (widget
));
411 if (status
->priv
->widgets
== NULL
)
412 status
->priv
->widgets
=
413 g_hash_table_new (g_direct_hash
, g_direct_equal
);
415 g_hash_table_insert (status
->priv
->widgets
, widget
, widget
);
416 g_object_weak_ref (G_OBJECT (widget
),
417 (GWeakNotify
) (on_widget_destroy
), status
);
421 anjuta_status_set_splash (AnjutaStatus
*status
, const gchar
*splash_file
,
422 gint splash_progress_position
)
424 g_return_if_fail (ANJUTA_IS_STATUS (status
));
425 g_return_if_fail (splash_file
!= NULL
);
426 g_return_if_fail (splash_progress_position
>= 0);
427 if (status
->priv
->splash_file
)
428 g_free (status
->priv
->splash_file
);
429 status
->priv
->splash_file
= g_strdup (splash_file
);
430 status
->priv
->splash_progress_position
= splash_progress_position
;
434 anjuta_status_disable_splash (AnjutaStatus
*status
,
435 gboolean disable_splash
)
437 g_return_if_fail (ANJUTA_IS_STATUS (status
));
439 status
->priv
->disable_splash
= disable_splash
;
440 if (status
->priv
->splash
)
442 gtk_widget_destroy (status
->priv
->splash
);
443 status
->priv
->splash
= NULL
;
444 anjuta_status_progress_add_ticks (status
, 0);
449 anjuta_status_progress_add_ticks (AnjutaStatus
*status
, gint ticks
)
453 g_return_if_fail (ANJUTA_IS_STATUS (status
));
454 g_return_if_fail (ticks
>= 0);
456 status
->priv
->total_ticks
+= ticks
;
457 if (!gtk_widget_get_realized (GTK_WIDGET (status
)))
459 if (status
->priv
->splash
== NULL
&&
460 status
->priv
->splash_file
&&
461 !status
->priv
->disable_splash
)
463 status
->priv
->splash
= e_splash_new (status
->priv
->splash_file
, 100);
464 if (status
->priv
->splash
)
465 gtk_widget_show (status
->priv
->splash
);
468 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
469 if (status
->priv
->splash
)
471 e_splash_set (E_SPLASH(status
->priv
->splash
), NULL
, NULL
, NULL
,
473 while (g_main_context_iteration(NULL
, FALSE
));
477 if (status
->priv
->progress_bar
&& status
->priv
->status_bar
)
479 GdkWindow
*progressbar_window
, *statusbar_window
;
481 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
),
483 gtk_widget_queue_draw (GTK_WIDGET (status
->priv
->status_bar
));
484 gtk_widget_queue_draw (GTK_WIDGET (status
->priv
->progress_bar
));
485 progressbar_window
= gtk_widget_get_window (GTK_WIDGET(status
->priv
->progress_bar
));
486 statusbar_window
= gtk_widget_get_window (GTK_WIDGET(status
->priv
->status_bar
));
487 if (progressbar_window
!= NULL
)
488 gdk_window_process_updates (progressbar_window
, TRUE
);
489 if (statusbar_window
!= NULL
)
490 gdk_window_process_updates (statusbar_window
, TRUE
);
496 anjuta_status_progress_pulse (AnjutaStatus
*status
, const gchar
*text
)
498 GtkProgressBar
*progressbar
;
499 GtkWidget
*statusbar
;
500 GdkWindow
*progressbar_window
, *statusbar_window
;
502 progressbar
= GTK_PROGRESS_BAR (status
->priv
->progress_bar
);
503 statusbar
= status
->priv
->status_bar
;
506 anjuta_status_push (status
, "%s", text
);
508 gtk_progress_bar_pulse (progressbar
);
510 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
511 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
512 progressbar_window
= gtk_widget_get_window (GTK_WIDGET (progressbar
));
513 if (progressbar_window
!= NULL
)
514 gdk_window_process_updates (progressbar_window
, TRUE
);
515 statusbar_window
= gtk_widget_get_window (GTK_WIDGET (statusbar
));
516 if (statusbar_window
!= NULL
)
517 gdk_window_process_updates (statusbar_window
, TRUE
);
521 anjuta_status_progress_tick (AnjutaStatus
*status
,
522 GdkPixbuf
*icon
, const gchar
*text
)
526 g_return_if_fail (ANJUTA_IS_STATUS (status
));
527 g_return_if_fail (status
->priv
->total_ticks
!= 0);
529 status
->priv
->current_ticks
++;
530 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
532 if (status
->priv
->splash
)
534 e_splash_set (E_SPLASH(status
->priv
->splash
), icon
, text
, NULL
, percentage
);
538 GtkProgressBar
*progressbar
;
539 GtkWidget
*statusbar
;
540 GdkWindow
*progressbar_window
, *statusbar_window
;
543 anjuta_status_set (status
, "%s", text
);
544 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
),
546 progressbar
= GTK_PROGRESS_BAR (status
->priv
->progress_bar
);
547 statusbar
= status
->priv
->status_bar
;
548 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
549 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
550 progressbar_window
= gtk_widget_get_window (GTK_WIDGET (progressbar
));
551 if (progressbar_window
!= NULL
)
552 gdk_window_process_updates (progressbar_window
, TRUE
);
553 statusbar_window
= gtk_widget_get_window (GTK_WIDGET (statusbar
));
554 if (statusbar_window
!= NULL
)
555 gdk_window_process_updates (statusbar_window
, TRUE
);
557 if (status
->priv
->current_ticks
>= status
->priv
->total_ticks
)
558 anjuta_status_progress_reset (status
);
562 anjuta_status_progress_increment_ticks (AnjutaStatus
*status
, gint ticks
,
566 GdkWindow
*progressbar_window
, *statusbar_window
;
568 g_return_if_fail (ANJUTA_IS_STATUS (status
));
569 g_return_if_fail (status
->priv
->total_ticks
!= 0);
571 status
->priv
->current_ticks
+= ticks
;
572 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
574 GtkProgressBar
*progressbar
;
575 GtkWidget
*statusbar
;
578 anjuta_status_set (status
, "%s", text
);
579 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
),
581 progressbar
= GTK_PROGRESS_BAR (status
->priv
->progress_bar
);
582 statusbar
= status
->priv
->status_bar
;
583 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
584 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
585 progressbar_window
= gtk_widget_get_window (GTK_WIDGET(progressbar
));
586 if (progressbar_window
!= NULL
)
587 gdk_window_process_updates (progressbar_window
, TRUE
);
588 statusbar_window
= gtk_widget_get_window (GTK_WIDGET(statusbar
));
589 if (statusbar_window
!= NULL
)
590 gdk_window_process_updates (statusbar_window
, TRUE
);
592 if (status
->priv
->current_ticks
>= status
->priv
->total_ticks
)
593 anjuta_status_progress_reset (status
);
597 anjuta_status_progress_reset (AnjutaStatus
*status
)
599 g_return_if_fail (ANJUTA_IS_STATUS (status
));
601 if (status
->priv
->splash
)
603 gtk_widget_destroy (status
->priv
->splash
);
604 status
->priv
->splash
= NULL
;
606 status
->priv
->current_ticks
= 0;
607 status
->priv
->total_ticks
= 0;
608 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
), 0);
609 anjuta_status_clear_stack (status
);
613 anjuta_status_timeout (AnjutaStatus
*status
)
615 anjuta_status_pop (status
);
616 g_object_unref (status
);
622 * anjuta_status: (skip)
623 * Display message in status until timeout (seconds)
626 anjuta_status (AnjutaStatus
*status
, const gchar
*mesg
, gint timeout
)
628 g_return_if_fail (ANJUTA_IS_STATUS (status
));
629 g_return_if_fail (mesg
!= NULL
);
630 anjuta_status_push (status
, "%s", mesg
);
631 g_timeout_add_seconds (timeout
, (void*) anjuta_status_timeout
, g_object_ref (status
));
635 anjuta_status_set_title_window (AnjutaStatus
*status
, GtkWidget
*window
)
637 g_return_if_fail (ANJUTA_IS_STATUS (status
));
638 g_return_if_fail (GTK_IS_WINDOW (window
));
639 status
->priv
->window
= GTK_WINDOW (window
);
640 g_object_add_weak_pointer (G_OBJECT (window
),
641 (gpointer
*)(gpointer
)&status
->priv
->window
);
645 anjuta_status_set_title (AnjutaStatus
*status
, const gchar
*title
)
647 g_return_if_fail (ANJUTA_IS_STATUS (status
));
649 if (!status
->priv
->window
)
652 const gchar
*app_name
= g_get_application_name();
655 gchar
* str
= g_strconcat (title
, " - ", app_name
, NULL
);
656 gtk_window_set_title (status
->priv
->window
, str
);
661 gtk_window_set_title (status
->priv
->window
, app_name
);
665 ANJUTA_TYPE_BEGIN(AnjutaStatus
, anjuta_status
, GTK_TYPE_BOX
);