Merge branch 'maint'

This commit is contained in:
Geert Janssens 2021-10-01 14:51:04 +02:00
commit e64bcfe620
20 changed files with 293 additions and 134 deletions

View File

@ -668,12 +668,11 @@ install(FILES ${gnucash_DOCS} DESTINATION ${CMAKE_INSTALL_DOCDIR})
# Create config.h
if (WIN32)
if (MINGW)
set (HAVE_SCANF_LLD 1)
else ()
set (HAVE_SCANF_I64D 1)
endif()
set (HAVE_HTMLHELPW 1)
if (MINGW)
set (HAVE_SCANF_LLD 1)
else ()
set (HAVE_SCANF_I64D 1)
endif()
endif()
check_include_files (dirent.h HAVE_DIRENT_H)

8
NEWS
View File

@ -1,5 +1,13 @@
Version history:
------- -------
4.8 - 28 September 2021
The ninth release of the 4.x stable series.
This is a snap release to fix a crasher bug on Linux. The only changes are
[gsettings] Avoid crash from settings schema not being registered.
Rethink how gsettings migration file is constructed
GSettings hotfix - resolve crash due to bad schema reference
4.7 - 26 September 2021
The eighth release of the 4.x stable series.

View File

@ -117,9 +117,6 @@
/* System has gnome-keyring 0.6 or better */
#cmakedefine HAVE_GNOME_KEYRING 1
/* System has HtmlHelpW */
#cmakedefine HAVE_HTMLHELPW 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1

View File

@ -4,11 +4,11 @@
set(SCHEMADIR_BUILD ${DATADIR_BUILD}/glib-2.0/schemas)
file(MAKE_DIRECTORY ${SCHEMADIR_BUILD})
unset(gschema_depends CACHE)
unset(gschema_preftrans_files CACHE)
# The subdirectories
add_subdirectory (gnome)
add_subdirectory (gnome-utils)
add_subdirectory (gnome-search)
add_subdirectory (gschemas)
add_subdirectory (gtkbuilder)
add_subdirectory (html)
add_subdirectory (import-export)
@ -16,6 +16,9 @@ add_subdirectory (python)
add_subdirectory (register)
add_subdirectory (report)
add_subdirectory (ui)
# gschemas directory goes last to ensure all schema files are installed
# before glib-compile-schemas is called
add_subdirectory (gschemas)
add_definitions (-DHAVE_CONFIG_H)

View File

@ -789,6 +789,7 @@ gnc_stock_split_dialog (GtkWidget *parent, Account * initial)
return;
}
gtk_window_set_transient_for (GTK_WINDOW (info->window), GTK_WINDOW(parent));
gtk_widget_show_all (info->window);
gnc_window_adjust_for_screen (GTK_WINDOW(info->window));

View File

