Merge branch 'maint'

This commit is contained in:
Christopher Lam
2022-03-12 15:18:43 +08:00
133 changed files with 147195 additions and 140087 deletions

52
HACKING
View File

@@ -17,57 +17,7 @@ the design document.
Coding Style Conventions
------------------------
General:
* When modifying a file, the style convention in that file should be
followed.
* When creating a new file, the style of existing files should be
followed.
* When creating lots of new files in a new directory, you may use
your own coding standards, but please try to stick as closely as
possible to the GNU coding standards.
* Do not submit patches that consist of (gratuitous) stylistic changes.
C:
* Use ISO C.
* Use glib memory routines where possible. This means you should be
using g_malloc(), g_new(), g_free(), etc., instead of malloc(),
free(), etc. Do not mix glib memory calls with libc calls!
* Where possible, use glib data abstractions instead of rolling your
own. Glib linked lists and pointer arrays are very convenient and
have been extensively used and tested.
* All gnucash functions and global variables are prefixed with gnc_
* Use static functions whenever possible
* Use const whenever possible
Scheme:
* All gnucash functions and global variables are prefixed with gnc:
* All global variables are enclosed in ** (i.e. gnc:*load-path*)
* All private functions are enclosed in __ (i.e. gnc:_do-not-call_)
* All C functions wrapped into scheme have dashes in place of underscores.
(xaccSplitGetBalance --> gnc:split-get-balance) - but FIXME:
This policy seems to have been dropped in favor of having
identical function names. cstim, 2006-10-30.
Dave Peticolas <dave@krondo.com>
August 22, 2000
Please refer to https://wiki.gnucash.org/wiki/CodingStandard.
==============
TIPS AND HINTS

View File

@@ -85,7 +85,6 @@ gnc_add_scheme_targets(scm-core-utils
DEPENDS "${GUILE_DEPENDS}")
set (engine_SCHEME_0
commodity-table.scm
gnc-numeric.scm
business-core.scm
)

View File

@@ -1,44 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; commodity-table.scm
;;; load and save commodity tables
;;;
;;; Bill Gribble <grib@billgribble.com> 3 Aug 2000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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@gnu.org
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-module (gnucash engine commodity-table))
(export GNC_COMMODITY_NS_CURRENCY)
(export GNC_COMMODITY_NS_NASDAQ)
(export GNC_COMMODITY_NS_NYSE)
(export GNC_COMMODITY_NS_AMEX)
(export GNC_COMMODITY_NS_EUREX)
(export GNC_COMMODITY_NS_MUTUAL)
(define GNC_COMMODITY_NS_CURRENCY "CURRENCY")
;; If you change the C side, change this too.
(define GNC_COMMODITY_NS_AMEX "AMEX")
(define GNC_COMMODITY_NS_NYSE "NYSE")
(define GNC_COMMODITY_NS_NASDAQ "NASDAQ")
(define GNC_COMMODITY_NS_EUREX "EUREX")
(define GNC_COMMODITY_NS_MUTUAL "FUND")
(define GNC_COMMODITY_NS_ASX "ASX")
(define GNC_COMMODITY_NS_NONCURRENCY (gettext "ALL NON-CURRENCY"))

View File

@@ -28,5 +28,7 @@
(load-and-reexport (sw_engine)
(gnucash engine business-core)
(gnucash engine commodity-table)
(gnucash engine gnc-numeric))
(define-public GNC_COMMODITY_NS_CURRENCY "CURRENCY")
(define-public GNC_COMMODITY_NS_NONCURRENCY (gettext "ALL NON-CURRENCY"))

View File

@@ -0,0 +1,165 @@
#!/usr/bin/env python3
## @file
# @brief Some examples for qof queries
# @author Christoph Holtermann
# @date 2022-03-06
# @ingroup python_bindings_examples
# @note incomplete set of qof examples, to be extended
import datetime
from random import randint
from gnucash import Session, SessionOpenMode, Account, Transaction, Split, \
GncNumeric, Query
from gnucash import QOF_COMPARE_GTE, QOF_COMPARE_GT, QOF_QUERY_AND, \
QOF_QUERY_OR, QOF_STRING_MATCH_NORMAL, QOF_COMPARE_CONTAINS, \
QOF_NUMERIC_MATCH_ANY
from gnucash import gnucash_core_c
from gnucash import gnucash_core
# We need to tell GnuCash the data format to create the new file as (xml://)
uri = "xml:///tmp/qof.gnucash"
def createAccounts(book):
root_account = book.get_root_account()
commodtable = book.get_table()
currency = commodtable.lookup("CURRENCY", "EUR")
ses.save()
print('Create two accounts ("Account A", "Account B")')
accountA = Account(book)
accountA.SetCommodity(currency)
accountA.SetName("Account A")
root_account.append_child(accountA)
accountB = Account(book)
accountB.SetCommodity(currency)
accountB.SetName("Account B")
root_account.append_child(accountB)
#ses.save()
return accountA, accountB
def createRandomTransactions(book, accountA, accountB):
split = Split(book)
currency = book.get_table().lookup("CURRENCY", "EUR")
print("Create 100 random transactions")
for i in range(100):
trans = Transaction(book)
trans.BeginEdit()
trans.SetCurrency(currency)
trans.SetDate(randint(1,28), randint(1,12), randint(1900,2000))
trans.SetDescription("Transaction "+str(i))
value = randint(0,10000)
value1 = GncNumeric(value, 100)
value2 = GncNumeric(-value, 100)
split1 = Split(book)
split1.SetValue(value1)
split1.SetAccount(accountA)
split1.SetMemo("A" + str(i))
split1.SetParent(trans)
split2 = Split(book)
split2.SetValue(value2)
split2.SetAccount(accountB)
split2.SetMemo("B" + str(i))
split2.SetParent(trans)
trans.CommitEdit()
def query_transactions(book, terms=[]):
query = Query()
query.search_for('Trans')
query.set_book(book)
if terms:
for term in terms:
query.add_term(*term)
transactions = []
for transaction in query.run():
transaction = Transaction(instance=transaction) # ToDo: query.run() should return objects
transactions.append(transaction)
query.destroy()
return transactions
def query_splits(book, terms=[]):
query = Query()
query.search_for('Split')
query.set_book(book)
if terms:
for term in terms:
query.add_term(*term)
splits = []
for split in query.run():
split = Split(instance=split) # ToDo: query.run() should return objects
splits.append(split)
query.destroy()
return splits
with Session(uri, SessionOpenMode.SESSION_NEW_STORE) as ses:
book = ses.get_book()
accountA, accountB = createAccounts(book)
createRandomTransactions(book, accountA, accountB)
# TRANSACTIONS
#
# get all transactions
transactions_all = query_transactions(book)
print("Query all: " + str(len(transactions_all)) + " transactions.")
# query date
threshold = datetime.datetime(1950,1,1)
QOF_DATE_MATCH_NORMAL = 2
terms = [(['date-posted'], gnucash_core.QueryDatePredicate(QOF_COMPARE_GTE, QOF_DATE_MATCH_NORMAL, threshold), QOF_QUERY_AND)]
transactions_2 = query_transactions(book, terms)
print("Query transactions with date > 1950: " + str(len(transactions_2)) + " (Should be about 50).")
# query description
isRegex = False
terms = [(['desc'], gnucash_core.QueryStringPredicate(QOF_COMPARE_CONTAINS, "Transaction 5", QOF_STRING_MATCH_NORMAL, isRegex), QOF_QUERY_AND)]
transactions_3 = query_transactions(book, terms)
print("Query transaction with description containing 'Transaction 5': " + str(len(transactions_3)) + " (Should be 11).")
# SPLITS
#
# query memo
isRegex = False
terms = [(['memo'], gnucash_core.QueryStringPredicate(QOF_COMPARE_CONTAINS, "A22", QOF_STRING_MATCH_NORMAL, isRegex), QOF_QUERY_AND)]
splits_1 = query_splits(book, terms)
print("Query splits with memo containing 'A22': " + str(len(splits_1)) + " (Should be 1).")
# query description
isRegex = False
terms = [(['trans', 'desc'], gnucash_core.QueryStringPredicate(QOF_COMPARE_CONTAINS, "Transaction 5", QOF_STRING_MATCH_NORMAL, isRegex), QOF_QUERY_AND)]
splits_2 = query_splits(book, terms)
print("Query splits with transaction description containing 'Transaction 5': " + str(len(splits_2)) + " (Should be 22).")
# query memo and desc
isRegex = False
terms = [(['memo'], gnucash_core.QueryStringPredicate(QOF_COMPARE_CONTAINS, "A22", QOF_STRING_MATCH_NORMAL, isRegex), QOF_QUERY_AND)]
terms += [(['trans', 'desc'], gnucash_core.QueryStringPredicate(QOF_COMPARE_CONTAINS, "Transaction 55", QOF_STRING_MATCH_NORMAL, isRegex), QOF_QUERY_OR)]
splits_4 = query_splits(book, terms)
print("Query splits with memo containing 'A22' or transaction desc containing 'Transaction 55': " + str(len(splits_4)) + " (Should be 3).")
# query split value
threshold = GncNumeric(5000, 100)
terms = [(["amount"], gnucash_core.QueryNumericPredicate(QOF_COMPARE_GT, QOF_NUMERIC_MATCH_ANY, threshold), QOF_QUERY_AND)]
splits_3 = query_splits(book, terms)
print("Query splits with amount > " + str(threshold) + ": " + str(len(splits_3)) + " (Should be about 100).")

View File

@@ -62,6 +62,9 @@ from gnucash import \
QOF_COMPARE_GTE, \
QOF_COMPARE_NEQ
from gnucash import \
QOF_DATE_MATCH_NORMAL
from gnucash import \
INVOICE_TYPE
@@ -915,8 +918,6 @@ def getAccountSplits(book, guid, date_posted_from, date_posted_to):
SPLIT_TRANS= 'trans'
QOF_DATE_MATCH_NORMAL = 1
TRANS_DATE_POSTED = 'date-posted'
if date_posted_from != None:

View File

@@ -908,7 +908,29 @@ from gnucash.gnucash_core_c import \
QOF_COMPARE_EQUAL, \
QOF_COMPARE_GT, \
QOF_COMPARE_GTE, \
QOF_COMPARE_NEQ
QOF_COMPARE_NEQ, \
QOF_COMPARE_CONTAINS, \
QOF_COMPARE_NCONTAINS
from gnucash.gnucash_core_c import \
QOF_DATE_MATCH_NORMAL, \
QOF_DATE_MATCH_DAY
from gnucash.gnucash_core_c import \
QOF_NUMERIC_MATCH_DEBIT, \
QOF_NUMERIC_MATCH_CREDIT, \
QOF_NUMERIC_MATCH_ANY
from gnucash.gnucash_core_c import \
QOF_GUID_MATCH_ANY, \
QOF_GUID_MATCH_NONE, \
QOF_GUID_MATCH_NULL, \
QOF_GUID_MATCH_ALL, \
QOF_GUID_MATCH_LIST_ANY
from gnucash.gnucash_core_c import \
QOF_CHAR_MATCH_ANY, \
QOF_CHAR_MATCH_NONE
from gnucash.gnucash_core_c import \
INVOICE_TYPE
@@ -967,3 +989,9 @@ class QueryGuidPredicate(GnuCashCoreClass):
QueryGuidPredicate.add_constructor_and_methods_with_prefix(
'qof_query_', 'guid_predicate')
class QueryNumericPredicate(GnuCashCoreClass):
pass
QueryNumericPredicate.add_constructor_and_methods_with_prefix(
'qof_query_', 'numeric_predicate')

View File

@@ -21,12 +21,12 @@ class TestCommodityNamespace(CommoditySession):
#print(self.table.__class__)
namespace_names = self.table.get_namespaces()
#print(namespace_names)
self.assertEqual(namespace_names, ['AMEX', 'NYSE', 'NASDAQ', 'EUREX', 'FUND', 'template', 'CURRENCY'])
self.assertEqual(namespace_names, ['All non-currency', 'template', 'CURRENCY'])
def test_namespaces_list(self):
namespaces = self.table.get_namespaces_list()
namespace_names = [ns.get_name() for ns in namespaces]
self.assertEqual(namespace_names, ['AMEX', 'NYSE', 'NASDAQ', 'EUREX', 'FUND', 'template', 'CURRENCY'])
self.assertEqual(namespace_names, ['All non-currency', 'template', 'CURRENCY'])
if __name__ == '__main__':
main()

View File

@@ -124,7 +124,9 @@ gnc_dup_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, gpointer user
(event->state & modifiers) == GDK_MOD1_MASK)
return FALSE;
if (event->keyval == GDK_KEY_plus || event->keyval == GDK_KEY_KP_Add)
/* See https://bugs.gnucash.org/show_bug.cgi?id=798386 for semicolon */
if (event->keyval == GDK_KEY_plus || event->keyval == GDK_KEY_KP_Add ||
event->keyval == GDK_KEY_semicolon)
increment = 1;
else if (event->keyval == GDK_KEY_minus || event->keyval == GDK_KEY_KP_Subtract)
increment = -1;

View File

@@ -486,7 +486,8 @@ gnc_handle_date_accelerator (GdkEventKey *event,
case GDK_KEY_KP_Add:
case GDK_KEY_plus:
case GDK_KEY_equal:
if (event->state & GDK_SHIFT_MASK)
case GDK_KEY_semicolon: // See https://bugs.gnucash.org/show_bug.cgi?id=798386
if (event->state & GDK_SHIFT_MASK)
g_date_add_days (&gdate, 7);
else if (event->state & GDK_MOD1_MASK)
g_date_add_months (&gdate, 1);

View File

@@ -403,6 +403,9 @@ gnc_account_sel_finalize (GObject *object)
if (gas->acctTypeFilters)
g_list_free (gas->acctTypeFilters);
if (gas->acctCommodityFilters)
g_list_free (gas->acctCommodityFilters);
G_OBJECT_CLASS (parent_class)->finalize (object);
}

View File

@@ -402,11 +402,9 @@ gnc_commodity *
gnc_currency_edit_get_currency (GNCCurrencyEdit *gce)
{
gnc_commodity *commodity;
const char *fullname;
char *mnemonic, *name;
GtkTreeModel *model;
GtkTreeIter iter;
GValue value = { 0 };
g_return_val_if_fail(gce != NULL, NULL);
g_return_val_if_fail(GNC_IS_CURRENCY_EDIT(gce), NULL);
@@ -414,10 +412,7 @@ gnc_currency_edit_get_currency (GNCCurrencyEdit *gce)
if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(gce), &iter))
{
model = gtk_combo_box_get_model(GTK_COMBO_BOX(gce));
gtk_tree_model_get_value(model, &iter, 0, &value);
fullname = g_value_get_string(&value);
mnemonic = g_strdup(fullname);
g_value_unset(&value);
gtk_tree_model_get (model, &iter, 0, &mnemonic, -1);
name = strchr(mnemonic, ' ');
if (name != NULL)

View File

@@ -315,3 +315,127 @@ gnc_choose_radio_option_dialog(GtkWidget *parent,
return radio_result;
}
static gchar *
gnc_input_dialog_internal (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input, gboolean use_entry)
{
gint result;
GtkWidget *view;
GtkTextBuffer *buffer;
gchar *user_input = NULL;
GtkTextIter start, end;
/* Create the widgets */
GtkWidget* dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
_("_Cancel"), GTK_RESPONSE_REJECT,
NULL);
GtkWidget* content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a label
GtkWidget* label = gtk_label_new (msg);
gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);
// add a textview or an entry.
if (use_entry)
{
view = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (view), default_input);
}
else
{
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, default_input, -1);
}
gtk_box_pack_start(GTK_BOX(content_area), view, TRUE, TRUE, 0);
// run the dialog
gtk_widget_show_all (dialog);
result = gtk_dialog_run (GTK_DIALOG (dialog));
if (result != GTK_RESPONSE_REJECT)
{
if (use_entry)
user_input = g_strdup (gtk_entry_get_text ((GTK_ENTRY (view))));
else
{
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
user_input = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
}
}
gtk_widget_destroy (dialog);
return user_input;
}
/********************************************************************\
* gnc_input_dialog *
* simple convenience dialog to get a single value from the user *
* user may choose between "Ok" and "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* default_input - will be displayed as default input *
* Return: the input (text) the user entered, if pressed "Ok" *
* NULL, if pressed "Cancel" *
\********************************************************************/
gchar *
gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
{
return gnc_input_dialog_internal (parent, title, msg, default_input, FALSE);
}
/********************************************************************\
* gnc_input_dialog_with_entry *
* Similar to gnc_input_dialog but use a single line entry widget *
* user may choose between "Ok" and "Cancel" *
\********************************************************************/
gchar *
gnc_input_dialog_with_entry (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
{
return gnc_input_dialog_internal (parent, title, msg, default_input, TRUE);
}
void
gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg)
{
GtkWidget *view;
GtkTextBuffer *buffer;
gint width, height;
/* Create the widgets */
GtkWidget* dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
GtkWidget* content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a scroll area
GtkWidget* scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start(GTK_BOX(content_area), scrolledwindow, TRUE, TRUE, 0);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, msg, -1);
gtk_container_add (GTK_CONTAINER (scrolledwindow), view);
// run the dialog
if (parent)
{
gtk_window_get_size (GTK_WINDOW(parent), &width, &height);
gtk_window_set_default_size (GTK_WINDOW(dialog), width, height);
}
gtk_widget_show_all (dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}

View File

@@ -416,7 +416,7 @@ const gchar *gnc_plugin_page_get_page_color (GncPluginPage *page);
*
* @param page The page whose name should be retrieved.
*
* @param The color for this page. This string is owned by the page and
* @param color The color for this page. This string is owned by the page and
* should not be freed by the caller.
*/
void gnc_plugin_page_set_page_color (GncPluginPage *page, const char *color);

View File

@@ -283,18 +283,14 @@ gnc_plugin_update_actions (GtkActionGroup *action_group,
gboolean value)
{
GtkAction *action;
GValue gvalue = { 0 };
gint i;
g_value_init (&gvalue, G_TYPE_BOOLEAN);
g_value_set_boolean (&gvalue, value);
for (i = 0; action_names[i]; i++)
{
action = gtk_action_group_get_action (action_group, action_names[i]);
if (action)
{
g_object_set_property (G_OBJECT(action), property_name, &gvalue);
g_object_set (G_OBJECT(action), property_name, value, NULL);
}
else
{
@@ -303,7 +299,6 @@ gnc_plugin_update_actions (GtkActionGroup *action_group,
g_list_length(gtk_action_group_list_actions(action_group)));
}
}
g_value_unset (&gvalue);
}

View File

