[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.
This commit is contained in:
John Ralls 2023-06-20 14:50:42 -07:00
parent 08d083e8e1
commit b041a76690
5 changed files with 69 additions and 3 deletions

View File

@ -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

View File

@ -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&

View File

@ -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
{

View File

@ -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.

View File

@ -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();
}
});
});