GnuCash  5.6-150-g038405b370+
gnucash.cpp
1 /*
2  * gnucash.cpp -- The program entry point for GnuCash
3  *
4  * Copyright (C) 2006 Chris Shoemaker <c.shoemaker@cox.net>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program 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, contact:
18  *
19  * Free Software Foundation Voice: +1-617-542-5942
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21  * Boston, MA 02110-1301, USA gnu@gnu.org
22  */
23 #include <config.h>
24 
25 #include <libguile.h>
26 #include <guile-mappings.h>
27 #ifdef __MINGW32__
28 #include <Windows.h>
29 #include <fcntl.h>
30 #endif
31 
32 #include "gnucash-commands.hpp"
33 #include "gnucash-core-app.hpp"
34 #ifdef __MINGW32__
35 #include "gnucash-locale-platform.h"
36 #endif
37 
38 #include <glib/gi18n.h>
39 #include <dialog-new-user.h>
40 #include <gfec.h>
41 #include <gnc-engine.h> // For define GNC_MOD_GUI
42 #include <gnc-file.h>
43 #include <gnc-filepath-utils.h>
44 #include <gnc-gnome-utils.h>
45 #include <gnc-hooks.h>
46 #include <gnc-module.h>
47 #include <gnc-path.h>
48 #include <gnc-plugin-bi-import.h>
49 #include <gnc-plugin-csv-export.h>
50 #include <gnc-plugin-csv-import.h>
53 #include <gnc-plugin-log-replay.h>
54 #include <gnc-plugin-qif-import.h>
55 #include <gnc-plugin-report-system.h>
56 #include <gnc-prefs.h>
57 #include <gnc-prefs-utils.h>
58 #include <gnc-session.h>
59 #include <gnc-splash.h>
60 #include <gnucash-register.h>
61 #include <search-core-type.h>
62 #include <top-level.h>
63 
64 #include <boost/locale.hpp>
65 #include <boost/optional.hpp>
66 #ifdef __MINGW32__
67 #include <boost/nowide/args.hpp>
68 #endif
69 #include <iostream>
70 #include <gnc-report.h>
71 #include <gnc-locale-utils.hpp>
72 #include <gnc-quotes.hpp>
73 
74 namespace bl = boost::locale;
75 
76 /* This static indicates the debugging module that this .o belongs to. */
77 static QofLogModule log_module = GNC_MOD_GUI;
78 
79 static void
80 load_gnucash_plugins()
81 {
83  gnc_plugin_csv_export_create_plugin ();
84  gnc_plugin_csv_import_create_plugin();
86  gnc_plugin_qif_import_create_plugin ();
87  gnc_plugin_log_replay_create_plugin ();
88 }
89 
90 static void
91 load_gnucash_modules()
92 {
93  struct
94  {
95  const gchar * name;
96  int version;
97  gboolean optional;
98  } modules[] =
99  {
100  { "gnucash/import-export/ofx", 0, TRUE },
101  { "gnucash/import-export/aqbanking", 0, TRUE },
102  { "gnucash/python", 0, TRUE },
103  };
104 
105  /* module initializations go here */
106  int len = sizeof(modules) / sizeof(*modules);
107  for (int i = 0; i < len; i++)
108  {
109  DEBUG("Loading module %s started", modules[i].name);
110  gnc_update_splash_screen(modules[i].name, GNC_SPLASH_PERCENTAGE_UNKNOWN);
111  if (modules[i].optional)
112  gnc_module_load_optional(modules[i].name, modules[i].version);
113  else
114  gnc_module_load(modules[i].name, modules[i].version);
115  DEBUG("Loading module %s finished", modules[i].name);
116  }
117 }
118 
119 static char *
120 get_file_to_load (const char* file_to_load)
121 {
122  if (file_to_load && *file_to_load != '\0')
123  return g_strdup(file_to_load);
124  else
125  /* Note history will always return a valid (possibly empty) string */
126  return gnc_history_get_last();
127 }
128 
129 extern SCM scm_init_sw_gnome_module(void);
130 
131 struct t_file_spec {
132  int nofile;
133  const char *file_to_load;
134 };
135 
136 static void
137 scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
138 {
139  auto user_file_spec = static_cast<t_file_spec*>(data);
140 
141  scm_c_eval_string("(debug-set! stack 200000)");
142 
143  auto main_mod = scm_c_resolve_module("gnucash utilities");
144  scm_set_current_module(main_mod);
145  scm_c_use_module("gnucash app-utils");
146 
148  gnc_search_core_initialize ();
149  gnc_hook_add_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_search_core_finalize, NULL, NULL);
151  gnc_report_init ();
152 
153  load_gnucash_plugins();
154  load_gnucash_modules();
155 
156  /* Load the scm config files before starting up the gui. This ensures that
157  * custom reports have been read into memory before the Reports
158  * menu is created. */
159  Gnucash::gnc_load_scm_config ([](const gchar *msg)
160  {
161  gnc_update_splash_screen (msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
162  PINFO ("%s", msg);
163  });
164 
165  /* Setting-up the report menu must come after the module
166  loading but before the gui initialization. */
167  gnc_plugin_report_system_new();
168 
169  /* TODO: After some more guile-extraction, this should happen even
170  before booting guile. */
171  gnc_main_gui_init();
172 
173  gnc_hook_add_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit, NULL, NULL);
174 
175  /* Install Price Quote Sources */
176 
177  try
178  {
179  const auto checking = _("Checking Finance::Quote…");
180  gnc_update_splash_screen (checking, GNC_SPLASH_PERCENTAGE_UNKNOWN);
181  GncQuotes quotes;
182  auto found = (bl::format (std::string{_("Found Finance::Quote version {1}.")}) % quotes.version()).str();
183  auto quote_sources = quotes.sources();
184  gnc_quote_source_set_fq_installed (quotes.version().c_str(), quote_sources);
185  gnc_update_splash_screen (found.c_str(), GNC_SPLASH_PERCENTAGE_UNKNOWN);
186  }
187  catch (const GncQuoteException& err)
188  {
189  auto msg = _("Unable to load Finance::Quote.");
190  PINFO ("Attempt to load Finance::Quote returned this error message:\n");
191  PINFO ("%s", err.what());
192  gnc_update_splash_screen (msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
193  }
194 
195  gnc_hook_run(HOOK_STARTUP, NULL);
196 
197  char* fn = nullptr;
198  if (!user_file_spec->nofile && (fn = get_file_to_load (user_file_spec->file_to_load)) && *fn )
199  {
200  auto msg = _("Loading data…");
201  gnc_update_splash_screen (msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
202  gnc_file_open_file(gnc_get_splash_screen(), fn, /*open_readonly*/ FALSE);
203  g_free(fn);
204  }
205  else if (gnc_prefs_get_bool(GNC_PREFS_GROUP_NEW_USER, GNC_PREF_FIRST_STARTUP))
206  {
207  g_free(fn); /* fn could be an empty string ("") */
208  gnc_destroy_splash_screen();
209  gnc_ui_new_user_dialog();
210  }
211 
212  /* Ensure temporary preferences are temporary */
213  gnc_prefs_reset_group (GNC_PREFS_GROUP_WARNINGS_TEMP);
214 
215  gnc_destroy_splash_screen();
217 
218  gnc_hook_run(HOOK_UI_POST_STARTUP, NULL);
219  gnc_ui_start_event_loop();
220  gnc_hook_remove_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit);
221 
222  gnc_shutdown(0);
223  return;
224 }
225 
226 namespace Gnucash {
227 
228  class Gnucash : public CoreApp
229  {
230  public:
231  Gnucash (const char* app_name);
232  void parse_command_line (int argc, char **argv);
233  int start (int argc, char **argv);
234 
235  private:
236  void configure_program_options (void);
237 
238  bool m_nofile = false;
239  };
240 
241 }
242 
243 Gnucash::Gnucash::Gnucash (const char *app_name) : Gnucash::CoreApp (app_name)
244 {
245  configure_program_options();
246 }
247 
248 
249 void
250 Gnucash::Gnucash::parse_command_line (int argc, char **argv)
251 {
252  Gnucash::CoreApp::parse_command_line (argc, argv);
253 }
254 
255 // Define command line options specific to gnucash.
256 void
257 Gnucash::Gnucash::configure_program_options (void)
258 {
259 
260  bpo::options_description app_options(_("Application Options"));
261  app_options.add_options()
262  ("nofile", bpo::bool_switch (&m_nofile),
263  _("Do not load the last file opened"));
264 
265  m_opt_desc_display->add (app_options);
266  m_opt_desc_all.add (app_options);
267 }
268 
269 int
270 Gnucash::Gnucash::start ([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
271 {
272  Gnucash::CoreApp::start();
273 
274  /* Now the module files are looked up, which might cause some library
275  initialization to be run, hence gtk must be initialized beforehand. */
276  gnc_module_system_init();
277 
278  gnc_gui_init();
279 
280  auto user_file_spec = t_file_spec {
281  m_nofile,
282  m_file_to_load ? m_file_to_load->c_str() : ""};
283  scm_boot_guile (argc, argv, scm_run_gnucash, &user_file_spec);
284 
285  return 0;
286 }
287 
288 int
289 main(int argc, char ** argv)
290 {
291  Gnucash::Gnucash application (PROJECT_NAME);
292 #ifdef __MINGW32__
293  boost::nowide::args a(argc, argv); // Fix arguments - make them UTF-8
294 #endif
295  /* We need to initialize gtk before looking up all modules */
296  if(!gtk_init_check (&argc, &argv))
297  {
298  std::cerr << bl::format (std::string{("Run '{1} --help' to see a full list of available command line options.")}) % *argv[0]
299  << "\n"
300  // Translators: Do not translate $DISPLAY! It is an environment variable for X11
301  << _("Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
302  "Perhaps you need to set the $DISPLAY environment variable?")
303  << "\n";
304  return 1;
305  }
306 #ifdef __MINGW32__
307  set_platform_ctype_to_acp ();
308 #endif
309 
310  application.parse_command_line (argc, argv);
311  return application.start (argc, argv);
312 }
void gnc_prefs_reset_group(const gchar *group)
Reset all preferences in a group to their default values in the preferences backend.
Definition: gnc-prefs.cpp:368
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
void gnc_plugin_bi_import_create_plugin(void)
Create a new GncPluginbi_import object and register it.
void gnc_shutdown(int exit_status)
Shutdown gnucash.
void gnc_main_window_show_all_windows(void)
Shows all main windows.
char * gnc_history_get_last(void)
Retrieve the name of the file most recently accessed.
Functions providing the file history menu.
Preferences initialization function.
Gnome specific utility functions.
void gnc_quote_source_set_fq_installed(const char *version_string, const std::vector< std::string > &sources_list)
Update gnucash internal tables based on what Finance::Quote sources are installed.
All type declarations for the whole Gnucash engine.
void gnc_gnome_utils_init(void)
Initialize the gnome-utils library Should be run once before using any gnome-utils features...
Generic api to store and retrieve preferences.
Plugin registration of the bi-import module.
void gnc_plugin_customer_import_create_plugin(void)
Create a new GncPlugincustomer_import object and register it.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
GncMainWindow * gnc_gui_init(void)
Initialize the gnucash gui.
void gnucash_register_add_cell_types(void)
Implementation.
File path resolution utility functions.
const std::string & version() noexcept
Get the installed Finance::Quote version.
const QuoteSources & sources() noexcept
Get the available Finance::Quote sources as a std::vector.
Plugin registration of the customer_import module.