@@ -108,13 +108,9 @@ GncBudget *
gnc_tree_model_budget_get_budget(GtkTreeModel *tm, GtkTreeIter *iter)
{
GncBudget *bgt;
GValue gv = { 0 };
GncGUID *guid;
gtk_tree_model_get_value(tm, iter, BUDGET_GUID_COLUMN, &gv);
guid = (GncGUID *) g_value_get_pointer(&gv);
g_value_unset(&gv);
gtk_tree_model_get (tm, iter, BUDGET_GUID_COLUMN, &guid, -1);
bgt = gnc_budget_lookup(guid, gnc_get_current_book());
return bgt;
}
@@ -123,7 +119,6 @@ gboolean
gnc_tree_model_budget_get_iter_for_budget(GtkTreeModel *tm, GtkTreeIter *iter,
GncBudget *bgt)
{
GValue gv = { 0 };
const GncGUID *guid1;
GncGUID *guid2;
@@ -134,9 +129,7 @@ gnc_tree_model_budget_get_iter_for_budget(GtkTreeModel *tm, GtkTreeIter *iter,
return FALSE;
while (gtk_list_store_iter_is_valid(GTK_LIST_STORE(tm), iter))
{
gtk_tree_model_get_value(tm, iter, BUDGET_GUID_COLUMN, &gv);
guid2 = (GncGUID *) g_value_get_pointer(&gv);
g_value_unset(&gv);
gtk_tree_model_get (tm, iter, BUDGET_GUID_COLUMN, &guid2, -1);
if (guid_equal(guid1, guid2))
return TRUE;

View File

@@ -104,6 +104,14 @@ extern void
gnc_error_dialog (GtkWindow *parent,
const char *format, ...) G_GNUC_PRINTF (2, 3);
extern gchar *
gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
extern gchar *
gnc_input_dialog_with_entry (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
extern void
gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg);
extern void
gnc_gnome_help (GtkWindow *parent, const char *file_name, const char *target_link);

View File

@@ -4,6 +4,7 @@ set (gnc_gnome_noinst_HEADERS
assistant-hierarchy.h
assistant-loan.h
assistant-stock-split.h
assistant-stock-transaction.h
business-options-gnome.h
business-urls.h
business-gnome-utils.h
@@ -66,6 +67,7 @@ set (gnc_gnome_SOURCES
assistant-hierarchy.c
assistant-loan.cpp
assistant-stock-split.c
assistant-stock-transaction.cpp
business-options-gnome.c
business-urls.c
business-gnome-utils.c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
/********************************************************************\
* assistant-stock-transaction.h -- stock assistant for GnuCash *
* Copyright (C) 2022 Christopher Lam *
* *
* 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@gnu.org *
\********************************************************************/
#ifndef GNC_ASSISTANT_STOCK_TRANSACTION_H
#define GNC_ASSISTANT_STOCK_TRANSACTION_H
#include "Account.h"
/********************************************************************\
* gnc_stock_transaction_assistant *
* opens up a assistant to record a stock transaction *
* *
* Args: parent - the parent of this window *
* account - the initial account to use *
* Return: nothing *
\********************************************************************/
void gnc_stock_transaction_assistant (GtkWidget *parent, Account * account);
#endif

View File

@@ -579,7 +579,6 @@ gnc_simple_combo_get_value (GtkComboBox *cbox)
{
GtkTreeIter iter;
GtkTreeModel *model;
GValue value = { 0 };
gpointer retval;
if (!cbox) return NULL;
@@ -587,9 +586,7 @@ gnc_simple_combo_get_value (GtkComboBox *cbox)
model = gtk_combo_box_get_model (cbox);
if (!gtk_combo_box_get_active_iter (cbox, &iter))
return NULL;
gtk_tree_model_get_value (model, &iter, 1, &value);
retval = g_value_get_pointer (&value);
g_value_unset (&value);
gtk_tree_model_get (model, &iter, 1, &retval, -1);
return retval;
}
@@ -610,28 +607,25 @@ gnc_simple_combo_set_value (GtkComboBox *cbox, gpointer data)
while (valid_iter)
{
GValue value = { 0 };
gpointer ptr;
gtk_tree_model_get_value (model, &iter, 1, &value);
gtk_tree_model_get (model, &iter, 1, &ptr, -1);
if (lsd && lsd->is_equal) // A specific comparator function was set
{
if ((lsd->is_equal)(g_value_get_pointer(&value), data))
if ((lsd->is_equal)(ptr, data))
{
gtk_combo_box_set_active_iter (cbox, &iter);
g_value_unset (&value);
return;
}
}
else // No specific comparator function set, use generic pointer comparison instead
{
if (g_value_get_pointer(&value) == data)
if (ptr == data)
{
gtk_combo_box_set_active_iter (cbox, &iter);
g_value_unset (&value);
return;
}
}
g_value_unset (&value);
valid_iter = gtk_tree_model_iter_next (model, &iter);
}
}

View File

@@ -810,16 +810,13 @@ static void print_date (GtkTreeViewColumn *tree_column,
GtkTreeIter *iter,
gpointer data)
{
GValue value = { 0 };
time64 doc_date_time;
gchar *doc_date_str = g_strdup (_("Open"));
gint col = GPOINTER_TO_INT(data);
g_return_if_fail (cell && iter && tree_model);
gtk_tree_model_get_value (tree_model, iter, col, &value);
doc_date_time = (time64) g_value_get_int64 (&value);
g_value_unset (&value);
gtk_tree_model_get (tree_model, iter, col, &doc_date_time, -1);
if (doc_date_time != G_MAXINT64) /* assumes INT64_MAX represents an invalid date/time */
{

View File

@@ -339,14 +339,11 @@ calculate_selected_total_helper (GtkTreeModel *model,
{
gnc_numeric *subtotal = (gnc_numeric*) data;
gnc_numeric cur_val;
GValue value = { 0 };
GNCLot *lot;
Account *acct;
gnc_commodity *currency;
gtk_tree_model_get_value (model, iter, 5, &value);
lot = (GNCLot *) g_value_get_pointer (&value);
g_value_unset (&value);
gtk_tree_model_get (model, iter, 5, &lot, -1);
/* Find the amount's currency to determine the required precision */
acct = gnc_lot_get_account (lot);
@@ -413,13 +410,10 @@ gnc_payment_dialog_highlight_documents (PaymentWindow *pw)
{
do
{
GValue value = { 0 };
GNCLot *lot;
GList *li_node;
gtk_tree_model_get_value (model, &iter, 5, &value);
lot = (GNCLot *) g_value_get_pointer (&value);
g_value_unset (&value);
gtk_tree_model_get (model, &iter, 5, &lot, -1);
if (!lot)
continue; /* Lot has been deleted behind our back... */
@@ -949,11 +943,8 @@ get_selected_lots (GtkTreeModel *model,
{
GList **return_list = data;
GNCLot *lot;
GValue value = { 0 };
gtk_tree_model_get_value (model, iter, 5, &value);
lot = (GNCLot *) g_value_get_pointer (&value);
g_value_unset (&value);
gtk_tree_model_get (model, iter, 5, &lot, -1);
if (lot)
*return_list = g_list_insert_sorted (*return_list, lot, (GCompareFunc)gncOwnerLotsSortFunc);
@@ -1186,16 +1177,13 @@ static void print_date (G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
GtkTreeIter *iter,
G_GNUC_UNUSED gpointer data)
{
GValue value = { 0 };
time64 doc_date_time;
gchar *doc_date_str;
g_return_if_fail (cell && iter && tree_model);
gtk_tree_model_get_value (tree_model, iter, 0, &value);
doc_date_time = (time64) g_value_get_int64 (&value);
g_value_unset (&value);
gtk_tree_model_get (tree_model, iter, 0, &doc_date_time, -1);
doc_date_str = qof_print_date (doc_date_time);
g_object_set (G_OBJECT (cell), "text", doc_date_str, NULL);
g_free (doc_date_str);

View File

@@ -884,7 +884,7 @@ gbv_treeview_resized_cb (GtkWidget *widget, GtkAllocation *allocation,
if ((g_strcmp0 (name, "description") == 0) && (!priv->show_account_desc))
total_node = g_list_next (total_node);
if (gtk_tree_view_column_get_visible (tree_view_col))
if (gtk_tree_view_column_get_visible (tree_view_col) && total_node != NULL)
{
gint col_width = gtk_tree_view_column_get_width (tree_view_col);
GtkTreeViewColumn *totals_view_col = total_node->data;
@@ -1532,16 +1532,16 @@ gnc_budget_view_refresh (GncBudgetView *budget_view)
num_periods = gnc_budget_get_num_periods (priv->budget);
col_list = priv->period_col_list;
col_list = g_list_reverse (priv->period_col_list);
totals_col_list = g_list_reverse (priv->totals_col_list);
num_periods_visible = g_list_length (col_list);
/* Hide any unneeded extra columns */
while (num_periods_visible > num_periods)
{
col = GTK_TREE_VIEW_COLUMN((g_list_last (col_list))->data);
col = GTK_TREE_VIEW_COLUMN (col_list->data);
gtk_tree_view_remove_column (GTK_TREE_VIEW(priv->tree_view), col);
col_list = g_list_delete_link (col_list, g_list_last (col_list));
col_list = g_list_delete_link (col_list, col_list);
num_periods_visible--;
col = GTK_TREE_VIEW_COLUMN(totals_col_list->data);
@@ -1588,7 +1588,7 @@ gnc_budget_view_refresh (GncBudgetView *budget_view)
budget_col_source, budget_col_edited, renderer);
g_object_set_data (G_OBJECT(col), "budget_view", budget_view);
g_object_set_data (G_OBJECT(col), "period_num", GUINT_TO_POINTER(num_periods_visible));
col_list = g_list_append (col_list, col);
col_list = g_list_prepend (col_list, col);
// add some padding to the right of the numbers
gbv_renderer_add_padding (renderer);
@@ -1611,7 +1611,7 @@ gnc_budget_view_refresh (GncBudgetView *budget_view)
gdk_rgba_free (note_color);
gdk_rgba_free (note_color_selected);
priv->period_col_list = col_list;
priv->period_col_list = g_list_reverse (col_list);
priv->totals_col_list = g_list_reverse (totals_col_list);
if (priv->total_col == NULL)

View File

@@ -338,7 +338,6 @@ gnc_plugin_page_owner_tree_new (GncOwnerType owner_type)
GtkActionGroup *action_group;
GtkAction *action;
GValue gvalue = { 0 };
gint i;
g_return_val_if_fail( (owner_type != GNC_OWNER_UNDEFINED)
@@ -365,15 +364,14 @@ gnc_plugin_page_owner_tree_new (GncOwnerType owner_type)
/* Hide menu and toolbar items that are not relevant for the active owner list */
action_group = gnc_plugin_page_get_action_group(GNC_PLUGIN_PAGE(plugin_page));
g_value_init (&gvalue, G_TYPE_BOOLEAN);
for (i = 0; action_owners[i].action_name; i++)
{
action = gtk_action_group_get_action (action_group, action_owners[i].action_name);
g_value_set_boolean (&gvalue, (priv->owner_type == action_owners[i].owner_type) );
g_object_set_property (G_OBJECT(action), "visible", &gvalue);
g_object_set (G_OBJECT(action),
"visible", (priv->owner_type == action_owners[i].owner_type),
NULL);
}
g_value_unset (&gvalue);
LEAVE("new %s tree page %p", gncOwnerTypeToQofIdType(owner_type), plugin_page);
return GNC_PLUGIN_PAGE(plugin_page);
}

View File

@@ -56,6 +56,7 @@
#include "dialog-transfer.h"
#include "dialog-utils.h"
#include "assistant-stock-split.h"
#include "assistant-stock-transaction.h"
#include "gnc-component-manager.h"
#include "gnc-date.h"
#include "gnc-date-edit.h"
@@ -215,6 +216,9 @@ static void gnc_plugin_page_register_cmd_style_double_line (
static void gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
GncPluginPageRegister* plugin_page);
static void gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
GncPluginPageRegister* page);
static void gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
GncPluginPageRegister* plugin_page);
static void gnc_plugin_page_register_cmd_transfer (GtkAction* action,
@@ -478,6 +482,11 @@ static GtkActionEntry gnc_plugin_page_register_actions [] =
N_ ("Automatically clear individual transactions, so as to reach a certain cleared amount"),
G_CALLBACK (gnc_plugin_page_register_cmd_autoclear)
},
{
"ActionsStockAssistantAction", NULL, N_ ("Stock Ass_istant"), NULL,
N_ ("Stock Assistant"),
G_CALLBACK (gnc_plugin_page_register_cmd_stock_assistant)
},
{
"ActionsStockSplitAction", NULL, N_ ("Stoc_k Split..."), NULL,
N_ ("Record a stock split or a stock merger"),
@@ -611,6 +620,18 @@ static const gchar* view_style_actions[] =
NULL
};
static const gchar* actions_requiring_extra[] =
{
"ActionsStockAssistantAction",
NULL
};
static const gchar* actions_requiring_priced_account[] =
{
"ActionsStockAssistantAction",
NULL
};
/** Short labels for use on the toolbar buttons. */
static action_toolbar_labels toolbar_labels[] =
{
@@ -1239,6 +1260,12 @@ gnc_plugin_page_register_ui_initial_state (GncPluginPageRegister* page)
gnc_plugin_update_actions (action_group, actions_requiring_account,
"sensitive", is_readwrite && account != NULL);
gnc_plugin_update_actions (action_group, actions_requiring_extra,
"visible", gnc_prefs_is_extra_enabled ());
gnc_plugin_update_actions (action_group, actions_requiring_priced_account,
"sensitive", xaccAccountIsPriced (account));
/* Set "style" radio button */
ledger_type = gnc_ledger_display_type (priv->ledger);
gnc_plugin_update_actions (action_group, view_style_actions,
@@ -4511,6 +4538,23 @@ gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
LEAVE (" ");
}
static void
gnc_plugin_page_register_cmd_stock_assistant (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));
window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
account = gnc_plugin_page_register_get_account (page);
gnc_stock_transaction_assistant (GTK_WIDGET (window), account);
LEAVE (" ");
}
static void
gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
GncPluginPageRegister* page)

View File

@@ -8,6 +8,7 @@ set (gtkbuilder_SOURCES
assistant-loan.glade
assistant-qif-import.glade
assistant-stock-split.glade
assistant-stock-transaction.glade
assistant-xml-encoding.glade
business-options-gnome.glade
business-prefs.glade

View File

@@ -0,0 +1,941 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkAssistant" id="stock_transaction_assistant">
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="border-width">12</property>
<property name="title" translatable="yes">Stock Split Assistant</property>
<property name="window-position">center</property>
<property name="default-width">500</property>
<signal name="cancel" handler="stock_assistant_cancel" swapped="no"/>
<signal name="close" handler="stock_assistant_finish" swapped="no"/>
<signal name="prepare" handler="stock_assistant_prepare" swapped="no"/>
<child>
<object class="GtkLabel" id="intro_page_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">start</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="label" translatable="yes">This assistant will help you record a stock transaction. The transaction type (purchase, sale, dividend, distribution, return of capital, stock split) will determine the transaction splits involved in the transaction.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="page-type">intro</property>
<property name="title" translatable="yes">Stock Transaction Assistant</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="transaction_type_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">12</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="transaction_type_page_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">Select the type of stock activity that you wish to record. The available types depend on whether the current stock balance is positive, nil, or negative (i.e. when shorting stock). The type will determine the component splits.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=2 -->
<object class="GtkGrid" id="transaction_type_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="transaction_type_combo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Type</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="transaction_type_page_combobox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<items>
<item translatable="yes">a1</item>
<item translatable="yes">b2</item>
<item translatable="yes">c3</item>
</items>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="transaction_type_page_explanation">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Transaction Type</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="transaction_details_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">12</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="transaction_details_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">Select the type of transaction date and description for your records.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=2 -->
<object class="GtkGrid" id="transaction_details_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="transaction_date_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Date</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="transaction_description_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Description</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="transaction_description_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Transaction Details</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="stock_amount_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="stock_amount_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">Enter the date and the number of shares you gained or lost in the transaction.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=3 -->
<object class="GtkGrid" id="stock_amount_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="row-spacing">6</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="stock_amount_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Shares</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="prev_balance_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Previous Balance</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="prev_balance_amount">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">(Previous Balance)</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="next_balance_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Next Balance</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="next_balance_amount">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">(Next Balance)</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Stock Amount</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="stock_value_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="stock_value_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">Enter the value of the shares.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=3 -->
<object class="GtkGrid" id="stock_value_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="row-spacing">6</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="stock_price_amount">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">(autocalculated price)</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="stock_memo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Memo</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="stock_memo_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="stock_price_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Price</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="stock_value_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Stock Value</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Stock Value</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="cash_details_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="stock_cash_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">In this page, input the asset account, and the monetary amount received/spent. It may differ from the stock value from the last page, if there are broker fees associated with this transaction.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=3 -->
<object class="GtkGrid" id="cash_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="cash_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Amount</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="cash_memo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Memo</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">cash_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="cash_memo_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="invisible-char">●</property>
<property name="text" translatable="yes">Cash</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkBox" id="cash_amount_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="cash_account_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Cash Account</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">cash_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes" comments="Dialog title for the remains of a stock split">Cash</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="fees_details_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="stock_fees_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">In this page, input any broker fees incurred in this transaction. The fee may be capitalized into the asset account, or expensed into a broker fees account. Typically fees on purchase are capitalized, and fees on sales are expensed. If there are no fees involved in this transaction, it can be left blank.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=4 -->
<object class="GtkGrid" id="fees_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="fees_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Amount</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="fees_memo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Memo</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">fees_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="fees_memo_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="invisible-char">●</property>
<property name="text" translatable="yes">Fees</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkBox" id="fees_amount_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="fees_account_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Broker Fees</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">fees_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="capitalize_fees_checkbutton">
<property name="label" translatable="yes">Capitalize broker fees into stock account?</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes" comments="Broker Fees">Fees</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="dividend_details_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="stock_dividend_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">In this page, input any dividend income received in this transaction.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=3 -->
<object class="GtkGrid" id="dividend_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="dividend_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Amount</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="dividend_memo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Memo</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">dividend_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="dividend_memo_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="invisible-char">●</property>
<property name="text" translatable="yes">Dividend</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkBox" id="dividend_amount_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="dividend_account_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Dividend Account</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">dividend_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes" comments="Broker Fees">Dividend</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="capgains_details_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="stock_capgains_title">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">In this page, input any capital gains or losses incurred, and the associated income account. Capital gains are positive, and capital losses are negative.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=3 -->
<object class="GtkGrid" id="capgains_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="capgains_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Amount</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="capgains_memo_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">_Memo</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">capgains_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="capgains_memo_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="invisible-char">●</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkBox" id="capgains_amount_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="capgains_account_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Capital Gains Account</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">capgains_memo_entry</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Capital Gains</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkBox" id="finish_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="finish_page_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">A summary of splits is shown as follows. If the summary is correct, and there are no errors, please press "Apply". You may also press "Back" to review your choices, or "Cancel" to quit without making any changes. </property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="finish_scrolled">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkTreeView" id="transaction_view">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="transaction_view_selection">
<property name="mode">browse</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="finish_summary">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">summary of errors</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="page-type">confirm</property>
<property name="title" translatable="yes">Finish</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkBox">
<property name="can-focus">False</property>
</object>
</child>
</object>
</interface>

View File

@@ -305,6 +305,8 @@
<property name="model">liststore2</property>
<property name="has-entry">True</property>
<property name="entry-text-column">0</property>
<property name="has-tooltip">True</property>
<property name="tooltip-markup" translatable="yes">Select a category for the commodity or enter a new one. One might use investment categories like STOCKS and BONDS or exchange names like NASDAQ and LSE.</property>
<signal name="changed" handler="gnc_ui_commodity_changed_cb" swapped="no"/>
<child internal-child="entry">
<object class="GtkEntry" id="combobox-entry5">

View File

@@ -2078,8 +2078,8 @@ many months before the current month</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="has-tooltip">True</property>
<property name="tooltip-markup">Enable the UPDATE AND RECONCILE action in the transaction matcher. If enabled, a transaction whose best match's score is above the Auto-CLEAR threshold and has a different date or amount than the matching existing transaction will cause the existing transaction to be updated and cleared by default.</property>
<property name="tooltip-text" translatable="yes">Enable the UPDATE AND RECONCILE action in the transaction matcher. If enabled, a transaction whose best match's score is above the Auto-CLEAR threshold and has a different date or amount than the matching existing transaction will cause the existing transaction to be updated and cleared by default.</property>
<property name="tooltip-markup">Enable the UPDATE AND CLEAR action in the transaction matcher. If enabled, a transaction whose best match's score is above the Auto-CLEAR threshold and has a different date or amount than the matching existing transaction will cause the existing transaction to be updated and cleared by default.</property>
<property name="tooltip-text" translatable="yes">Enable the UPDATE AND CLEAR action in the transaction matcher. If enabled, a transaction whose best match's score is above the Auto-CLEAR threshold and has a different date or amount than the matching existing transaction will cause the existing transaction to be updated and cleared by default.</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>

View File

@@ -88,8 +88,8 @@ void aai_destroy_cb(GtkWidget *object, gpointer user_data);
gboolean aai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
void aai_wizard_page_prepare (GtkAssistant *assistant, gpointer user_data);
void aai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data);
void aai_page_prepare (GtkAssistant *assistant, gpointer user_data);
void aai_button_clicked_cb(GtkButton *button, gpointer user_data);
void aai_match_delete_button_clicked_cb(GtkButton *button, gpointer user_data);
#ifdef AQBANKING6
@@ -234,7 +234,7 @@ aai_destroy_cb(GtkWidget *object, gpointer user_data)
}
void
aai_wizard_page_prepare (GtkAssistant *assistant, gpointer user_data)
aai_page_prepare (GtkAssistant *assistant, gpointer user_data)
{
ABInitialInfo *info = user_data;
gint num = gtk_assistant_get_current_page (assistant);
@@ -250,7 +250,7 @@ aai_wizard_page_prepare (GtkAssistant *assistant, gpointer user_data)
}
void
aai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data)
aai_button_clicked_cb(GtkButton *button, gpointer user_data)
{
ABInitialInfo *info = user_data;
gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(info->window));
@@ -815,7 +815,7 @@ void aai_on_prepare (GtkAssistant *assistant, GtkWidget *page,
{
case 1:
/* Current page is wizard button page */
aai_wizard_page_prepare (assistant , user_data );
aai_page_prepare (assistant , user_data );
break;
case 2:
/* Current page is match page */

View File

@@ -12,7 +12,7 @@
<signal name="close" handler="aai_on_finish" swapped="no"/>
<signal name="prepare" handler="aai_on_prepare" swapped="no"/>
<child>
<!-- n-columns=1 n-rows=2 -->
<!-- n-columns=1 n-rows=4 -->
<object class="GtkGrid" id="start_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -20,7 +20,7 @@
<property name="margin-end">12</property>
<property name="border-width">12</property>
<child>
<object class="GtkLabel">
<object class="GtkLabel" id="start_label1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
@@ -32,11 +32,11 @@
</packing>
</child>
<child>
<object class="GtkLabel">
<object class="GtkLabel" id="start_label2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes" comments="See https://wiki.gnucash.org/wiki/AqBanking for the used terminology and replace the link, if a localized version exists.">The requirements for Online Banking vary between the different supported AqBanking backends, but usually you will need:
<property name="label" translatable="yes">The requirements for Online Banking vary between the different supported AqBanking backends, but usually you will need:
* Your bank needs to grant you online access. See on their website or ask their customer service for how to obtain it.
They should also tell you:
* Your user ID that identifies you to their server, often your base account number;
@@ -45,11 +45,7 @@ They should also tell you:
* Authentication methods vary by backend and chosen method:
* FinTS PIN/TAN: Some methods require a specific gadget like a card reader or a mobile;
* FinTS HBCI: You have to exchange the public parts of asymmetric keys with your bank ("Ini-Letter").
* PayPal: registered email address, password, API signature;
See https://wiki.gnucash.org/wiki/AqBanking for more details.
Note: NO WARRANTIES FOR ANYTHING. Some banks run a poorly implemented Online Banking server. You should not rely on time-critical transfers through Online Banking, because sometimes the bank does not give you correct feedback when a transfer is rejected.</property>
* PayPal: registered email address, password, API signature;</property>
<property name="wrap">True</property>
</object>
<packing>
@@ -57,6 +53,36 @@ Note: NO WARRANTIES FOR ANYTHING. Some banks run a poorly implemented Online Ban
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="start_markup_label3">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="halign">start</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes" comments="See https://wiki.gnucash.org/wiki/AqBanking for the used terminology and replace the link, if a localized version exists.">See &lt;a href="https://wiki.gnucash.org/wiki/AqBanking"&gt;https://wiki.gnucash.org/wiki/AqBanking&lt;/a&gt; for more details</property>
<property name="use-markup">True</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="start_label4">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Note: NO WARRANTIES FOR ANYTHING. Some banks run a poorly implemented Online Banking server. You should not rely on time-critical transfers through Online Banking, because sometimes the bank does not give you correct feedback when a transfer is rejected.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
</object>
<packing>
<property name="page-type">intro</property>
@@ -66,21 +92,69 @@ Note: NO WARRANTIES FOR ANYTHING. Some banks run a poorly implemented Online Ban
</packing>
</child>
<child>
<object class="GtkBox" id="wizard_page">
<object class="GtkBox" id="aqbanking_page">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="border-width">12</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="wizard_label">
<object class="GtkLabel" id="aqbanking_label1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">The Setup of your Online Banking connection is handled by the external program "AqBanking Setup Wizard".
You have to set up at least one connection before you can continue.
<property name="halign">start</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">The Setup of your Online Banking connection is handled by the external program "AqBanking Setup".</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="aqbanking_label2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">That means:
* It ignores GnuCash's preferences like "Close log window when finished".
* To report issues read</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="aqbanking_markup_label3">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-bottom">6</property>
<property name="label" translatable="yes">&lt;a href="https://aquamaniac.de/rdm/projects/aqbanking/wiki/Bugreports/"&gt;https://aquamaniac.de/rdm/projects/aqbanking/wiki/Bugreports/&lt;/a&gt;</property>
<property name="use-markup">True</property>
<property name="wrap">True</property>
<property name="wrap-mode">char</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="aqbanking_label4">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">You have to set up at least one connection before you can continue.
Please press the button below to start it.</property>
<property name="wrap">True</property>
@@ -88,29 +162,28 @@ Please press the button below to start it.</property>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ab_wizard_button">
<property name="label" translatable="yes">_Start AqBanking Wizard</property>
<object class="GtkButton" id="ab_assistant_button">
<property name="label" translatable="yes">_Start AqBanking Setup</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="halign">center</property>
<property name="use-underline">True</property>
<signal name="clicked" handler="aai_wizard_button_clicked_cb" swapped="no"/>
<signal name="clicked" handler="aai_button_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">6</property>
</packing>
</child>
</object>
<packing>
<property name="page-type">intro</property>
<property name="title" translatable="yes">Start Online Banking Wizard</property>
<property name="title" translatable="yes">Start Online Banking Setup</property>
<property name="complete">True</property>
<property name="has-padding">False</property>
</packing>

View File

@@ -74,10 +74,6 @@ void gnc_bi_import_gui_option5_cb (GtkWidget *widget, gpointer data);
void gnc_bi_import_gui_open_mode_cb (GtkWidget *widget, gpointer data);
void gnc_import_gui_type_cb (GtkWidget *widget, gpointer data);
// utils
static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
static void gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg);
#define UNUSED_VAR __attribute__ ((unused))
static QofLogModule UNUSED_VAR log_module = G_LOG_DOMAIN; //G_LOG_BUSINESS;
@@ -392,114 +388,3 @@ void gnc_import_gui_type_cb (GtkWidget *widget, gpointer data)
}
/********************************************************************\
* gnc_input_dialog *
* simple convenience dialog to get a single value from the user *
* user may choose between "Ok" and "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* default_input - will be displayed as default input *
* Return: the input (text) the user entered, if pressed "Ok" *
* NULL, if pressed "Cancel" *
\********************************************************************/
static gchar *
gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
{
GtkWidget *dialog, *label, *content_area;
gint result;
GtkWidget *view;
GtkTextBuffer *buffer;
gchar *user_input = NULL;
GtkTextIter start, end;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
_("_Cancel"), GTK_RESPONSE_REJECT,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a label
label = gtk_label_new (msg);
gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, default_input, -1);
gtk_box_pack_start(GTK_BOX(content_area), view, TRUE, TRUE, 0);
// run the dialog
gtk_widget_show_all (dialog);
result = gtk_dialog_run (GTK_DIALOG (dialog));
if (result == GTK_RESPONSE_REJECT)
user_input = 0;
else
{
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
user_input = gtk_text_buffer_get_text (buffer,
&start, &end, FALSE);
}
gtk_widget_destroy (dialog);
return user_input;
}
/********************************************************************\
* gnc_info2_dialog *
* displays an information dialog box (with scrollable text area) *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* Return: none *
\********************************************************************/
static void
gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg)
{
GtkWidget *dialog, *scrolledwindow, *content_area;
GtkWidget *view;
GtkTextBuffer *buffer;
gint width, height;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a scroll area
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start(GTK_BOX(content_area), scrolledwindow, TRUE, TRUE, 0);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, msg, -1);
gtk_container_add (GTK_CONTAINER (scrolledwindow), view);
// run the dialog
if (parent)
{
gtk_window_get_size (GTK_WINDOW(parent), &width, &height);
gtk_window_set_default_size (GTK_WINDOW(dialog), width, height);
}
gtk_widget_show_all (dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}

View File

@@ -65,8 +65,6 @@ void csv_import_hrows_cb (GtkWidget *spin, gpointer user_data );
void csv_import_file_chooser_file_activated_cb (GtkFileChooser *chooser, CsvImportInfo *info);
void csv_import_file_chooser_selection_changed_cb (GtkFileChooser *chooser, CsvImportInfo *info);
static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
static const gchar *finish_tree_string = N_(
"The accounts will be imported from the file '%s' when you click 'Apply'.\n\n"
"You can verify your selections by clicking on 'Back' or 'Cancel' to Abort Import.\n");
@@ -346,74 +344,6 @@ void load_settings (CsvImportInfo *info)
/* =============================================================== */
/********************************************************************\
* gnc_input_dialog *
* simple convenience dialog to get a single value from the user *
* user may choose between "Ok" and "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* default_input - will be displayed as default input *
* Return: the input (text) the user entered, if pressed "Ok" *
* NULL, if pressed "Cancel" *
\********************************************************************/
static gchar *
gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
{
GtkWidget *dialog, *label, *content_area;
gint result;
GtkWidget *view;
GtkTextBuffer *buffer;
gchar *user_input;
GtkTextIter start, end;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW(parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
_("_Cancel"), GTK_RESPONSE_REJECT,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG(dialog));
// add a label
label = gtk_label_new (msg);
gtk_container_add (GTK_CONTAINER(content_area), label);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(view), GTK_WRAP_WORD_CHAR);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(view));
gtk_text_buffer_set_text (buffer, default_input, -1);
gtk_container_add (GTK_CONTAINER(content_area), view);
// run the dialog
gtk_widget_show_all (dialog);
result = gtk_dialog_run (GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_REJECT)
user_input = 0;
else
{
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
user_input = gtk_text_buffer_get_text (buffer,
&start, &end, FALSE);
}
gtk_widget_destroy (dialog);
return user_input;
}
/* =============================================================== */
/*******************************************************
* Assistant page prepare functions
*******************************************************/

View File

@@ -68,11 +68,6 @@ void gnc_customer_import_gui_option4_cb (GtkWidget *widget, gpointer data);
void gnc_customer_import_gui_option5_cb (GtkWidget *widget, gpointer data);
void gnc_customer_import_gui_type_cb (GtkWidget *widget, gpointer data);
// utils
static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
static void gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg);
CustomerImportGui *
gnc_plugin_customer_import_showGUI(GtkWindow *parent)
{
@@ -353,115 +348,3 @@ void gnc_customer_import_gui_type_cb (GtkWidget *widget, gpointer data)
//printf ("TYPE set to, %s\n",gui->type); // DEBUG
}
/********************************************************************\
* gnc_input_dialog *
* simple convenience dialog to get a single value from the user *
* user may choose between "Ok" and "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* default_input - will be displayed as default input *
* Return: the input (text) the user entered, if pressed "Ok" *
* NULL, if pressed "Cancel" *
\********************************************************************/
static gchar *
gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
{
GtkWidget *dialog, *label, *content_area;
gint result;
GtkWidget *view;
GtkTextBuffer *buffer;
gchar *user_input;
GtkTextIter start, end;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
_("_Cancel"), GTK_RESPONSE_REJECT,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a label
label = gtk_label_new (msg);
gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, default_input, -1);
gtk_box_pack_start(GTK_BOX(content_area), view, TRUE, TRUE, 0);
// run the dialog
gtk_widget_show_all (dialog);
result = gtk_dialog_run (GTK_DIALOG (dialog));
if (result == GTK_RESPONSE_REJECT)
user_input = 0;
else
{
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
user_input = gtk_text_buffer_get_text (buffer,
&start, &end, FALSE);
}
gtk_widget_destroy (dialog);
return user_input;
}
/********************************************************************\
* gnc_info2_dialog *
* displays an information dialog box (with scrollable text area) *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent window or NULL *
* title - the title of the dialog *
* msg - the message to display *
* Return: none *
\********************************************************************/
static void
gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg)
{
GtkWidget *dialog, *scrolledwindow, *content_area;
GtkWidget *view;
GtkTextBuffer *buffer;
gint width, height;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// add a scroll area
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start(GTK_BOX(content_area), scrolledwindow, TRUE, TRUE, 0);
// add a textview
view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, msg, -1);
gtk_container_add (GTK_CONTAINER (scrolledwindow), view);
// run the dialog
if (parent)
{
gtk_window_get_size (GTK_WINDOW(parent), &width, &height);
gtk_window_set_default_size (GTK_WINDOW(dialog), width, height);
}
gtk_widget_show_all (dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}

View File

@@ -130,7 +130,8 @@ static void gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *
GNCImportMainMatcher *info);
static void gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info);
GNCImportMainMatcher *info,
gboolean show_edit_actions);
static gboolean gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info);
@@ -884,6 +885,119 @@ gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
LEAVE("");
}
typedef enum
{
DESCRIPTION,
MEMO,
NOTES,
} edit_field;
static void
gnc_gen_trans_edit_fields (GtkMenuItem *menuitem, GNCImportMainMatcher *info,
edit_field field)
{
GtkTreeView *treeview;
GtkTreeSelection *selection;
GtkTreeModel *model;
GList *selected_rows;
GList *refs = NULL;
GtkTreeStore* store;
GNCImportTransInfo *trans_info;
Transaction* trans;
GtkTreeIter iter;
g_return_if_fail (info != NULL);
ENTER("assign_transfer_account_to_selection_cb");
treeview = GTK_TREE_VIEW(info->view);
model = gtk_tree_view_get_model (treeview);
store = GTK_TREE_STORE (model);
selection = gtk_tree_view_get_selection (treeview);
selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
if (!selected_rows)
{
LEAVE ("No selected rows");
return;
}
if (selected_rows->next)
{
LEAVE ("User selected multiple rows, not supported");
return;
}
g_return_if_fail (gtk_tree_model_get_iter (model, &iter,
selected_rows->data));
gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA,
&trans_info, -1);
trans = gnc_import_TransInfo_get_trans (trans_info);
switch (field)
{
case DESCRIPTION:
{
char* new_field =
gnc_input_dialog_with_entry(info->main_widget, "",
_("Enter new Description"),
xaccTransGetDescription (trans));
if (!new_field) break;
xaccTransSetDescription (trans, new_field);
gtk_tree_store_set (store, &iter, DOWNLOADED_COL_DESCRIPTION,
new_field, -1);
g_free (new_field);
break;
}
case MEMO:
{
Split *first_split =
gnc_import_TransInfo_get_fsplit (trans_info);
char *new_field =
gnc_input_dialog_with_entry(info->main_widget, "",
_("Enter new Memo"),
xaccSplitGetMemo (first_split));
if (!new_field) break;
xaccSplitSetMemo (first_split, new_field);
gtk_tree_store_set (store, &iter,
DOWNLOADED_COL_MEMO, new_field, -1);
g_free (new_field);
break;
}
case NOTES:
{
char* new_field =
gnc_input_dialog_with_entry(info->main_widget, "",
_("Enter new Notes"),
xaccTransGetNotes (trans));
if (!new_field) break;
xaccTransSetNotes (trans, new_field);
g_free (new_field);
break;
}
}
g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
LEAVE("");
}
static void
gnc_gen_trans_edit_description_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
{
gnc_gen_trans_edit_fields (menuitem, info, DESCRIPTION);
}
static void
gnc_gen_trans_edit_memo_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
{
gnc_gen_trans_edit_fields (menuitem, info, MEMO);
}
static void
gnc_gen_trans_edit_notes_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
{
gnc_gen_trans_edit_fields (menuitem, info, NOTES);
}
static void
gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
GtkTreePath *path,
@@ -971,7 +1085,8 @@ gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
static void
gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info)
GNCImportMainMatcher *info,
gboolean show_edit_actions)
{
GtkWidget *menu, *menuitem;
GdkEventButton *event_button;
@@ -986,6 +1101,33 @@ gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
info);
DEBUG("Callback to assign destination account to selection connected");
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
if (show_edit_actions)
{
menuitem = gtk_menu_item_new_with_label (
_("Edit description."));
g_signal_connect (menuitem, "activate",
G_CALLBACK (gnc_gen_trans_edit_description_cb),
info);
DEBUG("Callback to edit description");
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
menuitem = gtk_menu_item_new_with_label (
_("Edit memo."));
g_signal_connect (menuitem, "activate",
G_CALLBACK (gnc_gen_trans_edit_memo_cb),
info);
DEBUG("Callback to edit memo");
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
menuitem = gtk_menu_item_new_with_label (
_("Edit notes."));
g_signal_connect (menuitem, "activate",
G_CALLBACK (gnc_gen_trans_edit_notes_cb),
info);
DEBUG("Callback to edit notes");
gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
}
gtk_widget_show_all (menu);
event_button = (GdkEventButton *) event;
/* Note: event can be NULL here when called from view_onPopupMenu; */
@@ -1017,14 +1159,14 @@ gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
selection = gtk_tree_view_get_selection (treeview);
count = gtk_tree_selection_count_selected_rows (selection);
if (count > 1)
gnc_gen_trans_view_popup_menu (treeview, event, info);
gnc_gen_trans_view_popup_menu (treeview, event, info, FALSE);
else if (count > 0)
{
GList* selected;
GtkTreeModel *model;
selected = gtk_tree_selection_get_selected_rows (selection, &model);
if (get_action_for_path (selected->data, model) == GNCImport_ADD)
gnc_gen_trans_view_popup_menu (treeview, event, info);
gnc_gen_trans_view_popup_menu (treeview, event, info, TRUE);
g_list_free_full (selected, (GDestroyNotify)gtk_tree_path_free);
}
LEAVE("return TRUE");
@@ -1045,7 +1187,7 @@ gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
selection = gtk_tree_view_get_selection (treeview);
if (gtk_tree_selection_count_selected_rows (selection) > 0)
{
gnc_gen_trans_view_popup_menu (treeview, NULL, info);
gnc_gen_trans_view_popup_menu (treeview, NULL, info, TRUE);
LEAVE ("TRUE");
return TRUE;
}

