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