gnucash stable: [c++options]Dirty and changed are different.

John Ralls jralls at code.gnucash.org
Tue Jun 20 17:53:27 EDT 2023


Updated	 via  https://github.com/Gnucash/gnucash/commit/b041a766 (commit)
	from  https://github.com/Gnucash/gnucash/commit/08d083e8 (commit)



commit b041a766901da386b5e2967bed14bd44a5ff696d
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 20 14:50:42 2023 -0700

    [c++options]Dirty and changed are different.
    
    Report options need to be saved when they're different from the
    defaults, book options need to be saved when their value changes
    regardless of whether it's the default value. That's dirty. Implement
    it.

diff --git a/libgnucash/engine/gnc-option-impl.cpp b/libgnucash/engine/gnc-option-impl.cpp
index 905088884b..edb1b10d44 100644
--- a/libgnucash/engine/gnc-option-impl.cpp
+++ b/libgnucash/engine/gnc-option-impl.cpp
@@ -77,6 +77,7 @@ void
 GncOptionGncOwnerValue::set_value(const GncOwner* new_value)
 {
     m_value.reset(make_owner_ptr(new_value));
+    m_dirty = true;
 }
 
 void
@@ -196,6 +197,7 @@ void
 GncOptionQofInstanceValue::set_value(const QofInstance* new_value)
 {
     m_value = make_gnc_item(new_value);
+    m_dirty = true;
 }
 
 void
@@ -308,6 +310,7 @@ GncOptionCommodityValue::set_value(gnc_commodity* value)
         throw std::invalid_argument("Value not a currency when required or not a commodity. Value not set.");
     m_mnemonic = gnc_commodity_get_mnemonic(value);
     m_namespace = gnc_commodity_get_namespace(value);
+    m_dirty = true;
 }
 
 void
@@ -591,6 +594,7 @@ GncOptionDateValue::set_value(uint16_t index) noexcept
     assert(index < m_period_set.size());
     m_date = INT64_MAX;
     m_period = m_period_set[index];
+    m_dirty = true;
 }
 
 uint16_t
@@ -726,6 +730,7 @@ template <typename ValueType> void
 GncOptionValue<ValueType>::set_value(ValueType new_value)
 {
     m_value = new_value;
+    m_dirty = true;
 }
 
 template <typename ValueType> void
diff --git a/libgnucash/engine/gnc-option-impl.hpp b/libgnucash/engine/gnc-option-impl.hpp
index 10d4eeab18..4ebaa36708 100644
--- a/libgnucash/engine/gnc-option-impl.hpp
+++ b/libgnucash/engine/gnc-option-impl.hpp
@@ -101,6 +101,8 @@ public:
     void set_value(ValueType new_value);
     void set_default_value(ValueType new_value);
     void reset_default_value();
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept { return m_value != m_default_value; }
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -111,6 +113,7 @@ private:
     GncOptionUIType m_ui_type;
     ValueType m_value;
     ValueType m_default_value;
+    bool m_dirty{false};
 };
 
 
@@ -144,6 +147,8 @@ public:
     void set_value(const GncOwner* new_value);
     void set_default_value(const GncOwner* new_value);
     void reset_default_value();
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept;
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -154,6 +159,7 @@ private:
     GncOptionUIType m_ui_type;
     GncOwnerPtr m_value;
     GncOwnerPtr m_default_value;