View File

@@ -614,11 +614,21 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data, void *user_data)
/* set tran-num and/or split-action per book option */
if (data.check_number_valid)
{
gnc_set_num_action(transaction, split, data.check_number, NULL);
/* SQL will correctly interpret the string "null", but
* the transaction num field is declared to be
* non-null so substitute the empty string.
*/
const char *num_value =
strcasecmp (data.check_number, "null") == 0 ? "" :
data.check_number;
gnc_set_num_action(transaction, split, num_value, NULL);
}
else if (data.reference_number_valid)
{
gnc_set_num_action(transaction, split, data.reference_number, NULL);
const char *num_value =
strcasecmp (data.reference_number, "null") == 0 ? "" :
data.check_number;
gnc_set_num_action(transaction, split, num_value, NULL);
}
/* Also put the ofx transaction's memo in the
* split's memo field */

View File

@@ -736,58 +736,29 @@
;; compatible with the QIF type?
(and (string=? s (caddr elt))
(not (and (string? qif-type)
(string=? GNC_COMMODITY_NS_MUTUAL
(string=? (GNC-COMMODITY-NS-NONCURRENCY)
(cadr elt))
(or (string-ci=? qif-type "stock")
(string-ci=? qif-type "etf"))))))
prefs)
#f)))
(cond
;; If a preferences match was found, use its namespace.
(pref-match
(cadr pref-match))
;; Guess NYSE for symbols of 1-3 characters.
((< l 4)
GNC_COMMODITY_NS_NYSE)
;; Guess NYSE for symbols of 1-3 characters
;; followed by a dot and 1-2 characters.
((and d
(< l 7)
(< 0 d 4)
(<= 2 (- l d) 3))
GNC_COMMODITY_NS_NYSE)
;; Guess NASDAQ for symbols of 4 characters.
((= l 4)
GNC_COMMODITY_NS_NASDAQ)
;; Otherwise it's probably a fund.
(else
GNC_COMMODITY_NS_MUTUAL)))
;; If a preferences match was found, use its namespace.
(if pref-match (cadr pref-match))
;; There's no symbol. Default to a fund.
GNC_COMMODITY_NS_MUTUAL))
(GNC-COMMODITY-NS-NONCURRENCY))))
;; Was a QIF type given?
(if (string? qif-type)
;; Yes. We might be able to definitely determine the namespace.
(cond
;; Mutual fund
((string-ci=? qif-type "mutual fund")
GNC_COMMODITY_NS_MUTUAL)
;; Index
((string-ci=? qif-type "index")
;; This QIF type must be wrong; indexes aren't tradable!
GNC_COMMODITY_NS_MUTUAL)
(else
(guess-by-symbol qif-symbol)))
(if (or
(string-ci=? qif-type "mutual fund")
(string-ci=? qif-type "index"))
(GNC-COMMODITY-NS-NONCURRENCY)
(guess-by-symbol qif-symbol)))
;; No QIF type was given, so guess a
;; default namespace by symbol alone.
(guess-by-symbol qif-symbol)))
(guess-by-symbol qif-symbol))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -270,7 +270,7 @@
(default-currency
(gnc-commodity-table-find-full
(gnc-commodity-table-get-table (gnc-get-current-book))
GNC_COMMODITY_NS_CURRENCY default-currency-name))
(GNC-COMMODITY-NS-CURRENCY) default-currency-name))
(sorted-accounts-list '())
(markable-xtns '())
(sorted-qif-files-list (sort qif-files-list

View File

@@ -348,7 +348,7 @@ gnc_entry_ledger_get_taxable_value (VirtualLocation virt_loc,
const char *valstr =
get_taxable_entry (virt_loc, translate, conditionally_changed,
user_data);
if (valstr && *valstr == 'X')
if (valstr && *valstr != ' ')
return TRUE;
}
return FALSE;

View File

@@ -641,12 +641,9 @@ static Split *
gnc_find_split_in_trans_by_memo (Transaction *trans, const char *memo,
gboolean unit_price)
{
int i = 0;
Split *split;
while ((split = xaccTransGetSplit(trans, i)) != NULL)
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
{
i++;
Split *split = n->data;
if (unit_price)
{
gnc_numeric price = xaccSplitGetSharePrice (split);
@@ -899,21 +896,19 @@ gnc_split_register_auto_completion (SplitRegister *reg,
gnc_split_register_get_default_account (reg);
gnc_commodity *trans_cmdty = xaccTransGetCurrency(trans);
gnc_commodity *acct_cmdty = xaccAccountGetCommodity(default_account);
Split *s;
int i = 0;
if (gnc_commodity_is_currency(acct_cmdty) &&
!gnc_commodity_equal(trans_cmdty, acct_cmdty))
xaccTransSetCurrency(trans, acct_cmdty);
while ((s = xaccTransGetSplit(trans, i)) != NULL)
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
{
Split *s = n->data;
if (default_account == xaccSplitGetAccount(s))
{
blank_split = s;
info->blank_split_guid = *xaccSplitGetGUID(blank_split);
break;
}
i++;
}
}

View File

@@ -239,9 +239,6 @@ _find_split_with_parent_txn (gconstpointer a, gconstpointer b)
static void add_quickfill_completions (TableLayout* layout, Transaction* trans,
Split* split, gboolean has_last_num)
{
Split* s;
int i = 0;
gnc_quickfill_cell_add_completion (
(QuickFillCell*) gnc_table_layout_get_cell (layout, DESC_CELL),
xaccTransGetDescription (trans));
@@ -255,12 +252,12 @@ static void add_quickfill_completions (TableLayout* layout, Transaction* trans,
(NumCell*) gnc_table_layout_get_cell (layout, NUM_CELL),
gnc_get_num_action (trans, split));
while ((s = xaccTransGetSplit (trans, i)) != NULL)
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
{
Split *s = n->data;
gnc_quickfill_cell_add_completion (
(QuickFillCell*) gnc_table_layout_get_cell (layout, MEMO_CELL),
xaccSplitGetMemo (s));
i++;
}
}

View File

@@ -1114,14 +1114,13 @@ gnc_split_register_change_blank_split_ref (SplitRegister* reg, Split* split)
gnc_get_current_book ());
Split* pref_split = NULL; // has the same account as incoming split
Split* other_split = NULL; // other split
Split* s;
Account* blank_split_account = xaccSplitGetAccount (current_blank_split);
Transaction* trans = xaccSplitGetParent (split);
int i = 0;
// loop through splitlist looking for splits other than the blank_split
while ((s = xaccTransGetSplit (trans, i)) != NULL)
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
{
Split *s = n->data;
if (s != current_blank_split)
{
if (blank_split_account == xaccSplitGetAccount (s))
@@ -1129,7 +1128,6 @@ gnc_split_register_change_blank_split_ref (SplitRegister* reg, Split* split)
else
other_split = s; // any other split
}
i++;
}
// now change the saved blank split reference
if (pref_split != NULL)

View File

@@ -51,7 +51,7 @@ gnc_checkbox_cell_set_value (BasicCell *_cell, const char *value)
CheckboxCell *cell = (CheckboxCell *) _cell;
gboolean flag = FALSE;
if (value && *value == 'X')
if (value && *value != ' ')
flag = TRUE;
gnc_checkbox_cell_set_flag (cell, flag);

View File

@@ -1362,12 +1362,21 @@ gnucash_sheet_button_release_event (GtkWidget *widget, GdkEventButton *event)
return TRUE;
}
static float
clamp_scrollable_value (float value, GtkAdjustment* adj)
{
float lower = gtk_adjustment_get_lower (adj);
float upper = gtk_adjustment_get_upper (adj);
float size = gtk_adjustment_get_page_size (adj);
return CLAMP(value, lower, upper - size);
}
static gboolean
gnucash_scroll_event (GtkWidget *widget, GdkEventScroll *event)
{
GnucashSheet *sheet;
GtkAdjustment *vadj;
gfloat v_value;
gfloat h_value, v_value;
g_return_val_if_fail (widget != NULL, TRUE);
g_return_val_if_fail (GNUCASH_IS_SHEET(widget), TRUE);
@@ -1386,17 +1395,16 @@ gnucash_scroll_event (GtkWidget *widget, GdkEventScroll *event)
v_value += gtk_adjustment_get_step_increment (vadj);
break;
case GDK_SCROLL_SMOOTH:
if (event->delta_y < 0)
v_value -= gtk_adjustment_get_step_increment (vadj);
if (event->delta_y > 0)
v_value += gtk_adjustment_get_step_increment (vadj);
h_value = gtk_adjustment_get_value (sheet->hadj);
h_value += event->delta_x;
h_value = clamp_scrollable_value (h_value, sheet->hadj);
gtk_adjustment_set_value (sheet->hadj, h_value);
v_value += event->delta_y;
break;
default:
return FALSE;
}
v_value = CLAMP(v_value, gtk_adjustment_get_lower (vadj),
gtk_adjustment_get_upper (vadj) - gtk_adjustment_get_page_size (vadj));
v_value = clamp_scrollable_value (v_value, vadj);
gtk_adjustment_set_value (vadj, v_value);
if (event->delta_y == 0)

View File

@@ -51,6 +51,8 @@
(export gnc:html-chart-set-currency-iso!)
(export gnc:html-chart-currency-symbol)
(export gnc:html-chart-set-currency-symbol!)
(export gnc:html-chart-format-style)
(export gnc:html-chart-set-format-style!)
(export gnc:html-chart-render)
(export gnc:html-chart-set-custom-x-axis-ticks?!)
(export gnc:html-chart-set-title!)
@@ -144,13 +146,14 @@
(define-record-type <html-chart>
(make-html-chart width height chart-options currency-iso
currency-symbol custom-x-axis-ticks? custom-y-axis-ticks?)
currency-symbol format-style custom-x-axis-ticks? custom-y-axis-ticks?)
html-chart?
(width html-chart-width html-chart-set-width)
(height html-chart-height html-chart-set-height)
(chart-options html-chart-chart-options html-chart-set-chart-options)
(currency-iso html-chart-currency-iso html-chart-set-currency-iso)
(currency-symbol html-chart-currency-symbol html-chart-set-currency-symbol)
(format-style html-chart-format-style html-chart-set-format-style)
(custom-x-axis-ticks? html-chart-custom-x-axis-ticks?
html-chart-set-custom-x-axis-ticks?)
(custom-y-axis-ticks? html-chart-custom-y-axis-ticks?
@@ -166,6 +169,8 @@
(define gnc:html-chart-set-currency-iso! html-chart-set-currency-iso)
(define gnc:html-chart-currency-symbol html-chart-currency-symbol)
(define gnc:html-chart-set-currency-symbol! html-chart-set-currency-symbol)
(define gnc:html-chart-format-style html-chart-format-style)
(define gnc:html-chart-set-format-style! html-chart-set-format-style)
(define gnc:html-chart-custom-x-axis-ticks? html-chart-custom-x-axis-ticks?)
(define gnc:html-chart-set-custom-x-axis-ticks?! html-chart-set-custom-x-axis-ticks?)
(define gnc:html-chart-custom-y-axis-ticks? html-chart-custom-y-axis-ticks?)
@@ -254,6 +259,7 @@
(cons 'text ""))))))
"XXX" ;currency-iso
"\u00A4" ;currency-symbol
"currency";format-style
#t ;custom x-axis ticks?
#t ;custom y-axis ticks?
))
@@ -341,10 +347,10 @@
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
var toLocaleStringSupportsOptions = (typeof Intl == 'object' && Intl && typeof Intl.NumberFormat == 'function');
// format a number e.g. 2.5 into monetary e.g. \"$2.50\"
// format a number e.g. 2.5 into monetary e.g. \"$2.50\" or other style formsty
function numformat(amount) {
if (toLocaleStringSupportsOptions) {
return amount.toLocaleString(undefined, {style:'currency', currency:curriso});
return amount.toLocaleString(undefined, {style:formsty, currency:curriso});
} else {
return currsym + amount.toLocaleString();
}
@@ -457,6 +463,7 @@ document.getElementById(chartid).onclick = function(evt) {
(push (format #f "<script id='script-~a'>\n" id))
(push (format #f "var curriso = ~s;\n" (gnc:html-chart-currency-iso chart)))
(push (format #f "var currsym = ~s;\n" (gnc:html-chart-currency-symbol chart)))
(push (format #f "var formsty = ~s;\n" (gnc:html-chart-format-style chart)))
(push (format #f "var chartid = ~s;\n" id))
(push (format #f "var jumpid = 'jump-~a';\n" id))
(push (format #f "var loadstring = ~s;\n" (G_ "Load")))

View File

@@ -382,7 +382,7 @@
(define unreserved-chars-rfc3986
(char-set-union
(string->char-set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
(string->char-set ":/?#[]@") ;gen-delims
(string->char-set ":/?[]@") ;gen-delims
(string->char-set "-._~")))
;;path must be absolute. On Windows an absolute path begins with a

View File

@@ -34,6 +34,10 @@
(use-modules (gnucash app-utils))
(use-modules (gnucash report))
;; useful functions
(define (safe-/ x y)
(if (zero? y) 0 (/ x y)))
;; The option names are defined here to 1. save typing and 2. avoid
;; spelling errors. The *reportnames* are defined here (and not only
;; once at the very end) because I need them to define the "other"
@@ -176,6 +180,15 @@ developing over time"))
"e" (N_ "Display a table of the selected data.")
#f))
;; contributed by https://github.com/exxus
;; https://github.com/Gnucash/gnucash/pull/1272
(add-option
(gnc:make-simple-boolean-option
gnc:pagename-display
(N_ "Percentage chart")
"e1" (N_ "Display account contributions as a percentage of the total value for the period.")
#f))
(gnc:options-add-plot-size!
options gnc:pagename-display
optname-plot-width optname-plot-height "f" (cons 'percent 100.0) (cons 'percent 100.0))
@@ -246,6 +259,7 @@ developing over time"))
(work-to-do 0)
(all-data #f)
(show-table? (get-option gnc:pagename-display (N_ "Show table")))
(ratio-chart? (get-option gnc:pagename-display (N_ "Percentage chart")))
(document (gnc:make-html-document))
(chart (gnc:make-html-chart))
(topl-accounts (gnc:filter-accountlist-type
@@ -328,26 +342,35 @@ developing over time"))
;; created.
(other-anchor ""))
;; Converts a commodity-collector into gnc-monetary in the report's
;; currency using the exchange-fn calculated above. Returns a gnc-monetary
;; Converts a commodity-collector into amount in the report's
;; currency using the exchange-fn calculated above. Returns an amount
;; multiplied by the averaging-multiplier (smaller than one; multiplication
;; instead of division to avoid division-by-zero issues) in case
;; the user wants to see the amounts averaged over some value.
(define (collector->monetary c date)
(gnc:make-gnc-monetary
report-currency
(* averaging-multiplier
(gnc:gnc-monetary-amount
(gnc:sum-collector-commodity
c report-currency
(lambda (a b) (exchange-fn a b date)))))))
(define (collector->report-currency-amount c date)
(* averaging-multiplier
(gnc:gnc-monetary-amount
(gnc:sum-collector-commodity
c report-currency
(lambda (a b) (exchange-fn a b date))))))
(define acct->name
(if show-fullname? gnc-account-get-full-name xaccAccountGetName))
(define (all-zeros data)
(cond
((gnc:gnc-monetary? data) (zero? (gnc:gnc-monetary-amount data)))
((number? data) (zero? data))
((pair? data) (every all-zeros data))
(else (error 'huh))))
(define (get-negative-accounts data)
(let lp ((data data) (retval #f))
(match data
(() retval)
(((acc (? (cut any negative? <>))) . rest)
(lp rest (cons (acct->name acc) (or retval '()))))
((_ . rest) (lp rest retval)))))
;; this is an alist of account-balances
;; (list (list acc0 bal0 bal1 bal2 ...)
;; (list acc1 bal0 bal1 bal2 ...)
@@ -396,11 +419,11 @@ developing over time"))
(loop (cdr list-of-mon-collectors)
(cdr dates-list)
(cons (if do-intervals?
(collector->monetary
(collector->report-currency-amount
(gnc:collector- (cadr list-of-mon-collectors)
(car list-of-mon-collectors))
(cadr dates-list))
(collector->monetary
(collector->report-currency-amount
(car list-of-mon-collectors)
(car dates-list)))
result))))))
@@ -462,26 +485,21 @@ developing over time"))
;; Sort the account list according to the account code field.
(set! all-data
(sort
(filter (lambda (l)
(not (zero? (gnc:gnc-monetary-amount
(apply gnc:monetary+ (cadr l))))))
(filter (lambda (l) (not (zero? (apply + (cadr l)))))
(traverse-accounts 1 topl-accounts))
(case sort-method
((alphabetical)
(lambda (a b)
(if show-fullname?
(gnc:string-locale<? (gnc-account-get-full-name (car a))
(gnc-account-get-full-name (car b)))
(gnc:string-locale<? (xaccAccountGetName (car a))
(xaccAccountGetName (car b))))))
(gnc:string-locale<? (acct->name (car a))
(acct->name (car b)))))
((acct-code)
(lambda (a b)
(gnc:string-locale<? (xaccAccountGetCode (car a))
(xaccAccountGetCode (car b)))))
((amount)
(lambda (a b)
(> (gnc:gnc-monetary-amount (apply gnc:monetary+ (cadr a)))
(gnc:gnc-monetary-amount (apply gnc:monetary+ (cadr b)))))))))
(> (apply + (cadr a))
(apply + (cadr b))))))))
(cond
((or (null? all-data) (all-zeros (map cadr all-data)))
@@ -490,11 +508,28 @@ developing over time"))
(gnc:html-make-empty-data-warning
report-title (gnc:report-id report-obj))))
((and ratio-chart? (get-negative-accounts all-data)) =>
(lambda (neg-accounts)
(gnc:html-document-add-object!
document
(gnc:html-make-generic-warning
report-title (gnc:report-id report-obj)
"Negative amounts detected"
"Charting ratios cannot occur on accounts with negative balances. \
Please deselect the accounts with negative balances."))
(gnc:html-document-add-object!
document (gnc:make-html-text (gnc:html-markup-ul neg-accounts)))))
(else
(let* ((dates-list (if do-intervals?
(list-head dates-list (1- (length dates-list)))
dates-list))
(date-string-list (map qof-print-date dates-list)))
(date-string-list (map qof-print-date dates-list))
(list-of-rows (apply zip (map cadr all-data)))
;; total amounts
(row-totals (map (cut fold + 0 <>) list-of-rows)))
;; Set chart title, subtitle etc.
(gnc:html-chart-set-type!
@@ -514,7 +549,8 @@ developing over time"))
(gnc:html-chart-set-data-labels! chart date-string-list)
(gnc:html-chart-set-y-axis-label!
chart (gnc-commodity-get-mnemonic report-currency))
chart (if ratio-chart? "Ratio"
(gnc-commodity-get-mnemonic report-currency)))
;; If we have too many categories, we sum them into a new
;; 'other' category and add a link to a new report with just
@@ -523,7 +559,7 @@ developing over time"))
(let* ((start (take all-data (1- max-slices)))
(finish (drop all-data (1- max-slices)))
(other-sum (map
(lambda (l) (apply gnc:monetary+ l))
(lambda (l) (apply + l))
(apply zip (map cadr finish)))))
(set! all-data
(append start
@@ -549,9 +585,8 @@ developing over time"))
(let* ((acct (car series))
(label (cond
((string? acct) (car series))
(show-fullname? (gnc-account-get-full-name acct))
(else (xaccAccountGetName acct))))
(amounts (map gnc:gnc-monetary-amount (cadr series)))
(else (acct->name acct))))
(amounts (cadr series))
(stack (if stacked? "default" (number->string stack)))
(fill (eq? chart-type 'barchart))
(urls (cond
@@ -574,12 +609,10 @@ developing over time"))
(1+ tree-depth))
(list gnc:pagename-general
gnc:optname-reportname
(if show-fullname?
(gnc-account-get-full-name acct)
(xaccAccountGetName acct)))))))))
(acct->name acct))))))))
(gnc:html-chart-add-data-series!
chart label amounts color
'stack stack 'fill fill 'urls urls)))
chart label (if ratio-chart? (map safe-/ amounts row-totals) amounts)
color 'stack stack 'fill fill 'urls urls)))
all-data
(gnc:assign-colors (length all-data))
(iota (length all-data)))
@@ -589,6 +622,8 @@ developing over time"))
chart (gnc-commodity-get-mnemonic report-currency))
(gnc:html-chart-set-currency-symbol!
chart (gnc-commodity-get-nice-symbol report-currency))
(gnc:html-chart-set-format-style!
chart (if ratio-chart? "percent" "currency"))
(gnc:report-percent-done 98)
(gnc:html-document-add-object! document chart)
@@ -601,18 +636,27 @@ developing over time"))
(define (make-cell contents)
(gnc:make-html-table-cell/markup "number-cell" contents))
(define (make-cell-percent amt grandt)
(gnc:make-html-table-cell/markup "number-cell" (* (safe-/ amt grandt) 100) " %"))
(define (make-monetary-cell amount)
(make-cell (gnc:make-gnc-monetary report-currency amount)))
(for-each
(lambda (date row)
(lambda (date row row-total)
(gnc:html-table-append-row!
table
(append (list (make-cell date))
(map make-cell row)
(map (if ratio-chart?
(cut make-cell-percent <> row-total)
make-monetary-cell)
row)
(if cols>1?
(list
(make-cell (apply gnc:monetary+ row)))
(list (make-monetary-cell (apply + row)))
'()))))
date-string-list
(apply zip (map cadr all-data)))
list-of-rows
row-totals)
(gnc:html-table-set-col-headers!
table
@@ -622,8 +666,7 @@ developing over time"))
(lambda (col)
(cond
((string? col) col)
(show-fullname? (gnc-account-get-full-name col))
(else (xaccAccountGetName col))))
(else (acct->name col))))
(map car all-data))
(if cols>1?
(list (G_ "Grand Total"))
@@ -643,8 +686,7 @@ developing over time"))
(lambda (col)
(cond
((string? col) col)
(show-fullname? (gnc-account-get-full-name col))
(else (xaccAccountGetName col))))
(else (acct->name col))))
(map car all-data))
(if (pair? (cdr all-data))
(list (G_ "Grand Total"))
@@ -655,10 +697,10 @@ developing over time"))
(list date)
row
(if (pair? (cdr all-data))
(list (apply gnc:monetary+ row))
(list (apply + row))
'())))
(map (cut gnc-print-time64 <> iso-date) dates-list)
(apply zip (map cadr all-data)))))))))))))))
list-of-rows)))))))))))))
(unless (gnc:html-document-export-string document)
(gnc:html-document-set-export-error document (G_ "No exportable data")))

