Merge branch 'maint'

This commit is contained in:
Christopher Lam 2021-09-12 22:44:34 +08:00
commit 017ab06939
31 changed files with 269 additions and 262 deletions

View File

@ -1116,6 +1116,7 @@ gnc_scm2query_and_terms (SCM and_terms, query_version_t vers)
if (q_and) if (q_and)
{ {
q_new = qof_query_merge (q, q_and, QOF_QUERY_AND); q_new = qof_query_merge (q, q_and, QOF_QUERY_AND);
qof_query_destroy (q_and);
if (q_new) if (q_new)
{ {
@ -1158,6 +1159,7 @@ gnc_scm2query_or_terms (SCM or_terms, query_version_t vers)
if (q_or) if (q_or)
{ {
q_new = qof_query_merge (q, q_or, QOF_QUERY_OR); q_new = qof_query_merge (q, q_or, QOF_QUERY_OR);
qof_query_destroy (q_or);
if (q_new) if (q_new)
{ {

View File

@ -2,6 +2,7 @@ from unittest import main
from gnucash import Transaction, Book, Account, Split from gnucash import Transaction, Book, Account, Split
from unittest_support import * from unittest_support import *
from datetime import datetime, timezone
from test_book import BookSession from test_book import BookSession
@ -138,5 +139,12 @@ class TestTransaction(TransactionSession):
self.trans.SetNotes(NOTE) self.trans.SetNotes(NOTE)
self.assertEqual( NOTE, self.trans.GetNotes() ) self.assertEqual( NOTE, self.trans.GetNotes() )
def test_date(self):
ZERODATE=datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
DATE=datetime(2020, 2, 20, 10, 59, 0, tzinfo=timezone.utc)
self.assertEqual(ZERODATE, self.trans.GetDate().astimezone(timezone.utc))
self.trans.SetDate(DATE.day, DATE.month, DATE.year)
self.assertEqual(DATE, self.trans.GetDate().astimezone(timezone.utc))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -372,6 +372,7 @@ sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
gpointer user_data) gpointer user_data)
{ {
const Account *account_a, *account_b; const Account *account_a, *account_b;
const gnc_commodity *cur = gnc_default_currency();
gnc_numeric balance_a, balance_b; gnc_numeric balance_a, balance_b;
gint result; gint result;
@ -379,8 +380,8 @@ sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b); sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b);
/* Get balances */ /* Get balances */
balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, NULL); balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, cur);
balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, NULL); balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, cur);
result = gnc_numeric_compare(balance_a, balance_b); result = gnc_numeric_compare(balance_a, balance_b);
if (result != 0) if (result != 0)

View File

@ -930,6 +930,8 @@ gnc_customer_search (GtkWindow *parent, GncCustomer *start, QofBook *book)
/* Build the column list in reverse order */ /* Build the column list in reverse order */
if (columns == NULL) if (columns == NULL)
{ {
columns = gnc_search_param_prepend (columns, _("Shipping Contact"), NULL, type,
CUSTOMER_SHIPADDR, ADDRESS_NAME, NULL);
columns = gnc_search_param_prepend (columns, _("Contact"), NULL, type, columns = gnc_search_param_prepend (columns, _("Contact"), NULL, type,
CUSTOMER_ADDR, ADDRESS_NAME, NULL); CUSTOMER_ADDR, ADDRESS_NAME, NULL);
columns = gnc_search_param_prepend (columns, _("Company"), NULL, type, columns = gnc_search_param_prepend (columns, _("Company"), NULL, type,

View File

@ -136,10 +136,10 @@ gnc_report_system_file_stream_cb (const char *location, char ** data, int *len)
static gboolean static gboolean
gnc_report_system_report_stream_cb (const char *location, char ** data, int *len) gnc_report_system_report_stream_cb (const char *location, char ** data, int *len)
{ {
gboolean ok; gchar *captured_str = NULL;
gchar *captured_str; gboolean ok =
gnc_run_report_id_string_with_error_handling (location, data,
ok = gnc_run_report_id_string_with_error_handling (location, data, &captured_str); &captured_str);
if (!ok) if (!ok)
{ {

View File

@ -2120,6 +2120,9 @@ recn_destroy_cb (GtkWidget *w, gpointer data)
if (recnData->delete_refresh) if (recnData->delete_refresh)
gnc_resume_gui_refresh (); gnc_resume_gui_refresh ();
//Disable the actions, the handlers try to access recnData
gtk_action_group_set_sensitive(recnData->action_group, FALSE);
g_free (recnData); g_free (recnData);
} }

View File

@ -30,6 +30,7 @@
#endif #endif
#include "gnucash-commands.hpp" #include "gnucash-commands.hpp"
#include "gnucash-core-app.hpp"
extern "C" { extern "C" {
#include <gnc-engine-guile.h> #include <gnc-engine-guile.h>
@ -173,8 +174,7 @@ scm_run_report (void *data,
scm_c_use_module ("gnucash reports"); scm_c_use_module ("gnucash reports");
gnc_report_init (); gnc_report_init ();
// load_system_config(); Gnucash::gnc_load_scm_config();
// load_user_config();
gnc_prefs_init (); gnc_prefs_init ();
qof_event_suspend (); qof_event_suspend ();
@ -303,6 +303,7 @@ scm_report_show (void *data,
scm_c_use_module ("gnucash app-utils"); scm_c_use_module ("gnucash app-utils");
scm_c_use_module ("gnucash reports"); scm_c_use_module ("gnucash reports");
gnc_report_init (); gnc_report_init ();
Gnucash::gnc_load_scm_config();
if (!args->file_to_load.empty()) if (!args->file_to_load.empty())
{ {
@ -334,6 +335,7 @@ scm_report_list ([[maybe_unused]] void *data,
scm_c_use_module ("gnucash app-utils"); scm_c_use_module ("gnucash app-utils");
scm_c_use_module ("gnucash reports"); scm_c_use_module ("gnucash reports");
gnc_report_init (); gnc_report_init ();
Gnucash::gnc_load_scm_config();
scm_call_1 (scm_c_eval_string ("gnc:cmdline-report-list"), scm_call_1 (scm_c_eval_string ("gnc:cmdline-report-list"),
scm_current_output_port ()); scm_current_output_port ());

View File

@ -40,5 +40,9 @@ namespace Gnucash {
int report_list (void); int report_list (void);
int report_show (const bo_str& file_to_load, int report_show (const bo_str& file_to_load,
const bo_str& run_report); const bo_str& run_report);
// A helper function to load scm config files (SYSCONFIGDIR/config
// and USERCONFIGDIR/config-user.scm) on demand
void gnc_load_scm_config(void);
} }
#endif #endif

View File

@ -86,25 +86,6 @@ gnc_print_unstable_message(void)
<< bl::format (bl::translate ("To find the last stable version, please refer to {1}")) % PACKAGE_URL << "\n"; << bl::format (bl::translate ("To find the last stable version, please refer to {1}")) % PACKAGE_URL << "\n";
} }
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 static void
update_message(const gchar *msg) update_message(const gchar *msg)
{ {
@ -112,52 +93,30 @@ update_message(const gchar *msg)
g_message("%s", msg); g_message("%s", msg);
} }
static void void
load_system_config(void) Gnucash::gnc_load_scm_config (void)
{ {
static int is_system_config_loaded = FALSE; static auto is_system_config_loaded = false;
gchar *system_config_dir; if (!is_system_config_loaded)
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", nullptr);
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 auto msg = bl::translate ("Loading system scm configuration...").str (gnc_get_boost_locale());
}; update_message (msg.c_str());
static const gchar *stylesheet_files[] = { "stylesheets-2.0", NULL}; auto system_config_dir = gnc_path_get_pkgsysconfdir ();
static int is_user_config_loaded = FALSE; auto system_config = g_build_filename (system_config_dir, "config", nullptr);
is_system_config_loaded = gfec_try_load (system_config);
if (is_user_config_loaded) g_free (system_config_dir);
return; g_free (system_config);
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"); static auto is_user_config_loaded = false;
try_load_config_array(saved_report_files); if (!is_user_config_loaded)
update_message("loading stylesheets"); {
try_load_config_array(stylesheet_files); auto msg = bl::translate ("Loading user scm configuration...").str (gnc_get_boost_locale());
update_message (msg.c_str());
auto config_filename = g_build_filename (gnc_userconfig_dir (), "config-user.scm", nullptr);
is_user_config_loaded = gfec_try_load (config_filename);
g_free (config_filename);
}
} }
static void static void

View File

@ -70,5 +70,6 @@ private:
char *sys_locale = nullptr; char *sys_locale = nullptr;
}; };
void gnc_load_scm_config(void);
} }
#endif #endif

View File

@ -73,56 +73,6 @@ namespace bl = boost::locale;
static QofLogModule log_module = GNC_MOD_GUI; static QofLogModule log_module = GNC_MOD_GUI;
static gchar *userdata_migration_msg = NULL; static gchar *userdata_migration_msg = NULL;
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", nullptr);
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);
}
}
static void static void
load_gnucash_plugins() load_gnucash_plugins()
{ {
@ -207,11 +157,10 @@ scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **
load_gnucash_plugins(); load_gnucash_plugins();
load_gnucash_modules(); load_gnucash_modules();
/* Load the config before starting up the gui. This insures that /* Load the scm config files before starting up the gui. This ensures that
* custom reports have been read into memory before the Reports * custom reports have been read into memory before the Reports
* menu is created. */ * menu is created. */
load_system_config(); Gnucash::gnc_load_scm_config();
load_user_config();
/* Setting-up the report menu must come after the module /* Setting-up the report menu must come after the module
loading but before the gui initializat*ion. */ loading but before the gui initializat*ion. */

View File

@ -721,11 +721,11 @@
</child> </child>
<child> <child>
<object class="GtkCheckButton" id="pref/dialogs.sxs.since-last-run/review-transactions"> <object class="GtkCheckButton" id="pref/dialogs.sxs.since-last-run/review-transactions">
<property name="label" translatable="yes">Set 'Re_view Created Transactions' as default</property> <property name="label" translatable="yes">Re_view created transactions</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Set 'Review Created Transactions' as the default in the 'Since Last Run' dialog.</property> <property name="tooltip_text" translatable="yes">Set 'Review created transactions' as the default in the "since last run" dialog.</property>
<property name="halign">start</property> <property name="halign">start</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>

View File

@ -1048,6 +1048,93 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
return FALSE; return FALSE;
} }
/********************************************************************\
* check_trans_online_id() Callback function used by
* gnc_import_exists_online_id. Takes pointers to transaction and split,
* returns 0 if their online_ids do NOT match, or if the split
* belongs to the transaction
\********************************************************************/
static gint check_trans_online_id(Transaction *trans1, void *user_data)
{
Account *account;
Split *split1;
Split *split2 = user_data;
const gchar *online_id1;
const gchar *online_id2;
account = xaccSplitGetAccount(split2);
split1 = xaccTransFindSplitByAccount(trans1, account);
if (split1 == split2)
return 0;
/* hack - we really want to iterate over the _splits_ of the account
instead of the transactions */
g_assert(split1 != NULL);
if (gnc_import_split_has_online_id(split1))
online_id1 = gnc_import_get_split_online_id(split1);
else
online_id1 = gnc_import_get_trans_online_id(trans1);
online_id2 = gnc_import_get_split_online_id(split2);
if ((online_id1 == NULL) ||
(online_id2 == NULL) ||
(strcmp(online_id1, online_id2) != 0))
{
return 0;
}
else
{
/*printf("test_trans_online_id(): Duplicate found\n");*/
return 1;
}
}
/** Checks whether the given transaction's online_id already exists in
its parent account. */
gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_hash)
{
gboolean online_id_exists = FALSE;
Account *dest_acct;
Split *source_split;
/* Look for an online_id in the first split */
source_split = xaccTransGetSplit(trans, 0);
g_assert(source_split);
// No online id, no point in continuing. We'd crash if we tried.
if (!gnc_import_get_split_online_id (source_split))
return FALSE;
// Create a hash per account of a hash of all split IDs. Then the test below will be fast if
// we have many transactions to import.
dest_acct = xaccSplitGetAccount (source_split);
if (!g_hash_table_contains (acct_id_hash, dest_acct))
{
GHashTable* new_hash = g_hash_table_new (g_str_hash, g_str_equal);
GList* split_list = xaccAccountGetSplitList(dest_acct);
g_hash_table_insert (acct_id_hash, dest_acct, new_hash);
for (;split_list;split_list=split_list->next)
{
if (gnc_import_split_has_online_id (split_list->data))
g_hash_table_add (new_hash, (void*) gnc_import_get_split_online_id (split_list->data));
}
}
online_id_exists = g_hash_table_contains (g_hash_table_lookup (acct_id_hash, dest_acct),
gnc_import_get_split_online_id (source_split));
/* If it does, abort the process for this transaction, since it is
already in the system. */
if (online_id_exists == TRUE)
{
DEBUG("%s", "Transaction with same online ID exists, destroying current transaction");
xaccTransDestroy(trans);
xaccTransCommitEdit(trans);
}
return online_id_exists;
}
/* ****************************************************************** /* ******************************************************************
*/ */

View File

@ -57,6 +57,15 @@ typedef enum _action
/** @name Non-GUI Functions */ /** @name Non-GUI Functions */
/*@{*/ /*@{*/
/** Checks whether the given transaction's online_id already exists in
* its parent account. The given transaction has to be open for
* editing. If a matching online_id exists, the transaction is
* destroyed (!) and TRUE is returned, otherwise FALSE is returned.
*
* @param trans The transaction for which to check for an existing
* online_id. */
gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_hash);
/** Evaluates the match between trans_info and split using the provided parameters. /** Evaluates the match between trans_info and split using the provided parameters.
* *
* @param trans_info The TransInfo for the imported transaction * @param trans_info The TransInfo for the imported transaction

View File

@ -76,6 +76,7 @@ struct _main_matcher_info
gboolean add_toggled; // flag to indicate that add has been toggled to stop selection gboolean add_toggled; // flag to indicate that add has been toggled to stop selection
gint id; gint id;
GSList* temp_trans_list; // Temporary list of imported transactions GSList* temp_trans_list; // Temporary list of imported transactions
GHashTable* acct_id_hash; // Hash table, per account, of list of transaction IDs.
GSList* edited_accounts; // List of accounts currently edited. GSList* edited_accounts; // List of accounts currently edited.
}; };
@ -143,6 +144,14 @@ static gboolean query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
gpointer user_data); gpointer user_data);
/* end local prototypes */ /* end local prototypes */
static
gboolean delete_hash (gpointer key, gpointer value, gpointer user_data)
{
// Value is a hash table that needs to be destroyed.
g_hash_table_destroy (value);
return TRUE;
}
static void static void
update_all_balances (GNCImportMainMatcher *info) update_all_balances (GNCImportMainMatcher *info)
{ {
@ -209,6 +218,8 @@ gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
// We've deferred balance computations on many accounts. Let's do it now that we're done. // We've deferred balance computations on many accounts. Let's do it now that we're done.
update_all_balances (info); update_all_balances (info);
g_hash_table_foreach_remove (info->acct_id_hash, delete_hash, NULL);
info->acct_id_hash = NULL;
g_free (info); g_free (info);
} }
@ -1133,6 +1144,8 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info,
G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info); G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
g_signal_connect (view, "popup-menu", g_signal_connect (view, "popup-menu",
G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info); G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
info->acct_id_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
} }
static void static void
@ -1713,11 +1726,16 @@ gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transaction
g_assert (gui); g_assert (gui);
g_assert (trans); g_assert (trans);
transaction_info = gnc_import_TransInfo_new (trans, NULL); if (gnc_import_exists_online_id (trans, gui->acct_id_hash))
gnc_import_TransInfo_set_ref_id (transaction_info, ref_id); return;
// It's much faster to gather the imported transactions into a GSList than directly into the else
// treeview. {
gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info); transaction_info = gnc_import_TransInfo_new (trans, NULL);
gnc_import_TransInfo_set_ref_id (transaction_info, ref_id);
// It's much faster to gather the imported transactions into a GSList than directly into the
// treeview.
gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info);
}
return; return;
} }
@ -1781,6 +1799,8 @@ create_hash_of_potential_matches (GList *candidate_txns,
{ {
Account* split_account; Account* split_account;
GSList* split_list; GSList* split_list;
if (gnc_import_split_has_online_id (candidate->data))
continue;
split_account = xaccSplitGetAccount (candidate->data); split_account = xaccSplitGetAccount (candidate->data);
/* g_hash_table_steal_extended would do the two calls in one shot but is /* g_hash_table_steal_extended would do the two calls in one shot but is
* not available until GLib 2.58. * not available until GLib 2.58.

View File

@ -57,6 +57,29 @@ void gnc_import_set_acc_online_id (Account *account, const gchar *id)
xaccAccountCommitEdit (account); xaccAccountCommitEdit (account);
} }
const gchar * gnc_import_get_trans_online_id (Transaction * transaction)
{
gchar *id = NULL;
qof_instance_get (QOF_INSTANCE (transaction), "online-id", &id, NULL);
return id;
}
/* Not actually used */
void gnc_import_set_trans_online_id (Transaction *transaction,
const gchar *id)
{
g_return_if_fail (transaction != NULL);
xaccTransBeginEdit (transaction);
qof_instance_set (QOF_INSTANCE (transaction), "online-id", id, NULL);
xaccTransCommitEdit (transaction);
}
gboolean gnc_import_trans_has_online_id(Transaction * transaction)
{
const gchar * online_id;
online_id = gnc_import_get_trans_online_id(transaction);
return (online_id != NULL && strlen(online_id) > 0);
}
const gchar * gnc_import_get_split_online_id (Split * split) const gchar * gnc_import_get_split_online_id (Split * split)
{ {
gchar *id = NULL; gchar *id = NULL;

View File

@ -49,6 +49,17 @@ const gchar * gnc_import_get_acc_online_id(Account * account);
void gnc_import_set_acc_online_id(Account * account, void gnc_import_set_acc_online_id(Account * account,
const gchar * string_value); const gchar * string_value);
/** @} */ /** @} */
/** @name Setter-getters
Setter and getter functions for the online_id field for
Transactions.
@{
*/
const gchar * gnc_import_get_trans_online_id(Transaction * transaction);
void gnc_import_set_trans_online_id(Transaction * transaction,
const gchar * string_value);
/** @} */
gboolean gnc_import_trans_has_online_id(Transaction * transaction);
/** @name Setter-getters /** @name Setter-getters
Setter and getter functions for the online_id field for Setter and getter functions for the online_id field for

View File

@ -94,15 +94,6 @@
(lambda () (cons 'absolute (current-time))) (lambda () (cons 'absolute (current-time)))
#f 'absolute #f )) #f 'absolute #f ))
;; This is another date option, but the user can also select
;; the time.
(add-option
(gnc:make-date-option
(N_ "Hello, World!") (N_ "Time and Date Option")
"e" (N_ "This is a date option with time.")
(lambda () (cons 'absolute (current-time)))
#t 'absolute #f ))
(add-option (add-option
(gnc:make-date-option (gnc:make-date-option
(N_ "Hello, World!") (N_ "Combo Date Option") (N_ "Hello, World!") (N_ "Combo Date Option")
@ -234,8 +225,6 @@ option like this.")
(string-val (op-value "Hello, World!" "String Option")) (string-val (op-value "Hello, World!" "String Option"))
(date-val (gnc:date-option-absolute-time (date-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Just a Date Option"))) (op-value "Hello, World!" "Just a Date Option")))
(date2-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Time and Date Option")))
(rel-date-val (gnc:date-option-absolute-time (rel-date-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Relative Date Option"))) (op-value "Hello, World!" "Relative Date Option")))
(combo-date-val (gnc:date-option-absolute-time (combo-date-val (gnc:date-option-absolute-time
@ -258,7 +247,6 @@ option like this.")
;; qof-print-date ;; qof-print-date
(let ((time-string (gnc-print-time64 (current-time) "%X")) (let ((time-string (gnc-print-time64 (current-time) "%X"))
(date-string (gnc-print-time64 date-val "%x")) (date-string (gnc-print-time64 date-val "%x"))
(date-string2 (gnc-print-time64 date2-val "%x %X"))
(rel-date-string (gnc-print-time64 rel-date-val "%x")) (rel-date-string (gnc-print-time64 rel-date-val "%x"))
(combo-date-string (gnc-print-time64 combo-date-val "%x"))) (combo-date-string (gnc-print-time64 combo-date-val "%x")))
@ -369,11 +357,6 @@ new, totally cool report, consult the mailing list ~a.")
(G_ "The date option is ~a.") (G_ "The date option is ~a.")
(gnc:html-markup-b date-string))) (gnc:html-markup-b date-string)))
(gnc:html-markup-p
(gnc:html-markup/format
(G_ "The date and time option is ~a.")
(gnc:html-markup-b date-string2)))
(gnc:html-markup-p (gnc:html-markup-p
(gnc:html-markup/format (gnc:html-markup/format
(G_ "The relative date option is ~a.") (G_ "The relative date option is ~a.")

View File

@ -719,10 +719,14 @@ the option '~a'."))
(begin (begin
(rpterror-earlier "date" item (car full-list)) (rpterror-earlier "date" item (car full-list))
0))) 0)))
(let* ((value (default-getter)) (if show-time
(issue-deprecation-warning
(format #f "Date options with time of day values are deprecated and will be removed in GnuCash 5.")))
(let* ((value (default-getter))
(value->string (lambda () (value->string (lambda ()
(string-append "'" (gnc:value->string value))))) (string-append "'" (gnc:value->string value)))))
(gnc:make-option (gnc:make-option
section name sort-tag 'date documentation-string section name sort-tag 'date documentation-string
(lambda () value) (lambda () value)
(lambda (date) (lambda (date)

View File

@ -171,8 +171,11 @@ GncXmlBackend::session_end()
if (!m_linkfile.empty()) if (!m_linkfile.empty())
g_unlink (m_linkfile.c_str()); g_unlink (m_linkfile.c_str());
if (m_lockfd > 0) if (m_lockfd != -1)
{
close (m_lockfd); close (m_lockfd);
m_lockfd = -1;
}
if (!m_lockfile.empty()) if (!m_lockfile.empty())
{ {
@ -638,12 +641,13 @@ GncXmlBackend::get_file_lock ()
{ {
/* oops .. file is locked by another user .. */ /* oops .. file is locked by another user .. */
set_error(ERR_BACKEND_LOCKED); set_error(ERR_BACKEND_LOCKED);
m_lockfile.clear();
return false; return false;
} }
m_lockfd = g_open (m_lockfile.c_str(), O_RDWR | O_CREAT | O_EXCL , m_lockfd = g_open (m_lockfile.c_str(), O_RDWR | O_CREAT | O_EXCL ,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
if (m_lockfd < 0) if (m_lockfd == -1)
{ {
/* oops .. we can't create the lockfile .. */ /* oops .. we can't create the lockfile .. */
switch (errno) switch (errno)
@ -661,87 +665,11 @@ GncXmlBackend::get_file_lock ()
PWARN ("Unable to create the lockfile %s: %s", PWARN ("Unable to create the lockfile %s: %s",
m_lockfile.c_str(), strerror(errno)); m_lockfile.c_str(), strerror(errno));
set_error(be_err); set_error(be_err);
m_lockfile.clear();
return false; return false;
} }
/* OK, now work around some NFS atomic lock race condition
* mumbo-jumbo. We do this by linking a unique file, and
* then examining the link count. At least that's what the
* NFS programmers guide suggests.
* Note: the "unique filename" must be unique for the
* triplet filename-host-process, otherwise accidental
* aliases can occur.
*/
/* apparently, even this code may not work for some NFS
* implementations. In the long run, I am told that
* ftp.debian.org
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
* provides a better long-term solution.
*/
#ifndef G_OS_WIN32
auto path = m_lockfile.find_last_of('.');
std::stringstream linkfile;
if (path != std::string::npos)
linkfile << m_lockfile.substr(0, path);
else
linkfile << m_lockfile;
linkfile << "." << gethostid() << "." << getpid() << ".LNK";
rc = link (m_lockfile.c_str(), linkfile.str().c_str());
if (rc)
{
/* If hard links aren't supported, just allow the lock. */
if (errno == EPERM || errno == ENOSYS
# ifdef EOPNOTSUPP
|| errno == EOPNOTSUPP
# endif
# ifdef ENOTSUP
|| errno == ENOTSUP
# endif
)
{
return true;
}
/* Otherwise, something else is wrong. */
set_error(ERR_BACKEND_LOCKED);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
rc = g_stat (m_lockfile.c_str(), &statbuf);
if (rc)
{
/* oops .. stat failed! This can't happen! */
set_error(ERR_BACKEND_LOCKED);
std::string msg{"Failed to stat lockfile "};
set_message(msg + m_lockfile);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
if (statbuf.st_nlink != 2)
{
set_error(ERR_BACKEND_LOCKED);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
m_linkfile = linkfile.str();
return true; return true;
#else /* ifndef G_OS_WIN32 */
/* On windows, there is no NFS and the open(,O_CREAT | O_EXCL)
is sufficient for locking. */
return true;
#endif /* ifndef G_OS_WIN32 */
} }
bool bool

View File

@ -60,7 +60,7 @@ private:
std::string m_dirname; std::string m_dirname;
std::string m_lockfile; std::string m_lockfile;
std::string m_linkfile; std::string m_linkfile;
int m_lockfd; int m_lockfd = -1;
QofBook* m_book = nullptr; /* The primary, main open book */ QofBook* m_book = nullptr; /* The primary, main open book */
}; };

View File

@ -127,7 +127,7 @@ sxtg_book_begin (QofBook *book)
static void static void
sxtg_book_end (QofBook *book) sxtg_book_end (QofBook *book)
{ {
// gnc_book_set_template_root (book, NULL); gnc_book_set_template_root (book, NULL);
} }
static gboolean static gboolean

View File

@ -612,7 +612,7 @@ gnc_transaction_get_commodity_imbalance (Transaction *trans,
/* GFunc wrapper for xaccSplitDestroy */ /* GFunc wrapper for xaccSplitDestroy */
static void static void
destroy_split (void* ptr, void* data) destroy_split (void* ptr)
{ {
Split *split = GNC_SPLIT (ptr); Split *split = GNC_SPLIT (ptr);
if (split) if (split)
@ -642,7 +642,10 @@ xaccTransClearTradingSplits (Transaction *trans)
return; return;
xaccTransBeginEdit (trans); xaccTransBeginEdit (trans);
g_list_foreach (trading_splits, destroy_split, NULL); /* destroy_splits doesn't actually free the splits but this gets
* the list ifself freed.
*/
g_list_free_full (trading_splits, destroy_split);
xaccTransCommitEdit (trans); xaccTransCommitEdit (trans);
} }

View File

@ -2107,6 +2107,7 @@ xaccSplitGetOtherSplit (const Split *split)
{ {
Split *s = n->data; Split *s = n->data;
if ((s == split) || if ((s == split) ||
(!xaccTransStillHasSplit(trans, s)) ||
(xaccAccountGetType (xaccSplitGetAccount (s)) == ACCT_TYPE_TRADING) || (xaccAccountGetType (xaccSplitGetAccount (s)) == ACCT_TYPE_TRADING) ||
(qof_instance_has_slot (QOF_INSTANCE (s), "lot-split"))) (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split")))
continue; continue;

View File

@ -73,8 +73,8 @@ cashobjects_register(void)
g_return_val_if_fail(xaccAccountRegister(), FALSE); g_return_val_if_fail(xaccAccountRegister(), FALSE);
g_return_val_if_fail ( xaccTransRegister(), FALSE); g_return_val_if_fail ( xaccTransRegister(), FALSE);
g_return_val_if_fail ( xaccSplitRegister(), FALSE); g_return_val_if_fail ( xaccSplitRegister(), FALSE);
g_return_val_if_fail ( SXRegister (), FALSE);
g_return_val_if_fail ( gnc_sxtt_register(), FALSE); g_return_val_if_fail ( gnc_sxtt_register(), FALSE);
g_return_val_if_fail ( SXRegister (), FALSE);
g_return_val_if_fail(gnc_pricedb_register(), FALSE); g_return_val_if_fail(gnc_pricedb_register(), FALSE);
g_return_val_if_fail (gnc_budget_register(), FALSE); g_return_val_if_fail (gnc_budget_register(), FALSE);
g_return_val_if_fail ( gnc_lot_register (), FALSE); g_return_val_if_fail ( gnc_lot_register (), FALSE);

View File

@ -704,7 +704,7 @@ GncTaxTableList * gncTaxTableGetTables (QofBook *book)
if (!book) return NULL; if (!book) return NULL;
bi = qof_book_get_data (book, _GNC_MOD_NAME); bi = qof_book_get_data (book, _GNC_MOD_NAME);
return bi->tables; return bi ? bi->tables : NULL;
} }
const char *gncTaxTableGetName (const GncTaxTable *table) const char *gncTaxTableGetName (const GncTaxTable *table)

View File

@ -60,6 +60,15 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
return mockaccount ? mockaccount->for_each_transaction(proc, data) : 0; return mockaccount ? mockaccount->for_each_transaction(proc, data) : 0;
} }
SplitList *
xaccAccountGetSplitList (const Account *account)
{
SCOPED_TRACE("");
auto mockaccount = gnc_mockaccount(account);
return mockaccount ? mockaccount->xaccAccountGetSplitList() : nullptr;
}
GncImportMatchMap * GncImportMatchMap *
gnc_account_imap_create_imap (Account *acc) gnc_account_imap_create_imap (Account *acc)
{ {

View File

@ -43,6 +43,7 @@ public:
MOCK_METHOD0(commit_edit, void()); MOCK_METHOD0(commit_edit, void());
MOCK_CONST_METHOD0(get_book, QofBook*()); MOCK_CONST_METHOD0(get_book, QofBook*());
MOCK_CONST_METHOD2(for_each_transaction, gint(TransactionCallback, void*)); MOCK_CONST_METHOD2(for_each_transaction, gint(TransactionCallback, void*));
MOCK_CONST_METHOD0(xaccAccountGetSplitList, SplitList*());
MOCK_METHOD0(create_imap, GncImportMatchMap*()); MOCK_METHOD0(create_imap, GncImportMatchMap*());
protected: protected:

View File

@ -36,6 +36,7 @@ if ($( != 0) {
exit 0 if ($input ne "y"); exit 0 if ($input ne "y");
} }
CPAN::Shell->install('Test2'); #Required by an F::Q dependency but cpan doesn't notice.
CPAN::Shell->install('Date::Manip'); #Required by gnc-fq-helper CPAN::Shell->install('Date::Manip'); #Required by gnc-fq-helper
CPAN::Shell->install('Finance::Quote'); CPAN::Shell->install('Finance::Quote');

View File

@ -36,7 +36,7 @@ msgstr ""
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n" "cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-06-30 07:34+0200\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n"
"PO-Revision-Date: 2021-08-16 20:35+0000\n" "PO-Revision-Date: 2021-09-05 21:35+0000\n"
"Last-Translator: Christian Wehling <christian.wehling@web.de>\n" "Last-Translator: Christian Wehling <christian.wehling@web.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/gnucash/gnucash/" "Language-Team: German <https://hosted.weblate.org/projects/gnucash/gnucash/"
"de/>\n" "de/>\n"
@ -45,7 +45,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.8-dev\n" "X-Generator: Weblate 4.8.1-dev\n"
#: bindings/guile/commodity-table.scm:44 #: bindings/guile/commodity-table.scm:44
msgid "ALL NON-CURRENCY" msgid "ALL NON-CURRENCY"
@ -17134,7 +17134,7 @@ msgstr "Zahl, Datum, Zeit"
# erreichbar. Können wir das vereinheitlichen? # erreichbar. Können wir das vereinheitlichen?
#: gnucash/gtkbuilder/dialog-preferences.glade:1417 #: gnucash/gtkbuilder/dialog-preferences.glade:1417
msgid "Perform account list _setup on new file" msgid "Perform account list _setup on new file"
msgstr "Bei neuer Datei erstellen: Konten_einrichtung anzeigen" msgstr "Bei neuer Datei erstellen: Konten_einrichtung starten"
#: gnucash/gtkbuilder/dialog-preferences.glade:1423 #: gnucash/gtkbuilder/dialog-preferences.glade:1423
msgid "Present the new account list dialog when you choose File->New File." msgid "Present the new account list dialog when you choose File->New File."
@ -18328,7 +18328,7 @@ msgstr "<b>Voreinstellungen Buchungseditor</b>"
#: gnucash/gtkbuilder/dialog-sx.glade:545 #: gnucash/gtkbuilder/dialog-sx.glade:545
msgid "_Run when data file opened" msgid "_Run when data file opened"
msgstr "Seit-Letztem-Aufruf Fenster starten, wenn eine _Datei geöffnet wird" msgstr "Ausführen, wenn eine _Datei geöffnet wird"
#: gnucash/gtkbuilder/dialog-sx.glade:549 #: gnucash/gtkbuilder/dialog-sx.glade:549
msgid "Run the \"since last run\" process when a file is opened." msgid "Run the \"since last run\" process when a file is opened."
@ -18388,10 +18388,8 @@ msgid "R_emind in advance"
msgstr "Im Voraus er_innern" msgstr "Im Voraus er_innern"
#: gnucash/gtkbuilder/dialog-sx.glade:724 #: gnucash/gtkbuilder/dialog-sx.glade:724
#, fuzzy
#| msgid "_Review created transactions"
msgid "Set 'Re_view Created Transactions' as default" msgid "Set 'Re_view Created Transactions' as default"
msgstr "Erzeugte Buchungen _durchsehen" msgstr "'Erstellte _Buchungen durchsehen' als Standard festlegen"
#: gnucash/gtkbuilder/dialog-sx.glade:728 #: gnucash/gtkbuilder/dialog-sx.glade:728
msgid "" msgid ""

View File

@ -23,7 +23,7 @@ msgstr ""
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n" "cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-06-30 07:34+0200\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n"
"PO-Revision-Date: 2021-08-31 14:33+0000\n" "PO-Revision-Date: 2021-09-10 16:33+0000\n"
"Last-Translator: TianXing_Yi <ytx.cash@gmail.com>\n" "Last-Translator: TianXing_Yi <ytx.cash@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"gnucash/gnucash/zh_Hans/>\n" "gnucash/gnucash/zh_Hans/>\n"
@ -32,7 +32,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.8.1-dev\n" "X-Generator: Weblate 4.9-dev\n"
"X-Bugs: Report translation errors to the Language-Team address.\n" "X-Bugs: Report translation errors to the Language-Team address.\n"
#: bindings/guile/commodity-table.scm:44 #: bindings/guile/commodity-table.scm:44
@ -2162,7 +2162,7 @@ msgstr "入账日期"
#: gnucash/gnome/dialog-invoice.c:872 #: gnucash/gnome/dialog-invoice.c:872
msgid "Post to Account" msgid "Post to Account"
msgstr "入账科目" msgstr "入账科目"
#: gnucash/gnome/dialog-invoice.c:873 #: gnucash/gnome/dialog-invoice.c:873
msgid "Accumulate Splits?" msgid "Accumulate Splits?"
@ -3643,7 +3643,7 @@ msgstr "打开查找项目对话框"
#: gnucash/gnome/gnc-plugin-business.c:238 #: gnucash/gnome/gnc-plugin-business.c:238
#: gnucash/gnome/gnc-plugin-business.c:271 #: gnucash/gnome/gnc-plugin-business.c:271
msgid "_Process Payment..." msgid "_Process Payment..."
msgstr "处理收付(_P)..." msgstr "收付(_P)..."
#: gnucash/gnome/gnc-plugin-business.c:196 #: gnucash/gnome/gnc-plugin-business.c:196
#: gnucash/gnome/gnc-plugin-business.c:239 #: gnucash/gnome/gnc-plugin-business.c:239
@ -4946,7 +4946,7 @@ msgstr "显示员工报表"
#: gnucash/gnome/gnc-plugin-page-owner-tree.c:293 #: gnucash/gnome/gnc-plugin-page-owner-tree.c:293
msgid "New Voucher" msgid "New Voucher"
msgstr "新建支出凭证" msgstr "新建报销"
#: gnucash/gnome/gnc-plugin-page-owner-tree.c:446 #: gnucash/gnome/gnc-plugin-page-owner-tree.c:446
msgid "Owners" msgid "Owners"
@ -9239,7 +9239,7 @@ msgstr "重新计算(_R)"
#: gnucash/report/trep-engine.scm:168 gnucash/report/trep-engine.scm:956 #: gnucash/report/trep-engine.scm:168 gnucash/report/trep-engine.scm:956
#: gnucash/report/trep-engine.scm:1045 #: gnucash/report/trep-engine.scm:1045
msgid "Account Name" msgid "Account Name"
msgstr "科目名称" msgstr "名称"
#: gnucash/gnome-utils/gnc-tree-view-account.c:816 #: gnucash/gnome-utils/gnc-tree-view-account.c:816
#: gnucash/gnome-utils/gnc-tree-view-split-reg.c:2919 #: gnucash/gnome-utils/gnc-tree-view-split-reg.c:2919
@ -10877,13 +10877,13 @@ msgstr ""
msgid "" msgid ""
"Set \"Review Created Transactions\" as the default for the \"since last run" "Set \"Review Created Transactions\" as the default for the \"since last run"
"\" dialog." "\" dialog."
msgstr "" msgstr "将 \"审查创建的交易 \"设为 \"自上次运行以来 \"对话框的默认值。"
#: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:28 #: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:28
msgid "" msgid ""
"This setting controls whether as default the \"review created transactions\" " "This setting controls whether as default the \"review created transactions\" "
"is set for the \"since last run\" dialog." "is set for the \"since last run\" dialog."
msgstr "" msgstr "此设置控制 \"自上次运行以来 \"对话框是否默认设置 \"审查已创建的交易\"。"
#: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:35 #: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:35
msgid "Set the \"auto create\" flag by default" msgid "Set the \"auto create\" flag by default"
@ -11238,7 +11238,7 @@ msgstr "新打开的标签页前置,而非最后"
msgid "" msgid ""
"If active, new tabs are opened adjacent to current tab. If inactive, the new " "If active, new tabs are opened adjacent to current tab. If inactive, the new "
"tabs are opened instead at the end." "tabs are opened instead at the end."
msgstr "" msgstr "如果激活,新标签会在当前标签的旁边打开。如果不激活,新标签将在最后打开。"
#: gnucash/gschemas/org.gnucash.gschema.xml.in:140 #: gnucash/gschemas/org.gnucash.gschema.xml.in:140
#: gnucash/gtkbuilder/dialog-preferences.glade:940 #: gnucash/gtkbuilder/dialog-preferences.glade:940
@ -11330,7 +11330,7 @@ msgstr "最大的几个月又回到过去。"
msgid "" msgid ""
"Dates will be completed so that they are close to the current date. Enter " "Dates will be completed so that they are close to the current date. Enter "
"the maximum number of months to go backwards in time when completing dates." "the maximum number of months to go backwards in time when completing dates."
msgstr "录入月份和本月差值在限额内(小于等于),即本年;超出(大于)为明年。" msgstr "相隔月数小于等于设定值为本年,大于设定值为明年。"
#: gnucash/gschemas/org.gnucash.gschema.xml.in:180 #: gnucash/gschemas/org.gnucash.gschema.xml.in:180
msgid "Show Horizontal Grid Lines" msgid "Show Horizontal Grid Lines"
@ -15973,7 +15973,7 @@ msgstr "<b>日期补全</b>"
#: gnucash/gtkbuilder/dialog-preferences.glade:1112 #: gnucash/gtkbuilder/dialog-preferences.glade:1112
msgid "When a date is entered without year, it should be taken" msgid "When a date is entered without year, it should be taken"
msgstr "输入的日期没有年份时,其应属于" msgstr "没有年份的日期,其应属于"
#: gnucash/gtkbuilder/dialog-preferences.glade:1128 #: gnucash/gtkbuilder/dialog-preferences.glade:1128
msgid "" msgid ""
@ -15984,9 +15984,7 @@ msgstr "日期年份补全为本年。"
msgid "" msgid ""
"In a sliding 12-month window starting this\n" "In a sliding 12-month window starting this\n"
"many months before the current month" "many months before the current month"
msgstr "" msgstr "相隔月数定年份"
"从现在开始这个次数,它追溯到过去,\n"
"它被认为是那个月的12个月内的日期"
#: gnucash/gtkbuilder/dialog-preferences.glade:1165 #: gnucash/gtkbuilder/dialog-preferences.glade:1165
msgid "Enter number of months." msgid "Enter number of months."
@ -16257,13 +16255,13 @@ msgstr "不可能的匹配日阈值 (_U)"
msgid "" msgid ""
"A transaction whose date is within the threshold is likely to be a match. " "A transaction whose date is within the threshold is likely to be a match. "
"Default is 4 days." "Default is 4 days."
msgstr "" msgstr "日期在阈值内的交易可能是匹配的。默认为4天。"
#: gnucash/gtkbuilder/dialog-preferences.glade:2340 #: gnucash/gtkbuilder/dialog-preferences.glade:2340
msgid "" msgid ""
"A transaction whose date is outside the threshold is unlikely to be a match. " "A transaction whose date is outside the threshold is unlikely to be a match. "
"Default is 14 days." "Default is 14 days."
msgstr "" msgstr "日期在阈值之外的交易不太可能是匹配的。默认为14天。"
#: gnucash/gtkbuilder/dialog-preferences.glade:2385 #: gnucash/gtkbuilder/dialog-preferences.glade:2385
msgid "<b>Checks</b>" msgid "<b>Checks</b>"
@ -17203,7 +17201,7 @@ msgstr "默认复核已创建交易(_R)"
msgid "" msgid ""
"Set 'Review Created Transactions' as the default in the 'Since Last Run' " "Set 'Review Created Transactions' as the default in the 'Since Last Run' "
"dialog." "dialog."
msgstr "" msgstr "在 \"自上次运行 \"对话框中,将 \"审查创建的交易 \"设置为默认值。"
#: gnucash/gtkbuilder/dialog-sx.glade:765 #: gnucash/gtkbuilder/dialog-sx.glade:765
msgid "Edit Scheduled Transaction" msgid "Edit Scheduled Transaction"
@ -17356,7 +17354,7 @@ msgstr "GnuCash 每日提示"
#: gnucash/gtkbuilder/dialog-totd.glade:26 #: gnucash/gtkbuilder/dialog-totd.glade:26
msgid "_Previous" msgid "_Previous"
msgstr "去年末(_P)" msgstr "上一个(_P)"
#: gnucash/gtkbuilder/dialog-totd.glade:41 #: gnucash/gtkbuilder/dialog-totd.glade:41
msgid "_Next" msgid "_Next"
@ -21349,7 +21347,7 @@ msgstr "小计"
#: gnucash/report/reports/standard/owner-report.scm:56 #: gnucash/report/reports/standard/owner-report.scm:56
#: libgnucash/app-utils/business-options.scm:78 #: libgnucash/app-utils/business-options.scm:78
msgid "Tax" msgid "Tax"
msgstr "税" msgstr "税"
#: gnucash/register/ledger-core/gncEntryLedgerModel.c:127 #: gnucash/register/ledger-core/gncEntryLedgerModel.c:127
msgid "Billable?" msgid "Billable?"
@ -21968,7 +21966,7 @@ msgstr "价格信息的来源。"
#: gnucash/report/options-utilities.scm:144 #: gnucash/report/options-utilities.scm:144
msgid "Average cost of purchases weighted by volume" msgid "Average cost of purchases weighted by volume"
msgstr "" msgstr "按数量加权的平均采购成本"
#: gnucash/report/options-utilities.scm:145 #: gnucash/report/options-utilities.scm:145
msgid "Weighted average of all transactions in the past" msgid "Weighted average of all transactions in the past"
@ -22103,7 +22101,7 @@ msgstr "收入支出(_I)"
#: gnucash/report/report-core.scm:154 #: gnucash/report/report-core.scm:154
msgid "_Taxes" msgid "_Taxes"
msgstr "税(_U)" msgstr "税(_U)"
#: gnucash/report/report-core.scm:155 #: gnucash/report/report-core.scm:155
msgid "E_xamples" msgid "E_xamples"
@ -24537,7 +24535,7 @@ msgstr "以逐条求和计算么?"
#: gnucash/report/reports/standard/budget-barchart.scm:142 #: gnucash/report/reports/standard/budget-barchart.scm:142
msgid "Select which chart type to use." msgid "Select which chart type to use."
msgstr "" msgstr "选择要使用的图表类型。"
#: gnucash/report/reports/standard/budget-barchart.scm:144 #: gnucash/report/reports/standard/budget-barchart.scm:144
#: gnucash/report/reports/standard/category-barchart.scm:156 #: gnucash/report/reports/standard/category-barchart.scm:156