Implement registering/unregistering/calling change callbacks.

Drives reloading the report when the Apply or OK button is pressed.
This commit is contained in:
John Ralls 2021-08-12 14:29:56 -07:00
parent 86da12d844
commit 1af97ebb9a
4 changed files with 66 additions and 19 deletions

View File

@ -79,6 +79,7 @@ extern "C"
#include <memory>
#include <gnc-optiondb-impl.hpp>
/* NW: you can add GNC_MOD_REPORT to gnc-engine.h
or simply define it locally. Any unique string with
@ -111,14 +112,14 @@ typedef struct GncPluginPageReportPrivate
SCM cur_report;
/// The Option DB for this report.
GncOptionDB *cur_odb;
SCM option_change_cb_id;
size_t option_change_cb_id = 0;
/* initial_report is special; it's the one that's saved and
* restored. The name_change_callback only gets called when
* the initial_report name is changed. */
SCM initial_report;
GncOptionDB * initial_odb;
SCM name_change_cb_id;
size_t name_change_cb_id;
/* keep a list of edited reports so that we can destroy them when
* the window is closed. */
@ -550,7 +551,7 @@ gnc_plugin_page_report_setup( GncPluginPage *ppage )
priv->cur_report = SCM_BOOL_F;
priv->initial_report = SCM_BOOL_F;
priv->edited_reports = SCM_EOL;
priv->name_change_cb_id = SCM_BOOL_F;
priv->name_change_cb_id = 0;
g_object_get( ppage, "report-id", &report_id, nullptr );
@ -643,22 +644,17 @@ gnc_plugin_page_report_load_cb(GncHtml * html, URLType type,
scm_call_2(set_needs_save, inst_report, SCM_BOOL_T);
priv->initial_odb = gnc_get_report_optiondb(inst_report);
/*
priv->name_change_cb_id =
gnc_option_db_register_change_callback(priv->initial_odb,
gnc_plugin_page_report_refresh,
priv,
"General", "Report name");
*/
priv->initial_odb->register_callback(
gnc_plugin_page_report_refresh, priv);
}
if ((priv->cur_report != SCM_BOOL_F) && (priv->cur_odb != nullptr))
{
/*
gnc_option_db_unregister_change_callback_id(priv->cur_odb,
priv->option_change_cb_id);
*/
gnc_option_db_destroy(priv->cur_odb);
priv->cur_odb->unregister_callback(priv->option_change_cb_id);
priv->option_change_cb_id = 0;
priv->cur_odb = nullptr;
}
@ -668,12 +664,11 @@ gnc_plugin_page_report_load_cb(GncHtml * html, URLType type,
scm_gc_protect_object(priv->cur_report);
priv->cur_odb = gnc_get_report_optiondb(inst_report);
/*
priv->option_change_cb_id =
gnc_option_db_register_change_callback(priv->cur_odb,
gnc_plugin_page_report_option_change_cb,
report, nullptr, nullptr);
*/
priv->cur_odb->register_callback(
gnc_plugin_page_report_option_change_cb, report);
if (gnc_html_history_forward_p(gnc_html_get_history(priv->html)))
{
gnc_plugin_page_report_set_fwd_button(report, TRUE);

View File

@ -63,6 +63,25 @@ public:
};
using GncOptionSectionPtr = std::shared_ptr<GncOptionSection>;
using GncOptionDBChangeCallback = void (*)(void* user_data);
struct GncOptionDBCallback
{
GncOptionDBCallback(size_t id, GncOptionDBChangeCallback func,
void* data) :
m_id{id}, m_func{func}, m_data{data} {}
~GncOptionDBCallback() = default;
GncOptionDBCallback(const GncOptionDBCallback&) = delete;
GncOptionDBCallback(GncOptionDBCallback&&) = default;
GncOptionDBCallback& operator=(const GncOptionDBCallback&) = default;
GncOptionDBCallback& operator=(GncOptionDBCallback&&) = default;
size_t m_id;
GncOptionDBChangeCallback m_func;
void* m_data;
};
using GncCallbackVec = std::vector<GncOptionDBCallback>;
class GncOptionDB
{
@ -138,10 +157,14 @@ public:
const std::string& section,
const std::string& name) const noexcept;
std::istream& load_option_key_value(std::istream& iss);
size_t register_callback(GncOptionDBChangeCallback, void*);
void unregister_callback(size_t);
void run_callbacks();
private:
GncOptionSection* m_default_section;
std::vector<GncOptionSectionPtr> m_sections;
bool m_dirty = false;
GncCallbackVec m_callbacks{};
std::function<GncOptionUIItem*()> m_get_ui_value;
std::function<void(GncOptionUIItem*)> m_set_ui_value;

View File

@ -22,6 +22,7 @@
\********************************************************************/
#include <libguile.h>
#include <functional>
#include <string>
#include <limits>
#include <sstream>
@ -666,6 +667,31 @@ GncOptionDB::load_from_key_value(std::istream& iss)
return iss;
}
size_t
GncOptionDB::register_callback(GncOptionDBChangeCallback cb, void* data)
{
constexpr std::hash<GncOptionDBChangeCallback> cb_hash;
auto id{cb_hash(cb)};
if (std::find_if(m_callbacks.begin(), m_callbacks.end(),
[id](auto&cb)->bool{ return cb.m_id == id; }) == m_callbacks.end())
m_callbacks.emplace_back(id, cb, data);
return id;
}
void
GncOptionDB::unregister_callback(size_t id)
{
std::remove_if(m_callbacks.begin(), m_callbacks.end(),
[id](auto& cb)->bool { return cb.m_id == id; });
}
void
GncOptionDB::run_callbacks()
{
std::for_each(m_callbacks.begin(), m_callbacks.end(),
[](auto& cb)->void { cb.m_func(cb.m_data); });
}
static inline void
counter_option_path(const GncOption& option, GSList* list, std::string& name)
{
@ -1306,6 +1332,8 @@ gnc_option_db_commit(GncOptionDB* odb)
(void*)option.get_name().c_str());
} });
});
if (!errors)
odb->run_callbacks();
return errors;
}

View File

@ -799,6 +799,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
}
%}
%ignore GncOptionDBCallback;
%include "gnc-option-date.hpp"
%include "gnc-option.hpp"