View File

@@ -189,15 +189,15 @@
headingpage2 optname-payment-recd "c" ""
(G_ "Payment received, thank you!")))
(add-option (gnc:make-string-option headingpage2 optname-invoice-number-text
"d" "" (G_ "Invoice number: ")))
"d" "" (G_ "Invoice number:")))
(add-option (gnc:make-string-option headingpage2 optname-to-text
"e" "" (G_ "To: ")))
"e" "" (G_ "To:")))
(add-option (gnc:make-string-option headingpage2 optname-ref-text
"f" "" (G_ "Your ref: ")))
"f" "" (G_ "Your ref:")))
(add-option (gnc:make-string-option headingpage2 optname-jobnumber-text
"g" "" (G_ "Job number: ")))
"g" "" (G_ "Job number:")))
(add-option (gnc:make-string-option headingpage2 optname-jobname-text
"h" "" (G_ "Job name: ")))
"h" "" (G_ "Job name:")))
(add-option (gnc:make-text-option
notespage optname-extra-notes "a"

View File

@@ -243,6 +243,16 @@
(test-equal "auto"
'("Auto")
(sxml->table-row-col sxml 1 0 2))
;; test ratios
(set-option expense-options gnc:pagename-display "Percentage chart" #t)
(let ((sxml (gnc:options->sxml expense-report-uuid expense-options
"test-standard-category-report"
"ratios"
#:strip-tag "script")))
(test-equal "multi-acct ratios"
'("57.14 %" "14.29 %" "14.29 %" "14.29 %" "$14.00")
(cdr (sxml->table-row-col sxml 1 2 #f))))
(test-end "multi-acct-test"))))

View File

@@ -67,6 +67,7 @@
(test-begin "transaction.scm")
(null-test)
(trep-tests)
(csv-tests)
(reconcile-tests)
;; (test-end) must be run as the last function, it will
;; return #f if any of the tests have failed.
@@ -928,6 +929,30 @@
(gnc:html-document-export-string document))))
(test-end "csv-export")))
(define (csv-tests)
(test-begin "csv tests")
(test-equal "gnc:lists->csv empty"
""
(gnc:lists->csv '(())))
(test-equal "gnc:lists->csv simple"
"\"from\",\"01/01/2010\""
(gnc:lists->csv
'(("from" "01/01/2010"))))
(test-equal "gnc:lists->csv complex"
"\"from\",\"01/01/2010\",,,
\"to\",\"31/12/2010\",,,
\"total\",23500.0,30000.0,3.5714285714285716,sym"
(gnc:lists->csv
'(("from" "01/01/2010")
("to" "31/12/2010")
("total" 23500 30000 25/7 sym))))
(test-error "gnc:lists->csv improper list"
(gnc:lists->csv
'(("from" "01/01/2010")
("to" "31/12/2010")
("total" 23500 30000 25/7 . sym))))
(test-end "csv tests"))
(define (reconcile-tests)
(let* ((env (create-test-env))
(account-alist (env-create-account-structure-alist env structure))

View File

@@ -470,18 +470,28 @@ in the Options panel."))
str)
(display #\" port))))
(define max-items (apply max (map length lst)))
(define max-items
(let lp ((lst lst) (maximum 0))
(cond
((null? lst) maximum)
((pair? lst) (lp (cdr lst) (max maximum (length (car lst)))))
(else (error "strify " lst " must be a proper list")))))
(define (strify obj)
(cond
((not obj) "")
((or (null? obj) (not obj)) "")
((string? obj) (string-sanitize-csv obj))
((number? obj) (number->string (exact->inexact obj)))
((list? obj) (string-join
(map strify
(append obj
(make-list (- max-items (length obj)) #f)))
","))
((pair? obj) (let lp ((row obj) (acc '()) (pad max-items))
(cond
((zero? pad) (string-concatenate-reverse acc))
((null? row) (lp '() (cons "," acc) (1- pad)))
((pair? row) (lp (cdr row)
(cons* (if (pair? (cdr row)) "," "")
(strify (car row))
acc)
(1- pad)))
(else (error "strify " obj " must be a proper list")))))
((gnc:gnc-monetary? obj) (strify (gnc:gnc-monetary-amount obj)))
(else (object->string obj))))

View File

@@ -46,6 +46,7 @@
<menuitem name="ActionsReconcile" action="ActionsReconcileAction"/>
<menuitem name="ActionsAutoClear" action="ActionsAutoClearAction"/>
<menuitem name="ActionsStockSplit" action="ActionsStockSplitAction"/>
<menuitem name="ActionsStockAssistant" action="ActionsStockAssistantAction"/>
<menuitem name="ActionLots" action="ActionsLotsAction"/>
<separator name="ActionsSep4"/>
<menuitem name="BlankTransaction" action="BlankTransactionAction"/>

View File

@@ -435,7 +435,7 @@ the option '~a'."))
(if (string? currency)
(gnc-commodity-table-lookup
(gnc-commodity-table-get-table (gnc-get-current-book))
GNC_COMMODITY_NS_CURRENCY currency)
(GNC-COMMODITY-NS-CURRENCY) currency)
currency))
(let* ((value (currency->scm default-value))
@@ -561,7 +561,7 @@ the option '~a'."))
(define (commodity->scm commodity)
(if (string? commodity)
(list 'commodity-scm
GNC_COMMODITY_NS_CURRENCY
(GNC-COMMODITY-NS-CURRENCY)
commodity)
(list 'commodity-scm
(gnc-commodity-get-namespace commodity)
@@ -1560,7 +1560,7 @@ the option '~a'."))
(if (string? currency-string)
(gnc-commodity-table-lookup
(gnc-commodity-table-get-table (gnc-get-current-book))
GNC_COMMODITY_NS_CURRENCY currency-string)
(GNC-COMMODITY-NS-CURRENCY) currency-string)
#f))
(define (currency? val)

View File

@@ -182,7 +182,7 @@ GncSqlColumnTableEntryImpl<CT_OWNERREF>::add_to_query(QofIdTypeConst obj_name,
auto owner = (*getter) (pObject);
QofInstance* inst = nullptr;
GncOwnerType type;
GncOwnerType type = GNC_OWNER_NONE;
auto type_hdr = std::string{m_col_name} + "_type";
auto guid_hdr = std::string{m_col_name} + "_guid";

View File

@@ -124,11 +124,11 @@ extern const gchar*
gnc_v2_book_version_string; /* see gnc-book-xml-v2 */
/* Forward declarations */
static FILE* try_gz_open (const char* filename, const char* perms,
gboolean compress,
gboolean write);
static gboolean is_gzipped_file (const gchar* name);
static gboolean wait_for_gzip (FILE* file);
static std::pair<FILE*, GThread*> try_gz_open (const char* filename,
const char* perms,
gboolean compress,
gboolean write);
static bool is_gzipped_file (const gchar* name);
static void
clear_up_account_commodity (
@@ -796,22 +796,21 @@ qof_session_load_from_xml_file_v2_full (
* https://bugs.gnucash.org/show_bug.cgi?id=712528 for more
* info.
*/
const char* filename = xml_be->get_filename();
FILE* file;
gboolean is_compressed = is_gzipped_file (filename);
file = try_gz_open (filename, "r", is_compressed, FALSE);
if (file == NULL)
auto filename = xml_be->get_filename();
auto [file, thread] = try_gz_open (filename, "r",
is_gzipped_file (filename), FALSE);
if (!file)
{
PWARN ("Unable to open file %s", filename);
retval = FALSE;
retval = false;
}
else
{
retval = gnc_xml_parse_fd (top_parser, file,
generic_callback, gd, book);
fclose (file);
if (is_compressed)
wait_for_gzip (file);
if (thread)
g_thread_join (thread) != nullptr;
}
}
@@ -1387,46 +1386,122 @@ gnc_book_write_accounts_to_xml_filehandle_v2 (QofBackend* qof_be, QofBook* book,
return success;
}
#define BUFLEN 4096
static inline gzFile
do_gzopen (const char* filename, const char* perms)
{
#ifdef G_OS_WIN32
gzFile file;
char* new_perms = nullptr;
char* conv_name = g_win32_locale_filename_from_utf8 (filename);
if (!conv_name)
{
g_warning ("Could not convert '%s' to system codepage",
filename);
return nullptr;
}
if (strchr (perms, 'b'))
new_perms = g_strdup (perms);
else
new_perms = g_strdup_printf ("%cb%s", *perms, perms + 1);
file = gzopen (conv_name, new_perms);
g_free (new_perms);
g_free (conv_name);
return file;
#else
return gzopen (filename, perms);
#endif
}
constexpr uint32_t BUFLEN{4096};
static inline bool
gz_thread_write (gzFile file, gz_thread_params_t* params)
{
bool success = true;
gchar buffer[BUFLEN];
while (success)
{
auto bytes = read (params->fd, buffer, BUFLEN);
if (bytes > 0)
{
if (gzwrite (file, buffer, bytes) <= 0)
{
gint errnum;
auto error = gzerror (file, &errnum);
g_warning ("Could not write the compressed file '%s'. The error is: '%s' (%d)",
params->filename, error, errnum);
success = false;
}
}
else if (bytes == 0)
{
break;
}
else
{
g_warning ("Could not read from pipe. The error is '%s' (errno %d)",
g_strerror (errno) ? g_strerror (errno) : "", errno);
success = false;
}
}
return success;
}
#if COMPILER(MSVC)
#define WRITE_FN _write
#else
#define WRITE_FN write
#endif
static inline bool
gz_thread_read (gzFile file, gz_thread_params_t* params)
{
bool success = true;
gchar buffer[BUFLEN];
while (success)
{
auto gzval = gzread (file, buffer, BUFLEN);
if (gzval > 0)
{
if (WRITE_FN (params->fd, buffer, gzval) < 0)
{
g_warning ("Could not write to pipe. The error is '%s' (%d)",
g_strerror (errno) ? g_strerror (errno) : "", errno);
success = false;
}
}
else if (gzval == 0)
{
break;
}
else
{
gint errnum;
const gchar* error = gzerror (file, &errnum);
g_warning ("Could not read from compressed file '%s'. The error is: '%s' (%d)",
params->filename, error, errnum);
success = false;
}
}
return success;
}
/* Compress or decompress function that is to be run in a separate thread.
* Returns 1 on success or 0 otherwise, stuffed into a pointer type. */
static gpointer
gz_thread_func (gz_thread_params_t* params)
{
gchar buffer[BUFLEN];
gssize bytes;
gint gzval;
gzFile file;
gint success = 1;
bool success = true;
#ifdef G_OS_WIN32
{
gchar* conv_name = g_win32_locale_filename_from_utf8 (params->filename);
gchar* perms;
auto file = do_gzopen (params->filename, params->perms);
if (!conv_name)
{
g_warning ("Could not convert '%s' to system codepage",
params->filename);
success = 0;
goto cleanup_gz_thread_func;
}
if (strchr (params->perms, 'b'))
perms = g_strdup (params->perms);
else
perms = g_strdup_printf ("%cb%s", *params->perms, params->perms + 1);
file = gzopen (conv_name, perms);
g_free (perms);
g_free (conv_name);
}
#else /* !G_OS_WIN32 */
file = gzopen (params->filename, params->perms);
#endif /* G_OS_WIN32 */
if (file == NULL)
if (!file)
{
g_warning ("Child threads gzopen failed");
success = 0;
@@ -1435,73 +1510,18 @@ gz_thread_func (gz_thread_params_t* params)
if (params->write)
{
while (success)
{
bytes = read (params->fd, buffer, BUFLEN);
if (bytes > 0)
{
if (gzwrite (file, buffer, bytes) <= 0)
{
gint errnum;
const gchar* error = gzerror (file, &errnum);
g_warning ("Could not write the compressed file '%s'. The error is: '%s' (%d)",
params->filename, error, errnum);
success = 0;
}
}
else if (bytes == 0)
{
printf("gz_thread_func EOF\n");
break;
}
else
{
g_warning ("Could not read from pipe. The error is '%s' (errno %d)",
g_strerror (errno) ? g_strerror (errno) : "", errno);
success = 0;
}
}
success = gz_thread_write (file, params);
}
else
{
while (success)
{
gzval = gzread (file, buffer, BUFLEN);
if (gzval > 0)
{
if (
#if COMPILER(MSVC)
_write
#else
write
#endif
(params->fd, buffer, gzval) < 0)
{
g_warning ("Could not write to pipe. The error is '%s' (%d)",
g_strerror (errno) ? g_strerror (errno) : "", errno);
success = 0;
}
}
else if (gzval == 0)
{
break;
}
else
{
gint errnum;
const gchar* error = gzerror (file, &errnum);
g_warning ("Could not read from compressed file '%s'. The error is: '%s' (%d)",
params->filename, error, errnum);
success = 0;
}
}
success = gz_thread_read (file, params);
}
if ((gzval = gzclose (file)) != Z_OK)
{
g_warning ("Could not close the compressed file '%s' (errnum %d)",
params->filename, gzval);
success = 0;
success = false;
}
cleanup_gz_thread_func:
@@ -1513,7 +1533,7 @@ cleanup_gz_thread_func:
return GINT_TO_POINTER (success);
}
static FILE*
static std::pair<FILE*, GThread*>
try_gz_open (const char* filename, const char* perms, gboolean compress,
gboolean write)
{
@@ -1521,13 +1541,11 @@ try_gz_open (const char* filename, const char* perms, gboolean compress,
compress = TRUE;
if (!compress)
return g_fopen (filename, perms);
return std::pair<FILE*, GThread*>(g_fopen (filename, perms),
nullptr);
{
int filedes[2]{};
GThread* thread;
gz_thread_params_t* params;
FILE* file;
#ifdef G_OS_WIN32
if (_pipe (filedes, 4096, _O_BINARY) < 0)
@@ -1550,17 +1568,22 @@ try_gz_open (const char* filename, const char* perms, gboolean compress,
close(filedes[0]);
close(filedes[1]);
}
return g_fopen (filename, perms);
return std::pair<FILE*, GThread*>(g_fopen (filename, perms),
nullptr);
}
params = g_new (gz_thread_params_t, 1);
gz_thread_params_t* params = g_new (gz_thread_params_t, 1);
params->fd = filedes[write ? 0 : 1];
params->filename = g_strdup (filename);
params->perms = g_strdup (perms);
params->write = write;
thread = g_thread_new ("xml_thread", (GThreadFunc) gz_thread_func,
params);
auto thread = g_thread_new ("xml_thread", (GThreadFunc) gz_thread_func,
params);
FILE* file = nullptr;
if (!thread)
{
g_warning ("Could not create thread for (de)compression.");
@@ -1569,71 +1592,39 @@ try_gz_open (const char* filename, const char* perms, gboolean compress,
g_free (params);
close (filedes[0]);
close (filedes[1]);
return g_fopen (filename, perms);
file = g_fopen (filename, perms);
}
if (write)
file = fdopen (filedes[1], "w");
else
file = fdopen (filedes[0], "r");
G_LOCK (threads);
if (!threads)
threads = g_hash_table_new (g_direct_hash, g_direct_equal);
g_hash_table_insert (threads, file, thread);
G_UNLOCK (threads);
return file;
}
}
static gboolean
wait_for_gzip (FILE* file)
{
gboolean retval = TRUE;
G_LOCK (threads);
if (threads)
{
GThread* thread = static_cast<decltype (thread)> (g_hash_table_lookup (threads,
file));
if (thread)
{
g_hash_table_remove (threads, file);
retval = GPOINTER_TO_INT (g_thread_join (thread));
if (write)
file = fdopen (filedes[1], "w");
else
file = fdopen (filedes[0], "r");
}
}
G_UNLOCK (threads);
return retval;
return std::pair<FILE*, GThread*>(file, thread);
}
}
gboolean
gnc_book_write_to_xml_file_v2 (
QofBook* book,
const char* filename,
gboolean compress)
gnc_book_write_to_xml_file_v2 (QofBook* book, const char* filename,
gboolean compress)
{
FILE* out;
gboolean success = TRUE;
bool success = true;
out = try_gz_open (filename, "w", compress, TRUE);
auto [file, thread] = try_gz_open (filename, "w", compress, TRUE);
if (!file)
return false;
/* Try to write as much as possible */
if (!out
|| !gnc_book_write_to_xml_filehandle_v2 (book, out))
success = FALSE;
success = (gnc_book_write_to_xml_filehandle_v2 (book, file));
/* Close the output stream */
if (out && fclose (out))
success = FALSE;
success = ! (fclose (file));
/* Optionally wait for parallel compression threads */
if (out && compress)
if (!wait_for_gzip (out))
success = FALSE;
if (thread)
success = g_thread_join (thread) != nullptr;
return success;
}
@@ -1672,7 +1663,7 @@ gnc_book_write_accounts_to_xml_file_v2 (QofBackend* qof_be, QofBook* book,
}
/***********************************************************************/
static gboolean
static bool
is_gzipped_file (const gchar* name)
{
unsigned char buf[2];
@@ -1680,22 +1671,23 @@ is_gzipped_file (const gchar* name)
if (fd == -1)
{
return FALSE;
return false;
}
if (read (fd, buf, 2) != 2)
{
close (fd);
return FALSE;
return false;
}
close (fd);
/* 037 0213 are the header id bytes for a gzipped file. */
if (buf[0] == 037 && buf[1] == 0213)
{
return TRUE;
return true;
}
return FALSE;
return false;
}
QofBookFileType
@@ -1707,20 +1699,8 @@ gnc_is_xml_data_file_v2 (const gchar* name, gboolean* with_encoding)
char first_chunk[256];
int num_read;
#ifdef G_OS_WIN32
{
gchar* conv_name = g_win32_locale_filename_from_utf8 (name);
if (!conv_name)
g_warning ("Could not convert '%s' to system codepage", name);
else
{
file = gzopen (conv_name, "rb");
g_free (conv_name);
}
}
#else
file = gzopen (name, "r");
#endif
file = do_gzopen (name, "r");
if (file == NULL)
return GNC_BOOK_NOT_OURS;
@@ -1820,18 +1800,16 @@ gnc_xml2_find_ambiguous (const gchar* filename, GList* encodings,
GHashTable** unique, GHashTable** ambiguous,
GList** impossible)
{
FILE* file = NULL;
GList* iconv_list = NULL, *conv_list = NULL, *iter;
iconv_item_type* iconv_item = NULL, *ascii = NULL;
const gchar* enc;
GHashTable* processed = NULL;
gint n_impossible = 0;
GError* error = NULL;
gboolean is_compressed;
gboolean clean_return = FALSE;
is_compressed = is_gzipped_file (filename);
file = try_gz_open (filename, "r", is_compressed, FALSE);
auto [file, thread] = try_gz_open (filename, "r",
is_gzipped_file (filename), FALSE);
if (file == NULL)
{
PWARN ("Unable to open file %s", filename);
@@ -2014,8 +1992,8 @@ cleanup_find_ambs:
if (file)
{
fclose (file);
if (is_compressed)
wait_for_gzip (file);
if (thread)
g_thread_join (thread);
}
return (clean_return) ? n_impossible : -1;
@@ -2031,17 +2009,14 @@ static void
parse_with_subst_push_handler (xmlParserCtxtPtr xml_context,
push_data_type* push_data)
{
const gchar* filename;
FILE* file = NULL;
GIConv ascii = (GIConv) - 1;
GString* output = NULL;
GError* error = NULL;
gboolean is_compressed;
filename = push_data->filename;
is_compressed = is_gzipped_file (filename);
file = try_gz_open (filename, "r", is_compressed, FALSE);
if (file == NULL)
auto filename = push_data->filename;
auto [file, thread] = try_gz_open (filename, "r",
is_gzipped_file (filename), FALSE);
if (!file)
{
PWARN ("Unable to open file %s", filename);
goto cleanup_push_handler;
@@ -2154,8 +2129,8 @@ cleanup_push_handler:
if (file)
{
fclose (file);
if (is_compressed)
wait_for_gzip (file);
if (thread)
g_thread_join (thread);
}
}

View File

@@ -141,7 +141,7 @@ set (engine_SOURCES
cap-gains.c
cashobjects.c
gnc-aqbanking-templates.cpp
gnc-budget.c
gnc-budget.cpp
gnc-commodity.c
gnc-date.cpp
gnc-datetime.cpp

View File

@@ -30,9 +30,13 @@
#include <qof.h>
#include <qofbookslots.h>
#include <qofinstance-p.h>
#include <unordered_map>
#include <vector>
#include <memory>
#include "Account.h"
#include "guid.hpp"
#include "gnc-budget.h"
#include "gnc-commodity.h"
@@ -58,6 +62,17 @@ typedef struct
QofInstanceClass parent_class;
} BudgetClass;
struct PeriodData
{
std::string note;
bool value_is_set;
gnc_numeric value;
};
using PeriodDataVec = std::vector<PeriodData>;
using AcctMap = std::unordered_map<const Account*, PeriodDataVec>;
using StringVec = std::vector<std::string>;
typedef struct GncBudgetPrivate
{
/* The name is an arbitrary string assigned by the user. */
@@ -69,6 +84,8 @@ typedef struct GncBudgetPrivate
/* Recurrence (period info) for the budget */
Recurrence recurrence;
std::unique_ptr<AcctMap> acct_map;
/* Number of periods */
guint num_periods;
} GncBudgetPrivate;
@@ -93,6 +110,7 @@ gnc_budget_init(GncBudget* budget)
priv = GET_PRIVATE(budget);
priv->name = CACHE_INSERT(_("Unnamed Budget"));
priv->description = CACHE_INSERT("");
priv->acct_map = std::make_unique<AcctMap>();
priv->num_periods = 12;
date = gnc_g_date_new_today ();
@@ -173,7 +191,7 @@ gnc_budget_set_property( GObject* object,
gnc_budget_set_num_periods(budget, g_value_get_uint(value));
break;
case PROP_RECURRENCE:
gnc_budget_set_recurrence(budget, g_value_get_pointer(value));
gnc_budget_set_recurrence (budget, static_cast<Recurrence*>(g_value_get_pointer(value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -262,6 +280,7 @@ gnc_budget_free(QofInstance *inst)
CACHE_REMOVE(priv->name);
CACHE_REMOVE(priv->description);
priv->acct_map = nullptr; // nullify to ensure unique_ptr is freed.
/* qof_instance_release (&budget->inst); */
g_object_unref(budget);
@@ -286,12 +305,11 @@ gnc_budget_commit_edit(GncBudget *bgt)
GncBudget*
gnc_budget_new(QofBook *book)
{
GncBudget* budget;
g_return_val_if_fail(book, NULL);
ENTER(" ");
budget = g_object_new(GNC_TYPE_BUDGET, NULL);
auto budget { static_cast<GncBudget*>(g_object_new(GNC_TYPE_BUDGET, nullptr)) };
qof_instance_init_data (&budget->inst, GNC_ID_BUDGET, book);
qof_event_gen( &budget->inst, QOF_EVENT_CREATE , NULL);
@@ -461,6 +479,13 @@ gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
std::for_each (priv->acct_map->begin(),
priv->acct_map->end(),
[num_periods](auto& it)
{
it.second.resize(num_periods);
});
qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
}
@@ -471,31 +496,43 @@ gnc_budget_get_num_periods(const GncBudget* budget)
return GET_PRIVATE(budget)->num_periods;
}
static inline void
make_period_path (const Account *account, guint period_num, char *path1, char *path2)
static inline StringVec
make_period_data_path (const Account *account, guint period_num)
{
const GncGUID *guid;
gchar *bufend;
guid = xaccAccountGetGUID (account);
guid_to_string_buff (guid, path1);
g_sprintf (path2, "%d", period_num);
gnc::GUID acct_guid {*(xaccAccountGetGUID (account))};
return { acct_guid.to_string(), std::to_string (period_num) };
}
static inline StringVec
make_period_note_path (const Account *account, guint period_num)
{
StringVec path { GNC_BUDGET_NOTES_PATH };
StringVec data_path { make_period_data_path (account, period_num) };
std::move (data_path.begin(), data_path.end(), std::back_inserter (path));
return path;
}
static PeriodData& get_perioddata (const GncBudget *budget,
const Account *account,
guint period_num);
/* period_num is zero-based */
/* What happens when account is deleted, after we have an entry for it? */
void
gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
guint period_num)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
make_period_path (account, period_num, path_part_one, path_part_two);
g_return_if_fail (period_num < GET_PRIVATE(budget)->num_periods);
auto& data = get_perioddata (budget, account, period_num);
data.value_is_set = false;
gnc_budget_begin_edit(budget);
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
auto path = make_period_data_path (account, period_num);
auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
delete budget_kvp->set_path (path, nullptr);
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -509,9 +546,6 @@ void
gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
guint period_num, gnc_numeric val)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
if (period_num >= GET_PRIVATE(budget)->num_periods)
@@ -523,18 +557,22 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
make_period_path (account, period_num, path_part_one, path_part_two);
auto& perioddata = get_perioddata (budget, account, period_num);
auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
auto path = make_period_data_path (account, period_num);
gnc_budget_begin_edit(budget);
if (gnc_numeric_check(val))
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
{
delete budget_kvp->set_path (path, nullptr);
perioddata.value_is_set = false;
}
else
{
GValue v = G_VALUE_INIT;
g_value_init (&v, GNC_TYPE_NUMERIC);
g_value_set_boxed (&v, &val);
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
g_value_unset (&v);
KvpValue* v = new KvpValue (val);
delete budget_kvp->set_path (path, v);
perioddata.value_is_set = true;
perioddata.value = val;
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -543,62 +581,33 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
}
/* We don't need these here, but maybe they're useful somewhere else?
Maybe this should move to Account.h */
gboolean
gnc_budget_is_account_period_value_set(const GncBudget *budget,
const Account *account,
guint period_num)
gnc_budget_is_account_period_value_set (const GncBudget *budget,
const Account *account,
guint period_num)
{
GValue v = G_VALUE_INIT;
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
gconstpointer ptr = NULL;
g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
g_return_val_if_fail(account, FALSE);
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
if (G_VALUE_HOLDS_BOXED (&v))
ptr = g_value_get_boxed (&v);
g_value_unset (&v);
return (ptr != NULL);
g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods, false);
return get_perioddata (budget, account, period_num).value_is_set;
}
gnc_numeric
gnc_budget_get_account_period_value(const GncBudget *budget,
const Account *account,
guint period_num)
gnc_budget_get_account_period_value (const GncBudget *budget,
const Account *account,
guint period_num)
{
gnc_numeric *numeric = NULL;
gnc_numeric retval;
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
GValue v = G_VALUE_INIT;
g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods,
gnc_numeric_zero());
auto& data = get_perioddata (budget, account, period_num);
if (!data.value_is_set)
return gnc_numeric_zero();
g_return_val_if_fail(GNC_IS_BUDGET(budget), gnc_numeric_zero());
g_return_val_if_fail(account, gnc_numeric_zero());
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
if (G_VALUE_HOLDS_BOXED (&v))
numeric = (gnc_numeric*)g_value_get_boxed (&v);
retval = numeric ? *numeric : gnc_numeric_zero ();
g_value_unset (&v);
return retval;
return data.value;
}
void
gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
guint period_num, const gchar *note)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
if (period_num >= GET_PRIVATE(budget)->num_periods)
@@ -610,19 +619,22 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
make_period_path (account, period_num, path_part_one, path_part_two);
auto& perioddata = get_perioddata (budget, account, period_num);
auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
auto path = make_period_note_path (account, period_num);
gnc_budget_begin_edit(budget);
if (note == NULL)
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
{
delete budget_kvp->set_path (path, nullptr);
perioddata.note.clear ();
}
else
{
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, note);
KvpValue* v = new KvpValue (g_strdup (note));
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
g_value_unset (&v);
delete budget_kvp->set_path (path, v);
perioddata.note = note;
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -632,22 +644,12 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
}
gchar *
gnc_budget_get_account_period_note(const GncBudget *budget,
const Account *account, guint period_num)
gnc_budget_get_account_period_note (const GncBudget *budget,
const Account *account, guint period_num)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
GValue v = G_VALUE_INIT;
gchar *retval;
g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
g_return_val_if_fail(account, NULL);
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
retval = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string(&v) : NULL;
g_value_unset (&v);
return retval;
g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods, nullptr);
auto& data = get_perioddata (budget, account, period_num);
return data.note.empty () ? nullptr : g_strdup (data.note.c_str());
}
time64
@@ -674,6 +676,46 @@ gnc_budget_get_account_period_actual_value(
acc, period_num);
}
static PeriodData&
get_perioddata (const GncBudget *budget, const Account *account, guint period_num)
{
GncBudgetPrivate *priv = GET_PRIVATE (budget);
if (period_num >= priv->num_periods)
throw std::out_of_range("period_num >= num_periods");
auto& map = priv->acct_map;
auto map_iter = map->find (account);
if (map_iter == map->end ())
{
auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
PeriodDataVec vec {};
vec.reserve (priv->num_periods);
for (guint i = 0; i < priv->num_periods; i++)
{
std::string note;
auto kval1 { budget_kvp->get_slot (make_period_data_path (account, i)) };
auto kval2 { budget_kvp->get_slot (make_period_note_path (account, i)) };
auto is_set = kval1 && kval1->get_type() == KvpValue::Type::NUMERIC;
auto num = is_set ? kval1->get<gnc_numeric>() : gnc_numeric_zero ();
if (kval2 && kval2->get_type() == KvpValue::Type::STRING)
note = kval2->get<const char*>();
PeriodData data { std::move (note), is_set, num };
vec.push_back (std::move(data));
}
map_iter = map->insert_or_assign(account, std::move(vec)).first;
}
auto& vec = map_iter->second;
return vec.at(period_num);
}
GncBudget*
gnc_budget_lookup (const GncGUID *guid, const QofBook *book)
{
@@ -760,7 +802,7 @@ static QofObject budget_object_def =
DI(.interface_version = ) QOF_OBJECT_VERSION,
DI(.e_type = ) GNC_ID_BUDGET,
DI(.type_label = ) "Budget",
DI(.create = ) (gpointer)gnc_budget_new,
DI(.create = ) (void*(*)(QofBook*)) gnc_budget_new,
DI(.book_begin = ) NULL,
DI(.book_end = ) gnc_budget_book_end,
DI(.is_dirty = ) qof_collection_is_dirty,

View File

@@ -64,6 +64,11 @@
#ifndef __GNC_BUDGET_H__
#define __GNC_BUDGET_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <glib.h>
/** The budget data.*/
@@ -171,6 +176,11 @@ GncBudget* gnc_budget_get_default(QofBook *book);
GncBudget* gnc_budget_lookup (const GncGUID *guid, const QofBook *book);
#define gnc_budget_lookup_direct(g,b) gnc_budget_lookup(&(g),(b))
#ifdef __cplusplus
}
#endif
#endif // __BUDGET_H__
/** @} */

View File

@@ -2510,11 +2510,7 @@ gnc_commodity_table_add_default_data(gnc_commodity_table *table, QofBook *book)
gnc_commodity* c;
ENTER ("table=%p", table);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_AMEX, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_NYSE, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_NASDAQ, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_EUREX, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_MUTUAL, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_NONCURRENCY, book);
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_TEMPLATE, book);
c = gnc_commodity_new(book, "template", GNC_COMMODITY_NS_TEMPLATE, "template", "template", 1);
gnc_commodity_table_insert(table, c);

View File

@@ -104,21 +104,13 @@ GType gnc_commodity_namespace_get_type(void);
* only used to populate an option menu in the commodity selection
* window.
*/
#define GNC_COMMODITY_NS_LEGACY "GNC_LEGACY_CURRENCIES"
#define GNC_COMMODITY_NS_TEMPLATE "template"
#define GNC_COMMODITY_NS_LEGACY "GNC_LEGACY_CURRENCIES"
#define GNC_COMMODITY_NS_TEMPLATE "template"
/* The ISO define is deprecated in favor of CURRENCY */
#define GNC_COMMODITY_NS_ISO "ISO4217"
#define GNC_COMMODITY_NS_CURRENCY "CURRENCY"
#define GNC_COMMODITY_NS_NASDAQ "NASDAQ"
#define GNC_COMMODITY_NS_NYSE "NYSE"
#define GNC_COMMODITY_NS_EUREX "EUREX"
#define GNC_COMMODITY_NS_MUTUAL "FUND"
#define GNC_COMMODITY_NS_AMEX "AMEX"
#define GNC_COMMODITY_NS_ASX "ASX"
#define GNC_COMMODITY_NS_NONCURRENCY _("All non-currency")
/* Delay translation of this one, we use it in both translated and untranslated form
when presenting the currency related namespace to the user */
#define GNC_COMMODITY_NS_ISO_GUI N_("Currencies")
#define GNC_COMMODITY_NS_ISO "ISO4217"
#define GNC_COMMODITY_NS_CURRENCY "CURRENCY"
#define GNC_COMMODITY_NS_NONCURRENCY NC_("Commodity Type", "All non-currency")
#define GNC_COMMODITY_NS_ISO_GUI NC_("Commodity Type", "Currencies")
/** Max fraction is 10^9 because 10^10 would require changing it to an
* int64_t.

View File

@@ -126,6 +126,7 @@ static const char* source_names[(size_t)PRICE_SOURCE_INVALID + 1] =
"user:split-register",
"user:split-import",
"user:stock-split",
"user:stock-transaction",
"user:invoice-post", /* Retained for backwards compatibility */
"temporary",
"invalid"

View File

@@ -175,6 +175,7 @@ typedef enum
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
PRICE_SOURCE_SPLIT_IMPORT, // "user:split-import"
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
PRICE_SOURCE_STOCK_TRANSACTION,// "user:stock-transaction"
PRICE_SOURCE_INVOICE, // "user:invoice-post"
PRICE_SOURCE_TEMP, // "temporary"
PRICE_SOURCE_INVALID, // "invalid"

View File

@@ -29,6 +29,7 @@
#include <glib.h>
#include <qofinstance-p.h>
#include <inttypes.h>
#include "gnc-commodity.h"
@@ -120,7 +121,7 @@ gncEntryDiscountHowToString (GncDiscountHow how)
case (GNC_DISC_POSTTAX):
return "POSTTAX";
default:
g_warning ("asked to translate unknown discount-how %d.\n", how);
PWARN ("asked to translate unknown discount-how %d.\n", how);
break;
}
return NULL;
@@ -145,7 +146,7 @@ gboolean gncEntryDiscountStringToHow (const char *str, GncDiscountHow *how)
*how = GNC_DISC_POSTTAX;
return TRUE;
}
g_warning ("asked to translate unknown discount-how string %s.\n",
PWARN ("asked to translate unknown discount-how string %s.\n",
str ? str : "(null)");
return FALSE;
@@ -162,7 +163,7 @@ const char * gncEntryPaymentTypeToString (GncEntryPaymentType type)
case (GNC_PAYMENT_CARD):
return "CARD";
default:
g_warning ("asked to translate unknown payment type %d.\n", type);
PWARN ("asked to translate unknown payment type %d.\n", type);
break;
}
return NULL ;
@@ -182,7 +183,7 @@ gboolean gncEntryPaymentStringToType (const char *str, GncEntryPaymentType *type
*type = GNC_PAYMENT_CARD;
return TRUE;
}
g_warning ("asked to translate unknown discount-how string %s.\n",
PWARN ("asked to translate unknown discount-how string %s.\n",
str ? str : "(null)");
return FALSE;
@@ -591,29 +592,46 @@ void gncEntrySetInvPrice (GncEntry *entry, gnc_numeric price)
void gncEntrySetInvTaxable (GncEntry *entry, gboolean taxable)
{
if (!entry) return;
if (entry->i_taxable == taxable) return;
ENTER ("%d", taxable);
if (entry->i_taxable == taxable) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
entry->i_taxable = taxable;
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetInvTaxIncluded (GncEntry *entry, gboolean taxincluded)
{
if (!entry) return;
if (entry->i_taxincluded == taxincluded) return;
ENTER ("%d", taxincluded);
if (entry->i_taxincluded == taxincluded) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
entry->i_taxincluded = taxincluded;
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetInvTaxTable (GncEntry *entry, GncTaxTable *table)
{
if (!entry) return;
if (entry->i_tax_table == table) return;
ENTER ("%s", gncTaxTableGetName (table));
if (entry->i_tax_table == table) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
if (entry->i_tax_table)
gncTaxTableDecRef (entry->i_tax_table);
@@ -623,6 +641,7 @@ void gncEntrySetInvTaxTable (GncEntry *entry, GncTaxTable *table)
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetInvDiscount (GncEntry *entry, gnc_numeric discount)
@@ -715,29 +734,46 @@ void gncEntrySetBillPrice (GncEntry *entry, gnc_numeric price)
void gncEntrySetBillTaxable (GncEntry *entry, gboolean taxable)
{
if (!entry) return;
if (entry->b_taxable == taxable) return;
ENTER ("%d", taxable);
if (entry->b_taxable == taxable) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
entry->b_taxable = taxable;
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetBillTaxIncluded (GncEntry *entry, gboolean taxincluded)
{
if (!entry) return;
if (entry->b_taxincluded == taxincluded) return;
ENTER ("%d", taxincluded);
if (entry->b_taxincluded == taxincluded) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
entry->b_taxincluded = taxincluded;
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetBillTaxTable (GncEntry *entry, GncTaxTable *table)
{
if (!entry) return;
if (entry->b_tax_table == table) return;
ENTER ("%s", gncTaxTableGetName (table));
if (entry->b_tax_table == table) {
LEAVE ("Value already set");
return;
}
gncEntryBeginEdit (entry);
if (entry->b_tax_table)
gncTaxTableDecRef (entry->b_tax_table);
@@ -747,6 +783,7 @@ void gncEntrySetBillTaxTable (GncEntry *entry, GncTaxTable *table)
entry->values_dirty = TRUE;
mark_entry (entry);
gncEntryCommitEdit (entry);
LEAVE ("");
}
void gncEntrySetBillable (GncEntry *entry, gboolean billable)
@@ -1106,10 +1143,12 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
GList * entries = gncTaxTableGetEntries (tax_table);
GList * node;
ENTER ("");
/* Step 1: compute the aggregate price */
aggregate = gnc_numeric_mul (qty, price, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND);
PINFO ("Aggregate value %" PRId64 "/%" PRId64, aggregate.num, aggregate.denom);
/* Step 2: compute the pre-tax aggregate */
/* First, compute the aggregate tpercent and tvalue numbers */
@@ -1129,14 +1168,14 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
GNC_HOW_DENOM_LCD);
break;
default:
g_warning ("Unknown tax type: %d", gncTaxTableEntryGetType (entry));
PWARN ("Unknown tax type: %d", gncTaxTableEntryGetType (entry));
break;
}
}
/* now we need to convert from 5% -> .05 */
tpercent = gnc_numeric_div (tpercent, percent, GNC_DENOM_AUTO,
GNC_HOW_DENOM_EXACT | GNC_HOW_RND_NEVER);
PINFO("Tax rate %" PRId64 "/%" PRId64, tpercent.num, tpercent.denom);
/* Next, actually compute the pre-tax aggregate value based on the
* taxincluded flag.
*/
@@ -1153,13 +1192,16 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
gnc_numeric_create (1, 1),
GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD),
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND);
PINFO ("pretax %" PRId64 "/%" PRId64, pretax.num, pretax.denom);
if (!gnc_numeric_zero_p(qty))
{
i_net_price = gnc_numeric_div (pretax, qty, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND);
}
PINFO("i_net_price %" PRId64 "/%" PRId64, i_net_price.num, i_net_price.denom);
}
else
{
PINFO ("Tax not included or no tax table, pretax is aggregate");
pretax = aggregate;
}
@@ -1224,7 +1266,7 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
break;
default:
g_warning ("unknown DiscountHow value: %d", discount_how);
PWARN ("unknown DiscountHow value: %d", discount_how);
break;
}
@@ -1247,6 +1289,7 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
{
GList * taxes = NULL;
PINFO("Computing tax value list");
for (node = entries; node; node = node->next)
{
GncTaxTableEntry *entry = node->data;
@@ -1276,6 +1319,7 @@ static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
if (net_price != NULL)
*net_price = i_net_price;
LEAVE ("");
return;
}
@@ -1317,12 +1361,14 @@ gncEntryRecomputeValues (GncEntry *entry)
int denom;
GList *tv_iter;
ENTER ("");
/* See if either tax table changed since we last computed values */
if (entry->i_tax_table)
{
time64 modtime = gncTaxTableLastModifiedSecs (entry->i_tax_table);
if (entry->i_taxtable_modtime != modtime)
{
PINFO ("Invoice tax table changed since last recompute.");
entry->values_dirty = TRUE;
entry->i_taxtable_modtime = modtime;
}
@@ -1332,13 +1378,16 @@ gncEntryRecomputeValues (GncEntry *entry)
time64 modtime = gncTaxTableLastModifiedSecs (entry->b_tax_table);
if (entry->b_taxtable_modtime != modtime)
{
PINFO ("Bill tax table changed since last recompute.");
entry->values_dirty = TRUE;
entry->b_taxtable_modtime = modtime;
}
}
if (!entry->values_dirty)
if (!entry->values_dirty) {
LEAVE ("No changes");
return;
}
/* Clear the last-computed tax values */
if (entry->i_tax_values)
@@ -1356,6 +1405,7 @@ gncEntryRecomputeValues (GncEntry *entry)
denom = get_entry_commodity_denom (entry);
/* Compute the invoice values */
DEBUG("Compute Invoice Values.");
gncEntryComputeValue (entry->quantity, entry->i_price,
(entry->i_taxable ? entry->i_tax_table : NULL),
entry->i_taxincluded,
@@ -1366,6 +1416,7 @@ gncEntryRecomputeValues (GncEntry *entry)
&(entry->i_tax_values));
/* Compute the bill values */
DEBUG("Compute BILL Values.");
gncEntryComputeValue (entry->quantity, entry->b_price,
(entry->b_taxable ? entry->b_tax_table : NULL),
entry->b_taxincluded,
@@ -1397,6 +1448,7 @@ gncEntryRecomputeValues (GncEntry *entry)
denom, GNC_HOW_DENOM_EXACT | GNC_HOW_RND_ROUND_HALF_UP);
}
entry->values_dirty = FALSE;
LEAVE ("");
}
/* The "Int" functions below are for internal use only.

View File

@@ -30,6 +30,7 @@
#include <config.h>
#include <stdint.h>
#include <inttypes.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <qofinstance-p.h>
@@ -943,6 +944,7 @@ static gnc_numeric gncInvoiceGetNetAndTaxesInternal (GncInvoice *invoice, gboole
g_return_val_if_fail (invoice, net_total);
ENTER ("");
/* Is the current document an invoice/credit note related to a customer or a vendor/employee ?
* The GncEntry code needs to know to return the proper entry amounts
*/
@@ -966,7 +968,7 @@ static gnc_numeric gncInvoiceGetNetAndTaxesInternal (GncInvoice *invoice, gboole
if (gnc_numeric_check (value) == GNC_ERROR_OK)
net_total = gnc_numeric_add (net_total, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
else
g_warning ("bad value in our entry");
PWARN ("bad value in our entry");
}
if (taxes)
@@ -991,6 +993,7 @@ static gnc_numeric gncInvoiceGetNetAndTaxesInternal (GncInvoice *invoice, gboole
*taxes = tv_list;
}
LEAVE ("%" PRId64 "/%" PRId64, net_total.num, net_total.denom);
return net_total;
}
@@ -1004,6 +1007,7 @@ static gnc_numeric gncInvoiceGetTotalInternal (GncInvoice *invoice, gboolean use
if (!invoice) return gnc_numeric_zero ();
ENTER ("");
total = gncInvoiceGetNetAndTaxesInternal (invoice, use_value, use_tax? &taxes : NULL, use_payment_type, type);
if (use_tax)
@@ -1015,6 +1019,7 @@ static gnc_numeric gncInvoiceGetTotalInternal (GncInvoice *invoice, gboolean use
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT | GNC_HOW_RND_ROUND_HALF_UP);
gncAccountValueDestroy (taxes);
}
LEAVE ("%" PRId64 "/%" PRId64, total.num, total.denom);
return total;
}
@@ -1070,6 +1075,7 @@ GList * gncInvoiceGetTypeListForOwnerType (GncOwnerType type)
type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_EMPL_CREDIT_NOTE));
return type_list;
default:
PWARN("Bad owner type, no invoices.");
return NULL;
}
@@ -1379,6 +1385,7 @@ GHashTable *gncInvoiceGetForeignCurrencies (const GncInvoice *invoice)
gboolean is_cn = gncInvoiceGetIsCreditNote (invoice);
GHashTable *amt_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_free);
ENTER ("");
for (entries_iter = invoice->entries; entries_iter != NULL; entries_iter = g_list_next(entries_iter))
{
@@ -1429,6 +1436,8 @@ GHashTable *gncInvoiceGetForeignCurrencies (const GncInvoice *invoice)
}
gncAccountValueDestroy (tt_amts);
}
LEAVE ("");
return amt_hash;
}
@@ -1442,6 +1451,7 @@ static gboolean gncInvoicePostAddSplit (QofBook *book,
{
Split *split;
ENTER ("");
split = xaccMallocSplit (book);
/* set action and memo? */
@@ -1484,6 +1494,8 @@ static gboolean gncInvoicePostAddSplit (QofBook *book,
We can't really do anything sensible about it, and this is
a user-interface free zone so we can't try asking the user
again either, have to return NULL*/
PERR("Multiple commodities with no price.");
LEAVE ("FALSE");
return FALSE;
}
else
@@ -1496,6 +1508,7 @@ static gboolean gncInvoicePostAddSplit (QofBook *book,
}
}
LEAVE ("TRUE");
return TRUE;
}
@@ -1522,6 +1535,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
if (!invoice || !acc) return NULL;
if (gncInvoiceIsPosted (invoice)) return NULL;
ENTER ("");
gncInvoiceBeginEdit (invoice);
book = qof_instance_get_book (invoice);
@@ -1624,6 +1638,8 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
value = gncEntryGetBalValue (entry, TRUE, is_cust_doc);
tax = gncEntryGetBalTaxValue (entry, TRUE, is_cust_doc);
DEBUG ("Tax %" PRId64 "/%" PRId64 " on entry value %" PRId64 "/%" PRId64,
tax.num, tax.denom, value.num, value.denom);
/* add the value for the account split */
this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
gncEntryGetBillAccount (entry));
@@ -1642,6 +1658,8 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
We can't really do anything sensible about it, and this is
a user-interface free zone so we can't try asking the user
again either, have to return NULL*/
PERR("Failed to add split %s", gncEntryGetDescription (entry));
LEAVE ("NULL");
return NULL;
}
@@ -1676,12 +1694,12 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
}
else
g_warning ("bad value in our entry");
PWARN ("bad value in our entry");
}
/* check the taxes */
if (gnc_numeric_check (tax) != GNC_ERROR_OK)
g_warning ("bad tax in our entry");
PWARN ("bad tax in our entry");
} /* for */
@@ -1691,6 +1709,8 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
gncAccountValueDestroy (taxes);
/* Iterate through the splitinfo list and generate the splits */
if (splitinfo)
PINFO ("Processing Split List");
for (iter = splitinfo; iter; iter = iter->next)
{
GncAccountValue *acc_val = iter->data;
@@ -1704,6 +1724,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
We can't really do anything sensible about it, and this is
a user-interface free zone so we can't try asking the user
again either, have to return NULL*/
PERR("Failed to add split %s, aborting accumulated splits.", memo);
return NULL;
}
}
@@ -1720,6 +1741,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
gnc_numeric to_charge_bal_amount = (is_cn ? gnc_numeric_neg (invoice->to_charge_amount)
: invoice->to_charge_amount);
PINFO ("Process to_card payment split");
/* Set memo. */
xaccSplitSetMemo (split, _("Extra to Charge Card"));
/* Set action based on book option */
@@ -1740,6 +1762,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
{
Split *split = xaccMallocSplit (book);
PINFO ("Process to_card balancing split");
/* Set memo */
xaccSplitSetMemo (split, memo);
/* Set action based on book option */
@@ -1778,6 +1801,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
if (autopay)
gncInvoiceAutoApplyPayments (invoice);
LEAVE ("");
return txn;
}
@@ -1797,6 +1821,7 @@ gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables)
lot = gncInvoiceGetPostedLot (invoice);
g_return_val_if_fail (lot, FALSE);
ENTER ("");
/* Destroy the Posted Transaction */
xaccTransClearReadOnly (txn);
xaccTransBeginEdit (txn);
@@ -1822,6 +1847,8 @@ gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables)
// Note: make a copy of the lot list here, when splits are deleted from the lot,
// the original list may be destroyed by the lot code.
lot_split_list = g_list_copy (gnc_lot_get_split_list (lot));
if (lot_split_list)
PINFO ("Recreating link transactions for remaining lots");
for (lot_split_iter = lot_split_list; lot_split_iter; lot_split_iter = lot_split_iter->next)
{
Split *split = lot_split_iter->data;
@@ -1912,6 +1939,8 @@ gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables)
mark_invoice (invoice);
gncInvoiceCommitEdit (invoice);
LEAVE ("TRUE");
return TRUE;
}

