mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-30 12:44:01 -06:00
94bb28d9ab
Ensure that all includes of swig-runtime.h are *followed* by including guile-mappings.h so that the defines masking scm_to_utf8_string and scm_from_utf8_string are undone.
2919 lines
99 KiB
C
2919 lines
99 KiB
C
/********************************************************************\
|
|
* option-util.c -- GNOME<->guile option interface *
|
|
* Copyright (C) 2000 Dave Peticolas *
|
|
* Copyright (C) 2017 Aaron Laws *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License*
|
|
* along with this program; if not, contact: *
|
|
* *
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
|
\********************************************************************/
|
|
|
|
#include <config.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
|
|
#include "Account.h"
|
|
#include "option-util.h"
|
|
#include "glib-helpers.h"
|
|
#include "gnc-guile-utils.h"
|
|
#include "qof.h"
|
|
#include "swig-runtime.h"
|
|
#include "guile-mappings.h"
|
|
|
|
|
|
/* TODO:
|
|
|
|
- for make-date-option, there seems to be only support for getting,
|
|
not for setting.
|
|
*/
|
|
|
|
|
|
/****** Structures *************************************************/
|
|
|
|
struct gnc_option
|
|
{
|
|
/* Handle to the scheme-side option */
|
|
SCM guile_option;
|
|
|
|
/* Flag to indicate change by the UI */
|
|
gboolean changed;
|
|
|
|
/* The widget which is holding this option */
|
|
gpointer widget;
|
|
|
|
/* The option db which holds this option */
|
|
GNCOptionDB *odb;
|
|
};
|
|
|
|
struct gnc_option_section
|
|
{
|
|
char * section_name;
|
|
|
|
GSList * options;
|
|
};
|
|
|
|
struct gnc_option_db
|
|
{
|
|
SCM guile_options;
|
|
|
|
GSList *option_sections;
|
|
|
|
gboolean options_dirty;
|
|
|
|
GNCOptionDBHandle handle;
|
|
|
|
GNCOptionGetUIValue get_ui_value;
|
|
GNCOptionSetUIValue set_ui_value;
|
|
GNCOptionSetSelectable set_selectable;
|
|
};
|
|
|
|
typedef struct _Getters Getters;
|
|
struct _Getters
|
|
{
|
|
SCM section;
|
|
SCM name;
|
|
SCM type;
|
|
SCM sort_tag;
|
|
SCM documentation;
|
|
SCM getter;
|
|
SCM setter;
|
|
SCM default_getter;
|
|
SCM value_validator;
|
|
SCM option_data;
|
|
SCM index_to_name;
|
|
SCM index_to_description;
|
|
SCM index_to_value;
|
|
SCM value_to_index;
|
|
SCM number_of_indices;
|
|
SCM option_widget_changed_cb;
|
|
SCM date_option_subtype;
|
|
SCM date_option_show_time;
|
|
SCM date_option_value_type;
|
|
SCM date_option_value_absolute;
|
|
SCM date_option_value_relative;
|
|
SCM plot_size_option_value_type;
|
|
SCM plot_size_option_value;
|
|
SCM currency_accounting_option_currency_doc_string;
|
|
SCM currency_accounting_option_default_currency;
|
|
SCM currency_accounting_option_policy_doc_string;
|
|
SCM currency_accounting_option_default_policy;
|
|
SCM currency_accounting_option_gain_loss_account_doc_string;
|
|
SCM currency_accounting_option_method;
|
|
SCM currency_accounting_option_book_currency;
|
|
SCM currency_accounting_option_selected_default_policy;
|
|
SCM currency_accounting_option_selected_default_gain_loss_account;
|
|
};
|
|
|
|
|
|
/****** Globals ****************************************************/
|
|
|
|
static Getters getters = {0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
/* This static indicates the debugging module this .o belongs to. */
|
|
static QofLogModule log_module = GNC_MOD_GUI;
|
|
|
|
static GHashTable *option_dbs = NULL;
|
|
static int last_db_handle = 0;
|
|
|
|
|
|
/*******************************************************************/
|
|
void
|
|
gnc_option_set_changed (GNCOption *option, gboolean changed)
|
|
{
|
|
g_return_if_fail (option != NULL);
|
|
option->changed = changed;
|
|
}
|
|
|
|
gpointer
|
|
gnc_option_get_widget (GNCOption *option)
|
|
{
|
|
if (!option) return NULL;
|
|
return option->widget;
|
|
}
|
|
|
|
void
|
|
gnc_option_set_widget (GNCOption *option, gpointer widget)
|
|
{
|
|
g_return_if_fail (option != NULL);
|
|
option->widget = widget;
|
|
}
|
|
|
|
SCM
|
|
gnc_option_get_ui_value (GNCOption *option)
|
|
{
|
|
g_return_val_if_fail (option != NULL, SCM_UNDEFINED);
|
|
g_return_val_if_fail (option->odb != NULL, SCM_UNDEFINED);
|
|
g_return_val_if_fail (option->odb->get_ui_value != NULL, SCM_UNDEFINED);
|
|
|
|
return option->odb->get_ui_value (option);
|
|
}
|
|
|
|
void
|
|
gnc_option_set_ui_value (GNCOption *option, gboolean use_default)
|
|
{
|
|
g_return_if_fail (option != NULL);
|
|
g_return_if_fail (option->odb != NULL);
|
|
|
|
if (!option->odb->set_ui_value)
|
|
return;
|
|
|
|
option->odb->set_ui_value (option, use_default);
|
|
}
|
|
|
|
void
|
|
gnc_option_set_selectable (GNCOption *option, gboolean selectable)
|
|
{
|
|
g_return_if_fail (option != NULL);
|
|
g_return_if_fail (option->odb != NULL);
|
|
g_return_if_fail (option->odb->set_selectable != NULL);
|
|
|
|
option->odb->set_selectable (option, selectable);
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_init *
|
|
* initialize the options structures from the guile side *
|
|
* *
|
|
* Args: odb - the option database to initialize *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
static void
|
|
gnc_option_db_init(GNCOptionDB *odb)
|
|
{
|
|
SCM func = scm_c_eval_string("gnc:send-options");
|
|
|
|
scm_call_2(func, scm_from_int (odb->handle), odb->guile_options);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_new *
|
|
* allocate a new option database and initialize its values *
|
|
* *
|
|
* Args: guile_options - SCM handle to options *
|
|
* Returns: a new option database *
|
|
\********************************************************************/
|
|
GNCOptionDB *
|
|
gnc_option_db_new(SCM guile_options)
|
|
{
|
|
GNCOptionDB *odb;
|
|
GNCOptionDB *lookup;
|
|
|
|
odb = g_new0(GNCOptionDB, 1);
|
|
|
|
odb->guile_options = guile_options;
|
|
scm_gc_protect_object(guile_options);
|
|
|
|
odb->option_sections = NULL;
|
|
odb->options_dirty = FALSE;
|
|
|
|
if (option_dbs == NULL)
|
|
option_dbs = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
do
|
|
{
|
|
odb->handle = last_db_handle++;
|
|
lookup = g_hash_table_lookup(option_dbs, &odb->handle);
|
|
}
|
|
while (lookup != NULL);
|
|
|
|
g_hash_table_insert(option_dbs, &odb->handle, odb);
|
|
|
|
gnc_option_db_init(odb);
|
|
|
|
return odb;
|
|
}
|
|
|
|
/* Create an option DB for a particular data type */
|
|
/* For now, this is global, just like when it was in guile.
|
|
But, it should be make per-book. */
|
|
static GHashTable *kvp_registry = NULL;
|
|
|
|
static void
|
|
init_table(void)
|
|
{
|
|
if (!kvp_registry)
|
|
kvp_registry = g_hash_table_new(g_str_hash, g_str_equal);
|
|
}
|
|
|
|
|
|
/* create a new options object for the requested type */
|
|
static SCM
|
|
gnc_make_kvp_options(QofIdType id_type)
|
|
{
|
|
GList *list, *p;
|
|
SCM gnc_new_options = SCM_UNDEFINED;
|
|
SCM options = SCM_UNDEFINED;
|
|
|
|
init_table();
|
|
list = g_hash_table_lookup(kvp_registry, id_type);
|
|
gnc_new_options = scm_c_eval_string("gnc:new-options");
|
|
options = scm_call_0(gnc_new_options);
|
|
|
|
for (p = list; p; p = p->next)
|
|
{
|
|
SCM generator = p->data;
|
|
scm_call_1(generator, options);
|
|
}
|
|
return options;
|
|
}
|
|
|
|
GNCOptionDB *
|
|
gnc_option_db_new_for_type(QofIdType id_type)
|
|
{
|
|
SCM options;
|
|
|
|
if (!id_type) return NULL;
|
|
options = gnc_make_kvp_options(id_type);
|
|
return gnc_option_db_new (options);
|
|
}
|
|
|
|
void
|
|
gnc_option_db_load(GNCOptionDB* odb, QofBook *book)
|
|
{
|
|
static SCM kvp_to_scm = SCM_UNDEFINED;
|
|
SCM scm_book;
|
|
|
|
if (!odb || !book) return;
|
|
|
|
if (kvp_to_scm == SCM_UNDEFINED)
|
|
{
|
|
kvp_to_scm = scm_c_eval_string("gnc:options-kvp->scm");
|
|
if (!scm_is_procedure (kvp_to_scm))
|
|
{
|
|
PERR ("not a procedure\n");
|
|
kvp_to_scm = SCM_UNDEFINED;
|
|
return;
|
|
}
|
|
}
|
|
|
|
scm_book = SWIG_NewPointerObj(book, SWIG_TypeQuery("_p_QofBook"), 0);
|
|
|
|
scm_call_2 (kvp_to_scm, odb->guile_options, scm_book);
|
|
}
|
|
|
|
void
|
|
gnc_option_db_save(GNCOptionDB* odb, QofBook *book, gboolean clear_all)
|
|
{
|
|
static SCM scm_to_kvp = SCM_UNDEFINED;
|
|
SCM scm_book;
|
|
SCM scm_clear_all;
|
|
|
|
if (!odb || !book) return;
|
|
|
|
if (scm_to_kvp == SCM_UNDEFINED)
|
|
{
|
|
scm_to_kvp = scm_c_eval_string("gnc:options-scm->kvp");
|
|
if (!scm_is_procedure (scm_to_kvp))
|
|
{
|
|
PERR ("not a procedure\n");
|
|
scm_to_kvp = SCM_UNDEFINED;
|
|
return;
|
|
}
|
|
}
|
|
|
|
scm_book = SWIG_NewPointerObj(book, SWIG_TypeQuery("_p_QofBook"), 0);
|
|
scm_clear_all = scm_from_bool (clear_all);
|
|
|
|
scm_call_3 (scm_to_kvp, odb->guile_options, scm_book, scm_clear_all);
|
|
}
|
|
/********************************************************************\
|
|
* gnc_option_db_destroy *
|
|
* unregister the scheme options and free all the memory *
|
|
* associated with an option database, including the database *
|
|
* itself *
|
|
* *
|
|
* Args: options database to destroy *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_destroy(GNCOptionDB *odb)
|
|
{
|
|
GSList *snode;
|
|
|
|
if (odb == NULL)
|
|
return;
|
|
|
|
for (snode = odb->option_sections; snode; snode = snode->next)
|
|
{
|
|
GNCOptionSection *section = snode->data;
|
|
GSList *onode;
|
|
|
|
for (onode = section->options; onode; onode = onode->next)
|
|
{
|
|
GNCOption *option = onode->data;
|
|
|
|
scm_gc_unprotect_object(option->guile_option);
|
|
g_free (option);
|
|
}
|
|
|
|
/* Free the option list */
|
|
g_slist_free(section->options);
|
|
section->options = NULL;
|
|
|
|
if (section->section_name != NULL)
|
|
free(section->section_name);
|
|
section->section_name = NULL;
|
|
|
|
g_free (section);
|
|
}
|
|
|
|
g_slist_free(odb->option_sections);
|
|
|
|
odb->option_sections = NULL;
|
|
odb->options_dirty = FALSE;
|
|
|
|
g_hash_table_remove(option_dbs, &odb->handle);
|
|
|
|
if (g_hash_table_size(option_dbs) == 0)
|
|
{
|
|
g_hash_table_destroy(option_dbs);
|
|
option_dbs = NULL;
|
|
}
|
|
|
|
scm_gc_unprotect_object(odb->guile_options);
|
|
odb->guile_options = SCM_UNDEFINED;
|
|
|
|
g_free(odb);
|
|
}
|
|
|
|
void
|
|
gnc_option_db_set_ui_callbacks (GNCOptionDB *odb,
|
|
GNCOptionGetUIValue get_ui_value,
|
|
GNCOptionSetUIValue set_ui_value,
|
|
GNCOptionSetSelectable set_selectable)
|
|
{
|
|
g_return_if_fail (odb != NULL);
|
|
|
|
odb->get_ui_value = get_ui_value;
|
|
odb->set_ui_value = set_ui_value;
|
|
odb->set_selectable = set_selectable;
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_register_change_callback *
|
|
* register a callback to be called whenever an option changes *
|
|
* *
|
|
* Args: odb - the option database to register with *
|
|
* callback - the callback function to register *
|
|
* user_data - the user data for the callback *
|
|
* section - the section to get callbacks for. *
|
|
* If NULL, get callbacks for any section changes.*
|
|
* name - the option name to get callbacks for. *
|
|
* If NULL, get callbacks for any option in the *
|
|
* section. Only used if section is non-NULL. *
|
|
* Returns: SCM handle for unregistering *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_db_register_change_callback(GNCOptionDB *odb,
|
|
GNCOptionChangeCallback callback,
|
|
gpointer data,
|
|
const char *section,
|
|
const char *name)
|
|
{
|
|
SCM register_proc;
|
|
SCM arg;
|
|
SCM args;
|
|
|
|
if (!odb || !callback)
|
|
return SCM_UNDEFINED;
|
|
|
|
/* Get the register procedure */
|
|
register_proc = scm_c_eval_string("gnc:options-register-c-callback");
|
|
if (!scm_is_procedure(register_proc))
|
|
{
|
|
PERR("not a procedure\n");
|
|
return SCM_UNDEFINED;
|
|
}
|
|
|
|
/* Now build the args list for apply */
|
|
args = SCM_EOL;
|
|
|
|
/* first the guile options database */
|
|
args = scm_cons(odb->guile_options, args);
|
|
|
|
/* next the data */
|
|
arg = SWIG_NewPointerObj(data, SWIG_TypeQuery("_p_void"), 0);
|
|
args = scm_cons(arg, args);
|
|
|
|
/* next the callback */
|
|
arg = SWIG_NewPointerObj(
|
|
callback, SWIG_TypeQuery("GNCOptionChangeCallback"), 0);
|
|
args = scm_cons(arg, args);
|
|
|
|
/* next the name */
|
|
if (name == NULL)
|
|
{
|
|
arg = SCM_BOOL_F;
|
|
}
|
|
else
|
|
{
|
|
arg = scm_from_utf8_string(name);
|
|
}
|
|
args = scm_cons(arg, args);
|
|
|
|
/* next the section */
|
|
if (section == NULL)
|
|
{
|
|
arg = SCM_BOOL_F;
|
|
}
|
|
else
|
|
{
|
|
arg = scm_from_utf8_string(section);
|
|
}
|
|
args = scm_cons(arg, args);
|
|
|
|
/* now apply the procedure */
|
|
return scm_apply(register_proc, args, SCM_EOL);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_unregister_change_callback_id *
|
|
* unregister the change callback associated with the given id *
|
|
* *
|
|
* Args: odb - the option database to register with *
|
|
* callback - the callback function to register *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_unregister_change_callback_id(GNCOptionDB *odb, SCM callback_id)
|
|
{
|
|
SCM proc;
|
|
|
|
if (callback_id == SCM_UNDEFINED)
|
|
return;
|
|
|
|
proc = scm_c_eval_string("gnc:options-unregister-callback-id");
|
|
if (!scm_is_procedure(proc))
|
|
{
|
|
PERR("not a procedure\n");
|
|
return;
|
|
}
|
|
|
|
scm_call_2(proc, callback_id, odb->guile_options);
|
|
}
|
|
|
|
void
|
|
gncp_option_invoke_callback (GNCOptionChangeCallback callback, void *data)
|
|
{
|
|
callback (data);
|
|
}
|
|
|
|
static void
|
|
gnc_call_option_change_callbacks(GNCOptionDB *odb)
|
|
{
|
|
SCM proc;
|
|
|
|
proc = scm_c_eval_string("gnc:options-run-callbacks");
|
|
if (!scm_is_procedure(proc))
|
|
{
|
|
PERR("not a procedure\n");
|
|
return;
|
|
}
|
|
|
|
scm_call_1(proc, odb->guile_options);
|
|
}
|
|
|
|
|
|
static void
|
|
initialize_getters(void)
|
|
{
|
|
static gboolean getters_initialized = FALSE;
|
|
|
|
if (getters_initialized)
|
|
return;
|
|
|
|
getters.section = scm_c_eval_string("gnc:option-section");
|
|
getters.name = scm_c_eval_string("gnc:option-name");
|
|
getters.type = scm_c_eval_string("gnc:option-type");
|
|
getters.sort_tag = scm_c_eval_string("gnc:option-sort-tag");
|
|
getters.documentation =
|
|
scm_c_eval_string("gnc:option-documentation");
|
|
getters.getter = scm_c_eval_string("gnc:option-getter");
|
|
getters.setter = scm_c_eval_string("gnc:option-setter");
|
|
getters.default_getter =
|
|
scm_c_eval_string("gnc:option-default-getter");
|
|
getters.value_validator =
|
|
scm_c_eval_string("gnc:option-value-validator");
|
|
getters.option_data = scm_c_eval_string("gnc:option-data");
|
|
getters.index_to_name = scm_c_eval_string("gnc:option-index-get-name");
|
|
getters.index_to_description =
|
|
scm_c_eval_string("gnc:option-index-get-description");
|
|
getters.number_of_indices = scm_c_eval_string("gnc:option-number-of-indices");
|
|
getters.index_to_value = scm_c_eval_string("gnc:option-index-get-value");
|
|
getters.value_to_index = scm_c_eval_string("gnc:option-value-get-index");
|
|
getters.option_widget_changed_cb =
|
|
scm_c_eval_string("gnc:option-widget-changed-proc");
|
|
getters.date_option_subtype = scm_c_eval_string("gnc:date-option-get-subtype");
|
|
getters.date_option_show_time = scm_c_eval_string("gnc:date-option-show-time?");
|
|
getters.date_option_value_type = scm_c_eval_string ("gnc:date-option-value-type");
|
|
getters.date_option_value_absolute =
|
|
scm_c_eval_string("gnc:date-option-absolute-time");
|
|
getters.date_option_value_relative =
|
|
scm_c_eval_string("gnc:date-option-relative-time");
|
|
getters.plot_size_option_value_type = scm_c_eval_string ("gnc:plot-size-option-value-type");
|
|
getters.plot_size_option_value = scm_c_eval_string("gnc:plot-size-option-value");
|
|
getters.currency_accounting_option_currency_doc_string =
|
|
scm_c_eval_string("gnc:currency-accounting-option-get-curr-doc-string");
|
|
getters.currency_accounting_option_default_currency =
|
|
scm_c_eval_string("gnc:currency-accounting-option-get-default-curr");
|
|
getters.currency_accounting_option_policy_doc_string =
|
|
scm_c_eval_string("gnc:currency-accounting-option-get-policy-doc-string");
|
|
getters.currency_accounting_option_default_policy =
|
|
scm_c_eval_string("gnc:currency-accounting-option-get-default-policy");
|
|
getters.currency_accounting_option_gain_loss_account_doc_string =
|
|
scm_c_eval_string("gnc:currency-accounting-option-get-gain-loss-account-doc-string");
|
|
getters.currency_accounting_option_method =
|
|
scm_c_eval_string("gnc:currency-accounting-option-selected-method");
|
|
getters.currency_accounting_option_book_currency =
|
|
scm_c_eval_string("gnc:currency-accounting-option-selected-currency");
|
|
getters.currency_accounting_option_selected_default_policy =
|
|
scm_c_eval_string("gnc:currency-accounting-option-selected-policy");
|
|
getters.currency_accounting_option_selected_default_gain_loss_account =
|
|
scm_c_eval_string("gnc:currency-accounting-option-selected-gain-loss-account");
|
|
|
|
getters_initialized = TRUE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_section *
|
|
* returns the malloc'ed section name of the option, or NULL *
|
|
* if it can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_section(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string(getters.section, option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_name *
|
|
* returns the malloc'ed name of the option, or NULL *
|
|
* if it can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_name(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string(getters.name, option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_type *
|
|
* returns the malloc'ed type of the option, or NULL *
|
|
* if it can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_type(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_symbol_to_string(getters.type,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_sort_tag *
|
|
* returns the malloc'ed sort tag of the option, or NULL *
|
|
* if it can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_sort_tag(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string(getters.sort_tag, option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_documentation *
|
|
* returns the malloc'ed documentation string of the option, or *
|
|
* NULL if it can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_documentation(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string(getters.documentation,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_getter *
|
|
* returns the SCM handle for the option getter function. *
|
|
* This value should be tested with scm_procedure_p before use. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM handle to function *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_getter(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_procedure(getters.getter,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_setter *
|
|
* returns the SCM handle for the option setter function. *
|
|
* This value should be tested with scm_procedure_p before use. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM handle to function *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_setter(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_procedure(getters.setter,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_default_getter *
|
|
* returns the SCM handle for the option default_getter function. *
|
|
* This value should be tested with scm_procedure_p before use. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM handle to function *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_default_getter(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_procedure(getters.default_getter,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_value_validator *
|
|
* returns the SCM handle for the option value validator function.*
|
|
* This value should be tested with scm_procedure_p before use. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM handle to function *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_value_validator(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_procedure(getters.value_validator,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_widget_changed_proc_getter *
|
|
* returns the SCM handle for the function to be called if the *
|
|
* GUI widget representing the option is changed. *
|
|
* This value should be tested with scm_procedure_p before use. *
|
|
* If no such function exists, returns SCM_UNDEFINED. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM handle to function *
|
|
* If no such function exists, returns SCM_UNDEFINED. *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_widget_changed_proc_getter(GNCOption *option)
|
|
{
|
|
SCM cb;
|
|
|
|
initialize_getters();
|
|
|
|
if ( scm_is_procedure( getters.option_widget_changed_cb ) )
|
|
{
|
|
/* call the callback function getter to get the actual callback function */
|
|
cb = scm_call_1(getters.option_widget_changed_cb, option->guile_option);
|
|
|
|
if ( scm_is_procedure( cb ) ) /* a callback exists */
|
|
{
|
|
return( cb );
|
|
}
|
|
/* else no callback exists - this is a legal situation */
|
|
}
|
|
else /* getters not set up correctly? */
|
|
{
|
|
PERR("getters.option_widget_changed_cb is not a valid procedure\n");
|
|
}
|
|
|
|
return( SCM_UNDEFINED );
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_call_option_widget_changed_proc *
|
|
* If there is an option_widget_changed_cb for this option, call *
|
|
* it with the SCM value of the option that is passed in. If *
|
|
* there is no such callback function or value, do nothing. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: void *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_call_option_widget_changed_proc(GNCOption *option)
|
|
{
|
|
SCM cb, value;
|
|
|
|
cb = gnc_option_widget_changed_proc_getter(option);
|
|
|
|
if ( cb != SCM_UNDEFINED )
|
|
{
|
|
value = gnc_option_get_ui_value(option);
|
|
|
|
if ( value != SCM_UNDEFINED )
|
|
{
|
|
scm_call_1(cb, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_num_permissible_values *
|
|
* returns the number of permissible values in the option, or *
|
|
* -1 if there are no values available. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: number of permissible options or -1 *
|
|
\********************************************************************/
|
|
int
|
|
gnc_option_num_permissible_values(GNCOption *option)
|
|
{
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
value = scm_call_1(getters.number_of_indices, option->guile_option);
|
|
|
|
if (scm_is_exact(value))
|
|
{
|
|
return scm_to_int(value);
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_permissible_value_index *
|
|
* returns the index of the permissible value matching the *
|
|
* provided value, or -1 if it couldn't be found *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* value - the SCM handle of the value *
|
|
* Returns: index of permissible value, or -1 *
|
|
\********************************************************************/
|
|
int
|
|
gnc_option_permissible_value_index(GNCOption *option, SCM search_value)
|
|
{
|
|
SCM value;
|
|
value = scm_call_2(getters.value_to_index, option->guile_option, search_value);
|
|
if (value == SCM_BOOL_F)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return scm_to_int(value);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_permissible_value *
|
|
* returns the SCM handle to the indexth permissible value in the *
|
|
* option, or SCM_UNDEFINED if the index was out of range or *
|
|
* there was some other problem. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* index - the index of the permissible value *
|
|
* Returns: SCM handle to option value or SCM_UNDEFINED *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_permissible_value(GNCOption *option, int index)
|
|
{
|
|
SCM value;
|
|
|
|
if (index < 0)
|
|
return SCM_UNDEFINED;
|
|
|
|
initialize_getters();
|
|
|
|
value = scm_call_2(getters.index_to_value, option->guile_option,
|
|
scm_from_int (index));
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_permissible_value_name *
|
|
* returns the malloc'd name of the indexth permissible value in *
|
|
* the option, or NULL if the index was out of range or there are *
|
|
* no values available. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* index - the index of the permissible value *
|
|
* Returns: malloc'd name of permissible value or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_permissible_value_name(GNCOption *option, int index)
|
|
{
|
|
SCM name;
|
|
|
|
if (index < 0)
|
|
return NULL;
|
|
|
|
initialize_getters();
|
|
|
|
name = scm_call_2(getters.index_to_name, option->guile_option,
|
|
scm_from_int (index));
|
|
if (name == SCM_UNDEFINED)
|
|
return NULL;
|
|
if (!scm_is_string(name))
|
|
return NULL;
|
|
|
|
return gnc_scm_to_utf8_string (name);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_permissible_value_description *
|
|
* returns the malloc'd description of the indexth permissible *
|
|
* value in the option, or NULL if the index was out of range or *
|
|
* there are no values available. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* index - the index of the permissible value *
|
|
* Returns: malloc'd description of permissible value or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_permissible_value_description(GNCOption *option, int index)
|
|
{
|
|
SCM help;
|
|
|
|
if (index < 0)
|
|
return NULL;
|
|
|
|
initialize_getters();
|
|
|
|
help = scm_call_2(getters.index_to_description, option->guile_option,
|
|
scm_from_int (index));
|
|
if (help == SCM_UNDEFINED)
|
|
return NULL;
|
|
if (!scm_is_string(help))
|
|
return NULL;
|
|
|
|
return gnc_scm_to_utf8_string (help);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_show_time *
|
|
* returns true if the gui should display the time as well as *
|
|
* the date for this option. Only use this for date options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: true if time should be shown *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_show_time(GNCOption *option)
|
|
{
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
value = scm_call_1(getters.date_option_show_time, option->guile_option);
|
|
|
|
return scm_is_true(value);
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_get_option_data *
|
|
* returns the option data of this option *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: the option data *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_get_option_data(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1(getters.option_data, option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_multiple_selection *
|
|
* returns true if the gui should allow multiple selection of *
|
|
* accounts. Only use this for account options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: true if multiple selection allowed *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_multiple_selection(GNCOption *option)
|
|
{
|
|
SCM pair;
|
|
|
|
initialize_getters();
|
|
|
|
pair = scm_call_1(getters.option_data, option->guile_option);
|
|
|
|
return !scm_is_true(scm_not(SCM_CAR(pair)));
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_get_account_type_list *
|
|
* returns the list of account_types in the option (or NULL if *
|
|
* no special list is provided). Only use this for account *
|
|
* options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: GList of account types (must be freed by caller) *
|
|
\********************************************************************/
|
|
GList *
|
|
gnc_option_get_account_type_list(GNCOption *option)
|
|
{
|
|
SCM pair;
|
|
SCM lst;
|
|
GList *type_list = NULL;
|
|
|
|
initialize_getters();
|
|
|
|
pair = scm_call_1(getters.option_data, option->guile_option);
|
|
lst = SCM_CDR(pair);
|
|
|
|
while (!scm_is_null (lst))
|
|
{
|
|
GNCAccountType type;
|
|
SCM item;
|
|
|
|
/* Compute this item and the rest of the list */
|
|
item = SCM_CAR (lst);
|
|
lst = SCM_CDR (lst);
|
|
|
|
if (scm_is_false (scm_integer_p (item)))
|
|
{
|
|
PERR ("Invalid type");
|
|
}
|
|
else
|
|
{
|
|
type = scm_to_long (item);
|
|
type_list = g_list_prepend (type_list, GINT_TO_POINTER (type));
|
|
}
|
|
}
|
|
|
|
return g_list_reverse (type_list);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_get_range_info *
|
|
* returns the range info for a number range option in the pointer*
|
|
* arguments. NULL arguments are ignored. Use only for number *
|
|
* range options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: true if everything went ok :) *
|
|
\********************************************************************/
|
|
gboolean gnc_option_get_range_info(GNCOption *option,
|
|
double *lower_bound,
|
|
double *upper_bound,
|
|
int *num_decimals,
|
|
double *step_size)
|
|
{
|
|
SCM list;
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
list = scm_call_1(getters.option_data, option->guile_option);
|
|
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
/* lower bound */
|
|
value = SCM_CAR(list);
|
|
list = SCM_CDR(list);
|
|
|
|
if (!scm_is_number(value))
|
|
return FALSE;
|
|
|
|
if (lower_bound != NULL)
|
|
*lower_bound = scm_to_double(value);
|
|
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
/* upper bound */
|
|
value = SCM_CAR(list);
|
|
list = SCM_CDR(list);
|
|
|
|
if (!scm_is_number(value))
|
|
return FALSE;
|
|
|
|
if (upper_bound != NULL)
|
|
*upper_bound = scm_to_double(value);
|
|
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
/* number of decimals */
|
|
value = SCM_CAR(list);
|
|
list = SCM_CDR(list);
|
|
|
|
if (!scm_is_number(value))
|
|
return FALSE;
|
|
|
|
/* Guile-1.6 returns this as a double, so let's use that in all cases.
|
|
* This is still safe for earlier guiles, too -- tested with 1.3.4.
|
|
*/
|
|
if (num_decimals != NULL)
|
|
{
|
|
double decimals = scm_to_double(value);
|
|
*num_decimals = (int)decimals;
|
|
}
|
|
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
/* step size */
|
|
value = SCM_CAR(list);
|
|
|
|
if (!scm_is_number(value))
|
|
return FALSE;
|
|
|
|
if (step_size != NULL)
|
|
*step_size = scm_to_double(value);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_color_range *
|
|
* returns the color range for rgba values. *
|
|
* Only use this for color options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: color range for the option *
|
|
\********************************************************************/
|
|
gdouble
|
|
gnc_option_color_range(GNCOption *option)
|
|
{
|
|
SCM list;
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
list = scm_call_1(getters.option_data, option->guile_option);
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return 0.0;
|
|
|
|
value = SCM_CAR(list);
|
|
if (!scm_is_number(value))
|
|
return 0.0;
|
|
|
|
return scm_to_double(value);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_use_alpha *
|
|
* returns true if the color option should use alpha transparency *
|
|
* Only use this for color options. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: true if alpha transparency should be used *
|
|
\********************************************************************/
|
|
gdouble
|
|
gnc_option_use_alpha(GNCOption *option)
|
|
{
|
|
SCM list;
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
list = scm_call_1(getters.option_data, option->guile_option);
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
list = SCM_CDR(list);
|
|
if (!scm_is_list(list) || scm_is_null(list))
|
|
return FALSE;
|
|
|
|
value = SCM_CAR(list);
|
|
if (!scm_is_bool(value))
|
|
return FALSE;
|
|
|
|
return scm_is_true(value);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_get_color_argb *
|
|
* returns the argb value of a color option *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: argb value of option *
|
|
\********************************************************************/
|
|
guint32
|
|
gnc_option_get_color_argb(GNCOption *option)
|
|
{
|
|
gdouble red, green, blue, alpha;
|
|
guint32 color = 0;
|
|
|
|
if (!gnc_option_get_color_info(option, FALSE, &red, &green, &blue, &alpha))
|
|
return 0;
|
|
|
|
color |= (guint32) (alpha * 255.0);
|
|
color <<= 8;
|
|
|
|
color |= (guint32) (red * 255.0);
|
|
color <<= 8;
|
|
|
|
color |= (guint32) (green * 255.0);
|
|
color <<= 8;
|
|
|
|
color |= (guint32) (blue * 255.0);
|
|
|
|
return color;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_get_color_info *
|
|
* gets the color information from a color option. rgba values *
|
|
* returned are between 0.0 and 1.0. *
|
|
* *
|
|
* Args: option - option to get info from *
|
|
* use_default - use the default or current value *
|
|
* red - where to store the red value *
|
|
* blue - where to store the blue value *
|
|
* green - where to store the green value *
|
|
* alpha - where to store the alpha value *
|
|
* Return: true if everything went ok *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_get_color_info(GNCOption *option,
|
|
gboolean use_default,
|
|
gdouble *red,
|
|
gdouble *green,
|
|
gdouble *blue,
|
|
gdouble *alpha)
|
|
{
|
|
gdouble scale;
|
|
gdouble rgba;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
if (option == NULL)
|
|
return FALSE;
|
|
|
|
if (use_default)
|
|
getter = gnc_option_default_getter(option);
|
|
else
|
|
getter = gnc_option_getter(option);
|
|
if (getter == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
value = scm_call_0(getter);
|
|
if (!scm_is_list(value) || scm_is_null(value) || !scm_is_number(SCM_CAR(value)))
|
|
return FALSE;
|
|
|
|
scale = gnc_option_color_range(option);
|
|
if (scale <= 0.0)
|
|
return FALSE;
|
|
|
|
scale = 1.0 / scale;
|
|
|
|
rgba = scm_to_double(SCM_CAR(value));
|
|
if (red != NULL)
|
|
*red = MIN(1.0, rgba * scale);
|
|
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_list(value) || scm_is_null(value) || !scm_is_number(SCM_CAR(value)))
|
|
return FALSE;
|
|
|
|
rgba = scm_to_double(SCM_CAR(value));
|
|
if (green != NULL)
|
|
*green = MIN(1.0, rgba * scale);
|
|
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_list(value) || scm_is_null(value) || !scm_is_number(SCM_CAR(value)))
|
|
return FALSE;
|
|
|
|
rgba = scm_to_double(SCM_CAR(value));
|
|
if (blue != NULL)
|
|
*blue = MIN(1.0, rgba * scale);
|
|
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_list(value) || scm_is_null(value) || !scm_is_number(SCM_CAR(value)))
|
|
return FALSE;
|
|
|
|
rgba = scm_to_double(SCM_CAR(value));
|
|
if (alpha != NULL)
|
|
*alpha = MIN(1.0, rgba * scale);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_set_default *
|
|
* set the option to its default value *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_set_default(GNCOption *option)
|
|
{
|
|
SCM default_getter;
|
|
SCM setter;
|
|
SCM value;
|
|
|
|
if (option == NULL)
|
|
return;
|
|
|
|
default_getter = gnc_option_default_getter(option);
|
|
if (default_getter == SCM_UNDEFINED)
|
|
return;
|
|
|
|
value = scm_call_0(default_getter);
|
|
|
|
setter = gnc_option_setter(option);
|
|
if (setter == SCM_UNDEFINED)
|
|
return;
|
|
|
|
scm_call_1(setter, value);
|
|
}
|
|
|
|
|
|
static gint
|
|
compare_sections(gconstpointer a, gconstpointer b)
|
|
{
|
|
const GNCOptionSection *sa = a;
|
|
const GNCOptionSection *sb = b;
|
|
|
|
return g_strcmp0(sa->section_name, sb->section_name);
|
|
}
|
|
|
|
static gint
|
|
compare_option_tags(gconstpointer a, gconstpointer b)
|
|
{
|
|
GNCOption *oa = (GNCOption *) a;
|
|
GNCOption *ob = (GNCOption *) b;
|
|
char *tag_a = gnc_option_sort_tag(oa);
|
|
char *tag_b = gnc_option_sort_tag(ob);
|
|
gint result;
|
|
|
|
result = g_strcmp0(tag_a, tag_b);
|
|
|
|
if (tag_a != NULL)
|
|
free(tag_a);
|
|
|
|
if (tag_b != NULL)
|
|
free(tag_b);
|
|
|
|
return result;
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_dirty *
|
|
* returns true if guile has registered more options into the *
|
|
* database since the last time the database was cleaned. *
|
|
* *
|
|
* Returns: dirty flag *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_dirty(GNCOptionDB *odb)
|
|
{
|
|
g_return_val_if_fail (odb, FALSE);
|
|
|
|
return odb->options_dirty;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_clean *
|
|
* resets the dirty flag of the option database *
|
|
* *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_clean(GNCOptionDB *odb)
|
|
{
|
|
g_return_if_fail (odb);
|
|
|
|
odb->options_dirty = FALSE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* _gnc_option_db_register_option *
|
|
* registers an option with an option database. Intended to be *
|
|
* called from guile. *
|
|
* *
|
|
* Args: odb - the option database *
|
|
* option - the guile option *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_register_option(GNCOptionDBHandle handle, SCM guile_option)
|
|
{
|
|
GNCOptionDB *odb;
|
|
GNCOption *option;
|
|
GNCOptionSection *section;
|
|
|
|
odb = g_hash_table_lookup(option_dbs, &handle);
|
|
|
|
g_return_if_fail (odb != NULL);
|
|
|
|
odb->options_dirty = TRUE;
|
|
|
|
/* Make the option structure */
|
|
option = g_new0(GNCOption, 1);
|
|
option->guile_option = guile_option;
|
|
option->changed = FALSE;
|
|
option->widget = NULL;
|
|
option->odb = odb;
|
|
|
|
/* Prevent guile from garbage collecting the option */
|
|
scm_gc_protect_object(guile_option);
|
|
|
|
/* Make the section structure */
|
|
section = g_new0(GNCOptionSection, 1);
|
|
section->section_name = gnc_option_section(option);
|
|
section->options = NULL;
|
|
|
|
/* See if the section is already there */
|
|
{
|
|
GSList *old;
|
|
|
|
old = g_slist_find_custom(odb->option_sections, section, compare_sections);
|
|
|
|
if (old != NULL)
|
|
{
|
|
if (section->section_name != NULL)
|
|
free(section->section_name);
|
|
g_free(section);
|
|
section = old->data;
|
|
}
|
|
else
|
|
odb->option_sections = g_slist_insert_sorted(odb->option_sections,
|
|
section, compare_sections);
|
|
}
|
|
|
|
section->options = g_slist_insert_sorted(section->options, option,
|
|
compare_option_tags);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_num_sections *
|
|
* returns the number of option sections registered so far in the *
|
|
* database *
|
|
* *
|
|
* Args: odb - the database to count sections for *
|
|
* Returns: number of option sections *
|
|
\********************************************************************/
|
|
guint
|
|
gnc_option_db_num_sections(GNCOptionDB *odb)
|
|
{
|
|
return g_slist_length(odb->option_sections);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_get_section *
|
|
* returns the ith option section in the database, or NULL *
|
|
* *
|
|
* Args: odb - the option database *
|
|
* i - index of section *
|
|
* Returns: ith option sectioin *
|
|
\********************************************************************/
|
|
GNCOptionSection *
|
|
gnc_option_db_get_section(GNCOptionDB *odb, gint i)
|
|
{
|
|
return g_slist_nth_data(odb->option_sections, i);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_section_name *
|
|
* returns the name of the options section *
|
|
* *
|
|
* Args: section - section to get name of *
|
|
* Returns: name of option section *
|
|
\********************************************************************/
|
|
const char *
|
|
gnc_option_section_name(GNCOptionSection *section)
|
|
{
|
|
return section->section_name;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_section_num_options *
|
|
* returns the number of options in a given section *
|
|
* *
|
|
* Args: section - section to count options for *
|
|
* Returns: number of options in section *
|
|
\********************************************************************/
|
|
guint
|
|
gnc_option_section_num_options(GNCOptionSection *section)
|
|
{
|
|
return g_slist_length(section->options);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_get_option_section_option *
|
|
* returns the ith option in a given section *
|
|
* *
|
|
* Args: section - section to retrieve option for *
|
|
* i - index of option *
|
|
* Returns: ith option in section *
|
|
\********************************************************************/
|
|
GNCOption *
|
|
gnc_get_option_section_option(GNCOptionSection *section, int i)
|
|
{
|
|
return g_slist_nth_data(section->options, i);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_get_option_by_name *
|
|
* returns an option given section name and name *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section_name - name of section to search for *
|
|
* name - name to search for *
|
|
* Returns: given option, or NULL if none *
|
|
\********************************************************************/
|
|
GNCOption *
|
|
gnc_option_db_get_option_by_name(GNCOptionDB *odb, const char *section_name,
|
|
const char *name)
|
|
{
|
|
GSList *section_node;
|
|
GSList *option_node;
|
|
GNCOptionSection section_key;
|
|
GNCOptionSection *section;
|
|
GNCOption *option;
|
|
gint result;
|
|
char *node_name;
|
|
|
|
if (odb == NULL)
|
|
return NULL;
|
|
|
|
section_key.section_name = (char *) section_name;
|
|
|
|
section_node = g_slist_find_custom(odb->option_sections, §ion_key,
|
|
compare_sections);
|
|
|
|
if (section_node == NULL)
|
|
return NULL;
|
|
|
|
section = section_node->data;
|
|
option_node = section->options;
|
|
|
|
while (option_node != NULL)
|
|
{
|
|
option = option_node->data;
|
|
|
|
node_name = gnc_option_name(option);
|
|
result = g_strcmp0(name, node_name);
|
|
free(node_name);
|
|
|
|
if (result == 0)
|
|
return option;
|
|
|
|
option_node = option_node->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_get_option_by_SCM *
|
|
* returns an option given SCM handle. Uses section and name. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* guile_option - SCM handle of option *
|
|
* Returns: given option, or NULL if none *
|
|
\********************************************************************/
|
|
GNCOption *
|
|
gnc_option_db_get_option_by_SCM(GNCOptionDB *odb, SCM guile_option)
|
|
{
|
|
GNCOption option_key;
|
|
GNCOption *option;
|
|
char *section_name;
|
|
char *name;
|
|
|
|
option_key.guile_option = guile_option;
|
|
|
|
section_name = gnc_option_section(&option_key);
|
|
name = gnc_option_name(&option_key);
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section_name, name);
|
|
|
|
if (section_name != NULL)
|
|
free(section_name);
|
|
|
|
if (name != NULL)
|
|
free(name);
|
|
|
|
return option;
|
|
}
|
|
|
|
|
|
static SCM
|
|
gnc_option_valid_value(GNCOption *option, SCM value)
|
|
{
|
|
SCM validator;
|
|
SCM result, ok;
|
|
|
|
validator = gnc_option_value_validator(option);
|
|
|
|
result = scm_call_1(validator, value);
|
|
if (!scm_is_list(result) || scm_is_null(result))
|
|
return SCM_UNDEFINED;
|
|
|
|
ok = SCM_CAR(result);
|
|
if (!scm_is_bool(ok))
|
|
return SCM_UNDEFINED;
|
|
|
|
if (!scm_is_true(ok))
|
|
return SCM_UNDEFINED;
|
|
|
|
result = SCM_CDR(result);
|
|
if (!scm_is_list(result) || scm_is_null(result))
|
|
return SCM_UNDEFINED;
|
|
|
|
return SCM_CAR(result);
|
|
}
|
|
|
|
|
|
static char*
|
|
gnc_commit_option(GNCOption *option)
|
|
{
|
|
SCM validator, setter, value;
|
|
SCM result, ok;
|
|
char* retval = NULL;
|
|
|
|
/* Validate the ui's value */
|
|
value = gnc_option_get_ui_value(option);
|
|
if (value == SCM_UNDEFINED)
|
|
return NULL;
|
|
|
|
validator = gnc_option_value_validator(option);
|
|
|
|
result = scm_call_1(validator, value);
|
|
if (!scm_is_list(result) || scm_is_null(result))
|
|
{
|
|
PERR("bad validation result\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* First element determines validity */
|
|
ok = SCM_CAR(result);
|
|
if (!scm_is_bool(ok))
|
|
{
|
|
PERR("bad validation result\n");
|
|
return NULL;
|
|
}
|
|
|
|
if (scm_is_true(ok))
|
|
{
|
|
/* Second element is value to use */
|
|
value = SCM_CADR(result);
|
|
setter = gnc_option_setter(option);
|
|
|
|
scm_call_1(setter, value);
|
|
|
|
gnc_option_set_ui_value (option, FALSE);
|
|
}
|
|
else
|
|
{
|
|
SCM oops;
|
|
char *section, *name;
|
|
const char *message = NULL;
|
|
const char *format = _("There is a problem with option %s:%s.\n%s");
|
|
const char *bad_value = _("Invalid option value");
|
|
|
|
name = gnc_option_name(option);
|
|
section = gnc_option_section(option);
|
|
|
|
/* Second element is error message */
|
|
oops = SCM_CADR(result);
|
|
if (!scm_is_string(oops))
|
|
{
|
|
PERR("bad validation result\n");
|
|
retval = g_strdup_printf(format,
|
|
section ? section : "(null)",
|
|
name ? name : "(null)",
|
|
bad_value);
|
|
}
|
|
else
|
|
{
|
|
message = gnc_scm_to_utf8_string (oops);
|
|
retval = g_strdup_printf(format,
|
|
section ? section : "(null)",
|
|
name ? name : "(null)",
|
|
message ? message : "(null)");
|
|
}
|
|
if (name != NULL)
|
|
free(name);
|
|
if (section != NULL)
|
|
free(section);
|
|
g_free ((gpointer *) message);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_get_changed *
|
|
* returns a boolean value, TRUE if any option has changed, *
|
|
* FALSE is none of the options have changed *
|
|
* *
|
|
* Args: odb - option database to check *
|
|
* Return: boolean *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_get_changed(GNCOptionDB *odb)
|
|
{
|
|
GSList *section_node;
|
|
GSList *option_node;
|
|
GNCOptionSection *section;
|
|
GNCOption *option;
|
|
|
|
g_return_val_if_fail (odb, FALSE);
|
|
|
|
for (section_node = odb->option_sections; section_node;
|
|
section_node = section_node->next)
|
|
{
|
|
|
|
section = section_node->data;
|
|
|
|
for (option_node = section->options; option_node;
|
|
option_node = option_node->next)
|
|
{
|
|
|
|
option = option_node->data;
|
|
|
|
if (option->changed)
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_commit *
|
|
* commits the options which have changed, and which are valid *
|
|
* for those which are not valid, error dialogs are shown. *
|
|
* *
|
|
* Args: odb - option database to commit *
|
|
* Return: nothing *
|
|
\********************************************************************/
|
|
GList*
|
|
gnc_option_db_commit(GNCOptionDB *odb)
|
|
{
|
|
GSList *section_node;
|
|
GSList *option_node;
|
|
GNCOptionSection *section;
|
|
GNCOption *option;
|
|
gboolean changed_something = FALSE;
|
|
GList *commit_errors = NULL;
|
|
|
|
g_return_val_if_fail (odb, NULL);
|
|
|
|
section_node = odb->option_sections;
|
|
while (section_node != NULL)
|
|
{
|
|
section = section_node->data;
|
|
|
|
option_node = section->options;
|
|
while (option_node != NULL)
|
|
{
|
|
option = option_node->data;
|
|
|
|
if (option->changed)
|
|
{
|
|
char *result = NULL;
|
|
result = gnc_commit_option(option_node->data);
|
|
if (result)
|
|
commit_errors = g_list_append (commit_errors, result);
|
|
changed_something = TRUE;
|
|
option->changed = FALSE;
|
|
}
|
|
|
|
option_node = option_node->next;
|
|
}
|
|
|
|
section_node = section_node->next;
|
|
}
|
|
|
|
if (changed_something)
|
|
gnc_call_option_change_callbacks(odb);
|
|
|
|
return commit_errors;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_section_reset_widgets *
|
|
* reset all option widgets in one section to their default. *
|
|
* values *
|
|
* *
|
|
* Args: odb - option database to reset *
|
|
* Return: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_section_reset_widgets (GNCOptionSection *section)
|
|
{
|
|
GSList *option_node;
|
|
GNCOption *option;
|
|
|
|
g_return_if_fail (section);
|
|
|
|
/* Don't reset "invisible" options.
|
|
* If the section name begins "__" we should not reset
|
|
*/
|
|
if (section->section_name == NULL ||
|
|
strncmp (section->section_name, "__", 2) == 0)
|
|
return;
|
|
|
|
for (option_node = section->options;
|
|
option_node != NULL;
|
|
option_node = option_node->next)
|
|
{
|
|
option = option_node->data;
|
|
|
|
gnc_option_set_ui_value (option, TRUE);
|
|
gnc_option_set_changed (option, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_reset_widgets *
|
|
* reset all option widgets to their default values. *
|
|
* *
|
|
* Args: odb - option database to reset *
|
|
* Return: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_reset_widgets (GNCOptionDB *odb)
|
|
{
|
|
GSList *section_node;
|
|
GNCOptionSection *section;
|
|
|
|
g_return_if_fail (odb);
|
|
|
|
for (section_node = odb->option_sections;
|
|
section_node != NULL;
|
|
section_node = section_node->next)
|
|
{
|
|
section = section_node->data;
|
|
gnc_option_db_section_reset_widgets (section);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_get_default_section *
|
|
* returns the malloc'd section name of the default section, *
|
|
* or NULL if there is none. *
|
|
* *
|
|
* Args: odb - option database to get default page for *
|
|
* Return: g_malloc'd default section name *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_db_get_default_section(GNCOptionDB *odb)
|
|
{
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
if (odb == NULL)
|
|
return NULL;
|
|
|
|
getter = scm_c_eval_string("gnc:options-get-default-section");
|
|
if (!scm_is_procedure(getter))
|
|
return NULL;
|
|
|
|
value = scm_call_1(getter, odb->guile_options);
|
|
if (!scm_is_string(value))
|
|
return NULL;
|
|
|
|
return gnc_scm_to_utf8_string (value);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_option *
|
|
* looks up an option. If present, returns its SCM value, *
|
|
* otherwise returns the default. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: option value *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_option_db_lookup_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
SCM default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
if (option == NULL)
|
|
return default_value;
|
|
|
|
getter = gnc_option_getter(option);
|
|
if (getter == SCM_UNDEFINED)
|
|
return default_value;
|
|
|
|
return scm_call_0(getter);
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_boolean_option *
|
|
* looks up a boolean option. If present, returns its value, *
|
|
* otherwise returns the default. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: gboolean option value *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_lookup_boolean_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gboolean default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
if (option == NULL)
|
|
return default_value;
|
|
|
|
getter = gnc_option_getter(option);
|
|
if (getter == SCM_UNDEFINED)
|
|
return default_value;
|
|
|
|
value = scm_call_0(getter);
|
|
|
|
if (scm_is_bool(value))
|
|
return scm_is_true(value);
|
|
else
|
|
return default_value;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_string_option *
|
|
* looks up a string option. If present, returns its malloc'ed *
|
|
* value, otherwise returns the strdup'ed default, or NULL if *
|
|
* default was NULL. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: char * option value *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_db_lookup_string_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
const char *default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
if (option != NULL)
|
|
{
|
|
getter = gnc_option_getter(option);
|
|
if (getter != SCM_UNDEFINED)
|
|
{
|
|
value = scm_call_0(getter);
|
|
if (scm_is_string(value))
|
|
return gnc_scm_to_utf8_string (value);
|
|
}
|
|
}
|
|
|
|
if (default_value == NULL)
|
|
return NULL;
|
|
|
|
return strdup(default_value);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_font_option *
|
|
* looks up a font option. If present, returns its malloc'ed *
|
|
* string value, otherwise returns the strdup'ed default, or NULL *
|
|
* if default was NULL. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: char * option value *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_db_lookup_font_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
const char *default_value)
|
|
{
|
|
return gnc_option_db_lookup_string_option(odb, section, name, default_value);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_multichoice_option *
|
|
* looks up a multichoice option. If present, returns its *
|
|
* name as a malloc'ed string *
|
|
* value, otherwise returns the strdup'ed default, or NULL if *
|
|
* default was NULL. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: char * option value *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_option_db_lookup_multichoice_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
const char *default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
if (option != NULL)
|
|
{
|
|
getter = gnc_option_getter(option);
|
|
if (getter != SCM_UNDEFINED)
|
|
{
|
|
value = scm_call_0(getter);
|
|
if (scm_is_symbol(value))
|
|
return gnc_scm_symbol_to_locale_string (value);
|
|
}
|
|
}
|
|
|
|
if (default_value == NULL)
|
|
return NULL;
|
|
|
|
return strdup(default_value);
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_number_option *
|
|
* looks up a number option. If present, returns its value *
|
|
* as a gdouble, otherwise returns the default_value. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default - default value if not found *
|
|
* Return: gdouble representation of value *
|
|
\********************************************************************/
|
|
gdouble
|
|
gnc_option_db_lookup_number_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gdouble default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
if (option != NULL)
|
|
{
|
|
getter = gnc_option_getter(option);
|
|
if (getter != SCM_UNDEFINED)
|
|
{
|
|
value = scm_call_0(getter);
|
|
if (scm_is_number(value))
|
|
return scm_to_double(value);
|
|
}
|
|
}
|
|
|
|
return default_value;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_color_option *
|
|
* looks up a color option. If present, returns its value in the *
|
|
* color variable, otherwise leaves the color variable alone. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* red - where to store the red value *
|
|
* blue - where to store the blue value *
|
|
* green - where to store the green value *
|
|
* alpha - where to store the alpha value *
|
|
* Return: true if option was found *
|
|
\********************************************************************/
|
|
gboolean gnc_option_db_lookup_color_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gdouble *red,
|
|
gdouble *green,
|
|
gdouble *blue,
|
|
gdouble *alpha)
|
|
{
|
|
GNCOption *option;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
return gnc_option_get_color_info(option, FALSE, red, green, blue, alpha);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_color_option_argb *
|
|
* looks up a color option. If present, returns its argb value, *
|
|
* otherwise returns the given default value. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default_value - default value to return if problem *
|
|
* Return: argb value *
|
|
\********************************************************************/
|
|
guint32 gnc_option_db_lookup_color_option_argb(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
guint32 default_value)
|
|
{
|
|
GNCOption *option;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return default_value;
|
|
|
|
return gnc_option_get_color_argb(option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_list_option *
|
|
* looks up a list option. If present, returns its value as a *
|
|
* list of strings representing the symbols. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default_value - default value to return if problem *
|
|
* Return: list of values *
|
|
\********************************************************************/
|
|
GSList *
|
|
gnc_option_db_lookup_list_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
GSList *default_value)
|
|
{
|
|
GNCOption *option;
|
|
GSList *list = NULL;
|
|
SCM getter;
|
|
SCM value;
|
|
SCM item;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return default_value;
|
|
|
|
getter = gnc_option_getter(option);
|
|
if (getter == SCM_UNDEFINED)
|
|
return default_value;
|
|
|
|
value = scm_call_0(getter);
|
|
while (scm_is_list(value) && !scm_is_null(value))
|
|
{
|
|
item = SCM_CAR(value);
|
|
value = SCM_CDR(value);
|
|
|
|
if (!scm_is_symbol(item))
|
|
{
|
|
gnc_free_list_option_value(list);
|
|
|
|
return default_value;
|
|
}
|
|
|
|
list = g_slist_prepend(list, gnc_scm_symbol_to_locale_string (item));
|
|
}
|
|
|
|
if (!scm_is_list(value) || !scm_is_null(value))
|
|
{
|
|
gnc_free_list_option_value(list);
|
|
|
|
return default_value;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_lookup_currency_option *
|
|
* looks up a currency option. If present, returns its value as a *
|
|
* gnc_commodity object. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* default_value - default value to return if problem *
|
|
* Return: commodity or NULL if no commodity found *
|
|
\********************************************************************/
|
|
gnc_commodity *
|
|
gnc_option_db_lookup_currency_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gnc_commodity *default_value)
|
|
{
|
|
GNCOption *option;
|
|
SCM getter;
|
|
SCM value;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return default_value;
|
|
|
|
getter = gnc_option_getter(option);
|
|
if (getter == SCM_UNDEFINED)
|
|
return default_value;
|
|
|
|
value = scm_call_0(getter);
|
|
|
|
return gnc_scm_to_commodity (value);
|
|
}
|
|
|
|
static void
|
|
free_helper(gpointer string, gpointer not_used)
|
|
{
|
|
if (string) free(string);
|
|
}
|
|
|
|
void
|
|
gnc_free_list_option_value(GSList *list)
|
|
{
|
|
g_slist_foreach(list, free_helper, NULL);
|
|
g_slist_free(list);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_set_option_default *
|
|
* set the option to its default value *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* Returns: nothing *
|
|
\********************************************************************/
|
|
void
|
|
gnc_option_db_set_option_default(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name)
|
|
{
|
|
GNCOption *option;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
|
|
gnc_option_set_default(option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_set_option *
|
|
* sets the option to the given value. If successful *
|
|
* returns TRUE, otherwise FALSE. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* value - value to set to *
|
|
* Return: success indicator *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_set_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
SCM value)
|
|
{
|
|
GNCOption *option;
|
|
SCM setter;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return FALSE;
|
|
|
|
value = gnc_option_valid_value(option, value);
|
|
if (value == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
setter = gnc_option_setter(option);
|
|
if (setter == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
scm_call_1(setter, value);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_set_number_option *
|
|
* sets the number option to the given value. If successful *
|
|
* returns TRUE, otherwise FALSE. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* value - value to set to *
|
|
* Return: success indicator *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_set_number_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gdouble value)
|
|
{
|
|
GNCOption *option;
|
|
SCM scm_value;
|
|
SCM setter;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return FALSE;
|
|
|
|
scm_value = scm_from_double (value);
|
|
|
|
scm_value = gnc_option_valid_value(option, scm_value);
|
|
if (scm_value == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
setter = gnc_option_setter(option);
|
|
if (setter == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
scm_call_1(setter, scm_value);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_set_boolean_option *
|
|
* sets the boolean option to the given value. If successful *
|
|
* returns TRUE, otherwise FALSE. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* value - value to set to *
|
|
* Return: success indicator *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_set_boolean_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
gboolean value)
|
|
{
|
|
GNCOption *option;
|
|
SCM scm_value;
|
|
SCM setter;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return FALSE;
|
|
|
|
scm_value = SCM_BOOL(value);
|
|
|
|
scm_value = gnc_option_valid_value(option, scm_value);
|
|
if (scm_value == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
setter = gnc_option_setter(option);
|
|
if (setter == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
scm_call_1(setter, scm_value);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_option_db_set_string_option *
|
|
* sets the string option to the given value. If successful *
|
|
* returns TRUE, otherwise FALSE. *
|
|
* *
|
|
* Args: odb - option database to search in *
|
|
* section - section name of option *
|
|
* name - name of option *
|
|
* value - value to set to *
|
|
* Return: success indicator *
|
|
\********************************************************************/
|
|
gboolean
|
|
gnc_option_db_set_string_option(GNCOptionDB *odb,
|
|
const char *section,
|
|
const char *name,
|
|
const char *value)
|
|
{
|
|
GNCOption *option;
|
|
SCM scm_value;
|
|
SCM setter;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (option == NULL)
|
|
return FALSE;
|
|
|
|
if (value)
|
|
scm_value = scm_from_utf8_string(value);
|
|
else
|
|
scm_value = SCM_BOOL_F;
|
|
|
|
scm_value = gnc_option_valid_value(option, scm_value);
|
|
if (scm_value == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
setter = gnc_option_setter(option);
|
|
if (setter == SCM_UNDEFINED)
|
|
return FALSE;
|
|
|
|
scm_call_1(setter, scm_value);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_option_date_option_get_subtype *
|
|
* find out whether a date option is a relative or absolute date *
|
|
* *
|
|
* Args: option - option to get date subtype for *
|
|
* Return: newly allocated subtype string or NULL *
|
|
\*******************************************************************/
|
|
char *
|
|
gnc_option_date_option_get_subtype(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_symbol_to_string(getters.date_option_subtype, option->guile_option);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_date_option_value_get_type *
|
|
* get the type of a date option value *
|
|
* *
|
|
* Args: option_value - option value to get type of *
|
|
* Return: newly allocated type string or NULL *
|
|
\*******************************************************************/
|
|
char *
|
|
gnc_date_option_value_get_type (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_symbol_to_string (getters.date_option_value_type, option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_date_option_value_get_absolute *
|
|
* get the absolute time of a date option value *
|
|
* *
|
|
* Args: option_value - option value to get absolute time of *
|
|
* Return: time64 value *
|
|
\*******************************************************************/
|
|
time64
|
|
gnc_date_option_value_get_absolute (SCM option_value)
|
|
{
|
|
SCM value;
|
|
initialize_getters();
|
|
value = scm_call_1 (getters.date_option_value_absolute, option_value);
|
|
return scm_to_int64 (value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_date_option_value_get_relative *
|
|
* get the relative time of a date option value *
|
|
* *
|
|
* Args: option_value - option value to get relative time of *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
SCM
|
|
gnc_date_option_value_get_relative (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1 (getters.date_option_value_relative, option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_plot_size_option_value_get_type *
|
|
* get the type of a plot size option value *
|
|
* *
|
|
* Args: option_value - option value to get type of *
|
|
* Return: newly allocated type string or NULL *
|
|
\*******************************************************************/
|
|
char *
|
|
gnc_plot_size_option_value_get_type (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_symbol_to_string (getters.plot_size_option_value_type, option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_plot_size_option_value_get_value *
|
|
* get the plot size option value *
|
|
* *
|
|
* Args: option_value - option value to get the plot size of *
|
|
* Return: double value *
|
|
\*******************************************************************/
|
|
gdouble
|
|
gnc_plot_size_option_value_get_value (SCM option_value)
|
|
{
|
|
SCM value;
|
|
|
|
initialize_getters();
|
|
|
|
value = scm_call_1 (getters.plot_size_option_value, option_value);
|
|
|
|
if (scm_is_number(value))
|
|
return scm_to_double (value);
|
|
else
|
|
return 1.0;
|
|
}
|
|
|
|
/********************************************************************\
|
|
* gnc_currency_accounting_option_currency_documentation *
|
|
* returns the malloc'ed documentation string for currency *
|
|
* selector of the currency-accounting option, or NULL if it *
|
|
* can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_currency_accounting_option_currency_documentation(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string
|
|
(getters.currency_accounting_option_currency_doc_string,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_currency_accounting_option_get_default_currency *
|
|
* returns the SCM value for the currency-accounting option *
|
|
* default currency. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM value *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_get_default_currency(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1
|
|
(getters.currency_accounting_option_default_currency,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_currency_accounting_option_policy_documentation *
|
|
* returns the malloc'ed documentation string for policy *
|
|
* selector of the currency-accounting option, or NULL if it *
|
|
* can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_currency_accounting_option_policy_documentation(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string
|
|
(getters.currency_accounting_option_policy_doc_string,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_currency_accounting_option_get_default_policy *
|
|
* returns the SCM value for the currency-accounting option *
|
|
* default policy. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: SCM value *
|
|
\********************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_get_default_policy(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1
|
|
(getters.currency_accounting_option_default_policy,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/********************************************************************\
|
|
* gnc_currency_accounting_option_gain_loss_account_documentation *
|
|
* returns the malloc'ed documentation string for account *
|
|
* selector of the currency-accounting option, or NULL if it *
|
|
* can't be retrieved. *
|
|
* *
|
|
* Args: option - the GNCOption *
|
|
* Returns: malloc'ed char * or NULL *
|
|
\********************************************************************/
|
|
char *
|
|
gnc_currency_accounting_option_gain_loss_account_documentation(GNCOption *option)
|
|
{
|
|
initialize_getters();
|
|
|
|
return gnc_scm_call_1_to_string
|
|
(getters.currency_accounting_option_gain_loss_account_doc_string,
|
|
option->guile_option);
|
|
}
|
|
|
|
|
|
/*******************************************************************\
|
|
* gnc_currency_accounting_option_value_get_method *
|
|
* get the currency accounting method of the option as a symbol *
|
|
* *
|
|
* Args: option_value - option value to get method of *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_value_get_method (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1 (getters.currency_accounting_option_method, option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_currency_accounting_option_value_get_book_currency *
|
|
* get the book-currency if that is the currency accounting *
|
|
* method of the option as a symbol *
|
|
* *
|
|
* Args: option_value - option value to get method of *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_value_get_book_currency (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1 (getters.currency_accounting_option_book_currency, option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_currency_accounting_option_value_get_default_policy *
|
|
* get the default policy if book-currency is the currency *
|
|
* accounting method of the option as a symbol *
|
|
* *
|
|
* Args: option_value - option value to get method of *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_value_get_default_policy (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1
|
|
(getters.currency_accounting_option_selected_default_policy,
|
|
option_value);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_currency_accounting_option_value_get_default_account *
|
|
* get the default gain/loss account if book-currency is the *
|
|
* currency accounting method, if one is specified, of the *
|
|
* option as a symbol *
|
|
* *
|
|
* Args: option_value - option value to get method of *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
SCM
|
|
gnc_currency_accounting_option_value_get_default_account (SCM option_value)
|
|
{
|
|
initialize_getters();
|
|
|
|
return scm_call_1
|
|
(getters.currency_accounting_option_selected_default_gain_loss_account,
|
|
option_value);
|
|
}
|
|
|
|
static int
|
|
find_option_db_with_selectable_pred (gpointer key, gpointer value, gpointer data)
|
|
{
|
|
SCM guile_options = data;
|
|
GNCOptionDB *odb = value;
|
|
|
|
if (odb && (odb->guile_options == guile_options)
|
|
&& odb->set_selectable )
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
static GNCOptionDB *
|
|
find_option_db_with_selectable (SCM guile_options)
|
|
{
|
|
return g_hash_table_find (option_dbs, find_option_db_with_selectable_pred,
|
|
guile_options);
|
|
}
|
|
|
|
/*******************************************************************\
|
|
* gnc_option_db_set_option_selectable_by_name *
|
|
* set the sensitivity of the option widget *
|
|
* *
|
|
* Args: guile_options - guile side option db *
|
|
* section - section of option *
|
|
* name - name of option *
|
|
* selectable - selectable status *
|
|
* Return: SCM value *
|
|
\*******************************************************************/
|
|
void
|
|
gnc_option_db_set_option_selectable_by_name(SCM guile_options,
|
|
const char *section,
|
|
const char *name,
|
|
gboolean selectable)
|
|
{
|
|
GNCOptionDB *odb;
|
|
GNCOption *option;
|
|
|
|
odb = find_option_db_with_selectable (guile_options);
|
|
if (!odb)
|
|
return;
|
|
|
|
option = gnc_option_db_get_option_by_name(odb, section, name);
|
|
if (!option)
|
|
return;
|
|
|
|
gnc_option_set_selectable (option, selectable);
|
|
}
|
|
|
|
/* the value is a list of:
|
|
* format(symbol), month(symbol), include-years(bool), custom-string(string)
|
|
*/
|
|
|
|
gboolean gnc_dateformat_option_value_parse(SCM value, QofDateFormat *format,
|
|
GNCDateMonthFormat *months,
|
|
gboolean *years, char **custom)
|
|
{
|
|
SCM val;
|
|
gchar *str;
|
|
|
|
if (!scm_is_list(value) || scm_is_null(value))
|
|
return TRUE;
|
|
|
|
do
|
|
{
|
|
|
|
/* Parse the format */
|
|
val = SCM_CAR(value);
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_symbol(val))
|
|
break;
|
|
str = gnc_scm_symbol_to_locale_string (val);
|
|
if (!str)
|
|
break;
|
|
|
|
if (format)
|
|
{
|
|
if (gnc_date_string_to_dateformat(str, format))
|
|
{
|
|
g_free (str);
|
|
break;
|
|
}
|
|
}
|
|
g_free (str);
|
|
|
|
/* parse the months */
|
|
val = SCM_CAR(value);
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_symbol(val))
|
|
break;
|
|
str = gnc_scm_symbol_to_locale_string (val);
|
|
if (!str)
|
|
break;
|
|
|
|
if (months)
|
|
{
|
|
if (gnc_date_string_to_monthformat(str, months))
|
|
{
|
|
g_free (str);
|
|
break;
|
|
}
|
|
}
|
|
g_free (str);
|
|
|
|
/* parse the years */
|
|
val = SCM_CAR(value);
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_bool(val))
|
|
break;
|
|
|
|
if (years)
|
|
*years = scm_is_true(val);
|
|
|
|
/* parse the custom */
|
|
val = SCM_CAR(value);
|
|
value = SCM_CDR(value);
|
|
if (!scm_is_string(val))
|
|
break;
|
|
if (!scm_is_null(value))
|
|
break;
|
|
|
|
if (custom)
|
|
*custom = gnc_scm_to_utf8_string (val);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
while (FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
SCM gnc_dateformat_option_set_value(QofDateFormat format, GNCDateMonthFormat months,
|
|
gboolean years, const char *custom)
|
|
{
|
|
SCM value = SCM_EOL;
|
|
SCM val;
|
|
const char *str;
|
|
|
|
/* build the list in reverse order */
|
|
if (custom)
|
|
val = scm_from_utf8_string(custom);
|
|
else
|
|
val = SCM_BOOL_F;
|
|
value = scm_cons(val, value);
|
|
|
|
val = SCM_BOOL(years);
|
|
value = scm_cons(val, value);
|
|
|
|
str = gnc_date_monthformat_to_string(months);
|
|
if (str)
|
|
val = scm_from_locale_symbol(str);
|
|
else
|
|
val = SCM_BOOL_F;
|
|
value = scm_cons(val, value);
|
|
|
|
str = gnc_date_dateformat_to_string(format);
|
|
if (str)
|
|
val = scm_from_locale_symbol(str);
|
|
else
|
|
val = SCM_BOOL_F;
|
|
value = scm_cons(val, value);
|
|
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
* the generator should be a procedure that takes one argument,
|
|
* an options object. The procedure should fill in the options with
|
|
* its defined kvp options.
|
|
*/
|
|
void
|
|
gnc_register_kvp_option_generator(QofIdType id_type, SCM generator)
|
|
{
|
|
GList *list;
|
|
init_table();
|
|
list = g_hash_table_lookup(kvp_registry, id_type);
|
|
list = g_list_prepend(list, generator);
|
|
g_hash_table_insert(kvp_registry, (gpointer) id_type, list);
|
|
scm_gc_protect_object(generator);
|
|
}
|