/** * * * \param * \param * * \return * */ gint utils_gtkbuilder_merge_ui_data_in_builder ( GtkBuilder *builder, const gchar *ui_name ) { gchar *filename; gint result; GError *error = NULL; /* Chargement du XML dans bet_graph_builder */ filename = utils_gtkbuilder_get_full_path ( ui_name ); if ( !g_file_test ( filename, G_FILE_TEST_EXISTS ) ) { gchar* tmpstr; tmpstr = g_strdup_printf ( _("Cannot open file '%s': %s"), filename, _("File does not exist") ); dialogue_error ( tmpstr ); g_free ( tmpstr ); g_free ( filename ); return 0; } result = gtk_builder_add_from_file ( builder, filename, &error ); if ( result == 0 ) { g_error ("%s", error->message); g_error_free ( error ); } g_free ( filename ); return result; }
/** * return a new GtkBuilder initiate with a file * * \param gchar short name of UI file * * \return GtkBuilder new GtkBuildeR * */ GtkBuilder *utils_gtk_builder_new_from_file ( const gchar *ui_name ) { GtkBuilder *builder; gchar *filename; /* obtention du nom long du fichier UI */ filename = utils_gtkbuilder_get_full_path ( ui_name ); if ( !g_file_test ( filename, G_FILE_TEST_EXISTS ) ) { gchar* tmpstr; tmpstr = g_strdup_printf ( _("Cannot open file '%s': %s"), filename, _("File does not exist") ); dialogue_error ( tmpstr ); g_free ( tmpstr ); g_free ( filename ); return NULL; } builder = gtk_builder_new_from_file ( filename ); g_free ( filename ); return builder; }
/** * ajoute une nouvelle icone pour le compte passé en paramètre * * /param la chaine codée de l'icone * return TRUE if OK else FALSE * */ gboolean gsb_select_icon_new_account_icon_from_file ( gint account_number, const gchar *filename ) { struct_account_icon *icon; GdkPixbuf *pixbuf; GError *error = NULL; if ( !filename || !strlen ( filename ) ) return FALSE; else { if ( !g_file_test ( filename, G_FILE_TEST_EXISTS ) ) return FALSE; } icon = g_malloc0 ( sizeof ( struct_account_icon ) ); icon_buffer = icon; if ( !icon ) { dialogue_error_memory (); return FALSE; } icon -> account_number = account_number; pixbuf = gdk_pixbuf_new_from_file_at_size ( filename , 32, 32, &error ); if ( pixbuf ) { icon -> pixbuf = pixbuf; list_accounts_icon = g_slist_prepend ( list_accounts_icon, icon ); return TRUE; } else { gchar* tmp_str; tmp_str = g_strconcat( "Erreur de pixbuf : ", error -> message, " image ", filename, NULL ); devel_debug ( tmp_str ); dialogue_error ( tmp_str ); g_error_free ( error ); g_free ( tmp_str ); g_free ( icon ); return FALSE; } }
/** * Initialize user interface part when a new accounts file is created. */ void gsb_file_new_gui ( void ) { GtkWidget *main_vbox; GtkWidget *tree_view_widget; GtkWidget *notebook_general; /* dégrise les menus nécessaire */ gsb_menu_set_menus_with_file_sensitive ( TRUE ); /* récupère l'organisation des colonnes */ recuperation_noms_colonnes_et_tips (); /* Create main widget. */ gsb_status_message ( _("Creating main window") ); main_vbox = g_object_get_data ( G_OBJECT ( run.window ), "main_vbox" ); gtk_box_pack_start ( GTK_BOX ( main_vbox ), gsb_gui_create_general_widgets ( ), TRUE, TRUE, 0 ); /* create the model */ if (!transaction_list_create ()) { dialogue_error (_("The model of the list couldn't be created... " "Bad things will happen very soon...")); return; } /* Create transaction list. */ tree_view_widget = gsb_transactions_list_make_gui_list (); gtk_box_pack_start ( GTK_BOX ( tree_view_vbox ), tree_view_widget, TRUE, TRUE, 0 ); gtk_widget_show ( tree_view_widget ); navigation_change_account ( gsb_gui_navigation_get_current_account () ); /* Display accounts in menus */ gsb_menu_update_accounts_in_menus (); notebook_general = gsb_gui_get_general_notebook ( ); gtk_notebook_set_current_page ( GTK_NOTEBOOK( notebook_general ), GSB_HOME_PAGE ); gtk_widget_show ( notebook_general ); }
/** * called by menu : begin the debug mode * show a message to say where the log will be saved * * \param * * \return FALSE * */ gboolean gsb_debug_start_log ( void ) { gchar *tmp_str; gchar *debug_filename; devel_debug ( NULL ); if ( nom_fichier_comptes ) { gchar *base_filename = g_strdup ( nom_fichier_comptes ); gchar *complete_filename; gchar *basename; base_filename [strlen ( base_filename ) - 4] = 0; complete_filename = g_strconcat ( base_filename, "-log.txt", NULL); basename = g_path_get_basename ( complete_filename ); debug_filename = g_build_filename ( my_get_gsb_file_default_dir (), basename, NULL); g_free ( basename); g_free ( complete_filename ); g_free ( base_filename ); } else { debug_filename = g_build_filename ( my_get_gsb_file_default_dir (), "No_name-log.txt", NULL); } tmp_str = g_strdup_printf (_("The debug-mode is starting. Grisbi will write a log into %s. " "Please send that file with the obfuscated file into the bug report."), debug_filename ); dialogue ( tmp_str ); g_free (tmp_str); debug_file = g_fopen ( debug_filename, "w" ); g_free ( debug_filename ); if ( debug_file ) { GtkWidget *widget; gchar *tmp_str_2; GtkUIManager *ui_manager = gsb_menu_get_ui_manager ( ); widget = gtk_ui_manager_get_widget ( ui_manager, "/menubar/FileMenu/DebugMode" ); etat.debug_mode = TRUE; /* unsensitive the menu, we cannot reverse the debug mode */ if ( widget && GTK_IS_WIDGET ( widget ) ) gtk_widget_set_sensitive ( widget, FALSE ); /* début du mode débogage */ tmp_str = g_strdup_printf(_("%s, %2f : Debug - %s:%d:%s\n\n"), get_debug_time ( ), (double ) clock ( )/ CLOCKS_PER_SEC, __FILE__, __LINE__, __PRETTY_FUNCTION__ ); fwrite ( tmp_str, sizeof (gchar), strlen ( tmp_str ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); /* write locales */ tmp_str = gsb_main_get_print_locale_var ( ); fwrite ( tmp_str, sizeof (gchar), strlen ( tmp_str ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); tmp_str = g_strdup_printf ( "gint64\n" "\tG_GINT64_MODIFIER = \"%s\"\n" "\t%"G_GINT64_MODIFIER"d\n\n", G_GINT64_MODIFIER, G_MAXINT64 ); fwrite ( tmp_str, sizeof (gchar), strlen ( tmp_str ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); tmp_str = gsb_main_get_print_dir_var ( ); fwrite ( tmp_str, sizeof (gchar), strlen ( tmp_str ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); tmp_str = g_strdup ( "Formats importés\n" ); fwrite ( tmp_str, sizeof (gchar), strlen ( tmp_str ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); tmp_str = gsb_import_formats_get_list_formats_to_string ( ); tmp_str_2 = g_strconcat ( tmp_str, "\n", NULL ); fwrite ( tmp_str_2, sizeof (gchar), strlen ( tmp_str_2 ), debug_file ); fflush ( debug_file ); g_free ( tmp_str ); g_free ( tmp_str_2 ); } else dialogue_error (_("Grisbi failed to create the log file...") ); return FALSE; }
/** * save the config file * it uses the glib config utils after 0.6.0 * if cannot load, try the xml file before that version * * \param * * \return TRUE if ok * */ gboolean gsb_file_config_save_config ( void ) { GKeyFile *config; const gchar *filename; gchar *file_content; gchar *name; gsize length; FILE *conf_file; gint i; devel_debug (NULL); filename = gsb_dirs_get_grisbirc_filename (); config = g_key_file_new (); #if IS_DEVELOPMENT_VERSION == 1 /* set config model */ g_key_file_set_integer ( config, "Model", "Stable_config_file_model", conf.stable_config_file_model ); #endif g_key_file_set_integer ( config, "Geometry", "Root_x", conf.root_x ); g_key_file_set_integer ( config, "Geometry", "Root_y", conf.root_y ); g_key_file_set_integer ( config, "Geometry", "Width", conf.main_width ); g_key_file_set_integer ( config, "Geometry", "Height", conf.main_height ); g_key_file_set_integer ( config, "Geometry", "Full_screen", conf.full_screen ); g_key_file_set_integer ( config, "Geometry", "Maximize_screen", conf.maximize_screen ); /* Remember size of main panel */ g_key_file_set_integer ( config, "Geometry", "Panel_width", conf.panel_width ); /* preferences size */ g_key_file_set_integer ( config, "Geometry", "Prefs_width", conf.prefs_width ); /* save general */ g_key_file_set_integer ( config, "General", "Can modify R", conf.r_modifiable ); g_key_file_set_string ( config, "General", "Path", gsb_file_get_last_path () ); g_key_file_set_integer ( config, "General", "Show permission alert", conf.alerte_permission ); g_key_file_set_integer ( config, "General", "Function of enter", conf.entree ); g_key_file_set_integer ( config, "General", "Show alert messages", conf.alerte_mini ); g_key_file_set_integer ( config, "General", "Use user font", conf.utilise_fonte_listes ); if ( conf.font_string ) g_key_file_set_string ( config, "General", "Font name", conf.font_string ); if ( conf.browser_command ) { gchar *string; string = my_strdelimit ( conf.browser_command, "&", "\\e" ); if ( string ) g_key_file_set_string ( config, "General", "Web", string ); g_free (string); } g_key_file_set_integer ( config, "General", "Pluriel_final", conf.pluriel_final ); g_key_file_set_integer ( config, "General", "Metatree_action_2button_press", conf.metatree_action_2button_press ); /* save backup part */ g_key_file_set_integer ( config, "Backup", "Make backup", conf.make_backup ); g_key_file_set_integer ( config, "Backup", "Make backup single file", conf.make_bakup_single_file ); g_key_file_set_integer ( config, "Backup", "Make backup every x minutes", conf.make_backup_every_minutes ); g_key_file_set_integer ( config, "Backup", "Compress backup", conf.compress_backup ); g_key_file_set_integer ( config, "Backup", "Make backup nb minutes", conf.make_backup_nb_minutes ); if (gsb_file_get_backup_path ()) g_key_file_set_string ( config, "Backup", "Backup path", gsb_file_get_backup_path ()); /* save input/output */ g_key_file_set_integer ( config, "IO", "Load last file", conf.dernier_fichier_auto ); g_key_file_set_integer ( config, "IO", "Save at closing", conf.sauvegarde_auto ); g_key_file_set_integer ( config, "IO", "Save at opening", conf.sauvegarde_demarrage ); g_key_file_set_integer ( config, "IO", "Nb last opened files", conf.nb_max_derniers_fichiers_ouverts ); g_key_file_set_integer ( config, "IO", "Compress file", conf.compress_file ); g_key_file_set_integer ( config, "IO", "Force saving", conf.force_enregistrement ); if ( conf.nb_derniers_fichiers_ouverts > 0 && tab_noms_derniers_fichiers_ouverts) g_key_file_set_string_list ( config, "IO", "Names last files", (const gchar **) tab_noms_derniers_fichiers_ouverts, conf.nb_derniers_fichiers_ouverts); g_key_file_set_integer ( config, "IO", "Check_archival_at_opening", conf.check_for_archival ); g_key_file_set_integer ( config, "IO", "Max_transactions_before_warn_archival", conf.max_non_archived_transactions_for_check ); /* save scheduled section */ g_key_file_set_integer ( config, "Scheduled", "Days before remind", nb_days_before_scheduled ); g_key_file_set_integer ( config, "Scheduled", "Execute scheduled of month", conf.execute_scheduled_of_month ); g_key_file_set_integer ( config, "Scheduled", "Balances with scheduled", conf.balances_with_scheduled ); g_key_file_set_integer ( config, "Scheduled", "Group_partial_balance", conf.group_partial_balance_under_accounts ); /* save shown section */ g_key_file_set_integer ( config, "Display", "Show transaction form", conf.formulaire_toujours_affiche ); g_key_file_set_integer ( config, "Display", "Show selected transaction in form", conf.show_transaction_selected_in_form ); g_key_file_set_integer ( config, "Display", "Show transaction gives balance", conf.show_transaction_gives_balance ); g_key_file_set_integer ( config, "Display", "Transactions_list_primary_sorting", conf.transactions_list_primary_sorting ); g_key_file_set_integer ( config, "Display", "Transactions_list_secondary_sorting", conf.transactions_list_secondary_sorting ); g_key_file_set_integer ( config, "Display", "Show automatic financial year", conf.affichage_exercice_automatique ); g_key_file_set_integer ( config, "Display", "Automatic completion payee", conf.automatic_completion_payee ); g_key_file_set_integer ( config, "Display", "Limit payee completion", conf.limit_completion_to_current_account ); g_key_file_set_integer ( config, "Display", "Automatic_recover_splits", conf.automatic_recover_splits ); g_key_file_set_integer ( config, "Display", "Automatic_erase_credit_debit", conf.automatic_erase_credit_debit ); g_key_file_set_integer ( config, "Display", "Display toolbar", conf.display_toolbar ); g_key_file_set_integer ( config, "Display", "Active_scrolling_left_pane", conf.active_scrolling_left_pane ); g_key_file_set_integer ( config, "Display", "Show headings bar", conf.show_headings_bar ); g_key_file_set_integer ( config, "Display", "Show closed accounts", conf.show_closed_accounts ); g_key_file_set_integer ( config, "Display", "Display grisbi title", conf.display_grisbi_title ); /* save messages */ for ( i = 0; messages[i].name; i ++ ) { name = g_strconcat ( messages[i].name , "-answer", NULL ); g_key_file_set_integer ( config, "Messages", messages[i].name, messages[i].hidden ); g_key_file_set_integer ( config, "Messages", name, messages[i].default_answer ); g_free ( name ); } for ( i = 0; delete_msg[i].name; i ++ ) { g_key_file_set_integer ( config, "Messages", delete_msg[i].name, delete_msg[i].hidden ); } g_key_file_set_integer ( config, "Messages", "Last tip", conf.last_tip ); g_key_file_set_integer ( config, "Messages", "Show tip", conf.show_tip ); /* save into a file */ file_content = g_key_file_to_data ( config, &length, NULL ); conf_file = fopen ( filename, "w" ); #ifndef _WIN32 if ( !conf_file ) { utils_files_create_XDG_dir ( ); conf_file = fopen ( filename, "w" ); } #endif if ( !conf_file || !fwrite ( file_content, sizeof ( gchar ), length, conf_file ) ) { gchar* tmpstr = g_strdup_printf ( _("Cannot save configuration file '%s': %s"), filename, g_strerror ( errno ) ); dialogue_error ( tmpstr ); g_free ( tmpstr ); g_free ( file_content); g_key_file_free (config); return ( FALSE ); } fclose ( conf_file ); g_free ( file_content); g_key_file_free (config); return TRUE; }
/* get the line af the file, * convert it in UTF8 and fill string with that line * * \param fichier * \param string * \param coding_system the orig coding system of the string * * \return EOF, 1 if ok, 0 if problem * */ gint get_utf8_line_from_file ( FILE *fichier, gchar **string, const gchar *coding_system ) { gchar c = 0; gint i = 0; gint j = 0; gchar *pointeur_char = NULL; gchar *tmp_string; if ( !fichier ) return 0; /* allocate 30 characters, and increase it 30 by 30 */ pointeur_char = (gchar*)g_realloc(pointeur_char,30*sizeof(gchar)); if ( !pointeur_char ) { /* ouch, not enough memory */ dialogue_error ( _("Memory allocation error" )); return 0; } /* get the string untill \n or \r (windows format) */ c =(gchar)fgetc(fichier); while ( ( c != '\n' ) && (c != '\r') && !feof (fichier)) { pointeur_char[j++] = c; if ( ++i == 29 ) { pointeur_char = (gchar*)g_realloc(pointeur_char, j + 1 + 30*sizeof(gchar)); if ( !pointeur_char ) { /* ouch, not enough memory */ dialogue_error ( _("Memory allocation error" )); return 0; } i = 0; } c =(gchar)fgetc(fichier); } pointeur_char[j] = 0; /* if we finished on \r, jump the \n after it */ if ( c == '\r' ) { c =(gchar)fgetc(fichier); if ( c != '\n' ) { ungetc ( c, fichier ); } } tmp_string = g_convert ( pointeur_char, -1, "UTF-8", coding_system, NULL, NULL, NULL ); if (!tmp_string) { devel_debug ("convert to utf8 failed, will use latin2utf8"); tmp_string = latin2utf8 (pointeur_char); if ( tmp_string == NULL ) { dialogue_special ( GTK_MESSAGE_ERROR, make_hint ( _("Convert to utf8 failed."), _("If the result is not correct, try again by selecting the " "correct character set in the window for selecting files.") ) ); return 0; } } *string = tmp_string; g_free (pointeur_char); if ( feof(fichier)) return EOF; else return 1; }
/** * save the category file * we don't check anything here, all must be done before, here we just write * the file * use the same method as gsb_file_save_save_file * * \param filename the name of the file * * \return TRUE : ok, FALSE : problem * */ gboolean gsb_file_others_save_category ( gchar *filename ) { gchar *file_content; gchar *tmp_str; FILE *file; gulong iterator; gulong length_calculated; gulong length_part; devel_debug (filename); /* we begin to try to reserve enough memory to make the entire file * if not enough, we will make it growth later * the data below are about the memory to take for each part and for 1 of this part * with that i think we will allocate enough memory in one time but not too much */ length_part = 500; length_calculated = length_part * g_slist_length (gsb_data_category_get_categories_list()); if ( length_calculated == 0 ) { tmp_str = g_strdup ( _("There is no category to record. Back.") ); dialogue_error ( tmp_str ); g_free ( tmp_str ); return ( TRUE ); } iterator = 0; file_content = g_malloc0 ( length_calculated ); /* begin the file whit xml markup */ iterator = gsb_file_save_append_part ( iterator, &length_calculated, &file_content, my_strdup ("<?xml version=\"1.0\"?>\n<Grisbi_categ>\n")); iterator = gsb_file_others_save_general_part ( iterator, &length_calculated, &file_content, VERSION_FICHIER_CATEG ); iterator = gsb_file_save_category_part ( iterator, &length_calculated, &file_content ); /* finish the file */ iterator = gsb_file_save_append_part ( iterator, &length_calculated, &file_content, my_strdup ("</Grisbi_categ>")); /* the file is in memory, we can save it */ file = utils_files_utf8_fopen ( filename, "w" ); if ( !file || !fwrite ( file_content, sizeof (gchar), iterator, file )) { tmp_str = g_strdup_printf ( _("Cannot save file '%s': %s"), filename, g_strerror ( errno ) ); dialogue_error ( tmp_str ); g_free ( tmp_str ); g_free ( file_content ); if (file) fclose(file); return ( FALSE ); } fclose (file); g_free ( file_content); return ( TRUE ); }
gboolean gsb_file_others_load_budget_from_category ( const gchar *filename ) { gchar *file_content; gchar* tmp_str; GSList *import_list = NULL; devel_debug (filename); /* general check */ if ( !g_file_test ( filename, G_FILE_TEST_EXISTS ) ) { tmp_str = g_strdup_printf (_("Cannot open file '%s': %s"), filename, g_strerror ( errno ) ); dialogue_error ( tmp_str ); g_free ( tmp_str ); return FALSE; } /* check here if it's not a regular file */ if ( !g_file_test ( filename, G_FILE_TEST_IS_REGULAR ) ) { tmp_str = g_strdup_printf ( _("%s doesn't seem to be a regular file,\nplease check it and try again."), filename ); dialogue_error ( tmp_str ); g_free ( tmp_str ); return ( FALSE ); } /* load the file */ if ( g_file_get_contents ( filename, &file_content, NULL, NULL ) ) { GMarkupParser *markup_parser; GMarkupParseContext *context; /* check if it's a good file */ if ( !gsb_file_others_check_file ( file_content, 5 ) ) { g_free ( file_content ); return FALSE; } /* we load only after 0.6 files, * there is very few people who will want to upgrade previous categories, budgets... * and i'm too lazy to create an import for old files */ /* fill the GMarkupParser for a new xml structure */ markup_parser = g_malloc0 (sizeof (GMarkupParser)); markup_parser -> start_element = (void *) gsb_file_others_start_budget_from_category; markup_parser -> error = (void *) gsb_file_load_error; context = g_markup_parse_context_new ( markup_parser, 0, &import_list, NULL ); g_markup_parse_context_parse ( context, file_content, strlen ( file_content ), NULL ); /* on remplit l'arbre des imputation */ budgetary_lines_fill_list ( ); g_markup_parse_context_free ( context ); g_free ( markup_parser ); g_free ( file_content ); gsb_file_set_modified ( TRUE ); } else { tmp_str = g_strdup_printf (_("Cannot open file '%s': %s"), filename, g_strerror ( errno ) ); dialogue_error ( tmp_str ); g_free ( tmp_str ); return FALSE; } return TRUE; }
/** * check if the file given in param is a good file with the origin * * \param file_content the file loaded * \param origin what we want (0: category, 1:budget, 2:report) * * \return TRUE ok, FALSE else * */ gboolean gsb_file_others_check_file ( gchar *file_content, gint origin ) { if ( !file_content || strlen (file_content) < 37 ) { dialogue_error ( _("This is not a Grisbi file, loading canceled...")); return FALSE; } file_content = gsb_string_uniform_new_line ( file_content, 37 ); if ( !file_content ) { dialogue_error ( _("This is not a Grisbi file, loading canceled...")); return FALSE; } switch ( origin ) { case 0: if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_categ>", 36 ) ) { /* check if not before 0.6 */ if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_categ>\n <General\n", 47 ) ) return TRUE; else dialogue_error (_("The file version is below 0.6.0, Grisbi cannot import it.")); } else dialogue_error ( _("This is not a category file, loading canceled...")); break; case 1: /* check first if it's not below 0.6 */ if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_ib>", 33 ) ) dialogue_error (_("The file version is below 0.6.0, Grisbi cannot import it.")); else { if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_budget>", 37 ) ) return TRUE; else dialogue_error ( _("This is not a budget file, loading canceled...")); } break; case 2: /* check first if it's not below 0.6 */ if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_etat>", 35 ) ) dialogue_error (_("The file version is below 0.6.0, Grisbi cannot import it.")); else { if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_report>", 37 ) ) return TRUE; else dialogue_error ( _("This is not a report file, loading canceled...")); } break; case 5: if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_categ>", 36 ) ) { /* check if not before 0.6 */ if ( !strncmp ( file_content, "<?xml version=\"1.0\"?>\n<Grisbi_categ>\n <General\n", 47 ) ) return TRUE; else dialogue_error (_("The file version is below 0.6.0, Grisbi cannot import it.")); } else dialogue_error ( _("This is not a category file, loading canceled...")); break; } return FALSE; }
/** * called to load the category/budget/report file given in param * * \filename the filename to load with full path * * \return TRUE if ok * */ gboolean gsb_file_others_load ( gchar *filename, gint origin ) { gchar *file_content; GSList *import_list = NULL; GError *error = NULL; devel_debug (filename); /* general check */ if ( !g_file_test ( filename, G_FILE_TEST_EXISTS )) { gchar* tmpstr = g_strdup_printf (_("Cannot open file '%s': %s"), filename, g_strerror(errno)); dialogue_error ( tmpstr ); g_free ( tmpstr ); return FALSE; } /* check here if it's not a regular file */ if ( !g_file_test ( filename, G_FILE_TEST_IS_REGULAR )) { gchar* tmpstr = g_strdup_printf ( _("%s doesn't seem to be a regular file,\nplease check it and try again."), filename ); dialogue_error ( tmpstr ); g_free ( tmpstr ); return ( FALSE ); } /* load the file */ if ( g_file_get_contents ( filename, &file_content, NULL, NULL )) { GMarkupParser *markup_parser; GMarkupParseContext *context; /* check if it's a good file */ if ( !gsb_file_others_check_file ( file_content, origin )) { g_free (file_content); return FALSE; } /* we load only after 0.6 files, * there is very few people who will want to upgrade previous categories, budgets... * and i'm too lazy to create an import for old files */ /* fill the GMarkupParser for a new xml structure */ markup_parser = g_malloc0 ( sizeof ( GMarkupParser ) ); markup_parser -> start_element = ( void * ) gsb_file_others_start_element; markup_parser -> error = ( void * ) gsb_file_load_error; context = g_markup_parse_context_new ( markup_parser, 0, &import_list, NULL ); if ( !g_markup_parse_context_parse ( context, file_content, strlen ( file_content ), &error ) ) { gchar* tmpstr; tmpstr = g_strdup_printf (_("Error parsing file '%s': %s"), filename, error->message ); dialogue_error ( tmpstr ); g_free ( tmpstr ); g_markup_parse_context_free ( context ); g_free ( markup_parser ); g_free ( file_content ); return FALSE; } gint report_number; /* now, import_list contains the list of categories/budget or report */ switch ( origin ) { case 0: /* comes for category */ categories_fill_list (); break; case 1: /* comes for budget */ budgetary_lines_fill_list (); break; case 2: /* comes for report, * as we cannot have the same things between differents grisbi files, * we cannot export/import currencies, financial years, accounts names, * categories, budgetaries and parties * so we erase them here because perhaps they doesn't exist and show * a warning : the user has to do it by himself (untill a druid to help him ?) */ /* we import only 1 report, so it's the last one */ report_number = gsb_data_report_max_number (); if (report_number) { /* set the currencies */ gsb_data_report_set_currency_general ( report_number, 1 ); gsb_data_report_set_category_currency ( report_number, 1 ); gsb_data_report_set_budget_currency ( report_number, 1 ); gsb_data_report_set_payee_currency ( report_number, 1 ); gsb_data_report_set_amount_comparison_currency ( report_number, 1 ); /* erase the financials years */ gsb_data_report_set_financial_year_list ( report_number, NULL ); /* erase the accounts */ gsb_data_report_set_account_numbers_list ( report_number, NULL); /* erase the transferts accounts */ gsb_data_report_set_transfer_account_numbers_list ( report_number, NULL ); /* erase the categories */ gsb_data_report_set_category_struct_list ( report_number, NULL ); /* erase the parties */ gsb_data_report_set_payee_numbers_list ( report_number, NULL ); /* erase the kinds of payment */ gsb_data_report_set_method_of_payment_list ( report_number, NULL ); gsb_gui_navigation_add_report ( report_number ); /* inform the user of that */ dialogue_hint ( _("Some things in a report cannot be imported:\n" "The selected lists of financial years, accounts, transfer accounts, " "categories, budgetaries, parties and kind of payments.\nSo that lists " "have been erased while the import.\nThe currencies have been set too " "on the first currency of this Grisbi file.\nYou should check and modify " "that in the property box of that account."), _("Importing a report")); } break; } g_markup_parse_context_free (context); g_free (markup_parser); g_free (file_content); gsb_file_set_modified ( TRUE ); } else { gchar* tmpstr = g_strdup_printf (_("Cannot open file '%s': %s"), filename, g_strerror(errno)); dialogue_error ( tmpstr ); g_free ( tmpstr ); return FALSE; } return TRUE; }
/** * callback called by the button to launch the automatic association * between transactions and reconcile * * \param button * \param assistant * * \return FALSE * */ static gboolean gsb_assistant_reconcile_config_lauch_manu_asso ( GtkWidget *button, GtkWidget *assistant ) { GList *tmp_list; GtkTreeIter iter; GtkTreeModel *model; GtkTreeSelection *selection; GList *path_list; gint account_number = -1; GtkWidget *dialog; GtkWidget *label; GtkWidget *scrolled_window; GtkWidget *dialog_tree_view; GtkListStore *dialog_store; gint return_value; gint i; enum dialog_column { DIALOG_NAME = 0, DIALOG_INIT_DATE, DIALOG_FINAL_DATE, DIALOG_RECONCILE_NUMBER, DIALOG_NB_COL }; gint selected_reconcile_number; gint transaction_number; /* get the selection */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_transactions_to_link)); /* get the selected transactions */ path_list = gtk_tree_selection_get_selected_rows ( GTK_TREE_SELECTION (selection), &model ); if (!path_list) return FALSE; /* ok, we have a selection, before continuing, * we check that all the transactions are on the same account */ tmp_list = path_list; while (tmp_list) { GtkTreePath *path; path = tmp_list -> data; if (gtk_tree_model_get_iter ( GTK_TREE_MODEL (model), &iter, path )) { gtk_tree_model_get ( GTK_TREE_MODEL (model), &iter, TRANSACTION_NUMBER, &transaction_number, -1 ); if (account_number == -1) account_number = gsb_data_transaction_get_account_number (transaction_number); else { if (gsb_data_transaction_get_account_number (transaction_number) != account_number) { dialogue_error (_("All the selected transactions have to belong to the same account !")); /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); return FALSE; } } } tmp_list = tmp_list -> next; } if (account_number == -1) { /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); return FALSE; } /* ok, all the transactions belong to the same account, we can * show a dialog to select the reconcile */ dialog = gtk_dialog_new_with_buttons ( _("Selection of a reconciliation"), GTK_WINDOW ( assistant ), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-ok", GTK_RESPONSE_OK, NULL ); gtk_window_set_default_size ( GTK_WINDOW ( dialog ), 770, 412 ); gtk_window_set_position ( GTK_WINDOW ( dialog ), GTK_WIN_POS_CENTER_ON_PARENT ); gtk_window_set_resizable ( GTK_WINDOW ( dialog ), TRUE ); gtk_container_set_border_width ( GTK_CONTAINER ( dialog ), 12 ); label = gtk_label_new ( _("Select the reconciliation to associate to the selected transactions: ") ); gtk_misc_set_alignment ( GTK_MISC ( label ), 0.0, 0.0 ); gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), label, FALSE, FALSE, 10 ); /* make the list */ scrolled_window = gtk_scrolled_window_new (FALSE, FALSE); gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), scrolled_window, TRUE, TRUE, 0 ); dialog_store = gtk_list_store_new ( DIALOG_NB_COL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT ); dialog_tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (dialog_store)); g_object_unref (G_OBJECT(dialog_store)); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (dialog_tree_view), TRUE); gtk_container_add ( GTK_CONTAINER (scrolled_window), dialog_tree_view ); /* set the columns */ for (i=DIALOG_NAME ; i<DIALOG_RECONCILE_NUMBER ; i++) { GtkTreeViewColumn *column; GtkCellRenderer *cell; gchar *titles[] = { _("Reconciliation reference"), _("Initial date"), _("Final date") }; gfloat alignment[] = { COLUMN_LEFT, COLUMN_CENTER, COLUMN_CENTER }; cell = gtk_cell_renderer_text_new (); g_object_set ( G_OBJECT (cell), "xalign", alignment[i], NULL ); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_sizing ( column, GTK_TREE_VIEW_COLUMN_AUTOSIZE ); gtk_tree_view_column_set_alignment ( column, alignment[i] ); gtk_tree_view_column_pack_start ( column, cell, TRUE ); gtk_tree_view_column_set_title ( column, titles[i] ); gtk_tree_view_column_set_attributes (column, cell, "text", i, NULL); gtk_tree_view_column_set_expand ( column, TRUE ); gtk_tree_view_column_set_resizable ( column, TRUE ); gtk_tree_view_append_column ( GTK_TREE_VIEW(dialog_tree_view), column); } /* fill the tree view */ tmp_list = gsb_data_reconcile_get_reconcile_list (); while (tmp_list) { gint reconcile_number; reconcile_number = gsb_data_reconcile_get_no_reconcile (tmp_list -> data); if (gsb_data_reconcile_get_account (reconcile_number) == account_number) { gchar *init_date_str; gchar *final_date_str; init_date_str = gsb_format_gdate (gsb_data_reconcile_get_init_date (reconcile_number)); final_date_str = gsb_format_gdate (gsb_data_reconcile_get_final_date (reconcile_number)); gtk_list_store_append ( GTK_LIST_STORE (dialog_store), &iter ); gtk_list_store_set ( GTK_LIST_STORE (dialog_store), &iter, DIALOG_NAME, gsb_data_reconcile_get_name (reconcile_number), DIALOG_INIT_DATE, init_date_str, DIALOG_FINAL_DATE, final_date_str, DIALOG_RECONCILE_NUMBER, reconcile_number, -1 ); g_free (init_date_str); g_free (final_date_str); } tmp_list = tmp_list -> next; } gtk_widget_show_all (dialog); /* launch the dialog */ return_value = gtk_dialog_run (GTK_DIALOG (dialog)); if (return_value != GTK_RESPONSE_OK) { gtk_widget_destroy (dialog); return FALSE; } /* we get the selected reconcile */ if (!gtk_tree_selection_get_selected ( gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog_tree_view)), NULL, &iter )) { dialogue_warning (_("No selection found, the transactions are not modified.")); gtk_widget_destroy (dialog); return FALSE; } gtk_tree_model_get ( GTK_TREE_MODEL (dialog_store), &iter, DIALOG_RECONCILE_NUMBER, &selected_reconcile_number, -1 ); /* ok we have the reconcile number, we can destroy the dialog */ gtk_widget_destroy (dialog); /* and now, fill the selected transactions with that reconcile number */ tmp_list = g_list_last (path_list); while (tmp_list) { GtkTreePath *path; path = tmp_list -> data; if (gtk_tree_model_get_iter ( GTK_TREE_MODEL (model), &iter, path )) { gtk_tree_model_get ( GTK_TREE_MODEL (model), &iter, TRANSACTION_NUMBER, &transaction_number, -1 ); gtk_list_store_remove ( GTK_LIST_STORE (model), &iter ); gsb_data_transaction_set_reconcile_number ( transaction_number, selected_reconcile_number ); transactions_to_link--; } tmp_list = tmp_list -> prev; } /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); /* now there is 2 way : * either transactions_to_link is 0, we go directly to the succes page * either it's not null, and the user should create more reconciles */ if (transactions_to_link) { gchar *string; /* update the labels */ string = g_strdup_printf (_("Still %d transactions to link with a reconciliation."), transactions_to_link); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_1), string); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_3), string); g_free (string); gtk_widget_grab_focus (treeview_transactions_to_link); } else { /* go to the success page */ gsb_assistant_set_next ( assistant, RECONCILE_ASSISTANT_MANUALLY_ASSOCIATE, RECONCILE_ASSISTANT_SUCCESS ); gsb_assistant_next_page (assistant); } return FALSE; }
/** * this function try to understand in what order are the content of the date, * the two order known are d-m-y or y-m-d (hoping Money won't do something like m-y-d...) * the only way to know that is to check all the transactions imported and verify the first * order, if doesn't work, it's the second * * \param transactions_list the list of imported transactions * * \return -1 for not found, or ORDER_... (see the enum at the begining of file) * */ static gint gsb_qif_get_date_order ( GSList *transactions_list ) { GSList *tmp_list; gint order = 0; gchar *date_wrong[ORDER_MAX]; /* to find the good order of the content of the date, we check all possible orders * and check if all the dates are possible with that order. if one day 2 different order * can be good with that check, we should implement a second check : the transactions * are sorted normally, either in ascending, sometimes in descending order. * so check for the valids order if the transactions are sorted, normally, only one we be correct */ tmp_list = transactions_list; while ( tmp_list ) { struct struct_ope_importation *transaction = tmp_list -> data; gchar **array; gint year = 0, month = 0, day = 0; if ( !transaction -> date_tmp ) continue; array = gsb_qif_get_date_content ( transaction -> date_tmp ); /* if array still contains /, there is a problem (more than 2 / in the first entry) */ if ( memchr ( array[2], '/', strlen ( array[2] ) ) ) { gchar *string = g_strdup_printf ( _("The date %s seems contains more than 2 separators.\n" "This shouldn't happen. Please contact the Grisbi team to try to " "add your strange format into Grisbi"), transaction -> date_tmp ); dialogue_error ( string ); g_free ( string ); return -1; } /* get the day, month and year according to the order */ switch (order) { case ORDER_DD_MM_YY: day = atoi (array[0]); month = atoi (array[1]); year = atoi (array[2]); break; case ORDER_MM_DD_YY: day = atoi (array[1]); month = atoi (array[0]); year = atoi (array[2]); break; case ORDER_YY_MM_DD: day = atoi (array[2]); month = atoi (array[1]); year = atoi (array[0]); break; case ORDER_YY_DD_MM: day = atoi (array[1]); month = atoi (array[2]); year = atoi (array[0]); break; case ORDER_DD_YY_MM: day = atoi (array[0]); month = atoi (array[2]); year = atoi (array[1]); break; case ORDER_MM_YY_DD: day = atoi (array[2]); month = atoi (array[0]); year = atoi (array[1]); break; } /* the year can be yy or yyyy, we change that here */ if ( year < 100 ) { if ( year < 80 ) year = year + 2000; else year = year + 1900; } if ( g_date_valid_dmy ( day, month, year ) ) /* the date is valid, go to the next date */ tmp_list = tmp_list -> next; else { /* the date is not valid, change the order or go away */ date_wrong[order] = transaction -> date_tmp; order++; if ( order < ORDER_MAX ) /* we try again with the new order */ tmp_list = transactions_list; else { /* the order was already changed for all the formats, we show the problem and leave */ gint i; gchar *string = my_strdup ( _("The order cannot be determined,\n") ); for ( i = 0; i < ORDER_MAX; i++ ) { gchar *tmp_str; tmp_str = g_strconcat ( string,_("Date wrong for the order "), order_names[i], " : ", date_wrong[i], "\n", NULL ); g_free (string); string = tmp_str; } dialogue_error (string); g_free (string); g_strfreev (array); return -1; } } g_strfreev (array); } return order; }
/** * \brief Import QIF data. * * Open a QIF file and fills in data in a struct_compte_importation * data structure. * * \param assistant Not used. * \param imported A pointer to structure containing name and * format of imported file. * * \return TRUE on success. */ gboolean recuperation_donnees_qif ( GtkWidget *assistant, struct imported_file *imported ) { gchar *tmp_str; struct struct_compte_importation *imported_account; gint returned_value = 0; gboolean premier_compte = TRUE; FILE *qif_file; qif_file = utf8_fopen ( imported -> name, "r" ); if ( ! qif_file ) return FALSE; mismatch_dates = TRUE; /* qif_file pointe sur le qif_file qui a été reconnu comme qif */ rewind ( qif_file ); imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation )); imported_account -> nom_de_compte = unique_imported_name ( _("Invalid QIF file") ); imported_account -> filename = my_strdup ( imported -> name ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename */ imported_account -> real_filename = my_strdup (imported -> name); /* It is positioned on the first line of file */ returned_value = get_utf8_line_from_file ( qif_file, &tmp_str, imported -> coding_system ); do { GSList *tmp_list; gchar *account_name = NULL; gint order = 0; gboolean name_preced = FALSE; struct struct_ope_importation *imported_transaction; do { if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Account", 8 ) == 0 ) { /* create and fill the new account */ imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation ) ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename and account_name */ imported_account -> real_filename = my_strdup ( imported -> name ); imported_account -> filename = my_strdup ( imported -> name ); account_name = gsb_qif_get_account_name ( qif_file, imported -> coding_system ); imported_account -> nom_de_compte = unique_imported_name ( account_name ); g_free ( account_name ); name_preced = TRUE; premier_compte = FALSE; returned_value = get_utf8_line_from_file ( qif_file, &tmp_str, imported -> coding_system ); } else if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Type:Cat", 9 ) == 0 ) { do { returned_value = gsb_qif_recupere_categories ( qif_file, imported -> coding_system ); if ( returned_value == 0 ) tmp_str = last_header; } /* continue untill the end of the file or a change of account */ while ( returned_value != EOF && returned_value != 0 ); } else if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Type", 5 ) == 0 ) { gint account_type; account_type = gsb_qif_get_account_type ( tmp_str ) ; if ( account_type == -1 ) { name_preced = FALSE; continue; } else { if ( name_preced == FALSE ) { /* create and fill the new account */ imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation ) ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename and account_name */ imported_account -> real_filename = my_strdup ( imported -> name ); imported_account -> filename = my_strdup ( imported -> name ); imported_account -> nom_de_compte = unique_imported_name ( my_strdup ( _("Imported QIF account" ) ) ); premier_compte = FALSE; } if ( account_type == 6 ) { /* on considère le imported_account d'investissement comme un imported_account * bancaire mais met un warning car pas implémenté, aucune idée si ça passe ou pas... */ gchar *msg; msg = g_strdup_printf ( _("Grisbi found an investment account:\n%s\n" "which is not implemented yet. Nevertheless, Grisbi will try " "to import it as a bank account." ), imported -> name ); dialogue_warning ( msg ); g_free ( msg ); account_type = 0; } imported_account -> type_de_compte = account_type; returned_value = -2; } } else name_preced = FALSE; } while ( returned_value != EOF && returned_value != -2 ); if ( returned_value == EOF ) { if ( premier_compte ) { /* no account already saved, so send an error */ liste_comptes_importes_error = g_slist_append ( liste_comptes_importes_error, imported_account ); fclose ( qif_file ); return FALSE; } else { /* we have at least saved an account before, ok, enough for me */ fclose ( qif_file ); return TRUE; } } do { returned_value = gsb_qif_recupere_operations_from_account ( qif_file, imported -> coding_system, imported_account ); if ( returned_value == 0 ) tmp_str = last_header; } /* continue untill the end of the file or a change of account */ while ( returned_value != EOF && returned_value != 0 ); /* first, we need to check if the first transaction is an opening balance * or a normal transaction * update : money sometimes translate Opening balance... */ if ( g_slist_length ( imported_account -> operations_importees) > 0 ) { imported_transaction = imported_account -> operations_importees -> data; if ( imported_transaction -> tiers && (!g_ascii_strncasecmp ( imported_transaction -> tiers, "Opening Balance", 15 ) || !g_ascii_strcasecmp ( imported_transaction -> tiers, _("Opening Balance") ) ) ) { /* ok, we are on an opening balance, we transfer the first transaction * to the initial datas of the account */ /* get the initial amount */ imported_account -> solde = imported_transaction -> montant; /* get the name of account */ tmp_str = my_strdelimit (imported_transaction -> categ, "[]", ""); if ( imported_account -> nom_de_compte ) g_free ( imported_account -> nom_de_compte ); imported_account -> nom_de_compte = unique_imported_name ( tmp_str ); g_free (tmp_str); /* get the date of the file */ imported_account -> date_solde_qif = my_strdup ( imported_transaction -> date_tmp ); /* now, we can remove the first imported transaction */ imported_account -> operations_importees = g_slist_remove ( imported_account -> operations_importees, imported_transaction ); g_free (imported_transaction); } /* now we need to transform the dates of transaction into gdate */ /* try to understand the order */ order = gsb_qif_get_date_order ( imported_account -> operations_importees ); if (order == -1) dialogue_error ( _("Grisbi couldn't determine the format of the date into the qif file.\n" "Please contact the Grisbi team ([email protected]) to find " "the problem.\nFor now, all the dates will be imported as 01.01.1970") ); } tmp_list = imported_account -> operations_importees; while (tmp_list) { imported_transaction = tmp_list -> data; if (order == -1) /* we didn't find the order */ imported_transaction -> date = g_date_new_dmy ( 1,1,2000 ); else imported_transaction -> date = gsb_qif_get_date ( imported_transaction -> date_tmp, order ); tmp_list = tmp_list -> next; } /* set the date of the qif file */ if ( imported_account -> date_solde_qif ) imported_account -> date_fin = gsb_qif_get_date (imported_account -> date_solde_qif, order); /* add that account to the others */ liste_comptes_importes = g_slist_append ( liste_comptes_importes, imported_account ); } /* go to the next account */ while ( returned_value != EOF ); fclose ( qif_file ); return ( TRUE ); }
/** * remplit le modèle qu'il crée et attache au GtkIconView * * \param nom de l'icône initiale ou NULL * * \return un GtkTreePath qui donne la position de l'icône passée * en paramètre * */ GtkTreePath * gsb_select_icon_fill_icon_view ( gchar * name_icon ) { GDir *dir; GError *error = NULL; GtkTreePath *tree_path = NULL; devel_debug ( path_icon ); dir = g_dir_open ( path_icon, 0, &error ); if ( dir ) { GtkListStore *store; GtkTreeIter iter; GdkPixbuf *pixbuf; GSList *liste = NULL; gint i = 0; const gchar *name = NULL; while ( (name = g_dir_read_name ( dir ) ) ) { liste = g_slist_append ( liste, g_strdup ( name ) ); } liste = g_slist_sort ( liste, (GCompareFunc) my_strcasecmp ); store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); while ( liste ) { gchar *tmpstr = g_strconcat ( path_icon, G_DIR_SEPARATOR_S, liste -> data, NULL ); if ( g_strcmp0 ( tmpstr, name_icon ) == 0 ) { gchar *tmpstr = utils_str_itoa ( i ); tree_path = gtk_tree_path_new_from_string ( tmpstr ); g_free ( tmpstr ); } pixbuf = gdk_pixbuf_new_from_file_at_size ( tmpstr, 32, 32, NULL); if ( pixbuf ) { gchar *tmpstr; gtk_list_store_append ( store, &iter ); tmpstr = gsb_select_icon_troncate_name_icon ( liste -> data, 10 ); gtk_list_store_set (store, &iter, PIXBUF_COLUMN, pixbuf, TEXT_COLUMN, tmpstr, -1); g_free ( tmpstr ); g_object_unref (pixbuf); } g_free ( tmpstr ); liste = liste -> next; i++; } gtk_icon_view_set_model (GTK_ICON_VIEW ( icon_view ), GTK_TREE_MODEL (store)); g_dir_close ( dir ); } else { dialogue_error ( error -> message ); g_error_free ( error ); } if ( tree_path == NULL ) tree_path = gtk_tree_path_new_from_string ( "0" ); return tree_path; }