heraia_ui.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   heraia_ui.c
00004   main menus, callback and utility functions
00005 
00006   (C) Copyright 2005 - 2010 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009 
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option)
00013   any later version.
00014 
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019 
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023 */
00024 /** @file heraia_ui.c
00025  * This file has all the functions to manage heraia's ui
00026  * - signals definitions and functions
00027  * - widgets activations
00028  * - closing / openning windows
00029  */
00030 
00031 #include <libheraia.h>
00032 
00033 static void set_a_propos_properties(GtkWidget *about_dialog);
00034 static gboolean load_heraia_xml(heraia_struct_t *main_struct);
00035 static void heraia_ui_connect_signals(heraia_struct_t *main_struct);
00036 static void record_and_hide_about_box(heraia_struct_t *main_struct);
00037 static gboolean unsaved_documents(heraia_struct_t *main_struct);
00038 static gboolean close_heraia(heraia_struct_t *main_struct);
00039 static GtkWidget *create_tab_close_button(heraia_struct_t *main_struct, GtkWidget *tab_label);
00040 static GtkWidget *find_label_from_hbox(GtkWidget *hbox);
00041 
00042 /**
00043  * @fn void on_quit_activate(GtkWidget *widget, gpointer data)
00044  *  Quit, file menu
00045  * @param widget : the widget that issued the signal
00046  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00047  */
00048 void on_quit_activate(GtkWidget *widget, gpointer data)
00049 {
00050     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00051     gboolean quit_heraia = FALSE;
00052 
00053     quit_heraia = close_heraia(main_struct);
00054 
00055     if (quit_heraia == TRUE)
00056         {
00057             gtk_main_quit();
00058         }
00059 }
00060 
00061 
00062 /**
00063  * @fn void on_new_activate(GtkWidget *widget, gpointer data)
00064  *  New, file menu
00065  * @param widget : the widget that issued the signal
00066  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00067  */
00068 void on_new_activate(GtkWidget *widget, gpointer data)
00069 {
00070     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00071 
00072     log_message(main_struct, G_LOG_LEVEL_WARNING, Q_("Not implemented Yet (Please contribute !)"));
00073 }
00074 
00075 
00076 /**
00077  * @fn void on_preferences_activate(GtkWidget *widget, gpointer data)
00078  *  Preferences, file menu :
00079  *  Displays the preference window (as a modal window)
00080  * @param widget : the widget that issued the signal
00081  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00082  */
00083 void on_preferences_activate(GtkWidget *widget, gpointer data)
00084 {
00085     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00086     GtkWidget *pref_window = NULL;
00087 
00088     pref_window = heraia_get_widget(main_struct->xmls->main, "main_preferences_window");
00089 
00090     if (pref_window != NULL)
00091         {
00092             move_and_show_dialog_box(pref_window, main_struct->win_prop->main_pref_window);
00093         }
00094 
00095 }
00096 
00097 
00098 /**
00099  * @fn void set_a_propos_properties(GtkWidget *about_dialog)
00100  * Sets name and version in the dialog box
00101  * @param about_dialog the widget that contain all the about box
00102  */
00103 static void set_a_propos_properties(GtkWidget *about_dialog)
00104 {
00105 
00106     if (about_dialog != NULL)
00107         {
00108             if (GTK_MINOR_VERSION >= 12)
00109                 {
00110                     gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about_dialog), PACKAGE_NAME);
00111                 }
00112             if (GTK_MINOR_VERSION >= 6)
00113                 {
00114                     gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_dialog), PACKAGE_VERSION);
00115                 }
00116         }
00117 }
00118 
00119 
00120 /**
00121  * @fn void a_propos_activate(GtkWidget *widget, gpointer data)
00122  *  Shows apropos's dialog box
00123  * @param widget : the widget that issued the signal
00124  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00125  */
00126 void a_propos_activate(GtkWidget *widget, gpointer data)
00127 {
00128     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00129     GtkWidget *about_dialog = NULL;
00130 
00131     about_dialog = heraia_get_widget(main_struct->xmls->main, "about_dialog");
00132 
00133     if (about_dialog != NULL)
00134         {
00135             set_a_propos_properties(about_dialog);
00136             move_and_show_dialog_box(about_dialog, main_struct->win_prop->about_box);
00137         }
00138 }
00139 
00140 
00141 /**
00142  * @fn void move_and_show_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00143  *  Move the dialog box to the wanted position, shows it and says it in the displayed prop
00144  * @param dialog_box : the dialog box we want to move and show
00145  * @param dialog_prop : window_prop_t properties structure corresponding to the dialog box
00146  */
00147 void move_and_show_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00148 {
00149     if (dialog_prop != NULL)
00150         {
00151 
00152             if (dialog_prop->displayed == FALSE)
00153                 {
00154                     if (dialog_prop->x > 0 && dialog_prop->y > 0)
00155                         {
00156                             gtk_window_move(GTK_WINDOW(dialog_box), dialog_prop->x, dialog_prop->y);
00157                         }
00158 
00159                     if (dialog_prop->width > 0 && dialog_prop->height > 0)
00160                         {
00161                             gtk_window_resize(GTK_WINDOW(dialog_box), dialog_prop->width, dialog_prop->height);
00162                         }
00163 
00164                     gtk_widget_show_all(dialog_box);
00165                     dialog_prop->displayed = TRUE;
00166                 }
00167         }
00168 }
00169 
00170 
00171 /**
00172  * @fn void record_dialog_box_position(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00173  * Records one dialog position
00174  * @param dialog_box : a dialog box from which we want to record the position
00175  * @param[in,out] dialog_prop : window_prop_t properties structure corresponding to the dialog box
00176  */
00177 void record_dialog_box_position(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00178 {
00179     gint x = 0;
00180     gint y = 0;
00181     gint width = WPT_DEFAULT_WIDTH;
00182     gint height = WPT_DEFAULT_HEIGHT;
00183 
00184     if (dialog_prop != NULL && dialog_prop->displayed == TRUE)
00185         {
00186             if (dialog_box != NULL)
00187                 {
00188                     gtk_window_get_position(GTK_WINDOW(dialog_box), &x, &y);
00189                     gtk_window_get_size(GTK_WINDOW(dialog_box), &width, &height);
00190                     dialog_prop->x = x;
00191                     dialog_prop->y = y;
00192                     dialog_prop->width = width;
00193                     dialog_prop->height = height;
00194                 }
00195         }
00196 }
00197 
00198 
00199 /**
00200  * @fn void record_all_dialog_box_positions(heraia_struct_t *main_struct)
00201  * Records all the positions of the displayed windows
00202  * @param[in,out] main_struct : main structure
00203  */
00204 void record_all_dialog_box_positions(heraia_struct_t *main_struct)
00205 {
00206     GtkWidget *dialog_box = NULL;
00207 
00208     if (main_struct != NULL &&
00209         main_struct->xmls != NULL &&
00210         main_struct->xmls->main != NULL &&
00211         main_struct->win_prop != NULL &&
00212         main_struct->current_DW != NULL)
00213         {
00214             /* data interpretor */
00215             dialog_box = main_struct->current_DW->diw;
00216             record_dialog_box_position(dialog_box, main_struct->win_prop->data_interpretor);
00217 
00218             /* About box */
00219             dialog_box = heraia_get_widget (main_struct->xmls->main, "about_dialog");
00220             record_dialog_box_position(dialog_box, main_struct->win_prop->about_box);
00221 
00222             /* Log window */
00223             dialog_box = heraia_get_widget (main_struct->xmls->main, "log_window");
00224             record_dialog_box_position(dialog_box, main_struct->win_prop->log_box);
00225 
00226             /* main_dialog */
00227             dialog_box = heraia_get_widget (main_struct->xmls->main, "main_window");
00228             record_dialog_box_position(dialog_box, main_struct->win_prop->main_dialog);
00229 
00230             /* plugin_list */
00231             dialog_box = heraia_get_widget (main_struct->xmls->main, "plugin_list_window");
00232             record_dialog_box_position(dialog_box, main_struct->win_prop->plugin_list);
00233 
00234             /* list data types */
00235             dialog_box = heraia_get_widget (main_struct->xmls->main, "list_data_types_window");
00236             record_dialog_box_position(dialog_box, main_struct->win_prop->ldt);
00237 
00238             /* main_preferences */
00239             dialog_box = heraia_get_widget (main_struct->xmls->main, "main_preferences_window");
00240             record_dialog_box_position(dialog_box, main_struct->win_prop->main_pref_window);
00241         }
00242 }
00243 
00244 
00245 /**
00246  * @fn void record_and_hide_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00247  *  Record position and hide a dialog box
00248  * @param dialog_box : the dialog box we want to record its position and then hide
00249  * @param dialog_prop : window_prop_t properties structure corresponding to the dialog box
00250  */
00251 void record_and_hide_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00252 {
00253 
00254     if (dialog_prop->displayed == TRUE)
00255         {
00256             record_dialog_box_position(dialog_box, dialog_prop);
00257 
00258             gtk_widget_hide(dialog_box);
00259             dialog_prop->displayed = FALSE;
00260         }
00261 }
00262 
00263 
00264 /**
00265  * @fn static void record_and_hide_about_box(heraia_struct_t *main_struct)
00266  *  Record position and hide about dialog box
00267  * @param [in,out] main_struct : main structure
00268  */
00269 static void record_and_hide_about_box(heraia_struct_t *main_struct)
00270 {
00271     GtkWidget *about_dialog = NULL;
00272 
00273     about_dialog = heraia_get_widget(main_struct->xmls->main, "about_dialog");
00274 
00275     if (about_dialog != NULL)
00276         {
00277             record_and_hide_dialog_box(about_dialog, main_struct->win_prop->about_box);
00278         }
00279 }
00280 
00281 
00282 /**
00283  * @fn void a_propos_response(GtkWidget *widget, gint response, gpointer data)
00284  *  To close the A propos dialog box (with the "close" button)
00285  * @param widget : calling widget (may be NULL as we don't use this)
00286  * @param response : may be whatever you want as we neither use this !
00287  * @param data : MUST be heraia_struct_t *main_struct main structure
00288  */
00289 static void a_propos_response(GtkWidget *widget, gint response, gpointer data)
00290 {
00291     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00292     record_and_hide_about_box(main_struct);
00293 }
00294 
00295 
00296 /**
00297  * @fn void a_propos_close(GtkWidget *widget, gpointer data)
00298  *  To close the A propos dialog box
00299  * @param widget : calling widget (may be NULL as we don't use this)
00300  * @param data : MUST be heraia_struct_t *main_struct main structure
00301  */
00302 static void a_propos_close(GtkWidget *widget, gpointer data)
00303 {
00304     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00305     record_and_hide_about_box(main_struct);
00306 }
00307 
00308 
00309 /**
00310  * @fn gboolean a_propos_delete(GtkWidget *widget, GdkEvent  *event, gpointer data)
00311  *  To close the A propos dialog box
00312  * @param widget : calling widget (may be NULL as we don't use this)
00313  * @param event : event associated (may be NULL as we don't use this)
00314  * @param data : MUST be heraia_struct_t *main_struct main structure
00315  * @return returns TRUE in order to allow other functions to do something with
00316  *         that event.
00317  */
00318 static gboolean a_propos_delete(GtkWidget *widget, GdkEvent  *event, gpointer data)
00319 {
00320     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00321     record_and_hide_about_box(main_struct);
00322 
00323     return TRUE;
00324 }
00325 
00326 
00327 /**
00328  *  Undo, edit menu
00329  * @param widget : the widget that issued the signal
00330  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00331  */
00332 void on_undo_activate(GtkWidget *widget, gpointer data)
00333 {
00334     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00335     GtkBuilder *xml = NULL;
00336     gboolean result = FALSE;
00337 
00338     if (main_struct != NULL && main_struct->current_doc != NULL && main_struct->xmls->main != NULL)
00339         {
00340             result = hex_document_undo(main_struct->current_doc->hex_doc);
00341 
00342             xml = main_struct->xmls->main;
00343 
00344             if (result == TRUE)
00345                 {
00346                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_redo"), TRUE);
00347                 }
00348 
00349             if (main_struct->current_doc->hex_doc->undo_top == NULL)
00350                 {   /* No more undos are possible. The document is as the origin ! */
00351                     set_notebook_tab_label_color(main_struct, FALSE);
00352                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_undo"), FALSE);
00353                     main_struct->current_doc->modified = FALSE;
00354                 }
00355             else
00356                 {
00357                     set_notebook_tab_label_color(main_struct, TRUE);
00358                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_undo"), TRUE);
00359                 }
00360 
00361         }
00362 
00363 }
00364 
00365 
00366 /**
00367  *  Redo, edit menu
00368  * @param widget : the widget that issued the signal
00369  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00370  */
00371 void on_redo_activate(GtkWidget *widget, gpointer data)
00372 {
00373     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00374     GtkBuilder *xml = NULL;
00375     gboolean result = FALSE;
00376 
00377     if (main_struct != NULL && main_struct->current_doc != NULL && main_struct->xmls->main != NULL)
00378         {
00379             result = hex_document_redo(main_struct->current_doc->hex_doc);
00380 
00381             xml = main_struct->xmls->main;
00382 
00383             if (result == TRUE)
00384                 {
00385                     set_notebook_tab_label_color(main_struct, TRUE);
00386                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_undo"), TRUE);
00387                     main_struct->current_doc->modified = TRUE;
00388                 }
00389 
00390             if (main_struct->current_doc->hex_doc->undo_stack == NULL || main_struct->current_doc->hex_doc->undo_stack == main_struct->current_doc->hex_doc->undo_top)
00391                 {
00392                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_redo"), FALSE);
00393                 }
00394             else
00395                 {
00396                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_redo"), TRUE);
00397                 }
00398         }
00399 }
00400 
00401 
00402 /**
00403  *  Delete, edit menu
00404  * @warning Not yet implemented
00405  * @todo Write a usefull function here :)
00406  * @param widget : the widget that issued the signal
00407  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00408  */
00409 void on_delete_activate(GtkWidget *widget, gpointer data)
00410 {
00411     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00412 
00413     if (main_struct != NULL && main_struct->current_doc != NULL)
00414         {
00415             gtk_hex_delete_selection(GTK_HEX(main_struct->current_doc->hex_widget));
00416             refresh_event_handler(widget, data);
00417         }
00418 }
00419 
00420 
00421 /**
00422  *  Cut, edit menu
00423  * @warning Not yet implemented
00424  * @todo Write a usefull function here :)
00425  * @param widget : the widget that issued the signal
00426  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00427  */
00428 void on_cut_activate(GtkWidget *widget, gpointer data)
00429 {
00430     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00431 
00432     if (main_struct != NULL && main_struct->current_doc != NULL)
00433         {
00434             gtk_hex_cut_to_clipboard(GTK_HEX(main_struct->current_doc->hex_widget));
00435             refresh_event_handler(widget, data);
00436         }
00437 }
00438 
00439 
00440 /**
00441  *  Copy, edit menu
00442  * @warning Not yet implemented
00443  * @todo Write a usefull function here :)
00444  * @param widget : the widget that issued the signal
00445  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00446  */
00447 void on_copy_activate(GtkWidget *widget, gpointer data)
00448 {
00449     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00450 
00451     if (main_struct != NULL && main_struct->current_doc != NULL)
00452         {
00453             gtk_hex_copy_to_clipboard(GTK_HEX(main_struct->current_doc->hex_widget));
00454         }
00455 }
00456 
00457 
00458 /**
00459  *  Paste, edit menu
00460  * @warning Not yet implemented
00461  * @todo Write a usefull function here :)
00462  * @param widget : the widget that issued the signal
00463  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00464  */
00465 void on_paste_activate(GtkWidget *widget, gpointer data)
00466 {
00467     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00468 
00469     if (main_struct != NULL && main_struct->current_doc != NULL)
00470         {
00471             gtk_hex_paste_from_clipboard(GTK_HEX(main_struct->current_doc->hex_widget));
00472             refresh_event_handler(widget, data);
00473         }
00474 }
00475 
00476 
00477 /**
00478  *  This function is refreshing the labels on the main
00479  *  window in order to reflect cursor position, selected
00480  *  positions and total selected size.
00481  *  It is also used to refresh the file label on the tab.
00482  * @param main_struct : main structure
00483  */
00484 void refresh_file_labels(heraia_struct_t *main_struct)
00485 {
00486     GtkWidget *position_label = NULL;
00487     GtkWidget *file_size_label = NULL;
00488     GtkWidget *file_sel_label = NULL;
00489     GtkWidget *file_sel_size_label = NULL;
00490     guint64 position = 0;
00491     guint64 file_size = 0;
00492     selection_t *sel = NULL;
00493     gchar *position_text = NULL;
00494     gchar *file_size_text = NULL;
00495     gchar *file_sel_text = NULL;
00496     gchar *file_sel_size_text = NULL;
00497 
00498     if (main_struct != NULL)
00499         {
00500             position_label = heraia_get_widget(main_struct->xmls->main, "file_position_label");
00501             file_size_label = heraia_get_widget(main_struct->xmls->main, "file_size_label");
00502             file_sel_label = heraia_get_widget(main_struct->xmls->main, "file_selection_label");
00503             file_sel_size_label = heraia_get_widget(main_struct->xmls->main, "file_selection_size_label");
00504 
00505             if (main_struct->current_doc != NULL && main_struct->current_doc->hex_widget != NULL)
00506                 {
00507                     position = ghex_get_cursor_position(main_struct->current_doc->hex_widget);
00508                     file_size = ghex_file_size((Heraia_Hex *) main_struct->current_doc->hex_widget);
00509                     sel = ghex_get_selection(main_struct->current_doc->hex_widget);
00510 
00511                     /* position begins at 0 and this is not really human readable */
00512                     /* it's more confusing than anything so we do + 1             */
00513                     /* To translators : do not translate <small> and such         */
00514                     if (is_toggle_button_activated(main_struct->xmls->main, "mp_thousand_bt") == TRUE)
00515                         {
00516                             position_text = g_strdup_printf("<small>%'lu</small>", position + 1);
00517                             file_size_text = g_strdup_printf("<small>%'lu</small>", file_size);
00518                             file_sel_text = g_strdup_printf("<small>%'lu -> %'lu</small>", sel->start + 1, sel->end + 1);
00519                             file_sel_size_text = g_strdup_printf("<small>%'li</small>", (sel->end - sel->start) + 1);
00520                         }
00521                     else
00522                         {
00523                             position_text = g_strdup_printf("<small>%lu</small>", position + 1);
00524                             file_size_text = g_strdup_printf("<small>%lu</small>", file_size);
00525                             file_sel_text = g_strdup_printf("<small>%lu - %lu</small>", sel->start + 1, sel->end + 1);
00526                             file_sel_size_text = g_strdup_printf("<small>%li</small>", (sel->end - sel->start) + 1);
00527                         }
00528 
00529                     gtk_label_set_markup(GTK_LABEL(position_label), position_text);
00530                     gtk_label_set_markup(GTK_LABEL(file_size_label), file_size_text);
00531                     gtk_label_set_markup(GTK_LABEL(file_sel_label), file_sel_text);
00532                     gtk_label_set_markup(GTK_LABEL(file_sel_size_label), file_sel_size_text);
00533 
00534                     g_free(position_text);
00535                     g_free(file_size_text);
00536                     g_free(file_sel_text);
00537                     g_free(file_sel_size_text);
00538                     g_free(sel);
00539 
00540                     /* refreshing the tab filename itself if necessary only ! */
00541                     if (main_struct->current_doc->modified != main_struct->current_doc->hex_doc->changed)
00542                         {
00543                             main_struct->current_doc->modified = main_struct->current_doc->hex_doc->changed;
00544                             set_notebook_tab_label_color(main_struct, main_struct->current_doc->hex_doc->changed);
00545 
00546                             /* If the document changes, then when might undo things ... */
00547                             gtk_widget_set_sensitive(heraia_get_widget(main_struct->xmls->main, "menu_undo"), TRUE);
00548 
00549                         }
00550 
00551                 }
00552             else
00553                 {
00554                     gtk_label_set_text(GTK_LABEL(position_label), "");
00555                     gtk_label_set_text(GTK_LABEL(file_size_label), "");
00556                     gtk_label_set_text(GTK_LABEL(file_sel_label), "");
00557                     gtk_label_set_text(GTK_LABEL(file_sel_size_label), "");
00558                 }
00559         }
00560 }
00561 
00562 
00563 /**
00564  *  This function is here to ensure that everything will be
00565  *  refreshed upon a signal event.
00566  * @warning This function is not thread safe (do not use in a thread)
00567  * @todo try to put some mutexes on main_struct->event to make this
00568  *       thread safe some way
00569  * @param widget : the widget that issued the signal
00570  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00571  */
00572 void refresh_event_handler(GtkWidget *widget, gpointer data)
00573 {
00574     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00575 
00576     if (main_struct != NULL)
00577         {
00578             /* Beware, this mechanism is not thread safe ! */
00579             if (main_struct->event == HERAIA_REFRESH_NOTHING)
00580                 {
00581                     main_struct->event = HERAIA_REFRESH_CURSOR_MOVE;
00582                 }
00583 
00584             refresh_data_interpretor_window(widget, main_struct);
00585             refresh_all_plugins(main_struct);
00586             refresh_file_labels(main_struct);
00587 
00588             main_struct->event = HERAIA_REFRESH_NOTHING;
00589         }
00590 }
00591 
00592 
00593 /**
00594  *  This handles the menuitem "Ouvrir" to open a file
00595  * @warning This function is not thread safe (do not use in a thread)
00596  * @todo try to put some mutexes on main_struct->event to make this
00597  *       thread safe some way
00598  * @param widget : the widget that issued the signal
00599  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00600  */
00601 void on_open_activate(GtkWidget *widget, gpointer data)
00602 {
00603     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00604     GSList *list = NULL;
00605     GSList *head = NULL;
00606     gboolean success = FALSE;
00607 
00608     list = select_file_to_load(main_struct);
00609 
00610     if (list != NULL)
00611         {
00612             head = list;
00613             while (list != NULL)
00614                 {
00615                     success = load_file_to_analyse(main_struct, list->data);
00616                     g_free(list->data);
00617                     list = g_slist_next(list);
00618                 }
00619 
00620             g_slist_free(head);
00621 
00622             if (success == TRUE && main_struct->current_doc != NULL)
00623                  {
00624                     /* Not thread safe here ? */
00625                     main_struct->event = HERAIA_REFRESH_NEW_FILE;
00626                     refresh_event_handler(main_struct->current_doc->hex_widget, main_struct);
00627                  }
00628         }
00629 }
00630 
00631 
00632 /**
00633  * Searches main notebook's tabs for a particular widget and returns the number
00634  * of the corresponding tab if it exists, -1 otherwise
00635  * @param main_struct : main structure
00636  * @param to_find : a GtkWidget that we want to find in the main notebook tabs
00637  * @return a gint as tha tab number that contains the widget "to_find" or -1 if
00638  *         not found
00639  */
00640 gint find_tab_number_from_widget(heraia_struct_t *main_struct, GtkWidget *to_find)
00641 {
00642     GtkWidget *notebook = NULL;  /**< Notenook on the main window         */
00643     GtkWidget *page = NULL;      /**< pages on the notebook               */
00644     GtkWidget *tab_label = NULL; /**< tab label GtkWidget (hbox + others) */
00645     gint nb_pages = 0;           /**< Number of pages in the notebook     */
00646     gint i = 0;
00647     gboolean found = FALSE;      /**< True when the widget has been found */
00648     GList *children = NULL;      /**< Children from the tab label         */
00649 
00650     notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
00651 
00652     nb_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
00653 
00654     i = 0;
00655     found = FALSE;
00656     while (i < nb_pages && found == FALSE)
00657         {
00658             page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
00659 
00660             if (page != NULL)
00661                 {
00662                     tab_label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
00663 
00664                     if (GTK_IS_HBOX(tab_label))
00665                         {
00666                             children = gtk_container_get_children(GTK_CONTAINER(tab_label));
00667                         }
00668 
00669                     while (children != NULL && found == FALSE)
00670                         {
00671                             if (children->data == to_find)
00672                                 {
00673                                     found = TRUE;
00674                                 }
00675                             else
00676                                 {
00677                                     children = g_list_next(children);
00678                                 }
00679                         }
00680                 }
00681 
00682             if (found == FALSE)
00683                 {
00684                     i++;
00685                 }
00686         }
00687 
00688     if (found == TRUE)
00689         {
00690             return i;
00691         }
00692     else
00693         {
00694             return -1;
00695         }
00696 }
00697 
00698 
00699 /**
00700  * Closes an openned file
00701  * @param widget : the widget that issued the signal
00702  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00703  */
00704 void on_close_activate(GtkWidget *widget, gpointer data)
00705 {
00706     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00707     doc_t * closing_doc = NULL;  /**< Current document to close in heraia    */
00708     doc_t *document = NULL;      /**< To iterate over the array of documents */
00709     GtkWidget *notebook = NULL;  /**< Notenook on the main window            */
00710     GtkWidget *dialog = NULL;    /**< The dialog box                         */
00711     GtkWidget *parent = NULL;    /**< parent widget for the dialog box       */
00712     gint result = 0;             /**< result from the dialog box             */
00713     gint index = -1;
00714     gint i = 0;
00715     gint tab_number = 0;
00716     gboolean is_current_doc;     /**< Says wheter the document that we are
00717                                       trying to close is the current one or
00718                                       not                                    */
00719 
00720     if (main_struct != NULL && main_struct->current_doc != NULL)
00721         {
00722             /* Guessing where the user asked to close the document */
00723             if (GTK_IS_BUTTON(widget))
00724                 {
00725                     /* Guessing which document the user has closed */
00726                     tab_number = find_tab_number_from_widget(main_struct, widget);
00727                     closing_doc = g_ptr_array_index(main_struct->documents, tab_number);
00728                     is_current_doc = closing_doc == main_struct->current_doc;
00729                 }
00730             else
00731                 {
00732                     closing_doc = main_struct->current_doc;
00733                 }
00734 
00735             log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Closing document %s"), doc_t_document_get_filename(closing_doc));
00736 
00737             if (closing_doc->modified == TRUE)
00738                 {
00739                     /* Displays a dialog box that let the user choose what to do */
00740                     parent = heraia_get_widget(main_struct->xmls->main, "main_window");
00741 
00742                     dialog = gtk_message_dialog_new(GTK_WINDOW(parent), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, Q_("This document has been edited and is not saved !"));
00743                     gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog), Q_("Do you want to close it without saving it ?"));
00744 
00745                     result = gtk_dialog_run(GTK_DIALOG(dialog));
00746 
00747                     gtk_widget_destroy(dialog);
00748 
00749                     switch (result)
00750                         {
00751                             case GTK_RESPONSE_YES: /* Will continue if we say Yes */
00752                             break;
00753 
00754                             default:  /* Stops closing if we say No */
00755                                 return;
00756                             break;
00757                         }
00758                 }
00759 
00760             /* Try to catch the index of the closing document */
00761             i = 0;
00762             index = -1;
00763             while (i < main_struct->documents->len && index == -1)
00764                 {
00765                     document = g_ptr_array_index(main_struct->documents, i);
00766                     if (document == closing_doc)
00767                         {
00768                             index = i;
00769                         }
00770                     i++;
00771                 }
00772 
00773             if (index >= 0)
00774                 {
00775                     /* Removing the index in the array */
00776                     g_ptr_array_remove_index(main_struct->documents, index);
00777 
00778                     /* And removing it in the notebook */
00779                     notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
00780                     gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), index);
00781 
00782                     /* kills the widget and the document */
00783                     close_doc_t(closing_doc);
00784 
00785 
00786                     /* Try to find out the new current document */
00787                     /* We do not need to update if the current doc is not closed ! */
00788                     if (is_current_doc == TRUE)
00789                         {
00790                             if (main_struct->documents->len > 0)
00791                                 {
00792                                     /* there is still some documents opened (at least one) */
00793                                     if (index == 0)
00794                                         {
00795                                             main_struct->current_doc = g_ptr_array_index(main_struct->documents, 0);
00796                                             gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
00797                                         }
00798                                     else
00799                                         {
00800                                             main_struct->current_doc = g_ptr_array_index(main_struct->documents, index - 1);
00801                                             gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), index - 1);
00802                                         }
00803                                 }
00804                             else
00805                                 {
00806                                     /* No more documents openned */
00807                                     main_struct->current_doc = NULL;
00808                                     grey_main_widgets(main_struct->xmls->main, TRUE);
00809                                 }
00810                         }
00811                     /* updating things in conformance to the new situation */
00812                     refresh_event_handler(notebook, main_struct);
00813                     update_main_window_name(main_struct);
00814 
00815                 }
00816         }
00817 }
00818 
00819 
00820 /**
00821  *  Here we attemp to save the edited file
00822  *  @todo be more accurate on error (error type, message and filename) returns
00823  *        we should return something at least ...
00824  * @param widget : the widget that issued the signal
00825  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00826  */
00827 void on_save_activate(GtkWidget *widget, gpointer data)
00828 {
00829     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00830     HERAIA_ERROR erreur = HERAIA_NOERR;
00831     gchar *filename = NULL;
00832 
00833     if (main_struct != NULL && main_struct->current_doc != NULL)
00834         {
00835             erreur = heraia_hex_document_save(main_struct->current_doc);
00836 
00837             if (erreur != HERAIA_NOERR)
00838                 {
00839                     filename = doc_t_document_get_filename(main_struct->current_doc);
00840                     log_message(main_struct, G_LOG_LEVEL_ERROR, Q_("Error while saving file %s !"), filename);
00841                 }
00842             else
00843                 {
00844                     set_notebook_tab_label_color(main_struct, FALSE);
00845                     main_struct->current_doc->modified = FALSE; /* document has just been saved (thus it is not modified !) */
00846                 }
00847         }
00848 }
00849 
00850 
00851 /**
00852  * @fn void on_save_as_activate(GtkWidget *widget, gpointer data)
00853  *  This handle the save_as menu entry (here the filename changes)
00854  * @param widget : the widget that issued the signal
00855  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00856  */
00857 void on_save_as_activate(GtkWidget *widget, gpointer data)
00858 {
00859     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00860     HERAIA_ERROR erreur = HERAIA_NOERR;
00861     gchar *filename = NULL;  /**< Auto malloc'ed, do not free */
00862 
00863     if (main_struct != NULL && main_struct->current_doc != NULL)
00864         {
00865             filename = select_a_file_to_save(main_struct);
00866 
00867             if (filename != NULL)
00868                 {
00869                     erreur = heraia_hex_document_save_as(main_struct->current_doc, filename);
00870                 }
00871             else
00872                 {
00873                     erreur = HERAIA_CANCELLED;
00874                 }
00875 
00876             if (erreur != HERAIA_NOERR)
00877                 {
00878                     if (erreur == HERAIA_CANCELLED)
00879                         {
00880                             log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Saving file as... : operation cancelled."));
00881                         }
00882                     else
00883                         {
00884                             log_message(main_struct, G_LOG_LEVEL_ERROR, Q_("Error while saving file as %s"), doc_t_document_get_filename(main_struct->current_doc));
00885                         }
00886                 }
00887             else
00888                 {
00889                     /* updating the window name and tab's name */
00890                     update_main_window_name(main_struct);
00891                     set_notebook_tab_name(main_struct);
00892                     main_struct->current_doc->modified = FALSE; /* document has just been saved (thus it is not modified !) */
00893                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("File %s saved and now edited."), doc_t_document_get_filename(main_struct->current_doc));
00894                 }
00895         }
00896 }
00897 
00898 
00899 /**
00900  * @fn void on_DIMenu_activate(GtkWidget *widget, gpointer data)
00901  *  This handles the menuitem "Data Interpretor" that
00902  *  shows or hides the data interpretor window
00903  * @param widget : the widget that issued the signal
00904  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00905  */
00906 void on_DIMenu_activate(GtkWidget *widget, gpointer data)
00907 {
00908 
00909     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00910     data_window_t *dw = NULL;      /**< data_window structure for data interpretor */
00911     GtkNotebook *notebook = NULL;  /**< data interpretor's notebook                */
00912 
00913     if (main_struct != NULL)
00914         {
00915             dw = main_struct->current_DW;
00916 
00917             if (dw != NULL)
00918                 {
00919                     if (dw->diw == NULL)
00920                         {
00921                             dw->diw = heraia_get_widget(main_struct->xmls->main, "data_interpretor_window");
00922                         }
00923 
00924                     if (dw->diw != NULL)
00925                         {
00926                             notebook = GTK_NOTEBOOK(heraia_get_widget(main_struct->xmls->main, "diw_notebook"));
00927 
00928                             if (main_struct->win_prop->data_interpretor->displayed == FALSE)
00929                                 {
00930                                     /* Setting the first page of the notebook as default (Numbers) */
00931                                     gtk_notebook_set_current_page(notebook, dw->tab_displayed);
00932 
00933                                     /* moving to the right position */
00934                                     move_and_show_dialog_box(dw->diw, main_struct->win_prop->data_interpretor);
00935 
00936                                     refresh_data_interpretor_window(widget, data);
00937                                 }
00938                             else
00939                                 {
00940                                     /* recording some prefs from the dialog : position + opened tab */
00941                                     dw->tab_displayed = gtk_notebook_get_current_page(notebook);
00942                                     record_and_hide_dialog_box(dw->diw, main_struct->win_prop->data_interpretor);
00943                                 }
00944                         }
00945                 }
00946         }
00947 }
00948 
00949 
00950 /**
00951  * Called when tests submenu is activated
00952  * @param widget : the widget that issued the signal
00953  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00954  */
00955 void on_tests_menu_activate(GtkWidget *widget, gpointer data)
00956 {
00957     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00958     gboolean result = FALSE;
00959 
00960     if (main_struct != NULL)
00961         {
00962             result = tests_ui(main_struct);
00963 
00964             if (result == TRUE)
00965                 {
00966                     log_message(main_struct, G_LOG_LEVEL_INFO, Q_("All tests went Ok."));
00967                 }
00968             else
00969                 {
00970                     log_message(main_struct, G_LOG_LEVEL_WARNING, Q_("Some tests failed."));
00971                 }
00972         }
00973 }
00974 
00975 
00976 /**
00977  * @fn delete_main_struct_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00978  *  When the user destroys or delete the main window
00979  * @param widget : calling widget
00980  * @param event : event associated (may be NULL as we don't use this here)
00981  * @param data : MUST be heraia_struct_t *main_struct main structure
00982  */
00983 gboolean delete_main_struct_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00984 {
00985 
00986     on_quit_activate(widget, data);
00987 
00988     /* If we are leaving heraia, we are not supposed to be here ! */
00989     return TRUE;
00990 }
00991 
00992 
00993 /**
00994  * @fn gboolean delete_dt_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00995  *  call back function for the data interpretor window destruction
00996  * @param widget : calling widget (may be NULL as we don't use this here)
00997  * @param event : event associated (may be NULL as we don't use this here)
00998  * @param data : MUST be heraia_struct_t *main_struct main structure and not NULL
00999  */
01000 gboolean delete_dt_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
01001 {
01002     heraia_struct_t *main_struct = (heraia_struct_t *) data;
01003 
01004     g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
01005 
01006     return TRUE;
01007 }
01008 
01009 
01010 /**
01011  * @fn void destroy_dt_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
01012  *  call back function for the data interpretor window destruction
01013  * @param widget : calling widget (may be NULL as we don't use this here)
01014  * @param event : event associated (may be NULL as we don't use this here)
01015  * @param data : MUST be heraia_struct_t *main_struct main structure and not NULL
01016  */
01017 void destroy_dt_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
01018 {
01019     heraia_struct_t *main_struct = (heraia_struct_t *) data;
01020 
01021     g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
01022 }
01023 
01024 
01025 /**
01026  * What to do when a change occurs in tabs (user selected a particular
01027  * tab)
01028  * @param notebook : the widget that issued this signal
01029  * @param page : the new current page
01030  * @param tab_num : index of this page
01031  * @param data : MUST be heraia_struct_t *main_struct !
01032  */
01033 gboolean file_notebook_tab_changed(GtkNotebook *notebook, GtkNotebookPage *page, gint tab_num, gpointer data)
01034 {
01035     heraia_struct_t *main_struct = (heraia_struct_t *) data;
01036 
01037     if (main_struct != NULL)
01038         {
01039             if (tab_num >= 0 && tab_num <= main_struct->documents->len)
01040                 {
01041                     /* Current document is now from the selected tab */
01042                     main_struct->current_doc = g_ptr_array_index(main_struct->documents, tab_num);
01043 
01044                     /* Changing main window's name */
01045                     update_main_window_name(main_struct);
01046 
01047                     /* Refreshing the view */
01048                     main_struct->event = HERAIA_REFRESH_TAB_CHANGED;
01049                     refresh_event_handler(GTK_WIDGET(notebook), main_struct);
01050                     main_struct->event = HERAIA_REFRESH_NOTHING;
01051                 }
01052 
01053         }
01054 
01055     return TRUE;
01056 }
01057 
01058 /* End of call back functions that handle the data interpretor window */
01059 
01060 
01061 /**
01062  * @fn static gchar *make_absolute_path(gchar *filename)
01063  *  Returns an absolute path to the filename
01064  *  the string should be freed when no longer needed
01065  *  very UGLy !
01066  * @todo do something without any system calls !!!
01067  * @param filename : relative notation filename from which to extract an
01068  *        absolute path
01069  * @return returns a string with the absolute path which should be freed when
01070  *         no longer needed
01071  */
01072 static gchar *make_absolute_path(gchar *filename)
01073 {
01074     gchar *current_dir = NULL;
01075     gchar *new_dir = NULL;
01076 
01077     if (g_path_is_absolute(filename) == TRUE)
01078         {
01079             /* if the filename is already in an absolute format */
01080             return  g_path_get_dirname(filename);
01081         }
01082     else
01083         {
01084             current_dir = g_get_current_dir();
01085             new_dir = g_path_get_dirname(filename);
01086 
01087             if (g_chdir(new_dir) == 0)
01088                 {
01089                     g_free(new_dir);
01090                     new_dir = g_get_current_dir();
01091                     g_chdir(current_dir);
01092                     g_free(current_dir);
01093 
01094                     return new_dir;
01095                 }
01096             else
01097                 {
01098                     g_free(current_dir);
01099 
01100                     return NULL;
01101                 }
01102         }
01103 }
01104 
01105 
01106 /**
01107  *  Sets the working directory for the file chooser to the directory of the
01108  *  filename (even if filename is a relative filename such as ../docs/test_file)
01109  * @param file_chooser : An initialized GtkFileChooser
01110  * @param filename : a filename (one previously openned)
01111  */
01112 void set_the_working_directory(GtkFileChooser *file_chooser, gchar *filename)
01113 {
01114     gchar *dirname = NULL;    /**< directory where we want to be, at first, in the file chooser */
01115 
01116     dirname = make_absolute_path(filename);
01117 
01118     if (dirname != NULL)
01119         {
01120             gtk_file_chooser_set_current_folder(file_chooser, dirname);
01121             g_free(dirname);
01122         }
01123 }
01124 
01125 
01126 /**
01127  *  This function does open a file selector dialog box and returns the selected
01128  *  filename.
01129  * @param main_struct : main structure
01130  * @return returns a list of filenames to be loaded (if any)
01131  */
01132 GSList *select_file_to_load(heraia_struct_t *main_struct)
01133 {
01134     GtkWidget *parent = NULL; /**< A parent window (we use main_struct)            */
01135     GtkFileChooser *file_chooser = NULL;
01136     GSList *list = NULL;   /**< list of selected (if any) filenames to be openned  */
01137 
01138     parent = heraia_get_widget(main_struct->xmls->main, "main_window");
01139 
01140     file_chooser = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(Q_("Select a file to analyse"),
01141                                                                 GTK_WINDOW(parent),
01142                                                                 GTK_FILE_CHOOSER_ACTION_OPEN,
01143                                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
01144                                                                 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
01145                                                                 NULL));
01146 
01147     /**
01148      *  for the moment we do not want to retrieve multiples selections
01149      *  but this could be a valuable thing in the future
01150      */
01151     gtk_window_set_modal(GTK_WINDOW(file_chooser), TRUE);
01152     gtk_file_chooser_set_select_multiple(file_chooser, TRUE);
01153 
01154     /**
01155      *  We want the file selection path to be the one of the previous
01156      *  openned file if any !
01157      */
01158     if (doc_t_document_get_filename(main_struct->current_doc) != NULL)
01159        {
01160             set_the_working_directory(file_chooser, doc_t_document_get_filename(main_struct->current_doc));
01161        }
01162 
01163     switch (gtk_dialog_run(GTK_DIALOG(file_chooser)))
01164         {
01165             case GTK_RESPONSE_OK:
01166 
01167                 list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(file_chooser));
01168                 gtk_widget_destroy(GTK_WIDGET(file_chooser));
01169 
01170                 return list;
01171              break;
01172 
01173             case GTK_RESPONSE_CANCEL:
01174             default:
01175                 gtk_widget_destroy(GTK_WIDGET(file_chooser));
01176 
01177                 return NULL;
01178              break;
01179         }
01180 }
01181 
01182 
01183 /**
01184  * @fn gchar *select_a_file_to_save(heraia_struct_t *main_struct)
01185  *  This function opens a dialog box that allow one to choose a
01186  *  file name to the file which is about to be saved
01187  * @param main_struct : main structure
01188  * @return returns complete filename (path and filename)
01189  */
01190 gchar *select_a_file_to_save(heraia_struct_t *main_struct)
01191 {
01192     GtkWidget *parent = NULL;     /**< A parent window (we use main_struct) */
01193     GtkFileChooser *fcd = NULL;
01194     gchar *filename = NULL;
01195 
01196     parent = heraia_get_widget(main_struct->xmls->main, "main_window");
01197 
01198     /* Selection a name to the file to save */
01199     fcd = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(Q_("Save As..."),
01200                                                        GTK_WINDOW(parent),
01201                                                        GTK_FILE_CHOOSER_ACTION_SAVE,
01202                                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
01203                                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
01204                                                        NULL));
01205 
01206     /* window properties : modal, without multi-selection and with confirmation */
01207     gtk_window_set_modal(GTK_WINDOW(fcd), TRUE);
01208     gtk_file_chooser_set_select_multiple(fcd, FALSE);
01209     gtk_file_chooser_set_do_overwrite_confirmation(fcd, TRUE);
01210 
01211     /* we do want to have the file's directory where to save the new file */
01212     if (doc_t_document_get_filename(main_struct->current_doc) != NULL)
01213        {
01214             set_the_working_directory(fcd, doc_t_document_get_filename(main_struct->current_doc));
01215        }
01216 
01217     switch(gtk_dialog_run(GTK_DIALOG(fcd)))
01218         {
01219             case GTK_RESPONSE_OK:
01220                 /* retrieving the filename */
01221                 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fcd));
01222                 break;
01223             default:
01224                 filename = NULL;
01225                 break;
01226         }
01227 
01228     gtk_widget_destroy(GTK_WIDGET(fcd));
01229 
01230     return filename;
01231 }
01232 
01233 
01234 /**
01235  *  Update main window heraia's name to reflect the current edited file
01236  * @param main_struct : main structure
01237  */
01238 void update_main_window_name(heraia_struct_t *main_struct)
01239 {
01240     GtkWidget *widget = NULL;
01241     gchar *filename = NULL;
01242     gchar *whole_filename = NULL;
01243 
01244     if (main_struct != NULL && main_struct->current_doc != NULL)
01245         {
01246             widget = heraia_get_widget(main_struct->xmls->main, "main_window");
01247 
01248             whole_filename = doc_t_document_get_filename(main_struct->current_doc);
01249 
01250             filename = g_filename_display_basename(whole_filename);
01251 
01252             gtk_window_set_title(GTK_WINDOW(widget), filename);
01253         }
01254     else if (main_struct != NULL)
01255         {
01256             widget = heraia_get_widget(main_struct->xmls->main, "main_window");
01257             gtk_window_set_title(GTK_WINDOW(widget), "Heraia");
01258         }
01259 }
01260 
01261 /**
01262  * Tries to find the label contained in the hbox
01263  * @param hbox : the hbox widget containing one GtkLabel
01264  * @return the label or NULL if not found
01265  */
01266 static GtkWidget *find_label_from_hbox(GtkWidget *hbox)
01267 {
01268     GList *children = NULL;     /**< List of children in hbox widget */
01269     gboolean found = FALSE;
01270 
01271     if (hbox != NULL)
01272         {
01273             children = gtk_container_get_children(GTK_CONTAINER(hbox));
01274             found = FALSE;
01275 
01276             while (children != NULL && found == FALSE)
01277                 {
01278                     if (GTK_IS_LABEL(children->data))
01279                         {
01280                             found = TRUE;
01281                         }
01282                     else
01283                         {
01284                             children = g_list_next(children);
01285                         }
01286                 }
01287 
01288             if (found == TRUE)
01289                 {
01290                     return children->data;
01291                 }
01292             else
01293                 {
01294                     return NULL;
01295                 }
01296         }
01297     else
01298         {
01299             return NULL;
01300         }
01301 }
01302 
01303 
01304 /**
01305  *  Sets notebook's tab's name. This function should only be called
01306  *  when a new filename was set (open and save as functions)
01307  * @param main_struct : main structure
01308  */
01309 void set_notebook_tab_name(heraia_struct_t *main_struct)
01310 {
01311     GtkWidget *notebook = NULL; /**< file notebook in main window                */
01312     GtkWidget *page = NULL;     /**< Current page for the file notebook          */
01313     GtkWidget *hbox = NULL;     /**< container that has the label and the button */
01314     GtkWidget *label = NULL;    /**< tab's label                                 */
01315     doc_t *doc = NULL;          /**< corresponding tab's document                */
01316     gchar *filename = NULL;
01317     gchar *whole_filename;
01318     gint current = 0;           /**< index of the current tab displayed          */
01319     gchar *markup= NULL;        /**< markup text                                 */
01320 
01321     if (main_struct != NULL && main_struct->current_doc != NULL)
01322         {
01323             notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
01324             current = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
01325             page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), current);
01326             hbox = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
01327             label = find_label_from_hbox(hbox);
01328 
01329             if (label != NULL)
01330                 {
01331                     doc = g_ptr_array_index(main_struct->documents, current);
01332                     whole_filename = doc_t_document_get_filename(doc);
01333 
01334                     if (whole_filename != NULL)
01335                         {
01336                             filename = g_filename_display_basename(whole_filename);
01337                             markup =  g_markup_printf_escaped("%s", filename);
01338                             gtk_label_set_markup(GTK_LABEL(label), markup);
01339                             gtk_widget_set_tooltip_text(label, g_filename_display_name(whole_filename));
01340                             g_free(markup);
01341                         }
01342                 }
01343         }
01344 }
01345 
01346 
01347 /**
01348  * Set the style for the label
01349  * @param main_struct : main structure
01350  * @param color : If color is TRUE sets the color for the file tab's label
01351  *                If not, then sets it to default
01352  */
01353 void set_notebook_tab_label_color(heraia_struct_t *main_struct, gboolean color)
01354 {
01355     GtkWidget *notebook = NULL;   /**< file notebook in main window                */
01356     GtkWidget *page = NULL;       /**< Current page for the file notebook          */
01357     GtkWidget *label = NULL;      /**< tab's label                                 */
01358     GtkWidget *menu_label = NULL; /**< menu tab's label                            */
01359     GtkWidget *hbox = NULL;       /**< container that has the label and the button */
01360     gint current = 0;             /**< index of the current tab displayed          */
01361     gchar *markup= NULL;          /**< markup text                                 */
01362     gchar *text = NULL;           /**< label's text                                */
01363 
01364     if (main_struct != NULL && main_struct->current_doc != NULL)
01365         {
01366             notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
01367             current = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
01368             page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), current);
01369             hbox = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
01370             label = find_label_from_hbox(hbox);
01371 
01372             if (label != NULL)
01373                 {
01374                     text = g_strdup(gtk_label_get_text(GTK_LABEL(label)));
01375 
01376                     if (color == TRUE)
01377                         {
01378                             markup = g_markup_printf_escaped("<span foreground=\"blue\">%s</span>", text);
01379                         }
01380                     else
01381                         {
01382                             markup = g_markup_printf_escaped("%s", text);
01383                         }
01384 
01385                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Changing color for filename %s in tab : %d"), markup, current);
01386                     gtk_label_set_markup(GTK_LABEL(label), markup);
01387                     menu_label = gtk_label_new(NULL);
01388                     gtk_label_set_markup(GTK_LABEL(menu_label), markup);
01389                     gtk_notebook_set_menu_label(GTK_NOTEBOOK(notebook), page, menu_label);
01390 
01391                     g_free(markup);
01392                     g_free(text);
01393                 }
01394         }
01395 }
01396 
01397 
01398 /**
01399  * Hides or grey all widgets that needs an open file when boolean greyed is
01400  * TRUE. Also sets the current page of the notebook to the first one.
01401  * @param xml : GtkBuilder XML main structure
01402  * @param greyed : boolean (TRUE to hide an grey widgets)
01403  */
01404 void grey_main_widgets(GtkBuilder *xml, gboolean greyed)
01405 {
01406     GtkWidget *notebook = NULL;  /* file notebook in main window */
01407 
01408     if (xml != NULL)
01409         {
01410             notebook = heraia_get_widget(xml, "file_notebook");
01411 
01412             if (greyed == TRUE)
01413                 {
01414                     gtk_widget_set_sensitive(heraia_get_widget(xml, "save"), FALSE);
01415                     gtk_widget_set_sensitive(heraia_get_widget(xml, "save_as"), FALSE);
01416                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_cut"), FALSE);
01417                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_copy"), FALSE);
01418                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_paste"), FALSE);
01419                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_delete"), FALSE);
01420                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_close"), FALSE);
01421                     gtk_widget_hide(notebook);
01422                 }
01423             else
01424                 {
01425                     gtk_widget_set_sensitive(heraia_get_widget(xml, "save"), TRUE);
01426                     gtk_widget_set_sensitive(heraia_get_widget(xml, "save_as"), TRUE);
01427                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_cut"), TRUE);
01428                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_copy"), TRUE);
01429                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_paste"), TRUE);
01430                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_delete"), TRUE);
01431                     gtk_widget_set_sensitive(heraia_get_widget(xml, "menu_close"), TRUE);
01432                     gtk_widget_show_all(notebook);
01433                 }
01434         }
01435 }
01436 
01437 
01438 /**
01439  *  Here we might init some call backs and menu options
01440  *  and display the interface (main && sub-windows)
01441  *  This function should be called only once at main program's
01442  *  init time
01443  * @param main_struct : main structure
01444  */
01445 void init_heraia_interface(heraia_struct_t *main_struct)
01446 {
01447 
01448     if (main_struct != NULL)
01449         {
01450             /* inits window states (shows or hide windows) */
01451             init_window_states(main_struct);
01452 
01453 
01454             /* menus */
01455             gtk_widget_set_sensitive(heraia_get_widget(main_struct->xmls->main, "menu_redo"), FALSE);
01456             gtk_widget_set_sensitive(heraia_get_widget(main_struct->xmls->main, "menu_undo"), FALSE);
01457             if (main_struct->current_doc != NULL)
01458                 {
01459                     grey_main_widgets(main_struct->xmls->main, FALSE);
01460                 }
01461             else
01462                 {
01463                     grey_main_widgets(main_struct->xmls->main, TRUE);
01464                 }
01465 
01466             refresh_file_labels(main_struct);
01467         }
01468 }
01469 
01470 
01471 /**
01472  *  Loads the GtkBuilder xml files that describes the heraia project
01473  *  tries the following paths in that order :
01474  *  - /etc/heraia/heraia.gtkbuilder
01475  *  - /home/[user]/.heraia/heraia.gtkbuilder
01476  *  - PWD/heraia.gtkbuilder
01477  * @param main_struct : main structure
01478  * @return TRUE if everything went ok, FALSE otherwise
01479  */
01480 static gboolean load_heraia_xml(heraia_struct_t *main_struct)
01481 {
01482     gchar *filename = NULL;
01483 
01484     if (main_struct != NULL && main_struct->xmls != NULL)
01485         {
01486             filename = g_strdup_printf("heraia.gtkbuilder");
01487             main_struct->xmls->main = load_xml_file(main_struct->location_list, filename);
01488             g_free(filename);
01489 
01490             if (main_struct->xmls->main == NULL)
01491                 {
01492                     return FALSE;
01493                 }
01494             else
01495                 {
01496                     return TRUE;
01497                 }
01498         }
01499     else
01500         {
01501             return FALSE;
01502         }
01503 }
01504 
01505 
01506 /**
01507  *  Connects the signal that the cursor has moved to
01508  *  the refreshing function
01509  * @param main_struct : main structure
01510  * @param hex_widget : the hex_widget we want to connect the signal to
01511  */
01512 void connect_cursor_moved_signal(heraia_struct_t *main_struct, GtkWidget *hex_widget)
01513 {
01514     g_signal_connect(G_OBJECT(hex_widget), "cursor_moved",
01515                      G_CALLBACK(refresh_event_handler), main_struct);
01516 }
01517 
01518 
01519 /**
01520  *  Connect the signals at the interface
01521  * @param main_struct : main structure
01522  */
01523 static void heraia_ui_connect_signals(heraia_struct_t *main_struct)
01524 {
01525 
01526     /* the data interpretor menu */
01527     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "DIMenu")), "activate",
01528                      G_CALLBACK(on_DIMenu_activate), main_struct);
01529 
01530     /* Quit, file menu */
01531     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "quit")), "activate",
01532                      G_CALLBACK(on_quit_activate), main_struct);
01533 
01534     /* New, file menu */
01535     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "new")), "activate",
01536                      G_CALLBACK(on_new_activate), main_struct);
01537 
01538     /* Open, file menu */
01539     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "open")), "activate",
01540                      G_CALLBACK(on_open_activate), main_struct);
01541 
01542     /* Close, file menu */
01543     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_close")), "activate",
01544                      G_CALLBACK(on_close_activate), main_struct);
01545 
01546     /* Save, file menu */
01547     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "save")), "activate",
01548                      G_CALLBACK(on_save_activate), main_struct);
01549 
01550     /* Save As, file menu */
01551     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "save_as")), "activate",
01552                      G_CALLBACK(on_save_as_activate), main_struct);
01553 
01554     /* Preferences, Edit menu ; See main_pref_window.c for main_pref_window's signals */
01555     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "preferences")), "activate",
01556                      G_CALLBACK(on_preferences_activate), main_struct);
01557 
01558    /* Undo, edit menu */
01559     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_undo")), "activate",
01560                      G_CALLBACK(on_undo_activate), main_struct);
01561 
01562    /* Redo, edit menu */
01563     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_redo")), "activate",
01564                      G_CALLBACK(on_redo_activate), main_struct);
01565 
01566     /* Cut, edit menu */
01567     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_cut")), "activate",
01568                      G_CALLBACK(on_cut_activate), main_struct);
01569 
01570     /* Copy, edit menu */
01571     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_copy")), "activate",
01572                      G_CALLBACK(on_copy_activate), main_struct);
01573 
01574     /* Paste, edit menu */
01575     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_paste")), "activate",
01576                      G_CALLBACK(on_paste_activate), main_struct);
01577 
01578     /* Delete, edit menu */
01579     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "menu_delete")), "activate",
01580                      G_CALLBACK(on_delete_activate), main_struct);
01581 
01582     /* Test, Help menu */
01583     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "tests_menu")), "activate",
01584                      G_CALLBACK(on_tests_menu_activate), main_struct);
01585 
01586 
01587     /* about dialog box */
01588     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "a_propos")), "activate",
01589                      G_CALLBACK(a_propos_activate), main_struct);
01590 
01591     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "close",
01592                      G_CALLBACK(a_propos_close), main_struct);
01593 
01594     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "response",
01595                      G_CALLBACK(a_propos_response), main_struct);
01596 
01597     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "delete-event",
01598                      G_CALLBACK(a_propos_delete), main_struct);
01599 
01600 
01601     /* main notebook */
01602     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "file_notebook")),"switch-page",
01603                      G_CALLBACK(file_notebook_tab_changed), main_struct);
01604 
01605 
01606     /* main window killed or destroyed */
01607     g_signal_connect(G_OBJECT (heraia_get_widget(main_struct->xmls->main, "main_window")), "delete-event",
01608                      G_CALLBACK(delete_main_struct_event), main_struct);
01609 }
01610 
01611 
01612 /** @fn int load_heraia_ui(heraia_struct_t *main_struct)
01613  *  Loads, if possible, the gtkbuilder xml file and then connects the
01614  *  signals and inits the following windows :
01615  *  - log window
01616  *  - data_interpretor window
01617  *  - list data types
01618  * @param main_struct : main structure
01619  * @return TRUE if load_heraia_xml suceeded, FALSE otherwise
01620  * @todo add more return values to init functions to detect any error while
01621  *       initializing the ui
01622  */
01623 int load_heraia_ui(heraia_struct_t *main_struct)
01624 {
01625     gboolean success = FALSE;
01626 
01627     /* load the XML interfaces (main & treatment) */
01628     success = load_heraia_xml(main_struct);
01629 
01630     if (success == TRUE)
01631         {
01632             /* Heraia UI signals */
01633             if (main_struct->debug == TRUE)
01634                 {
01635                     fprintf(stdout, Q_("Connecting heraia_ui signals     "));
01636                 }
01637 
01638             heraia_ui_connect_signals(main_struct);
01639 
01640             if (main_struct->debug == TRUE)
01641                 {
01642                     fprintf(stdout, Q_(" [Done]\n"));
01643                 }
01644 
01645             /* The Log window */
01646             if (main_struct->debug == TRUE)
01647                 {
01648                     fprintf(stdout, Q_("log window init interface        "));
01649                 }
01650 
01651             log_window_init_interface(main_struct);
01652 
01653             if (main_struct->debug == TRUE)
01654                 {
01655                     fprintf(stdout, Q_(" [Done]\n"));
01656                 }
01657 
01658             /* Preferences window */
01659             if (main_struct->debug == TRUE)
01660                 {
01661                     fprintf(stdout, Q_("preferences window init interface"));
01662                 }
01663 
01664             main_pref_window_init_interface(main_struct);
01665 
01666             if (main_struct->debug == TRUE)
01667                 {
01668                     fprintf(stdout, Q_(" [Done]\n"));
01669                 }
01670 
01671 
01672             /* The data interpretor window */
01673             if (main_struct->debug == TRUE)
01674                 {
01675                     fprintf(stdout, Q_("data interpretor init interface  "));
01676                 }
01677 
01678             data_interpretor_init_interface(main_struct);
01679 
01680             if (main_struct->debug == TRUE)
01681                 {
01682                     fprintf(stdout, Q_(" [Done]\n"));
01683                 }
01684 
01685 
01686             /* preferences file */
01687 
01688             fprintf(stdout, Q_("Loading heraia preference file   "));
01689 
01690             if (load_preference_file(main_struct) != TRUE)
01691                 {
01692                     fprintf(stdout, Q_(" [FAILED]\n"));
01693                 }
01694             else /* Setting up preferences */
01695                 {
01696                     fprintf(stdout, Q_(" [Done]\n"));
01697                     fprintf(stdout, Q_("Setting up preferences           "));
01698                     load_preferences(main_struct);
01699                     fprintf(stdout, Q_(" [Done]\n"));
01700                 }
01701         }
01702 
01703     return success;
01704 }
01705 
01706 
01707 /**
01708  * @fn void add_text_to_textview(GtkTextView *textview, const char *format, ...)
01709  *  adds a text to a textview
01710  * @param textview : the textview where to add text
01711  * @param format : printf style format
01712  * @param ... : a va_list arguments to fit format (as with printf)
01713  */
01714 void add_text_to_textview(GtkTextView *textview, const char *format, ...)
01715 {
01716     va_list args;
01717     GtkTextBuffer *tb = NULL;
01718     GtkTextIter iEnd;
01719     gchar *display = NULL;
01720     GError *err = NULL;
01721 
01722     va_start(args, format);
01723     display = g_locale_to_utf8(g_strdup_vprintf(format, args), -1, NULL, NULL, &err);
01724     va_end(args);
01725 
01726     tb = GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)));
01727     gtk_text_buffer_get_end_iter(tb, &iEnd);
01728     gtk_text_buffer_insert(tb, &iEnd, display, -1);
01729     g_free(display);
01730 }
01731 
01732 
01733 /**
01734  * @fn kill_text_from_textview(GtkTextView *textview)
01735  *  Kills the text from a textview
01736  * @param textview : the textview to kill the text from
01737  */
01738 void kill_text_from_textview(GtkTextView *textview)
01739 {
01740     GtkTextBuffer *tb = NULL;
01741     GtkTextIter iStart;
01742     GtkTextIter iEnd;
01743 
01744     tb = GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)));
01745     gtk_text_buffer_get_start_iter(tb, &iStart);
01746     gtk_text_buffer_get_end_iter(tb, &iEnd);
01747     gtk_text_buffer_delete (tb, &iStart, &iEnd);
01748 }
01749 
01750 
01751 /**
01752  * @fn GtkWidget *gtk_radio_button_get_active(GSList *group)
01753  *  Try to find the active radio button widget in a group
01754  *  This does not take into account inconsistant states
01755  *  returns the first active radio button otherwise NULL
01756  * @param group : A group of GtkRadioButtons
01757  * @return returns the active widget if any (NULL if none)
01758  */
01759 GtkWidget *gtk_radio_button_get_active(GSList *group)
01760 {
01761     GSList *tmp_slist = group;
01762     GtkToggleButton *toggle_button = NULL;
01763 
01764     while (tmp_slist)
01765         {
01766             toggle_button = tmp_slist->data;
01767 
01768             if (gtk_toggle_button_get_active(toggle_button))
01769                 {
01770                     return GTK_WIDGET(toggle_button);
01771                 }
01772 
01773             tmp_slist = g_slist_next(tmp_slist);
01774         }
01775 
01776     return NULL;
01777 }
01778 
01779 
01780 /**
01781  * @fn GtkWidget *gtk_radio_button_get_active_from_widget(GtkRadioButton *radio_group_member)
01782  * gets the active radio button from a radio group
01783  * @param radio_button : GtkRadioButton to get radio group from
01784  * @returns the active GtkRadioButton within the group from
01785  *          radio_button
01786  **/
01787 GtkWidget *gtk_radio_button_get_active_from_widget(GtkRadioButton *radio_button)
01788 {
01789     if (radio_button != NULL)
01790         {
01791             return gtk_radio_button_get_active(gtk_radio_button_get_group(radio_button));
01792         }
01793     else
01794         {
01795             return NULL;
01796         }
01797 }
01798 
01799 
01800 /**
01801  * Sets the radio button active
01802  * @param radio_button : The GtkRadioButton to be active within it's group
01803  */
01804 void gtk_radio_button_set_active(GtkRadioButton *radio_button)
01805 {
01806     GSList *group = NULL;
01807     GtkToggleButton *toggle_button = NULL;
01808 
01809     group = gtk_radio_button_get_group(radio_button);
01810 
01811     while (group)
01812         {
01813             toggle_button = group->data;
01814 
01815             if (toggle_button == GTK_TOGGLE_BUTTON(radio_button))
01816                 {
01817                    gtk_toggle_button_set_active(toggle_button, TRUE);
01818                 }
01819             else
01820                 {
01821                     gtk_toggle_button_set_active(toggle_button, FALSE);
01822                 }
01823 
01824             group = g_slist_next(group);
01825         }
01826 }
01827 
01828 
01829 /**
01830  * @fn gboolean is_cmi_checked(GtkWidget *check_menu_item)
01831  *  Tells whether a GtkCheckMenuItem is Checked or not
01832  * @param check_menu_item : a GtkCheckMenuItem to verify
01833  * @return returns TRUE if the Check Manu Item is checked, FALSE otherwise
01834  */
01835 gboolean is_cmi_checked(GtkWidget *check_menu_item)
01836 {
01837     return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(check_menu_item));
01838 }
01839 
01840 
01841 /**
01842  * @fn gboolean is_toggle_button_activated(GtkBuilder *main_xml, gchar *check_button)
01843  *  returns the state of a named check button contained
01844  *  in the GtkBuilder XML description
01845  * @param main_xml : a GtkBuilder XML definition
01846  * @param check_button : the name of an existing check_button within the GtkBuilder
01847  *        definition
01848  * @return TRUE if the button is activated / toggled , FALSE otherwise
01849  */
01850 gboolean is_toggle_button_activated(GtkBuilder *main_xml, gchar *check_button)
01851 {
01852     gboolean activated = FALSE;
01853 
01854     if (main_xml != NULL)
01855         {
01856             activated = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(heraia_get_widget(main_xml, check_button)));
01857         }
01858 
01859     return activated;
01860 }
01861 
01862 
01863 /**
01864  *  This is a wrapper to the GtkBuilder xml get widget. It is intended
01865  *  to simplify the developpers lives if they have to choose or
01866  *  propose other means to do the same thing than libglade (say,
01867  *  for example, GtkBuilder ;-)
01868  * @param xml : A GtkBuilder XML definition
01869  * @param widget_name : an existing widget name in the GtkBuilder definition
01870  * @return returns the widget itself if it exists in the definition file (NULL
01871  *         otherwise)
01872  */
01873 GtkWidget *heraia_get_widget(GtkBuilder *xml, gchar *widget_name)
01874 {
01875    /**
01876     * For debug purposes only (very verbose as this function is the main used)
01877     * fprintf(stdout, "Getting Widget named %s\n", widget_name);
01878     */
01879 
01880     if (xml != NULL && widget_name != NULL)
01881         {
01882             return GTK_WIDGET(gtk_builder_get_object(xml, widget_name));
01883         }
01884     else
01885         {
01886             return NULL;
01887         }
01888 }
01889 
01890 
01891 /**
01892  * @fn void destroy_a_single_widget(GtkWidget *widget)
01893  *  Destroys a single widget if it exists
01894  * @param widget : the widget to destroy
01895  */
01896 void destroy_a_single_widget(GtkWidget *widget)
01897 {
01898     if (widget != NULL)
01899         {
01900             gtk_widget_destroy(widget);
01901         }
01902 }
01903 
01904 
01905 /**
01906  * Verify if we can safely close everything
01907  * @param main_struct : main structure
01908  * @return a boolean which is TRUE if unsaved documents still exists and FALSE
01909  *         otherwise
01910  */
01911 static gboolean unsaved_documents(heraia_struct_t *main_struct)
01912 {
01913     doc_t *current_doc = NULL;
01914     gboolean result = FALSE;
01915     guint i = 0;
01916 
01917     if (main_struct != NULL && main_struct->documents != NULL)
01918         {
01919             for(i = 0; i < main_struct->documents->len; i++)
01920                 {
01921                     current_doc =  g_ptr_array_index(main_struct->documents, i);
01922                     result = result | current_doc->modified;
01923                 }
01924 
01925             return result;
01926         }
01927 
01928     return result;
01929 }
01930 
01931 
01932 /**
01933  * @fn void close_heraia(heraia_struct_t *main_struct)
01934  * Before closing heraia we need to do few things
01935  * @param main_struct : main_struct
01936  * @return TRUE if we can safely quit heraia, FALSE otherwise
01937  */
01938 static gboolean close_heraia(heraia_struct_t *main_struct)
01939 {
01940     gboolean unsaved = FALSE;    /**< if there is any unsaved documents */
01941     gboolean quit_heraia = TRUE; /**< By default we want to quit        */
01942     GtkWidget *dialog = NULL;    /**< The dialog box                    */
01943     GtkWidget *parent = NULL;    /**< parent widget for the dialog box  */
01944     gint result = 0;             /**< result from the dialog box        */
01945 
01946     unsaved = unsaved_documents(main_struct);
01947 
01948     if (unsaved == TRUE)
01949         {
01950             /* Displays a dialog box that let the user choose what to do */
01951             parent = heraia_get_widget(main_struct->xmls->main, "main_window");
01952 
01953             dialog = gtk_message_dialog_new(GTK_WINDOW(parent), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, Q_("Unsaved document(s) remains."));
01954             gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog), Q_("Do you want to quit without saving ?"));
01955 
01956 
01957             result = gtk_dialog_run(GTK_DIALOG(dialog));
01958 
01959             switch (result)
01960                 {
01961                     case GTK_RESPONSE_YES:
01962                         quit_heraia = TRUE;
01963                     break;
01964 
01965                     default:
01966                         quit_heraia = FALSE;
01967                     break;
01968                 }
01969 
01970             gtk_widget_destroy(dialog);
01971         }
01972 
01973     if ( quit_heraia == TRUE)
01974         {
01975             /* recording window's position */
01976             record_all_dialog_box_positions(main_struct);
01977 
01978             /* . Saving preferences */
01979             save_preferences(main_struct);
01980         }
01981 
01982     return quit_heraia;
01983 }
01984 
01985 
01986 /**
01987  * @fn void init_one_cmi_window_state(GtkWidget *dialog_box, GtkWidget *cmi, window_prop_t *dialog_prop)
01988  * init one cmi window based state
01989  * @param dialog_box : the window or dialog box we want to init its state
01990  * @param cmi : corresponding check menu item
01991  * @param dialog_prop : corresponding window properties (should be initialized and not NULL)
01992  */
01993 static void init_one_cmi_window_state(GtkWidget *dialog_box, GtkWidget *cmi, window_prop_t *dialog_prop)
01994 {
01995     gboolean activated = FALSE;
01996 
01997     if (dialog_box != NULL && cmi != NULL && dialog_prop != NULL)
01998         {
01999             activated = dialog_prop->displayed;
02000             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(cmi), activated);
02001             if (activated == TRUE)
02002                 {
02003                     gtk_window_move(GTK_WINDOW(dialog_box), dialog_prop->x, dialog_prop->y);
02004                     gtk_window_resize(GTK_WINDOW(dialog_box), dialog_prop->width, dialog_prop->height);
02005                     gtk_widget_show_all(dialog_box);
02006                 }
02007         }
02008 }
02009 
02010 
02011 /**
02012  * @fn init_window_states(heraia_struct_t *main_struct)
02013  *  Inits all windows states (positions, displayed, and so on...)
02014  * @param main_struct : main structure
02015  */
02016 void init_window_states(heraia_struct_t *main_struct)
02017 {
02018     GtkWidget *cmi = NULL;
02019     GtkWidget *dialog_box = NULL;
02020 
02021     if (main_struct != NULL && main_struct->xmls != NULL  && main_struct->xmls->main != NULL)
02022         {
02023             if (main_struct->win_prop)
02024                 {
02025                     /* Main window (always the first one) */
02026                     dialog_box = heraia_get_widget(main_struct->xmls->main, "main_window");
02027                     if (main_struct->win_prop->main_dialog->displayed == TRUE)
02028                         {
02029                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->main_dialog->x, main_struct->win_prop->main_dialog->y);
02030                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->main_dialog->width, main_struct->win_prop->main_dialog->height);
02031                             gtk_widget_show(dialog_box);
02032                         }
02033 
02034                     /* Log Window Interface */
02035                     cmi = heraia_get_widget(main_struct->xmls->main, "mw_cmi_show_logw");
02036                     dialog_box = heraia_get_widget(main_struct->xmls->main, "log_window");
02037                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->log_box);
02038 
02039                     /* Data Interpretor Interface */
02040                     cmi = heraia_get_widget(main_struct->xmls->main, "DIMenu");
02041                     /* Emit the specific signal to activate the check_menu_item */
02042                     if (main_struct->win_prop->data_interpretor->displayed == TRUE)
02043                         {
02044                             main_struct->win_prop->data_interpretor->displayed = FALSE; /* dirty trick */
02045                             g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
02046                         }
02047 
02048                     /* List Data type Interface */
02049                     cmi = heraia_get_widget(main_struct->xmls->main, "ldt_menu");
02050                     dialog_box = heraia_get_widget(main_struct->xmls->main, "list_data_types_window");
02051                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->ldt);
02052 
02053                     /* Plugin List Interface */
02054                     cmi = heraia_get_widget(main_struct->xmls->main, "mw_cmi_plugin_list");
02055                     dialog_box = heraia_get_widget(main_struct->xmls->main, "plugin_list_window");
02056                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->plugin_list);
02057 
02058                     /* Preferences window */
02059                     dialog_box = heraia_get_widget(main_struct->xmls->main, "main_preferences_window");
02060                     if (main_struct->win_prop->main_pref_window->displayed == TRUE)
02061                         {
02062                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->main_pref_window->x, main_struct->win_prop->main_pref_window->y);
02063                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->main_pref_window->width, main_struct->win_prop->main_pref_window->height);
02064                             gtk_widget_show_all(dialog_box);
02065                         }
02066 
02067                     /* About Box */
02068                     dialog_box = heraia_get_widget(main_struct->xmls->main, "about_dialog");
02069                     if (main_struct->win_prop->about_box->displayed == TRUE)
02070                         {
02071                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->about_box->x, main_struct->win_prop->about_box->y);
02072                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->about_box->width, main_struct->win_prop->about_box->height);
02073                             set_a_propos_properties(dialog_box);
02074                             gtk_widget_show_all(dialog_box);
02075                         }
02076                 }
02077         }
02078 }
02079 
02080 
02081 /**
02082  * Creates a label an a button to add into a tab from main window's notebook
02083  * @param main_struct : main structure
02084  * @param tab_label : a GtkWidget that is the label we want to add to the tab
02085  * @return a newly created GtkWidget which contains the label and a close button
02086  */
02087 static GtkWidget *create_tab_close_button(heraia_struct_t *main_struct, GtkWidget *tab_label)
02088 {
02089     GtkWidget *hbox = NULL;    /**< used for hbox creation in the tabs */
02090     GtkWidget *button = NULL;  /**< Closing button                     */
02091 
02092 
02093      /* Close button in tabs */
02094     hbox = gtk_hbox_new(FALSE, 0);
02095 
02096     button = gtk_button_new_with_label("x");
02097     gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
02098     gtk_widget_set_size_request(button, 18, 17);
02099     gtk_widget_set_tooltip_text(button, Q_("Close button"));
02100     g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_close_activate), main_struct);
02101 
02102     /* Packing label and button all together in order to display everything in the tab */
02103     gtk_box_pack_start(GTK_BOX(hbox), tab_label, FALSE, FALSE, 0);
02104     gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 2);
02105     gtk_widget_show_all(hbox);
02106 
02107     return hbox;
02108 }
02109 
02110 
02111 /**
02112  * Adds a new tab to the main window in file's notebook
02113  * @param main_struct : main structure
02114  * @param doc : the new document that will be related to the tab
02115  */
02116 void add_new_tab_in_main_window(heraia_struct_t *main_struct, doc_t *doc)
02117 {
02118     GtkWidget *vbox = NULL;       /**< used for vbox creation               */
02119     GtkNotebook *notebook = NULL; /**< file_notebook from heraia.gtkbuilder */
02120     GtkWidget *tab_label = NULL;  /**< tab's label                          */
02121     GtkWidget *menu_label = NULL; /**<menu's label                          */
02122     gint tab_num = -1;            /**< new tab's index                      */
02123     gchar *filename = NULL;
02124     gchar *whole_filename;
02125     gchar *markup = NULL;         /**< markup text                          */
02126     gchar *menu_markup = NULL;    /**< menu markup text                     */
02127     GtkWidget *hbox = NULL;       /**< used for hbox creation in the tabs   */
02128 
02129     notebook = GTK_NOTEBOOK(heraia_get_widget(main_struct->xmls->main, "file_notebook"));
02130     vbox = gtk_vbox_new(FALSE, 2);
02131     gtk_box_pack_start(GTK_BOX(vbox), doc->hex_widget, TRUE, TRUE, 3);
02132 
02133     /* tab's label and menu label */
02134     tab_label = gtk_label_new(NULL);
02135     menu_label = gtk_label_new(NULL);
02136     whole_filename = doc_t_document_get_filename(doc);
02137 
02138     if (whole_filename != NULL)
02139         {
02140             filename = g_filename_display_basename(whole_filename);
02141             markup = g_markup_printf_escaped("%s", filename);
02142             menu_markup = g_markup_printf_escaped("%s", filename);
02143             gtk_label_set_markup(GTK_LABEL(tab_label), markup);
02144             gtk_label_set_markup(GTK_LABEL(menu_label), menu_markup);
02145             gtk_label_set_justify(GTK_LABEL(menu_label), GTK_JUSTIFY_LEFT);
02146             gtk_widget_set_tooltip_text(tab_label, g_filename_display_name(whole_filename));
02147             g_free(markup);
02148             g_free(menu_markup);
02149         }
02150 
02151     hbox = create_tab_close_button(main_struct, tab_label);
02152 
02153     gtk_widget_show_all(vbox);
02154     tab_num = gtk_notebook_append_page_menu(notebook, vbox, hbox, menu_label);
02155 
02156     gtk_notebook_set_current_page(notebook, tab_num);
02157     main_struct->current_doc = doc;
02158 }
02159 
02160 
02161 /**
02162  *  To help plugins to deal with widgets, shows or hide a specific widget
02163  * @param widget : the widget to show or hide
02164  * @param show : what to do : TRUE to show the widget, FALSE to hide it
02165  * @param win_prop : window properties.
02166  */
02167 void show_hide_widget(GtkWidget *widget, gboolean show, window_prop_t *win_prop)
02168 {
02169     if (win_prop != NULL)
02170             {
02171                 if (show)
02172                     {
02173                         move_and_show_dialog_box(widget, win_prop);
02174                     }
02175                 else
02176                     {
02177                         record_and_hide_dialog_box(widget, win_prop);
02178                     }
02179             }
02180         else
02181             {
02182                 if (show)
02183                     {
02184                         gtk_widget_show(widget);
02185                     }
02186                 else
02187                     {
02188                         gtk_widget_hide(widget);
02189                     }
02190             }
02191 }
Generated on Fri Aug 20 09:15:18 2010 for Heraia by  doxygen 1.6.3