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