base_window_is_willing_to_quit() successively invoke each derived class
[nautilus-actions.git] / src / nact / base-window.c
blobacc928806ef9f9820c1e212844724fc907fb1cbb
1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
24 * Authors:
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <glib.h>
36 #include <glib/gi18n.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #include "base-application.h"
41 #include "base-iprefs.h"
42 #include "base-window.h"
43 #include "nact-gtk-utils.h"
45 /* private class data
47 struct _BaseWindowClassPrivate {
48 void *empty; /* so that gcc -pedantic is happy */
51 /* private instance data
53 struct _BaseWindowPrivate {
54 gboolean dispose_has_run;
56 /* properties
58 BaseWindow *parent;
59 BaseApplication *application;
60 gchar *xmlui_filename;
61 gboolean has_own_builder;
62 gchar *toplevel_name;
64 /* internals
66 GtkWindow *gtk_toplevel;
67 gboolean initialized;
69 GSList *signals;
70 gboolean save_window_position;
71 BaseBuilder *builder;
74 /* connected signal, to be disconnected at NactWindow dispose
76 typedef struct {
77 gpointer instance;
78 gulong handler_id;
80 BaseWindowRecordedSignal;
82 /* instance properties
84 enum {
85 BASE_PROP_0,
87 BASE_PROP_PARENT_ID,
88 BASE_PROP_APPLICATION_ID,
89 BASE_PROP_XMLUI_FILENAME_ID,
90 BASE_PROP_HAS_OWN_BUILDER_ID,
91 BASE_PROP_TOPLEVEL_NAME_ID,
93 BASE_PROP_N_PROPERTIES
96 /* signals defined in BaseWindow, to be used in all derived classes
98 enum {
99 INITIALIZE_GTK,
100 INITIALIZE_BASE,
101 ALL_WIDGETS_SHOWED,
102 LAST_SIGNAL
105 static GObjectClass *st_parent_class = NULL;
106 static gint st_signals[ LAST_SIGNAL ] = { 0 };
107 static gboolean st_debug_signal_connect = FALSE;
108 static BaseWindow *st_first_window = NULL;
110 static GType register_type( void );
111 static void class_init( BaseWindowClass *klass );
112 static void iprefs_base_iface_init( BaseIPrefsInterface *iface );
113 static void instance_init( GTypeInstance *instance, gpointer klass );
114 static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
115 static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
116 static void instance_dispose( GObject *application );
117 static void instance_finalize( GObject *application );
119 static gboolean setup_builder( const BaseWindow *window );
120 static gboolean load_gtk_toplevel( const BaseWindow *window );
121 static gboolean is_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel );
122 static void set_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel, gboolean init );
124 static gboolean on_delete_event( GtkWidget *widget, GdkEvent *event, BaseWindow *window );
126 static void on_initialize_gtk_toplevel_class_handler( BaseWindow *window, gpointer user_data );
127 static void do_initialize_gtk_toplevel( BaseWindow *window, gpointer user_data );
128 static void on_initialize_base_window_class_handler( BaseWindow *window, gpointer user_data );
129 static void do_initialize_base_window( BaseWindow *window, gpointer user_data );
130 static void on_all_widgets_showed_class_handler( BaseWindow *window, gpointer user_data );
132 static gboolean v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
133 static gchar *v_get_toplevel_name( const BaseWindow *window );
134 static gchar *v_get_iprefs_window_id( const BaseWindow *window );
136 static gboolean window_do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
137 static gboolean window_do_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
138 static gboolean window_do_is_willing_to_quit( const BaseWindow *window );
140 static gboolean is_main_window( BaseWindow *window );
142 static void record_connected_signal( BaseWindow *window, GObject *instance, gulong handler_id );
143 static gint display_dlg( const BaseWindow *parent, GtkMessageType type_message, GtkButtonsType type_buttons, const gchar *primary, const gchar *secondary );
145 GType
146 base_window_get_type( void )
148 static GType window_type = 0;
150 if( !window_type ){
151 window_type = register_type();
154 return( window_type );
157 static GType
158 register_type( void )
160 static const gchar *thisfn = "base_window_register_type";
161 GType type;
163 static GTypeInfo info = {
164 sizeof( BaseWindowClass ),
165 ( GBaseInitFunc ) NULL,
166 ( GBaseFinalizeFunc ) NULL,
167 ( GClassInitFunc ) class_init,
168 NULL,
169 NULL,
170 sizeof( BaseWindow ),
172 ( GInstanceInitFunc ) instance_init
175 static const GInterfaceInfo iprefs_base_iface_info = {
176 ( GInterfaceInitFunc ) iprefs_base_iface_init,
177 NULL,
178 NULL
181 g_debug( "%s", thisfn );
183 type = g_type_register_static( G_TYPE_OBJECT, "BaseWindow", &info, 0 );
185 g_type_add_interface_static( type, BASE_IPREFS_TYPE, &iprefs_base_iface_info );
187 return( type );
190 static void
191 class_init( BaseWindowClass *klass )
193 static const gchar *thisfn = "base_window_class_init";
194 GObjectClass *object_class;
196 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
198 st_parent_class = g_type_class_peek_parent( klass );
200 object_class = G_OBJECT_CLASS( klass );
201 object_class->dispose = instance_dispose;
202 object_class->finalize = instance_finalize;
203 object_class->get_property = instance_get_property;
204 object_class->set_property = instance_set_property;
206 g_object_class_install_property( object_class, BASE_PROP_PARENT_ID,
207 g_param_spec_pointer(
208 BASE_PROP_PARENT,
209 _( "Parent BaseWindow" ),
210 _( "A pointer (not a reference) to the BaseWindow parent of this BaseWindow" ),
211 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
213 g_object_class_install_property( object_class, BASE_PROP_APPLICATION_ID,
214 g_param_spec_pointer(
215 BASE_PROP_APPLICATION,
216 _( "BaseApplication" ),
217 _( "A pointer (not a reference) to the BaseApplication instance" ),
218 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
220 g_object_class_install_property( object_class, BASE_PROP_XMLUI_FILENAME_ID,
221 g_param_spec_string(
222 BASE_PROP_XMLUI_FILENAME,
223 _( "XML UI filename" ),
224 _( "The filename which contains the XML UI definition" ),
226 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
228 g_object_class_install_property( object_class, BASE_PROP_HAS_OWN_BUILDER_ID,
229 g_param_spec_boolean(
230 BASE_PROP_HAS_OWN_BUILDER,
231 _( "Has its own GtkBuilder" ),
232 _( "Whether this BaseWindow reallocates a new GtkBuilder each time it is opened" ),
233 FALSE,
234 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
236 g_object_class_install_property( object_class, BASE_PROP_TOPLEVEL_NAME_ID,
237 g_param_spec_string(
238 BASE_PROP_TOPLEVEL_NAME,
239 _( "Toplevel name" ),
240 _( "The internal GtkBuildable name of the toplevel window" ),
242 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
244 klass->private = g_new0( BaseWindowClassPrivate, 1 );
246 klass->initial_load_toplevel = do_initialize_gtk_toplevel;
247 klass->runtime_init_toplevel = do_initialize_base_window;
248 klass->all_widgets_showed = NULL;
249 klass->dialog_response = window_do_dialog_response;
250 klass->delete_event = window_do_delete_event;
251 klass->get_toplevel_name = NULL;
252 klass->get_iprefs_window_id = NULL;
253 klass->get_ui_filename = NULL;
254 klass->is_willing_to_quit = window_do_is_willing_to_quit;
257 * base-window-initialize-gtk:
259 * The signal is emitted by the #BaseWindow instance when it has
260 * loaded for the first time the Gtk toplevel widget from the GtkBuilder.
262 st_signals[ INITIALIZE_GTK ] =
263 g_signal_new_class_handler(
264 BASE_SIGNAL_INITIALIZE_GTK,
265 G_TYPE_FROM_CLASS( klass ),
266 G_SIGNAL_RUN_LAST,
267 G_CALLBACK( on_initialize_gtk_toplevel_class_handler ),
268 NULL,
269 NULL,
270 g_cclosure_marshal_VOID__POINTER,
271 G_TYPE_NONE,
273 G_TYPE_POINTER );
276 * base-window-initialize-window:
278 * The signal is emitted by the #BaseWindow instance after the toplevel
279 * GtkWindow has been initialized, before actually displaying the window.
280 * Is is so time to initialize it with runtime values.
282 st_signals[ INITIALIZE_BASE ] =
283 g_signal_new_class_handler(
284 BASE_SIGNAL_INITIALIZE_WINDOW,
285 G_TYPE_FROM_CLASS( klass ),
286 G_SIGNAL_RUN_LAST,
287 G_CALLBACK( on_initialize_base_window_class_handler ),
288 NULL,
289 NULL,
290 g_cclosure_marshal_VOID__POINTER,
291 G_TYPE_NONE,
293 G_TYPE_POINTER );
296 * nact-signal-base-window-all-widgets-showed:
298 * The signal is emitted by the #BaseWindow instance when the
299 * toplevel widget has been initialized with its runtime values,
300 * just after showing it and all its descendants.
302 * It is typically used by notebooks, to select the first visible
303 * page.
305 st_signals[ ALL_WIDGETS_SHOWED ] =
306 g_signal_new_class_handler(
307 BASE_SIGNAL_ALL_WIDGETS_SHOWED,
308 G_TYPE_FROM_CLASS( klass ),
309 G_SIGNAL_RUN_LAST,
310 G_CALLBACK( on_all_widgets_showed_class_handler ),
311 NULL,
312 NULL,
313 g_cclosure_marshal_VOID__POINTER,
314 G_TYPE_NONE,
316 G_TYPE_POINTER );
319 static void
320 iprefs_base_iface_init( BaseIPrefsInterface *iface )
322 static const gchar *thisfn = "base_window_iprefs_base_iface_init";
324 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
326 iface->iprefs_get_window_id = v_get_iprefs_window_id;
329 static void
330 instance_init( GTypeInstance *instance, gpointer klass )
332 static const gchar *thisfn = "base_window_instance_init";
333 BaseWindow *self;
335 g_return_if_fail( BASE_IS_WINDOW( instance ));
337 g_debug( "%s: instance=%p (%s), klass=%p",
338 thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
340 self = BASE_WINDOW( instance );
342 /* at a first glance, we may suppose that this first window is the main one
343 * if this is not the case, we have to write some more code
345 if( !st_first_window ){
346 st_first_window = self;
349 self->private = g_new0( BaseWindowPrivate, 1 );
351 self->private->dispose_has_run = FALSE;
352 self->private->signals = NULL;
353 self->private->save_window_position = TRUE;
356 static void
357 instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
359 BaseWindow *self;
361 g_return_if_fail( BASE_IS_WINDOW( object ));
362 self = BASE_WINDOW( object );
364 if( !self->private->dispose_has_run ){
366 switch( property_id ){
367 case BASE_PROP_PARENT_ID:
368 g_value_set_pointer( value, self->private->parent );
369 break;
371 case BASE_PROP_APPLICATION_ID:
372 g_value_set_pointer( value, self->private->application );
373 break;
375 case BASE_PROP_XMLUI_FILENAME_ID:
376 g_value_set_string( value, self->private->xmlui_filename );
377 break;
379 case BASE_PROP_HAS_OWN_BUILDER_ID:
380 g_value_set_boolean( value, self->private->has_own_builder );
381 break;
383 case BASE_PROP_TOPLEVEL_NAME_ID:
384 g_value_set_string( value, self->private->toplevel_name );
385 break;
387 default:
388 G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
389 break;
394 static void
395 instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
397 BaseWindow *self;
399 g_return_if_fail( BASE_IS_WINDOW( object ));
400 self = BASE_WINDOW( object );
402 if( !self->private->dispose_has_run ){
404 switch( property_id ){
405 case BASE_PROP_PARENT_ID:
406 self->private->parent = g_value_get_pointer( value );
407 break;
409 case BASE_PROP_APPLICATION_ID:
410 self->private->application = g_value_get_pointer( value );
411 break;
413 case BASE_PROP_XMLUI_FILENAME_ID:
414 g_free( self->private->xmlui_filename );
415 self->private->xmlui_filename = g_value_dup_string( value );
416 break;
418 case BASE_PROP_HAS_OWN_BUILDER_ID:
419 self->private->has_own_builder = g_value_get_boolean( value );
420 break;
422 case BASE_PROP_TOPLEVEL_NAME_ID:
423 g_free( self->private->toplevel_name );
424 self->private->toplevel_name = g_value_dup_string( value );
425 break;
427 default:
428 G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
429 break;
434 static void
435 instance_dispose( GObject *window )
437 static const gchar *thisfn = "base_window_instance_dispose";
438 BaseWindow *self;
439 GSList *is;
441 g_return_if_fail( BASE_IS_WINDOW( window ));
443 self = BASE_WINDOW( window );
445 if( !self->private->dispose_has_run ){
447 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
449 if( self->private->save_window_position ){
450 base_iprefs_save_window_position( self );
453 /* signals must be deconnected before quitting main loop
455 for( is = self->private->signals ; is ; is = is->next ){
456 BaseWindowRecordedSignal *str = ( BaseWindowRecordedSignal * ) is->data;
457 if( g_signal_handler_is_connected( str->instance, str->handler_id )){
458 g_signal_handler_disconnect( str->instance, str->handler_id );
459 if( st_debug_signal_connect ){
460 g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );
463 g_free( str );
465 g_slist_free( self->private->signals );
467 if( is_main_window( BASE_WINDOW( window ))){
468 g_debug( "%s: quitting main window", thisfn );
469 gtk_main_quit ();
470 gtk_widget_destroy( GTK_WIDGET( self->private->gtk_toplevel ));
472 } else if( GTK_IS_ASSISTANT( self->private->gtk_toplevel )){
473 g_debug( "%s: quitting assistant", thisfn );
474 gtk_main_quit();
475 if( is_gtk_toplevel_initialized( self, self->private->gtk_toplevel )){
476 gtk_widget_hide( GTK_WIDGET( self->private->gtk_toplevel ));
479 } else {
480 g_debug( "%s: quitting dialog", thisfn );
481 if( is_gtk_toplevel_initialized( self, self->private->gtk_toplevel )){
482 gtk_widget_hide( GTK_WIDGET( self->private->gtk_toplevel ));
486 /* must dispose _after_ quitting the loop
488 self->private->dispose_has_run = TRUE;
490 /* release the Gtkbuilder, if any
492 if( self->private->has_own_builder ){
493 if( self->private->builder ){
494 g_object_unref( self->private->builder );
498 /* chain up to the parent class */
499 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
500 G_OBJECT_CLASS( st_parent_class )->dispose( window );
505 static void
506 instance_finalize( GObject *window )
508 static const gchar *thisfn = "base_window_instance_finalize";
509 BaseWindow *self;
511 g_return_if_fail( BASE_IS_WINDOW( window ));
513 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
515 self = BASE_WINDOW( window );
517 g_free( self->private->toplevel_name );
518 g_free( self->private->xmlui_filename );
520 g_free( self->private );
522 /* chain call to parent class */
523 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
524 G_OBJECT_CLASS( st_parent_class )->finalize( window );
529 * base_window_init:
530 * @window: this #BaseWindow object.
532 * Initializes the window.
534 * This is a one-time initialization just after the BaseWindow has been
535 * allocated. This should leave the BaseWindow object with a valid
536 * toplevel GtkWindow dialog. This is also time to make one-time
537 * initialization on this toplevel dialog.
539 * For an every-time initialization, see base_window_run().
541 * Note that the BaseWindow itself should be initialized each time
542 * the user opens the dialog, though the GtkWindow itself needs only
543 * be initialized the first time it is loaded.
545 * Returns: %TRUE if the window has been successfully initialized,
546 * %FALSE else.
548 gboolean
549 base_window_init( BaseWindow *window )
551 static const gchar *thisfn = "base_window_init";
553 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
555 if( !window->private->dispose_has_run &&
556 !window->private->initialized ){
558 g_debug( "%s: window=%p", thisfn, ( void * ) window );
560 if( !window->private->application ){
561 g_return_val_if_fail( window->private->parent, FALSE );
562 g_return_val_if_fail( BASE_IS_WINDOW( window->private->parent ), FALSE );
563 window->private->application = BASE_APPLICATION( base_window_get_application( window->private->parent ));
564 g_debug( "%s: application=%p", thisfn, ( void * ) window->private->application );
567 g_return_val_if_fail( window->private->application, FALSE );
568 g_return_val_if_fail( BASE_IS_APPLICATION( window->private->application ), FALSE );
570 if( setup_builder( window ) &
571 load_gtk_toplevel( window )){
573 if( window->private->gtk_toplevel ){
574 g_return_val_if_fail( GTK_IS_WINDOW( window->private->gtk_toplevel ), FALSE );
576 if( !is_gtk_toplevel_initialized( window, window->private->gtk_toplevel )){
577 g_signal_emit_by_name( window, BASE_SIGNAL_INITIALIZE_GTK, NULL );
578 set_gtk_toplevel_initialized( window, window->private->gtk_toplevel, TRUE );
581 window->private->initialized = TRUE;
586 return( window->private->initialized );
590 * setup the builder of the window as a new one, or use the global one
592 * A dialog may have its own builder ,sharing the common UI XML definition file
593 * or a dialog may have its own UI XML definition file, sharing the common builder
594 * or a dialog may have both its UI XML definition file with its own builder
596 static gboolean
597 setup_builder( const BaseWindow *window )
599 static const gchar *thisfn = "base_window_setup_builder";
600 gboolean ret;
601 GError *error = NULL;
602 gchar *msg;
604 /* allocate a dedicated BaseBuilder or use the common one
606 if( window->private->has_own_builder ){
607 window->private->builder = base_builder_new();
608 } else {
609 g_return_val_if_fail( BASE_IS_APPLICATION( window->private->application ), FALSE );
610 window->private->builder = base_application_get_builder( window->private->application );
613 /* use the xml ui filename provided as a construction property
614 * or ask the window for it
616 if(( !window->private->xmlui_filename || !g_utf8_strlen( window->private->xmlui_filename, -1 )) &&
617 BASE_WINDOW_GET_CLASS( window )->get_ui_filename ){
619 g_free( window->private->xmlui_filename );
620 window->private->xmlui_filename = BASE_WINDOW_GET_CLASS( window )->get_ui_filename( window );
623 /* load the XML definition from the UI file
625 ret = FALSE;
626 if( window->private->xmlui_filename && g_utf8_strlen( window->private->xmlui_filename, -1 )){
627 if( base_builder_add_from_file( window->private->builder, window->private->xmlui_filename, &error )){
628 ret = TRUE;
629 } else {
630 msg = g_strdup_printf( _( "Unable to load %s UI XML definition: %s" ), window->private->xmlui_filename, error->message );
631 base_window_display_error_dlg( NULL, thisfn, msg );
632 g_free( msg );
633 g_error_free( error );
637 return( ret );
640 static gboolean
641 load_gtk_toplevel( const BaseWindow *window )
643 gchar *toplevel_name;
644 GtkWindow *gtk_toplevel;
645 gchar *msg;
647 /* we should only test for the construction property toplevel_name
648 * during the transition, also asks the derived class
650 toplevel_name = v_get_toplevel_name( window );
651 gtk_toplevel = NULL;
653 if( toplevel_name ){
654 if( strlen( toplevel_name )){
655 g_return_val_if_fail( BASE_IS_BUILDER( window->private->builder ), FALSE );
656 gtk_toplevel = base_builder_get_toplevel_by_name( window->private->builder, toplevel_name );
658 if( !gtk_toplevel ){
659 msg = g_strdup_printf( _( "Unable to load %s dialog definition." ), toplevel_name );
660 base_window_display_error_dlg( NULL, msg, NULL );
661 g_free( msg );
666 g_free( toplevel_name );
667 window->private->gtk_toplevel = gtk_toplevel;
669 return( gtk_toplevel != NULL );
672 static gboolean
673 is_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel )
675 gboolean initialized;
677 initialized = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( gtk_toplevel ), "base-window-gtk-toplevel-initialized" ));
679 return( initialized );
682 static void
683 set_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel, gboolean initialized )
685 g_object_set_data( G_OBJECT( gtk_toplevel ), "base-window-gtk-toplevel-initialized", GUINT_TO_POINTER( initialized ));
689 * base_window_run:
690 * @window: this #BaseWindow object.
692 * Runs the window.
694 * Returns: the exit code of the program is this is the main window.
697 base_window_run( BaseWindow *window )
699 static const gchar *thisfn = "base_window_run";
700 gboolean run_ok;
701 gint code;
703 g_return_val_if_fail( BASE_IS_WINDOW( window ), BASE_EXIT_CODE_START_FAIL );
705 run_ok = FALSE;
707 if( !window->private->dispose_has_run ){
709 run_ok = window->private->initialized;
711 if( !window->private->initialized ){
712 run_ok = base_window_init( window );
715 if( run_ok ){
716 g_return_val_if_fail( GTK_IS_WINDOW( window->private->gtk_toplevel ), BASE_EXIT_CODE_START_FAIL );
718 g_debug( "%s: window=%p", thisfn, ( void * ) window );
719 g_signal_emit_by_name( window, BASE_SIGNAL_INITIALIZE_WINDOW, NULL );
721 gtk_widget_show_all( GTK_WIDGET( window->private->gtk_toplevel ));
722 g_signal_emit_by_name( window, BASE_SIGNAL_ALL_WIDGETS_SHOWED, NULL );
724 if( is_main_window( window )){
725 if( GTK_IS_DIALOG( window->private->gtk_toplevel )){
726 g_signal_connect( G_OBJECT( window->private->gtk_toplevel ), "response", G_CALLBACK( v_dialog_response ), window );
727 } else {
728 g_signal_connect( G_OBJECT( window->private->gtk_toplevel ), "delete-event", G_CALLBACK( on_delete_event ), window );
731 g_debug( "%s: application=%p, starting gtk_main", thisfn, ( void * ) window->private->application );
732 gtk_main();
734 } else if( GTK_IS_ASSISTANT( window->private->gtk_toplevel )){
735 g_debug( "%s: starting gtk_main", thisfn );
736 gtk_main();
738 } else {
739 g_assert( GTK_IS_DIALOG( window->private->gtk_toplevel ));
740 g_debug( "%s: starting gtk_dialog_run", thisfn );
741 do {
742 code = gtk_dialog_run( GTK_DIALOG( window->private->gtk_toplevel ));
744 while( !v_dialog_response( GTK_DIALOG( window->private->gtk_toplevel ), code, window ));
749 return( run_ok ? BASE_EXIT_CODE_OK : BASE_EXIT_CODE_MAIN_WINDOW );
753 * base_window_get_application:
754 * @window: this #BaseWindow object.
756 * Returns: a pointer on the #BaseApplication object.
758 * The returned pointer is owned by the primary allocator of the
759 * application ; it should not be g_free() nor g_object_unref() by the
760 * caller.
762 BaseApplication *
763 base_window_get_application( const BaseWindow *window )
765 BaseApplication *application = NULL;
767 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
769 if( !window->private->dispose_has_run ){
771 application = window->private->application;
774 return( application );
778 * base_window_get_parent:
779 * @window: this #BaseWindow instance..
781 * Returns the #BaseWindow parent of @window.
783 * The returned object is owned by @window, and should not be freed.
785 BaseWindow *
786 base_window_get_parent( const BaseWindow *window )
788 BaseWindow *parent = NULL;
790 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
792 if( !window->private->dispose_has_run ){
794 parent = window->private->parent;
797 return( parent );
801 * base_window_get_gtk_toplevel:
802 * @window: this #BaseWindow instance..
804 * Returns the top-level GtkWindow attached to this BaseWindow object.
806 * The caller may close the window by g_object_unref()-ing the returned
807 * #GtkWindow.
809 GtkWindow *
810 base_window_get_gtk_toplevel( const BaseWindow *window )
812 GtkWindow *gtk_toplevel = NULL;
814 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
816 if( !window->private->dispose_has_run ){
818 gtk_toplevel = window->private->gtk_toplevel;
821 return( gtk_toplevel );
825 * base_window_get_gtk_toplevel_by_name:
826 * @window: this #BaseWindow instance.
827 * @name: the name of the searched GtkWindow.
829 * Returns: the named top-level GtkWindow.
831 * This is just a convenience function to be able to open quickly a
832 * window (e.g. Legend dialog).
834 * The caller may close the window by g_object_unref()-ing the returned
835 * #GtkWindow.
837 GtkWindow *
838 base_window_get_gtk_toplevel_by_name( const BaseWindow *window, const gchar *name )
840 GtkWindow *gtk_toplevel = NULL;
842 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
844 if( !window->private->dispose_has_run ){
846 gtk_toplevel = base_builder_get_toplevel_by_name( window->private->builder, name );
849 return( gtk_toplevel );
853 * base_window_get_widget:
854 * @window: this #BaseWindow instance.
855 * @name: the name of the searched child.
857 * Returns a pointer to the named widget which is a child of the
858 * toplevel #GtkWindow associated with @window.
860 * Returns: a pointer to the searched widget, or NULL.
861 * This pointer is owned by GtkBuilder instance, and must not be
862 * g_free() nor g_object_unref() by the caller.
864 GtkWidget *
865 base_window_get_widget( const BaseWindow *window, const gchar *name )
867 GtkWidget *widget = NULL;
869 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
871 if( !window->private->dispose_has_run ){
873 widget = nact_gtk_utils_get_widget_by_name( window->private->gtk_toplevel, name );
876 return( widget );
880 * base_window_is_willing_to_quit:
881 * @window: this #BaseWindow instance.
883 * Returns: %TRUE if the application is willing to quit, %FALSE else.
885 * This function is called when the session manager detects the end of
886 * session and thus asks its client if they are willing to quit.
888 gboolean
889 base_window_is_willing_to_quit( const BaseWindow *window )
891 gboolean willing_to;
892 GObjectClass *class;
894 willing_to = TRUE;
896 g_return_val_if_fail( BASE_IS_WINDOW( window ), TRUE );
898 if( !window->private->dispose_has_run ){
900 for( class = G_OBJECT_GET_CLASS( window ) ; willing_to && BASE_IS_WINDOW_CLASS( class ) ; class = g_type_class_peek_parent( class )){
901 if( BASE_WINDOW_CLASS( class )->is_willing_to_quit ){
902 willing_to = BASE_WINDOW_CLASS( class )->is_willing_to_quit( window );
907 return( willing_to );
911 * handler of "delete-event" message
912 * let a chance to derived class to handle it
913 * our own function does nothing, and let the signal be propagated.
915 static gboolean
916 on_delete_event( GtkWidget *toplevel, GdkEvent *event, BaseWindow *window )
918 static const gchar *thisfn = "base_window_on_delete_event";
919 static gboolean stop = FALSE;
921 g_debug( "%s: toplevel=%p, event=%p, window=%p",
922 thisfn, ( void * ) toplevel, ( void * ) event, ( void * ) window );
923 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
925 if( !window->private->dispose_has_run ){
927 if( BASE_WINDOW_GET_CLASS( window )->delete_event ){
928 stop = BASE_WINDOW_GET_CLASS( window )->delete_event( window, GTK_WINDOW( toplevel ), event );
930 } else {
931 stop = window_do_delete_event( window, GTK_WINDOW( toplevel ), event );
935 return( stop );
939 * default class handler for "base-window-initialize-gtk" signal
941 * successively invokes the method of each derived class, starting from
942 * the topmost derived up to this BaseWindow
944 static void
945 on_initialize_gtk_toplevel_class_handler( BaseWindow *window, gpointer user_data )
947 static const gchar *thisfn = "base_window_on_initialize_gtk_toplevel_class_handler";
948 GObjectClass *class;
950 g_return_if_fail( BASE_IS_WINDOW( window ));
952 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
954 if( !window->private->dispose_has_run ){
956 for( class = G_OBJECT_GET_CLASS( window ) ; BASE_IS_WINDOW_CLASS( class ) ; class = g_type_class_peek_parent( class )){
957 if( BASE_WINDOW_CLASS( class )->initial_load_toplevel ){
958 BASE_WINDOW_CLASS( class )->initial_load_toplevel( window, user_data );
964 static void
965 do_initialize_gtk_toplevel( BaseWindow *window, gpointer user_data )
967 static const gchar *thisfn = "base_window_do_initialize_gtk_toplevel";
968 GtkWindow *parent_gtk_toplevel;
970 g_return_if_fail( BASE_IS_WINDOW( window ));
972 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
974 if( !window->private->dispose_has_run ){
976 g_debug( "%s: parent=%p (%s)", thisfn,
977 ( void * ) window->private->parent,
978 window->private->parent ? G_OBJECT_TYPE_NAME( window->private->parent ) : "null" );
980 if( window->private->parent ){
982 g_return_if_fail( BASE_IS_WINDOW( window->private->parent ));
983 parent_gtk_toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( window->private->parent ));
984 g_debug( "%s: toplevel=%p, parent_gtk_toplevel=%p", thisfn, ( void * ) window->private->gtk_toplevel, ( void * ) parent_gtk_toplevel );
985 gtk_window_set_transient_for( window->private->gtk_toplevel, parent_gtk_toplevel );
991 * default class handler for "nact-signal-base-window-runtime-init" message
992 * -> does nothing here
994 static void
995 on_initialize_base_window_class_handler( BaseWindow *window, gpointer user_data )
997 static const gchar *thisfn = "base_window_on_initialize_base_window_class_handler";
998 GObjectClass *class;
1000 g_return_if_fail( BASE_IS_WINDOW( window ));
1002 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
1004 if( !window->private->dispose_has_run ){
1006 for( class = G_OBJECT_GET_CLASS( window ) ; BASE_IS_WINDOW_CLASS( class ) ; class = g_type_class_peek_parent( class )){
1007 if( BASE_WINDOW_CLASS( class )->runtime_init_toplevel ){
1008 BASE_WINDOW_CLASS( class )->runtime_init_toplevel( window, user_data );
1014 static void
1015 do_initialize_base_window( BaseWindow *window, gpointer user_data )
1017 static const gchar *thisfn = "base_window_do_initialize_base_window";
1019 g_return_if_fail( BASE_IS_WINDOW( window ));
1021 g_debug( "%s: window=%p, user_data=%p, parent_window=%p",
1022 thisfn, ( void * ) window, ( void * ) user_data, ( void * ) window->private->parent );
1024 if( !window->private->dispose_has_run ){
1026 base_iprefs_position_window( window );
1030 static void
1031 on_all_widgets_showed_class_handler( BaseWindow *window, gpointer user_data )
1033 static const gchar *thisfn = "base_window_on_all_widgets_showed_class_handler";
1034 GObjectClass *class;
1036 g_return_if_fail( BASE_IS_WINDOW( window ));
1038 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
1040 if( !window->private->dispose_has_run ){
1042 for( class = G_OBJECT_GET_CLASS( window ) ; BASE_IS_WINDOW_CLASS( class ) ; class = g_type_class_peek_parent( class )){
1043 if( BASE_WINDOW_CLASS( class )->all_widgets_showed ){
1044 BASE_WINDOW_CLASS( class )->all_widgets_showed( window, user_data );
1050 static gboolean
1051 v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
1053 static const gchar *thisfn = "base_window_v_dialog_response";
1054 gboolean stop = FALSE;
1056 g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, ( void * ) dialog, code, ( void * ) window );
1057 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
1059 if( !window->private->dispose_has_run ){
1061 if( BASE_WINDOW_GET_CLASS( window )->dialog_response ){
1062 stop = BASE_WINDOW_GET_CLASS( window )->dialog_response( dialog, code, window );
1064 } else {
1065 stop = window_do_dialog_response( dialog, code, window );
1069 return( stop );
1072 static gchar *
1073 v_get_toplevel_name( const BaseWindow *window )
1075 gchar *name = NULL;
1077 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
1079 g_object_get( G_OBJECT( window ), BASE_PROP_TOPLEVEL_NAME, &name, NULL );
1081 if( !name || !strlen( name )){
1082 if( BASE_WINDOW_GET_CLASS( window )->get_toplevel_name ){
1083 name = BASE_WINDOW_GET_CLASS( window )->get_toplevel_name( window );
1084 if( name && strlen( name )){
1085 g_object_set( G_OBJECT( window ), BASE_PROP_TOPLEVEL_NAME, name, NULL );
1090 return( name );
1093 static gchar *
1094 v_get_iprefs_window_id( const BaseWindow *window )
1096 gchar *id = NULL;
1098 g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
1100 if( !window->private->dispose_has_run ){
1102 if( BASE_WINDOW_GET_CLASS( window )->get_iprefs_window_id ){
1103 id = BASE_WINDOW_GET_CLASS( window )->get_iprefs_window_id( window );
1107 return( id );
1111 * return TRUE to quit the dialog loop
1113 static gboolean
1114 window_do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
1116 static const gchar *thisfn = "base_window_do_dialog_response";
1118 g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, ( void * ) dialog, code, ( void * ) window );
1119 g_return_val_if_fail( GTK_IS_DIALOG( dialog ), FALSE );
1120 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
1122 return( TRUE );
1126 * return TRUE to stop other handlers from being invoked for the event.
1127 * note that default handler will destroy this window
1129 static gboolean
1130 window_do_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event )
1132 static const gchar *thisfn = "base_window_do_delete_event";
1134 g_debug( "%s: window=%p, toplevel=%p, event=%p",
1135 thisfn, ( void * ) window, ( void * ) toplevel, ( void * ) event );
1136 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
1137 g_return_val_if_fail( GTK_IS_WINDOW( toplevel ), FALSE );
1139 return( FALSE );
1142 static gboolean
1143 window_do_is_willing_to_quit( const BaseWindow *window )
1145 static const gchar *thisfn = "base_window_do_is_willing_to_quit";
1147 g_debug( "%s: window=%p", thisfn, ( void * ) window );
1149 return( TRUE );
1152 static gboolean
1153 is_main_window( BaseWindow *window )
1155 gboolean is_main = FALSE;
1157 g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
1159 if( !window->private->dispose_has_run ){
1161 is_main = ( window == st_first_window );
1164 return( is_main );
1168 * base_window_display_error_dlg:
1169 * @parent: the #BaseWindow parent, may be %NULL.
1170 * @primary: the primary message.
1171 * @secondary: the secondary message.
1173 * Display an error dialog box, with a 'OK' button only.
1175 * if @secondary is not null, then @primary is displayed as a bold title.
1177 void
1178 base_window_display_error_dlg( const BaseWindow *parent, const gchar *primary, const gchar *secondary )
1180 display_dlg( parent, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, primary, secondary );
1184 * base_window_display_yesno_dlg:
1185 * @parent: the #BaseWindow parent, may be %NULL.
1186 * @primary: the primary message.
1187 * @secondary: the secondary message.
1189 * Display a warning dialog box, with a 'OK' button only.
1191 * if @secondary is not null, then @primary is displayed as a bold title.
1193 * Returns: %TRUE if the user has clicked 'Yes', %FALSE else.
1195 gboolean
1196 base_window_display_yesno_dlg( const BaseWindow *parent, const gchar *primary, const gchar *secondary )
1198 gint result;
1200 result = display_dlg( parent, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, primary, secondary );
1202 return( result == GTK_RESPONSE_YES );
1206 * base_window_display_message_dlg:
1207 * @parent: the #BaseWindow parent, may be %NULL.
1208 * @message: the message to be displayed.
1210 * Displays an information dialog with only an OK button.
1212 void
1213 base_window_display_message_dlg( const BaseWindow *parent, GSList *msg )
1215 GString *string;
1216 GSList *im;
1218 string = g_string_new( "" );
1219 for( im = msg ; im ; im = im->next ){
1220 if( g_utf8_strlen( string->str, -1 )){
1221 string = g_string_append( string, "\n" );
1223 string = g_string_append( string, ( gchar * ) im->data );
1225 display_dlg( parent, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, string->str, NULL );
1227 g_string_free( string, TRUE );
1230 static gint
1231 display_dlg( const BaseWindow *parent, GtkMessageType type_message, GtkButtonsType type_buttons, const gchar *primary, const gchar *secondary )
1233 GtkWindow *gtk_parent;
1234 GtkWidget *dialog;
1235 gint result;
1237 gtk_parent = NULL;
1238 if( parent ){
1239 gtk_parent = base_window_get_gtk_toplevel( parent );
1242 dialog = gtk_message_dialog_new( gtk_parent, GTK_DIALOG_MODAL, type_message, type_buttons, "%s", primary );
1244 if( secondary && g_utf8_strlen( secondary, -1 )){
1245 gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( dialog ), "%s", secondary );
1248 g_object_set( G_OBJECT( dialog ) , "title", g_get_application_name(), NULL );
1250 result = gtk_dialog_run( GTK_DIALOG( dialog ));
1252 gtk_widget_destroy( dialog );
1254 return( result );
1258 * Records a connected signal, to be disconnected at NactWindow dispose.
1260 gulong
1261 base_window_signal_connect( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn )
1263 gulong handler_id = 0;
1265 g_return_val_if_fail( BASE_IS_WINDOW( window ), ( gulong ) 0 );
1267 if( !window->private->dispose_has_run ){
1269 handler_id = g_signal_connect( instance, signal, fn, window );
1270 record_connected_signal( window, instance, handler_id );
1273 return( handler_id );
1276 gulong
1277 base_window_signal_connect_after( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn )
1279 gulong handler_id = 0;
1281 g_return_val_if_fail( BASE_IS_WINDOW( window ), ( gulong ) 0 );
1283 if( !window->private->dispose_has_run ){
1285 handler_id = g_signal_connect_after( instance, signal, fn, window );
1286 record_connected_signal( window, instance, handler_id );
1289 return( handler_id );
1292 gulong
1293 base_window_signal_connect_by_name( BaseWindow *window, const gchar *name, const gchar *signal, GCallback fn )
1295 gulong handler_id = 0;
1297 g_return_val_if_fail( BASE_IS_WINDOW( window ), ( gulong ) 0 );
1299 if( !window->private->dispose_has_run ){
1301 GtkWidget *widget = base_window_get_widget( window, name );
1302 if( GTK_IS_WIDGET( widget )){
1304 handler_id = base_window_signal_connect( window, G_OBJECT( widget ), signal, fn );
1308 return( handler_id );
1311 gulong
1312 base_window_signal_connect_with_data( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn, void *user_data )
1314 gulong handler_id = 0;
1316 g_return_val_if_fail( BASE_IS_WINDOW( window ), ( gulong ) 0 );
1318 if( !window->private->dispose_has_run ){
1320 handler_id = g_signal_connect( instance, signal, fn, user_data );
1321 record_connected_signal( window, instance, handler_id );
1324 return( handler_id );
1327 static void
1328 record_connected_signal( BaseWindow *window, GObject *instance, gulong handler_id )
1330 static const gchar *thisfn = "base_window_record_connected_signal";
1332 BaseWindowRecordedSignal *str = g_new0( BaseWindowRecordedSignal, 1 );
1333 str->instance = instance;
1334 str->handler_id = handler_id;
1335 window->private->signals = g_slist_prepend( window->private->signals, str );
1337 if( st_debug_signal_connect ){
1338 g_debug( "%s: connecting signal handler %p:%lu", thisfn, ( void * ) instance, handler_id );