View File

@@ -96,10 +96,10 @@ test_gnc_set_budget_num_periods_data_retention ()
gnc_budget_set_num_periods(budget, 10);
gnc_budget_set_num_periods(budget, 20);
/* value and note are retained */
g_assert (gnc_budget_is_account_period_value_set(budget, acc, 15));
/* value and note are lost */
g_assert (!gnc_budget_is_account_period_value_set(budget, acc, 15));
note = gnc_budget_get_account_period_note (budget, acc, 11);
g_assert_cmpstr (note, ==, "undefined");
g_assert_cmpstr (note, ==, NULL);
g_free (note);
gnc_budget_destroy(budget);

View File

@@ -1,7 +1,6 @@
# This is a list of files which contain translatable strings.
# This file was autogenerated by cmake.
bindings/guile/business-core.scm
bindings/guile/commodity-table.scm
bindings/guile/core-utils.scm
bindings/guile/engine.scm
bindings/guile/glib-guile.c
@@ -22,6 +21,7 @@ bindings/python/example_scripts/gncinvoice_jinja.py
bindings/python/example_scripts/latex_invoices.py
bindings/python/example_scripts/new_book_with_opening_balances.py
bindings/python/example_scripts/price_database_example.py
bindings/python/example_scripts/qof.py
bindings/python/example_scripts/quotes_historic.py
bindings/python/example_scripts/rest-api/gnucash_rest.py
bindings/python/example_scripts/rest-api/gnucash_simple.py
@@ -51,6 +51,7 @@ gnucash/gnome/assistant-acct-period.c
gnucash/gnome/assistant-hierarchy.c
gnucash/gnome/assistant-loan.cpp
gnucash/gnome/assistant-stock-split.c
gnucash/gnome/assistant-stock-transaction.cpp
gnucash/gnome/business-gnome-utils.c
gnucash/gnome/business-options-gnome.c
gnucash/gnome/business-urls.c
@@ -232,6 +233,7 @@ gnucash/gtkbuilder/assistant-hierarchy.glade
gnucash/gtkbuilder/assistant-loan.glade
gnucash/gtkbuilder/assistant-qif-import.glade
gnucash/gtkbuilder/assistant-stock-split.glade
gnucash/gtkbuilder/assistant-stock-transaction.glade
gnucash/gtkbuilder/assistant-xml-encoding.glade
gnucash/gtkbuilder/business-options-gnome.glade
gnucash/gtkbuilder/business-prefs.glade
@@ -608,7 +610,7 @@ libgnucash/engine/engine-helpers.c
libgnucash/engine/gncAddress.c
libgnucash/engine/gnc-aqbanking-templates.cpp
libgnucash/engine/gncBillTerm.c
libgnucash/engine/gnc-budget.c
libgnucash/engine/gnc-budget.cpp
libgnucash/engine/gncBusiness.c
libgnucash/engine/gnc-commodity.c
libgnucash/engine/gnc-commodity.h