@ -4072,13 +4072,6 @@ gnc_plugin_page_register_cmd_reverse_transaction (GtkAction* action,
if (trans == NULL)
return;
if (xaccTransGetReversedBy (trans))
{
gnc_error_dialog (GTK_WINDOW (window), "%s",
_ ("A reversing entry has already been created for this transaction."));
return;
}
split = gnc_split_register_get_current_split (reg);
account = xaccSplitGetAccount (split);
@ -4088,6 +4081,17 @@ gnc_plugin_page_register_cmd_reverse_transaction (GtkAction* action,
return;
}
new_trans = xaccTransGetReversedBy (trans);
if (new_trans)
{
const char *rev = _("A reversing entry has already been created for this transaction.");
const char *jump = _("Jump to the transaction?");
if (gnc_verify_dialog (GTK_WINDOW (window), TRUE, "%s\n\n%s", rev, jump))
goto jump_to_trans;
else
return;
}
if (!gnc_dup_time64_dialog (window, _("Reverse Transaction"),
_("New Transaction Information"), &date))
{
@ -4104,6 +4108,7 @@ gnc_plugin_page_register_cmd_reverse_transaction (GtkAction* action,
gnc_resume_gui_refresh();
jump_to_trans:
/* Now jump to new trans */
gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE (page));
split = xaccTransFindSplitByAccount(new_trans, account);
@ -4558,13 +4563,15 @@ gnc_plugin_page_register_cmd_stock_split (GtkAction* action,
GncPluginPageRegister* page)
{
Account* account;
GtkWindow* window;
ENTER ("(action %p, plugin_page %p)", action, page);
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
account = gnc_plugin_page_register_get_account (page);
gnc_stock_split_dialog (NULL, account);
window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
gnc_stock_split_dialog (GTK_WIDGET (window), account);
LEAVE (" ");
}
@ -4726,6 +4733,7 @@ gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
SplitRegister* reg;
GncInvoice* invoice;
Transaction *txn;
GtkWidget *window;
ENTER ("(action %p, plugin_page %p)", action, plugin_page);
@ -4734,6 +4742,7 @@ gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
reg = gnc_ledger_display_get_split_register (priv->gsr->ledger);
txn = gnc_split_register_get_current_trans (reg);
invoice = invoice_from_split (gnc_split_register_get_current_split (reg));
window = GNC_PLUGIN_PAGE(plugin_page)->window;
if (!invoice)
{
@ -4768,7 +4777,7 @@ gnc_plugin_page_register_cmd_jump_linked_invoice (GtkAction* action,
}
details = g_list_reverse (details);
choice = gnc_choose_radio_option_dialog
(GNC_PLUGIN_PAGE (plugin_page)->window, _("Select document"),
(window, _("Select document"),
_("Several documents are linked with this transaction. \
Please choose one:"), _("Select"), 0, details);
if (choice >= 0)
@ -4779,7 +4788,10 @@ Please choose one:"), _("Select"), 0, details);
}
if (invoice)
gnc_ui_invoice_edit (NULL, invoice);
{
GtkWindow *gtk_window = gnc_window_get_gtk_window (GNC_WINDOW (window));
gnc_ui_invoice_edit (gtk_window, invoice);
}
LEAVE (" ");
}

View File

@ -22,9 +22,21 @@ set(gschema_SOURCES
add_gschema_targets("${gschema_SOURCES}")
# Provide gnucash runtime with a list of migratable preferences
configure_file(migratable-prefs.xml ${DATADIR_BUILD}/${PROJECT_NAME}/migratable-prefs.xml COPYONLY)
install(FILES ${DATADIR_BUILD}/${PROJECT_NAME}/migratable-prefs.xml
set(local_preftrans_files ${gschema_preftrans_files})
list(APPEND local_preftrans_files ${CMAKE_CURRENT_SOURCE_DIR}/pref_transformations.xml)
set(gschema_preftrans_files ${local_preftrans_files} CACHE INTERNAL "files describing transformations for our gsettings based preferences")
# Provide gnucash runtime with a list of potential transformations to user set preferences
# following GSettings schema changes between gnucash releases
add_custom_command(
OUTPUT ${DATADIR_BUILD}/${PROJECT_NAME}/pref_transformations.xml
COMMAND cat ${gschema_preftrans_files} > ${DATADIR_BUILD}/${PROJECT_NAME}/pref_transformations.xml
DEPENDS ${gschema_preftrans_files}
)
add_custom_target(pref_transformations ALL DEPENDS ${DATADIR_BUILD}/${PROJECT_NAME}/pref_transformations.xml)
install(FILES ${DATADIR_BUILD}/${PROJECT_NAME}/pref_transformations.xml
DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME})
# Handle gschemas.compiled
@ -54,7 +66,7 @@ if (COMPILE_GSCHEMAS)
${GLIB_COMPILE_SCHEMAS} --strict \$ENV\{DESTDIR\}${CMAKE_INSTALL_FULL_DATADIR}/glib-2.0/schemas\")")
endif()
set(gschemas_DIST_local migratable-prefs.xml)
set(gschemas_DIST_local pref_transformations.xml)
foreach(file ${gschema_SOURCES})
list(APPEND gschemas_DIST_local ${file}.in)
endforeach()

View File

@ -5,6 +5,12 @@
</schema>
<schema id="org.gnucash.general" path="/org/gnucash/general/">
<key name="migrate-prefs-done" type="b">
<default>false</default>
<summary>-Obsolete-</summary>
<description>This setting is obsolete and will be removed in the next major @PROJECT_NAME@ release series.</description>
</key>
<key name="prefs-version" type="i">
<default>0</default>
<summary>The version of these settings</summary>
@ -419,6 +425,26 @@ For example setting this to 2.0 will display reports at twice their typical size
<child name="options" schema="org.gnucash.dialogs.options"/>
</schema>
<schema id="org.gnucash.dialogs.business-assoc" path="/org/gnucash/dialogs/business-assoc/">
<key type="(iiii)" name="last-geometry">
<default>(-1,-1,-1,-1)</default>
<summary>Last window position and size</summary>
<description>This setting describes the size and position of the window when it was last closed.
The numbers are the X and Y coordinates of the top left corner of the window
followed by the width and height of the window.</description>
</key>
</schema>
<schema id="org.gnucash.dialogs.trans-assoc" path="/org/gnucash/dialogs/trans-assoc/">
<key type="(iiii)" name="last-geometry">
<default>(-1,-1,-1,-1)</default>
<summary>Last window position and size</summary>
<description>This setting describes the size and position of the window when it was last closed.
The numbers are the X and Y coordinates of the top left corner of the window
followed by the width and height of the window.</description>
</key>
</schema>
<schema id="org.gnucash.dialogs.account" path="/org/gnucash/dialogs/account/">
<key name="last-geometry" type="(iiii)">
<default>(-1,-1,-1,-1)</default>
@ -1668,7 +1694,7 @@ For example setting this to 2.0 will display reports at twice their typical size
<summary>Last pathname used</summary>
<description>This field contains the last pathname used by this window. It will be used as the initial filename/pathname the next time this window is opened.</description>
</key>
<child name="connection-dialog" schema="org.gnucash.GnuCash.dialogs.import.hbci.connection-dialog"/>
<child name="connection-dialog" schema="org.gnucash.dialogs.import.hbci.connection-dialog"/>
</schema>
<schema id="org.gnucash.dialogs.import.hbci.connection-dialog" path="/org/gnucash/dialogs/import/hbci/connection-dialog/">

View File

@ -230,6 +230,7 @@
<summary>Set book option on new files to use split "action" field for "Num" field on registers/reports</summary>
<description>If selected, the default book option for new files is set so that the 'Num' cell on registers shows/updates the split 'action' field and the transaction 'num' field is shown on the second line in double line mode (and is not visible in single line mode). Otherwise, the default book option for new files is set so that the 'Num' cell on registers shows/updates the transaction 'num' field.</description>
</key>
<child name="register" schema="org.gnucash.GnuCash.general.register"/>
<child name="report" schema="org.gnucash.GnuCash.general.report"/>
</schema>

View File

@ -1,3 +1,78 @@
<!-- GSettings preference transformation rules
This xml file describes rules to transform the user's GSettings based
preferences following schema changes between GnuCash versions. These
rules are evaluated and (optionally) executed at runtime in order to
dynamically make changes to the user's preferences to adapt them to the
current version of GnuCash.
An example of such a transformation is changing the name of a preference.
While the user may have set a value for the old name, without any
additional work the new name would only be set to the default. As a result
the user would experience a reset of the preference.
By adding a migration rule here, GnuCash will copy the value from the old
name to the new name at startup and hence for the user the name change
becomes transparent.
All rules are grouped within 'release' nodes. Such nodes describe the
GnuCash version in which the related schema changes first happened.
GnuCash will use this information to check at runtime whether the enclosed
rules should still be executed.
The format of a release node is as follows:
<release version="encoded_version">
...
</releaase>
encoded_version = gnucash_major * 1000 + gnucash_minor
For example for gnucash 4.7 encoded_version becomes 4 * 1000 + 7 = 4007
Within a release node the following rules are currently supported:
<deprecate ... /> : does nothing other than informing GnuCash devs this
preference will eventually be removed with no
replacement. The preference should not be used anymore
in GnuCash code directly.
It takes two arguments (old-path and old-key) that
together define the preference
<migrate ... /> : informs GnuCash a preference has moved or has been
renamed. The old preference should be treated as
deprecated and should not be used anymore in GnuCash
code directly.
It takes four arguments (old-path, old-key and
new-path, new-key). The first two define the deprecated
preference the last two the replacement preference.
<obsolete ... /> : informs GnuCash this preference is ready to be removed
in the next major release and will be unset in this
major release series. This intermediary step is to
clean up the settings database over time.
It takes two arguments (old-path and old-key) that
together define the preference
Example
=======
<release version="4007">
<deprecate old-path="org.gnucash.GnuCash.general"
old-key="prefname" />
<migrate old-path="org.gnucash.general"
old-key="prefs-version"
new-path="org.gnucash.GnuCash.general"
new-key="prefs-version" />
<obsolete old-path="org.gnucash.general"
old-key="migrate-prefs-done" />
</release>
Note
====
Do not remove this file from the GnuCash sources even if there are
currently no active rules. Instead keep this introductory comment in
place and remove all other content.
-->
<release version="4007">
@ -1297,3 +1372,16 @@
new-key="end-period"/>
</release>
<release version="4009">
<obsolete old-path="org.gnucash.dialogs.business-assoc"
old-key="last-geometry"/>
<obsolete old-path="org.gnucash.dialogs.trans-assoc"
old-key="last-geometry"/>
<obsolete old-path="org.gnucash.general"
old-key="migrate-prefs-done"/>
</release>

View File

@ -4,12 +4,13 @@ if (WITH_AQBANKING)
add_gschema_targets("${aqb_GSCHEMA}")
file(READ migratable-prefs.xml migratable-prefs)
file(APPEND ${DATADIR_BUILD}/${PROJECT_NAME}/migratable-prefs.xml ${migratable-prefs})
set(local_preftrans_files ${gschema_preftrans_files})
list(APPEND local_preftrans_files ${CMAKE_CURRENT_SOURCE_DIR}/pref_transformations.xml)
set(gschema_preftrans_files ${local_preftrans_files} CACHE INTERNAL "files describing transformations for our gsettings based preferences")
endif()
set_dist_list(aqbanking_gschema_DIST
CMakeLists.txt
migratable-prefs.xml
pref_transformations.xml
org.gnucash.GnuCash.dialogs.import.hbci.gschema.xml.in
org.gnucash.GnuCash.dialogs.flicker.gschema.xml.in)

View File

@ -4,11 +4,12 @@ if (WITH_OFX)
add_gschema_targets("${ofx_GSCHEMA}")
file(READ migratable-prefs.xml migratable-prefs)
file(APPEND ${DATADIR_BUILD}/${PROJECT_NAME}/migratable-prefs.xml ${migratable-prefs})
set(local_preftrans_files ${gschema_preftrans_files})
list(APPEND local_preftrans_files ${CMAKE_CURRENT_SOURCE_DIR}/pref_transformations.xml)
set(gschema_preftrans_files ${local_preftrans_files} CACHE INTERNAL "files describing transformations for our gsettings based preferences")
endif()
set_dist_list(ofx_gschema_DIST
CMakeLists.txt
migratable-prefs.xml
pref_transformations.xml
org.gnucash.GnuCash.dialogs.import.ofx.gschema.xml.in)

View File

@ -101,9 +101,13 @@ static GSettings * gnc_gsettings_get_settings_ptr (const gchar *schema_str)
gset = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
DEBUG ("Looking for schema %s returned gsettings %p", full_name, gset);
if (!gset)
{
gset = g_settings_new (full_name);
auto schema_source {g_settings_schema_source_get_default()};
auto schema {g_settings_schema_source_lookup(schema_source, full_name,
FALSE)};
gset = g_settings_new_full (schema, nullptr, nullptr);
DEBUG ("Created gsettings object %p for schema %s", gset, full_name);
if (G_IS_SETTINGS(gset))
g_hash_table_insert (schema_hash, full_name, gset);
@ -114,7 +118,6 @@ static GSettings * gnc_gsettings_get_settings_ptr (const gchar *schema_str)
{
g_free(full_name);
}
LEAVE("");
return gset;
}
@ -652,19 +655,55 @@ gnc_gsettings_get_user_value (const gchar *schema,
}
}
using opt_str_vec = boost::optional<std::string>;
static void
migrate_one_key (const std::string &oldpath, const std::string &oldkey,
const std::string &newpath, const std::string &newkey)
deprecate_one_key (const opt_str_vec &oldpath, const opt_str_vec &oldkey)
{
PINFO ("Migrating '%s:%s' to '%s:%s'", oldpath.c_str(), oldkey.c_str(),
newpath.c_str(), newkey.c_str());
auto user_value = gnc_gsettings_get_user_value (oldpath.data(), oldkey.data());
if (user_value)
gnc_gsettings_set_value (newpath.data(), newkey.data(), user_value);
if (!oldpath || !oldkey )
{
DEBUG ("Skipping <deprecate> node - missing attribute (old-path or old-key)");
return;
}
PINFO ("'%s:%s' has been marked deprecated", oldpath->c_str(), oldkey->c_str());
/* This does nothing really, but is a reminder for future maintainers
* to mark this pref as obsolete in the next major release. */
}
static void
migrate_one_node (bpt::ptree &pt)
migrate_one_key (const opt_str_vec &oldpath, const opt_str_vec &oldkey,
const opt_str_vec &newpath, const opt_str_vec &newkey)
{
if (!oldpath || !oldkey || !newpath || !newkey)
{
DEBUG ("Skipping <migrate> node - missing attribute (old-path, old-key, new-path or new-key)");
return;
}
PINFO ("Migrating '%s:%s' to '%s:%s'", oldpath->c_str(), oldkey->c_str(),
newpath->c_str(), newkey->c_str());
auto user_value = gnc_gsettings_get_user_value (oldpath->c_str(), oldkey->c_str());
if (user_value)
gnc_gsettings_set_value (newpath->c_str(), newkey->c_str(), user_value);
}
static void
obsolete_one_key (const opt_str_vec &oldpath, const opt_str_vec &oldkey)
{
if (!oldpath || !oldkey )
{
DEBUG ("Skipping <obsolete> node - missing attribute (old-path or old-key)");
return;
}
PINFO ("Resetting obsolete '%s:%s'", oldpath->c_str(), oldkey->c_str());
gnc_gsettings_reset (oldpath->c_str(), oldkey->c_str());
}
static void
parse_one_release_node (bpt::ptree &pt)
{
/* loop over top-level property tree */
std::for_each (pt.begin(), pt.end(),
@ -672,53 +711,53 @@ migrate_one_node (bpt::ptree &pt)
{
if (node.first == "<xmlattr>")
return;
if (node.first != "migrate")
else if (node.first == "deprecate")
deprecate_one_key (node.second.get_optional<std::string> ("<xmlattr>.old-path"),
node.second.get_optional<std::string> ("<xmlattr>.old-key"));
else if (node.first == "migrate")
migrate_one_key (node.second.get_optional<std::string> ("<xmlattr>.old-path"),
node.second.get_optional<std::string> ("<xmlattr>.old-key"),
node.second.get_optional<std::string> ("<xmlattr>.new-path"),
node.second.get_optional<std::string> ("<xmlattr>.new-key"));
else if (node.first == "obsolete")
obsolete_one_key (node.second.get_optional<std::string> ("<xmlattr>.old-path"),
node.second.get_optional<std::string> ("<xmlattr>.old-key"));
else
{
DEBUG ("Skipping non-<migrate> node <%s>", node.first.c_str());
DEBUG ("Skipping unknown node <%s>", node.first.c_str());
return;
}
auto oldpath = node.second.get_optional<std::string> ("<xmlattr>.old-path");
auto oldkey = node.second.get_optional<std::string> ("<xmlattr>.old-key");
auto newpath = node.second.get_optional<std::string> ("<xmlattr>.new-path");
auto newkey = node.second.get_optional<std::string> ("<xmlattr>.new-key");
if (!oldpath || !oldkey || !newpath || !newkey)
{
DEBUG ("Skipping migration node - missing attribute (old-path, old-key, new-path or new-key)");
return;
}
migrate_one_key (*oldpath, *oldkey, *newpath, *newkey);
});
}
static void
migrate_settings (int old_maj_min)
transform_settings (int old_maj_min)
{
bpt::ptree pt;
auto pkg_data_dir = gnc_path_get_pkgdatadir();
auto migrate_file = std::string (pkg_data_dir) + "/migratable-prefs.xml";
auto transform_file = std::string (pkg_data_dir) + "/pref_transformations.xml";
g_free (pkg_data_dir);
std::ifstream migrate_stream {migrate_file};
if (!migrate_stream.is_open())
std::ifstream transform_stream {transform_file};
if (!transform_stream.is_open())
{
PWARN("Failed to load settings migration file '%s'", migrate_file.c_str());
PWARN("Failed to load preferences transformation file '%s'", transform_file.c_str());
return;
}
try
{
bpt::read_xml (migrate_stream, pt);
bpt::read_xml (transform_stream, pt);
}
catch (bpt::xml_parser_error &e) {
PWARN ("Failed to parse GnuCash settings migration file.\n");
PWARN ("Failed to parse GnuCash preferences transformation file.\n");
PWARN ("Error message:\n");
PWARN ("%s\n", e.what());
return;
}
catch (...) {
PWARN ("Unknown error while parsing GnuCash settings migration file.\n");
PWARN ("Unknown error while parsing GnuCash preferences transformation file.\n");
return;
}
@ -744,27 +783,36 @@ migrate_settings (int old_maj_min)
}
DEBUG ("Retrieved version value '%i'", *version);
migrate_one_node (node.second);
parse_one_release_node (node.second);
});
}
void gnc_gsettings_version_upgrade (void)
{
/* Use versioning to ensure this routine will only sync once for each
* superseded setting
* At first run of GnuCash 4.7 or more recent *all* settings will be migrated
* from prefix org.gnucash to org.gnucash.GnuCash, including our GNC_PREF_VERSION setting.
* As the logic to determine whether or not to upgrade depends on it we have to do
* some extra tests to figure when exactly to start doing migrations.
* - if GNC_PREF_VERSION is not set under old nor new prefix, that means
* gnucash has never run before on this system = no migration necessary
* - if GNC_PREF_VERSION is set under old prefix, but not new prefix
* => full migration from old to new prefix should still be run
/* This routine will conditionally execute conversion rules from
* prefs_transformations.xml to adapt the user's existing preferences to
* the current preferences schema. The rules in this file are versioned and
* only rules still relevant to the user's existing preferences and for
* this version of GnuCash will be executed.
*
* Starting with GnuCash 4.7 the code expects all preferences to be stored
* under prefix org.gnucash instead of org.gnucash.GnuCash, including our
* GNC_PREF_VERSION setting.
* As the logic to determine whether or not settings conversions are needed
* depends on this preference, we have to test for its value in two
* locations:
* - if GNC_PREF_VERSION is not set under old nor new prefix
* => GnuCash has never run before so no conversion run necessary
* - if GNC_PREF_VERSION is set under old prefix and not new prefix
* => user's preferences weren't moved yet from old to new prefix. Use old
* prefix GNC_PREF_VERSION to determine which conversions may be needed
* - if GNC_PREF_VERSION is set under both prefixes
* => ignore old prefix and use new prefix result to determine which
* migrations would still be needed.
* => ignore old prefix and use new prefix GNC_PREF_VERSION to determine
* which conversions may be needed.
* Sometime in the future (GnuCash 6.0) the old prefix will be fully removed
* and the test will be simplified to only check in the new prefix.
*/
ENTER("Start of settings migration routine.");
ENTER("Start of settings transform routine.");
auto ogG_maj_min = gnc_gsettings_get_user_value (GNC_PREFS_GROUP_GENERAL, GNC_PREF_VERSION);
auto og_maj_min = gnc_gsettings_get_user_value (GSET_SCHEMA_OLD_PREFIX "." GNC_PREFS_GROUP_GENERAL, GNC_PREF_VERSION);
@ -787,7 +835,7 @@ void gnc_gsettings_version_upgrade (void)
PINFO ("Previous setting compatibility level: %i", old_maj_min);
migrate_settings (old_maj_min);
transform_settings (old_maj_min);
/* Only write current version if it's more recent than what was set */
auto cur_maj_min = PROJECT_VERSION_MAJOR * 1000 + PROJECT_VERSION_MINOR;

View File

@ -24,15 +24,11 @@
#include <config.h>
#include <glib.h>
#ifdef HAVE_HTMLHELPW
# include <windows.h>
# include <htmlhelp.h>
#endif
#include <windows.h>
#include <htmlhelp.h>
#include "gnc-help-utils.h"
#ifdef HAVE_HTMLHELPW
static GHashTable *
parse_hhmap_file(const gchar *chmfile)
{
@ -137,24 +133,3 @@ gnc_show_htmlhelp(const gchar *chmfile, const gchar *anchor)
HtmlHelpW(GetDesktopWindow(), wpath, HH_HELP_CONTEXT, id);
g_free(wpath);
}
#else /* !HAVE_HTMLHELPW */
void
gnc_show_htmlhelp(const gchar *chmfile, const gchar *anchor)
{
gchar *argv[3];
g_return_if_fail(chmfile);
argv[0] = "hh";
argv[1] = g_strdup(chmfile);
argv[2] = NULL;
if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, NULL))
if (g_file_test(chmfile, G_FILE_TEST_IS_REGULAR))
g_warning("Found CHM help file, but could not spawn hh to open it");
g_free(argv[1]);
}
#endif /* HAVE_HTMLHELPW */

