gnucash master: Multiple changes pushed
Geert Janssens
gjanssens at code.gnucash.org
Fri May 29 17:05:53 EDT 2020
Updated via https://github.com/Gnucash/gnucash/commit/1ea284d8 (commit)
via https://github.com/Gnucash/gnucash/commit/4af7ea0f (commit)
via https://github.com/Gnucash/gnucash/commit/fa66168d (commit)
via https://github.com/Gnucash/gnucash/commit/b56b8768 (commit)
via https://github.com/Gnucash/gnucash/commit/09b270c6 (commit)
via https://github.com/Gnucash/gnucash/commit/5cf0c05c (commit)
via https://github.com/Gnucash/gnucash/commit/16003416 (commit)
via https://github.com/Gnucash/gnucash/commit/88ed957d (commit)
via https://github.com/Gnucash/gnucash/commit/a435b4c4 (commit)
via https://github.com/Gnucash/gnucash/commit/317f32de (commit)
via https://github.com/Gnucash/gnucash/commit/f6788412 (commit)
via https://github.com/Gnucash/gnucash/commit/2b8f91a1 (commit)
via https://github.com/Gnucash/gnucash/commit/91473b12 (commit)
via https://github.com/Gnucash/gnucash/commit/785f6702 (commit)
via https://github.com/Gnucash/gnucash/commit/969d00a5 (commit)
via https://github.com/Gnucash/gnucash/commit/c58cfdb8 (commit)
via https://github.com/Gnucash/gnucash/commit/3cd0de8c (commit)
via https://github.com/Gnucash/gnucash/commit/736979f9 (commit)
via https://github.com/Gnucash/gnucash/commit/9bf2b026 (commit)
from https://github.com/Gnucash/gnucash/commit/45d52d61 (commit)
commit 1ea284d868244f9453cc22e4e0f8bf3a88b95e45
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 18:26:52 2020 +0200
Use common input file parameter for gnucash-cli --add-price-quotes
As gnucash and most gnucash-cli commands will work on an input file
it makes sense to use the common positional input-file parameter everywhere.
It's still optional for a normal gnucash run though. It will fall back to
to last-used file as before.
A --add-price-quotes run on the other hand will bail out with an error
message. As this command is typically run unattended in a cron script
it's safer to explicitly request a file to work on.
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index f40f1a206..607392ba7 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -55,7 +55,7 @@ namespace Gnucash {
private:
void configure_program_options (void);
- std::string m_quotes_file;
+ bool m_add_quotes;
};
}
@@ -70,12 +70,11 @@ Gnucash::GnucashCli::parse_command_line (int argc, char **argv)
{
Gnucash::CoreApp::parse_command_line (argc, argv);
+ m_add_quotes = m_opt_map["add-price-quotes"].as<bool>();
+
if (m_opt_map.count ("namespace"))
gnc_prefs_set_namespace_regexp(m_opt_map["namespace"].
as<std::string>().c_str());
-
- if (m_opt_map.count ("add-price-quotes"))
- m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
}
// Define command line options specific to gnucash-cli.
@@ -84,7 +83,7 @@ Gnucash::GnucashCli::configure_program_options (void)
{
bpo::options_description quotes_options(_("Price Retrieval Options"));
quotes_options.add_options()
- ("add-price-quotes", bpo::value<std::string>(),
+ ("add-price-quotes", bpo::bool_switch(),
N_("Add price quotes to given GnuCash datafile.\n"))
("namespace", bpo::value<std::string>(),
N_("Regular expression determining which namespace commodities will be retrieved"));
@@ -97,10 +96,20 @@ Gnucash::GnucashCli::start ([[maybe_unused]] int argc, [[maybe_unused]] char **a
{
Gnucash::CoreApp::start();
- if (m_quotes_file.empty())
- return 1;
-
- return Gnucash::add_quotes (m_quotes_file);
+ if (m_add_quotes)
+ {
+ if (m_file_to_load.empty())
+ {
+ std::cerr << bl::translate("Missing data file parameter") << "\n\n"
+ << *m_opt_desc.get();
+ return 1;
+ }
+ else
+ return Gnucash::add_quotes (m_file_to_load);
+ }
+
+
+ return 1;
}
int
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 3e6f415c9..3017a9bb8 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -622,6 +622,9 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
m_log_to_filename = m_opt_map["logto"].
as<std::string>().c_str();
+ if (m_opt_map.count ("input-file"))
+ m_file_to_load = m_opt_map["input-file"].as<std::string>();
+
if (args_remaining)
file_to_load = args_remaining[0];
}
@@ -645,7 +648,11 @@ Gnucash::CoreApp::add_common_program_options (void)
("logto", bpo::value<std::string>(),
N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."))
("gsettings-prefix", bpo::value<std::string>(),
- N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."));
+ N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."))
+ ("input-file", bpo::value<std::string>(),
+ N_("[datafile]"));
+
+ m_pos_opt_desc.add("input-file", -1);
m_opt_desc->add (common_options);
}
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index 8c65443ba..e7e53553c 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -45,6 +45,7 @@ protected:
int gtk_show_help = 0;
std::string m_app_name;
std::string tagline;
+ std::string m_file_to_load;
std::unique_ptr<bpo::options_description> m_opt_desc;
bpo::variables_map m_opt_map;
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 00a715b78..2469ebbfb 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -304,8 +304,7 @@ namespace Gnucash {
void configure_program_options (void);
std::string m_gtk_help_msg;
- std::string m_file_to_load;
- std::string m_quotes_file; // Deprecated will be removed in gnucash 5.0
+ bool m_add_quotes; // Deprecated will be removed in gnucash 5.0
};
}
@@ -327,15 +326,11 @@ Gnucash::Gnucash::parse_command_line (int argc, char **argv)
exit(0);
}
+ m_add_quotes = m_opt_map["add-price-quotes"].as<bool>();
+
if (m_opt_map.count ("namespace"))
gnc_prefs_set_namespace_regexp (m_opt_map["namespace"].
as<std::string>().c_str());
-
- if (m_opt_map.count ("add-price-quotes"))
- m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
-
- if (m_opt_map.count ("input-file"))
- m_file_to_load = m_opt_map["input-file"].as<std::string>();
}
// Define command line options specific to gnucash.
@@ -361,18 +356,14 @@ Gnucash::Gnucash::configure_program_options (void)
bpo::options_description depr_options(_("Deprecated Options"));
depr_options.add_options()
- ("add-price-quotes", bpo::value<std::string>(),
+ ("add-price-quotes", bpo::bool_switch(),
N_("Add price quotes to given GnuCash datafile.\n"
"Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
"Please use \"gnucash-cli --add-price-quotes\" instead."))
("namespace", bpo::value<std::string>(),
N_("Regular expression determining which namespace commodities will be retrieved"
"Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
- "Please use \"gnucash-cli --add-price-quotes\" instead."))
- ("input-file", bpo::value<std::string>(),
- N_("[datafile]"));
-
- m_pos_opt_desc.add("input-file", -1);
+ "Please use \"gnucash-cli --add-price-quotes\" instead."));
m_opt_desc->add (app_options).add (depr_options);
}
@@ -384,11 +375,18 @@ Gnucash::Gnucash::start ([[maybe_unused]] int argc, [[maybe_unused]] char **argv
// Test for the deprecated add-price-quotes option and run it
// Will be removed in 5.0
- if (!m_quotes_file.empty())
+ if (m_add_quotes)
{
std::cerr << bl::translate ("The '--add-price-quotes' option to gnucash has been deprecated and will be removed in GnuCash 5.0. "
"Please use 'gnucash-cli --add-price-quotes' instead.") << "\n";
- return add_quotes (m_quotes_file);
+ if (m_file_to_load.empty())
+ {
+ std::cerr << bl::translate("Missing data file parameter") << "\n\n"
+ << *m_opt_desc.get();
+ return 1;
+ }
+ else
+ return add_quotes (m_file_to_load);
}
/* Now the module files are looked up, which might cause some library
commit 4af7ea0f0a0f06d384abdf321c804e059ddc992a
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 14:54:05 2020 +0200
Fix log initialization
- Log related options weren't parsed properly yet
- Rewrite gnc_log_init to use c++ features
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 20bf8b08a..3e6f415c9 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -47,6 +47,7 @@ extern "C" {
#include <gnc-version.h>
}
+#include <boost/algorithm/string.hpp>
#include <boost/locale.hpp>
#include <iostream>
#include <string>
@@ -348,60 +349,65 @@ load_user_config(void)
static void
-gnc_log_init (gchar **log_flags, gchar *log_to_filename)
+gnc_log_init (std::vector <std::string> &log_flags, std::string &log_to_filename)
{
- if (log_to_filename != NULL)
- qof_log_init_filename_special(log_to_filename);
+ if (!log_to_filename.empty())
+ {
+#ifdef __MINGW64__
+ auto *utf8_filename = g_utf16_to_utf8 (log_to_filename, -1, NULL, NULL, NULL);
+#else
+ auto utf8_filename = log_to_filename.c_str();
+#endif
+
+ qof_log_init_filename_special (utf8_filename);
+
+#ifdef __MINGW64__
+ g_free (utf8_filename);
+#endif
+ }
else
{
/* initialize logging to our file. */
- gchar *tracefilename;
- tracefilename = g_build_filename(g_get_tmp_dir(), "gnucash.trace",
- (gchar *)NULL);
- qof_log_init_filename(tracefilename);
- g_free(tracefilename);
+ auto tracefilename = g_build_filename (g_get_tmp_dir(), "gnucash.trace",
+ (gchar *)NULL);
+ qof_log_init_filename (tracefilename);
+ g_free (tracefilename);
}
// set a reasonable default.
qof_log_set_default(QOF_LOG_WARNING);
-
gnc_log_default();
if (gnc_prefs_is_debugging_enabled())
{
- qof_log_set_level("", QOF_LOG_INFO);
- qof_log_set_level("qof", QOF_LOG_INFO);
- qof_log_set_level("gnc", QOF_LOG_INFO);
+ qof_log_set_level ("", QOF_LOG_INFO);
+ qof_log_set_level ("qof", QOF_LOG_INFO);
+ qof_log_set_level ("gnc", QOF_LOG_INFO);
}
- {
- gchar *log_config_filename;
- log_config_filename = g_build_filename (gnc_userconfig_dir (),
- "log.conf", (char *)NULL);
- if (g_file_test(log_config_filename, G_FILE_TEST_EXISTS))
- qof_log_parse_log_config(log_config_filename);
- g_free(log_config_filename);
- }
+ auto log_config_filename = g_build_filename (gnc_userconfig_dir (),
+ "log.conf", (char *)NULL);
+ if (g_file_test (log_config_filename, G_FILE_TEST_EXISTS))
+ qof_log_parse_log_config (log_config_filename);
+ g_free (log_config_filename);
- if (log_flags != NULL)
+ if (!log_flags.empty())
{
- int i = 0;
- for (; log_flags[i] != NULL; i++)
+ for (auto log_flag : log_flags)
{
- QofLogLevel level;
- gchar **parts = NULL;
-
- gchar *log_opt = log_flags[i];
- parts = g_strsplit(log_opt, "=", 2);
- if (parts == NULL || parts[0] == NULL || parts[1] == NULL)
+ if (log_flag.empty () ||
+ log_flag[0] == '=' ||
+ log_flag[log_flag.length () - 1] == '=')
{
- g_warning("string [%s] not parseable", log_opt);
+ g_warning ("string [%s] not parseable", log_flag.c_str());
continue;
}
- level = qof_log_level_from_string(parts[1]);
- qof_log_set_level(parts[0], level);
- g_strfreev(parts);
+ std::vector<std::string> split_flag;
+ boost::split (split_flag, log_flag, [](char c){return c == '=';});
+
+ auto level = qof_log_level_from_string (split_flag[1].c_str());
+ qof_log_set_level (split_flag[0].c_str(), level);
}
}
}
@@ -567,11 +573,6 @@ Gnucash::CoreApp::CoreApp (const char* app_name)
void
Gnucash::CoreApp::parse_command_line (int argc, char **argv)
{
-#ifdef __MINGW64__
- wchar_t *tmp_log_to_filename = NULL;
-#else
- char *tmp_log_to_filename = NULL;
-#endif
try
{
bpo::store (bpo::command_line_parser (argc, argv).
@@ -586,16 +587,6 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
exit(1);
}
- if (tmp_log_to_filename != NULL)
- {
-#ifdef __MINGW64__
- log_to_filename = g_utf16_to_utf8(tmp_log_to_filename, -1, NULL, NULL, NULL);
- g_free (tmp_log_to_filename);
-#else
- log_to_filename = tmp_log_to_filename;
-#endif
- }
-
if (m_opt_map["version"].as<bool>())
{
bl::format rel_fmt (bl::translate ("GnuCash {1}"));
@@ -623,6 +614,14 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
gnc_gsettings_set_prefix (m_opt_map["gsettings-prefix"].
as<std::string>().c_str());
+ if (m_opt_map.count ("log"))
+ m_log_flags = m_opt_map["log"].
+ as<std::vector <std::string>>();
+
+ if (m_opt_map.count ("logto"))
+ m_log_to_filename = m_opt_map["logto"].
+ as<std::string>().c_str();
+
if (args_remaining)
file_to_load = args_remaining[0];
}
@@ -631,12 +630,6 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
void
Gnucash::CoreApp::add_common_program_options (void)
{
- #ifdef __MINGW64__
- wchar_t *tmp_log_to_filename = NULL;
- #else
- char *tmp_log_to_filename = NULL;
- #endif
-
bpo::options_description common_options(_("Common Options"));
common_options.add_options()
("help,h", bpo::bool_switch(),
@@ -669,7 +662,7 @@ Gnucash::CoreApp::start (void)
if (userdata_migration_msg)
g_print("\n\n%s\n", userdata_migration_msg);
- gnc_log_init (log_flags, log_to_filename);
+ gnc_log_init (m_log_flags, m_log_to_filename);
gnc_engine_init (0, NULL);
/* Write some locale details to the log to simplify debugging */
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index 57b610fcb..8c65443ba 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -54,11 +54,12 @@ private:
void add_common_program_options (void);
/* Command-line option variables */
+ std::string m_log_to_filename;
+ std::vector <std::string> m_log_flags;
+
int gnucash_show_version = 0;
int debugging = 0;
int extra = 0;
- char **log_flags;
- char *log_to_filename = nullptr;
int nofile = 0;
const char *gsettings_prefix = nullptr;
const char *add_quotes_file = nullptr;
commit fa66168d59276b982de63fdd53ae64eb7a6ff454
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 12:42:56 2020 +0200
Rework gnucash startup code to be a Gnucash class member function
This allows to remove a couple of helper functions
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 1c3634a08..20bf8b08a 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -657,18 +657,6 @@ Gnucash::CoreApp::add_common_program_options (void)
m_opt_desc->add (common_options);
}
-const char*
-Gnucash::CoreApp::get_file_to_load (void)
-{
- return file_to_load;
-}
-
-int
-Gnucash::CoreApp::get_no_file (void)
-{
- return nofile;
-}
-
void
Gnucash::CoreApp::start (void)
{
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index 1d759f92e..57b610fcb 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -41,9 +41,6 @@ public:
void parse_command_line (int argc, char **argv);
void start (void);
- const char *get_file_to_load (void);
- int get_no_file (void);
-
protected:
int gtk_show_help = 0;
std::string m_app_name;
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 950a05236..00a715b78 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -187,7 +187,7 @@ load_gnucash_modules()
static char *
get_file_to_load (const char* file_to_load)
{
- if (file_to_load)
+ if (file_to_load && *file_to_load != '\0')
return g_strdup(file_to_load);
else
/* Note history will always return a valid (possibly empty) string */
@@ -202,7 +202,7 @@ struct t_file_spec {
};
static void
-inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
+scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
auto user_file_spec = static_cast<t_file_spec*>(data);
SCM main_mod;
@@ -298,13 +298,13 @@ namespace Gnucash {
public:
Gnucash (const char* app_name);
void parse_command_line (int argc, char **argv);
+ int start (int argc, char **argv);
- std::string get_quotes_file (void)
- { return m_quotes_file; }
private:
void configure_program_options (void);
std::string m_gtk_help_msg;
+ std::string m_file_to_load;
std::string m_quotes_file; // Deprecated will be removed in gnucash 5.0
};
@@ -333,6 +333,9 @@ Gnucash::Gnucash::parse_command_line (int argc, char **argv)
if (m_opt_map.count ("add-price-quotes"))
m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
+
+ if (m_opt_map.count ("input-file"))
+ m_file_to_load = m_opt_map["input-file"].as<std::string>();
}
// Define command line options specific to gnucash.
@@ -354,7 +357,10 @@ Gnucash::Gnucash::configure_program_options (void)
("nofile", bpo::bool_switch(),
N_("Do not load the last file opened"))
("help-gtk", bpo::bool_switch(),
- _("Show help for gtk options"))
+ _("Show help for gtk options"));
+
+ bpo::options_description depr_options(_("Deprecated Options"));
+ depr_options.add_options()
("add-price-quotes", bpo::value<std::string>(),
N_("Add price quotes to given GnuCash datafile.\n"
"Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
@@ -368,7 +374,35 @@ Gnucash::Gnucash::configure_program_options (void)
m_pos_opt_desc.add("input-file", -1);
- m_opt_desc->add (app_options);
+ m_opt_desc->add (app_options).add (depr_options);
+}
+
+int
+Gnucash::Gnucash::start ([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
+{
+ Gnucash::CoreApp::start();
+
+ // Test for the deprecated add-price-quotes option and run it
+ // Will be removed in 5.0
+ if (!m_quotes_file.empty())
+ {
+ std::cerr << bl::translate ("The '--add-price-quotes' option to gnucash has been deprecated and will be removed in GnuCash 5.0. "
+ "Please use 'gnucash-cli --add-price-quotes' instead.") << "\n";
+ return add_quotes (m_quotes_file);
+ }
+
+ /* Now the module files are looked up, which might cause some library
+ initialization to be run, hence gtk must be initialized b*eforehand. */
+ gnc_module_system_init();
+
+ gnc_gui_init();
+
+ auto user_file_spec = t_file_spec {
+ m_opt_map["nofile"].as<bool>(),
+ m_file_to_load.c_str()};
+ scm_boot_guile (argc, argv, scm_run_gnucash, &user_file_spec);
+
+ return 0;
}
int
@@ -387,21 +421,5 @@ main(int argc, char ** argv)
}
application.parse_command_line (argc, argv);
- application.start();
-
- /* If asked via a command line parameter, fetch quotes only */
- auto quotes_file = application.get_quotes_file ();
- if (!quotes_file.empty())
- return Gnucash::add_quotes (quotes_file);
-
- /* Now the module files are looked up, which might cause some library
- initialization to be run, hence gtk must be initialized beforehand. */
- gnc_module_system_init();
-
- gnc_gui_init();
-
- auto user_file_spec = t_file_spec {application.get_no_file (), application.get_file_to_load ()};
- scm_boot_guile (argc, argv, inner_main, &user_file_spec);
-
- return 0;
+ return application.start (argc, argv);
}
commit b56b87685b5a8fd418f5c694fc079f60d615f4f0
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 14:13:33 2020 +0200
Factor out common quotes retrieval code into a new file gnucash-commands.cpp
This file will contain implementations of all
commands that can be run via gnucash-cli.
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index d908ecea1..769e05f5d 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -32,11 +32,13 @@ else()
endif()
set(gnucash_noinst_HEADERS
+ gnucash-commands.hpp
gnucash-core-app.hpp
)
set (gnucash_SOURCES
gnucash.cpp
+ gnucash-commands.cpp
gnucash-core-app.cpp
gnucash-gresources.c
${GNUCASH_RESOURCE_FILE}
@@ -62,6 +64,7 @@ target_link_libraries (gnucash
add_executable (gnucash-cli
gnucash-cli.cpp
+ gnucash-commands.cpp
gnucash-core-app.cpp
${GNUCASH_RESOURCE_FILE}
${gnucash_noinst_HEADERS}
@@ -287,7 +290,8 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash.cpp gnucash-cli.cpp gnucash-core-app.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ gnucash.cpp gnucash-commands.cpp gnucash-cli.cpp gnucash-core-app.cpp
+ gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
price-quotes.scm ${gnucash_noinst_HEADERS} ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index 568bafc3f..f40f1a206 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -22,21 +22,18 @@
*/
#include <config.h>
-#include <libguile.h>
-#include <guile-mappings.h>
#ifdef __MINGW32__
#include <Windows.h>
#include <fcntl.h>
#endif
+#include "gnucash-commands.hpp"
#include "gnucash-core-app.hpp"
extern "C" {
-#include <gnc-engine-guile.h>
+#include <glib/gi18n.h>
+#include <gnc-engine.h>
#include <gnc-prefs.h>
-#include <gnc-prefs-utils.h>
-#include <gnc-gnome-utils.h>
-#include <gnc-session.h>
}
#include <boost/locale.hpp>
@@ -47,67 +44,6 @@ namespace bl = boost::locale;
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
-static void
-inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
-{
- const char* add_quotes_file = static_cast<const char*>(data);
- SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
- QofSession *session = NULL;
-
- scm_c_eval_string("(debug-set! stack 200000)");
-
- mod = scm_c_resolve_module("gnucash price-quotes");
- scm_set_current_module(mod);
-
- gnc_prefs_init ();
- qof_event_suspend();
- scm_c_eval_string("(gnc:price-quotes-install-sources)");
-
- if (!gnc_quote_source_fq_installed())
- {
- std::cerr << bl::translate ("No quotes retrieved. Finance::Quote isn't "
- "installed properly.") << "\n";
- goto fail;
- }
-
- add_quotes = scm_c_eval_string("gnc:book-add-quotes");
- session = gnc_get_current_session();
- if (!session) goto fail;
-
- qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_load(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- scm_book = gnc_book_to_scm(qof_session_get_book(session));
- scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);
-
- qof_session_save(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_destroy(session);
- if (!scm_is_true(scm_result))
- {
- g_warning("Failed to add quotes to %s.", add_quotes_file);
- goto fail;
- }
-
- qof_event_resume();
- gnc_shutdown(0);
- return;
-fail:
- if (session)
- {
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
- g_warning("Session Error: %s",
- qof_session_get_error_message(session));
- qof_session_destroy(session);
- }
- qof_event_resume();
- gnc_shutdown(1);
-}
-
namespace Gnucash {
class GnucashCli : public CoreApp
@@ -115,7 +51,7 @@ namespace Gnucash {
public:
GnucashCli (const char* app_name);
void parse_command_line (int argc, char **argv);
- void start (int argc, char **argv);
+ int start (int argc, char **argv);
private:
void configure_program_options (void);
@@ -156,14 +92,15 @@ Gnucash::GnucashCli::configure_program_options (void)
m_opt_desc->add (quotes_options);
}
-void
-Gnucash::GnucashCli::start (int argc, char **argv)
+int
+Gnucash::GnucashCli::start ([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
Gnucash::CoreApp::start();
- if (not m_quotes_file.empty())
- scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void *)m_quotes_file.c_str());
+ if (m_quotes_file.empty())
+ return 1;
+ return Gnucash::add_quotes (m_quotes_file);
}
int
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-commands.cpp
similarity index 63%
copy from gnucash/gnucash-cli.cpp
copy to gnucash/gnucash-commands.cpp
index 568bafc3f..c855cd7ab 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-commands.cpp
@@ -29,7 +29,7 @@
#include <fcntl.h>
#endif
-#include "gnucash-core-app.hpp"
+#include "gnucash-commands.hpp"
extern "C" {
#include <gnc-engine-guile.h>
@@ -48,7 +48,7 @@ namespace bl = boost::locale;
static QofLogModule log_module = GNC_MOD_GUI;
static void
-inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
+scm_add_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
const char* add_quotes_file = static_cast<const char*>(data);
SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
@@ -108,71 +108,11 @@ fail:
gnc_shutdown(1);
}
-namespace Gnucash {
-
- class GnucashCli : public CoreApp
- {
- public:
- GnucashCli (const char* app_name);
- void parse_command_line (int argc, char **argv);
- void start (int argc, char **argv);
- private:
- void configure_program_options (void);
-
- std::string m_quotes_file;
- };
-
-}
-
-Gnucash::GnucashCli::GnucashCli (const char *app_name) : Gnucash::CoreApp (app_name)
-{
- configure_program_options();
-}
-
-void
-Gnucash::GnucashCli::parse_command_line (int argc, char **argv)
-{
- Gnucash::CoreApp::parse_command_line (argc, argv);
-
- if (m_opt_map.count ("namespace"))
- gnc_prefs_set_namespace_regexp(m_opt_map["namespace"].
- as<std::string>().c_str());
-
- if (m_opt_map.count ("add-price-quotes"))
- m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
-}
-
-// Define command line options specific to gnucash-cli.
-void
-Gnucash::GnucashCli::configure_program_options (void)
-{
- bpo::options_description quotes_options(_("Price Retrieval Options"));
- quotes_options.add_options()
- ("add-price-quotes", bpo::value<std::string>(),
- N_("Add price quotes to given GnuCash datafile.\n"))
- ("namespace", bpo::value<std::string>(),
- N_("Regular expression determining which namespace commodities will be retrieved"));
-
- m_opt_desc->add (quotes_options);
-}
-
-void
-Gnucash::GnucashCli::start (int argc, char **argv)
-{
- Gnucash::CoreApp::start();
-
- if (not m_quotes_file.empty())
- scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void *)m_quotes_file.c_str());
-
-}
-
int
-main(int argc, char **argv)
+Gnucash::add_quotes (std::string &uri)
{
- Gnucash::GnucashCli application (argv[0]);
-
- application.parse_command_line (argc, argv);
- application.start (argc, argv);
+ if (not uri.empty())
+ scm_boot_guile (0, nullptr, scm_add_quotes, (void *)uri.c_str());
return 0;
}
diff --git a/gnucash/gnucash-commands.hpp b/gnucash/gnucash-commands.hpp
new file mode 100644
index 000000000..819e60632
--- /dev/null
+++ b/gnucash/gnucash-commands.hpp
@@ -0,0 +1,35 @@
+/*
+ * gnucash-commands.hpp -- Implementation of all the commands that
+ * can be invoked via gnucash-cli
+ *
+ * Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+#ifndef GNUCASH_COMMANDS_HPP
+#define GNUCASH_COMMANDS_HPP
+
+#include <string>
+
+namespace Gnucash {
+
+ int add_quotes (std::string &uri);
+
+}
+#endif
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 46ac725df..950a05236 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -29,6 +29,7 @@
#include <fcntl.h>
#endif
+#include "gnucash-commands.hpp"
#include "gnucash-core-app.hpp"
extern "C" {
@@ -183,67 +184,6 @@ load_gnucash_modules()
}
}
-static void
-inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
-{
- const char* add_quotes_file = static_cast<const char*>(data);
- SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
- QofSession *session = NULL;
-
- scm_c_eval_string("(debug-set! stack 200000)");
-
- mod = scm_c_resolve_module("gnucash price-quotes");
- scm_set_current_module(mod);
-
- gnc_prefs_init ();
- qof_event_suspend();
- scm_c_eval_string("(gnc:price-quotes-install-sources)");
-
- if (!gnc_quote_source_fq_installed())
- {
- std::cerr << bl::translate ("No quotes retrieved. Finance::Quote isn't "
- "installed properly.") << "\n";
- goto fail;
- }
-
- add_quotes = scm_c_eval_string("gnc:book-add-quotes");
- session = gnc_get_current_session();
- if (!session) goto fail;
-
- qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_load(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- scm_book = gnc_book_to_scm(qof_session_get_book(session));
- scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);
-
- qof_session_save(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_destroy(session);
- if (!scm_is_true(scm_result))
- {
- g_warning("Failed to add quotes to %s.", add_quotes_file);
- goto fail;
- }
-
- qof_event_resume();
- gnc_shutdown(0);
- return;
-fail:
- if (session)
- {
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
- g_warning("Session Error: %s",
- qof_session_get_error_message(session));
- qof_session_destroy(session);
- }
- qof_event_resume();
- gnc_shutdown(1);
-}
-
static char *
get_file_to_load (const char* file_to_load)
{
@@ -452,10 +392,7 @@ main(int argc, char ** argv)
/* If asked via a command line parameter, fetch quotes only */
auto quotes_file = application.get_quotes_file ();
if (!quotes_file.empty())
- {
- scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void*) quotes_file.c_str());
- exit (0); /* never reached */
- }
+ return Gnucash::add_quotes (quotes_file);
/* Now the module files are looked up, which might cause some library
initialization to be run, hence gtk must be initialized beforehand. */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d5087722f..04c4dc1c9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -211,6 +211,7 @@ gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
gnucash/gnucash-cli.cpp
+gnucash/gnucash-commands.cpp
gnucash/gnucash-core-app.cpp
gnucash/gnucash.cpp
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
commit 09b270c693c73893d892676220e365e7b3bcc0ad
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 11:27:09 2020 +0200
Return from main instead of exiting
Right now it doesn't make a difference as the end of main
is currently never reached. However with some additional
tweaks it can be, and that would allow the application
destructor to be called for a nicer cleanup on exit.
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index 5c251a3c3..568bafc3f 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -174,5 +174,5 @@ main(int argc, char **argv)
application.parse_command_line (argc, argv);
application.start (argc, argv);
- exit(0); /* never reached */
+ return 0;
}
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 43a536790..46ac725df 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -465,5 +465,6 @@ main(int argc, char ** argv)
auto user_file_spec = t_file_spec {application.get_no_file (), application.get_file_to_load ()};
scm_boot_guile (argc, argv, inner_main, &user_file_spec);
- exit(0); /* never reached */
+
+ return 0;
}
commit 5cf0c05ca44638887eaeb152e6cf4719140de76c
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 11:10:51 2020 +0200
Catch unrecognized command line options
Print help message if that happens.
The alternative would be to pass allow_unregistered() to the options description
while parsing. That however would only make sense if we had other code to parse
the options. We don't.
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 8ff246050..1c3634a08 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -572,10 +572,19 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
#else
char *tmp_log_to_filename = NULL;
#endif
-
+ try
+ {
bpo::store (bpo::command_line_parser (argc, argv).
options (*m_opt_desc.get()).positional(m_pos_opt_desc).run(), m_opt_map);
bpo::notify (m_opt_map);
+ }
+ catch (std::exception &e)
+ {
+ std::cerr << e.what() << "\n\n";
+ std::cerr << *m_opt_desc.get();
+
+ exit(1);
+ }
if (tmp_log_to_filename != NULL)
{
commit 160034165c8b9b5782626833ee933f1eff3fe42d
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 11:02:28 2020 +0200
Make options that don't take arguments bool_switch type
This means they will always exist in the value store after parsing and
are set to true or false. This eliminates the need to test for their
existence first.
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 492559e0d..8ff246050 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -587,7 +587,7 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
#endif
}
- if (m_opt_map.count ("version"))
+ if (m_opt_map["version"].as<bool>())
{
bl::format rel_fmt (bl::translate ("GnuCash {1}"));
bl::format dev_fmt (bl::translate ("GnuCash {1} development version"));
@@ -601,14 +601,14 @@ Gnucash::CoreApp::parse_command_line (int argc, char **argv)
exit(0);
}
- if (m_opt_map.count ("help"))
+ if (m_opt_map["help"].as<bool>())
{
std::cout << *m_opt_desc.get() << "\n";
exit(0);
}
- gnc_prefs_set_debugging (m_opt_map.count ("debug"));
- gnc_prefs_set_extra (m_opt_map.count ("extra"));
+ gnc_prefs_set_debugging (m_opt_map["debug"].as<bool>());
+ gnc_prefs_set_extra (m_opt_map["extra"].as<bool>());
if (m_opt_map.count ("gsettings-prefix"))
gnc_gsettings_set_prefix (m_opt_map["gsettings-prefix"].
@@ -630,13 +630,13 @@ Gnucash::CoreApp::add_common_program_options (void)
bpo::options_description common_options(_("Common Options"));
common_options.add_options()
- ("help,h",
+ ("help,h", bpo::bool_switch(),
N_("Show this help message"))
- ("version,v",
+ ("version,v", bpo::bool_switch(),
N_("Show GnuCash version"))
- ("debug",
+ ("debug", bpo::bool_switch(),
N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""))
- ("extra",
+ ("extra", bpo::bool_switch(),
N_("Enable extra/development/debugging features."))
("log", bpo::value< std::vector<std::string> >(),
N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."))
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 531ffb3e2..43a536790 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -381,7 +381,7 @@ Gnucash::Gnucash::parse_command_line (int argc, char **argv)
{
Gnucash::CoreApp::parse_command_line (argc, argv);
- if (m_opt_map.count ("help-gtk"))
+ if (m_opt_map["help-gtk"].as<bool>())
{
std::cout << m_gtk_help_msg;
exit(0);
@@ -411,9 +411,10 @@ Gnucash::Gnucash::configure_program_options (void)
bpo::options_description app_options(_("Application Options"));
app_options.add_options()
- ("nofile",
+ ("nofile", bpo::bool_switch(),
N_("Do not load the last file opened"))
- ("help-gtk", _("Show help for gtk options"))
+ ("help-gtk", bpo::bool_switch(),
+ _("Show help for gtk options"))
("add-price-quotes", bpo::value<std::string>(),
N_("Add price quotes to given GnuCash datafile.\n"
"Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
commit 88ed957d2a062718aad2c6c1c4de62b36907bafb
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 11:01:01 2020 +0200
Pass argc and argv by value instead of by reference
Contrary to gtk_init, boost::program_options won't remove parsed options from
the argument list so there's no need to provide the option to update
the list.
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index afd59819b..5c251a3c3 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -114,7 +114,7 @@ namespace Gnucash {
{
public:
GnucashCli (const char* app_name);
- void parse_command_line (int *argc, char ***argv);
+ void parse_command_line (int argc, char **argv);
void start (int argc, char **argv);
private:
void configure_program_options (void);
@@ -130,7 +130,7 @@ Gnucash::GnucashCli::GnucashCli (const char *app_name) : Gnucash::CoreApp (app_n
}
void
-Gnucash::GnucashCli::parse_command_line (int *argc, char ***argv)
+Gnucash::GnucashCli::parse_command_line (int argc, char **argv)
{
Gnucash::CoreApp::parse_command_line (argc, argv);
@@ -171,7 +171,7 @@ main(int argc, char **argv)
{
Gnucash::GnucashCli application (argv[0]);
- application.parse_command_line (&argc, &argv);
+ application.parse_command_line (argc, argv);
application.start (argc, argv);
exit(0); /* never reached */
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 3ed3f096e..492559e0d 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -565,7 +565,7 @@ Gnucash::CoreApp::CoreApp (const char* app_name)
* before parsing any arguments if the GUI can't be initialized.
*/
void
-Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
+Gnucash::CoreApp::parse_command_line (int argc, char **argv)
{
#ifdef __MINGW64__
wchar_t *tmp_log_to_filename = NULL;
@@ -573,7 +573,7 @@ Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
char *tmp_log_to_filename = NULL;
#endif
- bpo::store (bpo::command_line_parser (*argc, *argv).
+ bpo::store (bpo::command_line_parser (argc, argv).
options (*m_opt_desc.get()).positional(m_pos_opt_desc).run(), m_opt_map);
bpo::notify (m_opt_map);
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index a93a1900c..1d759f92e 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -38,7 +38,7 @@ public:
CoreApp ();
CoreApp (const char* app_name);
- void parse_command_line (int *argc, char ***argv);
+ void parse_command_line (int argc, char **argv);
void start (void);
const char *get_file_to_load (void);
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index f3db65996..531ffb3e2 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -357,7 +357,7 @@ namespace Gnucash {
{
public:
Gnucash (const char* app_name);
- void parse_command_line (int *argc, char ***argv);
+ void parse_command_line (int argc, char **argv);
std::string get_quotes_file (void)
{ return m_quotes_file; }
@@ -377,7 +377,7 @@ Gnucash::Gnucash::Gnucash (const char *app_name) : Gnucash::CoreApp (app_name)
void
-Gnucash::Gnucash::parse_command_line (int *argc, char ***argv)
+Gnucash::Gnucash::parse_command_line (int argc, char **argv)
{
Gnucash::CoreApp::parse_command_line (argc, argv);
@@ -445,7 +445,7 @@ main(int argc, char ** argv)
return 1;
}
- application.parse_command_line (&argc, &argv);
+ application.parse_command_line (argc, argv);
application.start();
/* If asked via a command line parameter, fetch quotes only */
commit a435b4c4f6c02839b0f366f6fc7c06609d315e25
Author: Geert Janssens <geert at kobaltwit.be>
Date: Thu May 28 22:24:18 2020 +0200
Port command line option handling to boost::program_options
This allows for better separation of options in common, gnucash and gnucash-cli options.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c70b0d44e..2efbe9475 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -517,13 +517,13 @@ set (Boost_FIND_QUIETLY ON)
if (NOT DEFINED ${BOOST_ROOT})
set(BOOST_ROOT $ENV{BOOST_ROOT})
endif()
-find_package (Boost 1.67.0 COMPONENTS date_time regex locale filesystem system)
+find_package (Boost 1.67.0 COMPONENTS date_time regex locale filesystem system program_options)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
set(HAVE_BOOST 1)
else()
- find_package (Boost 1.60.0 REQUIRED COMPONENTS date_time regex locale filesystem system)
+ find_package (Boost 1.60.0 REQUIRED COMPONENTS date_time regex locale filesystem system program_options)
if (Boost_FOUND)
include (CheckIncludeFileCXX)
set(CMAKE_REQUIRED_FLAGS "-std=c++17")
@@ -538,7 +538,7 @@ else()
endif()
endif()
if (NOT HAVE_BOOST)
-message (SEND_ERROR "A suitable Boost is not installed, and is required. GnuCash requires that Boost be compatible and compiled with C++17. Boost 1.67 is the first compatible release but some distributions have patched earlier ones to work with C++17. Please install it and ensure that the following libraries are built: date_time, filesystem, locale, and regex.")
+message (SEND_ERROR "A suitable Boost is not installed, and is required. GnuCash requires that Boost be compatible and compiled with C++17. Boost 1.67 is the first compatible release but some distributions have patched earlier ones to work with C++17. Please install it and ensure that the following libraries are built: date_time, filesystem, locale, regex, program_options and system.")
endif()
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index 767c97105..afd59819b 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -33,6 +33,7 @@
extern "C" {
#include <gnc-engine-guile.h>
+#include <gnc-prefs.h>
#include <gnc-prefs-utils.h>
#include <gnc-gnome-utils.h>
#include <gnc-session.h>
@@ -107,17 +108,71 @@ fail:
gnc_shutdown(1);
}
+namespace Gnucash {
+
+ class GnucashCli : public CoreApp
+ {
+ public:
+ GnucashCli (const char* app_name);
+ void parse_command_line (int *argc, char ***argv);
+ void start (int argc, char **argv);
+ private:
+ void configure_program_options (void);
+
+ std::string m_quotes_file;
+ };
+
+}
+
+Gnucash::GnucashCli::GnucashCli (const char *app_name) : Gnucash::CoreApp (app_name)
+{
+ configure_program_options();
+}
+
+void
+Gnucash::GnucashCli::parse_command_line (int *argc, char ***argv)
+{
+ Gnucash::CoreApp::parse_command_line (argc, argv);
+
+ if (m_opt_map.count ("namespace"))
+ gnc_prefs_set_namespace_regexp(m_opt_map["namespace"].
+ as<std::string>().c_str());
+
+ if (m_opt_map.count ("add-price-quotes"))
+ m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
+}
+
+// Define command line options specific to gnucash-cli.
+void
+Gnucash::GnucashCli::configure_program_options (void)
+{
+ bpo::options_description quotes_options(_("Price Retrieval Options"));
+ quotes_options.add_options()
+ ("add-price-quotes", bpo::value<std::string>(),
+ N_("Add price quotes to given GnuCash datafile.\n"))
+ ("namespace", bpo::value<std::string>(),
+ N_("Regular expression determining which namespace commodities will be retrieved"));
+
+ m_opt_desc->add (quotes_options);
+}
+
+void
+Gnucash::GnucashCli::start (int argc, char **argv)
+{
+ Gnucash::CoreApp::start();
+
+ if (not m_quotes_file.empty())
+ scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void *)m_quotes_file.c_str());
+
+}
+
int
-main(int argc, char ** argv)
+main(int argc, char **argv)
{
- Gnucash::CoreApp application;
+ Gnucash::GnucashCli application (argv[0]);
application.parse_command_line (&argc, &argv);
- application.start ();
-
- auto quotes_file = application.get_quotes_file ();
- if (quotes_file)
- scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void *)quotes_file);
+ application.start (argc, argv);
exit(0); /* never reached */
}
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 576f9dfb3..3ed3f096e 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -49,6 +49,8 @@ extern "C" {
#include <boost/locale.hpp>
#include <iostream>
+#include <string>
+#include <vector>
namespace bl = boost::locale;
@@ -542,11 +544,22 @@ Gnucash::CoreApp::CoreApp ()
textdomain(PROJECT_NAME);
bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
g_free(localedir);
+}
+
+Gnucash::CoreApp::CoreApp (const char* app_name)
+{
+
+ CoreApp();
+
+ m_app_name = std::string(app_name);
// Now that gettext is properly initialized, set our help tagline.
tagline = bl::translate("- GnuCash, accounting for personal and small business finance").str(gnc_get_locale());
+ m_opt_desc = std::make_unique<bpo::options_description> ((bl::format (bl::gettext ("{1} [options]")) % m_app_name).str() + tagline);
+ add_common_program_options();
}
+
/* Parse command line options, using GOption interface.
* We can't let gtk_init_with_args do it because it fails
* before parsing any arguments if the GUI can't be initialized.
@@ -560,93 +573,9 @@ Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
char *tmp_log_to_filename = NULL;
#endif
- GOptionEntry options[] =
- {
- {
- "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
- N_("Show GnuCash version"), NULL
- },
-
- {
- "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
- N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
- },
-
- {
- "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
- N_("Enable extra/development/debugging features."), NULL
- },
-
- {
- "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
- N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
- NULL
- },
-
- {
- "logto", '\0', 0, G_OPTION_ARG_STRING, &tmp_log_to_filename,
- N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
- NULL
- },
-
- {
- "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
- N_("Do not load the last file opened"), NULL
- },
- {
- "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
- N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
- /* Translators: Argument description for autohelp; see
- * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("GSETTINGSPREFIX")
- },
- {
- "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
- N_("Add price quotes to given GnuCash datafile"),
- /* Translators: Argument description for autohelp; see
- * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("FILE")
- },
- {
- "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
- N_("Regular expression determining which namespace commodities will be retrieved"),
- /* Translators: Argument description for autohelp; see
- * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("REGEXP")
- },
- {
- G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]")
-
- },
- { NULL }
- };
-
- GError *error = NULL;
- GOptionContext *context = g_option_context_new (tagline.c_str());
-
- g_option_context_add_main_entries (context, options, PROJECT_NAME);
- if (!gtk_help_msg.empty())
- {
- GOptionEntry gtk_help_options[] =
- {
- {
- "help-gtk", 'v', 0, G_OPTION_ARG_NONE, >k_show_help,
- N_("Show GTK+ Options"), NULL
- },
- { NULL }
- };
- g_option_group_add_entries (g_option_context_get_main_group (context), gtk_help_options);
- }
-
- if (!g_option_context_parse (context, argc, argv, &error))
- {
- std::cerr << error->message << "\n"
- << bl::format (bl::translate ("Run '{1} --help' to see a full list of available command line options.")) % *argv[0]
- << "\n";
- g_error_free (error);
- exit (1);
- }
- g_option_context_free (context);
+ bpo::store (bpo::command_line_parser (*argc, *argv).
+ options (*m_opt_desc.get()).positional(m_pos_opt_desc).run(), m_opt_map);
+ bpo::notify (m_opt_map);
if (tmp_log_to_filename != NULL)
{
@@ -658,7 +587,7 @@ Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
#endif
}
- if (gnucash_show_version)
+ if (m_opt_map.count ("version"))
{
bl::format rel_fmt (bl::translate ("GnuCash {1}"));
bl::format dev_fmt (bl::translate ("GnuCash {1} development version"));
@@ -672,19 +601,53 @@ Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
exit(0);
}
- gnc_prefs_set_debugging(debugging);
- gnc_prefs_set_extra(extra);
+ if (m_opt_map.count ("help"))
+ {
+ std::cout << *m_opt_desc.get() << "\n";
+ exit(0);
+ }
- if (gsettings_prefix)
- gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
+ gnc_prefs_set_debugging (m_opt_map.count ("debug"));
+ gnc_prefs_set_extra (m_opt_map.count ("extra"));
- if (namespace_regexp)
- gnc_prefs_set_namespace_regexp(namespace_regexp);
+ if (m_opt_map.count ("gsettings-prefix"))
+ gnc_gsettings_set_prefix (m_opt_map["gsettings-prefix"].
+ as<std::string>().c_str());
if (args_remaining)
file_to_load = args_remaining[0];
}
+/* Define command line options common to all gnucash binaries. */
+void
+Gnucash::CoreApp::add_common_program_options (void)
+{
+ #ifdef __MINGW64__
+ wchar_t *tmp_log_to_filename = NULL;
+ #else
+ char *tmp_log_to_filename = NULL;
+ #endif
+
+ bpo::options_description common_options(_("Common Options"));
+ common_options.add_options()
+ ("help,h",
+ N_("Show this help message"))
+ ("version,v",
+ N_("Show GnuCash version"))
+ ("debug",
+ N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""))
+ ("extra",
+ N_("Enable extra/development/debugging features."))
+ ("log", bpo::value< std::vector<std::string> >(),
+ N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."))
+ ("logto", bpo::value<std::string>(),
+ N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."))
+ ("gsettings-prefix", bpo::value<std::string>(),
+ N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."));
+
+ m_opt_desc->add (common_options);
+}
+
const char*
Gnucash::CoreApp::get_file_to_load (void)
{
@@ -697,12 +660,6 @@ Gnucash::CoreApp::get_no_file (void)
return nofile;
}
-const char*
-Gnucash::CoreApp::get_quotes_file (void)
-{
- return add_quotes_file;
-}
-
void
Gnucash::CoreApp::start (void)
{
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index 449257e8f..a93a1900c 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -24,34 +24,43 @@
#ifndef GNUCASH_CORE_APP_HPP
#define GNUCASH_CORE_APP_HPP
+#include <boost/program_options.hpp>
#include <string>
+#include <vector>
namespace Gnucash {
+namespace bpo = boost::program_options;
+
class CoreApp
{
public:
CoreApp ();
+ CoreApp (const char* app_name);
void parse_command_line (int *argc, char ***argv);
void start (void);
const char *get_file_to_load (void);
int get_no_file (void);
- const char *get_quotes_file (void);
protected:
- std::string gtk_help_msg;
int gtk_show_help = 0;
+ std::string m_app_name;
std::string tagline;
+ std::unique_ptr<bpo::options_description> m_opt_desc;
+ bpo::variables_map m_opt_map;
+ bpo::positional_options_description m_pos_opt_desc;
+
private:
+ void add_common_program_options (void);
/* Command-line option variables */
int gnucash_show_version = 0;
int debugging = 0;
int extra = 0;
- char **log_flags = nullptr;
+ char **log_flags;
char *log_to_filename = nullptr;
int nofile = 0;
const char *gsettings_prefix = nullptr;
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 0f7dfb0e0..f3db65996 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -356,41 +356,84 @@ namespace Gnucash {
class Gnucash : public CoreApp
{
public:
+ Gnucash (const char* app_name);
void parse_command_line (int *argc, char ***argv);
+
+ std::string get_quotes_file (void)
+ { return m_quotes_file; }
+ private:
+ void configure_program_options (void);
+
+ std::string m_gtk_help_msg;
+ std::string m_quotes_file; // Deprecated will be removed in gnucash 5.0
};
}
+Gnucash::Gnucash::Gnucash (const char *app_name) : Gnucash::CoreApp (app_name)
+{
+ configure_program_options();
+}
+
+
void
Gnucash::Gnucash::parse_command_line (int *argc, char ***argv)
+{
+ Gnucash::CoreApp::parse_command_line (argc, argv);
+
+ if (m_opt_map.count ("help-gtk"))
+ {
+ std::cout << m_gtk_help_msg;
+ exit(0);
+ }
+
+ if (m_opt_map.count ("namespace"))
+ gnc_prefs_set_namespace_regexp (m_opt_map["namespace"].
+ as<std::string>().c_str());
+
+ if (m_opt_map.count ("add-price-quotes"))
+ m_quotes_file = m_opt_map["add-price-quotes"].as<std::string>();
+}
+
+// Define command line options specific to gnucash.
+void
+Gnucash::Gnucash::configure_program_options (void)
{
// The g_option context dance below is done to be able to show a help message
// for gtk's options. The options themselves are already parsed out by
// gtk_init_check by the time this function is called though. So it really only
// serves to be able to display a help message.
- GError *error = NULL;
auto context = g_option_context_new (tagline.c_str());
auto gtk_options = gtk_get_option_group(FALSE);
g_option_context_add_group (context, gtk_options);
- gtk_help_msg = std::string (g_option_context_get_help (context, FALSE, gtk_options));
+ m_gtk_help_msg = g_option_context_get_help (context, FALSE, gtk_options);
g_option_context_free (context);
- // Pass remaining command line bits to our base class for further parsing
- // This will include a --help-gtk option to display gtk's option help
- // extracted above
- Gnucash::CoreApp::parse_command_line (argc, argv);
-
- if (gtk_show_help)
- {
- std::cout << gtk_help_msg;
- exit(0);
- }
+ bpo::options_description app_options(_("Application Options"));
+ app_options.add_options()
+ ("nofile",
+ N_("Do not load the last file opened"))
+ ("help-gtk", _("Show help for gtk options"))
+ ("add-price-quotes", bpo::value<std::string>(),
+ N_("Add price quotes to given GnuCash datafile.\n"
+ "Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
+ "Please use \"gnucash-cli --add-price-quotes\" instead."))
+ ("namespace", bpo::value<std::string>(),
+ N_("Regular expression determining which namespace commodities will be retrieved"
+ "Note this option has been deprecated and will be removed in GnuCash 5.0.\n"
+ "Please use \"gnucash-cli --add-price-quotes\" instead."))
+ ("input-file", bpo::value<std::string>(),
+ N_("[datafile]"));
+
+ m_pos_opt_desc.add("input-file", -1);
+
+ m_opt_desc->add (app_options);
}
int
main(int argc, char ** argv)
{
- Gnucash::Gnucash application;
+ Gnucash::Gnucash application (argv[0]);
/* We need to initialize gtk before looking up all modules */
if(!gtk_init_check (&argc, &argv))
@@ -407,9 +450,9 @@ main(int argc, char ** argv)
/* If asked via a command line parameter, fetch quotes only */
auto quotes_file = application.get_quotes_file ();
- if (quotes_file)
+ if (!quotes_file.empty())
{
- scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void*) quotes_file);
+ scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void*) quotes_file.c_str());
exit (0); /* never reached */
}
commit 317f32de0b17a9513a392beb4777eb11edc80e4d
Author: Geert Janssens <geert at kobaltwit.be>
Date: Sat May 23 17:21:13 2020 +0200
Only offer gtk options for gnucash, not for gnucash-cli
* As the gtk command line options are only relevant for
gnucash and not gnucash-cli, remove the bit that adds
them from Gnucash::CoreApp.
* As the gtk command line options are parsed out by gtk_init_check
it's sufficient to run that before parsing our own command line
options to have gtk handle them for us.
* That just leaves us with the loss of a help message for the
gtk command line options. To handle that we derive a class
Gnucash::Gnucash from Gnucash::CoreApp which will generate an
option context for the gtk options purely to extract the help message.
This will then be used if the users pass option --help-gtk.
This is a bit clumsy to do with GOptionContext as it requires to store
a few gnucash only parameters in Gnucash::CoreApp. The plan is to
improve this in a future commit.
Note however we will still be stuck with the dummy option context generation
for the gtk option help message. There's just no other way to extract this
message otherwise.
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 019884bfa..576f9dfb3 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -62,6 +62,7 @@ static QofLogModule log_module = GNC_MOD_GUI;
#include <libintl.h>
#include <locale.h>
+#include <gnc-locale-utils.hpp>
#ifdef MAC_INTEGRATION
# include <Foundation/Foundation.h>
@@ -541,6 +542,9 @@ Gnucash::CoreApp::CoreApp ()
textdomain(PROJECT_NAME);
bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
g_free(localedir);
+
+ // Now that gettext is properly initialized, set our help tagline.
+ tagline = bl::translate("- GnuCash, accounting for personal and small business finance").str(gnc_get_locale());
}
/* Parse command line options, using GOption interface.
@@ -611,15 +615,29 @@ Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
N_("REGEXP")
},
{
- G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
- { NULL }
+ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]")
+
+ },
+ { NULL }
};
GError *error = NULL;
- GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
+ GOptionContext *context = g_option_context_new (tagline.c_str());
g_option_context_add_main_entries (context, options, PROJECT_NAME);
- g_option_context_add_group (context, gtk_get_option_group(FALSE));
+ if (!gtk_help_msg.empty())
+ {
+ GOptionEntry gtk_help_options[] =
+ {
+ {
+ "help-gtk", 'v', 0, G_OPTION_ARG_NONE, >k_show_help,
+ N_("Show GTK+ Options"), NULL
+ },
+ { NULL }
+ };
+ g_option_group_add_entries (g_option_context_get_main_group (context), gtk_help_options);
+ }
+
if (!g_option_context_parse (context, argc, argv, &error))
{
std::cerr << error->message << "\n"
diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp
index 1e58af6b5..449257e8f 100644
--- a/gnucash/gnucash-core-app.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -40,6 +40,11 @@ public:
int get_no_file (void);
const char *get_quotes_file (void);
+protected:
+ std::string gtk_help_msg;
+ int gtk_show_help = 0;
+ std::string tagline;
+
private:
/* Command-line option variables */
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index d816fdf49..0f7dfb0e0 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -351,10 +351,56 @@ inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
return;
}
+namespace Gnucash {
+
+ class Gnucash : public CoreApp
+ {
+ public:
+ void parse_command_line (int *argc, char ***argv);
+ };
+
+}
+
+void
+Gnucash::Gnucash::parse_command_line (int *argc, char ***argv)
+{
+ // The g_option context dance below is done to be able to show a help message
+ // for gtk's options. The options themselves are already parsed out by
+ // gtk_init_check by the time this function is called though. So it really only
+ // serves to be able to display a help message.
+ GError *error = NULL;
+ auto context = g_option_context_new (tagline.c_str());
+ auto gtk_options = gtk_get_option_group(FALSE);
+ g_option_context_add_group (context, gtk_options);
+ gtk_help_msg = std::string (g_option_context_get_help (context, FALSE, gtk_options));
+ g_option_context_free (context);
+
+ // Pass remaining command line bits to our base class for further parsing
+ // This will include a --help-gtk option to display gtk's option help
+ // extracted above
+ Gnucash::CoreApp::parse_command_line (argc, argv);
+
+ if (gtk_show_help)
+ {
+ std::cout << gtk_help_msg;
+ exit(0);
+ }
+}
+
int
main(int argc, char ** argv)
{
- Gnucash::CoreApp application;
+ Gnucash::Gnucash application;
+
+ /* We need to initialize gtk before looking up all modules */
+ if(!gtk_init_check (&argc, &argv))
+ {
+ std::cerr << bl::format (bl::translate ("Run '{1} --help' to see a full list of available command line options.")) % *argv[0]
+ << "\n"
+ << bl::translate ("Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
+ " Perhaps you need to set the $DISPLAY environment variable ?");
+ return 1;
+ }
application.parse_command_line (&argc, &argv);
application.start();
@@ -367,16 +413,6 @@ main(int argc, char ** argv)
exit (0); /* never reached */
}
- /* We need to initialize gtk before looking up all modules */
- if(!gtk_init_check (&argc, &argv))
- {
- std::cerr << bl::format (bl::translate ("Run '{1} --help' to see a full list of available command line options.")) % *argv[0]
- << "\n"
- << bl::translate ("Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
- " Perhaps you need to set the $DISPLAY environment variable ?");
- return 1;
- }
-
/* Now the module files are looked up, which might cause some library
initialization to be run, hence gtk must be initialized beforehand. */
gnc_module_system_init();
commit f6788412ce5044236ead015a03e9d70627608506
Author: John Ralls <jralls at ceridwen.us>
Date: Thu May 28 14:44:52 2020 -0700
MacOS Build Fixes
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index f102c1a76..d908ecea1 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -56,7 +56,7 @@ target_link_libraries (gnucash
gnc-engine gnc-module gnc-core-utils gnucash-guile
gnc-qif-import gnc-csv-import gnc-csv-export gnc-log-replay
gnc-bi-import gnc-customer-import gnc-report
- PkgConfig::GTK3 ${GUILE_LDFLAGS} ${GLIB2_LDFLAGS} ${GTK_MAC_LDFLAGS}
+ PkgConfig::GTK3 ${GUILE_LDFLAGS} ${GLIB2_LDFLAGS}
${Boost_LIBRARIES}
)
@@ -125,6 +125,8 @@ add_custom_command(
if (MAC_INTEGRATION)
target_compile_options(gnucash PRIVATE ${OSX_EXTRA_COMPILE_FLAGS})
target_link_libraries(gnucash ${OSX_EXTRA_LIBRARIES})
+ target_compile_options(gnucash-cli PRIVATE ${OSX_EXTRA_COMPILE_FLAGS})
+ target_link_libraries(gnucash-cli ${OSX_EXTRA_LIBRARIES})
endif()
install(TARGETS gnucash gnucash-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index 35d957159..019884bfa 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -38,6 +38,7 @@ extern "C" {
#include <gfec.h>
#include <gnc-environment.h>
#include <gnc-filepath-utils.h>
+#include <gnc-locale-utils.h>
#include <gnc-path.h>
#include <gnc-prefs.h>
#include <gnc-gsettings.h>
commit 2b8f91a191669a843155030e419b570d581ec06b
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 16:35:33 2020 +0200
Rename Gnucash::Base to Gnucash::CoreApp
That name better reflects what the class represents
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index e0beadf48..f102c1a76 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -32,12 +32,12 @@ else()
endif()
set(gnucash_noinst_HEADERS
- gnucash-base.hpp
+ gnucash-core-app.hpp
)
set (gnucash_SOURCES
gnucash.cpp
- gnucash-base.cpp
+ gnucash-core-app.cpp
gnucash-gresources.c
${GNUCASH_RESOURCE_FILE}
)
@@ -62,7 +62,7 @@ target_link_libraries (gnucash
add_executable (gnucash-cli
gnucash-cli.cpp
- gnucash-base.cpp
+ gnucash-core-app.cpp
${GNUCASH_RESOURCE_FILE}
${gnucash_noinst_HEADERS}
)
@@ -285,7 +285,7 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash.cpp gnucash-cli.cpp gnucash-base.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ gnucash.cpp gnucash-cli.cpp gnucash-core-app.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
price-quotes.scm ${gnucash_noinst_HEADERS} ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index 763a62c6e..767c97105 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -29,7 +29,7 @@
#include <fcntl.h>
#endif
-#include "gnucash-base.hpp"
+#include "gnucash-core-app.hpp"
extern "C" {
#include <gnc-engine-guile.h>
@@ -110,7 +110,7 @@ fail:
int
main(int argc, char ** argv)
{
- Gnucash::Base application;
+ Gnucash::CoreApp application;
application.parse_command_line (&argc, &argv);
application.start ();
diff --git a/gnucash/gnucash-base.cpp b/gnucash/gnucash-core-app.cpp
similarity index 98%
rename from gnucash/gnucash-base.cpp
rename to gnucash/gnucash-core-app.cpp
index 122724a11..35d957159 100644
--- a/gnucash/gnucash-base.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -1,5 +1,5 @@
/*
- * gnucash-base.cpp -- Basic application object for gnucash binaries
+ * gnucash-core-app.cpp -- Basic application object for gnucash binaries
*
* Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
*
@@ -32,7 +32,7 @@
#include <fcntl.h>
#endif
-#include "gnucash-base.hpp"
+#include "gnucash-core-app.hpp"
extern "C" {
#include <gfec.h>
@@ -495,7 +495,7 @@ redirect_stdout (void)
#endif
}
-Gnucash::Base::Base ()
+Gnucash::CoreApp::CoreApp ()
{
#if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
# error "No GLib thread implementation available!"
@@ -547,7 +547,7 @@ Gnucash::Base::Base ()
* before parsing any arguments if the GUI can't be initialized.
*/
void
-Gnucash::Base::parse_command_line (int *argc, char ***argv)
+Gnucash::CoreApp::parse_command_line (int *argc, char ***argv)
{
#ifdef __MINGW64__
wchar_t *tmp_log_to_filename = NULL;
@@ -667,25 +667,25 @@ Gnucash::Base::parse_command_line (int *argc, char ***argv)
}
const char*
-Gnucash::Base::get_file_to_load (void)
+Gnucash::CoreApp::get_file_to_load (void)
{
return file_to_load;
}
int
-Gnucash::Base::get_no_file (void)
+Gnucash::CoreApp::get_no_file (void)
{
return nofile;
}
const char*
-Gnucash::Base::get_quotes_file (void)
+Gnucash::CoreApp::get_quotes_file (void)
{
return add_quotes_file;
}
void
-Gnucash::Base::start (void)
+Gnucash::CoreApp::start (void)
{
gnc_print_unstable_message();
diff --git a/gnucash/gnucash-base.hpp b/gnucash/gnucash-core-app.hpp
similarity index 89%
rename from gnucash/gnucash-base.hpp
rename to gnucash/gnucash-core-app.hpp
index f993a71ee..1e58af6b5 100644
--- a/gnucash/gnucash-base.hpp
+++ b/gnucash/gnucash-core-app.hpp
@@ -1,5 +1,5 @@
/*
- * gnucash-base.hpp -- Basic application object for gnucash binaries
+ * gnucash-core-app.hpp -- Core application object for gnucash binaries
*
* Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
*
@@ -21,15 +21,17 @@
* Boston, MA 02110-1301, USA gnu at gnu.org
*/
-#ifndef GNUCASH_BASE_HPP
-#define GNUCASH_BASE_HPP
+#ifndef GNUCASH_CORE_APP_HPP
+#define GNUCASH_CORE_APP_HPP
+
+#include <string>
namespace Gnucash {
-class Base
+class CoreApp
{
public:
- Base ();
+ CoreApp ();
void parse_command_line (int *argc, char ***argv);
void start (void);
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 345020fde..d816fdf49 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -29,7 +29,7 @@
#include <fcntl.h>
#endif
-#include "gnucash-base.hpp"
+#include "gnucash-core-app.hpp"
extern "C" {
#include <dialog-new-user.h>
@@ -354,7 +354,7 @@ inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
int
main(int argc, char ** argv)
{
- Gnucash::Base application;
+ Gnucash::CoreApp application;
application.parse_command_line (&argc, &argv);
application.start();
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2353a72dc..d5087722f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,8 +210,8 @@ gnucash/gnome-utils/print-session.c
gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
-gnucash/gnucash-base.cpp
gnucash/gnucash-cli.cpp
+gnucash/gnucash-core-app.cpp
gnucash/gnucash.cpp
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.checkprinting.gschema.xml.in
commit 91473b1218a49dab8c28b261e7142e3607c66ad7
Author: Geert Janssens <geert at kobaltwit.be>
Date: Sat May 23 10:15:23 2020 +0200
Reformat Objective C code to work around a KDevelop bug.
KDevelop erroneously interprets [[ as the beginning of a C++17 attribute which
messes up all subsequent formatting. Changing this to '[ [' (with a space in between)
resolves the issue.
diff --git a/gnucash/gnucash-base.cpp b/gnucash/gnucash-base.cpp
index 8138aa141..122724a11 100644
--- a/gnucash/gnucash-base.cpp
+++ b/gnucash/gnucash-base.cpp
@@ -96,9 +96,9 @@ static void
mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
{
/* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
- NSLocale *cur_locale = [[NSLocale alloc] initWithLocaleIdentifier: locale_str];
- if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
- [cur_locale objectForKey: NSLocaleCurrencyCode]])
+ NSLocale *cur_locale = [ [NSLocale alloc] initWithLocaleIdentifier: locale_str];
+ if (![ [locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
+ [cur_locale objectForKey: NSLocaleCurrencyCode] ])
{
NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
NSEnumerator *locale_iter = [all_locales objectEnumerator];
@@ -107,9 +107,9 @@ mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
NSString *money_locale = nil;
while ((this_locale = (NSString*)[locale_iter nextObject]))
{
- NSLocale *templocale = [[NSLocale alloc]
+ NSLocale *templocale = [ [NSLocale alloc]
initWithLocaleIdentifier: this_locale];
- if ([[templocale objectForKey: NSLocaleCurrencyCode]
+ if ([ [templocale objectForKey: NSLocaleCurrencyCode]
isEqualToString: currency])
{
money_locale = this_locale;
@@ -137,7 +137,7 @@ mac_find_close_country(NSString *locale_str, NSString *country_str,
PWARN("Apple Locale is set to a value %s not supported"
" by the C runtime", [locale_str UTF8String]);
while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+ if ([ [ [NSLocale componentsFromLocaleIdentifier: this_locale]
objectForKey: NSLocaleCountryCode]
isEqualToString: country_str] &&
setlocale (LC_ALL, [this_locale UTF8String]))
@@ -147,7 +147,7 @@ mac_find_close_country(NSString *locale_str, NSString *country_str,
}
if (!new_locale)
while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+ if ([ [ [NSLocale componentsFromLocaleIdentifier: this_locale]
objectForKey: NSLocaleLanguageCode]
isEqualToString: lang_str] &&
setlocale (LC_ALL, [this_locale UTF8String]))
@@ -179,8 +179,8 @@ mac_convert_complex_language(NSString* this_lang)
NSArray *elements = [this_lang componentsSeparatedByString: @"-"];
if ([elements count] == 1)
return this_lang;
- if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
- if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
+ if ([ [elements objectAtIndex: 0] isEqualToString: @"zh"]) {
+ if ([ [elements objectAtIndex: 1] isEqualToString: @"Hans"])
this_lang = @"zh_CN";
else
this_lang = @"zh_TW";
@@ -202,7 +202,7 @@ mac_set_languages(NSArray* languages, NSString *lang_str)
NSRange not_found = {NSNotFound, 0};
while ((this_lang = [lang_iter nextObject])) {
this_lang = [this_lang stringByTrimmingCharactersInSet:
- [NSCharacterSet characterSetWithCharactersInString: @"\""]];
+ [NSCharacterSet characterSetWithCharactersInString: @"\""] ];
this_lang = mac_convert_complex_language(this_lang);
new_languages = [new_languages arrayByAddingObject: this_lang];
/* If it's an English language, add the "C" locale after it so that
@@ -213,7 +213,7 @@ mac_set_languages(NSArray* languages, NSString *lang_str)
NSArray *temp_array = [NSArray arrayWithObject: lang_str];
new_languages = [temp_array arrayByAddingObjectsFromArray: new_languages];
}
- langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
+ langs = [ [new_languages componentsJoinedByString:@":"] UTF8String];
}
if (langs && strlen(langs) > 0)
{
@@ -225,16 +225,16 @@ mac_set_languages(NSArray* languages, NSString *lang_str)
static void
set_mac_locale()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSAutoreleasePool *pool = [ [NSAutoreleasePool alloc] init];
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
NSLocale *locale = [NSLocale currentLocale];
NSString *lang_str, *country_str, *locale_str;
- NSArray *languages = [[defs arrayForKey: @"AppleLanguages"] retain];
+ NSArray *languages = [ [defs arrayForKey: @"AppleLanguages"] retain];
@try
{
lang_str = [locale objectForKey: NSLocaleLanguageCode];
country_str = [locale objectForKey: NSLocaleCountryCode];
- locale_str = [[lang_str stringByAppendingString: @"_"]
+ locale_str = [ [lang_str stringByAppendingString: @"_"]
stringByAppendingString: country_str];
}
@catch (NSException *err)
@@ -242,7 +242,7 @@ set_mac_locale()
PWARN("Locale detection raised error %s: %s. "
"Check that your locale settings in "
"System Preferences>Languages & Text are set correctly.",
- [[err name] UTF8String], [[err reason] UTF8String]);
+ [ [err name] UTF8String], [ [err reason] UTF8String]);
locale_str = @"_";
}
/* If we didn't get a valid current locale, the string will be just "_" */
commit 785f6702a11f6eb36b3f66470b1237f36ad08776
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 14:13:39 2020 +0200
Switch to using boost::locale::format and iostream for printing messages
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index a162c5f31..e0beadf48 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -57,6 +57,7 @@ target_link_libraries (gnucash
gnc-qif-import gnc-csv-import gnc-csv-export gnc-log-replay
gnc-bi-import gnc-customer-import gnc-report
PkgConfig::GTK3 ${GUILE_LDFLAGS} ${GLIB2_LDFLAGS} ${GTK_MAC_LDFLAGS}
+ ${Boost_LIBRARIES}
)
add_executable (gnucash-cli
@@ -74,6 +75,7 @@ target_link_libraries (gnucash-cli
gnc-gnome-utils gnc-app-utils
gnc-engine gnc-core-utils gnucash-guile gnc-report
${GUILE_LDFLAGS} ${GLIB2_LDFLAGS}
+ ${Boost_LIBRARIES}
)
if (BUILDING_FROM_VCS)
diff --git a/gnucash/gnucash-base.cpp b/gnucash/gnucash-base.cpp
index 6a2feb5d5..8138aa141 100644
--- a/gnucash/gnucash-base.cpp
+++ b/gnucash/gnucash-base.cpp
@@ -46,6 +46,11 @@ extern "C" {
#include <gnc-version.h>
}
+#include <boost/locale.hpp>
+#include <iostream>
+
+namespace bl = boost::locale;
+
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
@@ -78,13 +83,12 @@ gnc_print_unstable_message(void)
{
if (!is_development_version) return;
- g_print("\n\n%s\n%s\n%s %s\n%s %s\n",
- _("This is a development version. It may or may not work."),
- _("Report bugs and other problems to gnucash-devel at gnucash.org"),
- /* Translators: An URLs follows*/
- _("You can also lookup and file bug reports at"), PACKAGE_BUGREPORT,
- /* Translators: An URLs follows*/
- _("To find the last stable version, please refer to"), PACKAGE_URL);
+ std::cerr << bl::translate ("This is a development version. It may or may not work.") << "\n"
+ << bl::translate ("Report bugs and other problems to gnucash-devel at gnucash.org") << "\n"
+ /* Translators: {1} will be replaced with a URL*/
+ << bl::format (bl::translate ("You can also lookup and file bug reports at {1}")) % PACKAGE_BUGREPORT << "\n"
+ /* Translators: {1} will be replaced with a URL*/
+ << bl::format (bl::translate ("To find the last stable version, please refer to {1}")) % PACKAGE_URL << "\n";
}
#ifdef MAC_INTEGRATION
@@ -501,7 +505,7 @@ Gnucash::Base::Base ()
GError *binreloc_error = NULL;
if (!gnc_gbr_init(&binreloc_error))
{
- g_print("main: Error on gnc_gbr_init: %s\n", binreloc_error->message);
+ std::cerr << "main: Error on gnc_gbr_init: " << binreloc_error->message << "\n";
g_error_free(binreloc_error);
}
}
@@ -522,8 +526,8 @@ Gnucash::Base::Base ()
sys_locale = g_strdup (setlocale (LC_ALL, ""));
if (!sys_locale)
{
- g_print ("The locale defined in the environment isn't supported. "
- "Falling back to the 'C' (US English) locale\n");
+ std::cerr << "The locale defined in the environment isn't supported. "
+ << "Falling back to the 'C' (US English) locale\n";
g_setenv ("LC_ALL", "C", TRUE);
setlocale (LC_ALL, "C");
}
@@ -617,8 +621,9 @@ Gnucash::Base::parse_command_line (int *argc, char ***argv)
g_option_context_add_group (context, gtk_get_option_group(FALSE));
if (!g_option_context_parse (context, argc, argv, &error))
{
- g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
- error->message, *argv[0]);
+ std::cerr << error->message << "\n"
+ << bl::format (bl::translate ("Run '{1} --help' to see a full list of available command line options.")) % *argv[0]
+ << "\n";
g_error_free (error);
exit (1);
}
@@ -636,14 +641,15 @@ Gnucash::Base::parse_command_line (int *argc, char ***argv)
if (gnucash_show_version)
{
- const char *format_string;
+ bl::format rel_fmt (bl::translate ("GnuCash {1}"));
+ bl::format dev_fmt (bl::translate ("GnuCash {1} development version"));
+
if (is_development_version)
- format_string = _("GnuCash %s development version");
- else
- format_string = _("GnuCash %s");
+ std::cout << dev_fmt % gnc_version () << "\n";
+ else
+ std::cout << rel_fmt % gnc_version () << "\n";
- g_print (format_string, gnc_version());
- g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
+ std::cout << bl::translate ("Build ID") << ": " << gnc_build_id () << "\n";
exit(0);
}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index 3bbe67f36..763a62c6e 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -38,6 +38,11 @@ extern "C" {
#include <gnc-session.h>
}
+#include <boost/locale.hpp>
+#include <iostream>
+
+namespace bl = boost::locale;
+
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
@@ -59,8 +64,8 @@ inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unuse
if (!gnc_quote_source_fq_installed())
{
- g_print("%s", _("No quotes retrieved. Finance::Quote isn't "
- "installed properly.\n"));
+ std::cerr << bl::translate ("No quotes retrieved. Finance::Quote isn't "
+ "installed properly.") << "\n";
goto fail;
}
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 8203916a7..345020fde 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -58,6 +58,12 @@ extern "C" {
#include <top-level.h>
}
+#include <boost/locale.hpp>
+#include <iostream>
+#include <gnc-locale-utils.hpp>
+
+namespace bl = boost::locale;
+
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
static gchar *userdata_migration_msg = NULL;
@@ -195,8 +201,8 @@ inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unuse
if (!gnc_quote_source_fq_installed())
{
- g_print("%s", _("No quotes retrieved. Finance::Quote isn't "
- "installed properly.\n"));
+ std::cerr << bl::translate ("No quotes retrieved. Finance::Quote isn't "
+ "installed properly.") << "\n";
goto fail;
}
@@ -298,7 +304,8 @@ inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
gnc_hook_add_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit, NULL, NULL);
/* Install Price Quote Sources */
- gnc_update_splash_screen(_("Checking Finance::Quote..."), GNC_SPLASH_PERCENTAGE_UNKNOWN);
+ auto msg = bl::translate ("Checking Finance::Quote...").str(gnc_get_locale());
+ gnc_update_splash_screen (msg.c_str(), GNC_SPLASH_PERCENTAGE_UNKNOWN);
scm_c_use_module("gnucash price-quotes");
scm_c_eval_string("(gnc:price-quotes-install-sources)");
@@ -306,7 +313,8 @@ inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
if (!user_file_spec->nofile && (fn = get_file_to_load (user_file_spec->file_to_load)) && *fn )
{
- gnc_update_splash_screen(_("Loading data..."), GNC_SPLASH_PERCENTAGE_UNKNOWN);
+ auto msg = bl::translate ("Loading data...").str(gnc_get_locale());
+ gnc_update_splash_screen (msg.c_str(), GNC_SPLASH_PERCENTAGE_UNKNOWN);
gnc_file_open_file(gnc_get_splash_screen(), fn, /*open_readonly*/ FALSE);
g_free(fn);
}
@@ -362,10 +370,10 @@ main(int argc, char ** argv)
/* We need to initialize gtk before looking up all modules */
if(!gtk_init_check (&argc, &argv))
{
- g_printerr(_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
- _("Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
- " Perhaps you need to set the $DISPLAY environment variable ?"),
- argv[0]);
+ std::cerr << bl::format (bl::translate ("Run '{1} --help' to see a full list of available command line options.")) % *argv[0]
+ << "\n"
+ << bl::translate ("Error: could not initialize graphical user interface and option add-price-quotes was not set.\n"
+ " Perhaps you need to set the $DISPLAY environment variable ?");
return 1;
}
commit 969d00a59f9ededeb4ea27df69d694a8eba64eea
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 22 14:56:35 2020 +0200
Further cleanup in gnucash and gnucash-cli
- Remove unneeded includes, required a few fixes in other header files
- Silence unused parameter warnings using c++17 attribute [[maybe_unused]]
- Remove some duplicate, unused functions from gnucash and gnucash-cli
They were a left over from a previous commit
diff --git a/gnucash/gnome-utils/gnc-file.h b/gnucash/gnome-utils/gnc-file.h
index b038e0d00..176d5ae15 100644
--- a/gnucash/gnome-utils/gnc-file.h
+++ b/gnucash/gnome-utils/gnc-file.h
@@ -117,6 +117,7 @@
#include <glib.h>
#include "qof.h"
+#include <gtk/gtk.h>
typedef enum
{
diff --git a/gnucash/gnome/dialog-new-user.h b/gnucash/gnome/dialog-new-user.h
index 2780dbb61..78e9a0fc8 100644
--- a/gnucash/gnome/dialog-new-user.h
+++ b/gnucash/gnome/dialog-new-user.h
@@ -26,6 +26,8 @@
#define GNC_PREFS_GROUP_NEW_USER "dialogs.new-user"
#define GNC_PREF_FIRST_STARTUP "first-startup"
+#include <glib.h>
+
typedef struct _GNCNewUserDialog GNCNewUserDialog;
void gnc_ui_new_user_dialog (void);
diff --git a/gnucash/gnucash-base.cpp b/gnucash/gnucash-base.cpp
index ce3063306..6a2feb5d5 100644
--- a/gnucash/gnucash-base.cpp
+++ b/gnucash/gnucash-base.cpp
@@ -22,18 +22,10 @@
*/
#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <libguile.h>
#include <glib/gi18n.h>
-#include <glib.h>
#include <binreloc.h>
-#include <gnc-locale-utils.h>
#include <gnc-engine.h>
-#include <gnc-ui-util.h>
-#include <gnc-commodity.h>
-#include <swig-runtime.h>
#include <guile-mappings.h>
#ifdef __MINGW32__
#include <Windows.h>
@@ -44,17 +36,12 @@
extern "C" {
#include <gfec.h>
-#include <gnc-engine-guile.h>
#include <gnc-environment.h>
#include <gnc-filepath-utils.h>
-#include <gnc-hooks.h>
#include <gnc-path.h>
#include <gnc-prefs.h>
-#include <gnc-prefs-utils.h>
-#include <gnc-gnome-utils.h>
#include <gnc-gsettings.h>
#include <gnc-report.h>
-#include <gnc-session.h>
#include <gnc-splash.h>
#include <gnc-version.h>
}
diff --git a/gnucash/gnucash-base.hpp b/gnucash/gnucash-base.hpp
index 11652b4e1..f993a71ee 100644
--- a/gnucash/gnucash-base.hpp
+++ b/gnucash/gnucash-base.hpp
@@ -44,15 +44,15 @@ private:
int gnucash_show_version = 0;
int debugging = 0;
int extra = 0;
- gchar **log_flags = NULL;
- char *log_to_filename = NULL;
+ char **log_flags = nullptr;
+ char *log_to_filename = nullptr;
int nofile = 0;
- const gchar *gsettings_prefix = NULL;
- const char *add_quotes_file = NULL;
- char *namespace_regexp = NULL;
- const char *file_to_load = NULL;
- gchar **args_remaining = NULL;
- gchar *sys_locale = NULL;
+ const char *gsettings_prefix = nullptr;
+ const char *add_quotes_file = nullptr;
+ char *namespace_regexp = nullptr;
+ const char *file_to_load = nullptr;
+ char **args_remaining = nullptr;
+ char *sys_locale = nullptr;
};
}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index ea89f7cf4..3bbe67f36 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -22,18 +22,7 @@
*/
#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <libguile.h>
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <binreloc.h>
-#include <gnc-locale-utils.h>
-#include <gnc-engine.h>
-#include <gnc-ui-util.h>
-#include <gnc-commodity.h>
-#include <swig-runtime.h>
#include <guile-mappings.h>
#ifdef __MINGW32__
#include <Windows.h>
@@ -43,137 +32,17 @@
#include "gnucash-base.hpp"
extern "C" {
-#include <gfec.h>
#include <gnc-engine-guile.h>
-#include <gnc-environment.h>
-#include <gnc-filepath-utils.h>
-#include <gnc-hooks.h>
-#include <gnc-path.h>
-#include <gnc-prefs.h>
#include <gnc-prefs-utils.h>
#include <gnc-gnome-utils.h>
-#include <gnc-gsettings.h>
-#include <gnc-report.h>
#include <gnc-session.h>
-#include <gnc-splash.h>
-#include <gnc-version.h>
}
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
-/* Change the following to have a console window attached to GnuCash
- * for displaying stdout and stderr on Windows.
- */
-#define __MSWIN_CONSOLE__ 0
-
-#include <libintl.h>
-#include <locale.h>
-
-#ifdef MAC_INTEGRATION
-# include <Foundation/Foundation.h>
-#endif
-
-/* GNC_VCS is defined whenever we're building from an svn/svk/git/bzr tree */
-#ifdef GNC_VCS
-static int is_development_version = TRUE;
-#else
-static int is_development_version = FALSE;
-#define GNC_VCS ""
-#endif
-
-static gchar *userdata_migration_msg = NULL;
-
-static void
-gnc_print_unstable_message(void)
-{
- if (!is_development_version) return;
-
- g_print("\n\n%s\n%s\n%s %s\n%s %s\n",
- _("This is a development version. It may or may not work."),
- _("Report bugs and other problems to gnucash-devel at gnucash.org"),
- /* Translators: An URLs follows*/
- _("You can also lookup and file bug reports at"), PACKAGE_BUGREPORT,
- /* Translators: An URLs follows*/
- _("To find the last stable version, please refer to"), PACKAGE_URL);
-}
-
-static gboolean
-try_load_config_array(const gchar *fns[])
-{
- gchar *filename;
- int i;
-
- for (i = 0; fns[i]; i++)
- {
- filename = gnc_build_userdata_path(fns[i]);
- if (gfec_try_load(filename))
- {
- g_free(filename);
- return TRUE;
- }
- g_free(filename);
- }
- return FALSE;
-}
-
-static void
-update_message(const gchar *msg)
-{
- gnc_update_splash_screen(msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
- g_message("%s", msg);
-}
-
-static void
-load_system_config(void)
-{
- static int is_system_config_loaded = FALSE;
- gchar *system_config_dir;
- gchar *system_config;
-
- if (is_system_config_loaded) return;
-
- update_message("loading system configuration");
- system_config_dir = gnc_path_get_pkgsysconfdir();
- system_config = g_build_filename(system_config_dir, "config", NULL);
- is_system_config_loaded = gfec_try_load(system_config);
- g_free(system_config_dir);
- g_free(system_config);
-}
-
-static void
-load_user_config(void)
-{
- /* Don't continue adding to this list. When 3.0 rolls around bump
- the 2.4 files off the list. */
- static const gchar *saved_report_files[] =
- {
- SAVED_REPORTS_FILE, SAVED_REPORTS_FILE_OLD_REV, NULL
- };
- static const gchar *stylesheet_files[] = { "stylesheets-2.0", NULL};
- static int is_user_config_loaded = FALSE;
-
- if (is_user_config_loaded)
- return;
- else is_user_config_loaded = TRUE;
-
- update_message("loading user configuration");
- {
- gchar *config_filename;
- config_filename = g_build_filename (gnc_userconfig_dir (),
- "config-user.scm", (char *)NULL);
- gfec_try_load(config_filename);
- g_free(config_filename);
- }
-
- update_message("loading saved reports");
- try_load_config_array(saved_report_files);
- update_message("loading stylesheets");
- try_load_config_array(stylesheet_files);
-}
-
static void
-inner_main_add_price_quotes(void *data, int argc, char **argv)
+inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
const char* add_quotes_file = static_cast<const char*>(data);
SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index ad409f9ed..8203916a7 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -22,21 +22,8 @@
*/
#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <libguile.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <binreloc.h>
-#include <gnc-locale-utils.h>
-#include <gnc-engine.h>
-#include <gnc-ui-util.h>
-#include <gnc-commodity.h>
-#include <swig-runtime.h>
#include <guile-mappings.h>
-#include <window-report.h>
#ifdef __MINGW32__
#include <Windows.h>
#include <fcntl.h>
@@ -47,14 +34,10 @@
extern "C" {
#include <dialog-new-user.h>
#include <gfec.h>
-#include <gnc-engine-guile.h>
-#include <gnc-environment.h>
#include <gnc-file.h>
#include <gnc-filepath-utils.h>
#include <gnc-gnome-utils.h>
#include <gnc-gsettings.h>
-#include <gnc-hooks.h>
-#include <gnc-main-window.h>
#include <gnc-module.h>
#include <gnc-path.h>
#include <gnc-plugin-bi-import.h>
@@ -70,7 +53,6 @@ extern "C" {
#include <gnc-report.h>
#include <gnc-session.h>
#include <gnc-splash.h>
-#include <gnc-version.h>
#include <gnucash-register.h>
#include <search-core-type.h>
#include <top-level.h>
@@ -78,43 +60,8 @@ extern "C" {
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
-
-/* Change the following to have a console window attached to GnuCash
- * for displaying stdout and stderr on Windows.
- */
-#define __MSWIN_CONSOLE__ 0
-
-#include <libintl.h>
-#include <locale.h>
-
-#ifdef MAC_INTEGRATION
-# include <Foundation/Foundation.h>
-#endif
-
-/* GNC_VCS is defined whenever we're building from an svn/svk/git/bzr tree */
-#ifdef GNC_VCS
-static int is_development_version = TRUE;
-#else
-static int is_development_version = FALSE;
-#define GNC_VCS ""
-#endif
-
static gchar *userdata_migration_msg = NULL;
-static void
-gnc_print_unstable_message(void)
-{
- if (!is_development_version) return;
-
- g_print("\n\n%s\n%s\n%s %s\n%s %s\n",
- _("This is a development version. It may or may not work."),
- _("Report bugs and other problems to gnucash-devel at gnucash.org"),
- /* Translators: An URLs follows*/
- _("You can also lookup and file bug reports at"), PACKAGE_BUGREPORT,
- /* Translators: An URLs follows*/
- _("To find the last stable version, please refer to"), PACKAGE_URL);
-}
-
static gboolean
try_load_config_array(const gchar *fns[])
{
@@ -231,7 +178,7 @@ load_gnucash_modules()
}
static void
-inner_main_add_price_quotes(void *data, int argc, char **argv)
+inner_main_add_price_quotes(void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
const char* add_quotes_file = static_cast<const char*>(data);
SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
@@ -309,7 +256,7 @@ struct t_file_spec {
};
static void
-inner_main (void *data, int argc, char **argv)
+inner_main (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
auto user_file_spec = static_cast<t_file_spec*>(data);
SCM main_mod;
commit c58cfdb87dfaa90bbb0d3b4710e3198d651819aa
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 14:06:21 2020 +0200
Extract common setup bits from gnucash and gnucash-cli into a separate class Gnucash::Base
This is just a first start, more refactoring will follow in later commits.
The idea is to have an application class that provides the basic framework
gnucash and gnucash-cli will become specializations of this class adding their
specific functionality. I'm splitting this over several commits to be able to
keep track of all the many changes.
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index 7ec6eda17..a162c5f31 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -31,14 +31,20 @@ else()
endif()
+set(gnucash_noinst_HEADERS
+ gnucash-base.hpp
+)
+
set (gnucash_SOURCES
gnucash.cpp
+ gnucash-base.cpp
gnucash-gresources.c
${GNUCASH_RESOURCE_FILE}
)
add_executable (gnucash
- ${gnucash_SOURCES}
+ ${gnucash_SOURCES}
+ ${gnucash_noinst_HEADERS}
)
add_dependencies (gnucash gnucash-manpage)
@@ -55,7 +61,9 @@ target_link_libraries (gnucash
add_executable (gnucash-cli
gnucash-cli.cpp
+ gnucash-base.cpp
${GNUCASH_RESOURCE_FILE}
+ ${gnucash_noinst_HEADERS}
)
add_dependencies (gnucash-cli gnucash)
@@ -275,8 +283,8 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash.cpp gnucash-cli.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
- price-quotes.scm ${gnucash_EXTRA_DIST})
+ gnucash.cpp gnucash-cli.cpp gnucash-base.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ price-quotes.scm ${gnucash_noinst_HEADERS} ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
${gschemas_DIST} ${gtkbuilder_DIST} ${html_DIST} ${import_export_DIST} ${python_DIST} ${register_DIST}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-base.cpp
similarity index 76%
copy from gnucash/gnucash-cli.cpp
copy to gnucash/gnucash-base.cpp
index e4b3c990e..ce3063306 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-base.cpp
@@ -1,5 +1,5 @@
/*
- * gnucash-cli.cpp -- The command line entry point for GnuCash
+ * gnucash-base.cpp -- Basic application object for gnucash binaries
*
* Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
*
@@ -40,6 +40,8 @@
#include <fcntl.h>
#endif
+#include "gnucash-base.hpp"
+
extern "C" {
#include <gfec.h>
#include <gnc-engine-guile.h>
@@ -80,82 +82,7 @@ static int is_development_version = FALSE;
#define GNC_VCS ""
#endif
-/* Command-line option variables */
-static int gnucash_show_version = 0;
-static int debugging = 0;
-static int extra = 0;
-static gchar **log_flags = NULL;
-#ifdef __MINGW64__
-static wchar_t *log_to_filename = NULL;
-#else
-static char *log_to_filename = NULL;
-#endif
-static int nofile = 0;
-static const gchar *gsettings_prefix = NULL;
-static const char *add_quotes_file = NULL;
-static char *namespace_regexp = NULL;
-static const char *file_to_load = NULL;
-static gchar **args_remaining = NULL;
-static gchar *sys_locale = NULL;
-
-static GOptionEntry options[] =
-{
- {
- "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
- N_("Show GnuCash version"), NULL
- },
-
- {
- "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
- N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
- },
-
- {
- "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
- N_("Enable extra/development/debugging features."), NULL
- },
- {
- "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
- N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
- NULL
- },
-
- {
- "logto", '\0', 0, G_OPTION_ARG_STRING, &log_to_filename,
- N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
- NULL
- },
-
- {
- "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
- N_("Do not load the last file opened"), NULL
- },
- {
- "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
- N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("GSETTINGSPREFIX")
- },
- {
- "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
- N_("Add price quotes to given GnuCash datafile"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("FILE")
- },
- {
- "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
- N_("Regular expression determining which namespace commodities will be retrieved"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("REGEXP")
- },
- {
- G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
- { NULL }
-};
static gchar *userdata_migration_msg = NULL;
@@ -424,124 +351,12 @@ load_user_config(void)
try_load_config_array(stylesheet_files);
}
-/* Parse command line options, using GOption interface.
- * We can't let gtk_init_with_args do it because it fails
- * before parsing any arguments if the GUI can't be initialized.
- */
-static void
-gnc_parse_command_line(int *argc, char ***argv)
-{
- GError *error = NULL;
- GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
-
- g_option_context_add_main_entries (context, options, PROJECT_NAME);
- g_option_context_add_group (context, gtk_get_option_group(FALSE));
- if (!g_option_context_parse (context, argc, argv, &error))
- {
- g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
- error->message, *argv[0]);
- g_error_free (error);
- exit (1);
- }
- g_option_context_free (context);
- if (gnucash_show_version)
- {
- const char *format_string;
- if (is_development_version)
- format_string = _("GnuCash %s development version");
- else
- format_string = _("GnuCash %s");
-
- g_print (format_string, gnc_version());
- g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
- exit(0);
- }
-
- gnc_prefs_set_debugging(debugging);
- gnc_prefs_set_extra(extra);
-
- if (gsettings_prefix)
- gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
-
- if (namespace_regexp)
- gnc_prefs_set_namespace_regexp(namespace_regexp);
-
- if (args_remaining)
- file_to_load = args_remaining[0];
-}
-
-static void
-inner_main_add_price_quotes(void *closure, int argc, char **argv)
-{
- SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
- QofSession *session = NULL;
-
- scm_c_eval_string("(debug-set! stack 200000)");
-
- mod = scm_c_resolve_module("gnucash price-quotes");
- scm_set_current_module(mod);
-
- gnc_prefs_init ();
- qof_event_suspend();
- scm_c_eval_string("(gnc:price-quotes-install-sources)");
-
- if (!gnc_quote_source_fq_installed())
- {
- g_print("%s", _("No quotes retrieved. Finance::Quote isn't "
- "installed properly.\n"));
- goto fail;
- }
-
- add_quotes = scm_c_eval_string("gnc:book-add-quotes");
- session = gnc_get_current_session();
- if (!session) goto fail;
-
- qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_load(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- scm_book = gnc_book_to_scm(qof_session_get_book(session));
- scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);
-
- qof_session_save(session, NULL);
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
-
- qof_session_destroy(session);
- if (!scm_is_true(scm_result))
- {
- g_warning("Failed to add quotes to %s.", add_quotes_file);
- goto fail;
- }
-
- qof_event_resume();
- gnc_shutdown(0);
- return;
-fail:
- if (session)
- {
- if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
- g_warning("Session Error: %s",
- qof_session_get_error_message(session));
- qof_session_destroy(session);
- }
- qof_event_resume();
- gnc_shutdown(1);
-}
static void
-gnc_log_init()
+gnc_log_init (gchar **log_flags, gchar *log_to_filename)
{
if (log_to_filename != NULL)
- {
-#ifdef __MINGW64__
- char* filename = g_utf16_to_utf8(log_to_filename, -1, NULL, NULL, NULL);
-#else
- char* filename = log_to_filename;
-#endif
- qof_log_init_filename_special(filename);
- }
+ qof_log_init_filename_special(log_to_filename);
else
{
/* initialize logging to our file. */
@@ -689,14 +504,12 @@ redirect_stdout (void)
#endif
}
-int
-main(int argc, char ** argv)
+Gnucash::Base::Base ()
{
- gchar *localedir = gnc_path_get_localedir();
-#if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
-# error "No GLib thread implementation available!"
-#endif
-#ifdef ENABLE_BINRELOC
+ #if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
+ # error "No GLib thread implementation available!"
+ #endif
+ #ifdef ENABLE_BINRELOC
{
GError *binreloc_error = NULL;
if (!gnc_gbr_init(&binreloc_error))
@@ -705,47 +518,192 @@ main(int argc, char ** argv)
g_error_free(binreloc_error);
}
}
-#endif
+ #endif
redirect_stdout ();
/* This should be called before gettext is initialized
* The user may have configured a different language via
* the environment file.
*/
-#ifdef MAC_INTEGRATION
+ #ifdef MAC_INTEGRATION
set_mac_locale();
-#elif defined __MINGW32__
+ #elif defined __MINGW32__
set_win32_thread_locale();
-#endif
+ #endif
gnc_environment_setup();
-#if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
+ #if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
sys_locale = g_strdup (setlocale (LC_ALL, ""));
if (!sys_locale)
- {
+ {
g_print ("The locale defined in the environment isn't supported. "
- "Falling back to the 'C' (US English) locale\n");
+ "Falling back to the 'C' (US English) locale\n");
g_setenv ("LC_ALL", "C", TRUE);
setlocale (LC_ALL, "C");
- }
-#endif
+ }
+ #endif
+
+ auto localedir = gnc_path_get_localedir ();
bindtextdomain(PROJECT_NAME, localedir);
bindtextdomain("iso_4217", localedir); // For win32 to find currency name translations
bind_textdomain_codeset("iso_4217", "UTF-8");
textdomain(PROJECT_NAME);
bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
g_free(localedir);
+}
+
+/* Parse command line options, using GOption interface.
+ * We can't let gtk_init_with_args do it because it fails
+ * before parsing any arguments if the GUI can't be initialized.
+ */
+void
+Gnucash::Base::parse_command_line (int *argc, char ***argv)
+{
+#ifdef __MINGW64__
+ wchar_t *tmp_log_to_filename = NULL;
+#else
+ char *tmp_log_to_filename = NULL;
+#endif
+
+ GOptionEntry options[] =
+ {
+ {
+ "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
+ N_("Show GnuCash version"), NULL
+ },
+
+ {
+ "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
+ N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
+ },
+
+ {
+ "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
+ N_("Enable extra/development/debugging features."), NULL
+ },
- gnc_parse_command_line(&argc, &argv);
+ {
+ "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
+ N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
+ NULL
+ },
+
+ {
+ "logto", '\0', 0, G_OPTION_ARG_STRING, &tmp_log_to_filename,
+ N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
+ NULL
+ },
+
+ {
+ "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
+ N_("Do not load the last file opened"), NULL
+ },
+ {
+ "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
+ N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
+ /* Translators: Argument description for autohelp; see
+ * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("GSETTINGSPREFIX")
+ },
+ {
+ "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
+ N_("Add price quotes to given GnuCash datafile"),
+ /* Translators: Argument description for autohelp; see
+ * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("FILE")
+ },
+ {
+ "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
+ N_("Regular expression determining which namespace commodities will be retrieved"),
+ /* Translators: Argument description for autohelp; see
+ * http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("REGEXP")
+ },
+ {
+ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
+ { NULL }
+ };
+
+ GError *error = NULL;
+ GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
+
+ g_option_context_add_main_entries (context, options, PROJECT_NAME);
+ g_option_context_add_group (context, gtk_get_option_group(FALSE));
+ if (!g_option_context_parse (context, argc, argv, &error))
+ {
+ g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
+ error->message, *argv[0]);
+ g_error_free (error);
+ exit (1);
+ }
+ g_option_context_free (context);
+
+ if (tmp_log_to_filename != NULL)
+ {
+#ifdef __MINGW64__
+ log_to_filename = g_utf16_to_utf8(tmp_log_to_filename, -1, NULL, NULL, NULL);
+ g_free (tmp_log_to_filename);
+#else
+ log_to_filename = tmp_log_to_filename;
+#endif
+ }
+
+ if (gnucash_show_version)
+ {
+ const char *format_string;
+ if (is_development_version)
+ format_string = _("GnuCash %s development version");
+ else
+ format_string = _("GnuCash %s");
+
+ g_print (format_string, gnc_version());
+ g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
+ exit(0);
+ }
+
+ gnc_prefs_set_debugging(debugging);
+ gnc_prefs_set_extra(extra);
+
+ if (gsettings_prefix)
+ gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
+
+ if (namespace_regexp)
+ gnc_prefs_set_namespace_regexp(namespace_regexp);
+
+ if (args_remaining)
+ file_to_load = args_remaining[0];
+}
+
+const char*
+Gnucash::Base::get_file_to_load (void)
+{
+ return file_to_load;
+}
+
+int
+Gnucash::Base::get_no_file (void)
+{
+ return nofile;
+}
+
+const char*
+Gnucash::Base::get_quotes_file (void)
+{
+ return add_quotes_file;
+}
+
+void
+Gnucash::Base::start (void)
+{
gnc_print_unstable_message();
/* Make sure gnucash' user data directory is properly set up
- This must be done before any guile code is called as that would
- fail the migration message */
+ * This must be done before any guile code is called as that would
+ * fail the migration message */
userdata_migration_msg = gnc_filepath_init();
if (userdata_migration_msg)
g_print("\n\n%s\n", userdata_migration_msg);
- gnc_log_init();
+ gnc_log_init (log_flags, log_to_filename);
gnc_engine_init (0, NULL);
/* Write some locale details to the log to simplify debugging */
@@ -753,9 +711,4 @@ main(int argc, char ** argv)
PINFO ("Effective locale set to %s.", setlocale (LC_ALL, NULL));
g_free (sys_locale);
sys_locale = NULL;
-
- if (add_quotes_file)
- scm_boot_guile(argc, argv, inner_main_add_price_quotes, 0);
-
- exit(0); /* never reached */
}
diff --git a/gnucash/gnucash-base.hpp b/gnucash/gnucash-base.hpp
new file mode 100644
index 000000000..11652b4e1
--- /dev/null
+++ b/gnucash/gnucash-base.hpp
@@ -0,0 +1,59 @@
+/*
+ * gnucash-base.hpp -- Basic application object for gnucash binaries
+ *
+ * Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+#ifndef GNUCASH_BASE_HPP
+#define GNUCASH_BASE_HPP
+
+namespace Gnucash {
+
+class Base
+{
+public:
+ Base ();
+
+ void parse_command_line (int *argc, char ***argv);
+ void start (void);
+
+ const char *get_file_to_load (void);
+ int get_no_file (void);
+ const char *get_quotes_file (void);
+
+private:
+
+ /* Command-line option variables */
+ int gnucash_show_version = 0;
+ int debugging = 0;
+ int extra = 0;
+ gchar **log_flags = NULL;
+ char *log_to_filename = NULL;
+ int nofile = 0;
+ const gchar *gsettings_prefix = NULL;
+ const char *add_quotes_file = NULL;
+ char *namespace_regexp = NULL;
+ const char *file_to_load = NULL;
+ gchar **args_remaining = NULL;
+ gchar *sys_locale = NULL;
+};
+
+}
+#endif
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
index e4b3c990e..ea89f7cf4 100644
--- a/gnucash/gnucash-cli.cpp
+++ b/gnucash/gnucash-cli.cpp
@@ -40,6 +40,8 @@
#include <fcntl.h>
#endif
+#include "gnucash-base.hpp"
+
extern "C" {
#include <gfec.h>
#include <gnc-engine-guile.h>
@@ -80,83 +82,6 @@ static int is_development_version = FALSE;
#define GNC_VCS ""
#endif
-/* Command-line option variables */
-static int gnucash_show_version = 0;
-static int debugging = 0;
-static int extra = 0;
-static gchar **log_flags = NULL;
-#ifdef __MINGW64__
-static wchar_t *log_to_filename = NULL;
-#else
-static char *log_to_filename = NULL;
-#endif
-static int nofile = 0;
-static const gchar *gsettings_prefix = NULL;
-static const char *add_quotes_file = NULL;
-static char *namespace_regexp = NULL;
-static const char *file_to_load = NULL;
-static gchar **args_remaining = NULL;
-static gchar *sys_locale = NULL;
-
-static GOptionEntry options[] =
-{
- {
- "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
- N_("Show GnuCash version"), NULL
- },
-
- {
- "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
- N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
- },
-
- {
- "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
- N_("Enable extra/development/debugging features."), NULL
- },
-
- {
- "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
- N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
- NULL
- },
-
- {
- "logto", '\0', 0, G_OPTION_ARG_STRING, &log_to_filename,
- N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
- NULL
- },
-
- {
- "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
- N_("Do not load the last file opened"), NULL
- },
- {
- "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
- N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("GSETTINGSPREFIX")
- },
- {
- "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
- N_("Add price quotes to given GnuCash datafile"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("FILE")
- },
- {
- "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
- N_("Regular expression determining which namespace commodities will be retrieved"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("REGEXP")
- },
- {
- G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
- { NULL }
-};
-
static gchar *userdata_migration_msg = NULL;
static void
@@ -173,183 +98,6 @@ gnc_print_unstable_message(void)
_("To find the last stable version, please refer to"), PACKAGE_URL);
}
-#ifdef MAC_INTEGRATION
-static void
-mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
-{
- /* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
- NSLocale *cur_locale = [[NSLocale alloc] initWithLocaleIdentifier: locale_str];
- if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
- [cur_locale objectForKey: NSLocaleCurrencyCode]])
- {
- NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
- NSEnumerator *locale_iter = [all_locales objectEnumerator];
- NSString *this_locale;
- NSString *currency = [locale objectForKey: NSLocaleCurrencyCode];
- NSString *money_locale = nil;
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- {
- NSLocale *templocale = [[NSLocale alloc]
- initWithLocaleIdentifier: this_locale];
- if ([[templocale objectForKey: NSLocaleCurrencyCode]
- isEqualToString: currency])
- {
- money_locale = this_locale;
- [templocale release];
- break;
- }
- [templocale release];
- }
- if (money_locale)
- setlocale(LC_MONETARY, [money_locale UTF8String]);
- }
- [cur_locale release];
-}
-/* The locale that we got from AppKit isn't a supported POSIX one, so we need to
- * find something close. First see if we can find another locale for the
- * country; failing that, try the language. Ultimately fall back on en_US.
- */
-static NSString*
-mac_find_close_country(NSString *locale_str, NSString *country_str,
- NSString *lang_str)
-{
- NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
- NSEnumerator *locale_iter = [all_locales objectEnumerator];
- NSString *this_locale, *new_locale = nil;
- PWARN("Apple Locale is set to a value %s not supported"
- " by the C runtime", [locale_str UTF8String]);
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
- objectForKey: NSLocaleCountryCode]
- isEqualToString: country_str] &&
- setlocale (LC_ALL, [this_locale UTF8String]))
- {
- new_locale = this_locale;
- break;
- }
- if (!new_locale)
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
- objectForKey: NSLocaleLanguageCode]
- isEqualToString: lang_str] &&
- setlocale (LC_ALL, [this_locale UTF8String]))
- {
- new_locale = this_locale;
- break;
- }
- if (new_locale)
- locale_str = new_locale;
- else
- {
- locale_str = @"en_US";
- setlocale(LC_ALL, [locale_str UTF8String]);
- }
- PWARN("Using %s instead.", [locale_str UTF8String]);
- return locale_str;
-}
-
-/* Language subgroups (e.g., US English) are reported in the form "ll-SS"
- * (e.g. again, "en-US"), not what gettext wants. We convert those to
- * old-style locales, which is easy for most cases. There are two where it
- * isn't, though: Simplified Chinese (zh-Hans) and traditional Chinese
- * (zh-Hant), which are normally assigned the locales zh_CN and zh_TW,
- * respectively. Those are handled specially.
- */
-static NSString*
-mac_convert_complex_language(NSString* this_lang)
-{
- NSArray *elements = [this_lang componentsSeparatedByString: @"-"];
- if ([elements count] == 1)
- return this_lang;
- if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
- if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
- this_lang = @"zh_CN";
- else
- this_lang = @"zh_TW";
- }
- else
- this_lang = [elements componentsJoinedByString: @"_"];
- return this_lang;
-}
-
-static void
-mac_set_languages(NSArray* languages, NSString *lang_str)
-{
- /* Process the language list. */
-
- const gchar *langs = NULL;
- NSEnumerator *lang_iter = [languages objectEnumerator];
- NSArray *new_languages = [NSArray array];
- NSString *this_lang = NULL;
- NSRange not_found = {NSNotFound, 0};
- while ((this_lang = [lang_iter nextObject])) {
- this_lang = [this_lang stringByTrimmingCharactersInSet:
- [NSCharacterSet characterSetWithCharactersInString: @"\""]];
- this_lang = mac_convert_complex_language(this_lang);
- new_languages = [new_languages arrayByAddingObject: this_lang];
-/* If it's an English language, add the "C" locale after it so that
- * any messages can default to it */
- if (!NSEqualRanges([this_lang rangeOfString: @"en"], not_found))
- new_languages = [new_languages arrayByAddingObject: @"C"];
- if (![new_languages containsObject: lang_str]) {
- NSArray *temp_array = [NSArray arrayWithObject: lang_str];
- new_languages = [temp_array arrayByAddingObjectsFromArray: new_languages];
- }
- langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
- }
- if (langs && strlen(langs) > 0)
- {
- PWARN("Language list: %s", langs);
- g_setenv("LANGUAGE", langs, TRUE);
- }
-}
-
-static void
-set_mac_locale()
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
- NSLocale *locale = [NSLocale currentLocale];
- NSString *lang_str, *country_str, *locale_str;
- NSArray *languages = [[defs arrayForKey: @"AppleLanguages"] retain];
- @try
- {
- lang_str = [locale objectForKey: NSLocaleLanguageCode];
- country_str = [locale objectForKey: NSLocaleCountryCode];
- locale_str = [[lang_str stringByAppendingString: @"_"]
- stringByAppendingString: country_str];
- }
- @catch (NSException *err)
- {
- PWARN("Locale detection raised error %s: %s. "
- "Check that your locale settings in "
- "System Preferences>Languages & Text are set correctly.",
- [[err name] UTF8String], [[err reason] UTF8String]);
- locale_str = @"_";
- }
-/* If we didn't get a valid current locale, the string will be just "_" */
- if ([locale_str isEqualToString: @"_"])
- locale_str = @"en_US";
-
- lang_str = mac_convert_complex_language(lang_str);
- if (!setlocale(LC_ALL, [locale_str UTF8String]))
- locale_str = mac_find_close_country(locale_str, country_str, lang_str);
- if (g_getenv("LANG") == NULL)
- g_setenv("LANG", [locale_str UTF8String], TRUE);
- mac_set_currency_locale(locale, locale_str);
-/* Now call gnc_localeconv() to force creation of the app locale
- * before another call to setlocale messes it up. */
- gnc_localeconv ();
- /* Process the languages, including the one from the Apple locale. */
- if ([languages count] > 0)
- mac_set_languages(languages, lang_str);
- else
- g_setenv("LANGUAGE", [lang_str UTF8String], TRUE);
- [languages release];
- [pool drain];
-}
-#endif /* MAC_INTEGRATION */
-
static gboolean
try_load_config_array(const gchar *fns[])
{
@@ -424,55 +172,10 @@ load_user_config(void)
try_load_config_array(stylesheet_files);
}
-/* Parse command line options, using GOption interface.
- * We can't let gtk_init_with_args do it because it fails
- * before parsing any arguments if the GUI can't be initialized.
- */
static void
-gnc_parse_command_line(int *argc, char ***argv)
-{
- GError *error = NULL;
- GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
-
- g_option_context_add_main_entries (context, options, PROJECT_NAME);
- g_option_context_add_group (context, gtk_get_option_group(FALSE));
- if (!g_option_context_parse (context, argc, argv, &error))
- {
- g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
- error->message, *argv[0]);
- g_error_free (error);
- exit (1);
- }
- g_option_context_free (context);
- if (gnucash_show_version)
- {
- const char *format_string;
- if (is_development_version)
- format_string = _("GnuCash %s development version");
- else
- format_string = _("GnuCash %s");
-
- g_print (format_string, gnc_version());
- g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
- exit(0);
- }
-
- gnc_prefs_set_debugging(debugging);
- gnc_prefs_set_extra(extra);
-
- if (gsettings_prefix)
- gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
-
- if (namespace_regexp)
- gnc_prefs_set_namespace_regexp(namespace_regexp);
-
- if (args_remaining)
- file_to_load = args_remaining[0];
-}
-
-static void
-inner_main_add_price_quotes(void *closure, int argc, char **argv)
+inner_main_add_price_quotes(void *data, int argc, char **argv)
{
+ const char* add_quotes_file = static_cast<const char*>(data);
SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
QofSession *session = NULL;
@@ -530,232 +233,17 @@ fail:
gnc_shutdown(1);
}
-static void
-gnc_log_init()
-{
- if (log_to_filename != NULL)
- {
-#ifdef __MINGW64__
- char* filename = g_utf16_to_utf8(log_to_filename, -1, NULL, NULL, NULL);
-#else
- char* filename = log_to_filename;
-#endif
- qof_log_init_filename_special(filename);
- }
- else
- {
- /* initialize logging to our file. */
- gchar *tracefilename;
- tracefilename = g_build_filename(g_get_tmp_dir(), "gnucash.trace",
- (gchar *)NULL);
- qof_log_init_filename(tracefilename);
- g_free(tracefilename);
- }
-
- // set a reasonable default.
- qof_log_set_default(QOF_LOG_WARNING);
-
- gnc_log_default();
-
- if (gnc_prefs_is_debugging_enabled())
- {
- qof_log_set_level("", QOF_LOG_INFO);
- qof_log_set_level("qof", QOF_LOG_INFO);
- qof_log_set_level("gnc", QOF_LOG_INFO);
- }
-
- {
- gchar *log_config_filename;
- log_config_filename = g_build_filename (gnc_userconfig_dir (),
- "log.conf", (char *)NULL);
- if (g_file_test(log_config_filename, G_FILE_TEST_EXISTS))
- qof_log_parse_log_config(log_config_filename);
- g_free(log_config_filename);
- }
-
- if (log_flags != NULL)
- {
- int i = 0;
- for (; log_flags[i] != NULL; i++)
- {
- QofLogLevel level;
- gchar **parts = NULL;
-
- gchar *log_opt = log_flags[i];
- parts = g_strsplit(log_opt, "=", 2);
- if (parts == NULL || parts[0] == NULL || parts[1] == NULL)
- {
- g_warning("string [%s] not parseable", log_opt);
- continue;
- }
-
- level = qof_log_level_from_string(parts[1]);
- qof_log_set_level(parts[0], level);
- g_strfreev(parts);
- }
- }
-}
-
-#ifdef __MINGW32__
-/* If one of the Unix locale variables LC_ALL, LC_MESSAGES, or LANG is
- * set in the environment check to see if it's a valid locale and if
- * it is set both the Windows and POSIX locales to that. If not
- * retrieve the Windows locale and set POSIX to match.
- */
-static void
-set_win32_thread_locale()
-{
- WCHAR lpLocaleName[LOCALE_NAME_MAX_LENGTH];
- char *locale = NULL;
-
- if (((locale = getenv ("LC_ALL")) != NULL && locale[0] != '\0') ||
- ((locale = getenv ("LC_MESSAGES")) != NULL && locale[0] != '\0') ||
- ((locale = getenv ("LANG")) != NULL && locale[0] != '\0'))
- {
- gunichar2* wlocale = NULL;
- int len = 0;
- len = strchr(locale, '.') - locale;
- locale[2] = '-';
- wlocale = g_utf8_to_utf16 (locale, len, NULL, NULL, NULL);
- if (IsValidLocaleName(wlocale))
- {
- LCID lcid = LocaleNameToLCID(wlocale, LOCALE_ALLOW_NEUTRAL_NAMES);
- SetThreadLocale(lcid);
- locale[2] = '_';
- setlocale (LC_ALL, locale);
- sys_locale = locale;
- g_free(wlocale);
- return;
- }
- g_free(locale);
- g_free(wlocale);
- }
- if (GetUserDefaultLocaleName(lpLocaleName, LOCALE_NAME_MAX_LENGTH))
- {
- sys_locale = g_utf16_to_utf8((gunichar2*)lpLocaleName,
- LOCALE_NAME_MAX_LENGTH,
- NULL, NULL, NULL);
- sys_locale[2] = '_';
- setlocale (LC_ALL, sys_locale);
- return;
- }
-}
-#endif
-
-/* Creates a console window on MSWindows to display stdout and stderr
- * when __MSWIN_CONSOLE__ is defined at the top of the file.
- *
- * Useful for displaying the diagnostics printed before logging is
- * started and if logging is redirected with --logto=stderr.
- */
-static void
-redirect_stdout (void)
-{
-#if defined __MINGW32__ && __MSWIN_CONSOLE__
- static const WORD MAX_CONSOLE_LINES = 500;
- int hConHandle;
- long lStdHandle;
- CONSOLE_SCREEN_BUFFER_INFO coninfo;
- FILE *fp;
-
- // allocate a console for this app
- AllocConsole();
-
- // set the screen buffer to be big enough to let us scroll text
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
- coninfo.dwSize.Y = MAX_CONSOLE_LINES;
- SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
-
- // redirect unbuffered STDOUT to the console
- lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "w" );
- *stdout = *fp;
- setvbuf( stdout, NULL, _IONBF, 0 );
-
- // redirect unbuffered STDIN to the console
- lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "r" );
- *stdin = *fp;
- setvbuf( stdin, NULL, _IONBF, 0 );
-
- // redirect unbuffered STDERR to the console
- lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "w" );
- *stderr = *fp;
- setvbuf( stderr, NULL, _IONBF, 0 );
-#endif
-}
-
int
main(int argc, char ** argv)
{
- gchar *localedir = gnc_path_get_localedir();
-#if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
-# error "No GLib thread implementation available!"
-#endif
-#ifdef ENABLE_BINRELOC
- {
- GError *binreloc_error = NULL;
- if (!gnc_gbr_init(&binreloc_error))
- {
- g_print("main: Error on gnc_gbr_init: %s\n", binreloc_error->message);
- g_error_free(binreloc_error);
- }
- }
-#endif
- redirect_stdout ();
+ Gnucash::Base application;
- /* This should be called before gettext is initialized
- * The user may have configured a different language via
- * the environment file.
- */
-#ifdef MAC_INTEGRATION
- set_mac_locale();
-#elif defined __MINGW32__
- set_win32_thread_locale();
-#endif
- gnc_environment_setup();
-#if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
- sys_locale = g_strdup (setlocale (LC_ALL, ""));
- if (!sys_locale)
- {
- g_print ("The locale defined in the environment isn't supported. "
- "Falling back to the 'C' (US English) locale\n");
- g_setenv ("LC_ALL", "C", TRUE);
- setlocale (LC_ALL, "C");
- }
-#endif
- bindtextdomain(PROJECT_NAME, localedir);
- bindtextdomain("iso_4217", localedir); // For win32 to find currency name translations
- bind_textdomain_codeset("iso_4217", "UTF-8");
- textdomain(PROJECT_NAME);
- bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
- g_free(localedir);
-
- gnc_parse_command_line(&argc, &argv);
- gnc_print_unstable_message();
-
- /* Make sure gnucash' user data directory is properly set up
- This must be done before any guile code is called as that would
- fail the migration message */
- userdata_migration_msg = gnc_filepath_init();
- if (userdata_migration_msg)
- g_print("\n\n%s\n", userdata_migration_msg);
-
- gnc_log_init();
- gnc_engine_init (0, NULL);
-
- /* Write some locale details to the log to simplify debugging */
- PINFO ("System locale returned %s", sys_locale ? sys_locale : "(null)");
- PINFO ("Effective locale set to %s.", setlocale (LC_ALL, NULL));
- g_free (sys_locale);
- sys_locale = NULL;
-
- if (add_quotes_file)
- scm_boot_guile(argc, argv, inner_main_add_price_quotes, 0);
+ application.parse_command_line (&argc, &argv);
+ application.start ();
+
+ auto quotes_file = application.get_quotes_file ();
+ if (quotes_file)
+ scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void *)quotes_file);
exit(0); /* never reached */
}
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index 8419a739c..ad409f9ed 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -42,6 +42,8 @@
#include <fcntl.h>
#endif
+#include "gnucash-base.hpp"
+
extern "C" {
#include <dialog-new-user.h>
#include <gfec.h>
@@ -97,83 +99,6 @@ static int is_development_version = FALSE;
#define GNC_VCS ""
#endif
-/* Command-line option variables */
-static int gnucash_show_version = 0;
-static int debugging = 0;
-static int extra = 0;
-static gchar **log_flags = NULL;
-#ifdef __MINGW64__
-static wchar_t *log_to_filename = NULL;
-#else
-static char *log_to_filename = NULL;
-#endif
-static int nofile = 0;
-static const gchar *gsettings_prefix = NULL;
-static const char *add_quotes_file = NULL;
-static char *namespace_regexp = NULL;
-static const char *file_to_load = NULL;
-static gchar **args_remaining = NULL;
-static gchar *sys_locale = NULL;
-
-static GOptionEntry options[] =
-{
- {
- "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
- N_("Show GnuCash version"), NULL
- },
-
- {
- "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
- N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
- },
-
- {
- "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
- N_("Enable extra/development/debugging features."), NULL
- },
-
- {
- "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
- N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
- NULL
- },
-
- {
- "logto", '\0', 0, G_OPTION_ARG_STRING, &log_to_filename,
- N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
- NULL
- },
-
- {
- "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
- N_("Do not load the last file opened"), NULL
- },
- {
- "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
- N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("GSETTINGSPREFIX")
- },
- {
- "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
- N_("Add price quotes to given GnuCash datafile"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("FILE")
- },
- {
- "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
- N_("Regular expression determining which namespace commodities will be retrieved"),
- /* Translators: Argument description for autohelp; see
- http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
- N_("REGEXP")
- },
- {
- G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
- { NULL }
-};
-
static gchar *userdata_migration_msg = NULL;
static void
@@ -190,183 +115,6 @@ gnc_print_unstable_message(void)
_("To find the last stable version, please refer to"), PACKAGE_URL);
}
-#ifdef MAC_INTEGRATION
-static void
-mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
-{
- /* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
- NSLocale *cur_locale = [[NSLocale alloc] initWithLocaleIdentifier: locale_str];
- if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
- [cur_locale objectForKey: NSLocaleCurrencyCode]])
- {
- NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
- NSEnumerator *locale_iter = [all_locales objectEnumerator];
- NSString *this_locale;
- NSString *currency = [locale objectForKey: NSLocaleCurrencyCode];
- NSString *money_locale = nil;
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- {
- NSLocale *templocale = [[NSLocale alloc]
- initWithLocaleIdentifier: this_locale];
- if ([[templocale objectForKey: NSLocaleCurrencyCode]
- isEqualToString: currency])
- {
- money_locale = this_locale;
- [templocale release];
- break;
- }
- [templocale release];
- }
- if (money_locale)
- setlocale(LC_MONETARY, [money_locale UTF8String]);
- }
- [cur_locale release];
-}
-/* The locale that we got from AppKit isn't a supported POSIX one, so we need to
- * find something close. First see if we can find another locale for the
- * country; failing that, try the language. Ultimately fall back on en_US.
- */
-static NSString*
-mac_find_close_country(NSString *locale_str, NSString *country_str,
- NSString *lang_str)
-{
- NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
- NSEnumerator *locale_iter = [all_locales objectEnumerator];
- NSString *this_locale, *new_locale = nil;
- PWARN("Apple Locale is set to a value %s not supported"
- " by the C runtime", [locale_str UTF8String]);
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
- objectForKey: NSLocaleCountryCode]
- isEqualToString: country_str] &&
- setlocale (LC_ALL, [this_locale UTF8String]))
- {
- new_locale = this_locale;
- break;
- }
- if (!new_locale)
- while ((this_locale = (NSString*)[locale_iter nextObject]))
- if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
- objectForKey: NSLocaleLanguageCode]
- isEqualToString: lang_str] &&
- setlocale (LC_ALL, [this_locale UTF8String]))
- {
- new_locale = this_locale;
- break;
- }
- if (new_locale)
- locale_str = new_locale;
- else
- {
- locale_str = @"en_US";
- setlocale(LC_ALL, [locale_str UTF8String]);
- }
- PWARN("Using %s instead.", [locale_str UTF8String]);
- return locale_str;
-}
-
-/* Language subgroups (e.g., US English) are reported in the form "ll-SS"
- * (e.g. again, "en-US"), not what gettext wants. We convert those to
- * old-style locales, which is easy for most cases. There are two where it
- * isn't, though: Simplified Chinese (zh-Hans) and traditional Chinese
- * (zh-Hant), which are normally assigned the locales zh_CN and zh_TW,
- * respectively. Those are handled specially.
- */
-static NSString*
-mac_convert_complex_language(NSString* this_lang)
-{
- NSArray *elements = [this_lang componentsSeparatedByString: @"-"];
- if ([elements count] == 1)
- return this_lang;
- if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
- if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
- this_lang = @"zh_CN";
- else
- this_lang = @"zh_TW";
- }
- else
- this_lang = [elements componentsJoinedByString: @"_"];
- return this_lang;
-}
-
-static void
-mac_set_languages(NSArray* languages, NSString *lang_str)
-{
- /* Process the language list. */
-
- const gchar *langs = NULL;
- NSEnumerator *lang_iter = [languages objectEnumerator];
- NSArray *new_languages = [NSArray array];
- NSString *this_lang = NULL;
- NSRange not_found = {NSNotFound, 0};
- while ((this_lang = [lang_iter nextObject])) {
- this_lang = [this_lang stringByTrimmingCharactersInSet:
- [NSCharacterSet characterSetWithCharactersInString: @"\""]];
- this_lang = mac_convert_complex_language(this_lang);
- new_languages = [new_languages arrayByAddingObject: this_lang];
-/* If it's an English language, add the "C" locale after it so that
- * any messages can default to it */
- if (!NSEqualRanges([this_lang rangeOfString: @"en"], not_found))
- new_languages = [new_languages arrayByAddingObject: @"C"];
- if (![new_languages containsObject: lang_str]) {
- NSArray *temp_array = [NSArray arrayWithObject: lang_str];
- new_languages = [temp_array arrayByAddingObjectsFromArray: new_languages];
- }
- langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
- }
- if (langs && strlen(langs) > 0)
- {
- PWARN("Language list: %s", langs);
- g_setenv("LANGUAGE", langs, TRUE);
- }
-}
-
-static void
-set_mac_locale()
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
- NSLocale *locale = [NSLocale currentLocale];
- NSString *lang_str, *country_str, *locale_str;
- NSArray *languages = [[defs arrayForKey: @"AppleLanguages"] retain];
- @try
- {
- lang_str = [locale objectForKey: NSLocaleLanguageCode];
- country_str = [locale objectForKey: NSLocaleCountryCode];
- locale_str = [[lang_str stringByAppendingString: @"_"]
- stringByAppendingString: country_str];
- }
- @catch (NSException *err)
- {
- PWARN("Locale detection raised error %s: %s. "
- "Check that your locale settings in "
- "System Preferences>Languages & Text are set correctly.",
- [[err name] UTF8String], [[err reason] UTF8String]);
- locale_str = @"_";
- }
-/* If we didn't get a valid current locale, the string will be just "_" */
- if ([locale_str isEqualToString: @"_"])
- locale_str = @"en_US";
-
- lang_str = mac_convert_complex_language(lang_str);
- if (!setlocale(LC_ALL, [locale_str UTF8String]))
- locale_str = mac_find_close_country(locale_str, country_str, lang_str);
- if (g_getenv("LANG") == NULL)
- g_setenv("LANG", [locale_str UTF8String], TRUE);
- mac_set_currency_locale(locale, locale_str);
-/* Now call gnc_localeconv() to force creation of the app locale
- * before another call to setlocale messes it up. */
- gnc_localeconv ();
- /* Process the languages, including the one from the Apple locale. */
- if ([languages count] > 0)
- mac_set_languages(languages, lang_str);
- else
- g_setenv("LANGUAGE", [lang_str UTF8String], TRUE);
- [languages release];
- [pool drain];
-}
-#endif /* MAC_INTEGRATION */
-
static gboolean
try_load_config_array(const gchar *fns[])
{
@@ -441,52 +189,6 @@ load_user_config(void)
try_load_config_array(stylesheet_files);
}
-/* Parse command line options, using GOption interface.
- * We can't let gtk_init_with_args do it because it fails
- * before parsing any arguments if the GUI can't be initialized.
- */
-static void
-gnc_parse_command_line(int *argc, char ***argv)
-{
- GError *error = NULL;
- GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
-
- g_option_context_add_main_entries (context, options, PROJECT_NAME);
- g_option_context_add_group (context, gtk_get_option_group(FALSE));
- if (!g_option_context_parse (context, argc, argv, &error))
- {
- g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
- error->message, *argv[0]);
- g_error_free (error);
- exit (1);
- }
- g_option_context_free (context);
- if (gnucash_show_version)
- {
- const char *format_string;
- if (is_development_version)
- format_string = _("GnuCash %s development version");
- else
- format_string = _("GnuCash %s");
-
- g_print (format_string, gnc_version());
- g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
- exit(0);
- }
-
- gnc_prefs_set_debugging(debugging);
- gnc_prefs_set_extra(extra);
-
- if (gsettings_prefix)
- gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
-
- if (namespace_regexp)
- gnc_prefs_set_namespace_regexp(namespace_regexp);
-
- if (args_remaining)
- file_to_load = args_remaining[0];
-}
-
static void
load_gnucash_plugins()
{
@@ -529,8 +231,9 @@ load_gnucash_modules()
}
static void
-inner_main_add_price_quotes(void *closure, int argc, char **argv)
+inner_main_add_price_quotes(void *data, int argc, char **argv)
{
+ const char* add_quotes_file = static_cast<const char*>(data);
SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
QofSession *session = NULL;
@@ -589,7 +292,7 @@ fail:
}
static char *
-get_file_to_load()
+get_file_to_load (const char* file_to_load)
{
if (file_to_load)
return g_strdup(file_to_load);
@@ -600,9 +303,15 @@ get_file_to_load()
extern SCM scm_init_sw_gnome_module(void);
+struct t_file_spec {
+ int nofile;
+ const char *file_to_load;
+};
+
static void
-inner_main (void *closure, int argc, char **argv)
+inner_main (void *data, int argc, char **argv)
{
+ auto user_file_spec = static_cast<t_file_spec*>(data);
SCM main_mod;
char* fn = NULL;
@@ -648,7 +357,7 @@ inner_main (void *closure, int argc, char **argv)
gnc_hook_run(HOOK_STARTUP, NULL);
- if (!nofile && (fn = get_file_to_load()) && *fn )
+ if (!user_file_spec->nofile && (fn = get_file_to_load (user_file_spec->file_to_load)) && *fn )
{
gnc_update_splash_screen(_("Loading data..."), GNC_SPLASH_PERCENTAGE_UNKNOWN);
gnc_file_open_file(gnc_get_splash_screen(), fn, /*open_readonly*/ FALSE);
@@ -687,236 +396,20 @@ inner_main (void *closure, int argc, char **argv)
return;
}
-static void
-gnc_log_init()
-{
- if (log_to_filename != NULL)
- {
-#ifdef __MINGW64__
- char* filename = g_utf16_to_utf8(log_to_filename, -1, NULL, NULL, NULL);
-#else
- char* filename = log_to_filename;
-#endif
- qof_log_init_filename_special(filename);
- }
- else
- {
- /* initialize logging to our file. */
- gchar *tracefilename;
- tracefilename = g_build_filename(g_get_tmp_dir(), "gnucash.trace",
- (gchar *)NULL);
- qof_log_init_filename(tracefilename);
- g_free(tracefilename);
- }
-
- // set a reasonable default.
- qof_log_set_default(QOF_LOG_WARNING);
-
- gnc_log_default();
-
- if (gnc_prefs_is_debugging_enabled())
- {
- qof_log_set_level("", QOF_LOG_INFO);
- qof_log_set_level("qof", QOF_LOG_INFO);
- qof_log_set_level("gnc", QOF_LOG_INFO);
- }
-
- {
- gchar *log_config_filename;
- log_config_filename = g_build_filename (gnc_userconfig_dir (),
- "log.conf", (char *)NULL);
- if (g_file_test(log_config_filename, G_FILE_TEST_EXISTS))
- qof_log_parse_log_config(log_config_filename);
- g_free(log_config_filename);
- }
-
- if (log_flags != NULL)
- {
- int i = 0;
- for (; log_flags[i] != NULL; i++)
- {
- QofLogLevel level;
- gchar **parts = NULL;
-
- gchar *log_opt = log_flags[i];
- parts = g_strsplit(log_opt, "=", 2);
- if (parts == NULL || parts[0] == NULL || parts[1] == NULL)
- {
- g_warning("string [%s] not parseable", log_opt);
- continue;
- }
-
- level = qof_log_level_from_string(parts[1]);
- qof_log_set_level(parts[0], level);
- g_strfreev(parts);
- }
- }
-}
-
-#ifdef __MINGW32__
-/* If one of the Unix locale variables LC_ALL, LC_MESSAGES, or LANG is
- * set in the environment check to see if it's a valid locale and if
- * it is set both the Windows and POSIX locales to that. If not
- * retrieve the Windows locale and set POSIX to match.
- */
-static void
-set_win32_thread_locale()
-{
- WCHAR lpLocaleName[LOCALE_NAME_MAX_LENGTH];
- char *locale = NULL;
-
- if (((locale = getenv ("LC_ALL")) != NULL && locale[0] != '\0') ||
- ((locale = getenv ("LC_MESSAGES")) != NULL && locale[0] != '\0') ||
- ((locale = getenv ("LANG")) != NULL && locale[0] != '\0'))
- {
- gunichar2* wlocale = NULL;
- int len = 0;
- len = strchr(locale, '.') - locale;
- locale[2] = '-';
- wlocale = g_utf8_to_utf16 (locale, len, NULL, NULL, NULL);
- if (IsValidLocaleName(wlocale))
- {
- LCID lcid = LocaleNameToLCID(wlocale, LOCALE_ALLOW_NEUTRAL_NAMES);
- SetThreadLocale(lcid);
- locale[2] = '_';
- setlocale (LC_ALL, locale);
- sys_locale = locale;
- g_free(wlocale);
- return;
- }
- g_free(locale);
- g_free(wlocale);
- }
- if (GetUserDefaultLocaleName(lpLocaleName, LOCALE_NAME_MAX_LENGTH))
- {
- sys_locale = g_utf16_to_utf8((gunichar2*)lpLocaleName,
- LOCALE_NAME_MAX_LENGTH,
- NULL, NULL, NULL);
- sys_locale[2] = '_';
- setlocale (LC_ALL, sys_locale);
- return;
- }
-}
-#endif
-
-/* Creates a console window on MSWindows to display stdout and stderr
- * when __MSWIN_CONSOLE__ is defined at the top of the file.
- *
- * Useful for displaying the diagnostics printed before logging is
- * started and if logging is redirected with --logto=stderr.
- */
-static void
-redirect_stdout (void)
-{
-#if defined __MINGW32__ && __MSWIN_CONSOLE__
- static const WORD MAX_CONSOLE_LINES = 500;
- int hConHandle;
- long lStdHandle;
- CONSOLE_SCREEN_BUFFER_INFO coninfo;
- FILE *fp;
-
- // allocate a console for this app
- AllocConsole();
-
- // set the screen buffer to be big enough to let us scroll text
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
- coninfo.dwSize.Y = MAX_CONSOLE_LINES;
- SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
-
- // redirect unbuffered STDOUT to the console
- lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "w" );
- *stdout = *fp;
- setvbuf( stdout, NULL, _IONBF, 0 );
-
- // redirect unbuffered STDIN to the console
- lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "r" );
- *stdin = *fp;
- setvbuf( stdin, NULL, _IONBF, 0 );
-
- // redirect unbuffered STDERR to the console
- lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
- hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
- fp = _fdopen( hConHandle, "w" );
- *stderr = *fp;
- setvbuf( stderr, NULL, _IONBF, 0 );
-#endif
-}
-
int
main(int argc, char ** argv)
{
- gchar *localedir;
-#if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
-# error "No GLib thread implementation available!"
-#endif
-#ifdef ENABLE_BINRELOC
- {
- GError *binreloc_error = NULL;
- if (!gnc_gbr_init(&binreloc_error))
- {
- g_print("main: Error on gnc_gbr_init: %s\n", binreloc_error->message);
- g_error_free(binreloc_error);
- }
- }
-#endif
- redirect_stdout ();
-
- /* This should be called before gettext is initialized
- * The user may have configured a different language via
- * the environment file.
- */
-#ifdef MAC_INTEGRATION
- set_mac_locale();
-#elif defined __MINGW32__
- set_win32_thread_locale();
-#endif
- gnc_environment_setup();
-#if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
- sys_locale = g_strdup (setlocale (LC_ALL, ""));
- if (!sys_locale)
- {
- g_print ("The locale defined in the environment isn't supported. "
- "Falling back to the 'C' (US English) locale\n");
- g_setenv ("LC_ALL", "C", TRUE);
- setlocale (LC_ALL, "C");
- }
-#endif
- localedir = gnc_path_get_localedir();
- bindtextdomain(PROJECT_NAME, localedir);
- bindtextdomain("iso_4217", localedir); // For win32 to find currency name translations
- bind_textdomain_codeset("iso_4217", "UTF-8");
- textdomain(PROJECT_NAME);
- bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
- g_free(localedir);
-
- gnc_parse_command_line(&argc, &argv);
- gnc_print_unstable_message();
-
- /* Make sure gnucash' user data directory is properly set up
- This must be done before any guile code is called as that would
- fail the migration message */
- userdata_migration_msg = gnc_filepath_init();
- if (userdata_migration_msg)
- g_print("\n\n%s\n", userdata_migration_msg);
+ Gnucash::Base application;
- gnc_log_init();
- gnc_engine_init (0, NULL);
-
- /* Write some locale details to the log to simplify debugging */
- PINFO ("System locale returned %s", sys_locale ? sys_locale : "(null)");
- PINFO ("Effective locale set to %s.", setlocale (LC_ALL, NULL));
- g_free (sys_locale);
- sys_locale = NULL;
+ application.parse_command_line (&argc, &argv);
+ application.start();
/* If asked via a command line parameter, fetch quotes only */
- if (add_quotes_file)
+ auto quotes_file = application.get_quotes_file ();
+ if (quotes_file)
{
- scm_boot_guile(argc, argv, inner_main_add_price_quotes, 0);
- exit(0); /* never reached */
+ scm_boot_guile (argc, argv, inner_main_add_price_quotes, (void*) quotes_file);
+ exit (0); /* never reached */
}
/* We need to initialize gtk before looking up all modules */
@@ -934,6 +427,8 @@ main(int argc, char ** argv)
gnc_module_system_init();
gnc_gui_init();
- scm_boot_guile(argc, argv, inner_main, 0);
+
+ auto user_file_spec = t_file_spec {application.get_no_file (), application.get_file_to_load ()};
+ scm_boot_guile (argc, argv, inner_main, &user_file_spec);
exit(0); /* never reached */
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bd2dfb80e..2353a72dc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,6 +210,7 @@ gnucash/gnome-utils/print-session.c
gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
+gnucash/gnucash-base.cpp
gnucash/gnucash-cli.cpp
gnucash/gnucash.cpp
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
commit 3cd0de8ce4dd3a5acae1e71cc733cb37a3ae2387
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri May 29 13:57:20 2020 +0200
Introduce new executable 'gnucash-cli'
This tool is intended to expose certain gnucash functions to a command line interface.
The first one is --add-price-quotes. This option currently also exists in gnucash.
It will be marked deprecated there. Future extensions to this can be things like
report generation, non-interactive imports,...
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index 82ff041d1..7ec6eda17 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -45,11 +45,6 @@ add_dependencies (gnucash gnucash-manpage)
target_compile_definitions(gnucash PRIVATE -DG_LOG_DOMAIN=\"gnc.bin\")
-if (BUILDING_FROM_VCS)
- target_compile_definitions(gnucash PRIVATE -DGNC_VCS=\"git\")
- target_compile_definitions(gnc-gnome-utils PRIVATE -DGNC_VCS=\"git\")
-endif()
-
target_link_libraries (gnucash
gnc-ledger-core gnc-gnome gnc-gnome-utils gnc-app-utils
gnc-engine gnc-module gnc-core-utils gnucash-guile
@@ -58,6 +53,27 @@ target_link_libraries (gnucash
PkgConfig::GTK3 ${GUILE_LDFLAGS} ${GLIB2_LDFLAGS} ${GTK_MAC_LDFLAGS}
)
+add_executable (gnucash-cli
+ gnucash-cli.cpp
+ ${GNUCASH_RESOURCE_FILE}
+)
+
+add_dependencies (gnucash-cli gnucash)
+
+target_compile_definitions(gnucash-cli PRIVATE -DG_LOG_DOMAIN=\"gnc.bin\")
+
+target_link_libraries (gnucash-cli
+ gnc-gnome-utils gnc-app-utils
+ gnc-engine gnc-core-utils gnucash-guile gnc-report
+ ${GUILE_LDFLAGS} ${GLIB2_LDFLAGS}
+)
+
+if (BUILDING_FROM_VCS)
+ target_compile_definitions(gnucash PRIVATE -DGNC_VCS=\"git\")
+ target_compile_definitions(gnucash-cli PRIVATE -DGNC_VCS=\"git\")
+ target_compile_definitions(gnc-gnome-utils PRIVATE -DGNC_VCS=\"git\")
+endif()
+
# Get glib executable for generating the gresource file
execute_process(
COMMAND
@@ -101,7 +117,7 @@ if (MAC_INTEGRATION)
target_link_libraries(gnucash ${OSX_EXTRA_LIBRARIES})
endif()
-install(TARGETS gnucash DESTINATION ${CMAKE_INSTALL_BINDIR})
+install(TARGETS gnucash gnucash-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
# No headers to install.
@@ -259,8 +275,8 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
- price-quotes.scm ${gnucash_EXTRA_DIST})
+ gnucash.cpp gnucash-cli.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ price-quotes.scm ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
${gschemas_DIST} ${gtkbuilder_DIST} ${html_DIST} ${import_export_DIST} ${python_DIST} ${register_DIST}
diff --git a/gnucash/gnucash-cli.cpp b/gnucash/gnucash-cli.cpp
new file mode 100644
index 000000000..e4b3c990e
--- /dev/null
+++ b/gnucash/gnucash-cli.cpp
@@ -0,0 +1,761 @@
+/*
+ * gnucash-cli.cpp -- The command line entry point for GnuCash
+ *
+ * Copyright (C) 2020 Geert Janssens <geert at kobaltwit.be>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <libguile.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <binreloc.h>
+#include <gnc-locale-utils.h>
+#include <gnc-engine.h>
+#include <gnc-ui-util.h>
+#include <gnc-commodity.h>
+#include <swig-runtime.h>
+#include <guile-mappings.h>
+#ifdef __MINGW32__
+#include <Windows.h>
+#include <fcntl.h>
+#endif
+
+extern "C" {
+#include <gfec.h>
+#include <gnc-engine-guile.h>
+#include <gnc-environment.h>
+#include <gnc-filepath-utils.h>
+#include <gnc-hooks.h>
+#include <gnc-path.h>
+#include <gnc-prefs.h>
+#include <gnc-prefs-utils.h>
+#include <gnc-gnome-utils.h>
+#include <gnc-gsettings.h>
+#include <gnc-report.h>
+#include <gnc-session.h>
+#include <gnc-splash.h>
+#include <gnc-version.h>
+}
+
+/* This static indicates the debugging module that this .o belongs to. */
+static QofLogModule log_module = GNC_MOD_GUI;
+
+/* Change the following to have a console window attached to GnuCash
+ * for displaying stdout and stderr on Windows.
+ */
+#define __MSWIN_CONSOLE__ 0
+
+#include <libintl.h>
+#include <locale.h>
+
+#ifdef MAC_INTEGRATION
+# include <Foundation/Foundation.h>
+#endif
+
+/* GNC_VCS is defined whenever we're building from an svn/svk/git/bzr tree */
+#ifdef GNC_VCS
+static int is_development_version = TRUE;
+#else
+static int is_development_version = FALSE;
+#define GNC_VCS ""
+#endif
+
+/* Command-line option variables */
+static int gnucash_show_version = 0;
+static int debugging = 0;
+static int extra = 0;
+static gchar **log_flags = NULL;
+#ifdef __MINGW64__
+static wchar_t *log_to_filename = NULL;
+#else
+static char *log_to_filename = NULL;
+#endif
+static int nofile = 0;
+static const gchar *gsettings_prefix = NULL;
+static const char *add_quotes_file = NULL;
+static char *namespace_regexp = NULL;
+static const char *file_to_load = NULL;
+static gchar **args_remaining = NULL;
+static gchar *sys_locale = NULL;
+
+static GOptionEntry options[] =
+{
+ {
+ "version", 'v', 0, G_OPTION_ARG_NONE, &gnucash_show_version,
+ N_("Show GnuCash version"), NULL
+ },
+
+ {
+ "debug", '\0', 0, G_OPTION_ARG_NONE, &debugging,
+ N_("Enable debugging mode: provide deep detail in the logs.\nThis is equivalent to: --log \"=info\" --log \"qof=info\" --log \"gnc=info\""), NULL
+ },
+
+ {
+ "extra", '\0', 0, G_OPTION_ARG_NONE, &extra,
+ N_("Enable extra/development/debugging features."), NULL
+ },
+
+ {
+ "log", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &log_flags,
+ N_("Log level overrides, of the form \"modulename={debug,info,warn,crit,error}\"\nExamples: \"--log qof=debug\" or \"--log gnc.backend.file.sx=info\"\nThis can be invoked multiple times."),
+ NULL
+ },
+
+ {
+ "logto", '\0', 0, G_OPTION_ARG_STRING, &log_to_filename,
+ N_("File to log into; defaults to \"/tmp/gnucash.trace\"; can be \"stderr\" or \"stdout\"."),
+ NULL
+ },
+
+ {
+ "nofile", '\0', 0, G_OPTION_ARG_NONE, &nofile,
+ N_("Do not load the last file opened"), NULL
+ },
+ {
+ "gsettings-prefix", '\0', 0, G_OPTION_ARG_STRING, &gsettings_prefix,
+ N_("Set the prefix for gsettings schemas for gsettings queries. This can be useful to have a different settings tree while debugging."),
+ /* Translators: Argument description for autohelp; see
+ http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("GSETTINGSPREFIX")
+ },
+ {
+ "add-price-quotes", '\0', 0, G_OPTION_ARG_STRING, &add_quotes_file,
+ N_("Add price quotes to given GnuCash datafile"),
+ /* Translators: Argument description for autohelp; see
+ http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("FILE")
+ },
+ {
+ "namespace", '\0', 0, G_OPTION_ARG_STRING, &namespace_regexp,
+ N_("Regular expression determining which namespace commodities will be retrieved"),
+ /* Translators: Argument description for autohelp; see
+ http://developer.gnome.org/doc/API/2.0/glib/glib-Commandline-option-parser.html */
+ N_("REGEXP")
+ },
+ {
+ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, N_("[datafile]") },
+ { NULL }
+};
+
+static gchar *userdata_migration_msg = NULL;
+
+static void
+gnc_print_unstable_message(void)
+{
+ if (!is_development_version) return;
+
+ g_print("\n\n%s\n%s\n%s %s\n%s %s\n",
+ _("This is a development version. It may or may not work."),
+ _("Report bugs and other problems to gnucash-devel at gnucash.org"),
+ /* Translators: An URLs follows*/
+ _("You can also lookup and file bug reports at"), PACKAGE_BUGREPORT,
+ /* Translators: An URLs follows*/
+ _("To find the last stable version, please refer to"), PACKAGE_URL);
+}
+
+#ifdef MAC_INTEGRATION
+static void
+mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
+{
+ /* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
+ NSLocale *cur_locale = [[NSLocale alloc] initWithLocaleIdentifier: locale_str];
+ if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
+ [cur_locale objectForKey: NSLocaleCurrencyCode]])
+ {
+ NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
+ NSEnumerator *locale_iter = [all_locales objectEnumerator];
+ NSString *this_locale;
+ NSString *currency = [locale objectForKey: NSLocaleCurrencyCode];
+ NSString *money_locale = nil;
+ while ((this_locale = (NSString*)[locale_iter nextObject]))
+ {
+ NSLocale *templocale = [[NSLocale alloc]
+ initWithLocaleIdentifier: this_locale];
+ if ([[templocale objectForKey: NSLocaleCurrencyCode]
+ isEqualToString: currency])
+ {
+ money_locale = this_locale;
+ [templocale release];
+ break;
+ }
+ [templocale release];
+ }
+ if (money_locale)
+ setlocale(LC_MONETARY, [money_locale UTF8String]);
+ }
+ [cur_locale release];
+}
+/* The locale that we got from AppKit isn't a supported POSIX one, so we need to
+ * find something close. First see if we can find another locale for the
+ * country; failing that, try the language. Ultimately fall back on en_US.
+ */
+static NSString*
+mac_find_close_country(NSString *locale_str, NSString *country_str,
+ NSString *lang_str)
+{
+ NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
+ NSEnumerator *locale_iter = [all_locales objectEnumerator];
+ NSString *this_locale, *new_locale = nil;
+ PWARN("Apple Locale is set to a value %s not supported"
+ " by the C runtime", [locale_str UTF8String]);
+ while ((this_locale = (NSString*)[locale_iter nextObject]))
+ if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+ objectForKey: NSLocaleCountryCode]
+ isEqualToString: country_str] &&
+ setlocale (LC_ALL, [this_locale UTF8String]))
+ {
+ new_locale = this_locale;
+ break;
+ }
+ if (!new_locale)
+ while ((this_locale = (NSString*)[locale_iter nextObject]))
+ if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+ objectForKey: NSLocaleLanguageCode]
+ isEqualToString: lang_str] &&
+ setlocale (LC_ALL, [this_locale UTF8String]))
+ {
+ new_locale = this_locale;
+ break;
+ }
+ if (new_locale)
+ locale_str = new_locale;
+ else
+ {
+ locale_str = @"en_US";
+ setlocale(LC_ALL, [locale_str UTF8String]);
+ }
+ PWARN("Using %s instead.", [locale_str UTF8String]);
+ return locale_str;
+}
+
+/* Language subgroups (e.g., US English) are reported in the form "ll-SS"
+ * (e.g. again, "en-US"), not what gettext wants. We convert those to
+ * old-style locales, which is easy for most cases. There are two where it
+ * isn't, though: Simplified Chinese (zh-Hans) and traditional Chinese
+ * (zh-Hant), which are normally assigned the locales zh_CN and zh_TW,
+ * respectively. Those are handled specially.
+ */
+static NSString*
+mac_convert_complex_language(NSString* this_lang)
+{
+ NSArray *elements = [this_lang componentsSeparatedByString: @"-"];
+ if ([elements count] == 1)
+ return this_lang;
+ if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
+ if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
+ this_lang = @"zh_CN";
+ else
+ this_lang = @"zh_TW";
+ }
+ else
+ this_lang = [elements componentsJoinedByString: @"_"];
+ return this_lang;
+}
+
+static void
+mac_set_languages(NSArray* languages, NSString *lang_str)
+{
+ /* Process the language list. */
+
+ const gchar *langs = NULL;
+ NSEnumerator *lang_iter = [languages objectEnumerator];
+ NSArray *new_languages = [NSArray array];
+ NSString *this_lang = NULL;
+ NSRange not_found = {NSNotFound, 0};
+ while ((this_lang = [lang_iter nextObject])) {
+ this_lang = [this_lang stringByTrimmingCharactersInSet:
+ [NSCharacterSet characterSetWithCharactersInString: @"\""]];
+ this_lang = mac_convert_complex_language(this_lang);
+ new_languages = [new_languages arrayByAddingObject: this_lang];
+/* If it's an English language, add the "C" locale after it so that
+ * any messages can default to it */
+ if (!NSEqualRanges([this_lang rangeOfString: @"en"], not_found))
+ new_languages = [new_languages arrayByAddingObject: @"C"];
+ if (![new_languages containsObject: lang_str]) {
+ NSArray *temp_array = [NSArray arrayWithObject: lang_str];
+ new_languages = [temp_array arrayByAddingObjectsFromArray: new_languages];
+ }
+ langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
+ }
+ if (langs && strlen(langs) > 0)
+ {
+ PWARN("Language list: %s", langs);
+ g_setenv("LANGUAGE", langs, TRUE);
+ }
+}
+
+static void
+set_mac_locale()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
+ NSLocale *locale = [NSLocale currentLocale];
+ NSString *lang_str, *country_str, *locale_str;
+ NSArray *languages = [[defs arrayForKey: @"AppleLanguages"] retain];
+ @try
+ {
+ lang_str = [locale objectForKey: NSLocaleLanguageCode];
+ country_str = [locale objectForKey: NSLocaleCountryCode];
+ locale_str = [[lang_str stringByAppendingString: @"_"]
+ stringByAppendingString: country_str];
+ }
+ @catch (NSException *err)
+ {
+ PWARN("Locale detection raised error %s: %s. "
+ "Check that your locale settings in "
+ "System Preferences>Languages & Text are set correctly.",
+ [[err name] UTF8String], [[err reason] UTF8String]);
+ locale_str = @"_";
+ }
+/* If we didn't get a valid current locale, the string will be just "_" */
+ if ([locale_str isEqualToString: @"_"])
+ locale_str = @"en_US";
+
+ lang_str = mac_convert_complex_language(lang_str);
+ if (!setlocale(LC_ALL, [locale_str UTF8String]))
+ locale_str = mac_find_close_country(locale_str, country_str, lang_str);
+ if (g_getenv("LANG") == NULL)
+ g_setenv("LANG", [locale_str UTF8String], TRUE);
+ mac_set_currency_locale(locale, locale_str);
+/* Now call gnc_localeconv() to force creation of the app locale
+ * before another call to setlocale messes it up. */
+ gnc_localeconv ();
+ /* Process the languages, including the one from the Apple locale. */
+ if ([languages count] > 0)
+ mac_set_languages(languages, lang_str);
+ else
+ g_setenv("LANGUAGE", [lang_str UTF8String], TRUE);
+ [languages release];
+ [pool drain];
+}
+#endif /* MAC_INTEGRATION */
+
+static gboolean
+try_load_config_array(const gchar *fns[])
+{
+ gchar *filename;
+ int i;
+
+ for (i = 0; fns[i]; i++)
+ {
+ filename = gnc_build_userdata_path(fns[i]);
+ if (gfec_try_load(filename))
+ {
+ g_free(filename);
+ return TRUE;
+ }
+ g_free(filename);
+ }
+ return FALSE;
+}
+
+static void
+update_message(const gchar *msg)
+{
+ gnc_update_splash_screen(msg, GNC_SPLASH_PERCENTAGE_UNKNOWN);
+ g_message("%s", msg);
+}
+
+static void
+load_system_config(void)
+{
+ static int is_system_config_loaded = FALSE;
+ gchar *system_config_dir;
+ gchar *system_config;
+
+ if (is_system_config_loaded) return;
+
+ update_message("loading system configuration");
+ system_config_dir = gnc_path_get_pkgsysconfdir();
+ system_config = g_build_filename(system_config_dir, "config", NULL);
+ is_system_config_loaded = gfec_try_load(system_config);
+ g_free(system_config_dir);
+ g_free(system_config);
+}
+
+static void
+load_user_config(void)
+{
+ /* Don't continue adding to this list. When 3.0 rolls around bump
+ the 2.4 files off the list. */
+ static const gchar *saved_report_files[] =
+ {
+ SAVED_REPORTS_FILE, SAVED_REPORTS_FILE_OLD_REV, NULL
+ };
+ static const gchar *stylesheet_files[] = { "stylesheets-2.0", NULL};
+ static int is_user_config_loaded = FALSE;
+
+ if (is_user_config_loaded)
+ return;
+ else is_user_config_loaded = TRUE;
+
+ update_message("loading user configuration");
+ {
+ gchar *config_filename;
+ config_filename = g_build_filename (gnc_userconfig_dir (),
+ "config-user.scm", (char *)NULL);
+ gfec_try_load(config_filename);
+ g_free(config_filename);
+ }
+
+ update_message("loading saved reports");
+ try_load_config_array(saved_report_files);
+ update_message("loading stylesheets");
+ try_load_config_array(stylesheet_files);
+}
+
+/* Parse command line options, using GOption interface.
+ * We can't let gtk_init_with_args do it because it fails
+ * before parsing any arguments if the GUI can't be initialized.
+ */
+static void
+gnc_parse_command_line(int *argc, char ***argv)
+{
+ GError *error = NULL;
+ GOptionContext *context = g_option_context_new (_("- GnuCash, accounting for personal and small business finance"));
+
+ g_option_context_add_main_entries (context, options, PROJECT_NAME);
+ g_option_context_add_group (context, gtk_get_option_group(FALSE));
+ if (!g_option_context_parse (context, argc, argv, &error))
+ {
+ g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
+ error->message, *argv[0]);
+ g_error_free (error);
+ exit (1);
+ }
+ g_option_context_free (context);
+ if (gnucash_show_version)
+ {
+ const char *format_string;
+ if (is_development_version)
+ format_string = _("GnuCash %s development version");
+ else
+ format_string = _("GnuCash %s");
+
+ g_print (format_string, gnc_version());
+ g_print ("\n%s: %s\n", _("Build ID"), gnc_build_id());
+ exit(0);
+ }
+
+ gnc_prefs_set_debugging(debugging);
+ gnc_prefs_set_extra(extra);
+
+ if (gsettings_prefix)
+ gnc_gsettings_set_prefix(g_strdup(gsettings_prefix));
+
+ if (namespace_regexp)
+ gnc_prefs_set_namespace_regexp(namespace_regexp);
+
+ if (args_remaining)
+ file_to_load = args_remaining[0];
+}
+
+static void
+inner_main_add_price_quotes(void *closure, int argc, char **argv)
+{
+ SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
+ QofSession *session = NULL;
+
+ scm_c_eval_string("(debug-set! stack 200000)");
+
+ mod = scm_c_resolve_module("gnucash price-quotes");
+ scm_set_current_module(mod);
+
+ gnc_prefs_init ();
+ qof_event_suspend();
+ scm_c_eval_string("(gnc:price-quotes-install-sources)");
+
+ if (!gnc_quote_source_fq_installed())
+ {
+ g_print("%s", _("No quotes retrieved. Finance::Quote isn't "
+ "installed properly.\n"));
+ goto fail;
+ }
+
+ add_quotes = scm_c_eval_string("gnc:book-add-quotes");
+ session = gnc_get_current_session();
+ if (!session) goto fail;
+
+ qof_session_begin(session, add_quotes_file, FALSE, FALSE, FALSE);
+ if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
+
+ qof_session_load(session, NULL);
+ if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
+
+ scm_book = gnc_book_to_scm(qof_session_get_book(session));
+ scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);
+
+ qof_session_save(session, NULL);
+ if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;
+
+ qof_session_destroy(session);
+ if (!scm_is_true(scm_result))
+ {
+ g_warning("Failed to add quotes to %s.", add_quotes_file);
+ goto fail;
+ }
+
+ qof_event_resume();
+ gnc_shutdown(0);
+ return;
+fail:
+ if (session)
+ {
+ if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
+ g_warning("Session Error: %s",
+ qof_session_get_error_message(session));
+ qof_session_destroy(session);
+ }
+ qof_event_resume();
+ gnc_shutdown(1);
+}
+
+static void
+gnc_log_init()
+{
+ if (log_to_filename != NULL)
+ {
+#ifdef __MINGW64__
+ char* filename = g_utf16_to_utf8(log_to_filename, -1, NULL, NULL, NULL);
+#else
+ char* filename = log_to_filename;
+#endif
+ qof_log_init_filename_special(filename);
+ }
+ else
+ {
+ /* initialize logging to our file. */
+ gchar *tracefilename;
+ tracefilename = g_build_filename(g_get_tmp_dir(), "gnucash.trace",
+ (gchar *)NULL);
+ qof_log_init_filename(tracefilename);
+ g_free(tracefilename);
+ }
+
+ // set a reasonable default.
+ qof_log_set_default(QOF_LOG_WARNING);
+
+ gnc_log_default();
+
+ if (gnc_prefs_is_debugging_enabled())
+ {
+ qof_log_set_level("", QOF_LOG_INFO);
+ qof_log_set_level("qof", QOF_LOG_INFO);
+ qof_log_set_level("gnc", QOF_LOG_INFO);
+ }
+
+ {
+ gchar *log_config_filename;
+ log_config_filename = g_build_filename (gnc_userconfig_dir (),
+ "log.conf", (char *)NULL);
+ if (g_file_test(log_config_filename, G_FILE_TEST_EXISTS))
+ qof_log_parse_log_config(log_config_filename);
+ g_free(log_config_filename);
+ }
+
+ if (log_flags != NULL)
+ {
+ int i = 0;
+ for (; log_flags[i] != NULL; i++)
+ {
+ QofLogLevel level;
+ gchar **parts = NULL;
+
+ gchar *log_opt = log_flags[i];
+ parts = g_strsplit(log_opt, "=", 2);
+ if (parts == NULL || parts[0] == NULL || parts[1] == NULL)
+ {
+ g_warning("string [%s] not parseable", log_opt);
+ continue;
+ }
+
+ level = qof_log_level_from_string(parts[1]);
+ qof_log_set_level(parts[0], level);
+ g_strfreev(parts);
+ }
+ }
+}
+
+#ifdef __MINGW32__
+/* If one of the Unix locale variables LC_ALL, LC_MESSAGES, or LANG is
+ * set in the environment check to see if it's a valid locale and if
+ * it is set both the Windows and POSIX locales to that. If not
+ * retrieve the Windows locale and set POSIX to match.
+ */
+static void
+set_win32_thread_locale()
+{
+ WCHAR lpLocaleName[LOCALE_NAME_MAX_LENGTH];
+ char *locale = NULL;
+
+ if (((locale = getenv ("LC_ALL")) != NULL && locale[0] != '\0') ||
+ ((locale = getenv ("LC_MESSAGES")) != NULL && locale[0] != '\0') ||
+ ((locale = getenv ("LANG")) != NULL && locale[0] != '\0'))
+ {
+ gunichar2* wlocale = NULL;
+ int len = 0;
+ len = strchr(locale, '.') - locale;
+ locale[2] = '-';
+ wlocale = g_utf8_to_utf16 (locale, len, NULL, NULL, NULL);
+ if (IsValidLocaleName(wlocale))
+ {
+ LCID lcid = LocaleNameToLCID(wlocale, LOCALE_ALLOW_NEUTRAL_NAMES);
+ SetThreadLocale(lcid);
+ locale[2] = '_';
+ setlocale (LC_ALL, locale);
+ sys_locale = locale;
+ g_free(wlocale);
+ return;
+ }
+ g_free(locale);
+ g_free(wlocale);
+ }
+ if (GetUserDefaultLocaleName(lpLocaleName, LOCALE_NAME_MAX_LENGTH))
+ {
+ sys_locale = g_utf16_to_utf8((gunichar2*)lpLocaleName,
+ LOCALE_NAME_MAX_LENGTH,
+ NULL, NULL, NULL);
+ sys_locale[2] = '_';
+ setlocale (LC_ALL, sys_locale);
+ return;
+ }
+}
+#endif
+
+/* Creates a console window on MSWindows to display stdout and stderr
+ * when __MSWIN_CONSOLE__ is defined at the top of the file.
+ *
+ * Useful for displaying the diagnostics printed before logging is
+ * started and if logging is redirected with --logto=stderr.
+ */
+static void
+redirect_stdout (void)
+{
+#if defined __MINGW32__ && __MSWIN_CONSOLE__
+ static const WORD MAX_CONSOLE_LINES = 500;
+ int hConHandle;
+ long lStdHandle;
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ FILE *fp;
+
+ // allocate a console for this app
+ AllocConsole();
+
+ // set the screen buffer to be big enough to let us scroll text
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
+ coninfo.dwSize.Y = MAX_CONSOLE_LINES;
+ SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
+
+ // redirect unbuffered STDOUT to the console
+ lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
+ hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+ fp = _fdopen( hConHandle, "w" );
+ *stdout = *fp;
+ setvbuf( stdout, NULL, _IONBF, 0 );
+
+ // redirect unbuffered STDIN to the console
+ lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
+ hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+ fp = _fdopen( hConHandle, "r" );
+ *stdin = *fp;
+ setvbuf( stdin, NULL, _IONBF, 0 );
+
+ // redirect unbuffered STDERR to the console
+ lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
+ hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+ fp = _fdopen( hConHandle, "w" );
+ *stderr = *fp;
+ setvbuf( stderr, NULL, _IONBF, 0 );
+#endif
+}
+
+int
+main(int argc, char ** argv)
+{
+ gchar *localedir = gnc_path_get_localedir();
+#if !defined(G_THREADS_ENABLED) || defined(G_THREADS_IMPL_NONE)
+# error "No GLib thread implementation available!"
+#endif
+#ifdef ENABLE_BINRELOC
+ {
+ GError *binreloc_error = NULL;
+ if (!gnc_gbr_init(&binreloc_error))
+ {
+ g_print("main: Error on gnc_gbr_init: %s\n", binreloc_error->message);
+ g_error_free(binreloc_error);
+ }
+ }
+#endif
+ redirect_stdout ();
+
+ /* This should be called before gettext is initialized
+ * The user may have configured a different language via
+ * the environment file.
+ */
+#ifdef MAC_INTEGRATION
+ set_mac_locale();
+#elif defined __MINGW32__
+ set_win32_thread_locale();
+#endif
+ gnc_environment_setup();
+#if ! defined MAC_INTEGRATION && ! defined __MINGW32__/* setlocale already done */
+ sys_locale = g_strdup (setlocale (LC_ALL, ""));
+ if (!sys_locale)
+ {
+ g_print ("The locale defined in the environment isn't supported. "
+ "Falling back to the 'C' (US English) locale\n");
+ g_setenv ("LC_ALL", "C", TRUE);
+ setlocale (LC_ALL, "C");
+ }
+#endif
+ bindtextdomain(PROJECT_NAME, localedir);
+ bindtextdomain("iso_4217", localedir); // For win32 to find currency name translations
+ bind_textdomain_codeset("iso_4217", "UTF-8");
+ textdomain(PROJECT_NAME);
+ bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
+ g_free(localedir);
+
+ gnc_parse_command_line(&argc, &argv);
+ gnc_print_unstable_message();
+
+ /* Make sure gnucash' user data directory is properly set up
+ This must be done before any guile code is called as that would
+ fail the migration message */
+ userdata_migration_msg = gnc_filepath_init();
+ if (userdata_migration_msg)
+ g_print("\n\n%s\n", userdata_migration_msg);
+
+ gnc_log_init();
+ gnc_engine_init (0, NULL);
+
+ /* Write some locale details to the log to simplify debugging */
+ PINFO ("System locale returned %s", sys_locale ? sys_locale : "(null)");
+ PINFO ("Effective locale set to %s.", setlocale (LC_ALL, NULL));
+ g_free (sys_locale);
+ sys_locale = NULL;
+
+ if (add_quotes_file)
+ scm_boot_guile(argc, argv, inner_main_add_price_quotes, 0);
+
+ exit(0); /* never reached */
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9dac008dc..bd2dfb80e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,6 +210,7 @@ gnucash/gnome-utils/print-session.c
gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
+gnucash/gnucash-cli.cpp
gnucash/gnucash.cpp
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.checkprinting.gschema.xml.in
commit 736979f9326d1aedacd7b3a655addd2c775b0f0f
Author: Geert Janssens <geert at kobaltwit.be>
Date: Tue May 19 17:30:55 2020 +0200
Build gnucash main file as C++
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index e75e94f83..82ff041d1 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -32,7 +32,7 @@ else()
endif()
set (gnucash_SOURCES
- gnucash.c
+ gnucash.cpp
gnucash-gresources.c
${GNUCASH_RESOURCE_FILE}
)
@@ -259,7 +259,7 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash.c gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ gnucash.cpp gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
price-quotes.scm ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
diff --git a/gnucash/gnucash.c b/gnucash/gnucash.cpp
similarity index 96%
rename from gnucash/gnucash.c
rename to gnucash/gnucash.cpp
index 3d04bf009..8419a739c 100644
--- a/gnucash/gnucash.c
+++ b/gnucash/gnucash.cpp
@@ -1,5 +1,5 @@
/*
- * gnucash.c -- The program entry point for GnuCash
+ * gnucash.cpp -- The program entry point for GnuCash
*
* Copyright (C) 2006 Chris Shoemaker <c.shoemaker at cox.net>
*
@@ -28,49 +28,52 @@
#include <libguile.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
-#include "glib.h"
-#include "gnc-module.h"
-#include "gnc-path.h"
-#include "binreloc.h"
-#include "gnc-locale-utils.h"
-#include "gnc-version.h"
-#include "gnc-engine.h"
-#include "gnc-environment.h"
-#include "gnc-filepath-utils.h"
-#include "gnc-ui-util.h"
-#include "gnc-file.h"
-#include "gnc-hooks.h"
-#include "top-level.h"
-#include "gfec.h"
-#include "gnc-commodity.h"
-#include "gnc-prefs.h"
-#include "gnc-prefs-utils.h"
-#include "gnc-gsettings.h"
-#include "gnc-report.h"
-#include "gnc-main-window.h"
-#include "gnc-splash.h"
-#include "gnc-gnome-utils.h"
-#include "gnc-plugin-bi-import.h"
-#include "gnc-plugin-csv-export.h"
-#include "gnc-plugin-csv-import.h"
-#include "gnc-plugin-customer-import.h"
-#include "gnc-plugin-file-history.h"
-#include "gnc-plugin-log-replay.h"
-#include "gnc-plugin-qif-import.h"
-#include "gnc-plugin-report-system.h"
-#include "dialog-new-user.h"
-#include "gnc-session.h"
-#include "gnc-engine-guile.h"
-#include "gnucash-register.h"
-#include "swig-runtime.h"
-#include "guile-mappings.h"
-#include "search-core-type.h"
-#include "window-report.h"
+#include <glib.h>
+#include <binreloc.h>
+#include <gnc-locale-utils.h>
+#include <gnc-engine.h>
+#include <gnc-ui-util.h>
+#include <gnc-commodity.h>
+#include <swig-runtime.h>
+#include <guile-mappings.h>
+#include <window-report.h>
#ifdef __MINGW32__
#include <Windows.h>
#include <fcntl.h>
#endif
+extern "C" {
+#include <dialog-new-user.h>
+#include <gfec.h>
+#include <gnc-engine-guile.h>
+#include <gnc-environment.h>
+#include <gnc-file.h>
+#include <gnc-filepath-utils.h>
+#include <gnc-gnome-utils.h>
+#include <gnc-gsettings.h>
+#include <gnc-hooks.h>
+#include <gnc-main-window.h>
+#include <gnc-module.h>
+#include <gnc-path.h>
+#include <gnc-plugin-bi-import.h>
+#include <gnc-plugin-csv-export.h>
+#include <gnc-plugin-csv-import.h>
+#include <gnc-plugin-customer-import.h>
+#include <gnc-plugin-file-history.h>
+#include <gnc-plugin-log-replay.h>
+#include <gnc-plugin-qif-import.h>
+#include <gnc-plugin-report-system.h>
+#include <gnc-prefs.h>
+#include <gnc-prefs-utils.h>
+#include <gnc-report.h>
+#include <gnc-session.h>
+#include <gnc-splash.h>
+#include <gnc-version.h>
+#include <gnucash-register.h>
+#include <search-core-type.h>
+#include <top-level.h>
+}
+
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
@@ -501,7 +504,7 @@ load_gnucash_modules()
int i, len;
struct
{
- gchar * name;
+ const gchar * name;
int version;
gboolean optional;
} modules[] =
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e02e60db2..9dac008dc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,7 +210,7 @@ gnucash/gnome-utils/print-session.c
gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
-gnucash/gnucash.c
+gnucash/gnucash.cpp
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.checkprinting.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.commodities.gschema.xml.in
commit 9bf2b026ac2afe535a600d1269bf9e82dc90f61f
Author: Geert Janssens <geert at kobaltwit.be>
Date: Mon May 18 17:46:01 2020 +0200
Rename main source file from gnucash-bin.c to gnucash.c
That reflects more closely what the eventual binary will be named.
diff --git a/gnucash/CMakeLists.txt b/gnucash/CMakeLists.txt
index 9a4c423ad..e75e94f83 100644
--- a/gnucash/CMakeLists.txt
+++ b/gnucash/CMakeLists.txt
@@ -32,7 +32,7 @@ else()
endif()
set (gnucash_SOURCES
- gnucash-bin.c
+ gnucash.c
gnucash-gresources.c
${GNUCASH_RESOURCE_FILE}
)
@@ -259,7 +259,7 @@ gnc_add_scheme_targets(price-quotes
DEPENDS "scm-engine;scm-app-utils;scm-gnome-utils")
set_local_dist(gnucash_DIST_local CMakeLists.txt environment.in generate-gnc-script
- gnucash-bin.c gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
+ gnucash.c gnucash.rc.in gnucash-valgrind.in gnucash-gresources.xml ${gresource_files}
price-quotes.scm ${gnucash_EXTRA_DIST})
set (gnucash_DIST ${gnucash_DIST_local} ${gnome_DIST} ${gnome_search_DIST} ${gnome_utils_DIST}
diff --git a/gnucash/gnucash-bin.c b/gnucash/gnucash.c
similarity index 99%
rename from gnucash/gnucash-bin.c
rename to gnucash/gnucash.c
index cd5285858..3d04bf009 100644
--- a/gnucash/gnucash-bin.c
+++ b/gnucash/gnucash.c
@@ -1,5 +1,5 @@
/*
- * gnucash-bin.c -- The program entry point for GnuCash
+ * gnucash.c -- The program entry point for GnuCash
*
* Copyright (C) 2006 Chris Shoemaker <c.shoemaker at cox.net>
*
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 62acd2cc8..e02e60db2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -210,7 +210,7 @@ gnucash/gnome-utils/print-session.c
gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
-gnucash/gnucash-bin.c
+gnucash/gnucash.c
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.checkprinting.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.commodities.gschema.xml.in
Summary of changes:
CMakeLists.txt | 6 +-
gnucash/CMakeLists.txt | 54 +-
gnucash/gnome-utils/gnc-file.h | 1 +
gnucash/gnome/dialog-new-user.h | 2 +
gnucash/gnucash-bin.c | 936 ---------------------
gnucash/gnucash-cli.cpp | 124 +++
gnucash/gnucash-commands.cpp | 118 +++
.../business-urls.h => gnucash-commands.hpp} | 19 +-
gnucash/gnucash-core-app.cpp | 680 +++++++++++++++
gnucash/gnucash-core-app.hpp | 74 ++
gnucash/gnucash.cpp | 423 ++++++++++
po/POTFILES.in | 5 +-
12 files changed, 1483 insertions(+), 959 deletions(-)
delete mode 100644 gnucash/gnucash-bin.c
create mode 100644 gnucash/gnucash-cli.cpp
create mode 100644 gnucash/gnucash-commands.cpp
copy gnucash/{gnome/business-urls.h => gnucash-commands.hpp} (71%)
create mode 100644 gnucash/gnucash-core-app.cpp
create mode 100644 gnucash/gnucash-core-app.hpp
create mode 100644 gnucash/gnucash.cpp
More information about the gnucash-changes
mailing list