Extract the GncOptionDB* from the Scheme dispatch function closure.

Scheme code keeps the GncOptionDB in a closure. Extract it for C/C++
use. Ownership remains with the closure, don't free the GncOptionDB*.
This commit is contained in:
John Ralls 2021-08-02 16:52:34 -07:00
parent 99eaa81a28
commit a2e1a3e1b8
7 changed files with 78 additions and 25 deletions

View File

@ -168,7 +168,7 @@ gnc_style_sheet_dialog_create (StyleSheetDialog * ss,
{
SCM get_options = scm_c_eval_string ("gnc:html-style-sheet-options");
SCM scm_options = scm_call_1 (get_options, sheet_info);
SCM scm_dispatch = scm_call_1 (get_options, sheet_info);
ss_info * ssinfo = g_new0 (ss_info, 1);
GtkWidget * window;
gchar * title;
@ -176,7 +176,7 @@ gnc_style_sheet_dialog_create (StyleSheetDialog * ss,
title = g_strdup_printf(_("HTML Style Sheet Properties: %s"), name);
ssinfo->odialog = gnc_options_dialog_new(title, parent);
ssinfo->odb = (GncOptionDB *)scm_to_pointer(scm_options);
ssinfo->odb = gnc_get_optiondb_from_dispatcher(scm_dispatch);
ssinfo->stylesheet = sheet_info;
ssinfo->row_ref = row_ref;
g_free (title);

View File

@ -77,6 +77,9 @@ extern "C"
#include "print-session.h"
}
#include <memory>
/* NW: you can add GNC_MOD_REPORT to gnc-engine.h
or simply define it locally. Any unique string with
a gnucash- prefix will do. Then just set a log level
@ -584,7 +587,6 @@ gnc_plugin_page_report_load_cb(GncHtml * html, URLType type,
GncPluginPageReport *report = GNC_PLUGIN_PAGE_REPORT(data);
GncPluginPageReportPrivate *priv;
int report_id;
SCM get_options = scm_c_eval_string("gnc:report-options");
SCM set_needs_save = scm_c_eval_string("gnc:report-set-needs-save?!");
SCM inst_report;
@ -640,8 +642,7 @@ gnc_plugin_page_report_load_cb(GncHtml * html, URLType type,
DEBUG("calling set_needs_save for report with id=%d", report_id);
scm_call_2(set_needs_save, inst_report, SCM_BOOL_T);
priv->initial_odb =
(GncOptionDB *)scm_to_pointer(scm_call_1(get_options, inst_report));
priv->initial_odb = gnc_get_report_optiondb(inst_report);
/*
priv->name_change_cb_id =
gnc_option_db_register_change_callback(priv->initial_odb,
@ -666,8 +667,7 @@ gnc_plugin_page_report_load_cb(GncHtml * html, URLType type,
priv->cur_report = inst_report;
scm_gc_protect_object(priv->cur_report);
priv->cur_odb = (GncOptionDB *)scm_to_pointer(scm_call_1(get_options,
inst_report));
priv->cur_odb = gnc_get_report_optiondb(inst_report);
/*
priv->option_change_cb_id =
gnc_option_db_register_change_callback(priv->cur_odb,
@ -1032,20 +1032,25 @@ gnc_plugin_page_report_name_changed (GncPluginPage *page, const gchar *name)
ENTER("page %p, name %s", page, name);
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(page);
/* Is this a redundant call? */
old_name = gnc_option_db_lookup_string_value(priv->cur_odb, "General",
"Report name");
DEBUG("Comparing old name '%s' to new name '%s'",
old_name ? old_name : "(null)", name);
if (old_name && (strcmp(old_name, name) == 0))
if (priv->cur_odb)
{
LEAVE("no change");
return;
}
/* Store the new name for the report. */
gnc_option_db_set_string_value(priv->cur_odb, "General",
"Report name", name);
/* Is this a redundant call? */
old_name = gnc_option_db_lookup_string_value(priv->cur_odb, "General",
"Report name");
DEBUG("Comparing old name '%s' to new name '%s'",
old_name ? old_name : "(null)", name);
if (old_name && (strcmp(old_name, name) == 0))
{
LEAVE("no change");
return;
}
/* Store the new name for the report. */
gnc_option_db_set_string_value(priv->cur_odb, "General",
"Report name", name);
}
/* Have to manually call the option change hook. */
gnc_plugin_page_report_option_change_cb(page);

View File

@ -26,6 +26,7 @@
********************************************************************/
#include <libguile.h>
#include <glib/gi18n.h>
#include <memory>
extern "C"
{
@ -208,10 +209,8 @@ gboolean
gnc_report_edit_options(SCM report, GtkWindow *parent)
{
SCM set_editor = scm_c_eval_string("gnc:report-set-editor-widget!");
SCM get_options = scm_c_eval_string("gnc:report-options");
SCM get_report_type = scm_c_eval_string("gnc:report-type");
SCM ptr;
SCM options;
GncOptionDB* odb;
GtkWidget *options_widget = nullptr;
@ -220,14 +219,13 @@ gnc_report_edit_options(SCM report, GtkWindow *parent)
return TRUE;
/* Check if this report has options to edit */
options = scm_call_1(get_options, report);
if (options == SCM_BOOL_F)
odb = gnc_get_report_optiondb(report);
if (!odb)
{
gnc_warning_dialog (parent, "%s",
_("There are no options for this report."));
return FALSE;
}
odb = (GncOptionDB*)scm_to_pointer(options);
/* Multi-column type reports need a special options dialog */
ptr = scm_call_1(get_report_type, report);
@ -249,3 +247,11 @@ gnc_report_edit_options(SCM report, GtkWindow *parent)
return TRUE;
}
GncOptionDB*
gnc_get_report_optiondb(SCM report_instance)
{
SCM get_report_options = scm_c_eval_string("gnc:report-options");
auto scm_dispatch{scm_call_1(get_report_options, report_instance)};
return gnc_get_optiondb_from_dispatcher(scm_dispatch);
}

View File

@ -47,5 +47,6 @@ gboolean gnc_report_edit_options(SCM report, GtkWindow *parent);
#ifdef __cplusplus
}
GncOptionDB* gnc_get_report_optiondb(SCM report_instance);
#endif
#endif

View File

@ -824,6 +824,29 @@ GncOptionDB::load_from_kvp(QofBook* book) noexcept
});
}
GncOptionDB*
gnc_get_optiondb_from_dispatcher(SCM dispatcher)
{
SCM get_options = scm_c_eval_string("gnc:options-get");
if (dispatcher == SCM_BOOL_F)
return nullptr;
auto scm_ptr{scm_call_1(get_options, dispatcher)};
auto smob{!scm_is_null(scm_ptr) && SCM_INSTANCEP(scm_ptr) &&
scm_is_true(scm_slot_exists_p(scm_ptr, SCM_EOL)) ?
scm_slot_ref(scm_ptr, SCM_EOL) : (scm_ptr)};
void *c_ptr{nullptr};
if (!SCM_NULLP(smob))
{
if (SCM_POINTER_P(smob))
c_ptr = SCM_POINTER_VALUE(smob);
else
c_ptr = reinterpret_cast<void*>(SCM_CELL_WORD_1(smob));
}
auto u_ptr{static_cast<std::unique_ptr<GncOptionDB>*>(c_ptr)};
return u_ptr->get();
}
void
gnc_register_string_option(GncOptionDB* db, const char* section,
const char* name, const char* key,

View File

@ -59,6 +59,20 @@ GncOptionDB* gnc_option_db_new(void);
*/
void gnc_option_db_destroy(GncOptionDB* odb);
/**
* Obtain a GncOptionDB* from Scheme
*
* When report or stylesheet options are generated in Scheme the GncObjectDB is
* wrapped in a std::unique_ptr and then in a Guile SMOB by SWIG. The GUI code
* needs a reference to the GncObjectDB and we don't want to introduce swig
* library dependencies.
*
* @param dispatch The scheme dispatch function returned by gnc:new-options
* @return GncOptiondDB* Do not free this pointer!
*/
GncOptionDB*
gnc_get_optiondb_from_dispatcher(SCM dispatcher);
/**
* Write all changed ui_item values to their options.
* @param odb The GncOptionDB.

View File

@ -103,7 +103,11 @@
(let ((optiondb (new-gnc-optiondb)))
(define (dispatch key)
optiondb)
dispatch))
dispatch))
;; Use the dispatch function to get the optiondb
(define-public (gnc:options-get dispatch)
(dispatch 'get))
(define-public (gnc:options-set-default-section optiondb section)
(GncOptionDB-set-default-section (GncOptionDBPtr-get (optiondb 'set-default-section)) section))