30 #include <glib/gi18n.h>
32 #include "gnc-module.h"
35 #include "gnc-locale-utils.h"
36 #include "core-utils/gnc-version.h"
42 #include "gnc-hooks.h"
43 #include "top-level.h"
49 #include "gnc-report.h"
51 #include "gnc-splash.h"
54 #include "dialog-new-user.h"
55 #include "gnc-session.h"
56 #include "engine-helpers-guile.h"
57 #include "swig-runtime.h"
67 #ifdef MAC_INTEGRATION
68 # include <Foundation/Foundation.h>
73 static int is_development_version = TRUE;
75 static int is_development_version = FALSE;
76 #define GNUCASH_SCM ""
80 static int gnucash_show_version = 0;
81 static int debugging = 0;
83 static gchar **log_flags = NULL;
84 static gchar *log_to_filename = NULL;
85 static int nofile = 0;
86 static const gchar *gsettings_prefix = NULL;
87 static const char *add_quotes_file = NULL;
88 static char *namespace_regexp = NULL;
89 static const char *file_to_load = NULL;
90 static gchar **args_remaining = NULL;
92 static GOptionEntry options[] =
95 "version",
'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
96 N_(
"Show GnuCash version"), NULL
100 "debug",
'\0', 0, G_OPTION_ARG_NONE, &debugging,
101 N_(
"Enable debugging mode: increasing logging to provide deep detail."), NULL
105 "extra",
'\0', 0, G_OPTION_ARG_NONE, &extra,
106 N_(
"Enable extra/development/debugging features."), NULL
110 "log",
'\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
111 N_(
"Log level overrides, of the form \"log.ger.path={debug,info,warn,crit,error}\""),
116 "logto",
'\0', 0, G_OPTION_ARG_STRING, &log_to_filename,
117 N_(
"File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
122 "nofile",
'\0', 0, G_OPTION_ARG_NONE, &nofile,
123 N_(
"Do not load the last file opened"), NULL
126 "gsettings-prefix",
'\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
127 N_(
"Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
130 N_(
"GSETTINGSPREFIX")
133 "add-price-quotes",
'\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
134 N_(
"Add price quotes to given GnuCash datafile"),
140 "namespace",
'\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
141 N_(
"Regular expression determining which namespace commodities will be retrieved"),
147 G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_(
"[datafile]") },
152 gnc_print_unstable_message(
void)
154 if (!is_development_version)
return;
156 g_print(
"\n\n%s\n%s\n%s\n%s\n",
157 _(
"This is a development version. It may or may not work."),
159 _(
"You can also lookup and file bug reports at http://bugzilla.gnome.org"),
160 _(
"To find the last stable version, please refer to http://www.gnucash.org"));
163 #ifdef MAC_INTEGRATION
167 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
168 NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
169 NSArray *languages = [defs objectForKey:
@"AppleLanguages"];
170 const gchar *langs = NULL;
171 NSLocale *locale = [NSLocale currentLocale];
172 NSString *locale_str;
175 locale_str = [[[locale objectForKey: NSLocaleLanguageCode]
176 stringByAppendingString:
@"_"]
177 stringByAppendingString:
178 [locale objectForKey: NSLocaleCountryCode]];
180 @catch (NSException *err)
182 PWARN(
"Locale detection raised error %s: %s. "
183 "Check that your locale settings in "
184 "System Preferences>Languages & Text are set correctly.",
185 [[err name] UTF8String], [[err reason] UTF8String]);
189 if ([locale_str isEqualToString:
@"_"])
190 locale_str =
@"en_US";
192 if (!setlocale(LC_ALL, [locale_str UTF8String]))
194 NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
195 NSEnumerator *locale_iter = [all_locales objectEnumerator];
196 NSString *this_locale, *new_locale = nil;
197 NSString *lang = [locale objectForKey: NSLocaleLanguageCode];
198 PWARN(
"Apple Locale is set to a value %s not supported"
199 " by the C runtime", [locale_str UTF8String]);
200 while ((this_locale = (NSString*)[locale_iter nextObject]))
201 if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
202 objectForKey: NSLocaleLanguageCode]
203 isEqualToString: lang] &&
204 setlocale (LC_ALL, [this_locale UTF8String]))
206 new_locale = this_locale;
210 locale_str = new_locale;
213 locale_str =
@"en_US";
214 setlocale(LC_ALL, [locale_str UTF8String]);
216 PWARN(
"Using %s instead.", [locale_str UTF8String]);
218 if (g_getenv(
"LANG") == NULL)
219 g_setenv(
"LANG", [locale_str UTF8String], TRUE);
221 if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
222 [[[NSLocale alloc] initWithLocaleIdentifier: locale_str] objectForKey: NSLocaleCurrencyCode]]) {
223 NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
224 NSEnumerator *locale_iter = [all_locales objectEnumerator];
225 NSString *this_locale;
226 NSString *currency = [locale objectForKey: NSLocaleCurrencyCode];
227 NSString *money_locale = nil;
228 while ((this_locale = (NSString*)[locale_iter nextObject]))
230 NSLocale *templocale = [[NSLocale alloc]
231 initWithLocaleIdentifier: this_locale];
232 if ([[templocale objectForKey: NSLocaleCurrencyCode]
233 isEqualToString: currency])
235 money_locale = this_locale;
236 [templocale release];
239 [templocale release];
242 setlocale(LC_MONETARY, [money_locale UTF8String]);
256 if ([languages count] > 0) {
257 NSEnumerator *lang_iter = [languages objectEnumerator];
260 NSArray *new_languages = [NSArray array];
261 while ((this_lang = [lang_iter nextObject])) {
262 this_lang = [this_lang stringByTrimmingCharactersInSet:
263 [NSCharacterSet characterSetWithCharactersInString:
265 elements = [this_lang componentsSeparatedByString: @"-
"];
266 if ([elements count] > 1) {
267 if ([[elements objectAtIndex: 0] isEqualToString: @"zh
"]) {
268 if ([[elements objectAtIndex: 1] isEqualToString: @"Hans
"])
269 this_lang = @"zh_CN
";
271 this_lang = @"zh_TW
";
274 this_lang = [elements componentsJoinedByString: @"_
"];
276 new_languages = [new_languages arrayByAddingObject: this_lang];
277 /* If it's an English language, add the "C
" locale after it so that
278 * any messages can default to it */
279 if ( [[elements objectAtIndex: 0] isEqualToString: @"en
"])
280 new_languages = [new_languages arrayByAddingObject: @"C
"];
283 langs = [[new_languages componentsJoinedByString:@":
"] UTF8String];
285 if (langs && strlen(langs) > 0)
286 g_setenv("LANGUAGE
", langs, TRUE);
289 #endif /* MAC_INTEGRATION */
292 try_load_config_array(const gchar *fns[])
297 for (i = 0; fns[i]; i++)
299 filename = gnc_build_dotgnucash_path(fns[i]);
300 if (gfec_try_load(filename))
311 update_message(const gchar *msg)
313 gnc_update_splash_screen(msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
314 g_message("%s
", msg);
318 load_system_config(void)
320 static int is_system_config_loaded = FALSE;
321 gchar *system_config_dir;
322 gchar *system_config;
324 if (is_system_config_loaded) return;
326 update_message("loading system configuration
");
327 system_config_dir = gnc_path_get_pkgsysconfdir();
328 system_config = g_build_filename(system_config_dir, "config
", NULL);
329 is_system_config_loaded = gfec_try_load(system_config);
330 g_free(system_config_dir);
331 g_free(system_config);
335 load_user_config(void)
337 /* Don't continue adding to this list. When 2.0 rolls around bump
338 the 1.4 (unnumbered) files off the list. */
339 static const gchar *user_config_files[] =
341 "config-2.0.user
", "config-1.8.user
", "config-1.6.user
",
344 static const gchar *auto_config_files[] =
346 "config-2.0.
auto", "config-1.8.
auto", "config-1.6.
auto",
349 static const gchar *saved_report_files[] =
351 SAVED_REPORTS_FILE, SAVED_REPORTS_FILE_OLD_REV, NULL
353 static const gchar *stylesheet_files[] = { "stylesheets-2.0
", NULL};
354 static int is_user_config_loaded = FALSE;
356 if (is_user_config_loaded)
358 else is_user_config_loaded = TRUE;
360 update_message("loading user configuration
");
361 try_load_config_array(user_config_files);
362 update_message("loading
auto configuration
");
363 try_load_config_array(auto_config_files);
364 update_message("loading saved reports
");
365 try_load_config_array(saved_report_files);
366 update_message("loading stylesheets
");
367 try_load_config_array(stylesheet_files);
370 /* Parse command line options, using GOption interface.
371 * We can't let gtk_init_with_args do it because it fails
372 * before parsing any arguments if the GUI can't be initialized.
375 gnc_parse_command_line(int *argc, char ***argv)
378 GError *error = NULL;
379 GOptionContext *context = g_option_context_new (_("- GnuCash personal and small business finance management
"));
381 g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
382 g_option_context_add_group (context, gtk_get_option_group(FALSE));
383 if (!g_option_context_parse (context, argc, argv, &error))
385 g_printerr (_("%s\nRun
'%s --help' to see a full list of available command line options.\n
"),
386 error->message, *argv[0]);
387 g_error_free (error);
390 g_option_context_free (context);
392 if (gnucash_show_version)
394 gchar *fixed_message;
396 if (is_development_version)
398 fixed_message = g_strdup_printf(_("GnuCash %s development version
"), VERSION);
400 /* Translators: 1st %s is a fixed message, which is translated independently;
401 2nd %s is the scm type (svn/svk/git/bzr);
402 3rd %s is the scm revision number;
403 4th %s is the build date */
404 g_print ( _("%s\nThis copy was built from %s rev %s on %s.
"),
405 fixed_message, GNUCASH_SCM, GNUCASH_SCM_REV,
406 GNUCASH_BUILD_DATE );
410 fixed_message = g_strdup_printf(_("GnuCash %s
"), VERSION);
412 /* Translators: 1st %s is a fixed message, which is translated independently;
413 2nd %s is the scm (svn/svk/git/bzr) revision number;
414 3rd %s is the build date */
415 g_print ( _("%s\nThis copy was built from rev %s on %s.
"),
416 fixed_message, GNUCASH_SCM_REV, GNUCASH_BUILD_DATE );
419 g_free (fixed_message);
423 gnc_prefs_set_debugging(debugging);
424 gnc_prefs_set_extra(extra);
426 if (gsettings_prefix)
427 gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
429 if (namespace_regexp)
430 gnc_prefs_set_namespace_regexp(namespace_regexp);
433 file_to_load = args_remaining[0];
437 load_gnucash_modules()
447 { "gnucash/app-utils
", 0, FALSE },
448 { "gnucash/engine
", 0, FALSE },
449 { "gnucash/
register/ledger-core
", 0, FALSE },
450 { "gnucash/
register/
register-core
", 0, FALSE },
451 { "gnucash/
register/
register-gnome
", 0, FALSE },
452 { "gnucash/
import-export/qif-
import", 0, FALSE },
453 { "gnucash/
import-export/ofx
", 0, TRUE },
454 { "gnucash/
import-export/csv-
import", 0, TRUE },
455 { "gnucash/
import-export/csv-export
", 0, TRUE },
456 { "gnucash/
import-export/log-replay
", 0, TRUE },
457 { "gnucash/
import-export/aqbanking
", 0, TRUE },
458 { "gnucash/report/report-system
", 0, FALSE },
459 { "gnucash/report/stylesheets
", 0, FALSE },
460 { "gnucash/report/standard-reports
", 0, FALSE },
461 { "gnucash/report/utility-reports
", 0, FALSE },
462 { "gnucash/report/locale-specific/us
", 0, FALSE },
463 { "gnucash/report/report-gnome
", 0, FALSE },
464 { "gnucash/business-gnome
", 0, TRUE },
465 { "gnucash/gtkmm
", 0, TRUE },
466 { "gnucash/python
", 0, TRUE },
467 { "gnucash/plugins/bi_import
", 0, TRUE},
468 { "gnucash/plugins/customer_import
", 0, TRUE},
471 /* module initializations go here */
472 len = sizeof(modules) / sizeof(*modules);
473 for (i = 0; i < len; i++)
475 DEBUG("Loading module %s started
", modules[i].name);
476 gnc_update_splash_screen(modules[i].name, GNC_SPLASH_PERCENTAGE_UNKNOWN);
477 if (modules[i].optional)
478 gnc_module_load_optional(modules[i].name, modules[i].version);
480 gnc_module_load(modules[i].name, modules[i].version);
481 DEBUG("Loading module %s finished
", modules[i].name);
483 if (!gnc_engine_is_initialized())
485 /* On Windows this check used to fail anyway, see
486 * https://lists.gnucash.org/pipermail/gnucash-devel/2006-September/018529.html
487 * but more recently it seems to work as expected
488 * again. 2006-12-20, cstim. */
489 g_warning("GnuCash engine failed to initialize. Exiting.\n
");
495 inner_main_add_price_quotes(void *closure, int argc, char **argv)
497 SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
498 QofSession *session = NULL;
500 scm_c_eval_string("(debug-set! stack 200000)
");
502 mod = scm_c_resolve_module("gnucash price-quotes
");
503 scm_set_current_module(mod);
505 /* Don't load the modules since the stylesheet module crashes if the
506 GUI is not initialized */
507 #ifdef PRICE_QUOTES_NEED_MODULES
508 load_gnucash_modules();
512 scm_c_eval_string("(gnc:price-quotes-install-sources)
");
514 if (!gnc_quote_source_fq_installed())
516 g_print("%s
", _("No quotes retrieved. Finance::Quote isn
't "
517 "installed properly.\n"));
521 add_quotes = scm_c_eval_string("gnc:book-add-quotes");
522 session = gnc_get_current_session();
523 if (!session) goto fail;
525 qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
526 if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
528 qof_session_load(session, NULL);
529 if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
531 scm_book = gnc_book_to_scm(qof_session_get_book(session));
532 scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);
534 qof_session_save(session, NULL);
535 if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
537 qof_session_destroy(session);
538 if (!scm_is_true(scm_result))
540 g_warning("Failed to add quotes to %s.", add_quotes_file);
548 if (session && qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
549 g_warning("Session Error: %s", qof_session_get_error_message(session));
558 return g_strdup(file_to_load);
560 return gnc_history_get_last();
564 inner_main (void *closure, int argc, char **argv)
568 GError *error = NULL;
570 scm_c_eval_string("(debug-set! stack 200000)");
572 main_mod = scm_c_resolve_module("gnucash main");
573 scm_set_current_module(main_mod);
575 /* GnuCash switched to gsettings to store its preferences in version 2.5.6
576 * Migrate the user's preferences from gconf
if needed */
577 gnc_gsettings_migrate_from_gconf();
579 load_gnucash_modules();
584 load_system_config();
589 scm_c_use_module(
"gnucash report report-gnome");
590 scm_c_eval_string(
"(gnc:report-menu-setup)");
596 gnc_hook_add_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit, NULL);
599 gnc_update_splash_screen(_(
"Checking Finance::Quote..."), GNC_SPLASH_PERCENTAGE_UNKNOWN);
600 scm_c_use_module(
"gnucash price-quotes");
601 scm_c_eval_string(
"(gnc:price-quotes-install-sources)");
603 gnc_hook_run(HOOK_STARTUP, NULL);
605 if (!nofile && (fn = get_file_to_load()))
607 gnc_update_splash_screen(_(
"Loading data..."), GNC_SPLASH_PERCENTAGE_UNKNOWN);
608 gnc_file_open_file(fn, FALSE);
613 gnc_destroy_splash_screen();
614 gnc_ui_new_user_dialog();
617 gnc_destroy_splash_screen();
620 gnc_hook_run(HOOK_UI_POST_STARTUP, NULL);
621 gnc_ui_start_event_loop();
622 gnc_hook_remove_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit);
631 if (log_to_filename != NULL)
638 gchar *tracefilename;
639 tracefilename = g_build_filename(g_get_tmp_dir(),
"gnucash.trace",
642 g_free(tracefilename);
650 if (gnc_prefs_is_debugging_enabled())
658 gchar *log_config_filename;
660 if (g_file_test(log_config_filename, G_FILE_TEST_EXISTS))
662 g_free(log_config_filename);
665 if (log_flags != NULL)
668 for (; log_flags[i] != NULL; i++)
671 gchar **parts = NULL;
673 gchar *log_opt = log_flags[i];
674 parts = g_strsplit(log_opt,
"=", 2);
675 if (parts == NULL || parts[0] == NULL || parts[1] == NULL)
677 g_warning(
"string [%s] not parseable", log_opt);
681 level = qof_log_level_from_string(parts[1]);
689 main(
int argc,
char ** argv)
691 gchar *sys_locale = NULL;
692 #if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
693 # error "No GLib thread implementation available!"
695 #ifndef HAVE_GLIB_2_32
698 #ifdef ENABLE_BINRELOC
700 GError *binreloc_error = NULL;
701 if (!gnc_gbr_init(&binreloc_error))
703 g_print(
"main: Error on gnc_gbr_init: %s\n", binreloc_error->message);
704 g_error_free(binreloc_error);
713 #ifdef MAC_INTEGRATION
717 #ifndef MAC_INTEGRATION
718 sys_locale = g_strdup (setlocale (LC_ALL,
""));
721 g_print (
"The locale defined in the environment isn't supported. "
722 "Falling back to the 'C' (US English) locale\n");
723 g_setenv (
"LC_ALL",
"C", TRUE);
724 setlocale (LC_ALL,
"C");
729 gchar *localedir = gnc_path_get_localedir();
730 bindtextdomain(GETTEXT_PACKAGE, localedir);
731 textdomain(GETTEXT_PACKAGE);
732 bind_textdomain_codeset(GETTEXT_PACKAGE,
"UTF-8");
737 gnc_parse_command_line(&argc, &argv);
738 gnc_print_unstable_message();
742 #ifndef MAC_INTEGRATION
746 PINFO (
"System locale returned %s", sys_locale ? sys_locale :
"(null)");
747 PINFO (
"Effective locale set to %s.", setlocale (LC_ALL,
""));
755 gnc_module_system_init();
756 scm_boot_guile(argc, argv, inner_main_add_price_quotes, 0);
762 if(!gtk_init_check (&argc, &argv))
764 g_printerr(_(
"%s\nRun '%s --help' to see a full list of available command line options.\n"),
765 _(
"Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
766 " Perhaps you need to set the $DISPLAY environment variable ?"),
773 gnc_module_system_init();
776 scm_boot_guile(argc, argv, inner_main, 0);
void qof_log_set_level(QofLogModule module, QofLogLevel level)
utility functions for the GnuCash UI
#define PINFO(format, args...)
void qof_log_set_default(QofLogLevel log_level)
void gnc_shutdown(int exit_status)
gchar * gnc_build_dotgnucash_path(const gchar *filename)
Make a path to filename in the user's configuration directory.
void gnc_main_window_show_all_windows(void)
Functions for adding content to a window.
#define PWARN(format, args...)
void qof_log_init_filename_special(const char *log_to_filename)
void qof_log_init_filename(const gchar *logfilename)
void gnc_log_default(void)
Functions providing the file history menu.
code to set up the environment for proper gnucash functioning.
Preferences initialization function.
void gnc_environment_setup(void)
Gnome specific utility functions.
All type declarations for the whole Gnucash engine.
Generic api to store and retrieve preferences.
void gnc_gtk_add_rc_file(void)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
GncMainWindow * gnc_gui_init(void)
File path resolution utility functions.
GSettings helper routines.
Commodity handling public routines.
void qof_log_parse_log_config(const char *filename)
const gchar * QofLogModule