4812
po/ar.po

File diff suppressed because it is too large Load Diff

4812
po/as.po

File diff suppressed because it is too large Load Diff

4796
po/az.po

File diff suppressed because it is too large Load Diff

4816
po/bg.po

File diff suppressed because it is too large Load Diff

4812
po/brx.po

File diff suppressed because it is too large Load Diff

4818
po/ca.po

File diff suppressed because it is too large Load Diff

4808
po/cs.po

File diff suppressed because it is too large Load Diff

4801
po/da.po

File diff suppressed because it is too large Load Diff

4868
po/de.po

File diff suppressed because it is too large Load Diff

4817
po/doi.po

File diff suppressed because it is too large Load Diff

4859
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5269
po/es.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4791
po/et.po

File diff suppressed because it is too large Load Diff

4806
po/eu.po

File diff suppressed because it is too large Load Diff

4814
po/fa.po

File diff suppressed because it is too large Load Diff

4814
po/fi.po

File diff suppressed because it is too large Load Diff

4841
po/fr.po

File diff suppressed because it is too large Load Diff

View File

@@ -10,14 +10,15 @@
# Marco Zietzling <marco.zietzling@gmail.com>, 2021.
# Moritz Höppner <moritz.hoeppner@resourcify.de>, 2021.
# Tobias Mohr <tobias_mohr_1991@gmx.de>, 2021.
# Christian Wehling <christian.wehling@web.de>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-02 22:54+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"PO-Revision-Date: 2022-02-17 17:55+0000\n"
"Last-Translator: Christian Wehling <christian.wehling@web.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/gnucash/glossary/"
"de/>\n"
"Language: de\n"
@@ -25,7 +26,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.11-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -220,10 +221,8 @@ msgid "amount"
msgstr "Betrag"
#. "The amount finally to pay, respecting discounts, billing terms…"
#, fuzzy
#| msgid "amount"
msgid "amount due"
msgstr "Betrag"
msgstr "fälliger Betrag"
#. "The result of adding several amounts together and then dividing this total by the number of amounts"
msgid "average"
@@ -415,8 +414,9 @@ msgid "document link"
msgstr "Verknüpfung, Verknüpftes Dokument"
#. "The last day to pay an invoice in time."
#, fuzzy
msgid "due date"
msgstr ""
msgstr "Fälligkeitsdatum"
#. "Electronic mail. Some languages allow different writings, but each team should use only one. https://en.wikipedia.org/wiki/Email"
msgid "email"
@@ -792,14 +792,12 @@ msgstr "Buchungsteil"
#. "Alias of 'shares'"
msgid "stocks"
msgstr ""
msgstr "Aktien"
# bis gnucash 1.8.7: Buchung
#. "Sometimes one old share gets replaced by multiple new like 1 OLD @100¤ by 2 NEW @50¤"
#, fuzzy
#| msgid "split"
msgid "stock split"
msgstr "Buchungsteil"
msgstr "Aktienteilung"
#. "This sets the particular design or shape of a report."
msgid "style sheet"
@@ -918,13 +916,13 @@ msgid "withdraw (in the reconcile dialog)"
msgstr "Belastung"
msgid "stock"
msgstr ""
msgstr "Aktie"
msgid "due"
msgstr ""
msgstr "fällig"
msgid "Online"
msgstr ""
msgstr "Online"
msgid "Direct Debit"
msgstr ""
msgstr "Lastschrift"

