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 
00040 
00041 /**
00042  * @fn void on_quit_activate(GtkWidget *widget, gpointer data)
00043  *  Quit, file menu
00044  * @param widget : the widget that issued the signal
00045  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00046  */
00047 void on_quit_activate(GtkWidget *widget, gpointer data)
00048 {
00049     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00050     gboolean quit_heraia = FALSE;
00051 
00052     quit_heraia = close_heraia(main_struct);
00053 
00054     if (quit_heraia == TRUE)
00055         {
00056             gtk_main_quit();
00057         }
00058 }
00059 
00060 
00061 /**
00062  * @fn void on_new_activate(GtkWidget *widget, gpointer data)
00063  *  New, file menu
00064  * @param widget : the widget that issued the signal
00065  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00066  */
00067 void on_new_activate(GtkWidget *widget, gpointer data)
00068 {
00069     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00070 
00071     log_message(main_struct, G_LOG_LEVEL_WARNING, "Not implemented Yet (Please contribute !)");
00072 }
00073 
00074 
00075 /**
00076  * @fn void on_preferences_activate(GtkWidget *widget, gpointer data)
00077  *  Preferences, file menu :
00078  *  Displays the preference window (as a modal window)
00079  * @param widget : the widget that issued the signal
00080  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00081  */
00082 void on_preferences_activate(GtkWidget *widget, gpointer data)
00083 {
00084     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00085     GtkWidget *pref_window = NULL;
00086 
00087     pref_window = heraia_get_widget(main_struct->xmls->main, "main_preferences_window");
00088 
00089     if (pref_window != NULL)
00090         {
00091             move_and_show_dialog_box(pref_window, main_struct->win_prop->main_pref_window);
00092         }
00093 
00094 }
00095 
00096 
00097 /**
00098  * @fn void set_a_propos_properties(GtkWidget *about_dialog)
00099  * Sets name and version in the dialog box
00100  * @param about_dialog the widget that contain all the about box
00101  */
00102 static void set_a_propos_properties(GtkWidget *about_dialog)
00103 {
00104 
00105     if (about_dialog != NULL)
00106         {
00107             if (GTK_MINOR_VERSION >= 12)
00108                 {
00109                     gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about_dialog), PACKAGE_NAME);
00110                 }
00111             if (GTK_MINOR_VERSION >= 6)
00112                 {
00113                     gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_dialog), PACKAGE_VERSION);
00114                 }
00115         }
00116 }
00117 
00118 
00119 /**
00120  * @fn void a_propos_activate(GtkWidget *widget, gpointer data)
00121  *  Shows apropos's dialog box
00122  * @param widget : the widget that issued the signal
00123  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00124  */
00125 void a_propos_activate(GtkWidget *widget, gpointer data)
00126 {
00127     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00128     GtkWidget *about_dialog = NULL;
00129 
00130     about_dialog = heraia_get_widget(main_struct->xmls->main, "about_dialog");
00131 
00132     if (about_dialog != NULL)
00133         {
00134             set_a_propos_properties(about_dialog);
00135             move_and_show_dialog_box(about_dialog, main_struct->win_prop->about_box);
00136         }
00137 }
00138 
00139 
00140 /**
00141  * @fn void move_and_show_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00142  *  Move the dialog box to the wanted position, shows it and says it in the displayed prop
00143  * @param dialog_box : the dialog box we want to move and show
00144  * @param dialog_prop : window_prop_t properties structure corresponding to the dialog box
00145  */
00146 void move_and_show_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00147 {
00148     if (dialog_prop != NULL)
00149         {
00150 
00151             if (dialog_prop->displayed == FALSE)
00152                 {
00153                     if (dialog_prop->x > 0 && dialog_prop->y > 0)
00154                         {
00155                             gtk_window_move(GTK_WINDOW(dialog_box), dialog_prop->x, dialog_prop->y);
00156                         }
00157 
00158                     if (dialog_prop->width > 0 && dialog_prop->height > 0)
00159                         {
00160                             gtk_window_resize(GTK_WINDOW(dialog_box), dialog_prop->width, dialog_prop->height);
00161                         }
00162 
00163                     gtk_widget_show_all(dialog_box);
00164                     dialog_prop->displayed = TRUE;
00165                 }
00166         }
00167 }
00168 
00169 
00170 /**
00171  * @fn void record_dialog_box_position(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00172  * Records one dialog position
00173  * @param dialog_box : a dialog box from which we want to record the position
00174  * @param[in,out] dialog_prop : window_prop_t properties structure corresponding to the dialog box
00175  */
00176 void record_dialog_box_position(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00177 {
00178     gint x = 0;
00179     gint y = 0;
00180     gint width = WPT_DEFAULT_WIDTH;
00181     gint height = WPT_DEFAULT_HEIGHT;
00182 
00183     if (dialog_prop != NULL && dialog_prop->displayed == TRUE)
00184         {
00185             if (dialog_box != NULL)
00186                 {
00187                     gtk_window_get_position(GTK_WINDOW(dialog_box), &x, &y);
00188                     gtk_window_get_size(GTK_WINDOW(dialog_box), &width, &height);
00189                     dialog_prop->x = x;
00190                     dialog_prop->y = y;
00191                     dialog_prop->width = width;
00192                     dialog_prop->height = height;
00193                 }
00194         }
00195 }
00196 
00197 
00198 /**
00199  * @fn void record_all_dialog_box_positions(heraia_struct_t *main_struct)
00200  * Records all the positions of the displayed windows
00201  * @param[in,out] main_struct : main structure
00202  */
00203 void record_all_dialog_box_positions(heraia_struct_t *main_struct)
00204 {
00205     GtkWidget *dialog_box = NULL;
00206 
00207     if (main_struct != NULL &&
00208         main_struct->xmls != NULL &&
00209         main_struct->xmls->main != NULL &&
00210         main_struct->win_prop != NULL &&
00211         main_struct->current_DW != NULL)
00212         {
00213             /* data interpretor */
00214             dialog_box = main_struct->current_DW->diw;
00215             record_dialog_box_position(dialog_box, main_struct->win_prop->data_interpretor);
00216 
00217             /* About box */
00218             dialog_box = heraia_get_widget (main_struct->xmls->main, "about_dialog");
00219             record_dialog_box_position(dialog_box, main_struct->win_prop->about_box);
00220 
00221             /* Log window */
00222             dialog_box = heraia_get_widget (main_struct->xmls->main, "log_window");
00223             record_dialog_box_position(dialog_box, main_struct->win_prop->log_box);
00224 
00225             /* main_dialog */
00226             dialog_box = heraia_get_widget (main_struct->xmls->main, "main_window");
00227             record_dialog_box_position(dialog_box, main_struct->win_prop->main_dialog);
00228 
00229             /* plugin_list */
00230             dialog_box = heraia_get_widget (main_struct->xmls->main, "plugin_list_window");
00231             record_dialog_box_position(dialog_box, main_struct->win_prop->plugin_list);
00232 
00233             /* list data types */
00234             dialog_box = heraia_get_widget (main_struct->xmls->main, "list_data_types_window");
00235             record_dialog_box_position(dialog_box, main_struct->win_prop->ldt);
00236 
00237             /* main_preferences */
00238             dialog_box = heraia_get_widget (main_struct->xmls->main, "main_preferences_window");
00239             record_dialog_box_position(dialog_box, main_struct->win_prop->main_pref_window);
00240         }
00241 }
00242 
00243 
00244 /**
00245  * @fn void record_and_hide_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00246  *  Record position and hide a dialog box
00247  * @param dialog_box : the dialog box we want to record its position and then hide
00248  * @param dialog_prop : window_prop_t properties structure corresponding to the dialog box
00249  */
00250 void record_and_hide_dialog_box(GtkWidget *dialog_box, window_prop_t *dialog_prop)
00251 {
00252 
00253     if (dialog_prop->displayed == TRUE)
00254         {
00255             record_dialog_box_position(dialog_box, dialog_prop);
00256 
00257             gtk_widget_hide(dialog_box);
00258             dialog_prop->displayed = FALSE;
00259         }
00260 }
00261 
00262 
00263 /**
00264  * @fn static void record_and_hide_about_box(heraia_struct_t *main_struct)
00265  *  Record position and hide about dialog box
00266  * @param [in,out] main_struct : main structure
00267  */
00268 static void record_and_hide_about_box(heraia_struct_t *main_struct)
00269 {
00270     GtkWidget *about_dialog = NULL;
00271 
00272     about_dialog = heraia_get_widget(main_struct->xmls->main, "about_dialog");
00273 
00274     if (about_dialog != NULL)
00275         {
00276             record_and_hide_dialog_box(about_dialog, main_struct->win_prop->about_box);
00277         }
00278 }
00279 
00280 
00281 /**
00282  * @fn void a_propos_response(GtkWidget *widget, gint response, gpointer data)
00283  *  To close the A propos dialog box (with the "close" button)
00284  * @param widget : calling widget (may be NULL as we don't use this)
00285  * @param response : may be whatever you want as we neither use this !
00286  * @param data : MUST be heraia_struct_t *main_struct main structure
00287  */
00288 static void a_propos_response(GtkWidget *widget, gint response, gpointer data)
00289 {
00290     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00291     record_and_hide_about_box(main_struct);
00292 }
00293 
00294 
00295 /**
00296  * @fn void a_propos_close(GtkWidget *widget, gpointer data)
00297  *  To close the A propos dialog box
00298  * @param widget : calling widget (may be NULL as we don't use this)
00299  * @param data : MUST be heraia_struct_t *main_struct main structure
00300  */
00301 static void a_propos_close(GtkWidget *widget, gpointer data)
00302 {
00303     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00304     record_and_hide_about_box(main_struct);
00305 }
00306 
00307 
00308 /**
00309  * @fn gboolean a_propos_delete(GtkWidget *widget, GdkEvent  *event, gpointer data)
00310  *  To close the A propos dialog box
00311  * @param widget : calling widget (may be NULL as we don't use this)
00312  * @param event : event associated (may be NULL as we don't use this)
00313  * @param data : MUST be heraia_struct_t *main_struct main structure
00314  * @return returns TRUE in order to allow other functions to do something with
00315  *         that event.
00316  */
00317 static gboolean a_propos_delete(GtkWidget *widget, GdkEvent  *event, gpointer data)
00318 {
00319     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00320     record_and_hide_about_box(main_struct);
00321 
00322     return TRUE;
00323 }
00324 
00325 
00326 /**
00327  * @fn void on_delete_activate(GtkWidget *widget, gpointer data)
00328  *  Delete, edit menu
00329  * @warning Not yet implemented
00330  * @todo Write a usefull function here :)
00331  * @param widget : the widget that issued the signal
00332  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00333  */
00334 void on_delete_activate(GtkWidget *widget, gpointer data)
00335 {
00336     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00337 
00338     log_message(main_struct, G_LOG_LEVEL_WARNING, "Not implemented Yet (Please contribute !)");
00339 }
00340 
00341 
00342 /**
00343  * @fn void on_cut_activate(GtkWidget *widget, gpointer data)
00344  *  Cut, edit menu
00345  * @warning Not yet implemented
00346  * @todo Write a usefull function here :)
00347  * @param widget : the widget that issued the signal
00348  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00349  */
00350 void on_cut_activate(GtkWidget *widget, gpointer data)
00351 {
00352     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00353 
00354     log_message(main_struct, G_LOG_LEVEL_WARNING, "Not implemented Yet (Please contribute !)");
00355 }
00356 
00357 
00358 /**
00359  * @fn void on_copy_activate( GtkWidget *widget, gpointer data )
00360  *  Copy, edit menu
00361  * @warning Not yet implemented
00362  * @todo Write a usefull function here :)
00363  * @param widget : the widget that issued the signal
00364  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00365  */
00366 void on_copy_activate(GtkWidget *widget, gpointer data)
00367 {
00368     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00369 
00370     log_message(main_struct, G_LOG_LEVEL_WARNING, "Not implemented Yet (Please contribute !)");
00371 }
00372 
00373 
00374 /**
00375  * @fn void on_paste_activate( GtkWidget *widget, gpointer data )
00376  *  Paste, edit menu
00377  * @warning Not yet implemented
00378  * @todo Write a usefull function here :)
00379  * @param widget : the widget that issued the signal
00380  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00381  */
00382 void on_paste_activate(GtkWidget *widget, gpointer data)
00383 {
00384     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00385 
00386     log_message(main_struct, G_LOG_LEVEL_WARNING, "Not implemented Yet (Please contribute !)");
00387 }
00388 
00389 
00390 /**
00391  *  This function is refreshing the labels on the main
00392  *  window in order to reflect cursor position, selected
00393  *  positions and total selected size.
00394  *  It is also used to refresh the file label on the tab.
00395  * @param main_struct : main structure
00396  */
00397 void refresh_file_labels(heraia_struct_t *main_struct)
00398 {
00399     GtkWidget *position_label = NULL;
00400     GtkWidget *file_size_label = NULL;
00401     GtkWidget *file_sel_label = NULL;
00402     GtkWidget *file_sel_size_label = NULL;
00403     guint64 position = 0;
00404     guint64 file_size = 0;
00405     selection_t *sel = NULL;
00406     gchar *position_text = NULL;
00407     gchar *file_size_text = NULL;
00408     gchar *file_sel_text = NULL;
00409     gchar *file_sel_size_text = NULL;
00410 
00411     if (main_struct != NULL)
00412         {
00413             position_label = heraia_get_widget(main_struct->xmls->main, "file_position_label");
00414             file_size_label = heraia_get_widget(main_struct->xmls->main, "file_size_label");
00415             file_sel_label = heraia_get_widget(main_struct->xmls->main, "file_selection_label");
00416             file_sel_size_label = heraia_get_widget(main_struct->xmls->main, "file_selection_size_label");
00417 
00418             if (main_struct->current_doc != NULL && main_struct->current_doc->hex_widget != NULL)
00419                 {
00420                     position = ghex_get_cursor_position(main_struct->current_doc->hex_widget);
00421                     file_size = ghex_file_size((Heraia_Hex *) main_struct->current_doc->hex_widget);
00422                     sel = ghex_get_selection(main_struct->current_doc->hex_widget);
00423 
00424                     /* position begins at 0 and this is not really human readable */
00425                     /* it's more confusing than anything so we do + 1             */
00426                     /* To translators : do not translate <small> and such         */
00427                     if (is_toggle_button_activated(main_struct->xmls->main, "mp_thousand_bt") == TRUE)
00428                         {
00429                             position_text = g_strdup_printf("<small>%'lld</small>", position + 1);
00430                             file_size_text = g_strdup_printf("<small>%'lld</small>", file_size);
00431                             file_sel_text = g_strdup_printf("<small>%'lld -> %'lld</small>", sel->start + 1, sel->end + 1);
00432                             file_sel_size_text = g_strdup_printf("<small>%'lld</small>", (sel->end - sel->start) + 1);
00433                         }
00434                     else
00435                         {
00436                             position_text = g_strdup_printf("<small>%lld</small>", position + 1);
00437                             file_size_text = g_strdup_printf("<small>%lld</small>", file_size);
00438                             file_sel_text = g_strdup_printf("<small>%lld - %lld</small>", sel->start, sel->end);
00439                             file_sel_size_text = g_strdup_printf("<small>%lld</small>", (sel->end - sel->start));
00440                         }
00441 
00442                     gtk_label_set_markup(GTK_LABEL(position_label), position_text);
00443                     gtk_label_set_markup(GTK_LABEL(file_size_label), file_size_text);
00444                     gtk_label_set_markup(GTK_LABEL(file_sel_label), file_sel_text);
00445                     gtk_label_set_markup(GTK_LABEL(file_sel_size_label), file_sel_size_text);
00446 
00447                     g_free(position_text);
00448                     g_free(file_size_text);
00449                     g_free(file_sel_text);
00450                     g_free(file_sel_size_text);
00451                     g_free(sel);
00452 
00453                     /* refreshing the tab filename itself if necessary only ! */
00454                     if (main_struct->current_doc->modified != main_struct->current_doc->hex_doc->changed)
00455                         {
00456                             main_struct->current_doc->modified = main_struct->current_doc->hex_doc->changed;
00457                             set_notebook_tab_label_color(main_struct, main_struct->current_doc->hex_doc->changed);
00458                         }
00459 
00460                 }
00461             else
00462                 {
00463                     gtk_label_set_text(GTK_LABEL(position_label), "");
00464                     gtk_label_set_text(GTK_LABEL(file_size_label), "");
00465                     gtk_label_set_text(GTK_LABEL(file_sel_label), "");
00466                     gtk_label_set_text(GTK_LABEL(file_sel_size_label), "");
00467                 }
00468         }
00469 }
00470 
00471 
00472 /**
00473  *  This function is here to ensure that everything will be
00474  *  refreshed upon a signal event.
00475  * @warning This function is not thread safe (do not use in a thread)
00476  * @todo try to put some mutexes on main_struct->event to make this
00477  *       thread safe some way
00478  * @param widget : the widget that issued the signal
00479  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00480  */
00481 void refresh_event_handler(GtkWidget *widget, gpointer data)
00482 {
00483     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00484 
00485     if (main_struct != NULL)
00486         {
00487             /* Beware, this mechanism is not thread safe ! */
00488             if (main_struct->event == HERAIA_REFRESH_NOTHING)
00489                 {
00490                     main_struct->event = HERAIA_REFRESH_CURSOR_MOVE;
00491                 }
00492 
00493             refresh_data_interpretor_window(widget, main_struct);
00494             refresh_all_plugins(main_struct);
00495             refresh_file_labels(main_struct);
00496 
00497             main_struct->event = HERAIA_REFRESH_NOTHING;
00498         }
00499 }
00500 
00501 
00502 /**
00503  *  This handles the menuitem "Ouvrir" to open a file
00504  * @warning This function is not thread safe (do not use in a thread)
00505  * @todo try to put some mutexes on main_struct->event to make this
00506  *       thread safe some way
00507  * @param widget : the widget that issued the signal
00508  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00509  */
00510 void on_open_activate(GtkWidget *widget, gpointer data)
00511 {
00512     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00513     GSList *list = NULL;
00514     GSList *head = NULL;
00515     gboolean success = FALSE;
00516 
00517     list = select_file_to_load(main_struct);
00518 
00519     if (list != NULL)
00520         {
00521             head = list;
00522             while (list != NULL)
00523                 {
00524                     success = load_file_to_analyse(main_struct, list->data);
00525                     g_free(list->data);
00526                     list = g_slist_next(list);
00527                 }
00528 
00529             g_slist_free(head);
00530 
00531             if (success == TRUE && main_struct->current_doc != NULL)
00532                  {
00533                     /* Not thread safe here ? */
00534                     main_struct->event = HERAIA_REFRESH_NEW_FILE;
00535                     refresh_event_handler(main_struct->current_doc->hex_widget, main_struct);
00536                  }
00537         }
00538 }
00539 
00540 
00541 /**
00542  * @fn void on_save_activate(GtkWidget *widget, gpointer data)
00543  *  Here we attemp to save the edited file
00544  *  @todo be more accurate on error (error type, message and filename) returns
00545  *        we should return something at least ...
00546  * @param widget : the widget that issued the signal
00547  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00548  */
00549 void on_save_activate(GtkWidget *widget, gpointer data)
00550 {
00551     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00552     HERAIA_ERROR erreur = HERAIA_NOERR;
00553     gchar *filename = NULL;
00554 
00555     if (main_struct != NULL && main_struct->current_doc != NULL)
00556         {
00557             erreur = heraia_hex_document_save(main_struct->current_doc);
00558 
00559             if (erreur != HERAIA_NOERR)
00560                 {
00561                     filename = doc_t_document_get_filename(main_struct->current_doc);
00562                     log_message(main_struct, G_LOG_LEVEL_ERROR, "Error while saving file %s !", filename);
00563                 }
00564             else
00565                 {
00566                     set_notebook_tab_label_color(main_struct, FALSE);
00567                     main_struct->current_doc->modified = FALSE; /* document has just been saved (thus it is not modified !) */
00568                 }
00569         }
00570 }
00571 
00572 
00573 /**
00574  * @fn void on_save_as_activate(GtkWidget *widget, gpointer data)
00575  *  This handle the save_as menu entry (here the filename changes)
00576  * @param widget : the widget that issued the signal
00577  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00578  */
00579 void on_save_as_activate(GtkWidget *widget, gpointer data)
00580 {
00581     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00582     HERAIA_ERROR erreur = HERAIA_NOERR;
00583     gchar *filename = NULL;  /**< Auto malloc'ed, do not free */
00584 
00585     if (main_struct != NULL && main_struct->current_doc != NULL)
00586         {
00587             filename = select_a_file_to_save(main_struct);
00588 
00589             if (filename != NULL)
00590                 {
00591                     erreur = heraia_hex_document_save_as(main_struct->current_doc, filename);
00592                 }
00593             else
00594                 {
00595                     erreur = HERAIA_CANCELLED;
00596                 }
00597 
00598             if (erreur != HERAIA_NOERR)
00599                 {
00600                     if (erreur == HERAIA_CANCELLED)
00601                         {
00602                             log_message(main_struct, G_LOG_LEVEL_DEBUG, "Saving file as... : operation cancelled.");
00603                         }
00604                     else
00605                         {
00606                             log_message(main_struct, G_LOG_LEVEL_ERROR, "Error while saving file as %s", doc_t_document_get_filename(main_struct->current_doc));
00607                         }
00608                 }
00609             else
00610                 {
00611                     /* updating the window name and tab's name */
00612                     update_main_struct_name(main_struct);
00613                     set_notebook_tab_name(main_struct);
00614                     main_struct->current_doc->modified = FALSE; /* document has just been saved (thus it is not modified !) */
00615                     log_message(main_struct, G_LOG_LEVEL_DEBUG, "File %s saved and now edited.", doc_t_document_get_filename(main_struct->current_doc));
00616                 }
00617         }
00618 }
00619 
00620 
00621 /**
00622  * @fn void on_DIMenu_activate(GtkWidget *widget, gpointer data)
00623  *  This handles the menuitem "Data Interpretor" that
00624  *  shows or hides the data interpretor window
00625  * @param widget : the widget that issued the signal
00626  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00627  */
00628 void on_DIMenu_activate(GtkWidget *widget, gpointer data)
00629 {
00630 
00631     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00632     data_window_t *dw = NULL;      /**< data_window structure for data interpretor */
00633     GtkNotebook *notebook = NULL;  /**< data interpretor's notebook                */
00634 
00635     if (main_struct != NULL)
00636         {
00637             dw = main_struct->current_DW;
00638 
00639             if (dw != NULL)
00640                 {
00641                     if (dw->diw == NULL)
00642                         {
00643                             dw->diw = heraia_get_widget(main_struct->xmls->main, "data_interpretor_window");
00644                         }
00645 
00646                     if (dw->diw != NULL)
00647                         {
00648                             notebook = GTK_NOTEBOOK(heraia_get_widget(main_struct->xmls->main, "diw_notebook"));
00649 
00650                             if (main_struct->win_prop->data_interpretor->displayed == FALSE)
00651                                 {
00652                                     /* Setting the first page of the notebook as default (Numbers) */
00653                                     gtk_notebook_set_current_page(notebook, dw->tab_displayed);
00654 
00655                                     /* moving to the right position */
00656                                     move_and_show_dialog_box(dw->diw, main_struct->win_prop->data_interpretor);
00657 
00658                                     refresh_data_interpretor_window(widget, data);
00659                                 }
00660                             else
00661                                 {
00662                                     /* recording some prefs from the dialog : position + opened tab */
00663                                     dw->tab_displayed = gtk_notebook_get_current_page(notebook);
00664                                     record_and_hide_dialog_box(dw->diw, main_struct->win_prop->data_interpretor);
00665                                 }
00666                         }
00667                 }
00668         }
00669 }
00670 
00671 
00672 /**
00673  * Called when tests submenu is activated
00674  * @param widget : the widget that issued the signal
00675  * @param data : user data MUST be heraia_struct_t *main_struct main structure
00676  */
00677 void on_tests_menu_activate(GtkWidget *widget, gpointer data)
00678 {
00679     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00680     gboolean result = FALSE;
00681 
00682     if (main_struct != NULL)
00683         {
00684             result = tests_ui(main_struct);
00685 
00686             if (result == TRUE)
00687                 {
00688                     log_message(main_struct, G_LOG_LEVEL_INFO, "All tests went Ok.");
00689                 }
00690             else
00691                 {
00692                     log_message(main_struct, G_LOG_LEVEL_WARNING, "Some tests failed.");
00693                 }
00694         }
00695 }
00696 
00697 
00698 /**
00699  * @fn delete_main_struct_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00700  *  When the user destroys or delete the main window
00701  * @param widget : calling widget
00702  * @param event : event associated (may be NULL as we don't use this here)
00703  * @param data : MUST be heraia_struct_t *main_struct main structure
00704  */
00705 gboolean delete_main_struct_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00706 {
00707 
00708     on_quit_activate(widget, data);
00709 
00710     return FALSE;
00711 }
00712 
00713 
00714 /**
00715  * @fn gboolean delete_dt_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00716  *  call back function for the data interpretor window destruction
00717  * @param widget : calling widget (may be NULL as we don't use this here)
00718  * @param event : event associated (may be NULL as we don't use this here)
00719  * @param data : MUST be heraia_struct_t *main_struct main structure and not NULL
00720  */
00721 gboolean delete_dt_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00722 {
00723     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00724 
00725     g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
00726 
00727     return TRUE;
00728 }
00729 
00730 
00731 /**
00732  * @fn void destroy_dt_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00733  *  call back function for the data interpretor window destruction
00734  * @param widget : calling widget (may be NULL as we don't use this here)
00735  * @param event : event associated (may be NULL as we don't use this here)
00736  * @param data : MUST be heraia_struct_t *main_struct main structure and not NULL
00737  */
00738 void destroy_dt_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00739 {
00740     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00741 
00742     g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
00743 }
00744 
00745 
00746 /**
00747  * What to do when a change occurs in tabs (user selected a particular
00748  * tab
00749  * @param notebook : the widget that issued this signal
00750  * @param page : the new current page
00751  * @param tab_num : index of this page
00752  * @param data : MUST be heraia_struct_t *main_struct !
00753  */
00754 gboolean file_notebook_tab_changed(GtkNotebook *notebook, GtkNotebookPage *page, gint tab_num, gpointer data)
00755 {
00756     heraia_struct_t *main_struct = (heraia_struct_t *) data;
00757 
00758     if (main_struct != NULL)
00759         {
00760             main_struct->current_doc = g_ptr_array_index(main_struct->documents, tab_num);
00761             update_main_struct_name(main_struct);
00762             main_struct->event = HERAIA_REFRESH_TAB_CHANGED;
00763             refresh_event_handler(GTK_WIDGET(notebook), main_struct);
00764             main_struct->event = HERAIA_REFRESH_NOTHING;
00765 
00766         }
00767 
00768     return TRUE;
00769 }
00770 
00771 /* End of call back functions that handle the data interpretor window */
00772 
00773 
00774 /**
00775  * @fn static gchar *make_absolute_path(gchar *filename)
00776  *  Returns an absolute path to the filename
00777  *  the string should be freed when no longer needed
00778  *  very UGLy !
00779  * @todo do something without any system calls !!!
00780  * @param filename : relative notation filename from which to extract an
00781  *        absolute path
00782  * @return returns a string with the absolute path which should be freed when
00783  *         no longer needed
00784  */
00785 static gchar *make_absolute_path(gchar *filename)
00786 {
00787     gchar *current_dir = NULL;
00788     gchar *new_dir = NULL;
00789 
00790     if (g_path_is_absolute(filename) == TRUE)
00791         {
00792             /* if the filename is already in an absolute format */
00793             return  g_path_get_dirname(filename);
00794         }
00795     else
00796         {
00797             current_dir = g_get_current_dir();
00798             new_dir = g_path_get_dirname(filename);
00799 
00800             if (g_chdir(new_dir) == 0)
00801                 {
00802                     g_free(new_dir);
00803                     new_dir = g_get_current_dir();
00804                     g_chdir(current_dir);
00805                     g_free(current_dir);
00806 
00807                     return new_dir;
00808                 }
00809             else
00810                 {
00811                     g_free(current_dir);
00812 
00813                     return NULL;
00814                 }
00815         }
00816 }
00817 
00818 
00819 /**
00820  *  Sets the working directory for the file chooser to the directory of the
00821  *  filename (even if filename is a relative filename such as ../docs/test_file)
00822  * @param file_chooser : An initialized GtkFileChooser
00823  * @param filename : a filename (one previously openned)
00824  */
00825 void set_the_working_directory(GtkFileChooser *file_chooser, gchar *filename)
00826 {
00827     gchar *dirname = NULL;    /**< directory where we want to be, at first, in the file chooser */
00828 
00829     dirname = make_absolute_path(filename);
00830 
00831     if (dirname != NULL)
00832         {
00833             gtk_file_chooser_set_current_folder(file_chooser, dirname);
00834             g_free(dirname);
00835         }
00836 }
00837 
00838 
00839 /**
00840  *  This function does open a file selector dialog box and returns the selected
00841  *  filename.
00842  * @param main_struct : main structure
00843  * @return returns a list of filenames to be loaded (if any)
00844  */
00845 GSList *select_file_to_load(heraia_struct_t *main_struct)
00846 {
00847     GtkWidget *parent = NULL; /**< A parent window (we use main_struct)            */
00848     GtkFileChooser *file_chooser = NULL;
00849     GSList *list = NULL;   /**< list of selected (if any) filenames to be openned  */
00850 
00851     parent = heraia_get_widget(main_struct->xmls->main, "main_window");
00852 
00853     file_chooser = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new("Select a file to analyse",
00854                                                                 GTK_WINDOW(parent),
00855                                                                 GTK_FILE_CHOOSER_ACTION_OPEN,
00856                                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00857                                                                 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
00858                                                                 NULL));
00859 
00860     /**
00861      *  for the moment we do not want to retrieve multiples selections
00862      *  but this could be a valuable thing in the future
00863      */
00864     gtk_window_set_modal(GTK_WINDOW(file_chooser), TRUE);
00865     gtk_file_chooser_set_select_multiple(file_chooser, TRUE);
00866 
00867     /**
00868      *  We want the file selection path to be the one of the previous
00869      *  openned file if any !
00870      */
00871     if (doc_t_document_get_filename(main_struct->current_doc) != NULL)
00872        {
00873             set_the_working_directory(file_chooser, doc_t_document_get_filename(main_struct->current_doc));
00874        }
00875 
00876     switch (gtk_dialog_run(GTK_DIALOG(file_chooser)))
00877         {
00878             case GTK_RESPONSE_OK:
00879 
00880                 list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(file_chooser));
00881                 gtk_widget_destroy(GTK_WIDGET(file_chooser));
00882 
00883                 return list;
00884              break;
00885 
00886             case GTK_RESPONSE_CANCEL:
00887             default:
00888                 gtk_widget_destroy(GTK_WIDGET(file_chooser));
00889 
00890                 return NULL;
00891              break;
00892         }
00893 }
00894 
00895 
00896 /**
00897  * @fn gchar *select_a_file_to_save(heraia_struct_t *main_struct)
00898  *  This function opens a dialog box that allow one to choose a
00899  *  file name to the file which is about to be saved
00900  * @param main_struct : main structure
00901  * @return returns complete filename (path and filename)
00902  */
00903 gchar *select_a_file_to_save(heraia_struct_t *main_struct)
00904 {
00905     GtkWidget *parent = NULL;     /**< A parent window (we use main_struct) */
00906     GtkFileChooser *fcd = NULL;
00907     gchar *filename = NULL;
00908 
00909     parent = heraia_get_widget(main_struct->xmls->main, "main_window");
00910 
00911     /* Selection a name to the file to save */
00912     fcd = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new("Save As...",
00913                                                        GTK_WINDOW(parent),
00914                                                        GTK_FILE_CHOOSER_ACTION_SAVE,
00915                                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00916                                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
00917                                                        NULL));
00918 
00919     /* window properties : modal, without multi-selection and with confirmation */
00920     gtk_window_set_modal(GTK_WINDOW(fcd), TRUE);
00921     gtk_file_chooser_set_select_multiple(fcd, FALSE);
00922     gtk_file_chooser_set_do_overwrite_confirmation(fcd, TRUE);
00923 
00924     /* we do want to have the file's directory where to save the new file */
00925     if (doc_t_document_get_filename(main_struct->current_doc) != NULL)
00926        {
00927             set_the_working_directory(fcd, doc_t_document_get_filename(main_struct->current_doc));
00928        }
00929 
00930     switch(gtk_dialog_run(GTK_DIALOG(fcd)))
00931         {
00932             case GTK_RESPONSE_OK:
00933                 /* retrieving the filename */
00934                 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fcd));
00935                 break;
00936             default:
00937                 filename = NULL;
00938                 break;
00939         }
00940 
00941     gtk_widget_destroy(GTK_WIDGET(fcd));
00942 
00943     return filename;
00944 }
00945 
00946 
00947 /**
00948  * @fn void update_main_struct_name(heraia_struct_t *main_struct)
00949  *  Update main window heraia's name to reflect the current edited file
00950  * @param main_struct : main structure
00951  */
00952 void update_main_struct_name(heraia_struct_t *main_struct)
00953 {
00954     GtkWidget *widget = NULL;
00955     gchar *filename = NULL;
00956     gchar *whole_filename = NULL;
00957 
00958     if (main_struct != NULL && main_struct->current_doc != NULL)
00959        {
00960             widget = heraia_get_widget(main_struct->xmls->main, "main_window");
00961 
00962             whole_filename = doc_t_document_get_filename(main_struct->current_doc);
00963 
00964             filename = g_filename_display_basename(whole_filename);
00965 
00966             gtk_window_set_title(GTK_WINDOW(widget), filename);
00967        }
00968 }
00969 
00970 
00971 /**
00972  *  Sets notebook's tab's name. This function should only be called
00973  *  when a new filename was set (open and save as functions)
00974  * @param main_struct : main structure
00975  */
00976 void set_notebook_tab_name(heraia_struct_t *main_struct)
00977 {
00978     GtkWidget *notebook = NULL; /* file notebook in main window       */
00979     GtkWidget *page = NULL;     /* Current page for the file notebook */
00980     GtkWidget *label = NULL;    /* tab's label                        */
00981     doc_t *doc = NULL;          /* corresponding tab's document       */
00982     gchar *filename = NULL;
00983     gchar *whole_filename;
00984     gint current = 0;           /* index of the current tab displayed */
00985      gchar *markup= NULL;       /* markup text                        */
00986 
00987     if (main_struct != NULL && main_struct->current_doc != NULL)
00988        {
00989            notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
00990            current = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
00991            page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), current);
00992            label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
00993 
00994            doc = g_ptr_array_index(main_struct->documents, current);
00995            whole_filename = doc_t_document_get_filename(doc);
00996 
00997            if (whole_filename != NULL)
00998                {
00999                     filename = g_filename_display_basename(whole_filename);
01000                     markup =  g_markup_printf_escaped("%s", filename);
01001                     gtk_label_set_markup(GTK_LABEL(label), markup);
01002                     gtk_widget_set_tooltip_text(label, g_filename_display_name(whole_filename));
01003                     g_free(markup);
01004                }
01005        }
01006 }
01007 
01008 
01009 /**
01010  * Set the style for the label
01011  * @param main_struct : main structure
01012  * @param color : If color is TRUE sets the color for the file tab's label
01013  *                If not, then sets it to default
01014  */
01015 void set_notebook_tab_label_color(heraia_struct_t *main_struct, gboolean color)
01016 {
01017     GtkWidget *notebook = NULL; /* file notebook in main window       */
01018     GtkWidget *page = NULL;     /* Current page for the file notebook */
01019     GtkWidget *label = NULL;    /* tab's label                        */
01020     gint current = 0;           /* index of the current tab displayed */
01021     gchar *markup= NULL;        /* markup text                        */
01022     gchar *text = NULL;         /* label's text                       */
01023 
01024     if (main_struct != NULL && main_struct->current_doc != NULL)
01025         {
01026             notebook = heraia_get_widget(main_struct->xmls->main, "file_notebook");
01027             current = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
01028             page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), current);
01029             label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
01030 
01031             text = g_strdup(gtk_label_get_text(GTK_LABEL(label)));
01032 
01033             if (color == TRUE)
01034                 {
01035                     markup = g_markup_printf_escaped("<span foreground=\"blue\">%s</span>", text);
01036                 }
01037             else
01038                 {
01039                     markup = g_markup_printf_escaped("%s", text);
01040                 }
01041 
01042             log_message(main_struct, G_LOG_LEVEL_DEBUG, "Changing color for filename %s in tab : %d", markup, current);
01043             gtk_label_set_markup(GTK_LABEL(label), markup);
01044             g_free(markup);
01045             g_free(text);
01046         }
01047 }
01048 
01049 
01050 /**
01051  * Hides or grey all widgets that needs an open file when boolean show is
01052  * FALSE
01053  * @param main : main GtkBuilder XML structure
01054  * @param greyed : boolean (TRUE to hide an grey widgets)
01055  */
01056 void grey_main_widgets(GtkBuilder *main, gboolean greyed)
01057 {
01058     GtkWidget *notebook = NULL;  /* file notebook in main window */
01059 
01060     if (main != NULL)
01061         {
01062             notebook = heraia_get_widget(main, "file_notebook");
01063             gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
01064 
01065             if (greyed == TRUE)
01066                 {
01067                     gtk_widget_set_sensitive(heraia_get_widget(main, "save"), FALSE);
01068                     gtk_widget_set_sensitive(heraia_get_widget(main, "save_as"), FALSE);
01069                     gtk_widget_hide(notebook);
01070                 }
01071             else
01072                 {
01073                     gtk_widget_set_sensitive(heraia_get_widget(main, "save"), TRUE);
01074                     gtk_widget_set_sensitive(heraia_get_widget(main, "save_as"), TRUE);
01075                     gtk_widget_show_all(notebook);
01076                 }
01077         }
01078 }
01079 
01080 
01081 /**
01082  *  Here we might init some call backs and menu options
01083  *  and display the interface (main && sub-windows)
01084  *  This function should be called only once at main program's
01085  *  init time
01086  * @param main_struct : main structure
01087  */
01088 void init_heraia_interface(heraia_struct_t *main_struct)
01089 {
01090 
01091     if (main_struct != NULL)
01092         {
01093             /* inits window states (shows or hide windows) */
01094             init_window_states(main_struct);
01095 
01096             if (main_struct->current_doc != NULL)
01097                 {
01098                     grey_main_widgets(main_struct->xmls->main, FALSE);
01099                 }
01100             else
01101                 {
01102                     grey_main_widgets(main_struct->xmls->main, TRUE);
01103                 }
01104 
01105             refresh_file_labels(main_struct);
01106         }
01107 }
01108 
01109 
01110 /**
01111  *  Loads the GtkBuilder xml files that describes the heraia project
01112  *  tries the following paths in that order :
01113  *  - /etc/heraia/heraia.gtkbuilder
01114  *  - /home/[user]/.heraia/heraia.gtkbuilder
01115  *  - PWD/heraia.gtkbuilder
01116  * @param main_struct : main structure
01117  * @return TRUE if everything went ok, FALSE otherwise
01118  */
01119 static gboolean load_heraia_xml(heraia_struct_t *main_struct)
01120 {
01121     gchar *filename = NULL;
01122 
01123     if (main_struct != NULL && main_struct->xmls != NULL)
01124         {
01125             filename = g_strdup_printf("heraia.gtkbuilder");
01126             main_struct->xmls->main = load_xml_file(main_struct->location_list, filename);
01127             g_free(filename);
01128 
01129             if (main_struct->xmls->main == NULL)
01130                 {
01131                     return FALSE;
01132                 }
01133             else
01134                 {
01135                     return TRUE;
01136                 }
01137         }
01138     else
01139         {
01140             return FALSE;
01141         }
01142 }
01143 
01144 
01145 /**
01146  *  Connects the signal that the cursor has moved to
01147  *  the refreshing function
01148  * @param main_struct : main structure
01149  * @param hex_widget : the hex_widget we want to connect the signal to
01150  */
01151 void connect_cursor_moved_signal(heraia_struct_t *main_struct, GtkWidget *hex_widget)
01152 {
01153     g_signal_connect(G_OBJECT(hex_widget), "cursor_moved",
01154                      G_CALLBACK(refresh_event_handler), main_struct);
01155 }
01156 
01157 
01158 /**
01159  *  Connect the signals at the interface
01160  * @param main_struct : main structure
01161  */
01162 static void heraia_ui_connect_signals(heraia_struct_t *main_struct)
01163 {
01164 
01165     /* the data interpretor menu */
01166     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "DIMenu")), "activate",
01167                      G_CALLBACK(on_DIMenu_activate), main_struct);
01168 
01169     /* Quit, file menu */
01170     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "quit")), "activate",
01171                      G_CALLBACK(on_quit_activate), main_struct);
01172 
01173     /* New, file menu */
01174     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "new")), "activate",
01175                      G_CALLBACK(on_new_activate), main_struct);
01176 
01177     /* Open, file menu */
01178     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "open")), "activate",
01179                      G_CALLBACK(on_open_activate), main_struct);
01180 
01181     /* Save, file menu */
01182     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "save")), "activate",
01183                      G_CALLBACK(on_save_activate), main_struct);
01184 
01185     /* Save As, file menu */
01186     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "save_as")), "activate",
01187                      G_CALLBACK(on_save_as_activate), main_struct);
01188 
01189     /* Preferences, file menu ; See main_pref_window.c for main_pref_window's signals */
01190     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "preferences")), "activate",
01191                      G_CALLBACK(on_preferences_activate), main_struct);
01192 
01193     /* Cut, edit menu */
01194     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "cut")), "activate",
01195                      G_CALLBACK(on_cut_activate), main_struct);
01196 
01197     /* Copy, edit menu */
01198     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "copy")), "activate",
01199                      G_CALLBACK(on_copy_activate), main_struct);
01200 
01201     /* Paste, edit menu */
01202     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "paste")), "activate",
01203                      G_CALLBACK(on_paste_activate), main_struct);
01204 
01205     /* Delete, edit menu */
01206     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "delete")), "activate",
01207                      G_CALLBACK(on_delete_activate), main_struct);
01208 
01209     /* Test, Help menu */
01210     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "tests_menu")), "activate",
01211                      G_CALLBACK(on_tests_menu_activate), main_struct);
01212 
01213 
01214     /* about dialog box */
01215     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "a_propos")), "activate",
01216                      G_CALLBACK(a_propos_activate), main_struct);
01217 
01218     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "close",
01219                      G_CALLBACK(a_propos_close), main_struct);
01220 
01221     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "response",
01222                      G_CALLBACK(a_propos_response), main_struct);
01223 
01224     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "about_dialog")), "delete-event",
01225                      G_CALLBACK(a_propos_delete), main_struct);
01226 
01227 
01228     /* main notebook */
01229     g_signal_connect(G_OBJECT(heraia_get_widget(main_struct->xmls->main, "file_notebook")),"switch-page",
01230                      G_CALLBACK(file_notebook_tab_changed), main_struct);
01231 
01232 
01233     /* main window killed or destroyed */
01234     g_signal_connect(G_OBJECT (heraia_get_widget(main_struct->xmls->main, "main_window")), "delete-event",
01235                      G_CALLBACK(delete_main_struct_event), main_struct);
01236 }
01237 
01238 
01239 /** @fn int load_heraia_ui(heraia_struct_t *main_struct)
01240  *  Loads, if possible, the gtkbuilder xml file and then connects the
01241  *  signals and inits the following windows :
01242  *  - log window
01243  *  - data_interpretor window
01244  *  - list data types
01245  * @param main_struct : main structure
01246  * @return TRUE if load_heraia_xml suceeded, FALSE otherwise
01247  * @todo add more return values to init functions to detect any error while
01248  *       initializing the ui
01249  */
01250 int load_heraia_ui(heraia_struct_t *main_struct)
01251 {
01252     gboolean success = FALSE;
01253 
01254     /* load the XML interfaces (main & treatment) */
01255     success = load_heraia_xml(main_struct);
01256 
01257     if (success == TRUE)
01258         {
01259             /* Heraia UI signals */
01260             if (main_struct->debug == TRUE)
01261                 {
01262                     fprintf(stdout, "Connecting heraia_ui signals     ");
01263                 }
01264 
01265             heraia_ui_connect_signals(main_struct);
01266 
01267             if (main_struct->debug == TRUE)
01268                 {
01269                     fprintf(stdout, " [Done]\n");
01270                 }
01271 
01272             /* The Log window */
01273             if (main_struct->debug == TRUE)
01274                 {
01275                     fprintf(stdout, "log window init interface        ");
01276                 }
01277 
01278             log_window_init_interface(main_struct);
01279 
01280             if (main_struct->debug == TRUE)
01281                 {
01282                     fprintf(stdout, " [Done]\n");
01283                 }
01284 
01285             /* Preferences window */
01286             if (main_struct->debug == TRUE)
01287                 {
01288                     fprintf(stdout, "preferences window init interface");
01289                 }
01290 
01291             main_pref_window_init_interface(main_struct);
01292 
01293             if (main_struct->debug == TRUE)
01294                 {
01295                     fprintf(stdout, " [Done]\n");
01296                 }
01297 
01298 
01299             /* The data interpretor window */
01300             if (main_struct->debug == TRUE)
01301                 {
01302                     fprintf(stdout, "data interpretor init interface  ");
01303                 }
01304 
01305             data_interpretor_init_interface(main_struct);
01306 
01307             if (main_struct->debug == TRUE)
01308                 {
01309                     fprintf(stdout, " [Done]\n");
01310                 }
01311 
01312 
01313             /* preferences file */
01314 
01315             fprintf(stdout, "Loading heraia preference file   ");
01316 
01317             if (load_preference_file(main_struct) != TRUE)
01318                 {
01319                     fprintf(stdout, " [FAILED]\n");
01320                 }
01321             else /* Setting up preferences */
01322                 {
01323                     fprintf(stdout, " [Done]\n");
01324                     fprintf(stdout, "Setting up preferences           ");
01325                     load_preferences(main_struct);
01326                     fprintf(stdout, " [Done]\n");
01327                 }
01328         }
01329 
01330     return success;
01331 }
01332 
01333 
01334 /**
01335  * @fn void add_text_to_textview(GtkTextView *textview, const char *format, ...)
01336  *  adds a text to a textview
01337  * @param textview : the textview where to add text
01338  * @param format : printf style format
01339  * @param ... : a va_list arguments to fit format (as with printf)
01340  */
01341 void add_text_to_textview(GtkTextView *textview, const char *format, ...)
01342 {
01343     va_list args;
01344     GtkTextBuffer *tb = NULL;
01345     GtkTextIter iEnd;
01346     gchar *display = NULL;
01347     GError *err = NULL;
01348 
01349     va_start(args, format);
01350     display = g_locale_to_utf8(g_strdup_vprintf(format, args), -1, NULL, NULL, &err);
01351     va_end(args);
01352 
01353     tb = GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)));
01354     gtk_text_buffer_get_end_iter(tb, &iEnd);
01355     gtk_text_buffer_insert(tb, &iEnd, display, -1);
01356     g_free(display);
01357 }
01358 
01359 
01360 /**
01361  * @fn kill_text_from_textview(GtkTextView *textview)
01362  *  Kills the text from a textview
01363  * @param textview : the textview to kill the text from
01364  */
01365 void kill_text_from_textview(GtkTextView *textview)
01366 {
01367     GtkTextBuffer *tb = NULL;
01368     GtkTextIter iStart;
01369     GtkTextIter iEnd;
01370 
01371     tb = GTK_TEXT_BUFFER(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)));
01372     gtk_text_buffer_get_start_iter(tb, &iStart);
01373     gtk_text_buffer_get_end_iter(tb, &iEnd);
01374     gtk_text_buffer_delete (tb, &iStart, &iEnd);
01375 }
01376 
01377 
01378 /**
01379  * @fn GtkWidget *gtk_radio_button_get_active(GSList *group)
01380  *  Try to find the active radio button widget in a group
01381  *  This does not take into account inconsistant states
01382  *  returns the first active radio button otherwise NULL
01383  * @param group : A group of GtkRadioButtons
01384  * @return returns the active widget if any (NULL if none)
01385  */
01386 GtkWidget *gtk_radio_button_get_active(GSList *group)
01387 {
01388     GSList *tmp_slist = group;
01389 
01390     while (tmp_slist)
01391         {
01392             if (GTK_TOGGLE_BUTTON (tmp_slist->data)->active)
01393                 {
01394                     return GTK_WIDGET (tmp_slist->data);
01395                 }
01396             tmp_slist = tmp_slist->next;
01397         }
01398 
01399     return NULL;
01400 }
01401 
01402 
01403 /**
01404  * @fn GtkWidget *gtk_radio_button_get_active_from_widget(GtkRadioButton *radio_group_member)
01405  * gets the active radio button from a radio group
01406  * @param radio_group_member : widget to get radio group from
01407  * @returns the active GtkRadioButton within the group from
01408  *          radio_group_member
01409  **/
01410 GtkWidget *gtk_radio_button_get_active_from_widget(GtkRadioButton *radio_group_member)
01411 {
01412     if (radio_group_member)
01413         {
01414             return gtk_radio_button_get_active(radio_group_member->group);
01415         }
01416     else
01417         {
01418             return NULL;
01419         }
01420 }
01421 
01422 
01423 /**
01424  * @fn gboolean is_cmi_checked(GtkWidget *check_menu_item)
01425  *  Tells whether a GtkCheckMenuItem is Checked or not
01426  * @param check_menu_item : a GtkCheckMenuItem to verify
01427  * @return returns TRUE if the Check Manu Item is checked, FALSE otherwise
01428  */
01429 gboolean is_cmi_checked(GtkWidget *check_menu_item)
01430 {
01431     return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(check_menu_item));
01432 }
01433 
01434 
01435 /**
01436  * @fn gboolean is_toggle_button_activated(GtkBuilder *main_xml, gchar *check_button)
01437  *  returns the state of a named check button contained
01438  *  in the GtkBuilder XML description
01439  * @param main_xml : a GtkBuilder XML definition
01440  * @param check_button : the name of an existing check_button within the GtkBuilder
01441  *        definition
01442  * @return TRUE if the button is activated / toggled , FALSE otherwise
01443  */
01444 gboolean is_toggle_button_activated(GtkBuilder *main_xml, gchar *check_button)
01445 {
01446     gboolean activated = FALSE;
01447 
01448     if (main_xml != NULL)
01449         {
01450             activated = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(heraia_get_widget(main_xml, check_button)));
01451         }
01452 
01453     return activated;
01454 }
01455 
01456 
01457 /**
01458  * @fn GtkWidget *heraia_get_widget(GtkBuilder *xml, gchar *widget_name)
01459  *  This is a wrapper to the GtkBuilder xml get widget. It is intended
01460  *  to simplify the developpers lives if they have to choose or
01461  *  propose other means to do the same thing than libglade (say,
01462  *  for example, GtkBuilder ;-)
01463  * @param xml : A GtkBuilder XML definition
01464  * @param widget_name : an existing widget name in the GtkBuilder definition
01465  * @return returns the widget itself if it exists in the definition file (NULL
01466  *         otherwise)
01467  */
01468 GtkWidget *heraia_get_widget(GtkBuilder *xml, gchar *widget_name)
01469 {
01470    /**
01471     * For debug purposes only (very verbose as this function is the main used)
01472     * fprintf(stdout, "Getting Widget named %s\n", widget_name);
01473     */
01474 
01475     if (xml != NULL && widget_name != NULL)
01476         {
01477             return GTK_WIDGET(gtk_builder_get_object(xml, widget_name));
01478         }
01479     else
01480         {
01481             return NULL;
01482         }
01483 }
01484 
01485 
01486 /**
01487  * @fn void destroy_a_single_widget(GtkWidget *widget)
01488  *  Destroys a single widget if it exists
01489  * @param widget : the widget to destroy
01490  */
01491 void destroy_a_single_widget(GtkWidget *widget)
01492 {
01493     if (widget != NULL)
01494         {
01495             gtk_widget_destroy(widget);
01496         }
01497 }
01498 
01499 
01500 /**
01501  * Verify if we can safely close everything
01502  * @param main_struct : main structure
01503  * @return a boolean which is TRUE if unsaved documents still exists and FALSE
01504  *         otherwise
01505  */
01506 static gboolean unsaved_documents(heraia_struct_t *main_struct)
01507 {
01508     doc_t *current_doc = NULL;
01509     gboolean result = FALSE;
01510     guint i = 0;
01511 
01512     if (main_struct != NULL && main_struct->documents != NULL)
01513         {
01514             for(i = 0; i < main_struct->documents->len; i++)
01515                 {
01516                     current_doc =  g_ptr_array_index(main_struct->documents, i);
01517                     result = result | current_doc->modified;
01518                 }
01519 
01520             return result;
01521         }
01522 
01523     return result;
01524 }
01525 
01526 
01527 /**
01528  * @fn void close_heraia(heraia_struct_t *main_struct)
01529  * Before closing heraia we need to do few things
01530  * @param main_struct : main_struct
01531  * @return TRUE if we can safely quit heraia, FALSE otherwise
01532  */
01533 static gboolean close_heraia(heraia_struct_t *main_struct)
01534 {
01535     gboolean unsaved = FALSE;    /* if there is any unsaved documents */
01536     gboolean quit_heraia = TRUE; /* By default we want to quit        */
01537     GtkWidget *dialog = NULL;
01538     GtkWidget *label = NULL;
01539     GtkWidget *content_area = NULL;
01540     GtkWidget *parent = NULL;
01541     gint result = 0;
01542 
01543     unsaved = unsaved_documents(main_struct);
01544 
01545     if (unsaved == TRUE)
01546         {
01547             /* Displays a dialog box that let the user choose what to do */
01548             parent = heraia_get_widget(main_struct->xmls->main, "main_window");
01549             dialog = gtk_dialog_new_with_buttons(Q_("Unsaved document(s) remains."), GTK_WINDOW(parent), GTK_DIALOG_DESTROY_WITH_PARENT,
01550                                                  GTK_STOCK_YES, GTK_RESPONSE_YES,
01551                                                  GTK_STOCK_NO, GTK_RESPONSE_NO, NULL);
01552             content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
01553             gtk_container_set_border_width(GTK_CONTAINER(content_area), 4);
01554             label = gtk_label_new(Q_("Do you want to quit without saving ?"));
01555             gtk_container_add(GTK_CONTAINER(content_area), label);
01556             gtk_widget_show_all(dialog);
01557 
01558             gint result = gtk_dialog_run(GTK_DIALOG(dialog));
01559 
01560             switch (result)
01561                 {
01562                     case GTK_RESPONSE_YES:
01563                         quit_heraia = TRUE;
01564                     break;
01565 
01566                     default:
01567                         quit_heraia = FALSE;
01568                     break;
01569                 }
01570 
01571             gtk_widget_destroy(dialog);
01572         }
01573 
01574     if ( quit_heraia == TRUE)
01575         {
01576             /* recording window's position */
01577             record_all_dialog_box_positions(main_struct);
01578 
01579             /* . Saving preferences */
01580             save_preferences(main_struct);
01581         }
01582 
01583     return quit_heraia;
01584 }
01585 
01586 
01587 /**
01588  * @fn void init_one_cmi_window_state(GtkWidget *dialog_box, GtkWidget *cmi, window_prop_t *dialog_prop)
01589  * init one cmi window based state
01590  * @param dialog_box : the window or dialog box we want to init its state
01591  * @param cmi : corresponding check menu item
01592  * @param dialog_prop : corresponding window properties (should be initialized and not NULL)
01593  */
01594 static void init_one_cmi_window_state(GtkWidget *dialog_box, GtkWidget *cmi, window_prop_t *dialog_prop)
01595 {
01596     gboolean activated = FALSE;
01597 
01598     if (dialog_box != NULL && cmi != NULL && dialog_prop != NULL)
01599         {
01600             activated = dialog_prop->displayed;
01601             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(cmi), activated);
01602             if (activated == TRUE)
01603                 {
01604                     gtk_window_move(GTK_WINDOW(dialog_box), dialog_prop->x, dialog_prop->y);
01605                     gtk_window_resize(GTK_WINDOW(dialog_box), dialog_prop->width, dialog_prop->height);
01606                     gtk_widget_show_all(dialog_box);
01607                 }
01608         }
01609 }
01610 
01611 
01612 /**
01613  * @fn init_window_states(heraia_struct_t *main_struct)
01614  *  Inits all windows states (positions, displayed, and so on...)
01615  * @param main_struct : main structure
01616  */
01617 void init_window_states(heraia_struct_t *main_struct)
01618 {
01619     GtkWidget *cmi = NULL;
01620     GtkWidget *dialog_box = NULL;
01621 
01622     if (main_struct != NULL && main_struct->xmls != NULL  && main_struct->xmls->main != NULL)
01623         {
01624             if (main_struct->win_prop)
01625                 {
01626                     /* Main window (always the first one) */
01627                     dialog_box = heraia_get_widget(main_struct->xmls->main, "main_window");
01628                     if (main_struct->win_prop->main_dialog->displayed == TRUE)
01629                         {
01630                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->main_dialog->x, main_struct->win_prop->main_dialog->y);
01631                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->main_dialog->width, main_struct->win_prop->main_dialog->height);
01632                             gtk_widget_show(dialog_box);
01633                         }
01634 
01635                     /* Log Window Interface */
01636                     cmi = heraia_get_widget(main_struct->xmls->main, "mw_cmi_show_logw");
01637                     dialog_box = heraia_get_widget(main_struct->xmls->main, "log_window");
01638                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->log_box);
01639 
01640                     /* Data Interpretor Interface */
01641                     cmi = heraia_get_widget(main_struct->xmls->main, "DIMenu");
01642                     /* Emit the specific signal to activate the check_menu_item */
01643                     if (main_struct->win_prop->data_interpretor->displayed == TRUE)
01644                         {
01645                             main_struct->win_prop->data_interpretor->displayed = FALSE; /* dirty trick */
01646                             g_signal_emit_by_name(heraia_get_widget(main_struct->xmls->main, "DIMenu"), "activate");
01647                         }
01648 
01649                     /* List Data type Interface */
01650                     cmi = heraia_get_widget(main_struct->xmls->main, "ldt_menu");
01651                     dialog_box = heraia_get_widget(main_struct->xmls->main, "list_data_types_window");
01652                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->ldt);
01653 
01654                     /* Plugin List Interface */
01655                     cmi = heraia_get_widget(main_struct->xmls->main, "mw_cmi_plugin_list");
01656                     dialog_box = heraia_get_widget(main_struct->xmls->main, "plugin_list_window");
01657                     init_one_cmi_window_state(dialog_box, cmi, main_struct->win_prop->plugin_list);
01658 
01659                     /* Preferences window */
01660                     dialog_box = heraia_get_widget(main_struct->xmls->main, "main_preferences_window");
01661                     if (main_struct->win_prop->main_pref_window->displayed == TRUE)
01662                         {
01663                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->main_pref_window->x, main_struct->win_prop->main_pref_window->y);
01664                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->main_pref_window->width, main_struct->win_prop->main_pref_window->height);
01665                             gtk_widget_show_all(dialog_box);
01666                         }
01667 
01668                     /* About Box */
01669                     dialog_box = heraia_get_widget(main_struct->xmls->main, "about_dialog");
01670                     if (main_struct->win_prop->about_box->displayed == TRUE)
01671                         {
01672                             gtk_window_move(GTK_WINDOW(dialog_box), main_struct->win_prop->about_box->x, main_struct->win_prop->about_box->y);
01673                             gtk_window_resize(GTK_WINDOW(dialog_box), main_struct->win_prop->about_box->width, main_struct->win_prop->about_box->height);
01674                             set_a_propos_properties(dialog_box);
01675                             gtk_widget_show_all(dialog_box);
01676                         }
01677                 }
01678         }
01679 }
01680 
01681 /**
01682  *  Adds a new tab to the main window in file's notebook
01683  * @param main_struct : main structure
01684  * @param doc : the new document that will be related to the tab
01685  */
01686 void add_new_tab_in_main_struct(heraia_struct_t *main_struct, doc_t *doc)
01687 {
01688     GtkWidget *vbox = NULL;       /**< used for vbox creation               */
01689     GtkNotebook *notebook = NULL; /**< file_notebook from heraia.gtkbuilder */
01690     GtkWidget *tab_label = NULL;  /**< tab's label                          */
01691     gint tab_num = -1;            /**< new tab's index                      */
01692 
01693     notebook = GTK_NOTEBOOK(heraia_get_widget(main_struct->xmls->main, "file_notebook"));
01694     vbox = gtk_vbox_new(FALSE, 2);
01695     gtk_box_pack_start(GTK_BOX(vbox), doc->hex_widget, TRUE, TRUE, 3);
01696 
01697     tab_label = gtk_label_new(NULL);
01698 
01699     gtk_widget_show_all(vbox);
01700     tab_num = gtk_notebook_append_page(notebook, vbox, tab_label);
01701 
01702     gtk_notebook_set_current_page(notebook, tab_num);
01703     main_struct->current_doc = doc;
01704 }
01705 
01706 
01707 /**
01708  *  To help plugins to deal with widgets, shows or hide a specific widget
01709  * @param widget : the widget to show or hide
01710  * @param show : what to do : TRUE to show the widget, FALSE to hide it
01711  * @param win_prop : window properties.
01712  */
01713 void show_hide_widget(GtkWidget *widget, gboolean show, window_prop_t *win_prop)
01714 {
01715     if (win_prop != NULL)
01716             {
01717                 if (show)
01718                     {
01719                         move_and_show_dialog_box(widget, win_prop);
01720                     }
01721                 else
01722                     {
01723                         record_and_hide_dialog_box(widget, win_prop);
01724                     }
01725             }
01726         else
01727             {
01728                 if (show)
01729                     {
01730                         gtk_widget_show(widget);
01731                     }
01732                 else
01733                     {
01734                         gtk_widget_hide(widget);
01735                     }
01736             }
01737 }
Generated on Tue May 11 18:46:08 2010 for Heraia by  doxygen 1.6.3