import homebank-5.2.4
[chaz/homebank] / src / homebank.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "dsp-mainwindow.h"
24 #include "hb-preferences.h"
25 #include "language.h"
26
27
28 #ifdef G_OS_WIN32
29 #include <windows.h>
30 #endif
31
32 #define APPLICATION_NAME "HomeBank"
33
34
35 /****************************************************************************/
36 /* Debug macros */
37 /****************************************************************************/
38 #define MYDEBUG 0
39
40 #if MYDEBUG
41 #define DB(x) (x);
42 #else
43 #define DB(x);
44 #endif
45
46 /* our global datas */
47 struct HomeBank *GLOBALS;
48 struct Preferences *PREFS;
49
50
51 /* installation paths */
52 static gchar *config_dir = NULL;
53 static gchar *images_dir = NULL;
54 static gchar *pixmaps_dir = NULL;
55 static gchar *locale_dir = NULL;
56 static gchar *help_dir = NULL;
57 static gchar *datas_dir = NULL;
58
59
60 //#define MARKUP_STRING "<span size='small'>%s</span>"
61
62
63 /* Application arguments */
64 static gboolean arg_version = FALSE;
65 static gchar **files = NULL;
66
67 static GOptionEntry option_entries[] =
68 {
69 { "version", '\0', 0, G_OPTION_ARG_NONE, &arg_version,
70 N_("Output version information and exit"), NULL },
71
72 { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &files,
73 NULL, N_("[FILE]") },
74
75 { NULL }
76 };
77
78
79 /*
80 ** try to determine the file type (if supported for import by homebank)
81 **
82 **
83 */
84 gint homebank_alienfile_recognize(gchar *filename)
85 {
86 GIOChannel *io;
87 gint i, retval = FILETYPE_UNKNOWN;
88 gchar *tmpstr;
89 gint io_stat;
90 GError *err = NULL;
91 static gint csvtype[7] = {
92 CSV_DATE,
93 CSV_INT,
94 CSV_STRING,
95 CSV_STRING,
96 CSV_STRING,
97 CSV_DOUBLE,
98 CSV_STRING,
99 };
100
101
102 DB( g_print("\n[homebank] alienfile_recognize\n") );
103
104
105 io = g_io_channel_new_file(filename, "r", NULL);
106 if(io != NULL)
107 {
108 g_io_channel_set_encoding(io, NULL, NULL); /* set to binary mode */
109
110 for(i=0;i<25;i++)
111 {
112 if( retval != FILETYPE_UNKNOWN )
113 break;
114
115 io_stat = g_io_channel_read_line(io, &tmpstr, NULL, NULL, &err);
116 if( io_stat == G_IO_STATUS_EOF)
117 break;
118 if( io_stat == G_IO_STATUS_ERROR )
119 {
120 DB (g_print(" + ERROR %s\n",err->message));
121 break;
122 }
123 if( io_stat == G_IO_STATUS_NORMAL)
124 {
125 if( *tmpstr != '\0' )
126 {
127 DB( g_print(" line %d: '%s' retval=%d\n", i, tmpstr, retval) );
128
129 /* native homebank file */
130 if( g_str_has_prefix(tmpstr, "<homebank v="))
131 {
132 DB( g_print(" type is HomeBank\n") );
133 retval = FILETYPE_HOMEBANK;
134 }
135 else
136
137 // QIF file ?
138 if( g_str_has_prefix(tmpstr, "!Type") ||
139 g_str_has_prefix(tmpstr, "!type") ||
140 g_str_has_prefix(tmpstr, "!Option") ||
141 g_str_has_prefix(tmpstr, "!option") ||
142 g_str_has_prefix(tmpstr, "!Account") ||
143 g_str_has_prefix(tmpstr, "!account")
144 )
145 {
146 DB( g_print(" type is QIF\n") );
147 retval = FILETYPE_QIF;
148 }
149 else
150
151 /* is it OFX ? */
152 if( g_strstr_len(tmpstr, -1, "<OFX>") != NULL
153 || g_strstr_len(tmpstr, -1, "<ofx>") != NULL
154 /*|| strcasestr(tmpstr, "<OFC>") != NULL*/
155 )
156 {
157 DB( g_print(" type is OFX\n") );
158 retval = FILETYPE_OFX;
159 }
160
161 /* is it csv homebank ? */
162 else
163 {
164 gchar **str_array;
165 gboolean isvalid = FALSE;
166
167 hb_string_strip_crlf(tmpstr);
168 str_array = hb_csv_row_get(tmpstr, ";", 8);
169 isvalid = hb_csv_row_valid(str_array, 8, csvtype);
170
171 DB( g_print(" hbcsv %d\n", isvalid) );
172
173 if( isvalid == TRUE )
174 {
175 DB( g_print(" type is CSV homebank\n") );
176 retval = FILETYPE_CSV_HB;
177 }
178
179 g_strfreev (str_array);
180 }
181 g_free(tmpstr);
182 }
183 }
184 }
185 g_io_channel_unref (io);
186 }
187
188 return retval;
189 }
190
191
192 /* = = = = = = = = = = = = = = = = = = = = */
193
194
195 /*
196 ** ensure the filename ends with '.xhb'
197 */
198 void homebank_file_ensure_xhb(gchar *filename)
199 {
200 DB( g_print("\n[homebank] file_ensure_xhb\n") );
201 filename = (filename == NULL) ? g_strdup(GLOBALS->xhb_filepath) : filename;
202 if( g_str_has_suffix (filename, ".xhb") == FALSE )
203 {
204 gchar *newfilename;
205
206 newfilename = hb_filename_new_with_extension(filename, "xhb");
207 hbfile_change_filepath(newfilename);
208 DB( g_print(" - changed to: '%s'\n", GLOBALS->xhb_filepath) );
209 }
210 //#1460390
211 else
212 {
213 hbfile_change_filepath(filename);
214 }
215 }
216
217
218 static gboolean homebank_file_copy(gchar *srcfile, gchar *dstfile)
219 {
220 gchar *buffer;
221 gsize length;
222 //GError *error = NULL;
223 gboolean retval = FALSE;
224
225 DB( g_print("\n[homebank] file copy\n") );
226
227 if (g_file_get_contents (srcfile, &buffer, &length, NULL))
228 {
229 if(g_file_set_contents(dstfile, buffer, length, NULL))
230 {
231 retval = TRUE;
232 }
233 g_free(buffer);
234 }
235
236 DB( g_print(" - copied '%s' => '%s' :: %d\n", srcfile, dstfile, retval) );
237 return retval;
238 }
239
240
241 static gboolean homebank_file_delete_existing(gchar *filepath)
242 {
243 gboolean retval = FALSE;
244
245 DB( g_print("\n[homebank] file delete existing\n") );
246
247 if( g_file_test(filepath, G_FILE_TEST_EXISTS) )
248 {
249 DB( g_print(" - deleting: '%s'\n", filepath) );
250 g_remove(filepath);
251 retval = TRUE;
252 }
253 else
254 {
255 DB( g_print(" - cannot delete: '%s'\n", filepath) );
256 }
257
258 return retval;
259 }
260
261
262 void homebank_backup_current_file(void)
263 {
264 gchar *bakfilename;
265 GPtrArray *array;
266 gint i;
267
268 DB( g_print("\n[homebank] backup_current_file\n") );
269
270 //do normal linux backup file
271 DB( g_print(" normal backup with ~\n") );
272 bakfilename = hb_filename_new_with_extension (GLOBALS->xhb_filepath, "xhb~");
273 homebank_file_delete_existing(bakfilename);
274 //#512046 copy file not to broke potential links
275 //retval = g_rename(pathname, newname);
276 homebank_file_copy (GLOBALS->xhb_filepath, bakfilename);
277 g_free(bakfilename);
278
279 //do safe backup according to user preferences
280 DB( g_print(" user pref backup\n") );
281 if( PREFS->bak_is_automatic == TRUE )
282 {
283 bakfilename = hb_filename_new_for_backup(GLOBALS->xhb_filepath);
284 if( g_file_test(bakfilename, G_FILE_TEST_EXISTS) == FALSE )
285 {
286 homebank_file_copy (GLOBALS->xhb_filepath, bakfilename);
287 }
288 g_free(bakfilename);
289
290 //delete any offscale backup
291 DB( g_print(" clean old backup\n") );
292 array = hb_filename_backup_list(GLOBALS->xhb_filepath);
293
294 DB( g_print(" found %d match\n", array->len) );
295
296 gchar *dirname = g_path_get_dirname(GLOBALS->xhb_filepath);
297
298 for(i=0;i<(gint)array->len;i++)
299 {
300 gchar *offscalefilename = g_ptr_array_index(array, i);
301
302 DB( g_print(" %d : '%s'\n", i, offscalefilename) );
303 if( i >= PREFS->bak_max_num_copies )
304 {
305 gchar *bakdelfilepath = g_build_filename(dirname, offscalefilename, NULL);
306
307 DB( g_print(" - should delete '%s'\n", bakdelfilepath) );
308
309 homebank_file_delete_existing(bakdelfilepath);
310
311 g_free(bakdelfilepath);
312 }
313 }
314 g_ptr_array_free(array, TRUE);
315
316 g_free(dirname);
317 }
318
319 }
320
321
322 /* = = = = = = = = = = = = = = = = = = = = */
323 /* url open */
324
325
326 #ifdef G_OS_WIN32
327 #define SW_NORMAL 1
328
329 static gboolean
330 homebank_util_url_show_win32 (const gchar *url)
331 {
332 int retval;
333 gchar *errmsg;
334
335 /* win32 API call */
336 retval = ShellExecuteA (NULL, "open", url, NULL, NULL, SW_NORMAL);
337
338 if (retval < 0 || retval > 32)
339 return TRUE;
340
341 errmsg = g_win32_error_message(retval);
342 DB( g_print ("%s\n", errmsg) );
343 g_free(errmsg);
344
345 return FALSE;
346 }
347
348 #else
349
350 static gboolean
351 homebank_util_url_show_unix (const gchar *url)
352 {
353 gboolean retval;
354 GError *err = NULL;
355
356 retval = gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (GLOBALS->mainwindow)), url, GDK_CURRENT_TIME, &err);
357
358 if (!retval)
359 {
360 ui_dialog_msg_infoerror(GTK_WINDOW(GLOBALS->mainwindow), GTK_MESSAGE_ERROR,
361 _("Browser error."),
362 _("Could not display the URL '%s'"),
363 url
364 );
365 }
366
367 if(err != NULL)
368 {
369 g_print ("%s\n", err->message);
370 g_error_free (err);
371 }
372
373 return retval;
374 }
375
376 #endif
377
378 gboolean
379 homebank_util_url_show (const gchar *url)
380 {
381
382 if(url == NULL)
383 return FALSE;
384
385
386 #ifdef G_OS_WIN32
387 return homebank_util_url_show_win32 (url);
388 #else
389 return homebank_util_url_show_unix (url);
390 #endif
391 }
392
393
394 /* = = = = = = = = = = = = = = = = = = = = */
395 /* lastopenedfiles */
396
397 /*
398 ** load lastopenedfiles from homedir/.homebank
399 */
400 gchar *homebank_lastopenedfiles_load(void)
401 {
402 GKeyFile *keyfile;
403 gchar *group, *filename, *tmpfilename;
404 gchar *lastfilename = NULL;
405 GError *error = NULL;
406
407 DB( g_print("\n[homebank] lastopenedfiles load\n") );
408
409 keyfile = g_key_file_new();
410 if(keyfile)
411 {
412 filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
413 if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error))
414 {
415 group = "HomeBank";
416
417 if(g_key_file_has_key(keyfile, group, "LastOpenedFile", NULL))
418 {
419 tmpfilename = g_key_file_get_string (keyfile, group, "LastOpenedFile", NULL);
420 // #593082
421 if (g_file_test (tmpfilename, G_FILE_TEST_EXISTS) != FALSE)
422 {
423 lastfilename = tmpfilename;
424 }
425 }
426 }
427
428 if( error )
429 {
430 g_print("failed: %s\n", error->message);
431 g_error_free (error);
432 }
433
434 g_free(filename);
435 g_key_file_free (keyfile);
436 }
437
438 return lastfilename;
439 }
440
441
442 /*
443 ** save lastopenedfiles to homedir/.homebank (HB_DATA_PATH)
444 */
445 gboolean homebank_lastopenedfiles_save(void)
446 {
447 GKeyFile *keyfile;
448 gboolean retval = FALSE;
449 gchar *group, *filename;
450 gsize length;
451 GError *error = NULL;
452
453 DB( g_print("\n[homebank] lastopenedfiles save\n") );
454
455 if( GLOBALS->xhb_filepath != NULL )
456 {
457 //don't save bakup files
458 if( hbfile_file_isbackup(GLOBALS->xhb_filepath) == FALSE )
459 {
460 keyfile = g_key_file_new();
461 if(keyfile )
462 {
463 DB( g_print(" - saving '%s'\n", GLOBALS->xhb_filepath) );
464
465 group = "HomeBank";
466 g_key_file_set_string (keyfile, group, "LastOpenedFile", GLOBALS->xhb_filepath);
467
468 gchar *contents = g_key_file_to_data( keyfile, &length, NULL);
469
470 //DB( g_print(" keyfile:\n%s\nlen=%d\n", contents, length) );
471
472 filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
473
474 g_file_set_contents(filename, contents, length, &error);
475 g_free(filename);
476
477 if( error )
478 {
479 g_print("failed: %s\n", error->message);
480 g_error_free (error);
481 }
482
483 g_free(contents);
484 g_key_file_free (keyfile);
485 }
486 }
487 }
488
489 return retval;
490 }
491
492
493
494 /* = = = = = = = = = = = = = = = = = = = = */
495 /* Main homebank */
496 #ifdef G_OS_WIN32
497 static GtkCssProvider *provider;
498
499 static void
500 homebank_theme_changed (GtkSettings *settings, GParamSpec *pspec, gpointer data)
501 {
502
503 if (pspec == NULL || g_str_equal (pspec->name, "gtk-theme-name"))
504 {
505 gchar *theme;
506 GdkScreen *screen;
507
508 g_object_get (settings, "gtk-theme-name", &theme, NULL);
509 screen = gdk_screen_get_default ();
510
511 DB( g_print("theme %s\n", theme) );
512
513 if (g_str_equal (theme, "gtk-win32"))
514 {
515 if (provider == NULL)
516 {
517 gchar *filename;
518
519 filename = g_build_filename(homebank_app_get_datas_dir(), "homebank-gtk-win32.css", NULL );
520 DB( g_print("tweak file %s\n", filename) );
521
522 if( g_file_test(filename, G_FILE_TEST_EXISTS) )
523 {
524 provider = gtk_css_provider_new ();
525 gtk_css_provider_load_from_path (provider, filename, NULL);
526 }
527 g_free (filename);
528 }
529
530 if(provider != NULL)
531 {
532 DB( g_print(" assign provider %p to screen %p\n", provider, screen) );
533
534 gtk_style_context_add_provider_for_screen (screen,
535 GTK_STYLE_PROVIDER (provider),
536 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
537 }
538 }
539 else if (provider != NULL)
540 {
541 gtk_style_context_remove_provider_for_screen (screen,
542 GTK_STYLE_PROVIDER (provider));
543 g_clear_object (&provider);
544 }
545
546 g_free (theme);
547 }
548 }
549
550 static void
551 homebank_setup_theme_extensions (void)
552 {
553 GtkSettings *settings;
554
555 settings = gtk_settings_get_default ();
556 provider = NULL;
557 g_signal_connect (settings, "notify", G_CALLBACK (homebank_theme_changed), NULL);
558 homebank_theme_changed (settings, NULL, NULL);
559 }
560 #endif
561
562
563 static void
564 homebank_icon_theme_setup()
565 {
566 DB( g_print("\n[homebank] icon_theme_setup\n") );
567
568 GLOBALS->icontheme = gtk_icon_theme_get_default();
569
570 DB( g_print(" - prepend theme search path: %s\n", homebank_app_get_pixmaps_dir()) );
571 gtk_icon_theme_prepend_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir());
572 //DB( g_print(" - append theme search path: %s\n", homebank_app_get_pixmaps_dir()) );
573 //gtk_icon_theme_append_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir());
574
575
576 #if MYDEBUG == 1
577 GtkIconTheme *ic = gtk_icon_theme_get_default();
578 guint i;
579 gchar **paths;
580
581 DB( g_print(" - get default icon theme\n") );
582
583 gtk_icon_theme_get_search_path(ic, &paths, NULL);
584 for(i=0;i<g_strv_length(paths);i++)
585 {
586 g_print(" - path %d: %s\n", i, paths[i]);
587 }
588
589 g_strfreev(paths);
590
591 #endif
592
593
594 }
595
596
597 const gchar *
598 homebank_app_get_config_dir (void)
599 {
600 return config_dir;
601 }
602
603 const gchar *
604 homebank_app_get_images_dir (void)
605 {
606 return images_dir;
607 }
608
609 const gchar *
610 homebank_app_get_pixmaps_dir (void)
611 {
612 return pixmaps_dir;
613 }
614
615 const gchar *
616 homebank_app_get_locale_dir (void)
617 {
618 return locale_dir;
619 }
620
621 const gchar *
622 homebank_app_get_help_dir (void)
623 {
624 return help_dir;
625 }
626
627 const gchar *
628 homebank_app_get_datas_dir (void)
629 {
630 return datas_dir;
631 }
632
633
634 /* build package paths at runtime */
635 static void
636 build_package_paths (void)
637 {
638 DB( g_print("\n[homebank] build_package_paths\n") );
639
640 #ifdef G_OS_WIN32
641 gchar *prefix;
642
643 prefix = g_win32_get_package_installation_directory_of_module (NULL);
644 locale_dir = g_build_filename (prefix, "share", "locale", NULL);
645 images_dir = g_build_filename (prefix, "share", PACKAGE, "images", NULL);
646 pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "icons", NULL);
647 help_dir = g_build_filename (prefix, "share", PACKAGE, "help", NULL);
648 datas_dir = g_build_filename (prefix, "share", PACKAGE, "datas", NULL);
649 #ifdef PORTABLE_APP
650 DB( g_print(" - app is portable under windows\n") );
651 config_dir = g_build_filename(prefix, "config", NULL);
652 #else
653 config_dir = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL);
654 #endif
655 g_free (prefix);
656 #else
657 locale_dir = g_build_filename (DATA_DIR, "locale", NULL);
658 images_dir = g_build_filename (SHARE_DIR, "images", NULL);
659 pixmaps_dir = g_build_filename (DATA_DIR, PACKAGE, "icons", NULL);
660 help_dir = g_build_filename (DATA_DIR, PACKAGE, "help", NULL);
661 datas_dir = g_build_filename (DATA_DIR, PACKAGE, "datas", NULL);
662 config_dir = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL);
663
664 //#870023 Ubuntu packages the help files in "/usr/share/doc/homebank-data/help/" for some strange reason
665 if(! g_file_test(help_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
666 {
667 g_free (help_dir);
668 help_dir = g_build_filename ("/usr", "share", "doc", "homebank-data", "help", NULL);
669 }
670 #endif
671
672 DB( g_print(" - config_dir : %s\n", config_dir) );
673 DB( g_print(" - images_dir : %s\n", images_dir) );
674 DB( g_print(" - pixmaps_dir: %s\n", pixmaps_dir) );
675 DB( g_print(" - locale_dir : %s\n", locale_dir) );
676 DB( g_print(" - help_dir : %s\n", help_dir) );
677 DB( g_print(" - datas_dir : %s\n", datas_dir) );
678
679 }
680
681
682 guint32 homebank_app_date_get_julian(void)
683 {
684 GDate *date;
685 //init global default value
686 date = g_date_new();
687 g_date_set_time_t(date, time(NULL));
688 GLOBALS->today = g_date_get_julian(date);
689 g_date_free(date);
690 return GLOBALS->today;
691 }
692
693
694 static gboolean homebank_check_app_dir_migrate_file(gchar *srcdir, gchar *dstdir, gchar *filename)
695 {
696 gchar *srcpath;
697 gchar *dstpath;
698 gchar *buffer;
699 gsize length;
700 //GError *error = NULL;
701 gboolean retval = FALSE;
702
703 DB( g_print("\n[homebank] check_app_dir_migrate_file\n") );
704
705 srcpath = g_build_filename(srcdir, filename, NULL );
706 dstpath = g_build_filename(dstdir, filename, NULL );
707
708 if (g_file_get_contents (srcpath, &buffer, &length, NULL))
709 {
710 if(g_file_set_contents(dstpath, buffer, length, NULL))
711 {
712 //g_print("sould delete %s\n", srcpath);
713 g_remove(srcpath);
714 retval = TRUE;
715 }
716 }
717
718 g_free(dstpath);
719 g_free(srcpath);
720
721 return retval;
722 }
723
724 /*
725 * check/create user home directory for .homebank (HB_DATA_PATH) directory
726 */
727 static void homebank_check_app_dir()
728 {
729 gchar *homedir;
730 const gchar *configdir;
731 gboolean exists;
732
733 DB( g_print("\n[homebank] check_app_dir\n") );
734
735 /* check if <userdir>/.config exist */
736 #ifndef G_OS_WIN32
737 configdir = g_get_user_config_dir();
738 DB( g_print(" - check '%s' exists\n", configdir) );
739 if(!g_file_test(configdir, G_FILE_TEST_IS_DIR))
740 {
741 DB( g_print(" - creating dir\n") );
742 g_mkdir(configdir, 0755);
743 }
744 #endif
745
746 /* check for XDG .config/homebank */
747 configdir = homebank_app_get_config_dir();
748 DB( g_print(" - config_dir is: '%s'\n", configdir) );
749 exists = g_file_test(configdir, G_FILE_TEST_IS_DIR);
750 if(exists)
751 {
752 /* just update folder security */
753 DB( g_print(" - chmod 0700\n") );
754 g_chmod(configdir, 0700);
755 GLOBALS->first_run = FALSE;
756 }
757 else
758 {
759 /* create the config dir */
760 DB( g_print(" - create config_dir\n") );
761 g_mkdir(configdir, 0755);
762 g_chmod(configdir, 0700);
763
764 /* any old homedir configuration out there ? */
765 homedir = g_build_filename(g_get_home_dir (), ".homebank", NULL );
766 DB( g_print(" - homedir is: '%s'\n", homedir) );
767
768 exists = g_file_test(homedir, G_FILE_TEST_IS_DIR);
769 if(exists)
770 {
771 gboolean f1, f2;
772 /* we must do the migration properly */
773 DB( g_print(" - migrate old 2 files\n") );
774 f1 = homebank_check_app_dir_migrate_file(homedir, config_dir, "preferences");
775 f2 = homebank_check_app_dir_migrate_file(homedir, config_dir, "lastopenedfiles");
776 if(f1 && f2)
777 {
778 DB( g_print(" - removing old dir\n") );
779 g_rmdir(homedir);
780 }
781 }
782 g_free(homedir);
783 GLOBALS->first_run = TRUE;
784 }
785
786 }
787
788
789 /*
790 ** application cleanup: icons, GList, memory
791 */
792 static void homebank_cleanup()
793 {
794
795 DB( g_print("\n[homebank] cleanup\n") );
796
797 //v3.4 save windows size/position
798 homebank_pref_save();
799
800 hbfile_cleanup(TRUE);
801
802 /* free our global datas */
803 if( PREFS )
804 {
805 homebank_pref_free();
806 g_free(PREFS);
807 }
808
809 if(GLOBALS)
810 {
811 g_free(GLOBALS);
812 }
813
814 g_free (config_dir);
815 g_free (images_dir);
816 g_free (pixmaps_dir);
817 g_free (locale_dir);
818 g_free (help_dir);
819
820 }
821
822
823
824 /*
825 ** application setup: icons, GList, memory
826 */
827 static gboolean homebank_setup()
828 {
829
830 DB( g_print("\n[homebank] setup\n") );
831
832 GLOBALS = g_malloc0(sizeof(struct HomeBank));
833 if(!GLOBALS) return FALSE;
834 PREFS = g_malloc0(sizeof(struct Preferences));
835 if(!PREFS) return FALSE;
836
837 // check homedir for .homebank dir
838 homebank_check_app_dir();
839
840 homebank_pref_setdefault();
841 homebank_pref_load();
842
843 hbfile_setup(TRUE);
844
845 homebank_icon_theme_setup();
846
847 #ifdef G_OS_WIN32
848 homebank_setup_theme_extensions();
849 #endif
850
851 homebank_app_date_get_julian();
852
853
854 #if MYDEBUG == 1
855
856 g_print(" - user_name: %s\n", g_get_user_name ());
857 g_print(" - real_name: %s\n", g_get_real_name ());
858 g_print(" - user_cache_dir: %s\n", g_get_user_cache_dir());
859 g_print(" - user_data_dir: %s\n", g_get_user_data_dir ());
860 g_print(" - user_config_dir: %s\n", g_get_user_config_dir ());
861 //g_print(" - system_data_dirs: %s\n", g_get_system_data_dirs ());
862 //g_print(" - system_config_dirs: %s\n", g_get_system_config_dirs ());
863
864 g_print(" - home_dir: %s\n", g_get_home_dir ());
865 g_print(" - tmp_dir: %s\n", g_get_tmp_dir ());
866 g_print(" - current_dir: %s\n", g_get_current_dir ());
867
868 #endif
869
870 return TRUE;
871 }
872
873
874 /* = = = = = = = = = = = = = = = = = = = = */
875 /* Main homebank */
876
877 static GtkWidget *
878 homebank_construct_splash()
879 {
880 GtkWidget *window;
881 GtkWidget *frame, *vbox, *image;
882 //gchar *ver_string, *markup, *version;
883 gchar *pathfilename;
884
885 DB( g_print("\n[homebank_construct_splash]\n") );
886
887 window = gtk_window_new(GTK_WINDOW_POPUP); //TOPLEVEL DONT WORK
888 gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
889 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
890
891 gtk_window_set_title (GTK_WINDOW (window), "HomeBank");
892 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
893
894 pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL);
895 image = gtk_image_new_from_file((const gchar *)pathfilename);
896 g_free(pathfilename);
897
898 frame = gtk_frame_new (NULL);
899 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
900 gtk_container_add (GTK_CONTAINER (window), frame);
901
902 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
903 gtk_container_add (GTK_CONTAINER (frame), vbox);
904
905 /*
906 ver_string = g_strdup_printf(_("Version: HomeBank-%s"), VERSION);
907
908 version = gtk_label_new(NULL);
909 markup = g_markup_printf_escaped(MARKUP_STRING, ver_string);
910 gtk_label_set_markup(GTK_LABEL(version), markup);
911 g_free(markup);
912 g_free(ver_string);
913 */
914
915 gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
916 //gtk_box_pack_start (GTK_BOX (vbox), version, FALSE, FALSE, 0);
917
918 return window;
919 }
920
921 static void
922 homebank_init_i18n (void)
923 {
924 /* We may change the locale later if the user specifies a language
925 * in the gimprc file. Here we are just initializing the locale
926 * according to the environment variables and set up the paths to
927 * the message catalogs.
928 */
929
930 setlocale (LC_ALL, "");
931
932 bindtextdomain (GETTEXT_PACKAGE, homebank_app_get_locale_dir ());
933 //#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
934 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
935 //#endif
936
937 textdomain (GETTEXT_PACKAGE);
938
939 /*#ifdef G_OS_WIN32
940 gchar *wl = g_win32_getlocale ();
941 DB( g_print(" - win32 locale is '%s'\n", wl) );
942 g_free(wl);
943 #endif*/
944
945 }
946
947
948 int
949 main (int argc, char *argv[])
950 {
951 GOptionContext *option_context;
952 GOptionGroup *option_group;
953 GError *error = NULL;
954 GtkWidget *mainwin;
955 GtkWidget *splash = NULL;
956 gboolean openlast;
957
958 DB( g_print("\n--------------------------------" ) );
959 DB( g_print("\nhomebank starting...\n" ) );
960
961 build_package_paths();
962
963 homebank_init_i18n ();
964
965 /* Set up option groups */
966 option_context = g_option_context_new (NULL);
967
968 //g_option_context_set_summary (option_context, _(""));
969
970 option_group = g_option_group_new ("homebank",
971 N_("HomeBank options"),
972 N_("HomeBank options"),
973 NULL, NULL);
974 g_option_group_add_entries (option_group, option_entries);
975 g_option_context_set_main_group (option_context, option_group);
976 g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
977
978 /* Add Gtk option group */
979 g_option_context_add_group (option_context, gtk_get_option_group (FALSE));
980
981 /* Parse command line */
982 if (!g_option_context_parse (option_context, &argc, &argv, &error))
983 {
984 g_option_context_free (option_context);
985
986 if (error)
987 {
988 g_print ("%s\n", error->message);
989 g_error_free (error);
990 }
991 else
992 g_print ("An unknown error occurred\n");
993
994 return -1;
995 }
996
997 g_option_context_free (option_context);
998 option_context = NULL;
999
1000 if (arg_version != FALSE)
1001 {
1002 /* Print version information and exit */
1003 g_print ("%s\n", PACKAGE " " VERSION);
1004 return 0;
1005 }
1006
1007 /* Pass NULL here since we parsed the gtk+ args already...
1008 * from this point all we need a DISPLAY variable to be set.
1009 */
1010 gtk_init (NULL, NULL);
1011
1012 //todo: sanity check gtk version here ?
1013
1014 g_set_application_name (APPLICATION_NAME);
1015
1016 if( homebank_setup() )
1017 {
1018 /* change the locale if a language is specified */
1019 language_init (PREFS->language);
1020
1021 if( PREFS->showsplash == TRUE )
1022 {
1023 splash = homebank_construct_splash();
1024 gtk_window_set_auto_startup_notification (FALSE);
1025 gtk_widget_show_all (splash);
1026 gtk_window_set_auto_startup_notification (TRUE);
1027
1028 // make sure splash is up
1029 while (gtk_events_pending ())
1030 gtk_main_iteration ();
1031 }
1032
1033 gtk_window_set_default_icon_name ("homebank");
1034
1035 DB( g_print(" - creating window\n" ) );
1036
1037 mainwin = (GtkWidget *)create_hbfile_window (NULL);
1038
1039 if(mainwin)
1040 {
1041
1042 //todo: pause on splash
1043 if( PREFS->showsplash == TRUE )
1044 {
1045 //g_usleep( G_USEC_PER_SEC * 1 );
1046 gtk_widget_hide(splash);
1047 gtk_widget_destroy(splash);
1048 }
1049
1050
1051 #if HB_UNSTABLE == TRUE
1052 /* GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(mainwin),
1053 GTK_DIALOG_DESTROY_WITH_PARENT,
1054 GTK_MESSAGE_WARNING,
1055 GTK_BUTTONS_CLOSE,
1056 "This is a beta version of HomeBank (UNSTABLE)"
1057 );
1058
1059 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
1060 "DO NOT USE with important files or do a backup first.\n"
1061 "This kind of release is for <b>TESTING ONLY</b>.\n"
1062 "<u>It may be buggy, crash, or lose your data</u>.\n\n"
1063
1064 "For unstable bugs report, questions, suggestions:\n"
1065 " - <b>DO NOT USE LaunchPad</b>\n"
1066 " - direct email to: &lt;homebank@free.fr&gt;\n\n"
1067
1068 "<i>Thanks !</i>"
1069 );
1070
1071 gtk_dialog_run (GTK_DIALOG (dialog));
1072 gtk_widget_destroy (dialog);*/
1073 #endif
1074
1075 if(GLOBALS->first_run)
1076 {
1077 ui_mainwindow_action_help_welcome();
1078 }
1079
1080
1081 while (gtk_events_pending ()) /* make sure splash is gone */
1082 gtk_main_iteration ();
1083
1084
1085 DB( g_print(" - open last file ?\n" ) );
1086
1087 // load a file ?
1088 /* load 1st file specified on commandline */
1089 openlast = PREFS->loadlast;
1090 if (files != NULL)
1091 {
1092 if (g_file_test (files[0], G_FILE_TEST_EXISTS) != FALSE)
1093 {
1094 DB( g_print(" - should load %s\n", files[0] ) );
1095 hbfile_change_filepath(g_strdup(files[0]));
1096 ui_mainwindow_open_internal(mainwin, NULL);
1097 openlast = FALSE;
1098 }
1099 else
1100 {
1101 g_warning (_("Unable to open '%s', the file does not exist.\n"), files[0]);
1102
1103 }
1104 g_strfreev (files);
1105 }
1106
1107
1108 DB( g_print(" - GLOBALS->xhb_filepath: '%s'\n", GLOBALS->xhb_filepath ) );
1109
1110 if( openlast )
1111 {
1112 gchar *lastfilepath;
1113
1114 lastfilepath = homebank_lastopenedfiles_load();
1115 if( lastfilepath != NULL )
1116 {
1117 //#1710955 test for backup open
1118 if( hbfile_file_isbackup(lastfilepath) )
1119 {
1120 if( ui_mainwindow_open_backup_check_confirm(lastfilepath) == TRUE )
1121 {
1122 GLOBALS->hbfile_is_bak = TRUE;
1123 }
1124 else
1125 {
1126 g_free(lastfilepath);
1127 goto nobak;
1128 }
1129 }
1130
1131 hbfile_change_filepath(lastfilepath);
1132 ui_mainwindow_open_internal(mainwin, NULL);
1133
1134 }
1135 }
1136
1137 /* -- hack to generate a big file -- */
1138 nobak:
1139
1140 /* update the mainwin display */
1141 ui_mainwindow_update(mainwin, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_VISUAL));
1142
1143 DB( g_print(" - gtk_main()\n" ) );
1144 gtk_main ();
1145
1146 DB( g_print(" - call destroy mainwin\n" ) );
1147 gtk_widget_destroy(mainwin);
1148 }
1149
1150 }
1151
1152
1153 homebank_cleanup();
1154
1155 return EXIT_SUCCESS;
1156 }
1157
1158 #ifdef G_OS_WIN32
1159 /* In case we build this as a windowed application */
1160
1161 #ifdef __GNUC__
1162 #define _stdcall __attribute__((stdcall))
1163 #endif
1164
1165 int _stdcall
1166 WinMain (struct HINSTANCE__ *hInstance,
1167 struct HINSTANCE__ *hPrevInstance,
1168 char *lpszCmdLine,
1169 int nCmdShow)
1170 {
1171 return main (__argc, __argv);
1172 }
1173 #endif
1174
This page took 0.101665 seconds and 5 git commands to generate.