View File

@ -274,8 +274,7 @@ gnc_transaction_init(Transaction* trans)
trans->date_posted = 0;
trans->marker = 0;
trans->orig = NULL;
trans->readonly_reason = NULL;
trans->reason_cache_valid = FALSE;
trans->readonly_reason = (char*) is_unset;
trans->isClosingTxn_cached = -1;
trans->notes = (char*) is_unset;
trans->doclink = (char*) is_unset;
@ -818,7 +817,8 @@ xaccFreeTransaction (Transaction *trans)
/* free up transaction strings */
CACHE_REMOVE(trans->num);
CACHE_REMOVE(trans->description);
g_free (trans->readonly_reason);
if (trans->readonly_reason != is_unset)
g_free (trans->readonly_reason);
if (trans->doclink != is_unset)
g_free (trans->doclink);
if (trans->void_reason != is_unset)
@ -832,7 +832,6 @@ xaccFreeTransaction (Transaction *trans)
trans->date_entered = 0;
trans->date_posted = 0;
trans->readonly_reason = NULL;
trans->reason_cache_valid = FALSE;
trans->doclink = NULL;
trans->notes = NULL;
trans->void_reason = NULL;
@ -2130,9 +2129,9 @@ void xaccTransClearReadOnly (Transaction *trans)
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
g_free (trans->readonly_reason);
if (trans->readonly_reason != is_unset)
g_free (trans->readonly_reason);
trans->readonly_reason = NULL;
trans->reason_cache_valid = TRUE;
}
}
@ -2150,9 +2149,9 @@ xaccTransSetReadOnly (Transaction *trans, const char *reason)
g_value_unset (&v);
xaccTransCommitEdit(trans);
g_free (trans->readonly_reason);
if (trans->readonly_reason != is_unset)
g_free (trans->readonly_reason);
trans->readonly_reason = g_strdup (reason);
trans->reason_cache_valid = TRUE;
}
}
@ -2570,22 +2569,13 @@ xaccTransGetReadOnly (Transaction *trans)
if (!trans)
return NULL;
if (!trans->reason_cache_valid)
if (trans->readonly_reason == is_unset)
{
GValue v = G_VALUE_INIT;
qof_instance_get_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_READ_ONLY_REASON);
/* Clear possible old cache value first */
g_free (trans->readonly_reason);
trans->readonly_reason = NULL;
/* Then set the new one */
if (G_VALUE_HOLDS_STRING (&v))
{
trans->readonly_reason = g_value_dup_string (&v);
g_value_unset (&v);
}
trans->reason_cache_valid = TRUE;
trans->readonly_reason = G_VALUE_HOLDS_STRING (&v) ?
g_value_dup_string (&v) : NULL;
g_value_unset (&v);
}
return trans->readonly_reason;
}

