gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Tue Mar 14 19:13:34 EDT 2023
Updated via https://github.com/Gnucash/gnucash/commit/3d1ad858 (commit)
via https://github.com/Gnucash/gnucash/commit/5de35f97 (commit)
via https://github.com/Gnucash/gnucash/commit/a44b3664 (commit)
via https://github.com/Gnucash/gnucash/commit/8db81058 (commit)
from https://github.com/Gnucash/gnucash/commit/83829e65 (commit)
commit 3d1ad8581b603b8ec43313f9772cb599a1ac4764
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Mar 14 15:56:43 2023 -0700
Bug 798787 - gnc-register-owner-option currently broken
Use the right option type now that it works right.
diff --git a/gnucash/gnome/business-options-gnome.cpp b/gnucash/gnome/business-options-gnome.cpp
index e28c667f1d..f9c96d00b1 100644
--- a/gnucash/gnome/business-options-gnome.cpp
+++ b/gnucash/gnome/business-options-gnome.cpp
@@ -40,6 +40,7 @@
#include <exception>
#include "gnc-option-gtk-ui.hpp"
+#include "gncOwner.h"
#include <gnc-option.hpp>
#define FUNC_NAME G_STRFUNC
@@ -67,17 +68,15 @@ public:
GncOptionGtkUIItem(widget, type) {}
void set_ui_item_from_option(GncOption& option) noexcept override
{
- GncOwner owner{};
- owner.type = ui_type_to_owner_type(option.get_ui_type());
- owner.owner.undefined = (void*)option.get_value<const QofInstance*>();
- gnc_owner_set_owner(get_widget(), &owner);
+ auto owner = option.get_value<const GncOwner*>();
+ gnc_owner_set_owner(get_widget(), owner);
}
void set_option_from_ui_item(GncOption& option) noexcept override
{
GncOwner owner{};
gnc_owner_get_owner(get_widget(), &owner);
if (owner.type == ui_type_to_owner_type(option.get_ui_type()))
- option.set_value(static_cast<const QofInstance*>(owner.owner.undefined));
+ option.set_value<const GncOwner*>(&owner);
}
};
commit 5de35f97c8c74fcd8ef52cf86e1d56377e3fd3f4
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Mar 14 15:54:43 2023 -0700
Fix gnc_owner_get_owner so that it sets the owner type.
Using the instance's QofIdType.
diff --git a/gnucash/gnome/business-gnome-utils.c b/gnucash/gnome/business-gnome-utils.c
index 55b437acad..78818a967d 100644
--- a/gnucash/gnome/business-gnome-utils.c
+++ b/gnucash/gnome/business-gnome-utils.c
@@ -23,6 +23,7 @@
* Boston, MA 02110-1301, USA gnu at gnu.org
*/
+#include <assert.h>
#include <config.h>
#include <gtk/gtk.h>
@@ -55,6 +56,10 @@
#include "gnc-prefs.h"
#include "gnc-commodity.h"
#include "gnc-report-combo.h"
+#include "qofinstance.h"
+#include "qoflog.h"
+
+static const QofLogModule log_module = G_LOG_DOMAIN;
typedef enum
{
@@ -277,14 +282,21 @@ void gnc_owner_get_owner (GtkWidget *widget, GncOwner *owner)
g_return_if_fail (widget != NULL);
g_return_if_fail (owner != NULL);
- /* We'll assume that the owner has the proper 'type' because we
- * can't change it here. Hopefully the caller has it set properly
- */
- owner->owner.undefined =
+ QofInstance *instance =
gnc_general_search_get_selected (GNC_GENERAL_SEARCH (widget));
+
+ if (owner->type == GNC_OWNER_NONE ||
+ g_strcmp0(instance->e_type, qofOwnerGetType(owner)) == 0)
+ qofOwnerSetEntity(owner, instance);
+ else
+ {
+ PWARN("Owner type mismatch: Instance %s, Owner %s",
+ instance->e_type, qofOwnerGetType(owner));
+ owner->owner.undefined = instance;
+ }
}
-void gnc_owner_set_owner (GtkWidget *widget, GncOwner *owner)
+void gnc_owner_set_owner (GtkWidget *widget, const GncOwner *owner)
{
g_return_if_fail (widget != NULL);
g_return_if_fail (owner != NULL);
diff --git a/gnucash/gnome/business-gnome-utils.h b/gnucash/gnome/business-gnome-utils.h
index d050d0a30c..e625c80eb2 100644
--- a/gnucash/gnome/business-gnome-utils.h
+++ b/gnucash/gnome/business-gnome-utils.h
@@ -78,7 +78,7 @@ GtkWidget * gnc_owner_edit_create (GtkWidget *label, GtkWidget *hbox,
QofBook *book, GncOwner *owner);
void gnc_owner_get_owner (GtkWidget *widget, GncOwner *owner);
-void gnc_owner_set_owner (GtkWidget *widget, GncOwner *owner);
+void gnc_owner_set_owner (GtkWidget *widget, const GncOwner *owner);
/* An invoice select widget..
commit a44b3664e2d586924f913d2245cb6023ede6a1a6
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Mar 14 15:50:34 2023 -0700
[c++options] Implement GncOptionGncOwnerValue class.
GncOwners aren't QofInstances and have limited lifetimes so an option
must hold its own, wrapped in std::unique_ptr for memory management.
diff --git a/bindings/guile/gnc-optiondb.i b/bindings/guile/gnc-optiondb.i
index 6aba978442..ce5c9433c8 100644
--- a/bindings/guile/gnc-optiondb.i
+++ b/bindings/guile/gnc-optiondb.i
@@ -740,6 +740,10 @@ gnc_option_test_book_destroy(QofBook* book)
wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
%ignore swig_get_option(GncOption&);
+%ignore GncOwnerDeleter;
+%ignore
+ GncOptionGncOwnerValue::GncOptionGncOwnerValue(GncOptionGncOwnerValue &&);
+
%inline %{
#include <cassert>
#include <algorithm>
@@ -1151,7 +1155,6 @@ inline SCM return_scm_value(ValueType value)
%template(gnc_make_bool_option) gnc_make_option<bool>;
%template(gnc_make_int64_option) gnc_make_option<int64_t>;
%template(gnc_make_query_option) gnc_make_option<const QofQuery*>;
-%template(gnc_make_owner_option) gnc_make_option<const GncOwner*>;
%rename (get_value) GncOption::get_scm_value;
%rename (get_default_value) GncOption::get_scm_default_value;
@@ -1247,13 +1250,12 @@ inline SCM return_scm_value(ValueType value)
return scm_simple_format(SCM_BOOL_F, date_fmt, value);
}
- if constexpr (is_same_decayed_v<decltype(option),
- GncOptionValue<const GncOwner*>>)
+ if constexpr (is_GncOwnerValue_v<decltype(option)>)
{
auto value{option.get_value()};
auto guid{scm_from_utf8_string(qof_instance_to_string(qofOwnerGetOwner(value)).c_str())};
auto type{scm_from_long(gncOwnerGetType(value))};
- return scm_simple_format(SCM_BOOL_F, ticked_format_str,
+ return scm_simple_format(SCM_BOOL_F, list_format_str,
scm_list_1(scm_cons(type, guid)));
}
if constexpr (is_QofQueryValue_v<decltype(option)>)
@@ -1420,6 +1422,24 @@ inline SCM return_scm_value(ValueType value)
}
return;
}
+ if constexpr (is_GncOwnerValue_v<decltype(option)>)
+ {
+ if (scm_is_pair(new_value))
+ {
+ GncOwner owner{};
+ owner.type = static_cast<GncOwnerType>(scm_to_int(scm_car(new_value)));
+ auto strval{scm_to_utf8_string(scm_cdr(new_value))};
+ owner.owner.undefined = qof_instance_from_string(strval, option.get_ui_type());
+ option.set_value(&owner);
+ }
+ else
+ {
+ auto val{scm_to_value<const GncOwner*>(new_value)};
+ option.set_value(val);
+ }
+ return;
+ }
+
if constexpr (is_QofQueryValue_v<decltype(option)>)
{
if (scm_is_pair(new_value))
@@ -1516,6 +1536,37 @@ inline SCM return_scm_value(ValueType value)
}
return;
}
+ if constexpr (is_GncOwnerValue_v<decltype(option)>)
+ {
+ if (scm_is_pair(new_value))
+ {
+ GncOwner owner{};
+ owner.type = static_cast<GncOwnerType>(scm_to_int(scm_car(new_value)));
+ auto strval{scm_to_utf8_string(scm_cdr(new_value))};
+ owner.owner.undefined = qof_instance_from_string(strval, option.get_ui_type());
+ option.set_default_value(&owner);
+ }
+ else
+ {
+ auto val{scm_to_value<const GncOwner*>(new_value)};
+ option.set_default_value(val);
+ }
+ return;
+ }
+ if constexpr (is_QofQueryValue_v<decltype(option)>)
+ {
+ if (scm_is_pair(new_value))
+ {
+ auto val{gnc_scm2query(new_value)};
+ option.set_default_value(val);
+ }
+ else
+ {
+ auto val{scm_to_value<const QofQuery*>(new_value)};
+ option.set_default_value(val);
+ }
+ return;
+ }
if constexpr (is_same_decayed_v<decltype(option),
GncOptionAccountSelValue>)
{
@@ -1674,6 +1725,26 @@ gnc_register_multichoice_callback_option(GncOptionDBPtr& db,
}
}
+ static GncOption*
+ gnc_make_gncowner_option(const char* section,
+ const char* name, const char* key,
+ const char* doc_string,
+ const GncOwner* value,
+ GncOptionUIType ui_type)
+ {
+ try {
+ return new GncOption(GncOptionGncOwnerValue{section, name, key,
+ doc_string,
+ value, ui_type});
+ }
+ catch (const std::exception& err)
+ {
+ std::cerr << "Make GncOwner option threw unexpected exception"
+ << err.what() << ", option not created." << std::endl;
+ return nullptr;
+ }
+ }
+
static GncOption*
gnc_make_account_list_option(const char* section,
const char* name, const char* key,
diff --git a/bindings/guile/options.scm b/bindings/guile/options.scm
index f72c08debf..6cf904c1eb 100644
--- a/bindings/guile/options.scm
+++ b/bindings/guile/options.scm
@@ -297,7 +297,7 @@
((eqv? owner-type GNC-OWNER-EMPLOYEE) (gncEmployeeLookupFlip guid book))
((eqv? owner-type GNC-OWNER-JOB) (gncJobLookupFlip guid book)))))
- (gnc-make-owner-option section name key docstring defval ui-type)))
+ (gnc-make-gncowner-option section name key docstring defval ui-type)))
(define-public (gnc:make-invoice-option section name key docstring getter validator)
(issue-deprecation-warning "gnc:make-invoice-option is deprecated. Make and register the option in one command with gnc-register-ionvoice-option.")
(let ((defval (if getter (getter) #f)))
diff --git a/bindings/guile/test/test-gnc-option-scheme-output.scm b/bindings/guile/test/test-gnc-option-scheme-output.scm
index f133c297fe..18407c5c81 100644
--- a/bindings/guile/test/test-gnc-option-scheme-output.scm
+++ b/bindings/guile/test/test-gnc-option-scheme-output.scm
@@ -588,7 +588,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(test-equal "owner unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let* ((option (gnc:lookup-option odb "foo" "bar"))
- (test-template test-literal-output-template)
+ (test-template test-list-output-template)
(book (gnc-get-current-book))
(owner (gncOwnerNew)))
(gncOwnerInitCustomer owner (gncCustomerCreate book))
diff --git a/libgnucash/engine/gnc-option-impl.cpp b/libgnucash/engine/gnc-option-impl.cpp
index 0f61e0995c..636960a548 100644
--- a/libgnucash/engine/gnc-option-impl.cpp
+++ b/libgnucash/engine/gnc-option-impl.cpp
@@ -37,6 +37,112 @@ static const QofLogModule log_module{"gnc.options"};
const std::string GncOptionMultichoiceValue::c_empty_string{""};
const std::string GncOptionMultichoiceValue::c_list_string{"multiple values"};
+static inline GncOwnerType
+ui_type_to_owner_type(GncOptionUIType ui_type)
+{
+ if (ui_type == GncOptionUIType::CUSTOMER)
+ return GNC_OWNER_CUSTOMER;
+ if (ui_type == GncOptionUIType::VENDOR)
+ return GNC_OWNER_VENDOR;
+ if (ui_type == GncOptionUIType::EMPLOYEE)
+ return GNC_OWNER_EMPLOYEE;
+ return GNC_OWNER_NONE;
+}
+
+static GncOwner*
+make_owner_ptr(const GncOwner* owner)
+{
+ if (!owner)
+ return nullptr;
+ auto rv{gncOwnerNew()};
+ gncOwnerCopy(owner, rv);
+ return rv;
+}
+
+GncOptionGncOwnerValue::GncOptionGncOwnerValue(
+ const char* section, const char* name,
+ const char* key, const char* doc_string,
+ const GncOwner* value, GncOptionUIType ui_type) :
+ OptionClassifier{section, name, key, doc_string},
+ m_ui_type(ui_type), m_value{make_owner_ptr(value)},
+ m_default_value{make_owner_ptr(value)} {}
+
+GncOptionGncOwnerValue::GncOptionGncOwnerValue(const GncOptionGncOwnerValue& from) :
+ OptionClassifier{from.m_section, from.m_name, from.m_sort_tag,
+ from.m_doc_string},
+ m_ui_type(from.get_ui_type()), m_value{make_owner_ptr(from.get_value())},
+ m_default_value{make_owner_ptr(from.get_default_value())} {}
+
+void
+GncOptionGncOwnerValue::set_value(const GncOwner* new_value)
+{
+ m_value.reset(make_owner_ptr(new_value));
+}
+
+void
+GncOptionGncOwnerValue::set_default_value(const GncOwner *new_value)
+{
+ m_value.reset(make_owner_ptr(new_value));
+ m_default_value.reset(make_owner_ptr(new_value));
+}
+
+const GncOwner*
+GncOptionGncOwnerValue::get_value() const
+{
+ return m_value.get();
+}
+
+const GncOwner*
+GncOptionGncOwnerValue::get_default_value() const
+{
+ return m_default_value.get();
+}
+
+void
+GncOptionGncOwnerValue::reset_default_value()
+{
+ gncOwnerCopy(m_default_value.get(), m_value.get());
+}
+
+bool
+GncOptionGncOwnerValue::is_changed() const noexcept
+{
+ return gncOwnerEqual(m_value.get(), m_default_value.get());
+}
+
+bool
+GncOptionGncOwnerValue::deserialize(const std::string& str) noexcept
+{
+ try {
+ auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
+ auto inst = qof_instance_from_guid(&guid, m_ui_type);
+ if (inst)
+ {
+ GncOwner owner{};
+ owner.type = ui_type_to_owner_type(m_ui_type);
+ owner.owner.undefined = inst;
+ set_default_value(&owner);
+ return true;
+ }
+ }
+ catch (const gnc::guid_syntax_exception& err)
+ {
+ PWARN("Failed to convert %s to a GUID", str.c_str());
+ }
+ return false;
+}
+
+std::string
+GncOptionGncOwnerValue::serialize() const noexcept
+{
+
+ auto owner{m_value.get()};
+ gnc::GUID guid{*qof_instance_get_guid(static_cast<QofInstance*>(owner->owner.undefined))};
+ std::string retval{guid.to_string()};
+
+ return retval;
+}
+
using GncItem = std::pair<QofIdTypeConst, GncGUID>;
static GncItem
@@ -60,6 +166,7 @@ get_current_root_account(void)
{
return gnc_book_get_root_account(get_current_book());
}
+
static const QofInstance*
qof_instance_from_gnc_item(const GncItem& item)
{
diff --git a/libgnucash/engine/gnc-option-impl.hpp b/libgnucash/engine/gnc-option-impl.hpp
index fec6a5db7f..704596ca51 100644
--- a/libgnucash/engine/gnc-option-impl.hpp
+++ b/libgnucash/engine/gnc-option-impl.hpp
@@ -113,6 +113,54 @@ private:
ValueType m_default_value;
};
+
+/** class GncOptionGncOwnerValue
+ *
+ * Unlike QofInstance based classes GncOwners are created on the fly, aren't
+ * placed in QofCollection, and therefore their lifetimes have to be managed.
+ * We use GncOwnerPtr for the purpose.
+ */
+struct GncOwnerDeleter
+{
+ void operator()(GncOwner* o) {
+ g_free(o);
+ }
+};
+
+using GncOwnerPtr = std::unique_ptr<GncOwner, GncOwnerDeleter>;
+
+class GncOptionGncOwnerValue: public OptionClassifier {
+public:
+ GncOptionGncOwnerValue(
+ const char* section, const char* name,
+ const char* key, const char* doc_string,
+ const GncOwner* value,
+ GncOptionUIType ui_type = GncOptionUIType::INTERNAL);
+ GncOptionGncOwnerValue(const GncOptionGncOwnerValue& from);
+ GncOptionGncOwnerValue(GncOptionGncOwnerValue&&) = default;
+ ~GncOptionGncOwnerValue() = default;
+ const GncOwner* get_value() const;
+ const GncOwner* get_default_value() const;
+ void set_value(const GncOwner* new_value);
+ void set_default_value(const GncOwner* new_value);
+ void reset_default_value();
+ bool is_changed() const noexcept;
+ GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
+ void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
+ bool is_internal() { return m_ui_type == GncOptionUIType::INTERNAL; }
+ std::string serialize() const noexcept;
+ bool deserialize(const std::string& str) noexcept;
+private:
+ GncOptionUIType m_ui_type;
+ GncOwnerPtr m_value;
+ GncOwnerPtr m_default_value;
+};
+
+/** class GncOptionQofinstanceValue
+ *
+ * QofInstances know what type they are but getting them to tell you is a pain
+ * so we put them in a pair with a type identifier.
+ */
using GncItem = std::pair<QofIdTypeConst, GncGUID>;
class GncOptionQofInstanceValue: public OptionClassifier {
@@ -201,6 +249,16 @@ QofInstance* qof_instance_from_string(const std::string& str,
QofInstance* qof_instance_from_guid(GncGUID*, GncOptionUIType type);
std::string qof_instance_to_string(const QofInstance* inst);
+template <typename T>
+struct is_GncOwnerValue
+{
+ static constexpr bool value =
+ std::is_same_v<std::decay_t<T>, GncOptionGncOwnerValue>;
+};
+
+template <typename T> inline constexpr bool
+is_GncOwnerValue_v = is_GncOwnerValue<T>::value;
+
template <typename T>
struct is_QofInstanceValue
{
diff --git a/libgnucash/engine/gnc-option.cpp b/libgnucash/engine/gnc-option.cpp
index 56f3f8aa31..81ce571b48 100644
--- a/libgnucash/engine/gnc-option.cpp
+++ b/libgnucash/engine/gnc-option.cpp
@@ -25,6 +25,7 @@
#include "gnc-option-impl.hpp"
#include "gnc-option-uitype.hpp"
#include "gnc-option-ui.hpp"
+#include "gncOwner.h"
static const char* log_module{"gnc.app-utils.gnc-option"};
@@ -466,8 +467,6 @@ template GncOption::GncOption(const char*, const char*, const char*,
const char*, std::string, GncOptionUIType);
template GncOption::GncOption(const char*, const char*, const char*,
const char*, const QofQuery*, GncOptionUIType);
-template GncOption::GncOption(const char*, const char*, const char*,
- const char*, const GncOwner*, GncOptionUIType);
template bool GncOption::get_value<bool>() const;
template int GncOption::get_value<int>() const;
@@ -477,6 +476,7 @@ template uint16_t GncOption::get_value<uint16_t>() const;
template const char* GncOption::get_value<const char*>() const;
template std::string GncOption::get_value<std::string>() const;
template const QofInstance* GncOption::get_value<const QofInstance*>() const;
+template const GncOwner* GncOption::get_value<const GncOwner*>() const;
template gnc_commodity* GncOption::get_value<gnc_commodity*>() const;
template const Account* GncOption::get_value<const Account*>() const;
template RelativeDatePeriod GncOption::get_value<RelativeDatePeriod>() const;
@@ -506,6 +506,7 @@ template void GncOption::set_value(char*);
template void GncOption::set_value(const char*);
template void GncOption::set_value(std::string);
template void GncOption::set_value(const QofInstance*);
+template void GncOption::set_value(const GncOwner*);
template void GncOption::set_value(gnc_commodity*);
template void GncOption::set_value(const Account*);
template void GncOption::set_value(RelativeDatePeriod);
@@ -556,5 +557,3 @@ template GncOption* gnc_make_option<bool>(const char*, const char*, const char*,
template GncOption* gnc_make_option<int64_t>(const char*, const char*,
const char*, const char*, int64_t,
GncOptionUIType);
-
-
diff --git a/libgnucash/engine/gnc-option.hpp b/libgnucash/engine/gnc-option.hpp
index 828ebaae29..f561414a0d 100644
--- a/libgnucash/engine/gnc-option.hpp
+++ b/libgnucash/engine/gnc-option.hpp
@@ -56,6 +56,7 @@ using QofQuery = _QofQuery;
struct QofInstance_s;
using QofInstance = QofInstance_s;
template <typename ValueType> class GncOptionValue;
+class GncOptionGncOwnerValue;
class GncOptionQofInstanceValue;
class GncOptionAccountListValue;
class GncOptionAccountSelValue;
@@ -101,8 +102,8 @@ using GncOptionVariant = std::variant<GncOptionValue<std::string>,
GncOptionValue<bool>,
GncOptionValue<int64_t>,
GncOptionQofInstanceValue,
+ GncOptionGncOwnerValue,
GncOptionValue<const QofQuery*>,
- GncOptionValue<const GncOwner*>,
GncOptionValue<GncOptionReportPlacementVec>,
GncOptionAccountListValue,
GncOptionAccountSelValue,
diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp
index b7f4f4083e..293bf9a24f 100644
--- a/libgnucash/engine/gnc-optiondb.cpp
+++ b/libgnucash/engine/gnc-optiondb.cpp
@@ -809,8 +809,8 @@ gnc_register_owner_option(GncOptionDB* db, const char* section,
default:
uitype = GncOptionUIType::INTERNAL;
};
- GncOption option{section, name, key, doc_string, value,
- uitype};
+ GncOption option{GncOptionGncOwnerValue{section, name, key, doc_string,
+ value, uitype}};
db->register_option(section, std::move(option));
}
commit 8db81058508be9ec1d510237ce33d1eb3de03199
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Mar 14 15:58:39 2023 -0700
[c++options] Warn when an option variant type's set_value isn't found.
diff --git a/libgnucash/engine/gnc-option.cpp b/libgnucash/engine/gnc-option.cpp
index 277491645e..56f3f8aa31 100644
--- a/libgnucash/engine/gnc-option.cpp
+++ b/libgnucash/engine/gnc-option.cpp
@@ -119,7 +119,7 @@ GncOption::set_value(ValueType value)
std::is_same_v<ValueType, time64> ||
std::is_same_v<ValueType, uint16_t>)))
option.set_value(value);
- if constexpr (is_same_decayed_v<decltype(option),
+ else if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (is_same_decayed_v<ValueType,
@@ -131,6 +131,9 @@ GncOption::set_value(ValueType value)
std::is_same_v<std::remove_cv<ValueType>, char*>)
option.set_value(value);
}
+ else
+ PWARN("No set_value handler: get_value returns %s, value_type is %s",
+ typeid(option.get_value()).name(), typeid(value).name());
}, *m_option);
}
Summary of changes:
bindings/guile/gnc-optiondb.i | 79 ++++++++++++++-
bindings/guile/options.scm | 2 +-
.../guile/test/test-gnc-option-scheme-output.scm | 2 +-
gnucash/gnome/business-gnome-utils.c | 22 ++++-
gnucash/gnome/business-gnome-utils.h | 2 +-
gnucash/gnome/business-options-gnome.cpp | 9 +-
libgnucash/engine/gnc-option-impl.cpp | 107 +++++++++++++++++++++
libgnucash/engine/gnc-option-impl.hpp | 58 +++++++++++
libgnucash/engine/gnc-option.cpp | 12 ++-
libgnucash/engine/gnc-option.hpp | 3 +-
libgnucash/engine/gnc-optiondb.cpp | 4 +-
11 files changed, 275 insertions(+), 25 deletions(-)
More information about the gnucash-changes
mailing list