Skip to content

Commit

Permalink
[c++options]Dirty and changed are different.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jralls committed Jun 20, 2023
1 parent 08d083e commit b041a76
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
5 changes: 5 additions & 0 deletions libgnucash/engine/gnc-option-impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ void
GncOptionGncOwnerValue::set_value(const GncOwner* new_value)
{
m_value.reset(make_owner_ptr(new_value));
m_dirty = true;
}

void
Expand Down Expand Up @@ -196,6 +197,7 @@ void
GncOptionQofInstanceValue::set_value(const QofInstance* new_value)
{
m_value = make_gnc_item(new_value);
m_dirty = true;
}

void
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
40 changes: 39 additions & 1 deletion libgnucash/engine/gnc-option-impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class GncOptionValue : public OptionClassifier
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; }
Expand All @@ -111,6 +113,7 @@ class GncOptionValue : public OptionClassifier
GncOptionUIType m_ui_type;
ValueType m_value;
ValueType m_default_value;
bool m_dirty{false};
};


Expand Down Expand Up @@ -144,6 +147,8 @@ class GncOptionGncOwnerValue: public OptionClassifier {
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; }
Expand All @@ -154,6 +159,7 @@ class GncOptionGncOwnerValue: public OptionClassifier {
GncOptionUIType m_ui_type;
GncOwnerPtr m_value;
GncOwnerPtr m_default_value;
bool m_dirty{false};
};

/** class GncOptionQofinstanceValue
Expand Down Expand Up @@ -181,6 +187,8 @@ class GncOptionQofInstanceValue: public OptionClassifier {
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; }
Expand All @@ -191,6 +199,7 @@ class GncOptionQofInstanceValue: public OptionClassifier {
GncOptionUIType m_ui_type;
GncItem m_value;
GncItem m_default_value;
bool m_dirty{false};
};

/** class GncOptionCommodityValue
Expand Down Expand Up @@ -229,6 +238,8 @@ class GncOptionCommodityValue : public OptionClassifier
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; }
Expand All @@ -242,6 +253,7 @@ class GncOptionCommodityValue : public OptionClassifier
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,
Expand Down Expand Up @@ -408,7 +420,10 @@ class GncOptionRangeValue : public OptionClassifier
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.");
}
Expand All @@ -426,6 +441,8 @@ class GncOptionRangeValue : public OptionClassifier
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; }
Expand All @@ -441,7 +458,8 @@ class GncOptionRangeValue : public OptionClassifier
ValueType m_min;
ValueType m_max;
ValueType m_step;
bool m_alternate = false;
bool m_alternate{false};
bool m_dirty{false};
};

template<class OptType,
Expand Down Expand Up @@ -615,6 +633,7 @@ class GncOptionMultichoiceValue : public OptionClassifier
{
m_value.clear();
m_value.push_back(index);
m_dirty = true;
}
else
throw std::invalid_argument("Value not a valid choice.");
Expand All @@ -626,6 +645,7 @@ class GncOptionMultichoiceValue : public OptionClassifier
{
m_value.clear();
m_value.push_back(index);
m_dirty = true;
}
else
throw std::invalid_argument("Value not a valid choice.");
Expand Down Expand Up @@ -689,6 +709,8 @@ class GncOptionMultichoiceValue : public OptionClassifier
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; }
Expand All @@ -712,6 +734,7 @@ class GncOptionMultichoiceValue : public OptionClassifier
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;
};
Expand Down Expand Up @@ -832,8 +855,11 @@ class GncOptionAccountListValue : public OptionClassifier
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))
Expand All @@ -842,6 +868,8 @@ class GncOptionAccountListValue : public OptionClassifier
}
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; }
Expand All @@ -855,6 +883,7 @@ class GncOptionAccountListValue : public OptionClassifier
GncOptionAccountList m_default_value;
GncOptionAccountTypeList m_allowed;
bool m_multiselect;
bool m_dirty{false};
};

template<> inline std::ostream&
Expand Down Expand Up @@ -943,6 +972,7 @@ class GncOptionAccountSelValue : public OptionClassifier
{
auto guid{qof_entity_get_guid(value)};
m_value = *guid;
m_dirty = true;
}
//else throw
}
Expand All @@ -956,6 +986,8 @@ class GncOptionAccountSelValue : public OptionClassifier
}
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; }
Expand All @@ -967,6 +999,7 @@ class GncOptionAccountSelValue : public OptionClassifier
GncGUID m_value;
GncGUID m_default_value;
GncOptionAccountTypeList m_allowed;
bool m_dirty{false};
};

template<> inline std::ostream&
Expand Down Expand Up @@ -1063,13 +1096,15 @@ class GncOptionDateValue : public OptionClassifier
{
m_period = value;
m_date = INT64_MAX;
m_dirty = true;
}
}
void set_value(time64 time) {
if (validate(time))
{
m_period = RelativeDatePeriod::ABSOLUTE;
m_date = time;
m_dirty = true;
}
}
void set_value(uint16_t index) noexcept;
Expand Down Expand Up @@ -1104,6 +1139,8 @@ class GncOptionDateValue : public OptionClassifier
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; }
Expand All @@ -1119,6 +1156,7 @@ class GncOptionDateValue : public OptionClassifier
RelativeDatePeriod m_period;
RelativeDatePeriod m_default_period;
RelativeDatePeriodVec m_period_set;
bool m_dirty{false};
};

template<> inline std::ostream&
Expand Down
17 changes: 17 additions & 0 deletions libgnucash/engine/gnc-option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"};

Expand Down Expand Up @@ -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
{
Expand Down
5 changes: 5 additions & 0 deletions libgnucash/engine/gnc-option.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ class GncOption
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.
Expand Down
5 changes: 3 additions & 2 deletions libgnucash/engine/gnc-optiondb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
});
});
Expand Down

0 comments on commit b041a76

Please sign in to comment.