View File

@ -114,11 +114,9 @@ struct transaction_s
/* The readonly_reason is a string that indicates why a transaction
* is marked as read-only. If NULL, the transaction is read-write.
* This value is stored in kvp, but we cache a copy here for
* performance reasons. reason_cache_valid indicates whether the
* cached value is valid.
* performance reasons.
*/
char * readonly_reason;
gboolean reason_cache_valid;
char * doclink;
char * void_reason;

View File

@ -33,7 +33,6 @@ public:
marker = 0;
orig = nullptr;
readonly_reason = nullptr;
reason_cache_valid = FALSE;
isClosingTxn_cached = -1;
}
void* operator new(size_t size)

View File

@ -23,8 +23,8 @@ msgstr ""
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-09-20 22:29+0200\n"
"PO-Revision-Date: 2021-09-21 03:37+0000\n"
"Last-Translator: Eric <spice2wolf@gmail.com>\n"
"PO-Revision-Date: 2021-09-28 05:36+0000\n"
"Last-Translator: TianXing_Yi <ytx.cash@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"gnucash/gnucash/zh_Hans/>\n"
"Language: zh_CN\n"
@ -17231,13 +17231,13 @@ msgstr "提前提醒(_E)"
#: gnucash/gtkbuilder/dialog-sx.glade:724
msgid "Re_view created transactions"
msgstr "复核创建的交易(_v)"
msgstr "复核创建的交易(_V)"
#: gnucash/gtkbuilder/dialog-sx.glade:728
msgid ""
"Set 'Review created transactions' as the default in the \"since last run\" "
"dialog."
msgstr "在“自上次运行以来”对话框中将“审核已创建的交易”设置为默认值。"
msgstr "“待执行”对话框中,默认选择“复核创建的交易”。"
#: gnucash/gtkbuilder/dialog-sx.glade:765
msgid "Edit Scheduled Transaction"
@ -21390,7 +21390,7 @@ msgstr "小计"
#: gnucash/report/reports/standard/owner-report.scm:56
#: libgnucash/app-utils/business-options.scm:78
msgid "Tax"
msgstr "税"
msgstr "税"
#: gnucash/register/ledger-core/gncEntryLedgerModel.c:127
msgid "Billable?"