+    bool m_dirty{false};
 };
 
 /** class GncOptionQofinstanceValue
@@ -181,6 +187,8 @@ public:
     void set_value(const QofInstance* new_value);
     void set_default_value(const QofInstance* new_value);
     void reset_default_value();
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept;
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -191,6 +199,7 @@ private:
     GncOptionUIType m_ui_type;
     GncItem m_value;
     GncItem m_default_value;
+    bool m_dirty{false};
 };
 
 /** class GncOptionCommodityValue
@@ -229,6 +238,8 @@ public:
     void set_value(gnc_commodity* value);
     void set_default_value(gnc_commodity* value);
     void reset_default_value();
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept;
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -242,6 +253,7 @@ private:
     std::string m_mnemonic;
     std::string m_default_namespace;
     std::string m_default_mnemonic;
+    bool m_dirty{false};
 };
 
 QofInstance* qof_instance_from_string(const std::string& str,
@@ -408,7 +420,10 @@ public:
     void set_value(ValueType value)
     {
         if (this->validate(value))
+        {
             m_value = value;
+            m_dirty = true;
+        }
         else
             throw std::invalid_argument("Validation failed, value not set.");
     }
@@ -426,6 +441,8 @@ public:
         step = m_step;
     }
     void reset_default_value() { m_value = m_default_value; }
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept { return m_value != m_default_value; }
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -441,7 +458,8 @@ private:
     ValueType m_min;
     ValueType m_max;
     ValueType m_step;
-    bool m_alternate = false;
+    bool m_alternate{false};
+    bool m_dirty{false};
 };
 
 template<class OptType,
@@ -615,6 +633,7 @@ public:
         {
             m_value.clear();
             m_value.push_back(index);
+            m_dirty = true;
         }
         else
             throw std::invalid_argument("Value not a valid choice.");
@@ -626,6 +645,7 @@ public:
         {
             m_value.clear();
             m_value.push_back(index);
+            m_dirty = true;
         }
         else
             throw std::invalid_argument("Value not a valid choice.");
@@ -689,6 +709,8 @@ public:
         return std::get<1>(m_choices.at(index)).c_str();
     }
     void reset_default_value() { m_value = m_default_value; }
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept { return m_value != m_default_value; }
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -712,6 +734,7 @@ private:
     GncMultichoiceOptionIndexVec m_value;
     GncMultichoiceOptionIndexVec m_default_value;
     GncMultichoiceOptionChoices m_choices;
+    bool m_dirty{false};
     static const std::string c_empty_string;
     static const std::string c_list_string;
 };
@@ -832,8 +855,11 @@ public:
     bool validate (const GncOptionAccountList& values) const;
     void set_value (GncOptionAccountList values) {
         if (validate(values))
+        {
             //throw!
             m_value = values;
+            m_dirty = true;
+        }
     }
     void set_default_value (GncOptionAccountList values) {
         if (validate(values))
@@ -842,6 +868,8 @@ public:
     }
     GList* account_type_list() const noexcept;
     void reset_default_value() { m_value = m_default_value; }
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept;
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -855,6 +883,7 @@ private:
     GncOptionAccountList m_default_value;
     GncOptionAccountTypeList m_allowed;
     bool m_multiselect;
+    bool m_dirty{false};
 };
 
 template<> inline std::ostream&
@@ -943,6 +972,7 @@ public:
         {
             auto guid{qof_entity_get_guid(value)};
             m_value = *guid;
+            m_dirty = true;
         }
         //else throw
     }
@@ -956,6 +986,8 @@ public:
     }
     GList* account_type_list() const noexcept;
     void reset_default_value() { m_value = m_default_value; }
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept { return !guid_equal(&m_value, &m_default_value); }
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
     void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
@@ -967,6 +999,7 @@ private:
     GncGUID m_value;
     GncGUID m_default_value;
     GncOptionAccountTypeList m_allowed;
+    bool m_dirty{false};
 };
 
 template<> inline std::ostream&
@@ -1063,6 +1096,7 @@ public:
         {
             m_period = value;
             m_date = INT64_MAX;
+            m_dirty = true;
         }
     }
     void set_value(time64 time) {
@@ -1070,6 +1104,7 @@ public:
         {
             m_period = RelativeDatePeriod::ABSOLUTE;
             m_date = time;
+            m_dirty = true;
         }
     }
     void set_value(uint16_t index) noexcept;
@@ -1104,6 +1139,8 @@ public:
         m_period = m_default_period;
         m_date = m_default_date;
     }
+    void mark_saved() noexcept { m_dirty = false; }
+    bool is_dirty() const noexcept { return m_dirty; }
     bool is_changed() const noexcept { return m_period != m_default_period &&
             m_date != m_default_date; }
     GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
@@ -1119,6 +1156,7 @@ private:
     RelativeDatePeriod m_period;
     RelativeDatePeriod m_default_period;
     RelativeDatePeriodVec m_period_set;
+    bool m_dirty{false};
 };
 
 template<> inline std::ostream&
diff --git a/libgnucash/engine/gnc-option.cpp b/libgnucash/engine/gnc-option.cpp
index 49fa74e73a..b95cc2e7bf 100644
--- a/libgnucash/engine/gnc-option.cpp
+++ b/libgnucash/engine/gnc-option.cpp
@@ -26,6 +26,7 @@
 #include "gnc-option-uitype.hpp"
 #include "gnc-option-ui.hpp"
 #include "gncOwner.h"
+#include "kvp-value.hpp"
 
 static const char* log_module{"gnc.app-utils.gnc-option"};
 
@@ -291,6 +292,22 @@ GncOption::is_internal()
                }, *m_option);
 }
 
+void
+GncOption::mark_saved() noexcept
+{
+    std::visit([](auto& option)->void {
+                          option.mark_saved();
+                      }, *m_option);
+}
+
+bool
+GncOption::is_dirty() const noexcept
+{
+    return std::visit([](const auto& option)->bool {
+                          return option.is_dirty();
+                      }, *m_option);
+}
+
 bool
 GncOption::is_changed() const noexcept
 {
diff --git a/libgnucash/engine/gnc-option.hpp b/libgnucash/engine/gnc-option.hpp
index b2f9ffb8a7..267c0aaee5 100644
--- a/libgnucash/engine/gnc-option.hpp
+++ b/libgnucash/engine/gnc-option.hpp
@@ -164,6 +164,11 @@ public:
     void set_option_from_ui_item();
     void make_internal();
     bool is_internal();
+/** Mark the option as needing to be saved. */
+    void mark_saved() noexcept;
+/** @returns true if the option has been marked as needing to be saved. */
+    bool is_dirty() const noexcept;
+/** @returns true if the option value differs from its default value. */
     bool is_changed() const noexcept;
 /** @returns false unless m_option contains a GncOptionMultiselectValue or
  * GncOptionAccountListValue for which multiple selections have been enabled.
diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp
index 11ad68ac47..e30199b210 100644
--- a/libgnucash/engine/gnc-optiondb.cpp
+++ b/libgnucash/engine/gnc-optiondb.cpp
@@ -445,8 +445,8 @@ GncOptionDB::save_to_kvp(QofBook* book, bool clear_options) const noexcept
         [book](GncOptionSectionPtr& section)
         {
             section->foreach_option(
-                [book, &section](auto& option) {
-                    if (option.is_changed())
+                [book, &section](GncOption& option) {
+                    if (option.is_dirty())
                     {
                         /* We need the string name out here so that it stays in
                          * scope long enough to pass its c_str to
@@ -482,6 +482,7 @@ GncOptionDB::save_to_kvp(QofBook* book, bool clear_options) const noexcept
                             kvp = new KvpValue{g_strdup(str.c_str())};
                         }
                         qof_book_set_option(book, kvp, &list_head);
+                        option.mark_saved();
                     }
                 });
         });



Summary of changes:
 libgnucash/engine/gnc-option-impl.cpp |  5 +++++
 libgnucash/engine/gnc-option-impl.hpp | 40 ++++++++++++++++++++++++++++++++++-
 libgnucash/engine/gnc-option.cpp      | 17 +++++++++++++++
 libgnucash/engine/gnc-option.hpp      |  5 +++++
 libgnucash/engine/gnc-optiondb.cpp    |  5 +++--
 5 files changed, 69 insertions(+), 3 deletions(-)



More information about the gnucash-changes mailing list