View File

@@ -16,7 +16,7 @@ msgstr ""
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-02-07 00:56+0000\n"
"PO-Revision-Date: 2022-03-06 22:36+0000\n"
"Last-Translator: Francisco Serrador <fserrador@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/gnucash/glossary/"
"es/>\n"
@@ -25,7 +25,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.11-dev\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"

View File

@@ -10,14 +10,15 @@
# ayiniho <ayiniho@tedomum.net>, 2021.
# Thomas Jungers <thomasjungers@gmail.com>, 2021.
# Maxime Leroy <lisacintosh@gmail.com>, 2021.
# Sébastien Ray <sebastien.ray@normalesup.org>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-02 22:54+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"PO-Revision-Date: 2022-03-09 20:11+0000\n"
"Last-Translator: Sébastien Ray <sebastien.ray@normalesup.org>\n"
"Language-Team: French <https://hosted.weblate.org/projects/gnucash/glossary/"
"fr/>\n"
"Language: fr\n"
@@ -25,7 +26,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -99,7 +100,7 @@ msgstr "type de compte : fond mutuel"
#. "The right side of the balance sheet in T account form shows the source of funds and contains equity & liability. While not common in english, most languages would translate 'equity & liability' with 'passive'. Complement: Active. See also: Report Form Implementation: https://bugs.gnucash.org/show_bug.cgi?id=421766"
msgid "account type: Passive"
msgstr "type de compte : passif"
msgstr "passif"
#. "Group of accounts tracking your success, complement of 'Assets & Liabilities'"
msgid "account type: Profit & Loss"
@@ -214,10 +215,8 @@ msgid "amount"
msgstr "montant brut, montant"
#. "The amount finally to pay, respecting discounts, billing terms…"
#, fuzzy
#| msgid "amount"
msgid "amount due"
msgstr "montant brut, montant"
msgstr "montant à payer"
#. "The result of adding several amounts together and then dividing this total by the number of amounts"
msgid "average"
@@ -401,7 +400,7 @@ msgstr "lien du document, lien vers un document, document lié"
#. "The last day to pay an invoice in time."
msgid "due date"
msgstr ""
msgstr "échéance"
#. "Electronic mail. Some languages allow different writings, but each team should use only one. https://en.wikipedia.org/wiki/Email"
msgid "email"
@@ -585,11 +584,11 @@ msgstr "options"
#. "Watch out: Although this word exists in gnucash program code, all that program code in gnucash is currently not activated. In the future, it will be used in business accounting as follows: A particular request to make or supply goods, but belonging to a (larger) job. Such a request can come from a customer or be sent to a vendor. An order will probably generate one invoice or bill."
msgid "order"
msgstr "rang"
msgstr "commande"
#. "Name of an automatically created account that holds splits that have no account."
msgid "orphan"
msgstr "orphelin"
msgstr "non soldé"
#. "The customer to (or employee or vendor from) which this invoice is sent - or short your business partner."
msgid "owner (of bill, invoice or expense voucher)"
@@ -761,13 +760,11 @@ msgstr "répartition"
#. "Alias of 'shares'"
msgid "stocks"
msgstr ""
msgstr "actions"
#. "Sometimes one old share gets replaced by multiple new like 1 OLD @100¤ by 2 NEW @50¤"
#, fuzzy
#| msgid "split"
msgid "stock split"
msgstr "répartition"
msgstr "fractionnement d'actions"
#. "This sets the particular design or shape of a report."
msgid "style sheet"
@@ -882,13 +879,13 @@ msgid "withdraw (in the reconcile dialog)"
msgstr "retrait (dans le dialogue de rapprochement)"
msgid "stock"
msgstr ""
msgstr "action"
msgid "due"
msgstr ""
msgstr "à payer"
msgid "Online"
msgstr ""
msgstr "En ligne"
msgid "Direct Debit"
msgstr ""
msgstr "Prélèvement automatique"

