1 /* ************************************************************************** */
2 /* */
3 /* Copyright (C) 2000-2008 Cédric Auger (cedric@grisbi.org) */
4 /* 2003-2008 Benjamin Drieu (bdrieu@april.org) */
5 /* 2008-2017 Pierre Biava (grisbi@pierre.biava.name) */
6 /* https://www.grisbi.org/ */
7 /* */
8 /* This program is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation; either version 2 of the License, or */
11 /* (at your option) any later version. */
12 /* */
13 /* This program is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
17 /* */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with this program; if not, write to the Free Software */
20 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21 /* */
22 /* ************************************************************************** */
23
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "include.h"
30 #include <time.h>
31 #include <limits.h>
32 #include <stdlib.h>
33 #include <glib/gstdio.h>
34 #include <glib/gi18n.h>
35
36 #ifdef G_OS_WIN32
37 #include <stdlib.h> // For realpath()
38 #endif /* WIN32 */
39
40 /*START_INCLUDE*/
41 #include "gsb_file.h"
42 #include "accueil.h"
43 #include "dialog.h"
44 #include "etats_gtktable.h"
45 #include "grisbi_app.h"
46 #include "gsb_account_property.h"
47 #include "gsb_assistant_account.h"
48 #include "gsb_data_account.h"
49 #include "gsb_data_archive_store.h"
50 #include "gsb_dirs.h"
51 #include "gsb_file_load.h"
52 #include "gsb_file_save.h"
53 #include "gsb_file_util.h"
54 #include "gsb_real.h"
55 #include "gsb_transactions_list.h"
56 #include "menu.h"
57 #include "navigation.h"
58 #include "parametres.h"
59 #include "structures.h"
60 #include "traitement_variables.h"
61 #include "transaction_list.h"
62 #include "utils.h"
63 #include "utils_dates.h"
64 #include "utils_files.h"
65 #include "utils_str.h"
66 #include "erreur.h"
67 /*END_INCLUDE*/
68
69 /**
70 * keep the last path used in grisbi, save in the configuration at the end */
71 static gchar *last_path_used = NULL;
72
73 static gchar *backup_path = NULL;
74
75 /** the timeout used to save a backup every x minutes */
76 gint id_timeout = 0;
77
78 /*START_EXTERN*/
79 /*END_EXTERN*/
80
81 /******************************************************************************/
82 /* Private Methods */
83 /******************************************************************************/
84 /**
85 *
86 *
87 * \param
88 *
89 * \return
90 **/
gsb_file_remove_old_backup(const gchar * filename,gint remove_backup_months)91 static void gsb_file_remove_old_backup (const gchar *filename,
92 gint remove_backup_months)
93 {
94 GFileEnumerator *direnum;
95 GFile *dir;
96 GDate *first_old_date;
97 GSList *filenames = NULL;
98 GSList *iterator;
99 gchar *basename;
100 gchar *name = NULL;
101
102 devel_debug (filename);
103
104 /* get name of file without extension */
105 basename = g_path_get_basename (filename);
106 if (g_str_has_suffix (basename, ".gsb"))
107 {
108 name = g_strndup (basename, strlen (basename) - 4);
109 g_free (basename);
110 }
111 else
112 {
113 g_free (basename);
114
115 return;
116 }
117
118 if (!name)
119 return;
120
121 /* get today date and first_old_date */
122 first_old_date = gdate_today ();
123 g_date_subtract_months (first_old_date, remove_backup_months);
124
125 /* balayage du répertoire de sauvegarde */
126 dir = g_file_new_for_path (backup_path);
127 direnum = g_file_enumerate_children (dir,
128 "standard::*",
129 G_FILE_QUERY_INFO_NONE,
130 NULL,
131 NULL);
132 if (!direnum)
133 return;
134
135 while (TRUE)
136 {
137 GFileInfo *info = NULL;
138 const gchar *old_filename;
139
140 if (!g_file_enumerator_iterate (direnum, &info, NULL, NULL, NULL))
141 break;
142
143 if (!info)
144 break;
145
146 old_filename = g_file_info_get_name (info);
147 if (old_filename && strlen (old_filename))
148 {
149 if (g_str_has_suffix (old_filename, ".gsb"))
150 {
151 if (name && g_str_has_prefix (old_filename, name))
152 {
153 GDate *date;
154 gchar *str_date;
155 gchar *tmp_year;
156 gchar *tmp_month;
157 gchar *tmp_day;
158 size_t long_name;
159
160 long_name = strlen (name);
161 str_date = g_strndup (old_filename+long_name+1, 8);
162 tmp_year = g_strndup (str_date, 4);
163 if (g_date_valid_year (utils_str_atoi (tmp_year)) == FALSE)
164 {
165 g_free (str_date);
166 g_free (tmp_year);
167
168 continue;
169 }
170 tmp_month = g_strndup (str_date+4, 2);
171 if (g_date_valid_month (utils_str_atoi (tmp_month)) == FALSE)
172 {
173 g_free (str_date);
174 g_free (tmp_year);
175 g_free (tmp_month);
176
177 continue;
178 }
179 tmp_day = g_strndup (str_date+6, 2);
180 if (g_date_valid_day (utils_str_atoi (tmp_day)) == FALSE)
181 {
182 g_free (str_date);
183 g_free (tmp_year);
184 g_free (tmp_month);
185 g_free (tmp_day);
186
187 continue;
188 }
189 date = g_date_new_dmy (utils_str_atoi (tmp_day),
190 utils_str_atoi (tmp_month),
191 utils_str_atoi (tmp_year));
192 if (g_date_valid (date) == FALSE)
193 {
194 g_date_free (date);
195 g_free (str_date);
196 g_free (tmp_year);
197 g_free (tmp_month);
198 g_free (tmp_day);
199
200 continue;
201 }
202 if (g_date_compare (date, first_old_date) < 0)
203 {
204 gchar *tmp_filename;
205
206 tmp_filename = g_build_filename (backup_path, G_DIR_SEPARATOR_S, old_filename, NULL);
207 filenames = g_slist_append (filenames, tmp_filename);
208 }
209 g_date_free (date);
210 g_free (str_date);
211 g_free (tmp_year);
212 g_free (tmp_month);
213 g_free (tmp_day);
214 }
215 }
216 }
217 else
218 {
219 continue;
220 }
221 }
222 g_object_unref (direnum);
223 g_object_unref (dir);
224 g_free (name);
225
226 if (!filenames)
227 {
228 g_date_free (first_old_date);
229
230 return;
231 }
232
233 dialogue_message ("remove-backup-files", g_slist_length (filenames), gsb_format_gdate (first_old_date));
234
235 g_date_free (first_old_date);
236
237 iterator = filenames;
238 while (iterator)
239 {
240 GFile *file;
241 gchar *path;
242
243 path = iterator->data;
244
245 file = g_file_new_for_path (path);
246 g_file_delete (file, FALSE, NULL);
247 iterator = iterator->next;
248 }
249
250 g_slist_free_full (filenames, g_free);
251 }
252
253 /**
254 * teste la validité d'un fichier
255 *
256 * \param const gchar filename
257 *
258 * \return TRUE if OK FALSE other
259 **/
gsb_file_test_file(const gchar * filename)260 static gboolean gsb_file_test_file (const gchar *filename)
261 {
262 gchar* tmp_str1;
263 gchar* tmp_str2;
264
265 if (!filename || !strlen (filename) || !g_file_test (filename, G_FILE_TEST_EXISTS))
266 {
267 tmp_str1 = g_strdup_printf (_("Cannot open file '%s': %s"),
268 filename,
269 _("File does not exist"));
270
271 tmp_str2 = g_strdup_printf (_("Error loading file '%s'"), filename);
272 dialogue_error_hint (tmp_str1, tmp_str2);
273
274 g_free (tmp_str1);
275 g_free (tmp_str2);
276
277 return FALSE;
278 }
279 /* check here if it's not a regular file */
280 if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
281 {
282 tmp_str1 = g_strdup_printf (_("%s doesn't seem to be a regular file,\n"
283 "please check it and try again."),
284 filename);
285 tmp_str2 = g_strdup_printf (_("Error loading file '%s'"),
286 filename);
287 dialogue_error_hint (tmp_str1 , tmp_str2);
288
289 g_free (tmp_str1);
290 g_free (tmp_str2);
291
292 return (FALSE);
293 }
294 return TRUE;
295 }
296
297 /**
298 * ask the name of the file to save it
299 *
300 * \param
301 *
302 * \return a newly allocated string containing the new name
303 **/
gsb_file_dialog_ask_name(const gchar * filename)304 static gchar *gsb_file_dialog_ask_name (const gchar *filename)
305 {
306 gchar *new_name;
307 GtkWidget *dialog;
308 gint result;
309 gchar *tmp_last_directory;
310
311 dialog = gtk_file_chooser_dialog_new (_("Name the accounts file"),
312 GTK_WINDOW (grisbi_app_get_active_window (NULL)),
313 GTK_FILE_CHOOSER_ACTION_SAVE,
314 "gtk-cancel", GTK_RESPONSE_CANCEL,
315 "gtk-save", GTK_RESPONSE_OK,
316 NULL);
317
318 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), gsb_file_get_last_path ());
319 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
320 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
321
322 if (!filename)
323 {
324 gchar* tmp_str;
325 GrisbiWinEtat *w_etat;
326
327 w_etat = (GrisbiWinEtat *) grisbi_win_get_w_etat ();
328
329 tmp_str = g_strconcat (w_etat->accounting_entity, ".gsb", NULL);
330 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), tmp_str);
331 g_free (tmp_str);
332 }
333 else
334 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), filename);
335
336 result = gtk_dialog_run (GTK_DIALOG (dialog));
337
338 switch (result)
339 {
340 case GTK_RESPONSE_OK :
341 new_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
342 tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (dialog), TRUE);
343 gsb_file_update_last_path (tmp_last_directory);
344 g_free (tmp_last_directory);
345 gtk_widget_destroy (GTK_WIDGET (dialog));
346 break;
347
348 default :
349 gtk_widget_destroy (GTK_WIDGET (dialog));
350 return NULL;
351 }
352
353 if (!g_strrstr (new_name, "."))
354 {
355 gchar* tmp_str;
356
357 tmp_str = new_name;
358 new_name = g_strconcat (tmp_str, ".gsb", NULL);
359 g_free (tmp_str);
360 }
361
362 return new_name;
363 }
364
365 /**
366 * propose to save the file if changed
367 * if the current file is not changed, return GTK_RESPONSE_NO directly, without dialog
368 *
369 * \param
370 *
371 * \return GTK_RESPONSE_OK to save, GTK_RESPONSE_NO not to save, other to cancel
372 **/
gsb_file_dialog_save(const gchar * filename,gint origine)373 static gint gsb_file_dialog_save (const gchar *filename,
374 gint origine)
375 {
376 GtkWidget *dialog;
377 gchar *hint = NULL;
378 gchar *message = NULL;
379 gint result;
380
381 dialog = gtk_message_dialog_new (GTK_WINDOW (grisbi_app_get_active_window (NULL)),
382 GTK_DIALOG_DESTROY_WITH_PARENT,
383 GTK_MESSAGE_WARNING,
384 GTK_BUTTONS_NONE,
385 " ");
386 switch (origine)
387 {
388 case -1:
389 {
390 gchar *time_elapsed;
391 time_t now;
392 gint difference;
393
394 now = time (NULL);
395 difference = (int) (difftime (now, run.file_modification));
396 hint = g_strdup_printf (_("Save changes to document '%s' before closing?"),
397 (filename ? g_path_get_basename(filename) : _("unnamed")));
398
399
400 gtk_dialog_add_buttons (GTK_DIALOG(dialog),
401 _("Close without saving"), GTK_RESPONSE_NO,
402 "gtk-cancel", GTK_RESPONSE_REJECT,
403 "gtk-save", GTK_RESPONSE_OK,
404 NULL);
405 if (difference >= 120)
406 {
407 time_elapsed = g_strdup_printf (_("%d minutes and %d seconds"), difference / 60, difference % 60);
408 }
409 else if (difference >= 60)
410 {
411 time_elapsed = g_strdup_printf (_("1 minute and %d seconds"), difference % 60);
412 }
413 else
414 {
415 time_elapsed = g_strdup_printf (_("%d seconds"), difference);
416 }
417 message = g_strdup_printf (_("If you close without saving, all of your changes "
418 "since %s will be discarded."),
419 time_elapsed);
420 g_free (time_elapsed);
421
422
423 break;
424 }
425 default:
426 {
427 hint = g_strdup_printf (_("Save changes in '%s' file?"),
428 (filename ? g_path_get_basename(filename) : _("unnamed")));
429
430 gtk_dialog_add_buttons (GTK_DIALOG(dialog),
431 "gtk-cancel", GTK_RESPONSE_NO,
432 "gtk-save", GTK_RESPONSE_OK,
433 NULL);
434 message = g_strdup("");
435 }
436 }
437 gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
438 g_object_set (G_OBJECT (dialog), "text", hint, "secondary-text", message, NULL);
439
440 g_free (message);
441 g_free (hint);
442
443 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
444
445 result = gtk_dialog_run (GTK_DIALOG (dialog));
446 gtk_widget_destroy (dialog);
447
448 return result;
449 }
450
451 /**
452 * save a backup of the file
453 *
454 * \param
455 *
456 * \return TRUE ok, FALSE problem
457 **/
gsb_file_save_backup(gboolean make_bakup_single_file,gboolean compress_backup)458 static gboolean gsb_file_save_backup (gboolean make_bakup_single_file,
459 gboolean compress_backup)
460 {
461 gboolean retour;
462 gchar *new_filename;
463 const gchar *filename;
464 struct tm *day_time;
465 time_t temps;
466 gchar *name;
467
468 if (!gsb_file_get_backup_path () || !gsb_file_get_modified ())
469 return FALSE;
470
471 grisbi_win_status_bar_message (_("Saving backup"));
472
473 /* on récupère d'abord le nom du fichier */
474 filename = grisbi_win_get_filename (NULL);
475 name = g_path_get_basename (filename);
476 if (g_str_has_suffix (name, ".gsb"))
477 {
478 gchar **tab_str;
479
480 tab_str = g_strsplit (name, ".gsb", 0);
481 if (tab_str[0] && strlen (tab_str[0]))
482 {
483 g_free (name);
484 name = g_strdup (tab_str[0]);
485 }
486 g_strfreev (tab_str);
487 }
488 /* create a filename for the backup :
489 * filename_yyyymmddTmmhhss.gsb */
490 if (make_bakup_single_file)
491 {
492 new_filename = g_strdup_printf ("%s%s%s_backup.gsb",
493 gsb_file_get_backup_path (),
494 G_DIR_SEPARATOR_S,
495 name);
496 }
497 else
498 {
499 time (&temps);
500 day_time = localtime (&temps);
501 new_filename = g_strdup_printf ("%s%s%s_%d%02d%02dT%02d%02d%02d.gsb",
502 gsb_file_get_backup_path (),
503 G_DIR_SEPARATOR_S,
504 name,
505 day_time->tm_year + 1900,
506 day_time->tm_mon + 1,
507 day_time->tm_mday,
508 day_time->tm_hour,
509 day_time->tm_min,
510 day_time->tm_sec);
511 }
512
513 retour = gsb_file_save_save_file (new_filename, compress_backup, 0);
514
515 g_free (new_filename);
516 g_free (name);
517
518 grisbi_win_status_bar_message (_("Done"));
519
520 return (retour);
521 }
522
523 /**
524 * called every x minutes defined by user
525 * to save a backup of the file
526 *
527 * \param null
528 *
529 * \return TRUE to continue the timeout, FALSE to stop the timeout
530 **/
gsb_file_automatic_backup(gpointer p_conf)531 static gboolean gsb_file_automatic_backup (gpointer p_conf)
532 {
533 GrisbiAppConf *a_conf;
534
535 devel_debug (NULL);
536 a_conf = (GrisbiAppConf *) p_conf;
537
538 if (!a_conf->make_backup_every_minutes)
539 /* stop the timeout */
540 return FALSE;
541
542 /* we save only if there is a nb of minutes, but don't stop the timer if not */
543 if (a_conf->make_backup_nb_minutes)
544 gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
545
546 return TRUE;
547 }
548
549 /**
550 * save the file
551 *
552 * \param origine 0 from gsb_file_save (menu), -1 from gsb_file_close, -2 from gsb_file_save_as
553 *
554 * \return TRUE if ok, FALSE if problem
555 **/
gsb_file_save_file(gint origine)556 static gboolean gsb_file_save_file (gint origine)
557 {
558 gint result = 0;
559 gchar *nouveau_nom_enregistrement;
560 gchar *filename;
561 GrisbiAppConf *a_conf;
562
563 devel_debug_int (origine);
564
565 /* on regarde si il y a quelque chose à sauvegarder sauf pour "sauvegarder sous" */
566 if ((!gsb_file_get_modified () && origine != -2)
567 ||
568 !gsb_data_account_get_accounts_amount ())
569 {
570 notice_debug ("nothing done in gsb_file_save_file");
571 return (TRUE);
572 }
573
574 a_conf = grisbi_app_get_a_conf ();
575
576 /* on récupère le nom du fichier */
577 filename = g_strdup (grisbi_win_get_filename (NULL));
578
579 /* on vérifie que le fichier n'est pas locké si il l'est on sort */
580 if (etat.fichier_deja_ouvert && !a_conf->force_enregistrement && origine != -2)
581 {
582 gchar* tmp_str1;
583 gchar* tmp_str2;
584
585 tmp_str1 = g_strdup_printf(_("Grisbi was unable to save this file because it is locked.\n"
586 "Please save it with another name or activate the \"%s\" "
587 "option in preferences."),
588 _("Force saving of locked files"));
589 tmp_str2 = g_strdup_printf(_("Can not save file \"%s\""), filename);
590 dialogue_error_hint (tmp_str1, tmp_str2);
591 g_free (tmp_str1);
592 g_free (tmp_str2);
593
594 return (FALSE);
595 }
596
597 /* on commence par demander si on sauvegarde ou pas sauf pour "sauvegarder sous" */
598 if (!a_conf->sauvegarde_auto && origine != -2)
599 {
600 result = gsb_file_dialog_save (filename, origine);
601 if (result == GTK_RESPONSE_NO)
602 {
603 gsb_file_set_modified (FALSE);
604 return (TRUE);
605 }
606 else if (result != GTK_RESPONSE_OK)
607 {
608 //~ gsb_file_set_modified (FALSE);
609 return (FALSE);
610 }
611 }
612
613 /* si le fichier de comptes n'a pas de nom ou si on enregistre sous un nouveau nom */
614 /* c'est ici */
615 if (!filename || origine == -2)
616 nouveau_nom_enregistrement = gsb_file_dialog_ask_name (filename);
617 else
618 nouveau_nom_enregistrement = g_strdup (filename);
619
620 if (!nouveau_nom_enregistrement)
621 return FALSE;
622
623 /* make backup before saving if asked */
624 if (a_conf->sauvegarde_fermeture)
625 gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
626
627 /* on a maintenant un nom de fichier et on sait qu'on peut sauvegarder */
628 grisbi_win_status_bar_message (_("Saving file"));
629
630 result = gsb_file_save_save_file (nouveau_nom_enregistrement, a_conf->compress_file, 0);
631
632 if (result)
633 {
634 grisbi_win_set_filename (NULL, nouveau_nom_enregistrement);
635
636 /* on ajoute un item au menu recent_file si origine = -2 */
637 if (origine == -2)
638 utils_files_append_name_to_recent_array (nouveau_nom_enregistrement);
639
640 /* saving was right, so unlock the last name */
641 gsb_file_util_modify_lock (filename, FALSE);
642
643 /* and lock the new name */
644 gsb_file_util_modify_lock (nouveau_nom_enregistrement, TRUE);
645
646 /* update variables */
647 etat.fichier_deja_ouvert = 0;
648 gsb_file_set_modified (FALSE);
649 grisbi_win_set_window_title (gsb_gui_navigation_get_current_account ());
650
651 /* Si nettoyage des fichiers de backup on le fait ici */
652 if (a_conf->remove_backup_files)
653 {
654 GrisbiWinRun *w_run;
655
656 w_run = (GrisbiWinRun *) grisbi_win_get_w_run ();
657 if (!w_run->remove_backup_files)
658 {
659 gsb_file_remove_old_backup (nouveau_nom_enregistrement,a_conf->remove_backup_months);
660 w_run->remove_backup_files = TRUE;
661 }
662 }
663 }
664
665 g_free (filename);
666 g_free (nouveau_nom_enregistrement);
667 grisbi_win_status_bar_message (_("Done"));
668
669 return (result);
670 }
671
672 /******************************************************************************/
673 /* Public Methods */
674 /******************************************************************************/
675 /**
676 * come here to finish to create the new file
677 * at this time, categories and currencies must created
678 * this part will just launch the assistant to create a new account
679 * a finish the initialisation to lauch grisbi
680 *
681 * \param
682 *
683 * \return FALSE
684 **/
gsb_file_new_finish(void)685 gboolean gsb_file_new_finish (void)
686 {
687 GrisbiWinRun *w_run;
688
689 /* create the first account */
690 if (!gsb_assistant_account_run ())
691 {
692 init_variables ();
693 return FALSE;
694 }
695
696 /* init the gui */
697 grisbi_win_new_file_gui ();
698
699 mise_a_jour_accueil (TRUE);
700 gsb_gui_navigation_set_selection (GSB_HOME_PAGE, -1, 0);
701
702 /* sensibilise les préférences */
703 w_run = (GrisbiWinRun *) grisbi_win_get_w_run ();
704 w_run->file_is_loading = TRUE;
705
706 gsb_file_set_modified (TRUE);
707 return FALSE;
708 }
709
710 /**
711 * called by file->open
712 * open a new file
713 *
714 * \param
715 *
716 * \return FALSE
717 **/
gsb_file_open_menu(void)718 gboolean gsb_file_open_menu (void)
719 {
720 GtkWidget *selection_fichier;
721 GtkFileFilter * filter;
722 gboolean result = FALSE;
723 gchar *tmp_last_directory;
724 gchar *filename;
725
726 selection_fichier = gtk_file_chooser_dialog_new (_("Open an accounts file"),
727 GTK_WINDOW (grisbi_app_get_active_window (NULL)),
728 GTK_FILE_CHOOSER_ACTION_OPEN,
729 "gtk-cancel", GTK_RESPONSE_CANCEL,
730 "gtk-open", GTK_RESPONSE_OK,
731 NULL);
732
733 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (selection_fichier), gsb_file_get_last_path ());
734 gtk_window_set_position (GTK_WINDOW (selection_fichier), GTK_WIN_POS_CENTER_ON_PARENT);
735
736 filter = gtk_file_filter_new ();
737 gtk_file_filter_set_name (filter, _("Grisbi files (*.gsb)"));
738 gtk_file_filter_add_pattern (filter, "*.gsb");
739 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
740 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
741
742 filter = gtk_file_filter_new ();
743 gtk_file_filter_set_name (filter, _("All files"));
744 gtk_file_filter_add_pattern (filter, "*");
745 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (selection_fichier), filter);
746
747 switch (gtk_dialog_run (GTK_DIALOG (selection_fichier)))
748 {
749 case GTK_RESPONSE_OK:
750 if (gsb_file_close())
751 {
752 gtk_widget_hide (selection_fichier);
753 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (selection_fichier));
754
755 tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (selection_fichier), TRUE);
756 gsb_file_update_last_path (tmp_last_directory);
757 g_free (tmp_last_directory);
758 result = gsb_file_open_file (filename);
759 g_free (filename);
760 }
761 break;
762 default:
763 break;
764 }
765
766 tmp_last_directory = utils_files_selection_get_last_directory (GTK_FILE_CHOOSER (selection_fichier), TRUE);
767 gsb_file_update_last_path (tmp_last_directory);
768 g_free (tmp_last_directory);
769 gtk_widget_destroy (selection_fichier);
770
771 return result;
772 }
773
774 /**
775 * init the variable last_path_used with the path given in param
776 *
777 * \param last_path
778 *
779 * \return
780 **/
gsb_file_init_last_path(const gchar * last_path)781 void gsb_file_init_last_path (const gchar *last_path)
782 {
783 devel_debug (last_path);
784
785 if (last_path && strlen (last_path))
786 {
787 if (last_path_used)
788 g_free (last_path_used);
789
790 last_path_used = my_strdup (last_path);
791 }
792 }
793
794 /**
795 * update the variable last_path_used with the path given in param
796 *
797 * \param last_path
798 *
799 * \return
800 **/
gsb_file_update_last_path(const gchar * last_path)801 void gsb_file_update_last_path (const gchar *last_path)
802 {
803 devel_debug (last_path);
804
805 if (last_path && strlen (last_path))
806 {
807 if (last_path_used)
808 g_free (last_path_used);
809 last_path_used = my_strdup (last_path);
810 }
811 }
812
813 /**
814 * the last_path_used is local variable,
815 * that return the content of that variable
816 *
817 * \param
818 *
819 * \return a const gchar, the last path used in grisbi
820 **/
gsb_file_get_last_path(void)821 const gchar *gsb_file_get_last_path (void)
822 {
823 return last_path_used;
824 }
825
826 /**
827 * get the backup path
828 *
829 * \param
830 *
831 * \return a const gchar with the backup path
832 **/
gsb_file_get_backup_path(void)833 const gchar *gsb_file_get_backup_path (void)
834 {
835 return backup_path;
836 }
837
838 /**
839 * set the backup path
840 *
841 * \param bakcup path
842 *
843 * \return
844 **/
gsb_file_set_backup_path(const gchar * path)845 void gsb_file_set_backup_path (const gchar *path)
846 {
847 /* first free backup_path */
848 if (backup_path)
849 g_free (backup_path);
850
851 if (path == NULL || strlen (path) == 0)
852 backup_path = my_strdup (gsb_dirs_get_user_data_dir ());
853 else
854 backup_path = my_strdup (path);
855
856 if (!g_file_test (path, G_FILE_TEST_EXISTS))
857 {
858 utils_files_create_XDG_dir ();
859 }
860 }
861
862 /**
863 * open a new grisbi file, don't check anything about another opened file that must
864 * have been done before
865 *
866 * \para filename the name of the file
867 *
868 * \return TRUE ok, FALSE problem
869 **/
gsb_file_open_file(const gchar * filename)870 gboolean gsb_file_open_file (const gchar *filename)
871 {
872 GrisbiAppConf *a_conf;
873
874 devel_debug (filename);
875 a_conf = grisbi_app_get_a_conf ();
876
877 if (!gsb_file_test_file (filename))
878 {
879 grisbi_win_stack_box_show (NULL, "accueil_page");
880 return FALSE;
881 }
882
883 grisbi_win_status_bar_wait (TRUE);
884 grisbi_win_status_bar_message (_("Loading accounts"));
885
886 /* initialise les variables d'état */
887 init_variables ();
888
889 /* try to load the file */
890 /* FIXME:BUG under Windows: for unknwon reason yet filename is cleared
891 * when returning from gsb_file_load_open_file!
892 * making application crashes!*/
893
894 if (gsb_file_load_open_file (filename))
895 {
896 /* the file has been opened succesfully */
897 /* on met à jour le nom du fichier */
898 grisbi_win_set_filename (NULL, filename);
899
900 /* mark the file as opened */
901 gsb_file_util_modify_lock (filename, TRUE);
902
903 /* we make a backup if necessary */
904 if (a_conf->sauvegarde_demarrage)
905 {
906 gsb_file_save_backup (a_conf->make_bakup_single_file, a_conf->compress_backup);
907 }
908 }
909 else
910 {
911 #ifdef HAVE_SSL
912 gchar *tmp_str1;
913 gchar *tmp_str2;
914 GrisbiWinRun *w_run;
915 #endif
916
917 /* Loading failed. */
918 grisbi_win_status_bar_message (_("Failed to load accounts"));
919
920 #ifdef HAVE_SSL
921 w_run = grisbi_win_get_w_run ();
922 if (w_run->old_version)
923 {
924 dialogue_error_hint (_("The version of your file is less than 0.6. "
925 "This file can not be imported by Grisbi."),
926 _("Version of Grisbi file too old :"));
927 grisbi_win_status_bar_stop_wait (TRUE);
928
929 return FALSE;
930 }
931
932 tmp_str1 = g_strdup_printf (_("Error loading file '%s'"), filename);
933
934 if (a_conf->sauvegarde_demarrage || a_conf->sauvegarde_fermeture || a_conf->make_backup_every_minutes)
935 {
936 tmp_str2 = g_strdup_printf (_("Grisbi was unable to load file. You should find the last "
937 "backups in '%s', they are saved with date and time into "
938 "their name so you should find easily the last backup "
939 "saved.\n"
940 "Please contact the Grisbi's team on devel@listes.grisbi.org "
941 "to find what happened to you current file."),
942 gsb_file_get_backup_path ());
943 }
944 else
945 {
946 if (gsb_file_get_backup_path ())
947 tmp_str2 = g_strdup_printf ( _("Grisbi was unable to load file and the backups seem not to "
948 "be activated... This is a bad thing.\nYour backup path is '%s', "
949 "try to find if earlier you had some backups in there ?\n"
950 "Please contact the Grisbi's team on devel@listes.grisbi.org "
951 "to find what happened to you current file."),
952 gsb_file_get_backup_path ());
953 else
954 tmp_str2 = my_strdup (_("Grisbi was unable to load file and the backups seem not "
955 "to be activated... This is a bad thing.\n"
956 "Please contact the Grisbi's team on "
957 "devel@listes.grisbi.org to find what happened to you "
958 "current file."));
959 }
960 dialogue_error_hint (tmp_str2, tmp_str1);
961 g_free (tmp_str1);
962 g_free (tmp_str2);
963 #endif
964 grisbi_win_status_bar_stop_wait (TRUE);
965 grisbi_win_stack_box_show (NULL, "accueil_page");
966 return FALSE;
967 }
968
969 /* ok, here the file or backup is loaded */
970 grisbi_win_status_bar_message (_("Checking schedulers"));
971
972 /* create the archives store data, ie the transaction which will replace the archive in
973 * the list of transactions */
974 gsb_data_archive_store_create_list ();
975
976 /* create all the gui */
977 grisbi_win_new_file_gui ();
978
979 /* check the amounts of all the accounts */
980 grisbi_win_status_bar_message (_("Checking amounts"));
981 gsb_data_account_set_all_limits_of_balance ();
982
983 /* set Grisbi title */
984 grisbi_win_set_window_title (-1);
985
986 /* for now, the flag for modification of the file is ok, but the menu couldn't be set
987 * as sensitive/unsensitive so do it now */
988 gsb_file_set_modified (gsb_file_get_modified ());
989
990 grisbi_win_status_bar_message (_("Done"));
991 grisbi_win_status_bar_stop_wait (TRUE);
992
993 /* go to the home page */
994 gsb_gui_navigation_set_selection (GSB_HOME_PAGE, -1, 0);
995
996 /* set the focus to the selection tree at left */
997 gtk_widget_grab_focus (gsb_gui_navigation_get_tree_view ());
998
999 return TRUE;
1000 }
1001
1002 /**
1003 * Perform the "Save" feature in menu
1004 *
1005 * \return TRUE on success. FALSE otherwise.
1006 */
gsb_file_save(void)1007 gboolean gsb_file_save (void)
1008 {
1009 return gsb_file_save_file (0);
1010 }
1011
1012 /**
1013 * Perform the "Save as" feature in menu
1014 *
1015 * \return TRUE on success. FALSE otherwise.
1016 */
gsb_file_save_as(void)1017 gboolean gsb_file_save_as (void)
1018 {
1019 return gsb_file_save_file (-2);
1020 }
1021
1022 /**
1023 * called when the user select the backup every x minutes
1024 *
1025 * \param checkbutton
1026 * \param null
1027 *
1028 * \return FALSE
1029 **/
gsb_file_automatic_backup_start(GtkWidget * checkbutton,gpointer null)1030 gboolean gsb_file_automatic_backup_start (GtkWidget *checkbutton,
1031 gpointer null)
1032 {
1033 GrisbiAppConf *a_conf;
1034
1035 a_conf = grisbi_app_get_a_conf ();
1036 devel_debug_int (a_conf->make_backup_every_minutes);
1037
1038 /* if there is already a timeout, we remove it */
1039 if (id_timeout)
1040 {
1041 g_source_remove (id_timeout);
1042 id_timeout = 0;
1043 }
1044
1045 /* launch the timeout only if active and if there is some minutes */
1046 if (a_conf->make_backup_every_minutes && a_conf->make_backup_nb_minutes)
1047 id_timeout = g_timeout_add_seconds (a_conf->make_backup_nb_minutes * 60,
1048 gsb_file_automatic_backup,
1049 a_conf);
1050 return FALSE;
1051 }
1052
1053 /**
1054 * called when the user change the interval of automatic backup
1055 *
1056 * \param spinbutton
1057 * \param null
1058 *
1059 * \return FALSE
1060 **/
gsb_file_automatic_backup_change_time(GtkWidget * spinbutton,gpointer null)1061 gboolean gsb_file_automatic_backup_change_time (GtkWidget *spinbutton,
1062 gpointer null)
1063 {
1064 GrisbiAppConf *a_conf;
1065
1066 a_conf = grisbi_app_get_a_conf ();
1067 devel_debug_int (a_conf->make_backup_every_minutes);
1068
1069 /* if there is already a timeout, we stop it */
1070 if (id_timeout)
1071 {
1072 g_source_remove (id_timeout);
1073 id_timeout = 0;
1074 }
1075
1076 /* set a new timeout only if there is an interval */
1077 if (a_conf->make_backup_nb_minutes)
1078 id_timeout = g_timeout_add_seconds (a_conf->make_backup_nb_minutes * 60,
1079 gsb_file_automatic_backup,
1080 a_conf);
1081
1082 return FALSE;
1083 }
1084
1085 /**
1086 * close the file
1087 * if no file loaded or no change, directly return TRUE
1088 *
1089 * \param
1090 *
1091 * \return FALSE if problem, TRUE if ok
1092 **/
gsb_file_close(void)1093 gboolean gsb_file_close (void)
1094 {
1095 gchar *filename;
1096 GrisbiAppConf *a_conf;
1097
1098 devel_debug (NULL);
1099 if (!assert_account_loaded ())
1100 {
1101 return TRUE;
1102 }
1103
1104 a_conf = grisbi_app_get_a_conf ();
1105
1106 /* on récupère le nom du fichier */
1107 filename = g_strdup (grisbi_win_get_filename (NULL));
1108
1109 if (gsb_file_get_modified ())
1110 {
1111 /* try to save */
1112 if (!gsb_file_save_file (-1))
1113 return FALSE;
1114 }
1115 else if (a_conf->sauvegarde_auto && filename)
1116 {
1117 /* try to save */
1118 if (!gsb_file_save_file (-1))
1119 return FALSE;
1120 }
1121
1122 if (!gsb_file_get_modified ())
1123 {
1124 /* remove the lock */
1125 if (!etat.fichier_deja_ouvert
1126 &&
1127 gsb_data_account_get_accounts_amount ()
1128 &&
1129 filename)
1130 {
1131 gsb_file_util_modify_lock (filename, FALSE);
1132 }
1133
1134 /* free all the variables */
1135 etats_gtktable_free_table_etat (); /* set table_etat = NULL: fix crash loading a multiple accounts files */
1136 init_variables ();
1137 grisbi_win_free_general_vbox ();
1138 gsb_account_property_clear_config ();
1139 grisbi_win_set_filename (NULL, NULL);
1140
1141 grisbi_win_set_window_title (-1);
1142
1143 /* unsensitive the necessaries menus */
1144 gsb_menu_set_menus_with_file_sensitive (FALSE);
1145 grisbi_win_menu_move_to_acc_delete ();
1146
1147 g_free (filename);
1148 return TRUE;
1149 }
1150
1151 return FALSE;
1152 }
1153
1154 /**
1155 * set or unset the modified flag (run structure)
1156 * and sensitive or not the menu to save the file
1157 *
1158 * \param modif TRUE to set the modified flag, FALSE to unset
1159 *
1160 * \return
1161 */
gsb_file_set_modified(gboolean modified)1162 void gsb_file_set_modified (gboolean modified)
1163 {
1164 /* devel_debug_int (modified); */
1165
1166 /* If no file is loaded, do not change menu items. */
1167 if (!gsb_data_account_get_accounts_amount ())
1168 return;
1169
1170 if (modified)
1171 {
1172 /* modification pour gerer la non modification par la recherche dans la liste des operations */
1173 run.file_modification = time (NULL);
1174 gsb_menu_gui_sensitive_win_menu_item ("save", TRUE);
1175 }
1176 else
1177 {
1178 run.file_modification = 0;
1179 gsb_menu_gui_sensitive_win_menu_item ("save", FALSE);
1180 }
1181 }
1182
1183 /**
1184 * Tell if the current file has been modified or not
1185 *
1186 * \return TRUE if modified, FALSE otherwise
1187 */
gsb_file_get_modified(void)1188 gboolean gsb_file_get_modified (void)
1189 {
1190 if (run.file_modification == 0)
1191 return FALSE;
1192 else
1193 return TRUE;
1194 }
1195
1196 /**
1197 * free the last_path path
1198 *
1199 * \param
1200 *
1201 * \return
1202 **/
gsb_file_free_last_path(void)1203 void gsb_file_free_last_path (void)
1204 {
1205 if (last_path_used)
1206 {
1207 g_free (last_path_used);
1208 last_path_used = NULL;
1209 }
1210 }
1211
1212 /**
1213 * free the backup path
1214 *
1215 * \param
1216 *
1217 * \return
1218 **/
gsb_file_free_backup_path(void)1219 void gsb_file_free_backup_path (void)
1220 {
1221 if (backup_path)
1222 {
1223 g_free (backup_path);
1224 backup_path = NULL;
1225 }
1226 }
1227
1228 /**
1229 * copy an old grisbi file
1230 *
1231 * \param filename the name of the file
1232 *
1233 * \return
1234 **/
gsb_file_copy_old_file(const gchar * filename)1235 void gsb_file_copy_old_file (const gchar *filename)
1236 {
1237 if (g_str_has_suffix (filename, ".gsb"))
1238 {
1239 GFile *file_ori;
1240 GFile *file_copy;
1241 GError *error = NULL;
1242 gchar *copy_old_filename;
1243 gchar *tmp_str;
1244
1245 copy_old_filename = g_path_get_basename (filename);
1246 tmp_str = copy_old_filename;
1247 copy_old_filename = gsb_string_remplace_string (copy_old_filename, ".gsb", "-old-version.gsb");
1248 g_free (tmp_str);
1249 tmp_str = copy_old_filename;
1250 copy_old_filename = g_build_filename (gsb_dirs_get_user_data_dir (), copy_old_filename, NULL);
1251 g_free (tmp_str);
1252
1253 file_ori = g_file_new_for_path (filename);
1254 file_copy = g_file_new_for_path (copy_old_filename);
1255
1256 if (!g_file_copy (file_ori, file_copy, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error))
1257 {
1258 dialogue_error (error->message);
1259 g_error_free (error);
1260 }
1261 else
1262 {
1263 tmp_str = g_strdup_printf (_("The original file was saved saved as:\n"
1264 "\"%s\"."),
1265 copy_old_filename);
1266
1267 dialogue_warning (tmp_str);
1268 g_free (tmp_str);
1269 }
1270 g_free (copy_old_filename);
1271 g_object_unref (file_ori);
1272 g_object_unref (file_copy);
1273 }
1274 }
1275 /**
1276 * Fonction de fermeture de grisbi sans appeler la fonction init_variables ().
1277 * Demandera une clarification de la libération des variables.
1278 *
1279 * \param
1280 *
1281 * \return
1282 **/
gsb_file_quit(void)1283 gboolean gsb_file_quit (void)
1284 {
1285 gchar *filename;
1286 GrisbiAppConf *a_conf;
1287
1288 devel_debug (NULL);
1289 if (!assert_account_loaded ())
1290 {
1291 return TRUE;
1292 }
1293
1294 a_conf = grisbi_app_get_a_conf ();
1295
1296 /* on récupère le nom du fichier */
1297 filename = g_strdup (grisbi_win_get_filename (NULL));
1298
1299 if (gsb_file_get_modified ())
1300 {
1301 /* try to save */
1302 if (!gsb_file_save_file (-1))
1303 return FALSE;
1304 }
1305 else if (a_conf->sauvegarde_auto && filename)
1306 {
1307 /* try to save */
1308 if (!gsb_file_save_file (-1))
1309 return FALSE;
1310 }
1311
1312 if (!gsb_file_get_modified ())
1313 {
1314 /* remove the lock */
1315 if (!etat.fichier_deja_ouvert
1316 &&
1317 gsb_data_account_get_accounts_amount ()
1318 &&
1319 filename)
1320 {
1321 gsb_file_util_modify_lock (filename, FALSE);
1322 }
1323
1324 /* free all the variables */
1325 etats_gtktable_free_table_etat (); /* set table_etat = NULL: fix crash loading a multiple accounts files */
1326 grisbi_win_free_general_vbox ();
1327 gsb_account_property_clear_config ();
1328 grisbi_win_set_filename (NULL, NULL);
1329
1330 grisbi_win_set_window_title (-1);
1331 grisbi_win_menu_move_to_acc_delete ();
1332
1333 g_free (filename);
1334 return TRUE;
1335 }
1336
1337 return FALSE;
1338 }
1339
1340 /**
1341 *
1342 *
1343 * \param
1344 *
1345 * \return
1346 **/
1347 /* Local Variables: */
1348 /* c-basic-offset: 4 */
1349 /* End: */
1350