/* $Id$ * Drivers acquiring installation utility * Copyright (C) 2003 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "ui-gnome.h" /* self */ #include #include "moduriload.h" #include "main.h" #include #include #include #include #include #include #include #include #include #include #include #include "final.h" #include #include /* Config: */ #define PROGRESS_UPDATE_USEC 200000 /* Although proper GTK+ locking is provided below there are some * bugs with compatibility of GTK+/Gnome-VFS/GConf. * The main thread executes gtk_main()->g_main_loop_run() * while the working thread initializes Gnome-VFS by GConf and * executes also g_main_loop_run() while sharing some poll() fds. */ /* #define UI_GNOME_THREADS 1 */ static GnomeApp *App; static GtkTreeStore *DriversTreeStore; static GtkFrame *DriversFrame; static GtkFrame *ProgressFrame; static GtkEntry *ProgressEntry; static GnomeDruid *Druid; static GtkButton *DruidButtonSkip; static GtkButton *DruidButtonOK; static GtkTreeView *DriversTreeView; static GnomeDruidPage *PageStart; static GnomeDruidPage *ScanDiskPage; static GnomeDruidPage *ScanPathPage; static GnomeDruidPage *MicrosoftComPage; static GnomeDruidPage *PageFinish; static GtkEntry *ScanPathLocationComboEntry; static GtkButton *MicrosoftComConfirmButton; static GtkProgressBar *MicrosoftComProgress; enum { DRIVERS_TREE_STORE_COLUMN_TYPE, DRIVERS_TREE_STORE_COLUMN_ID, DRIVERS_TREE_STORE_COLUMN_NUM, /* total # */ }; #define DRIVERS_TREE_STORE_COLUMN_TYPE_LIST G_TYPE_STRING,G_TYPE_STRING /* map: (gchar *)type-> (GtkTreeIter *) */ static GHashTable *DriversTreeStore_Iter_hash; static void DriversTreeStore_Iter_hash_key_destroy_func(gchar *type) { g_return_if_fail(type!=NULL); g_free(type); } static void DriversTreeStore_Iter_hash_init(void) { if (DriversTreeStore_Iter_hash) return; DriversTreeStore_Iter_hash=g_hash_table_new_full(g_str_hash,g_str_equal, (GDestroyNotify)DriversTreeStore_Iter_hash_key_destroy_func, NULL); /* value_destroy_func */ } static GtkTreeIter *DriversTreeStore_Iter_hash_get_iter(const gchar *type) { GtkTreeIter *r; g_return_val_if_fail(type!=NULL,NULL); DriversTreeStore_Iter_hash_init(); if (!(r=g_hash_table_lookup(DriversTreeStore_Iter_hash,type))) { captive_new(r); gtk_tree_store_append(DriversTreeStore, r, /* iter */ NULL); /* parent */ g_hash_table_insert(DriversTreeStore_Iter_hash,g_strdup(type),r); } return r; } static gboolean some_modules_found=FALSE; static gboolean in_progress=FALSE; static GnomeDruidPage *page_active; static void state_changed(void) { /* Not yet initialized? */ if (!App) return; gtk_widget_set_sensitive(GTK_WIDGET(DruidButtonSkip), (page_active!=PageStart && page_active!=PageFinish)); gtk_widget_set_sensitive(GTK_WIDGET(DruidButtonOK),some_modules_found); if (in_progress) { gtk_widget_set_sensitive(Druid->next,FALSE); gtk_widget_set_sensitive(GTK_WIDGET(DruidButtonOK),some_modules_found); gtk_widget_set_sensitive(GTK_WIDGET(MicrosoftComConfirmButton),FALSE); } else { /* It is checked by GTK+ whether the text changed: */ gtk_entry_set_text(ProgressEntry,""); gtk_widget_set_sensitive(Druid->next, (page_active!=PageFinish && page_active!=MicrosoftComPage)); gtk_widget_set_sensitive(GTK_WIDGET(MicrosoftComConfirmButton), (page_active==MicrosoftComPage)); gtk_progress_bar_set_fraction(MicrosoftComProgress,(gdouble)0); gtk_progress_bar_set_text(MicrosoftComProgress,""); } } static void ui_gnome_module_best_priority_notify(const gchar *module_type) { GtkTreeIter *iter; g_return_if_fail(module_type!=NULL); gdk_threads_enter(); iter=DriversTreeStore_Iter_hash_get_iter(module_type); gtk_tree_store_set(DriversTreeStore,iter, DRIVERS_TREE_STORE_COLUMN_TYPE,module_type, DRIVERS_TREE_STORE_COLUMN_ID , ((0 || !strcmp(module_type,"ntoskrnl.exe") || !strcmp(module_type,"ntfs.sys")) ? _("NOT FOUND; essential module for NTFS disks access") : _("not found; optional module")), -1); gdk_flush(); gdk_threads_leave(); } static void ui_gnome_module_available_notify(struct module_available *module_available) { GtkTreeIter *iter; static gboolean some_module_ntoskrnl_exe_found=FALSE; static gboolean some_module_ntfs_sys_found=FALSE; g_return_if_fail(module_available!=NULL); g_return_if_fail(module_available->module!=NULL); gdk_threads_enter(); iter=DriversTreeStore_Iter_hash_get_iter((const gchar *)module_available->module->type); gtk_tree_store_set(DriversTreeStore,iter, DRIVERS_TREE_STORE_COLUMN_TYPE,module_available->module->type, DRIVERS_TREE_STORE_COLUMN_ID ,module_available->module->id, -1); if (!strcmp((const char *)module_available->module->type,"ntoskrnl.exe")) some_module_ntoskrnl_exe_found=TRUE; if (!strcmp((const char *)module_available->module->type,"ntfs.sys")) some_module_ntfs_sys_found=TRUE; some_modules_found=some_module_ntoskrnl_exe_found && some_module_ntfs_sys_found; state_changed(); gdk_flush(); gdk_threads_leave(); } static gboolean all_modules_found=FALSE; static void ui_gnome_all_modules_found_notify(void) { gdk_threads_enter(); all_modules_found=TRUE; state_changed(); gdk_flush(); gdk_threads_leave(); } static gboolean aborted=FALSE; static gboolean aborted_back=FALSE; /* 'Back' button was clicked. */ static struct timeval ProgressEntry_updated_timeval; static struct timeval ProgressBar_updated_timeval; static void progress_start(void) { in_progress=TRUE; aborted=FALSE; aborted_back=FALSE; CAPTIVE_MEMZERO(&ProgressEntry_updated_timeval); CAPTIVE_MEMZERO(&ProgressBar_updated_timeval); state_changed(); } static void progress_end(void) { in_progress=FALSE; state_changed(); } static gboolean want_progress_update(struct timeval *timeval) { struct timeval now_timeval; struct timeval diff_timeval; g_return_val_if_fail(timeval!=NULL,FALSE); gettimeofday( /* FIXME: errors ignored */ &now_timeval, /* tv */ NULL); /* tz */ timersub(&now_timeval,timeval,&diff_timeval); if (!timeval->tv_sec || diff_timeval.tv_sec>0 || diff_timeval.tv_usec>=PROGRESS_UPDATE_USEC) { *timeval=now_timeval; return TRUE; } return FALSE; } static gboolean ui_gnome_progress(GnomeVFSURI *uri) { gboolean want_gdk_flush=FALSE; /* 'uri' may be NULL */ gdk_threads_enter(); if (ProgressEntry) { static gchar *uri_text=NULL; /* Store 'uri' on each call (not just if 'diff_timeval' permits) * as we may get into long cabinet extraction phase with 'uri==NULL' calls * where we want to display the currently processed 'uri'. */ if (uri) { g_free(uri_text); uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD); } if (uri_text) { if (want_progress_update(&ProgressEntry_updated_timeval)) { gtk_entry_set_text(ProgressEntry, uri_text+(strncmp(uri_text,"file://",strlen("file://")) ? 0 : strlen("file://"))); want_gdk_flush=TRUE; } } } #ifndef UI_GNOME_THREADS while (g_main_context_pending(NULL)) g_main_context_iteration( NULL, /* context */ FALSE); /* may_block */ #endif /* UI_GNOME_THREADS */ if (want_gdk_flush) gdk_flush(); gdk_threads_leave(); /* Do not: g_thread_yield(); * as it is TOO much expensive and we are multithreaded anyway. */ if (aborted) return TRUE; if (all_modules_found) return TRUE; return FALSE; } static void ui_gnome_progress_bar(gint done,gint length) { g_return_if_fail(done>=0); g_return_if_fail(length>=0); if (!want_progress_update(&ProgressBar_updated_timeval)) return; gdk_threads_enter(); if (!length) { gtk_progress_bar_pulse(MicrosoftComProgress); gtk_progress_bar_set_text(MicrosoftComProgress,""); } else { gchar *length_display; /* Do not format 'done' by gnome_vfs_format_file_size_for_display() * as the progress would not be visible for large 'done' sizes. */ gtk_progress_bar_set_fraction(MicrosoftComProgress,((gdouble)done)/length); length_display=gnome_vfs_format_file_size_for_display(length); gtk_progress_bar_set_text(MicrosoftComProgress, captive_printf_alloca("%d B / %s",(int)done,length_display)); g_free(length_display); } gdk_flush(); gdk_threads_leave(); } /* FIXME: Change it to "prepare" signal. */ void on_Page_map(GtkWidget *vbox_widget,GtkWidget *page_widget) { /* Handle non-object (NULL) signal with reversed parameters? */ if (GNOME_IS_DRUID_PAGE(vbox_widget) && page_widget==NULL) { page_widget=vbox_widget; vbox_widget=NULL; } g_return_if_fail(vbox_widget==NULL || GTK_IS_VBOX(vbox_widget)); g_return_if_fail(GNOME_IS_DRUID_PAGE(page_widget)); page_active=GNOME_DRUID_PAGE(page_widget); if (page_active==PageFinish) { gnome_druid_set_show_finish(Druid,FALSE); /* set it each time */ /**/ if (!some_modules_found) gnome_druid_page_edge_set_text(GNOME_DRUID_PAGE_EDGE(PageFinish),_( "We need at least some version of drivers essential for this project:" " ntoskrnl.exe and ntfs.sys. Please click 'Back' button to obtain them" " by several methods offered by this installer.")); else { gchar *text; text=final_text(all_modules_found); gnome_druid_page_edge_set_text(GNOME_DRUID_PAGE_EDGE(PageFinish),text); g_free(text); } } if (page_active==ScanPathPage) gtk_widget_grab_focus(GTK_WIDGET(ScanPathLocationComboEntry)); state_changed(); if (!vbox_widget) return; /* FIXME: 'freeze' apparently does not help 'repositioning' of * 'DriversTreeView' during first 'map' of each 'Page'. */ gtk_widget_freeze_child_notify(vbox_widget); gtk_widget_reparent(GTK_WIDGET(DriversFrame),vbox_widget); gtk_widget_reparent(GTK_WIDGET(ProgressFrame),vbox_widget); gtk_box_reorder_child(GTK_BOX(vbox_widget),GTK_WIDGET(DriversFrame), 0); /* position */ gtk_box_set_child_packing(GTK_BOX(vbox_widget),GTK_WIDGET(DriversFrame), FALSE, /* expand */ TRUE, /* fill */ 0, /* padding */ GTK_PACK_START); gtk_box_set_child_packing(GTK_BOX(vbox_widget),GTK_WIDGET(ProgressFrame), FALSE, /* expand */ TRUE, /* fill */ 0, /* padding */ GTK_PACK_START); /* FIXME: Needed to fix (0,0)-position inside parent GdkWindow. */ gtk_widget_queue_resize(GTK_WIDGET(DriversTreeView)); gtk_widget_queue_resize(GTK_WIDGET(ProgressEntry)); gtk_widget_thaw_child_notify(vbox_widget); } typedef void (*process_t)(void); #ifdef UI_GNOME_THREADS /* 'GThreadFunc' type. */ gpointer execute_process_func(process_t process /* data */) { (*process)(); gdk_threads_enter(); gtk_main_quit(); /* Abort gtk_main() of execute_process(). */ gdk_flush(); gdk_threads_leave(); return NULL; } #endif /* UI_GNOME_THREADS */ /* We are called inside gdk_threads_enter(). */ static void execute_process(process_t process) { #ifdef UI_GNOME_THREADS GThread *gthread; #endif /* UI_GNOME_THREADS */ progress_start(); #ifdef UI_GNOME_THREADS gthread=g_thread_create_full( (GThreadFunc)execute_process_func, /* func */ process, /* data */ 0, /* stack_size; 0 means the default size */ TRUE, /* joinable */ TRUE, /* bound; use system thread */ G_THREAD_PRIORITY_LOW, /* priority; G_THREAD_PRIORITY_LOW is the lowest one */ NULL); /* error */ gtk_main(); /* We are already called inside gdk_threads_enter(). */ /* I hope some other gtk_main_quit() did not occur as we would * locked if the 'process' func did not finish yet. */ g_thread_join(gthread); #else /* UI_GNOME_THREADS */ (*process)(); #endif /* UI_GNOME_THREADS */ progress_end(); } /* 'process_t' typed. */ static void process_scan_disk(void) { scan_disks_quick(); scan_disks(); } static GnomeVFSURI *process_scan_path_scan_path_uri; /* 'process_t' typed. */ static void process_scan_path(void) { mod_uri_load_base_reporting(process_scan_path_scan_path_uri); } /* 'process_t' typed. */ static void process_microsoft_com(void) { microsoft_com(); } gboolean on_Page_next(GnomeDruidPage *gnomedruidpage,GtkWidget *widget,gpointer user_data /* unused */) { g_return_val_if_fail(GNOME_IS_DRUID_PAGE(gnomedruidpage),FALSE); if (in_progress) /* bogus callback - we should be non-sensitive */ return TRUE; /* ignore button press */ /**/ if (page_active==PageStart) { if (all_modules_found) { gnome_druid_set_page(Druid,PageFinish); return TRUE; /* ignore button press */ } } else if (page_active==ScanDiskPage) { execute_process(process_scan_disk); if (aborted_back) { gnome_druid_set_page(Druid,PageStart); return TRUE; /* ignore button press */ } if (all_modules_found) { gnome_druid_set_page(Druid,PageFinish); return TRUE; /* ignore button press */ } return FALSE; /* proceed to next page */ } else if (page_active==ScanPathPage) { const gchar *scan_path_uri_text=gtk_entry_get_text(ScanPathLocationComboEntry); if (scan_path_uri_text && *scan_path_uri_text) { GnomeVFSURI *scan_path_uri; if ((scan_path_uri=gnome_vfs_uri_new(scan_path_uri_text))) { process_scan_path_scan_path_uri=scan_path_uri; execute_process(process_scan_path); gnome_vfs_uri_unref(scan_path_uri); if (aborted_back) { gnome_druid_set_page(Druid,(all_modules_found ? PageStart : ScanDiskPage)); return TRUE; /* ignore button press */ } if (all_modules_found) { gnome_druid_set_page(Druid,PageFinish); return TRUE; /* ignore button press */ } gtk_entry_set_text(ScanPathLocationComboEntry,""); } else g_warning(_("Invalid URI: %s"),scan_path_uri_text); gtk_widget_grab_focus(GTK_WIDGET(ScanPathLocationComboEntry)); return TRUE; /* ignore button press; we cleared the URI entry */ } return FALSE; /* proceed to next page */ } return FALSE; /* proceed to next page */ } void on_MicrosoftComConfirmButton_clicked(GtkButton *button,gpointer user_data) { g_return_if_fail(GTK_IS_BUTTON(button)); if (in_progress) /* bogus callback */ return; if (page_active!=MicrosoftComPage) /* bogus callback */ return; execute_process(process_microsoft_com); if (aborted_back) { gnome_druid_set_page(Druid,(all_modules_found ? PageStart : ScanPathPage)); return; } if (all_modules_found) { gnome_druid_set_page(Druid,PageFinish); return; } gnome_druid_set_page(Druid,PageFinish); } void on_DruidButtonSkip_clicked(GtkButton *button,gpointer user_data /* unused */) { g_return_if_fail(GTK_IS_BUTTON(button)); if (in_progress) { aborted=TRUE; state_changed(); return; } if (all_modules_found) gnome_druid_set_page(Druid,PageFinish); else if (page_active==ScanDiskPage) gnome_druid_set_page(Druid,ScanPathPage); else if (page_active==ScanPathPage) gnome_druid_set_page(Druid,MicrosoftComPage); else if (page_active==MicrosoftComPage) gnome_druid_set_page(Druid,PageFinish); } gboolean on_Page_back(GnomeDruidPage *gnomedruidpage,GtkWidget *widget,gpointer user_data) { g_return_val_if_fail(GNOME_IS_DRUID_PAGE(gnomedruidpage),FALSE); if (!in_progress) { if (all_modules_found) { gnome_druid_set_page(Druid,PageStart); return TRUE; /* ignore button press */ } return FALSE; /* proceed to previous page */ } aborted=TRUE; aborted_back=TRUE; state_changed(); return TRUE; /* ignore button press now; we will respect 'aborted_back' */ } void on_Druid_cancel(GnomeDruid *gnomedruid,gpointer user_data /* unused */) { g_return_if_fail(GNOME_IS_DRUID(gnomedruid)); /* gtk_main_quit() would not abort the current operation. */ exit(EXIT_SUCCESS); } static void on_DruidButtonOK_clicked_dialog_callback(gint reply,gint *replyp /* data */) { g_return_if_fail(reply>=0); g_return_if_fail(replyp!=NULL); *replyp=reply; } void on_DruidButtonOK_clicked(GtkButton *button,gpointer user_data /* unused */) { GtkWidget *dialog; gint reply; g_return_if_fail(GTK_IS_BUTTON(button)); if (all_modules_found) exit(EXIT_SUCCESS); /* TODO: Avoid dialog if already on Finish page. */ reply=-1; dialog=gnome_app_ok_cancel_modal(App,_( "Although essential modules (\"ntoskrnl.exe\" and \"ntfs.sys\") are available " "you may still want to get their better version and/or more modules. " "Really quit?"), (GnomeReplyCallback)on_DruidButtonOK_clicked_dialog_callback, &reply); /* data */ g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL); /* Never call gtk_main() from other thread than the initial one. * We would have to switch GTK+ context (g_main_context()?). */ gtk_main(); /* 'dialog' gets destroyed automatically */ if (reply==0) /* 0 for 'OK', 1 for 'Cancel', left -1 for dialog close. */ exit(EXIT_SUCCESS); } static void button_stock_set_label(GtkWidget *widget,const gchar *label_text_new /* callback_data */) { g_return_if_fail(GTK_IS_WIDGET(widget)); g_return_if_fail(label_text_new!=NULL); /**/ if (GTK_IS_CONTAINER(widget)) gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)button_stock_set_label, /* callback */ (/* de-conts */ gchar *)label_text_new); /* callback_data */ else if (GTK_IS_LABEL(widget)) gtk_label_set_text_with_mnemonic(GTK_LABEL(widget),label_text_new); } static void PageFinish_set_label_attr(GtkWidget *widget,gpointer callback_data /* unused */) { g_return_if_fail(GTK_IS_WIDGET(widget)); /**/ if (GTK_IS_CONTAINER(widget)) gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)PageFinish_set_label_attr, /* callback */ callback_data); /* callback_data; unused */ else if (GTK_IS_LABEL(widget) && gtk_label_get_line_wrap(GTK_LABEL(widget))) gtk_label_set_selectable(GTK_LABEL(widget),TRUE); } /* of "ui-gnome-interface.h": */ GtkWidget *create_App(void); /* of "ui-gnome-support.h": */ GtkWidget *lookup_widget(GtkWidget *widget,const gchar *widget_name); static void App_init(void) { GtkTreeViewColumn *column; GtkCellRenderer *cell; GtkBox *druid_button_box; gdk_threads_enter(); App=GNOME_APP(create_App()); DriversTreeView=GTK_TREE_VIEW(lookup_widget(GTK_WIDGET(App),"DriversTreeView")); DriversFrame=GTK_FRAME(lookup_widget(GTK_WIDGET(App),"DriversFrame")); ProgressFrame=GTK_FRAME(lookup_widget(GTK_WIDGET(App),"ProgressFrame")); Druid=GNOME_DRUID(lookup_widget(GTK_WIDGET(App),"Druid")); PageStart=GNOME_DRUID_PAGE(lookup_widget(GTK_WIDGET(App),"PageStart")); ScanDiskPage=GNOME_DRUID_PAGE(lookup_widget(GTK_WIDGET(App),"ScanDiskPage")); ScanPathPage=GNOME_DRUID_PAGE(lookup_widget(GTK_WIDGET(App),"ScanPathPage")); MicrosoftComPage=GNOME_DRUID_PAGE(lookup_widget(GTK_WIDGET(App),"MicrosoftComPage")); PageFinish=GNOME_DRUID_PAGE(lookup_widget(GTK_WIDGET(App),"PageFinish")); ScanPathLocationComboEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"ScanPathLocationComboEntry")); MicrosoftComConfirmButton=GTK_BUTTON(lookup_widget(GTK_WIDGET(App),"MicrosoftComConfirmButton")); MicrosoftComProgress=GTK_PROGRESS_BAR(lookup_widget(GTK_WIDGET(App),"MicrosoftComProgress")); ProgressEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"ProgressEntry")); druid_button_box=GTK_BOX(gtk_widget_get_parent(Druid->next)); DriversTreeStore=gtk_tree_store_new(DRIVERS_TREE_STORE_COLUMN_NUM,DRIVERS_TREE_STORE_COLUMN_TYPE_LIST); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(DriversTreeStore), DRIVERS_TREE_STORE_COLUMN_TYPE,GTK_SORT_ASCENDING); gtk_tree_view_set_model(DriversTreeView,GTK_TREE_MODEL(DriversTreeStore)); column=gtk_tree_view_column_new(); cell=gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column,cell, TRUE); /* expand */ gtk_tree_view_column_set_attributes(column,cell, "text",DRIVERS_TREE_STORE_COLUMN_TYPE, NULL); gtk_tree_view_append_column(DriversTreeView,column); column=gtk_tree_view_column_new(); cell=gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column,cell, TRUE); /* expand */ gtk_tree_view_column_set_attributes(column,cell, "text",DRIVERS_TREE_STORE_COLUMN_ID, NULL); gtk_tree_view_append_column(DriversTreeView,column); /* gnome_druid_set_show_finish() just replaces Next<->Finish buttons displayed. */ gtk_widget_hide(GTK_WIDGET(Druid->finish)); DruidButtonSkip=GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_REDO)); button_stock_set_label( GTK_WIDGET(DruidButtonSkip), /* widget */ _("_Skip")); /* label_text_new */ gtk_box_pack_end(druid_button_box,GTK_WIDGET(DruidButtonSkip),FALSE,TRUE,0); gtk_widget_show(GTK_WIDGET(DruidButtonSkip)); g_signal_connect((gpointer)DruidButtonSkip,"clicked",G_CALLBACK(on_DruidButtonSkip_clicked),NULL); DruidButtonOK=GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_OK)); gtk_box_pack_end(druid_button_box,GTK_WIDGET(DruidButtonOK),FALSE,TRUE,0); gtk_widget_show(GTK_WIDGET(DruidButtonOK)); g_signal_connect((gpointer)DruidButtonOK,"clicked",G_CALLBACK(on_DruidButtonOK_clicked),NULL); PageFinish_set_label_attr( GTK_WIDGET(PageFinish), /* widget */ NULL); /* callback_data; unused */ state_changed(); gdk_threads_leave(); } static void ui_gnome_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data) { GtkWidget *dialog; /* Ignore arrors by cabextract during its abortion. */ if (in_progress && aborted) return; gdk_threads_enter(); /**/ if (log_level & G_LOG_LEVEL_ERROR) dialog=gnome_app_error(App,message); else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING)) dialog=gnome_app_warning(App,message); else dialog=gnome_app_message(App,message); gtk_window_set_modal(GTK_WINDOW(dialog),TRUE); g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL); gtk_main(); /* 'dialog' gets destroyed automatically */ gdk_flush(); gdk_threads_leave(); } static void ui_gnome_interactive(void) { gdk_threads_enter(); /* Postpone gtk_widget_show_all() from App_init() here * to have already passed all ui_gnome_module_available_notify(). */ gnome_druid_set_page(Druid,MicrosoftComPage); gtk_widget_show_all(GTK_WIDGET(App)); #if 0 /* gnome_druid_set_page(Druid,PageStart); */ gnome_druid_set_page(Druid,ScanDiskPage); gnome_druid_set_page(Druid,ScanPathPage); /* gnome_druid_set_page(Druid,MicrosoftComPage); */ gnome_druid_set_page(Druid,PageFinish); #endif gnome_druid_set_page(Druid,PageStart); gtk_main(); gdk_threads_leave(); exit(EXIT_SUCCESS); } gboolean ui_gnome_init(void) { acquire_module_available_notify=ui_gnome_module_available_notify; acquire_module_all_modules_found_notify=ui_gnome_all_modules_found_notify; ui_progress=ui_gnome_progress; ui_progress_bar=ui_gnome_progress_bar; ui_interactive=ui_gnome_interactive; captivemodid_module_best_priority_notify=ui_gnome_module_best_priority_notify; #ifdef UI_GNOME_THREADS /* gdk_threads_init() must be called before gtk_init()! * gtk_init() gets called by create_App() here. */ if (!g_thread_supported()) g_thread_init(NULL); if (!gdk_threads_mutex) gdk_threads_init(); #endif /* UI_GNOME_THREADS */ /* Graphic widgets will all be hidden yet. */ App_init(); /* ui_gnome_g_log_handler() needs 'App'. */ g_log_set_handler( G_LOG_DOMAIN, /* log_domain; "Captive" */ G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL, /* log_levels */ ui_gnome_g_log_handler, /* log_func */ NULL); /* user_data */ return TRUE; }