View File

@@ -10,7 +10,7 @@ msgstr ""
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-02-07 10:56+0000\n"
"PO-Revision-Date: 2022-03-10 11:58+0000\n"
"Last-Translator: Avi Markovitz <avi.markovitz@gmail.com>\n"
"Language-Team: Hebrew <https://hosted.weblate.org/projects/gnucash/glossary/"
"he/>\n"
@@ -20,7 +20,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
"n % 10 == 0) ? 2 : 3));\n"
"X-Generator: Weblate 4.11-dev\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -228,7 +228,7 @@ msgstr "יתרה שהועברה אל"
#. "A written record of money received and paid out, showing the difference between the two total amounts"
msgid "balance sheet"
msgstr "מאזן"
msgstr "גליון מאזן"
#. "To arrange for income and spending to be equal"
msgid "balance, to"
@@ -660,7 +660,7 @@ msgstr "איזון מחדש"
#. "reconcile an account, a reconciled split. To find a way to make the bank's account statement agree with the user's recorded transactions in an account."
msgid "reconcile, to"
msgstr "התאמה, ל"
msgstr "התאמה"
#. "-"
msgid "record keeping"
@@ -672,15 +672,15 @@ msgstr "יומן"
#. "A transaction that is divided into two or more parts"
msgid "register entry: split transaction"
msgstr "רישום יומן: פיצול תנועה"
msgstr "רשומת יומן: פיצול תנועה"
#. "-"
msgid "register entry: stock split"
msgstr "רישום יומן: פיצול מניות"
msgstr "רשומת יומן: פיצול מניות"
#. "one form of register"
msgid "register: auto-split ledger"
msgstr "יומן: פיצול כרטסת אוטומטית"
msgstr "יומן: פיצול כרטסת אוטומטי"
#. "another form of register"
msgid "register: basic ledger"
@@ -688,7 +688,7 @@ msgstr "יומן: כרטסת בסיסית"
#. "another form of register"
msgid "register: general ledger"
msgstr "יומן: כרטסת חשבונות"
msgstr "יומן: כרטסת חשבונות ראשית"
#. "another form of register"
msgid "register: transaction journal"

View File

@@ -4,10 +4,10 @@
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-03 19:55+0000\n"
"PO-Revision-Date: 2022-03-11 11:54+0000\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n"
"Language-Team: Croatian <https://hosted.weblate.org/projects/gnucash/"
"glossary/hr/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -615,7 +615,7 @@ msgstr "portfelj"
#. "Register invoice, voucher in account register"
msgid "post, to"
msgstr "uknjiži"
msgstr "uknjiži, u"
#. "A menu choice in many graphical user interface applications that allows the user to specify how the application will act each time it is used. "
msgid "preferences"

View File

@@ -3,14 +3,15 @@
#
# Kornel Tako <takokornel@gmail.com>, 2007.
# Frank H. Ellenberger <frank.h.ellenberger@gmail.com>, 2020.
# Kárász Attila <cult.edie@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-02 22:54+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"PO-Revision-Date: 2022-03-08 14:55+0000\n"
"Last-Translator: Kárász Attila <cult.edie@gmail.com>\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/gnucash/"
"glossary/hu/>\n"
"Language: hu\n"
@@ -18,7 +19,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -269,7 +270,7 @@ msgstr "Könyv lezárása"
#. "An estimate or plan of the money available to somebody and how it will be spent over a period of time."
msgid "Budget"
msgstr "Kosár"
msgstr "Költségvetés"
#. "-"
msgid "business (adjective)"

View File

@@ -5,14 +5,15 @@
# Kjartan Maraas <kmaraas@gnome.org>, 2005.
# John Erling Blad <jeblad@gmail.com>, 2018
# Allan Nordhøy <epost@anotheragency.no>, 2021.
# Petter Reinholdtsen <pere-weblate@hungry.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-02 22:54+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"PO-Revision-Date: 2022-03-11 08:54+0000\n"
"Last-Translator: Petter Reinholdtsen <pere-weblate@hungry.com>\n"
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/gnucash/"
"glossary/nb_NO/>\n"
"Language: nb\n"
@@ -20,7 +21,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.12-dev\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "Term (Dear translator: This file will never be visible to the user!)"
@@ -342,7 +343,7 @@ msgstr "Egendefinert"
#. "Compact, well-structured presentation of informations. See https://en.wikipedia.org/wiki/Dashboard_(business)"
msgid "dashboard"
msgstr ""
msgstr "kontrollpanel"
#. "The backend where the data is stored."
msgid "database"
@@ -394,7 +395,7 @@ msgstr "dokumentlenke"
#. "The last day to pay an invoice in time."
msgid "due date"
msgstr ""
msgstr "forfallsdato"
#. "Electronic mail. Some languages allow different writings, but each team should use only one. https://en.wikipedia.org/wiki/Email"
msgid "email"
@@ -448,7 +449,7 @@ msgstr "resultatoppstilling"
#. "Free software is a matter of liberty, not price … see https://en.wikipedia.org/wiki/Free_software"
msgid "free software"
msgstr ""
msgstr "fri programvare"
#. "An increase in wealth; profit; advantage (See also: capital gains)"
msgid "gain"
@@ -506,7 +507,7 @@ msgstr "Tapte kontoer"
#. "A particular collection of items that were bought in one transaction. A lot is typically formed when the item is bought, and is closed when the item is sold out. Needed e.g. for U.S. tax purposes."
msgid "Lot"
msgstr ""
msgstr "Parti"
#. "Combine two books into one (see book)."
msgid "merge, to"
@@ -658,7 +659,7 @@ msgstr "resultat"
#. "OBSOLETE. This report was renamed to 'income statement' on 2004-07-13. Old definition: A list that shows the amount of money spent compared with the amount earned by a business in a particular period"
msgid "Profit & Loss"
msgstr "Resultat & Tap"
msgstr "Vinning & Tap"
#. "-"
msgid "quick-fill"
@@ -718,7 +719,7 @@ msgstr ""
#. "name of an equity account (?); to be distinguished from the opening balance."
msgid "Retained Earnings"
msgstr "Beholdt inntjening"
msgstr "Overført resultat"
#. "Create a new transaction that is the inverse of the old one. When you add the two together they completely cancel out. Accounts use this instead of voiding transactions, usually because the prior month has been closed and can no longer be changed, or the entire accounting system is 'write only'."
msgid "reverse transaction, to (Action in the register)"
@@ -762,7 +763,7 @@ msgstr "splitt"
#. "Alias of 'shares'"
msgid "stocks"
msgstr ""
msgstr "aksjer"
#. "Sometimes one old share gets replaced by multiple new like 1 OLD @100¤ by 2 NEW @50¤"
#, fuzzy
@@ -800,7 +801,7 @@ msgstr ""
#. "'Value Added Tax' is the other form of sales tax."
msgid "tax type: VAT"
msgstr ""
msgstr "avgiftstype: MVA"
#. "If you create a new e.g. style sheet, you can start from a template."
msgid "template"
@@ -883,13 +884,13 @@ msgid "withdraw (in the reconcile dialog)"
msgstr "uttak"
msgid "stock"
msgstr ""
msgstr "aksje"
msgid "due"
msgstr ""
msgstr "forfall"
msgid "Online"
msgstr ""
msgstr "Oppkoblet"
msgid "Direct Debit"
msgstr ""

View File

@@ -8,14 +8,15 @@
# 峡州仙士 <c@cjh0613.com>, 2021.
# Eric <spice2wolf@gmail.com>, 2021.
# Eric <alchemillatruth@purelymail.com>, 2022.
# YTX <ytx.cash@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: GnuCash 4.8\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug.cgi?"
"product=GnuCash&component=Translations\n"
"Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug."
"cgi?product=GnuCash&component=Translations\n"
"POT-Creation-Date: 2021-12-05 20:11+0100\n"
"PO-Revision-Date: 2022-01-07 13:54+0000\n"
"Last-Translator: Eric <alchemillatruth@purelymail.com>\n"
"PO-Revision-Date: 2022-02-18 12:17+0000\n"
"Last-Translator: YTX <ytx.cash@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"gnucash/glossary/zh_Hans/>\n"
"Language: zh_CN\n"
@@ -23,7 +24,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.11-dev\n"
# 翻译人员好这个是不会被最终用户所见的。这是为了您也就是翻译人员所提供的一个工具。GnuCash 是一个个人或小型企业理财的软件,是一个会计专业性比较强的软件,其中包含了很多的术语。而这里就是针对很多术语的解释。
# 请大家务必在翻译前先浏览此文件,否则很容易出现翻译不一致的地方。如果有必须修正的术语错误,也请先修改这个文件,然后再修改软件的 po这样后来的翻译人员就不会犯同样的出错了。请大家在翻译术语的时候尽量参考国内会计行业术语以方便专业人士使用。谢谢
@@ -598,7 +599,7 @@ msgstr "损失科目"
# 暂时找不到中文词汇与之对应,因此使用原文。
#. "A particular collection of items that were bought in one transaction. A lot is typically formed when the item is bought, and is closed when the item is sold out. Needed e.g. for U.S. tax purposes."
msgid "Lot"
msgstr "Lot"
msgstr "批次"
# 将两个账簿合成一个(见账簿)
#. "Combine two books into one (see book)."

4814
po/gu.po

File diff suppressed because it is too large Load Diff

4866
po/he.po

File diff suppressed because it is too large Load Diff

4812
po/hi.po

File diff suppressed because it is too large Load Diff

5161
po/hr.po

File diff suppressed because it is too large Load Diff

5082
po/hu.po

File diff suppressed because it is too large Load Diff

4820
po/id.po

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More