Merge branch 'c++options'

This commit is contained in:
John Ralls 2022-03-29 15:58:22 -07:00
commit abd1a0b3f1
106 changed files with 15978 additions and 13848 deletions

View File

@ -568,7 +568,7 @@ endif()
add_definitions(-D_GNU_SOURCE)
# Also, set the C++ version to c++11
# Set up the language standards:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

View File

@ -401,10 +401,6 @@ void qof_book_set_string_option(QofBook* book, const char* opt_name, const char*
SET_ENUM("OPTION-SECTION-ACCOUNTS");
SET_ENUM("OPTION-NAME-TRADING-ACCOUNTS");
SET_ENUM("OPTION-NAME-CURRENCY-ACCOUNTING");
SET_ENUM("OPTION-NAME-BOOK-CURRENCY");
SET_ENUM("OPTION-NAME-DEFAULT-GAINS-POLICY");
SET_ENUM("OPTION-NAME-DEFAULT-GAINS-LOSS-ACCT-GUID");
SET_ENUM("OPTION-NAME-AUTO-READONLY-DAYS");
SET_ENUM("OPTION-NAME-NUM-FIELD-SOURCE");

View File

@ -77,7 +77,7 @@ glist_to_scm_list_helper(GList *glist, swig_type_info *wct)
}
SCM
gnc_glist_to_scm_list(GList *glist, gchar *wct)
gnc_glist_to_scm_list(GList *glist, const gchar *wct)
{
swig_type_info *stype = SWIG_TypeQuery(wct);
g_return_val_if_fail(stype, SCM_UNDEFINED);

View File

@ -28,7 +28,7 @@
#include <glib.h>
#include <libguile.h>
SCM gnc_glist_to_scm_list(GList *glist, gchar *wct);
SCM gnc_glist_to_scm_list(GList *glist, const gchar *wct);
GList* gnc_scm_list_to_glist(SCM wcp_list);
SCM gnc_glist_string_to_scm(GList * list);

View File

@ -36,7 +36,7 @@ set (gnome_utils_SOURCES
dialog-dup-trans.c
dialog-file-access.c
dialog-object-references.c
dialog-options.c
dialog-options.cpp
dialog-preferences.c
dialog-query-view.c
dialog-reset-warnings.c
@ -60,7 +60,7 @@ set (gnome_utils_SOURCES
gnc-currency-edit.c
gnc-date-delta.c
gnc-date-edit.c
gnc-date-format.c
gnc-date-format.c
gnc-dense-cal.c
gnc-dense-cal-model.c
gnc-dense-cal-store.c
@ -75,7 +75,7 @@ set (gnome_utils_SOURCES
gnc-gui-query.c
gnc-icons.c
gnc-keyring.c
gnc-main-window.c
gnc-main-window.cpp
gnc-menu-extensions.c
gnc-plugin-file-history.c
gnc-plugin-manager.c
@ -110,6 +110,7 @@ set (gnome_utils_SOURCES
set(gnome_utils_noinst_HEADERS
dialog-tax-table.h
dialog-options.hpp
gnc-autosave.h
gnc-gobject-utils.h
gnc-gtk-utils.h
@ -127,7 +128,6 @@ set (gnome_utils_HEADERS
dialog-file-access.h
dialog-preferences.h
dialog-object-references.h
dialog-options.h
dialog-query-view.h
dialog-reset-warnings.h
dialog-totd.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,116 +0,0 @@
/********************************************************************\
* dialog-options.h -- GNOME option handling *
* Copyright (C) 1998-2000 Linas Vepstas *
* *
* 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 *
\********************************************************************/
#ifndef OPTIONS_DIALOG_H
#define OPTIONS_DIALOG_H
#include <libguile.h>
#include "option-util.h"
#include <gtk/gtk.h>
/** A simple wrapper that casts the gpointer result of
* gnc_option_get_widget() already into a GtkWidget*. */
GtkWidget *gnc_option_get_gtk_widget (GNCOption *option);
typedef struct gnc_option_win GNCOptionWin;
typedef void (* GNCOptionWinCallback)(GNCOptionWin *, gpointer data);
GNCOptionWin * gnc_options_dialog_new_modal (gboolean modal, gchar *title,
const char *component_class,
GtkWindow *parent);
GNCOptionWin * gnc_options_dialog_new (gchar *title, GtkWindow *parent);
GNCOptionWin * gnc_options_dialog_new_w_dialog (gchar *title, GtkWidget *dialog);
void gnc_options_dialog_destroy (GNCOptionWin * win);
void gnc_options_register_stocks (void);
GtkWidget * gnc_options_dialog_widget (GNCOptionWin * win);
GtkWidget * gnc_options_page_list (GNCOptionWin * win);
GtkWidget * gnc_options_dialog_notebook (GNCOptionWin * win);
void gnc_options_dialog_changed (GNCOptionWin *win);
void gnc_option_changed_widget_cb (GtkWidget *widget, GNCOption *option);
void gnc_option_changed_option_cb (GtkWidget *dummy, GNCOption *option);
void gnc_options_dialog_set_apply_cb (GNCOptionWin * win,
GNCOptionWinCallback thunk,
gpointer cb_data);
void gnc_options_dialog_set_help_cb (GNCOptionWin * win,
GNCOptionWinCallback thunk,
gpointer cb_data);
void gnc_options_dialog_set_close_cb (GNCOptionWin * win,
GNCOptionWinCallback thunk,
gpointer cb_data);
void gnc_options_dialog_set_global_help_cb (GNCOptionWinCallback thunk,
gpointer cb_data);
void gnc_options_dialog_build_contents (GNCOptionWin *win,
GNCOptionDB *odb);
void gnc_options_dialog_build_contents_full (GNCOptionWin *win,
GNCOptionDB *odb,
gboolean show_dialog);
/* Both apply_cb and close_cb should be scheme functions with 0 arguments.
* References to these functions will be held until the close_cb is called
*/
void gnc_options_dialog_set_scm_callbacks (GNCOptionWin *win,
SCM apply_cb,
SCM close_cb);
/*****************************************************************/
/* Option Registration */
/* Function to set the UI widget based upon the option */
typedef GtkWidget *
(*GNCOptionUISetWidget) (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed);
/* Function to set the UI Value for a particular option */
typedef gboolean
(*GNCOptionUISetValue) (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value);
/* Function to get the UI Value for a particular option */
typedef SCM
(*GNCOptionUIGetValue) (GNCOption *option, GtkWidget *widget);
typedef struct gnc_option_def
{
const char * option_name;
GNCOptionUISetWidget set_widget;
GNCOptionUISetValue set_value;
GNCOptionUIGetValue get_value;
} GNCOptionDef_t;
/* Register a new option type in the UI */
void gnc_options_ui_initialize (void);
void gnc_options_ui_register_option (GNCOptionDef_t *option);
GNCOptionDef_t * gnc_options_ui_get_option (const char *option_name);
#endif /* OPTIONS_DIALOG_H */

View File

@ -0,0 +1,200 @@
/********************************************************************\
* dialog-options.hpp -- GNOME option handling *
* Copyright (C) 1998-2000 Linas Vepstas *
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
* Copyright (c) 2011 Robert Fewell *
* Copyright 2019-2021 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
\********************************************************************/
/** @addtogroup GUI
@{ */
/** @addtogroup GuiOptions Options Dialog
@{ */
#ifndef GNC_DIALOG_OPTIONS_HPP_
#define GNC_DIALOG_OPTIONS_HPP_
#include <vector>
#include <gnc-option-uitype.hpp>
#include <gnc-option-ui.hpp>
/** @fn WidgetCreateFunc
* Function pointer for per-option-type GtkWidget constructors.
* @param option The option to create an element for.
* @param page_box The option dialog page's layout grid
* @param name_label A GtkLabel to attach to the widget
* @param documentation The string to use for the tooltip.
* @param enclosing The parent widget
* @param packed Whether the widget will be packed into an eventbox.
* @return pointer to the widget.
*/
typedef GtkWidget* (*WidgetCreateFunc)(GncOption&, GtkGrid*, GtkLabel*, char*,
GtkWidget**, bool*);
/** @class GncOptionUIFactory
* Factory class that keeps track of which GncOptionValueType needs which
* WidgetCreateFunc and calls the appropriate one when required.
*/
class GncOptionUIFactory
{
public:
/** Register a WidgetCreateFunc
* @param type The UI type
* @param func The function to register
*/
static void set_func(GncOptionUIType type, WidgetCreateFunc func);
/** Create a widget
* @param option The option for which to create the widget
* @param page The Option dialog page in which to insert the widget
* @param name The label to attach to the widget
* @param description The text for the widget's tooltip
* @param enclosing The widget's parent
* @param packed Whether the widget will be packed into an eventbox.
* @return pointer to the created widget.
*/
static GtkWidget* create(GncOption&, GtkGrid*, GtkLabel*, char*,
GtkWidget**, bool*);
private:
static std::vector<WidgetCreateFunc> s_registry;
static bool s_initialized;
};
/** class GncOptionGtkUIItem
* Gtk-specific Interface class for Option Widget
*/
class GncOptionGtkUIItem : public GncOptionUIItem
{
public:
GncOptionGtkUIItem(GtkWidget* widget, GncOptionUIType type);
GncOptionGtkUIItem(const GncOptionGtkUIItem& item);
GncOptionGtkUIItem(GncOptionGtkUIItem&&) = default;
virtual ~GncOptionGtkUIItem() override;
/** Control wether the widget is sensitive */
virtual void set_selectable(bool) const noexcept override;
/** Clear the data from the widget. */
void clear_ui_item() override;
void set_widget(GtkWidget* widget);
virtual GtkWidget* const get_widget() const { return m_widget; }
static WidgetCreateFunc option_widget_factory(GncOption& option,
GtkGrid* page,
GtkLabel* name,
char* description,
GtkWidget** enclosing,
bool* packed);
private:
GtkWidget* m_widget;
};
template<GncOptionUIType type> GtkWidget*
create_option_widget(GncOption& option, GtkGrid*, GtkLabel*, char*, GtkWidget**,
bool*);
/** Templated cast to convert various QofInstance subtype ptrs into QofInstance*
* to placate the C++ type system. QofInstance is a GObject hierarchy so the
* usual C++ type substitution doesn't work.
*/
template <typename Instance> inline const QofInstance*
qof_instance_cast(Instance inst)
{
static_assert(std::is_pointer_v<Instance>, "Pointers Only!");
return reinterpret_cast<const QofInstance*>(inst);
}
class GncOptionsDialog;
typedef void (* GncOptionsDialogCallback)(GncOptionsDialog*, void* data);
class GncOptionsDialog
{
GtkWidget * m_window;
GtkWidget * m_notebook;
GtkWidget * m_page_list_view;
GtkWidget * m_page_list;
GtkButton * m_help_button;
GtkButton * m_cancel_button;
GtkButton * m_apply_button;
GtkButton * m_ok_button;
bool toplevel;
GncOptionsDialogCallback m_apply_cb;
gpointer m_apply_cb_data;
GncOptionsDialogCallback m_help_cb;
gpointer m_help_cb_data;
GncOptionsDialogCallback m_close_cb;
gpointer m_close_cb_data;
/* Hold onto this for a complete reset */
GncOptionDB* m_option_db;
/* Hold on to this to unregister the right class */
const char* m_component_class;
/* widget being destroyed */
bool m_destroying{false};
public:
GncOptionsDialog(const char* title, GtkWindow* parent) :
GncOptionsDialog(false, title, nullptr, parent) {}
GncOptionsDialog(bool modal, const char* title, const char* component_class,
GtkWindow* parent);
GncOptionsDialog(const GncOptionsDialog&) = default;
GncOptionsDialog(GncOptionsDialog&&) = default;
~GncOptionsDialog();
GtkWidget* get_widget() const noexcept { return m_window; }
GtkWidget* get_page_list() const noexcept { return m_page_list; }
GtkWidget* get_page_list_view() const noexcept { return m_page_list_view; }
GtkWidget* get_notebook() const noexcept { return m_notebook; }
GncOptionDB* get_option_db() noexcept { return m_option_db; }
inline void build_contents(GncOptionDB* odb){
build_contents(odb, true); }
void build_contents(GncOptionDB* odb, bool show_dialog);
void set_sensitive(bool sensitive) noexcept;
void changed() noexcept;
void set_apply_cb(GncOptionsDialogCallback, void* cb_data) noexcept;
void call_apply_cb() noexcept;
void set_help_cb(GncOptionsDialogCallback, void* cb_data) noexcept;
void call_help_cb() noexcept;
void set_close_cb(GncOptionsDialogCallback, void* cb_data) noexcept;
void call_close_cb() noexcept;
void set_book_help_cb() noexcept;
void call_book_help_cb() noexcept;
void set_style_sheet_help_cb() noexcept;
void call_style_sheet_help_cb() noexcept;
};
void gnc_option_changed_widget_cb (GtkWidget *widget, GncOption *option);
void gnc_option_changed_option_cb (GtkWidget *dummy, GncOption *option);
/**
* Set the initial values of new book options to values specified in user
* preferences.
* Nothing to do with GncOptionsDialog, but it depends on Gtk and s used in
* both assistant-hierarchy and gnc-main-window.
* @param odb: The book's options database.
*/
void gnc_options_dialog_set_new_book_option_values (GncOptionDB *odb);
#endif // GNC_DIALOG_OPTIONS_HPP_
/** @}
@} */

View File

@ -821,51 +821,6 @@ gnc_new_book_option_display (GtkWidget *parent)
return TRUE;
}
/* This function returns a widget for selecting a cost policy
*/
GtkWidget *
gnc_cost_policy_select_new (void)
{
GtkWidget *cost_policy_widget = NULL;
GList *list_of_policies = NULL;
list_of_policies = gnc_get_valid_policy_list();
g_return_val_if_fail(g_list_length (list_of_policies) >= 0, NULL);
if (list_of_policies)
{
GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
GtkTreeIter iter;
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
const char *description;
GList *l = NULL;
/* Add values to the list store, entry and tooltip */
for (l = list_of_policies; l != NULL; l = l->next)
{
GNCPolicy *pcy = l->data;
description = PolicyGetDescription (pcy);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
0, (description && *description) ? _(description) : "",
-1);
}
g_list_free (list_of_policies);
/* Create the new Combo with the store */
cost_policy_widget = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(cost_policy_widget), renderer, TRUE);
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(cost_policy_widget),
renderer, "text", 0);
g_object_unref (store);
}
return cost_policy_widget;
}
/* This function returns a string for the CSS 'gnc-class-negative-numbers' class,
* the returned string must be freed
*/
gchar*
gnc_get_negative_color (void)
{

View File

@ -41,7 +41,6 @@
#include "gnc-window.h"
#include "gnc-icons.h"
#include "dialog-doclink-utils.h"
#include "dialog-options.h"
#include "dialog-commodity.h"
#include "dialog-totd.h"
#include "gnc-ui-util.h"
@ -73,13 +72,10 @@ const gchar *msg_no_help_reason =
/* Translators: URI of missing help files */
const gchar *msg_no_help_location = N_("Expected location");
static void gnc_book_options_help_cb (GNCOptionWin *win, gpointer dat);
void
gnc_gnome_utils_init (void)
{
gnc_component_manager_init ();
gnc_options_ui_initialize ();
scm_init_sw_gnome_utils_module();
scm_c_use_module ("sw_gnome_utils");
@ -87,63 +83,6 @@ gnc_gnome_utils_init (void)
}
static void
gnc_global_options_help_cb (GNCOptionWin *win, gpointer dat)
{
gnc_gnome_help (GTK_WINDOW(gnc_options_dialog_widget (win)), HF_HELP, HL_GLOBPREFS);
}
static void
gnc_book_options_help_cb (GNCOptionWin *win, gpointer dat)
{
gnc_gnome_help (GTK_WINDOW(gnc_options_dialog_widget (win)), HF_HELP, HL_BOOK_OPTIONS);
}
void
gnc_options_dialog_set_book_options_help_cb (GNCOptionWin *win)
{
gnc_options_dialog_set_help_cb(win,
(GNCOptionWinCallback)gnc_book_options_help_cb,
NULL);
}
void
gnc_options_dialog_set_new_book_option_values (GNCOptionDB *odb)
{
GNCOption *num_source_option;
GtkWidget *num_source_is_split_action_button;
gboolean num_source_is_split_action;
if (!odb) return;
num_source_is_split_action = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL,
GNC_PREF_NUM_SOURCE);
if (num_source_is_split_action)
{
num_source_option = gnc_option_db_get_option_by_name(odb,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_NUM_FIELD_SOURCE);
num_source_is_split_action_button =
gnc_option_get_gtk_widget (num_source_option);
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (num_source_is_split_action_button),
num_source_is_split_action);
}
}
static void
gnc_style_sheet_options_help_cb (GNCOptionWin *win, gpointer dat)
{
gnc_gnome_help (GTK_WINDOW(gnc_options_dialog_widget (win)), HF_HELP, HL_STYLE_SHEET);
}
void
gnc_options_dialog_set_style_sheet_options_help_cb (GNCOptionWin *win)
{
gnc_options_dialog_set_help_cb (win,
(GNCOptionWinCallback)gnc_style_sheet_options_help_cb,
NULL);
}
/* gnc_configure_date_format
* sets dateFormat to the current value on the scheme side
*
@ -772,8 +711,6 @@ gnc_gui_init(void)
gnc_file_set_shutdown_callback (gnc_shutdown);
gnc_options_dialog_set_global_help_cb (gnc_global_options_help_cb, NULL);
main_window = gnc_main_window_new ();
// Bug#350993:
// gtk_widget_show (GTK_WIDGET (main_window));

View File

@ -36,7 +36,6 @@
#define GNC_GNOME_UTILS_H
#include <gnc-main-window.h>
#include "dialog-options.h"
/** Initialize the gnome-utils library
* Should be run once before using any gnome-utils features.
@ -65,21 +64,6 @@ void gnc_gnome_help (GtkWindow *parent, const char *file_name,
*/
void gnc_launch_doclink (GtkWindow *parent, const char *uri);
/** Set the help callback to 'gnc_book_options_help_cb' to open a help browser
* and point it to the Book Options link in the Help file.
*/
void gnc_options_dialog_set_book_options_help_cb (GNCOptionWin *win);
/** Set the initial values of new book options to values specified in user
* preferences.
*/
void gnc_options_dialog_set_new_book_option_values (GNCOptionDB *odb);
/** Set the help callback to 'gnc_style_sheet_options_help_cb' to open a help browser
* and point it to the Style Sheet link in the Help file.
*/
void gnc_options_dialog_set_style_sheet_options_help_cb (GNCOptionWin *win);
/** Given a file name, find and load the requested pixmap. This
* routine will display an error message if it can't find the file or
* load the pixmap.

View File

@ -128,7 +128,7 @@ void gnc_gobject_tracking_dump (void);
#define _GNC_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \
\
static void type_name##_init (TypeName *self, void *class); \
static void type_name##_init (TypeName *self, void *klass); \
static void type_name##_class_init (TypeName##Class *klass); \
static gpointer type_name##_parent_class = NULL; \
static gint TypeName##_private_offset; \

View File

@ -33,6 +33,7 @@
#include "gnc-filepath-utils.h"
#include "gnc-gnome-utils.h"
#include "gnc-path.h"
#include <gnc-engine.h> // For define GNC_MOD_GUI
static QofLogModule log_module = GNC_MOD_GUI;

View File

@ -35,6 +35,10 @@
#ifndef __GNC_MAIN_WINDOW_H
#define __GNC_MAIN_WINDOW_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <gtk/gtk.h>
#include "gnc-plugin-page.h"
@ -450,12 +454,15 @@ GtkWidget *gnc_book_options_dialog_cb (gboolean modal, gchar *title,
* just in Book Options dialog opened from main window but also in new-file
* assistant).
*
* @param GNCOptionDB * options.
* @param GncOptionDB * options.
*
* @return TRUE if gnc_gui_refresh_all should be called; otherwise FALSE.
**/
gboolean gnc_book_options_dialog_apply_helper(GNCOptionDB * options);
gboolean gnc_book_options_dialog_apply_helper(GncOptionDB * options);
#ifdef __cplusplus
}
#endif
#endif /* __GNC_MAIN_WINDOW_H */
/** @} */

View File

@ -24,7 +24,6 @@
#include <config.h>
#include <gtk/gtk.h>
#include <glib-object.h>
#include <dialog-options.h>
#include <dialog-utils.h>
#include <gnc-amount-edit.h>
#include <gnc-date-edit.h>
@ -49,13 +48,6 @@ SCM scm_init_sw_gnome_utils_module (void);
%import "base-typemaps.i"
GNCOptionWin * gnc_options_dialog_new(gchar *title, GtkWindow* parent);
void gnc_options_dialog_destroy(GNCOptionWin * win);
void gnc_options_dialog_build_contents(GNCOptionWin *propertybox,
GNCOptionDB *odb);
void gnc_options_dialog_set_scm_callbacks (GNCOptionWin *win,
SCM apply_cb, SCM close_cb);
gboolean
gnc_verify_dialog (GtkWindow *parent, gboolean yes_is_default,
const gchar *format, ...);

View File

@ -27,7 +27,7 @@ set (gnc_gnome_noinst_HEADERS
dialog-payment.h
dialog-print-check.h
dialog-progress.h
dialog-report-column-view.h
dialog-report-column-view.hpp
dialog-report-style-sheet.h
dialog-sx-editor.h
dialog-sx-from-trans.h
@ -64,11 +64,11 @@ gnc_add_swig_guile_command (swig-gnome-c
set (gnc_gnome_SOURCES
assistant-acct-period.c
assistant-hierarchy.c
assistant-hierarchy.cpp
assistant-loan.cpp
assistant-stock-split.c
assistant-stock-transaction.cpp
business-options-gnome.c
business-options-gnome.cpp
business-urls.c
business-gnome-utils.c
dialog-doclink.c
@ -93,8 +93,8 @@ set (gnc_gnome_SOURCES
dialog-price-edit-db.c
dialog-print-check.c
dialog-progress.c
dialog-report-column-view.c
dialog-report-style-sheet.c
dialog-report-column-view.cpp
dialog-report-style-sheet.cpp
dialog-sx-editor.c
dialog-sx-from-trans.c
dialog-sx-since-last-run.c
@ -112,14 +112,14 @@ set (gnc_gnome_SOURCES
gnc-plugin-page-invoice.c
gnc-plugin-page-owner-tree.c
gnc-plugin-page-register.c
gnc-plugin-page-report.c
gnc-plugin-page-report.cpp
gnc-plugin-page-sx-list.c
gnc-split-reg.c
reconcile-view.c
search-owner.c
top-level.c
window-reconcile.c
window-report.c
window-report.cpp
window-autoclear.c
)

View File

@ -22,28 +22,28 @@
* Boston, MA 02110-1301, USA gnu@gnu.org *
\********************************************************************/
#include <libguile.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
extern "C"
{
#include <config.h>
#include <platform.h>
#include <libguile.h>
#if PLATFORM(WINDOWS)
#include <windows.h>
#endif
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef MAC_INTEGRATION
#include <Foundation/Foundation.h>
#endif
#include "gnc-account-merge.h"
#include "dialog-new-user.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "dialog-file-access.h"
#include "assistant-hierarchy.h"
@ -66,6 +66,10 @@
#include "gnc-plugin-page-account-tree.h"
#include "gnc-engine.h"
}
#include <dialog-options.hpp>
#include <gnc-optiondb.h>
static QofLogModule log_module = GNC_MOD_IMPORT;
#define GNC_PREFS_GROUP "dialogs.new-hierarchy"
@ -119,8 +123,8 @@ typedef struct
gboolean use_defaults;
gboolean new_book; /* presumably only used for new book creation but we check*/
GNCOptionDB *options;
GNCOptionWin *optionwin;
GncOptionDB *options;
GncOptionsDialog *optionwin;
GncHierarchyAssistantFinishedCallback when_completed;
@ -154,7 +158,7 @@ delete_hierarchy_dialog (hierarchy_data *data)
static void
destroy_hash_helper (gpointer key, gpointer value, gpointer user_data)
{
gnc_numeric *balance = value;
auto balance{static_cast<gnc_numeric*>(value)};
g_free (balance);
}
@ -166,9 +170,9 @@ gnc_hierarchy_destroy_cb (GtkWidget *obj, hierarchy_data *data)
hash = data->balance_hash;
if (hash)
{
g_hash_table_foreach (hash, destroy_hash_helper, NULL);
g_hash_table_foreach (hash, destroy_hash_helper, nullptr);
g_hash_table_destroy (hash);
data->balance_hash = NULL;
data->balance_hash = nullptr;
}
g_free (data->gnc_accounts_dir);
@ -177,12 +181,10 @@ gnc_hierarchy_destroy_cb (GtkWidget *obj, hierarchy_data *data)
static gnc_numeric
get_final_balance (GHashTable *hash, Account *account)
{
gnc_numeric *balance;
if (!hash || !account)
return gnc_numeric_zero ();
balance = g_hash_table_lookup(hash, account);
auto balance{static_cast<gnc_numeric*>(g_hash_table_lookup(hash, account))};
if (balance)
return *balance;
return gnc_numeric_zero ();
@ -191,12 +193,10 @@ get_final_balance (GHashTable *hash, Account *account)
static void
set_final_balance (GHashTable *hash, Account *account, gnc_numeric in_balance)
{
gnc_numeric *balance;
if (!hash || !account)
return;
balance = g_hash_table_lookup (hash, account);
auto balance{static_cast<gnc_numeric*>(g_hash_table_lookup(hash, account))};
if (balance)
{
*balance = in_balance;
@ -218,7 +218,7 @@ mac_locale()
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLocale* locale = [NSLocale currentLocale];
NSString* locale_str;
char *retval = NULL;
char *retval = nullptr;
@try
{
locale_str =[[[locale objectForKey: NSLocaleLanguageCode]
@ -241,7 +241,7 @@ mac_locale()
static gchar*
gnc_get_ea_locale_dir(const char *top_dir)
{
static gchar *default_locale = "C";
static const char* default_locale = "C";
gchar *ret;
gchar *locale;
GStatBuf buf;
@ -274,11 +274,11 @@ gnc_get_ea_locale_dir(const char *top_dir)
#elif defined MAC_INTEGRATION
locale = mac_locale();
# else
locale = g_strdup(setlocale(LC_MESSAGES, NULL));
locale = g_strdup(setlocale(LC_MESSAGES, nullptr));
#endif
i = strlen(locale);
ret = g_build_filename(top_dir, locale, (char *)NULL);
ret = g_build_filename(top_dir, locale, (char *)nullptr);
while (g_stat(ret, &buf) != 0)
{
@ -286,12 +286,12 @@ gnc_get_ea_locale_dir(const char *top_dir)
if (i < 1)
{
g_free(ret);
ret = g_build_filename(top_dir, default_locale, (char *)NULL);
ret = g_build_filename(top_dir, default_locale, (char *)nullptr);
break;
}
locale[i] = '\0';
g_free(ret);
ret = g_build_filename(top_dir, locale, (char *)NULL);
ret = g_build_filename(top_dir, locale, (char *)nullptr);
}
g_free(locale);
@ -313,8 +313,8 @@ region_combo_changed_cb (GtkComboBox *widget, hierarchy_data *data)
GtkTreeModel *filter_model = gtk_combo_box_get_model (GTK_COMBO_BOX(data->region_combo));
GtkTreeModel *region_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(filter_model));
GtkTreeIter filter_iter, region_iter;
gchar *lang_reg = NULL;
gchar *account_path = NULL;
gchar *lang_reg = nullptr;
gchar *account_path = nullptr;
if (gtk_combo_box_get_active_iter (widget, &filter_iter))
{
@ -335,13 +335,13 @@ region_combo_changed_cb (GtkComboBox *widget, hierarchy_data *data)
/* Remove the old account tree */
if (data->category_accounts_tree)
gtk_widget_destroy(GTK_WIDGET(data->category_accounts_tree));
data->category_accounts_tree = NULL;
data->category_accounts_tree = nullptr;
// clear the categories list store in prep for new load
if (cat_list)
gtk_list_store_clear (cat_list);
account_path = g_build_filename (data->gnc_accounts_dir, lang_reg, NULL);
account_path = g_build_filename (data->gnc_accounts_dir, lang_reg, nullptr);
qof_event_suspend ();
list = gnc_load_example_account_list (account_path);
@ -350,7 +350,7 @@ region_combo_changed_cb (GtkComboBox *widget, hierarchy_data *data)
if (data->initial_category)
{
gtk_tree_row_reference_free (data->initial_category);
data->initial_category = NULL;
data->initial_category = nullptr;
}
// repopulate the category list
@ -360,7 +360,7 @@ region_combo_changed_cb (GtkComboBox *widget, hierarchy_data *data)
{
path = gtk_tree_row_reference_get_path (data->initial_category);
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(data->categories_tree),
path, NULL, TRUE, 0.5, 0.5);
path, nullptr, TRUE, 0.5, 0.5);
}
else
path = gtk_tree_path_new_first ();
@ -393,8 +393,8 @@ region_combo_change_filter_cb (GtkComboBox *widget, hierarchy_data *data)
GtkTreeModel *sort_model = gtk_combo_box_get_model (GTK_COMBO_BOX(data->language_combo));
GtkTreeModel *language_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(sort_model));
GtkListStore *cat_list = GTK_LIST_STORE(gtk_tree_view_get_model (data->categories_tree));
GtkTreeIter *iter = NULL;
gchar *language = NULL;
GtkTreeIter *iter = nullptr;
gchar *language = nullptr;
gint count = 0;
gboolean valid;
@ -408,7 +408,7 @@ region_combo_change_filter_cb (GtkComboBox *widget, hierarchy_data *data)
// loop through the regions and filter any out that are not linked to language setting
while (valid)
{
gchar *region_test = NULL;
gchar *region_test = nullptr;
gtk_tree_model_get (region_model, &region_iter,
LANGUAGE_STRING, &region_test, -1);
@ -433,7 +433,7 @@ region_combo_change_filter_cb (GtkComboBox *widget, hierarchy_data *data)
// if we only have a language or just one region activate it
if (count == 1)
{
gchar *region_label = NULL;
gchar *region_label = nullptr;
GtkTreeIter filter_iter;
gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER(filter_model),
&filter_iter,
@ -476,10 +476,10 @@ update_language_region_combos (hierarchy_data *data, const gchar *locale_dir)
{
GtkListStore *language_store = gtk_list_store_new (1, G_TYPE_STRING);
GtkListStore *region_store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
GtkTreeModel *filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL(region_store), NULL);
GtkTreeModel *filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL(region_store), nullptr);
GtkTreeModel *sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(language_store));
GtkTreeIter language_iter, region_iter;
gchar *start_region = NULL;
gchar *start_region = nullptr;
gboolean valid;
// set sort order
@ -495,11 +495,11 @@ update_language_region_combos (hierarchy_data *data, const gchar *locale_dir)
if (g_file_test (data->gnc_accounts_dir, G_FILE_TEST_IS_DIR))
{
GHashTable *testhash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
GDir *acct_dir = g_dir_open (data->gnc_accounts_dir, 0, NULL);
GHashTable *testhash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nullptr);
GDir *acct_dir = g_dir_open (data->gnc_accounts_dir, 0, nullptr);
const gchar *name = "a";
while (name != NULL)
while (name != nullptr)
{
name = g_dir_read_name (acct_dir);
@ -524,7 +524,7 @@ update_language_region_combos (hierarchy_data *data, const gchar *locale_dir)
start_region = g_strdup (parts[0]);
}
// add the region part to the region model store
if (parts[1] != NULL)
if (parts[1] != nullptr)
gtk_list_store_set (region_store, &region_iter, REGION_STRING, parts[1], -1);
else
gtk_list_store_set (region_store, &region_iter, REGION_STRING, "--", -1);
@ -545,12 +545,13 @@ update_language_region_combos (hierarchy_data *data, const gchar *locale_dir)
lang_name = g_strdup (parts[0]);
// see if language is in hash table so we only add it once.
if (g_hash_table_lookup (testhash, lang_name) == NULL)
if (g_hash_table_lookup (testhash, lang_name) == nullptr)
{
static const char* t_str{"test"};
gtk_list_store_append (language_store, &language_iter);
gtk_list_store_set (language_store, &language_iter, LANGUAGE_STRING, lang_name, -1);
g_hash_table_insert (testhash, g_strdup (lang_name), "test");
g_hash_table_insert (testhash, g_strdup (lang_name), &t_str);
}
g_strfreev (parts);
g_free (lang_name);
@ -564,7 +565,7 @@ update_language_region_combos (hierarchy_data *data, const gchar *locale_dir)
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(language_store), &language_iter);
while (valid)
{
gchar *language_test = NULL;
gchar *language_test = nullptr;
gtk_tree_model_get (GTK_TREE_MODEL(language_store), &language_iter, LANGUAGE_STRING, &language_test, -1);
@ -676,8 +677,8 @@ add_one_category (GncExampleAccount *acc,
GtkTreePath* path;
gboolean use_defaults;
g_return_if_fail(acc != NULL);
g_return_if_fail(data != NULL);
g_return_if_fail(acc != nullptr);
g_return_if_fail(data != nullptr);
view = data->categories_tree;
store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
@ -755,11 +756,11 @@ account_categories_tree_view_prepare (hierarchy_data *data)
data);
renderer = gtk_cell_renderer_toggle_new ();
g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
g_object_set (G_OBJECT (renderer), "activatable", TRUE, nullptr);
column = gtk_tree_view_column_new_with_attributes (_("Selected"),
renderer,
"active", COL_CHECKED,
NULL);
nullptr);
gtk_tree_view_append_column (tree_view, column);
gtk_tree_view_column_set_sort_column_id (column, COL_CHECKED);
g_signal_connect (G_OBJECT (renderer), "toggled",
@ -771,7 +772,7 @@ account_categories_tree_view_prepare (hierarchy_data *data)
column = gtk_tree_view_column_new_with_attributes (_("Account Types"),
renderer,
"text", COL_TITLE,
NULL);
nullptr);
gtk_tree_view_append_column (tree_view, column);
gtk_tree_view_column_set_sort_column_id (column, COL_TITLE);
@ -779,7 +780,7 @@ account_categories_tree_view_prepare (hierarchy_data *data)
// column = gtk_tree_view_column_new_with_attributes (_("Description"),
// renderer,
// "text", COL_SHORT_DESCRIPTION,
// NULL);
// nullptr);
// gtk_tree_view_append_column (tree_view, column);
// gtk_tree_view_column_set_sort_column_id (column, COL_SHORT_DESCRIPTION);
@ -793,7 +794,7 @@ account_categories_tree_view_prepare (hierarchy_data *data)
if (data->initial_category)
{
path = gtk_tree_row_reference_get_path (data->initial_category);
gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
gtk_tree_view_scroll_to_cell (tree_view, path, nullptr, TRUE, 0.5, 0.5);
}
else
path = gtk_tree_path_new_first ();
@ -832,7 +833,7 @@ on_choose_account_categories_prepare (hierarchy_data *data)
/* clear out the description/tree */
if (data->category_accounts_tree)
gtk_widget_destroy(GTK_WIDGET(data->category_accounts_tree));
data->category_accounts_tree = NULL;
data->category_accounts_tree = nullptr;
buffer = gtk_text_view_get_buffer(data->category_description);
gtk_text_buffer_set_text(buffer, "", -1);
@ -861,7 +862,7 @@ categories_tree_selection_changed (GtkTreeSelection *selection,
/* Remove the old account tree */
if (data->category_accounts_tree)
gtk_widget_destroy(GTK_WIDGET(data->category_accounts_tree));
data->category_accounts_tree = NULL;
data->category_accounts_tree = nullptr;
/* Add a new one if something selected */
if (gtk_tree_selection_get_selected (selection, &model, &iter))
@ -911,7 +912,7 @@ select_helper (GtkListStore *store,
g_return_val_if_fail(GTK_IS_LIST_STORE(store), FALSE);
gtk_tree_model_get (GTK_TREE_MODEL(store), iter, COL_ACCOUNT, &gea, -1);
if ((gea != NULL) && !gea->exclude_from_select_all)
if ((gea != nullptr) && !gea->exclude_from_select_all)
{
gtk_list_store_set(store, iter,
COL_CHECKED, GPOINTER_TO_INT(data),
@ -946,11 +947,11 @@ clear_all_clicked (GtkButton *button,
static void
delete_our_account_tree (hierarchy_data *data)
{
if (data->our_account_tree != NULL)
if (data->our_account_tree != nullptr)
{
xaccAccountBeginEdit (data->our_account_tree);
xaccAccountDestroy (data->our_account_tree);
data->our_account_tree = NULL;
data->our_account_tree = nullptr;
}
}
@ -976,7 +977,7 @@ struct add_group_data_struct
static void
add_groups_for_each (Account *toadd, gpointer data)
{
struct add_group_data_struct *dadata = data;
auto dadata{static_cast<struct add_group_data_struct*>(data)};
Account *foundact;
foundact = gnc_account_lookup_by_name(dadata->to, xaccAccountGetName(toadd));
@ -1015,7 +1016,7 @@ add_new_accounts_with_random_guids (Account *into, Account *from,
{
struct add_group_data_struct data;
data.to = into;
data.parent = NULL;
data.parent = nullptr;
data.com = com;
gnc_account_foreach_child (from, add_groups_for_each, &data);
@ -1029,7 +1030,7 @@ hierarchy_merge_accounts (GSList *dalist, gnc_commodity *com)
for (mark = dalist; mark; mark = mark->next)
{
GncExampleAccount *xea = mark->data;
auto xea{static_cast<GncExampleAccount*>(mark->data)};
add_new_accounts_with_random_guids (ret, xea->root, com);
}
@ -1062,7 +1063,7 @@ accumulate_accounts (GtkListStore *store,
static GSList *
get_selected_account_list (GtkTreeView *tree_view)
{
GSList *actlist = NULL;
GSList *actlist = nullptr;
GtkTreeModel *model;
model = gtk_tree_view_get_model (tree_view);
@ -1124,7 +1125,7 @@ balance_cell_data_func (GtkTreeViewColumn *tree_column,
"text", string,
"editable", allow_value,
"sensitive", allow_value,
NULL);
nullptr);
}
static void
@ -1138,20 +1139,20 @@ balance_cell_edited (GtkCellRendererText *cell,
gnc_numeric amount;
hierarchy_data *data = (hierarchy_data *)user_data;
g_return_if_fail(data != NULL);
g_return_if_fail(data != nullptr);
account = gnc_tree_view_account_get_selected_account(data->final_account_tree);
if (account == NULL)
if (account == nullptr)
{
g_critical("account is null");
return;
}
error_loc = NULL;
error_loc = nullptr;
if (!gnc_exp_parser_parse (new_text, &amount, &error_loc))
{
amount = gnc_numeric_zero();
g_object_set (G_OBJECT(cell), "text", "", NULL);
g_object_set (G_OBJECT(cell), "text", "", nullptr);
}
/* Bug#348364: Emulating price-cell, we need to ensure the denominator of
* the amount is in the SCU of the account's commodity (so
@ -1163,7 +1164,7 @@ balance_cell_edited (GtkCellRendererText *cell,
amount = gnc_numeric_convert(amount, account_cmdty_fraction, GNC_HOW_RND_ROUND_HALF_UP);
}
set_final_balance (data->balance_hash, account, amount);
qof_event_gen (QOF_INSTANCE(account), QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(account), QOF_EVENT_MODIFY, nullptr);
}
static void
@ -1211,7 +1212,7 @@ placeholder_cell_toggled (GtkCellRendererToggle *cell_renderer,
GtkTreePath *treepath;
hierarchy_data *data = (hierarchy_data *)user_data;
g_return_if_fail(data != NULL);
g_return_if_fail(data != nullptr);
treepath = gtk_tree_path_new_from_string (path);
@ -1226,7 +1227,7 @@ placeholder_cell_toggled (GtkCellRendererToggle *cell_renderer,
if (!state)
{
set_final_balance (data->balance_hash, account, gnc_numeric_zero());
qof_event_gen (QOF_INSTANCE(account), QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(account), QOF_EVENT_MODIFY, nullptr);
}
gtk_tree_path_free (treepath);
}
@ -1238,16 +1239,15 @@ use_existing_account_data_func(GtkTreeViewColumn *tree_column,
GtkTreeIter *iter,
gpointer user_data)
{
Account *new_acct;
Account *real_root;
GncAccountMergeDisposition disposition;
char *to_user = "(error; unknown condition)";
auto to_user{"(error; unknown condition)"};
g_return_if_fail (GTK_TREE_MODEL (tree_model));
new_acct = gnc_tree_view_account_get_account_from_iter(tree_model, iter);
if (new_acct == NULL)
auto new_acct{static_cast<Account*>(gnc_tree_view_account_get_account_from_iter(tree_model, iter))};
if (!new_acct)
{
g_object_set (G_OBJECT(cell), "text", "(null account)", NULL);
g_object_set (G_OBJECT(cell), "text", "(null account)", nullptr);
return;
}
@ -1263,7 +1263,7 @@ use_existing_account_data_func(GtkTreeViewColumn *tree_column,
break;
}
g_object_set(G_OBJECT(cell), "text", to_user, NULL);
g_object_set(G_OBJECT(cell), "text", to_user, nullptr);
}
void
@ -1287,7 +1287,7 @@ on_final_account_prepare (hierarchy_data *data)
if (data->final_account_tree)
{
gtk_widget_destroy(GTK_WIDGET(data->final_account_tree));
data->final_account_tree = NULL;
data->final_account_tree = nullptr;
}
delete_our_account_tree (data);
@ -1330,17 +1330,17 @@ on_final_account_prepare (hierarchy_data *data)
g_object_set(G_OBJECT (renderer),
"activatable", TRUE,
"sensitive", TRUE,
NULL);
nullptr);
g_signal_connect (G_OBJECT (renderer), "toggled",
G_CALLBACK (placeholder_cell_toggled),
data);
column = gtk_tree_view_column_new_with_attributes(_("Placeholder"),
renderer, NULL);
renderer, nullptr);
gtk_tree_view_column_set_cell_data_func (column, renderer,
placeholder_cell_data_func,
(gpointer)data, NULL);
(gpointer)data, nullptr);
gnc_tree_view_append_column (GNC_TREE_VIEW(tree_view), column);
}
@ -1349,16 +1349,16 @@ on_final_account_prepare (hierarchy_data *data)
renderer = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (renderer),
"xalign", 1.0,
(char *)NULL);
(char *)nullptr);
g_signal_connect (G_OBJECT (renderer), "edited",
G_CALLBACK (balance_cell_edited),
data);
column = gtk_tree_view_column_new_with_attributes (_("Opening Balance"),
renderer,
NULL);
nullptr);
gtk_tree_view_column_set_cell_data_func (column, renderer,
balance_cell_data_func,
(gpointer)data, NULL);
(gpointer)data, nullptr);
gnc_tree_view_append_column (GNC_TREE_VIEW(tree_view), column);
}
@ -1368,16 +1368,16 @@ on_final_account_prepare (hierarchy_data *data)
GList *renderers;
column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(tree_view),
_("Use Existing"),
NULL,
NULL,
nullptr,
nullptr,
"yes",
GNC_TREE_VIEW_COLUMN_DATA_NONE,
GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
NULL);
nullptr);
renderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
g_object_set(G_OBJECT(renderer), "xalign", 1.0, (char*)NULL);
g_object_set(G_OBJECT(renderer), "xalign", 1.0, (char*)nullptr);
gtk_tree_view_column_set_cell_data_func(column, GTK_CELL_RENDERER(renderers->data),
use_existing_account_data_func, (gpointer)data, NULL);
use_existing_account_data_func, (gpointer)data, nullptr);
g_list_free(renderers);
}
@ -1396,7 +1396,7 @@ on_cancel (GtkAssistant *gtkassistant,
{
gnc_suspend_gui_refresh ();
if (data->new_book)
gnc_options_dialog_destroy (data->optionwin);
delete data->optionwin;
delete_hierarchy_dialog (data);
delete_our_account_tree (data);
@ -1414,7 +1414,8 @@ starting_balance_helper (Account *account, hierarchy_data *data)
balance = gnc_numeric_neg(balance);
if (!gnc_numeric_zero_p (balance) &&
gnc_commodity_is_currency (xaccAccountGetCommodity (account)))
gnc_account_create_opening_balance (account, balance, gnc_time (NULL),
gnc_account_create_opening_balance (account, balance,
gnc_time (nullptr),
gnc_get_current_book ());
}
@ -1443,7 +1444,7 @@ on_finish (GtkAssistant *gtkassistant,
gnc_suspend_gui_refresh ();
if (data->new_book)
gnc_options_dialog_destroy (data->optionwin);
delete data->optionwin;
account_trees_merge(gnc_get_current_root_account(), data->our_account_tree);
@ -1477,24 +1478,11 @@ on_select_currency_prepare (hierarchy_data *data)
{
gnc_book_options_dialog_apply_helper(data->options);
if (gnc_book_use_book_currency (gnc_get_current_book ()))
{
gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(data->currency_selector),
gnc_book_get_book_currency (gnc_get_current_book ()));
gtk_label_set_text (GTK_LABEL(data->currency_selector_label),
( _("You selected a book currency and it will be used for\n" \
"new accounts. Accounts in other currencies must be\n" \
"added manually.") ));
gtk_widget_set_sensitive(data->currency_selector, FALSE);
}
else
{
gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(data->currency_selector),
gnc_default_currency());
gtk_label_set_text (GTK_LABEL(data->currency_selector_label),
( _("Please choose the currency to use for new accounts.") ));
gtk_widget_set_sensitive(data->currency_selector, TRUE);
}
gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(data->currency_selector),
gnc_default_currency());
gtk_label_set_text (GTK_LABEL(data->currency_selector_label),
( _("Please choose the currency to use for new accounts.") ));
gtk_widget_set_sensitive(data->currency_selector, TRUE);
}
}
@ -1515,39 +1503,39 @@ on_select_currency_prepare (hierarchy_data *data)
* dialog to make it clean up after itself.
*/
static void
book_options_dialog_close_cb(GNCOptionWin * optionwin,
gpointer user_data)
book_options_dialog_close_cb(GncOptionsDialog *optionwin,
gpointer user_data)
{
GNCOptionDB * options = user_data;
auto options{static_cast<GncOptionDB*>(user_data)};
gnc_options_dialog_destroy(optionwin);
delete optionwin;
gnc_option_db_destroy(options);
}
static void
assistant_insert_book_options_page (hierarchy_data *data)
{
GtkWidget *options, *parent;
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_set_homogeneous (GTK_BOX (vbox), FALSE);
data->options = gnc_option_db_new_for_type (QOF_ID_BOOK);
data->options = gnc_option_db_new();
gnc_option_db_book_options(data->options);
qof_book_load_options (gnc_get_current_book (),
gnc_option_db_load, data->options);
gnc_option_db_clean (data->options);
/* The options dialog gets added to the notebook so it doesn't need a parent.*/
data->optionwin = gnc_options_dialog_new_modal (TRUE, _("New Book Options"),
DIALOG_BOOK_OPTIONS_CM_CLASS, NULL);
gnc_options_dialog_build_contents_full (data->optionwin, data->options, FALSE);
data->optionwin = new GncOptionsDialog(true, _("New Book Options"),
DIALOG_BOOK_OPTIONS_CM_CLASS,
nullptr);
data->optionwin->build_contents(data->options, false);
gnc_options_dialog_set_close_cb (data->optionwin,
book_options_dialog_close_cb,
(gpointer)data->options);
data->optionwin->set_close_cb(book_options_dialog_close_cb,
(gpointer)data->options);
gnc_options_dialog_set_new_book_option_values (data->options);
options = gnc_options_dialog_notebook (data->optionwin);
parent = gtk_widget_get_parent (options);
auto options = data->optionwin->get_notebook();
auto parent = gtk_widget_get_parent (options);
g_object_ref (options);
gtk_container_remove (GTK_CONTAINER(parent), options);
@ -1634,12 +1622,12 @@ gnc_create_hierarchy_assistant (gboolean use_defaults, GncHierarchyAssistantFini
/* Final Accounts Page */
data->final_account_tree_container = GTK_WIDGET(gtk_builder_get_object (builder, "final_account_tree_box"));
data->final_account_tree = NULL;
data->final_account_tree = nullptr;
data->balance_hash = g_hash_table_new(NULL, NULL);
data->balance_hash = g_hash_table_new(nullptr, nullptr);
gnc_restore_window_size (GNC_PREFS_GROUP,
GTK_WINDOW(data->dialog), gnc_ui_get_main_window(NULL));
GTK_WINDOW(data->dialog), gnc_ui_get_main_window(nullptr));
g_signal_connect (G_OBJECT(dialog), "destroy",
G_CALLBACK (gnc_hierarchy_destroy_cb), data);
@ -1656,7 +1644,7 @@ gnc_create_hierarchy_assistant (gboolean use_defaults, GncHierarchyAssistantFini
GtkWidget*
gnc_ui_hierarchy_assistant(gboolean use_defaults)
{
return gnc_create_hierarchy_assistant(use_defaults, NULL);
return gnc_create_hierarchy_assistant(use_defaults, nullptr);
}
GtkWidget*
@ -1670,7 +1658,7 @@ static void
after_assistant(void)
{
qof_book_mark_session_dirty(gnc_get_current_book());
gnc_ui_file_access_for_save_as (gnc_ui_get_main_window (NULL));
gnc_ui_file_access_for_save_as (gnc_ui_get_main_window (nullptr));
}
static void
@ -1686,5 +1674,6 @@ void
gnc_ui_hierarchy_assistant_initialize (void)
{
gnc_hook_add_dangler(HOOK_NEW_BOOK,
(GFunc)gnc_ui_hierarchy_assistant_hook, NULL, NULL);
(GFunc)gnc_ui_hierarchy_assistant_hook,
nullptr, nullptr);
}

View File

@ -29,6 +29,10 @@
* completes successfully. I.e., the new-user assistant can finish the GnuCash
* New-User Experience, create an account plugin-page, &c.
**/
#ifdef __cplusplus
extern "C"
{
#endif
typedef void (*GncHierarchyAssistantFinishedCallback)(void);
@ -37,4 +41,7 @@ GtkWidget* gnc_ui_hierarchy_assistant_with_callback(gboolean use_defaults, GncHi
void gnc_ui_hierarchy_assistant_initialize (void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,501 +0,0 @@
/*
* business-options.c -- Initialize Business Options
*
* Written By: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2002,2006 Derek Atkins
*
* 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 <gtk/gtk.h>
#include <glib/gi18n.h>
#include "swig-runtime.h"
#include "guile-mappings.h"
#include <libguile.h>
#include "gnc-ui-util.h"
#include "dialog-utils.h"
#include "qof.h"
#include "option-util.h"
#include "gnc-general-search.h"
#include "dialog-options.h"
#include "business-options-gnome.h"
#include "business-gnome-utils.h"
#include "dialog-invoice.h"
#define FUNC_NAME G_STRFUNC
static GtkWidget *
create_owner_widget (GNCOption *option, GncOwnerType type, GtkWidget *hbox)
{
GtkWidget *widget;
GncOwner owner;
switch (type)
{
case GNC_OWNER_CUSTOMER:
gncOwnerInitCustomer (&owner, NULL);
break;
case GNC_OWNER_VENDOR:
gncOwnerInitVendor (&owner, NULL);
break;
case GNC_OWNER_EMPLOYEE:
gncOwnerInitEmployee (&owner, NULL);
break;
case GNC_OWNER_JOB:
gncOwnerInitJob (&owner, NULL);
break;
default:
return NULL;
}
widget = gnc_owner_select_create (NULL, hbox,
gnc_get_current_book (), &owner);
gnc_option_set_widget (option, widget);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_option_cb), option);
return widget;
}
static GtkWidget *
make_name_label (char *name)
{
GtkWidget *label = gtk_label_new (name);
gnc_label_set_alignment (label, 1.0, 0.5);
return label;
}
/********************************************************************/
/* "Owner" Option functions */
static GncOwnerType
get_owner_type_from_option (GNCOption *option)
{
SCM odata = gnc_option_get_option_data (option);
/* The option data is enum-typed. It's just the enum value. */
return (GncOwnerType) scm_to_int(odata);
}
/* Function to set the UI widget based upon the option */
static GtkWidget *
owner_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_owner_widget (option, get_owner_type_from_option (option),
*enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
owner_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncOwner owner_def;
GncOwner *owner;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:owner_set_value",
"SCM is not a wrapped pointer.", value);
owner = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncOwner"), 1, 0);
/* XXX: should we verify that the owner type is correct? */
if (!owner)
{
owner_def.type = get_owner_type_from_option (option);
owner_def.owner.undefined = NULL;
owner = &owner_def;
}
widget = gnc_option_get_gtk_widget (option);
gnc_owner_set_owner (widget, owner);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
owner_get_value (GNCOption *option, GtkWidget *widget)
{
static GncOwner owner; /* XXX: might cause trouble? */
GncOwnerType type;
type = get_owner_type_from_option (option);
owner.type = type;
gnc_owner_get_owner (widget, &owner);
return SWIG_NewPointerObj(&owner, SWIG_TypeQuery("_p__gncOwner"), 0);
}
/********************************************************************/
/* "Customer" Option functions */
/* Function to set the UI widget based upon the option */
static GtkWidget *
customer_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_owner_widget (option, GNC_OWNER_CUSTOMER, *enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
customer_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncOwner owner;
GncCustomer *customer;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:customer_set_value",
"SCM is not a wrapped pointer.", value);
customer = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncCustomer"), 1, 0);
gncOwnerInitCustomer (&owner, customer);
widget = gnc_option_get_gtk_widget (option);
gnc_owner_set_owner (widget, &owner);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
customer_get_value (GNCOption *option, GtkWidget *widget)
{
GncOwner owner;
gnc_owner_get_owner (widget, &owner);
return SWIG_NewPointerObj(owner.owner.undefined,
SWIG_TypeQuery("_p__gncCustomer"), 0);
}
/********************************************************************/
/* "Vendor" Option functions */
/* Function to set the UI widget based upon the option */
static GtkWidget *
vendor_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_owner_widget (option, GNC_OWNER_VENDOR, *enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
vendor_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncOwner owner;
GncVendor *vendor;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:vendor_set_value",
"SCM is not a wrapped pointer.", value);
vendor = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncVendor"), 1, 0);
gncOwnerInitVendor (&owner, vendor);
widget = gnc_option_get_gtk_widget (option);
gnc_owner_set_owner (widget, &owner);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
vendor_get_value (GNCOption *option, GtkWidget *widget)
{
GncOwner owner;
gnc_owner_get_owner (widget, &owner);
return SWIG_NewPointerObj(owner.owner.undefined,
SWIG_TypeQuery("_p__gncVendor"), 0);
}
/********************************************************************/
/* "Employee" Option functions */
/* Function to set the UI widget based upon the option */
static GtkWidget *
employee_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_owner_widget (option, GNC_OWNER_EMPLOYEE, *enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
employee_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncOwner owner;
GncEmployee *employee;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:employee_set_value",
"SCM is not a wrapped pointer.", value);
employee = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncEmployee"), 1, 0);
gncOwnerInitEmployee (&owner, employee);
widget = gnc_option_get_gtk_widget (option);
gnc_owner_set_owner (widget, &owner);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
employee_get_value (GNCOption *option, GtkWidget *widget)
{
GncOwner owner;
gnc_owner_get_owner (widget, &owner);
return SWIG_NewPointerObj(owner.owner.undefined,
SWIG_TypeQuery("_p__gncEmployee"), 0);
}
/********************************************************************/
/* "Invoice" Option functions */
static GtkWidget *
create_invoice_widget (GNCOption *option, GtkWidget *hbox)
{
GtkWidget *widget;
/* No owner or starting invoice here, but that's okay. */
widget = gnc_invoice_select_create (hbox, gnc_get_current_book(),
NULL, NULL, NULL);
gnc_option_set_widget (option, widget);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_option_cb), option);
return widget;
}
/* Function to set the UI widget based upon the option */
static GtkWidget *
invoice_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_invoice_widget (option, *enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
invoice_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncInvoice *invoice;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:invoice_set_value",
"SCM is not a wrapped pointer.", value);
invoice = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncInvoice"), 1, 0);
widget = gnc_option_get_gtk_widget (option);
gnc_general_search_set_selected (GNC_GENERAL_SEARCH (widget), invoice);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
invoice_get_value (GNCOption *option, GtkWidget *widget)
{
GncInvoice *invoice;
invoice = gnc_general_search_get_selected (GNC_GENERAL_SEARCH (widget));
return SWIG_NewPointerObj(invoice, SWIG_TypeQuery("_p__gncInvoice"), 0);
}
/********************************************************************/
/* "Tax Table" Option functions */
static GtkWidget *
create_taxtable_widget (GNCOption *option, GtkWidget *hbox)
{
GtkWidget *widget;
GtkBuilder *builder;
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "business-options-gnome.glade", "taxtable_store");
gnc_builder_add_from_file (builder, "business-options-gnome.glade", "taxtable_menu");
widget = GTK_WIDGET (gtk_builder_get_object (builder, "taxtable_menu"));
gnc_taxtables_combo (GTK_COMBO_BOX(widget), gnc_get_current_book (), TRUE, NULL);
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
gnc_option_set_widget (option, widget);
g_signal_connect (widget, "changed",
G_CALLBACK (gnc_option_changed_option_cb), option);
g_object_unref(G_OBJECT(builder));
return widget;
}
/* Function to set the UI widget based upon the option */
static GtkWidget *
taxtable_set_widget (GNCOption *option, GtkGrid *page_box,
GtkLabel *name_label, char *documentation,
/* Return values */
GtkWidget **enclosing, gboolean *packed)
{
GtkWidget *value;
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
value = create_taxtable_widget (option, *enclosing);
gnc_option_set_ui_value (option, FALSE);
gtk_widget_show_all (*enclosing);
return value;
}
/* Function to set the UI Value for a particular option */
static gboolean
taxtable_set_value (GNCOption *option, gboolean use_default,
GtkWidget *widget, SCM value)
{
GncTaxTable *taxtable;
if (!SWIG_IsPointer (value))
scm_misc_error("business_options:taxtable_set_value",
"SCM is not a wrapped pointer.", value);
taxtable = SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncTaxTable"), 1, 0);
widget = gnc_option_get_gtk_widget (option);
gnc_simple_combo_set_value (GTK_COMBO_BOX(widget), taxtable);
return FALSE;
}
/* Function to get the UI Value for a particular option */
static SCM
taxtable_get_value (GNCOption *option, GtkWidget *widget)
{
GncTaxTable *taxtable;
taxtable = gnc_simple_combo_get_value (GTK_COMBO_BOX(widget));
return SWIG_NewPointerObj(taxtable, SWIG_TypeQuery("_p__gncTaxTable"), 0);
}
void
gnc_business_options_gnome_initialize (void)
{
int i;
static GNCOptionDef_t options[] =
{
{ "owner", owner_set_widget, owner_set_value, owner_get_value },
{
"customer", customer_set_widget, customer_set_value,
customer_get_value
},
{ "vendor", vendor_set_widget, vendor_set_value, vendor_get_value },
{ "employee", employee_set_widget, employee_set_value, employee_get_value },
{ "invoice", invoice_set_widget, invoice_set_value, invoice_get_value },
{ "taxtable", taxtable_set_widget, taxtable_set_value, taxtable_get_value },
{ NULL }
};
SWIG_GetModule(NULL); /* Work-around for SWIG bug. */
for (i = 0; options[i].option_name; i++)
gnc_options_ui_register_option (&(options[i]));
}

View File

@ -0,0 +1,224 @@
/*
* business-options.c -- Initialize Business Options
*
* Written By: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2002,2006 Derek Atkins
*
* 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 <libguile.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
extern "C"
{
#include <config.h>
#include "swig-runtime.h"
#include "guile-mappings.h"
#include "gnc-ui-util.h"
#include "dialog-utils.h"
#include "qof.h"
#include "gnc-general-search.h"
#include "business-options-gnome.h"
#include "business-gnome-utils.h"
#include "dialog-invoice.h"
}
#include <iostream>
#include <sstream>
#include <exception>
#include <dialog-options.hpp>
#include <gnc-option.hpp>
#define FUNC_NAME G_STRFUNC
static inline GncOwnerType
ui_type_to_owner_type(GncOptionUIType ui_type)
{
if (ui_type == GncOptionUIType::CUSTOMER)
return GNC_OWNER_CUSTOMER;
if (ui_type == GncOptionUIType::VENDOR)
return GNC_OWNER_VENDOR;
if (ui_type == GncOptionUIType::EMPLOYEE)
return GNC_OWNER_EMPLOYEE;
std::ostringstream oss;
oss << "UI type " << static_cast<unsigned int>(ui_type) << " could not be converted to owner type\n";
throw std::invalid_argument(oss.str());
}
class GncGtkOwnerUIItem : public GncOptionGtkUIItem
{
public:
GncGtkOwnerUIItem(GtkWidget* widget, GncOptionUIType type) :
GncOptionGtkUIItem(widget, type) {}
void set_ui_item_from_option(GncOption& option) noexcept override
{
GncOwner owner{};
owner.type = ui_type_to_owner_type(option.get_ui_type());
owner.owner.undefined = (void*)option.get_value<const QofInstance*>();
gnc_owner_set_owner(get_widget(), &owner);
}
void set_option_from_ui_item(GncOption& option) noexcept override
{
GncOwner owner{};
gnc_owner_get_owner(get_widget(), &owner);
if (owner.type == ui_type_to_owner_type(option.get_ui_type()))
option.set_value(static_cast<const QofInstance*>(owner.owner.undefined));
}
};
template<> GtkWidget*
create_option_widget<GncOptionUIType::OWNER>(GncOption& option,
GtkGrid *page_box,
GtkLabel *name_label,
char *documentation,
/* Return values */
GtkWidget **enclosing,
bool *packed)
{
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
GncOwner owner{};
auto ui_type{option.get_ui_type()};
owner.type = ui_type_to_owner_type(ui_type);
auto widget = gnc_owner_select_create(nullptr, *enclosing,
gnc_get_current_book(),
&owner);
option.set_ui_item(std::make_unique<GncGtkOwnerUIItem>(widget, ui_type));
option.set_ui_item_from_option();
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_widget_cb), &option);
gtk_widget_show_all(*enclosing);
return widget;
}
class GncGtkInvoiceUIItem : public GncOptionGtkUIItem
{
public:
GncGtkInvoiceUIItem(GtkWidget* widget) :
GncOptionGtkUIItem(widget, GncOptionUIType::INVOICE) {}
void set_ui_item_from_option(GncOption& option) noexcept override
{
auto instance{option.get_value<const QofInstance*>()};
if (instance)
gnc_general_search_set_selected(GNC_GENERAL_SEARCH(get_widget()),
GNC_INVOICE(instance));
}
void set_option_from_ui_item(GncOption& option) noexcept override
{
option.set_value(qof_instance_cast(gnc_general_search_get_selected(GNC_GENERAL_SEARCH(get_widget()))));
}
};
template<> GtkWidget*
create_option_widget<GncOptionUIType::INVOICE>(GncOption& option,
GtkGrid *page_box,
GtkLabel *name_label,
char *documentation,
/* Return values */
GtkWidget **enclosing,
bool *packed)
{
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
auto widget{gnc_invoice_select_create(*enclosing, gnc_get_current_book(),
nullptr, nullptr, nullptr)};
option.set_ui_item(std::make_unique<GncGtkInvoiceUIItem>(widget));
option.set_ui_item_from_option();
g_signal_connect(G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_widget_cb), &option);
gtk_widget_show_all(*enclosing);
return widget;
}
class GncGtkTaxTableUIItem : public GncOptionGtkUIItem
{
public:
GncGtkTaxTableUIItem(GtkWidget* widget) :
GncOptionGtkUIItem(widget, GncOptionUIType::TAX_TABLE) {}
void set_ui_item_from_option(GncOption& option) noexcept override
{
auto taxtable{option.get_value<const QofInstance*>()};
if (taxtable)
gnc_simple_combo_set_value(GTK_COMBO_BOX(get_widget()),
GNC_TAXTABLE(taxtable));
}
void set_option_from_ui_item(GncOption& option) noexcept override
{
auto taxtable{gnc_simple_combo_get_value(GTK_COMBO_BOX(get_widget()))};
option.set_value<const QofInstance*>(qof_instance_cast(taxtable));
}
};
template<> GtkWidget*
create_option_widget<GncOptionUIType::TAX_TABLE>(GncOption& option,
GtkGrid *page_box,
GtkLabel *name_label,
char *documentation,
/* Return values */
GtkWidget **enclosing,
bool *packed)
{
*enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
constexpr const char* glade_file{"business-options-gnome.glade"};
constexpr const char* glade_store{"taxtable_store"};
constexpr const char* glade_menu{"taxtable_menu"};
auto builder{gtk_builder_new()};
gnc_builder_add_from_file(builder, glade_file, glade_store);
gnc_builder_add_from_file(builder, glade_file, glade_menu);
auto widget{GTK_WIDGET(gtk_builder_get_object(builder, glade_menu))};
gnc_taxtables_combo(GTK_COMBO_BOX(widget), gnc_get_current_book(), TRUE,
nullptr);
gtk_box_pack_start(GTK_BOX(*enclosing), widget, FALSE, FALSE, 0);
option.set_ui_item(std::make_unique<GncGtkTaxTableUIItem>(widget));
option.set_ui_item_from_option();
g_object_unref(builder); // Needs to wait until after widget has been reffed.
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_widget_cb), &option);
gtk_widget_show_all(*enclosing);
return widget;
}
void
gnc_business_options_gnome_initialize(void)
{
GncOptionUIFactory::set_func(GncOptionUIType::OWNER,
create_option_widget<GncOptionUIType::OWNER>);
GncOptionUIFactory::set_func(GncOptionUIType::CUSTOMER,
create_option_widget<GncOptionUIType::OWNER>);
GncOptionUIFactory::set_func(GncOptionUIType::VENDOR,
create_option_widget<GncOptionUIType::OWNER>);
GncOptionUIFactory::set_func(GncOptionUIType::EMPLOYEE,
create_option_widget<GncOptionUIType::OWNER>);
GncOptionUIFactory::set_func(GncOptionUIType::INVOICE,
create_option_widget<GncOptionUIType::INVOICE>);
GncOptionUIFactory::set_func(GncOptionUIType::TAX_TABLE,
create_option_widget<GncOptionUIType::TAX_TABLE>);
}

View File

@ -1,5 +1,5 @@
/*
* business-options.h -- Initialize the Business Options
* business-options-gnome.h -- Initialize the Business Options
*
* Written By: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2002 Derek Atkins
@ -21,10 +21,19 @@
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/** @addtogroup GUI
@{ */
/** @addtogroup GuiOptions Options Dialog
@{ */
#ifndef GNC_BUSINESS_OPTIONS_H_
#define GNC_BUSINESS_OPTIONS_H_
/**
* Set up the business and counters pages in the File Preferences dialog.
*/
void gnc_business_options_gnome_initialize (void);
#endif /* GNC_BUSINESS_OPTIONS_H_ */
/** @}
@} */

View File

@ -29,10 +29,8 @@
#include "swig-runtime.h"
#include "dialog-custom-report.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "gnc-main-window.h"
#include "option-util.h"
#include "window-report.h"
#include "guile-mappings.h"
#include "gnc-guile-utils.h"

View File

@ -1,705 +0,0 @@
/********************************************************************
* dialog-report-column-view.c -- editor for column view of reports *
* Copyright (C) 2001 Bill Gribble <grib@billgribble.com> *
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
* *
* 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 <gtk/gtk.h>
#include <libguile.h>
#include "swig-runtime.h"
#include "dialog-report-column-view.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "option-util.h"
#include "window-report.h"
#include "guile-mappings.h"
#include "gnc-guile-utils.h"
#include "gnc-report.h"
#include "gnc-ui.h"
enum available_cols
{
AVAILABLE_COL_NAME = 0,
AVAILABLE_COL_GUID,
NUM_AVAILABLE_COLS
};
enum contents_cols
{
CONTENTS_COL_NAME = 0,
CONTENTS_COL_ROW,
CONTENTS_COL_REPORT_ROWS,
CONTENTS_COL_REPORT_COLS,
NUM_CONTENTS_COLS
};
struct gncp_column_view_edit
{
GNCOptionWin * optwin;
GtkTreeView * available;
GtkTreeView * contents;
SCM options;
SCM view;
GNCOptionDB * odb;
SCM available_list;
SCM contents_list;
int contents_selected;
GtkWidget *add_button;
GtkWidget *remove_button;
GtkWidget *up_button;
GtkWidget *down_button;
GtkWidget *size_button;
};
void gnc_column_view_edit_add_cb(GtkButton * button, gpointer user_data);
void gnc_column_view_edit_remove_cb(GtkButton * button, gpointer user_data);
void gnc_edit_column_view_move_up_cb(GtkButton * button, gpointer user_data);
void gnc_edit_column_view_move_down_cb(GtkButton * button, gpointer user_data);
void gnc_column_view_edit_size_cb(GtkButton * button, gpointer user_data);
static void
gnc_column_view_set_option(GNCOptionDB * odb, char * section, char * name,
SCM new_value)
{
GNCOption * option =
gnc_option_db_get_option_by_name(odb, section, name);
if (option)
{
gnc_option_db_set_option(odb, section, name, new_value);
/* set_option doesn't do this */
gnc_option_set_changed (option, TRUE);
}
}
static void
gnc_column_view_edit_destroy(gnc_column_view_edit * view)
{
gnc_options_dialog_destroy(view->optwin);
scm_gc_unprotect_object(view->options);
scm_gc_unprotect_object(view->view);
gnc_option_db_destroy(view->odb);
g_free(view);
}
static void
update_available_lists(gnc_column_view_edit * view)
{
SCM get_rpt_guids = scm_c_eval_string("gnc:all-report-template-guids");
SCM template_menu_name = scm_c_eval_string("gnc:report-template-menu-name/report-guid");
SCM rpt_guids = scm_call_0(get_rpt_guids);
SCM selection;
gchar *name;
gchar *guid_str;
GtkTreeModel *model;
GtkListStore *store;
GtkTreeIter iter;
GtkTreeSelection *tree_selection;
/* Update the list of available reports (left selection box). */
tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view->available));
model = gtk_tree_view_get_model (GTK_TREE_VIEW(view->available));
if (gtk_tree_selection_get_selected(tree_selection, &model, &iter))
{
gchar *guid_str;
gtk_tree_model_get(model, &iter,
AVAILABLE_COL_GUID, &guid_str,
-1);
selection = scm_from_utf8_string(guid_str);
g_free (guid_str);
}
else
selection = SCM_UNDEFINED;
scm_gc_unprotect_object(view->available_list);
view->available_list = rpt_guids;
scm_gc_protect_object(view->available_list);
store = GTK_LIST_STORE(model);
gtk_list_store_clear(store);
if (scm_is_list(rpt_guids))
{
for (int i = 0; !scm_is_null(rpt_guids); rpt_guids = SCM_CDR(rpt_guids), i++)
{
SCM rpt_guids_temp = SCM_CAR(rpt_guids);
guid_str = scm_to_utf8_string (rpt_guids_temp);
name = gnc_scm_to_utf8_string (scm_call_2(template_menu_name, rpt_guids_temp,
SCM_BOOL_F));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
AVAILABLE_COL_NAME, _(name),
AVAILABLE_COL_GUID, guid_str,
-1);
if (scm_is_equal (rpt_guids_temp, selection))
gtk_tree_selection_select_iter (tree_selection, &iter);
g_free (name);
g_free (guid_str);
}
}
}
static void
update_contents_lists(gnc_column_view_edit * view)
{
SCM report_menu_name = scm_c_eval_string("gnc:report-menu-name");
SCM contents =
gnc_option_db_lookup_option(view->odb, "__general", "report-list",
SCM_BOOL_F);
SCM this_report;
SCM selection;
gchar *name;
GtkListStore *store;
GtkTreeIter iter;
GtkTreeSelection *tree_selection;
/* Update the list of selected reports (right selection box). */
tree_selection = gtk_tree_view_get_selection(view->contents);
if (scm_is_list(view->contents_list) && !scm_is_null (view->contents_list))
{
int row = view->contents_selected;
row = MIN (row, scm_ilength (view->contents_list) - 1);
selection = scm_list_ref (view->contents_list, scm_from_int (row));
}
else
selection = SCM_UNDEFINED;
scm_gc_unprotect_object(view->contents_list);
view->contents_list = contents;
scm_gc_protect_object(view->contents_list);
store = GTK_LIST_STORE(gtk_tree_view_get_model(view->contents));
gtk_list_store_clear(store);
if (scm_is_list(contents))
{
for (int i = 0; !scm_is_null(contents); contents = SCM_CDR(contents), i++)
{
SCM contents_temp = SCM_CAR(contents);
int id = scm_to_int(SCM_CAAR(contents));
this_report = gnc_report_find(id);
name = gnc_scm_to_utf8_string (scm_call_1(report_menu_name, this_report));
gtk_list_store_append(store, &iter);
gtk_list_store_set
(store, &iter,
CONTENTS_COL_NAME, _(name),
CONTENTS_COL_ROW, i,
CONTENTS_COL_REPORT_COLS, scm_to_int(SCM_CADR(contents_temp)),
CONTENTS_COL_REPORT_ROWS, scm_to_int(SCM_CADDR(contents_temp)),
-1);
if (scm_is_equal (contents_temp, selection))
gtk_tree_selection_select_iter (tree_selection, &iter);
g_free (name);
}
}
}
static void
gnc_column_view_update_buttons_cb (GtkTreeSelection *selection,
gnc_column_view_edit *r)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean is_selected;
/* compare treeviews to establish which selected treeview */
if (gtk_tree_selection_get_tree_view (selection) == r->available)
{
/* available treeview */
is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_widget_set_sensitive (r->add_button, is_selected);
return;
}
/* contents treeview */
is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_widget_set_sensitive (r->size_button, is_selected);
gtk_widget_set_sensitive (r->remove_button, is_selected);
if (is_selected)
{
int len = scm_ilength (r->contents_list);
gtk_tree_model_get (model, &iter,
CONTENTS_COL_ROW, &r->contents_selected, -1);
if (len > 1)
{
gtk_widget_set_sensitive (r->up_button, TRUE);
gtk_widget_set_sensitive (r->down_button, TRUE);
if (r->contents_selected == len -1)
gtk_widget_set_sensitive (r->down_button, FALSE);
if (r->contents_selected == 0)
gtk_widget_set_sensitive (r->up_button, FALSE);
}
}
else
{
gtk_widget_set_sensitive (r->up_button, FALSE);
gtk_widget_set_sensitive (r->down_button, FALSE);
}
}
static void
gnc_column_view_edit_apply_cb(GNCOptionWin * w, gpointer user_data)
{
SCM dirty_report = scm_c_eval_string("gnc:report-set-dirty?!");
gnc_column_view_edit * win = user_data;
GList *results = NULL, *iter;
if (!win) return;
results = gnc_option_db_commit (win->odb);
for (iter = results; iter; iter = iter->next)
{
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(gnc_options_dialog_widget(w)),
0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free (iter->data);
}
g_list_free (results);
scm_call_2(dirty_report, win->view, SCM_BOOL_T);
}
static void
gnc_column_view_edit_close_cb(GNCOptionWin * win, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
SCM set_editor = scm_c_eval_string("gnc:report-set-editor-widget!");
scm_call_2(set_editor, r->view, SCM_BOOL_F);
gnc_column_view_edit_destroy(r);
}
/********************************************************************
* gnc_column_view_edit_options
* create the editor.
********************************************************************/
GtkWidget *
gnc_column_view_edit_options(SCM options, SCM view)
{
SCM get_editor = scm_c_eval_string("gnc:report-editor-widget");
SCM ptr;
GtkWidget * editor;
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
ptr = scm_call_1(get_editor, view);
if (ptr != SCM_BOOL_F)
{
#define FUNC_NAME "gtk_window_present"
GtkWindow * w = SWIG_MustGetPtr(ptr, SWIG_TypeQuery("_p_GtkWidget"), 1, 0);
gtk_window_present(w);
#undef FUNC_NAME
return NULL;
}
else
{
gnc_column_view_edit * r = g_new0(gnc_column_view_edit, 1);
GtkBuilder *builder;
r->optwin = gnc_options_dialog_new (NULL, GTK_WINDOW(gnc_ui_get_main_window (NULL)));
/* Hide the generic dialog page list. */
gtk_widget_hide(gnc_options_page_list(r->optwin));
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-report.glade", "view_contents_table");
editor = GTK_WIDGET(gtk_builder_get_object (builder, "view_contents_table"));
r->available = GTK_TREE_VIEW (gtk_builder_get_object (builder, "available_view"));
r->contents = GTK_TREE_VIEW (gtk_builder_get_object (builder, "contents_view"));
r->add_button = GTK_WIDGET(gtk_builder_get_object (builder, "add_button1"));
r->remove_button = GTK_WIDGET(gtk_builder_get_object (builder, "remove_button1"));
r->up_button = GTK_WIDGET(gtk_builder_get_object (builder, "up_button1"));
r->down_button = GTK_WIDGET(gtk_builder_get_object (builder, "down_button1"));
r->size_button = GTK_WIDGET(gtk_builder_get_object (builder, "size_button1"));
r->options = options;
r->view = view;
r->available_list = SCM_EOL;
r->contents_selected = 0;
r->contents_list = SCM_EOL;
r->odb = gnc_option_db_new(r->options);
gnc_options_dialog_build_contents(r->optwin, r->odb);
gtk_notebook_append_page(GTK_NOTEBOOK(gnc_options_dialog_notebook
(r->optwin)),
editor,
gtk_label_new(_("Contents")));
scm_gc_protect_object(r->options);
scm_gc_protect_object(r->view);
scm_gc_protect_object(r->available_list);
scm_gc_protect_object(r->contents_list);
/* Build the 'available' view */
store = gtk_list_store_new (NUM_AVAILABLE_COLS, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_view_set_model(r->available, GTK_TREE_MODEL(store));
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), AVAILABLE_COL_NAME, GTK_SORT_ASCENDING);
g_object_unref(store);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("", renderer,
"text", AVAILABLE_COL_NAME,
NULL);
gtk_tree_view_append_column(r->available, column);
/* use the selection cb to update buttons */
selection = gtk_tree_view_get_selection(r->available);
g_signal_connect(selection, "changed",
G_CALLBACK(gnc_column_view_update_buttons_cb), r);
/* Build the 'contents' view */
store = gtk_list_store_new (NUM_CONTENTS_COLS, G_TYPE_STRING, G_TYPE_INT,
G_TYPE_INT, G_TYPE_INT);
gtk_tree_view_set_model(r->contents, GTK_TREE_MODEL(store));
g_object_unref(store);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Report"), renderer,
"text", CONTENTS_COL_NAME,
NULL);
gtk_tree_view_append_column(r->contents, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Rows"), renderer,
"text", CONTENTS_COL_REPORT_ROWS,
NULL);
gtk_tree_view_append_column(r->contents, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Cols"), renderer,
"text", CONTENTS_COL_REPORT_COLS,
NULL);
gtk_tree_view_append_column(r->contents, column);
/* use the selection cb to update buttons */
selection = gtk_tree_view_get_selection(r->contents);
g_signal_connect(selection, "changed",
G_CALLBACK(gnc_column_view_update_buttons_cb), r);
update_available_lists(r);
update_contents_lists(r);
gnc_options_dialog_set_apply_cb(r->optwin,
gnc_column_view_edit_apply_cb, r);
gnc_options_dialog_set_close_cb(r->optwin,
gnc_column_view_edit_close_cb, r);
gtk_widget_show(gnc_options_dialog_widget(r->optwin));
gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, r);
g_object_unref(G_OBJECT(builder));
return gnc_options_dialog_widget(r->optwin);
}
}
void
gnc_column_view_edit_add_cb(GtkButton * button, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
SCM make_report = scm_c_eval_string("gnc:make-report");
SCM mark_report = scm_c_eval_string("gnc:report-set-needs-save?!");
SCM template_name;
SCM new_report;
SCM newlist = SCM_EOL;
SCM oldlist = r->contents_list;
int count;
int oldlength, id;
gchar *guid_str;
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(r->available));
GtkTreeModel *model;
GtkTreeIter iter;
/* make sure there is a selected entry */
if (gtk_tree_selection_get_selected(selection, &model, &iter))
gtk_tree_model_get(model, &iter,
AVAILABLE_COL_GUID, &guid_str, -1);
else
return;
if (scm_is_list(r->available_list))
{
template_name = scm_from_utf8_string(guid_str);
new_report = scm_call_1(make_report, template_name);
id = scm_to_int(new_report);
scm_call_2(mark_report, gnc_report_find(id), SCM_BOOL_T);
oldlength = scm_ilength(r->contents_list);
if (oldlength > r->contents_selected)
{
for (count = 0; count < r->contents_selected; count++)
{
newlist = scm_cons(SCM_CAR(oldlist), newlist);
oldlist = SCM_CDR(oldlist);
}
newlist = scm_append
(scm_list_n (scm_reverse
(scm_cons
(scm_list_4 (new_report,
scm_from_int (1),
scm_from_int (1),
SCM_BOOL_F),
newlist)),
oldlist,
SCM_UNDEFINED));
}
else
{
newlist = scm_append
(scm_list_n (oldlist,
scm_list_1
(scm_list_4 (new_report,
scm_from_int (1),
scm_from_int (1),
SCM_BOOL_F)),
SCM_UNDEFINED));
r->contents_selected = oldlength;
}
scm_gc_unprotect_object(r->contents_list);
r->contents_list = newlist;
scm_gc_protect_object(r->contents_list);
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
gnc_options_dialog_changed (r->optwin);
}
g_free (guid_str);
update_contents_lists(r);
}
void
gnc_column_view_edit_remove_cb(GtkButton * button, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
SCM newlist = SCM_EOL;
SCM oldlist = r->contents_list;
int count;
int oldlength;
if (scm_is_list(r->contents_list))
{
oldlength = scm_ilength(r->contents_list);
if (oldlength > r->contents_selected)
{
for (count = 0; count < r->contents_selected; count++)
{
newlist = scm_cons(SCM_CAR(oldlist), newlist);
oldlist = SCM_CDR(oldlist);
}
if (count <= oldlength)
{
newlist = scm_append(scm_list_n (scm_reverse(newlist), SCM_CDR(oldlist), SCM_UNDEFINED));
}
}
if (r->contents_selected > 0 && oldlength == r->contents_selected + 1)
{
r->contents_selected --;
}
scm_gc_unprotect_object(r->contents_list);
r->contents_list = newlist;
scm_gc_protect_object(r->contents_list);
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
gnc_options_dialog_changed (r->optwin);
}
update_contents_lists(r);
}
void
gnc_edit_column_view_move_up_cb(GtkButton * button, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
SCM oldlist = r->contents_list;
SCM newlist = SCM_EOL;
SCM temp;
int oldlength;
int count;
oldlength = scm_ilength(r->contents_list);
if ((r->contents_selected > 0) && (oldlength > r->contents_selected))
{
for (count = 1; count < r->contents_selected; count++)
{
newlist = scm_cons(SCM_CAR(oldlist), newlist);
oldlist = SCM_CDR(oldlist);
}
temp = SCM_CAR(oldlist);
oldlist = SCM_CDR(oldlist);
newlist = scm_cons(temp, scm_cons(SCM_CAR(oldlist), newlist));
newlist = scm_append(scm_list_n (scm_reverse(newlist), SCM_CDR(oldlist), SCM_UNDEFINED));
scm_gc_unprotect_object(r->contents_list);
r->contents_list = newlist;
scm_gc_protect_object(r->contents_list);
r->contents_selected = r->contents_selected - 1;
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
gnc_options_dialog_changed (r->optwin);
update_contents_lists(r);
}
}
void
gnc_edit_column_view_move_down_cb(GtkButton * button, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
SCM oldlist = r->contents_list;
SCM newlist = SCM_EOL;
SCM temp;
int oldlength;
int count;
oldlength = scm_ilength(r->contents_list);
if (oldlength > (r->contents_selected + 1))
{
for (count = 0; count < r->contents_selected; count++)
{
newlist = scm_cons(SCM_CAR(oldlist), newlist);
oldlist = SCM_CDR(oldlist);
}
temp = SCM_CAR(oldlist);
oldlist = SCM_CDR(oldlist);
newlist = scm_cons(temp, scm_cons(SCM_CAR(oldlist), newlist));
newlist = scm_append(scm_list_n (scm_reverse(newlist), SCM_CDR(oldlist), SCM_UNDEFINED));
scm_gc_unprotect_object(r->contents_list);
r->contents_list = newlist;
scm_gc_protect_object(r->contents_list);
r->contents_selected = r->contents_selected + 1;
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
gnc_options_dialog_changed (r->optwin);
update_contents_lists(r);
}
}
void
gnc_column_view_edit_size_cb(GtkButton * button, gpointer user_data)
{
gnc_column_view_edit * r = user_data;
GtkWidget * rowspin;
GtkWidget * colspin;
GtkWidget * dlg;
GtkBuilder *builder;
SCM current;
int length;
int dlg_ret;
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-report.glade", "col_adjustment");
gnc_builder_add_from_file (builder, "dialog-report.glade", "row_adjustment");
gnc_builder_add_from_file (builder, "dialog-report.glade", "edit_report_size");
dlg = GTK_WIDGET(gtk_builder_get_object (builder, "edit_report_size"));
gtk_window_set_transient_for (GTK_WINDOW(dlg),
GTK_WINDOW(gtk_widget_get_toplevel (GTK_WIDGET(button))));
/* get the spinner widgets */
rowspin = GTK_WIDGET(gtk_builder_get_object (builder, "row_spin"));
colspin = GTK_WIDGET(gtk_builder_get_object (builder, "col_spin"));
length = scm_ilength(r->contents_list);
if (length > r->contents_selected)
{
current = scm_list_ref(r->contents_list,
scm_from_int (r->contents_selected));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(colspin),
(float)scm_to_int(SCM_CADR(current)));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(rowspin),
(float)scm_to_int(SCM_CADDR(current)));
dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg));
gtk_widget_hide(dlg);
if (dlg_ret == GTK_RESPONSE_OK)
{
current = scm_list_4 (SCM_CAR (current),
scm_from_int (gtk_spin_button_get_value_as_int
(GTK_SPIN_BUTTON(colspin))),
scm_from_int (gtk_spin_button_get_value_as_int
(GTK_SPIN_BUTTON(rowspin))),
SCM_BOOL_F);
scm_gc_unprotect_object(r->contents_list);
r->contents_list = scm_list_set_x(r->contents_list,
scm_from_int (r->contents_selected),
current);
scm_gc_protect_object(r->contents_list);
gnc_options_dialog_changed (r->optwin);
update_contents_lists(r);
}
g_object_unref(G_OBJECT(builder));
gtk_widget_destroy(dlg);
}
}

View File

@ -0,0 +1,565 @@
/********************************************************************
* dialog-report-column-view.c -- editor for column view of reports *
* Copyright (C) 2001 Bill Gribble <grib@billgribble.com> *
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
* *
* 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 <libguile.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <algorithm>
extern "C"
{
#include <config.h>
#include "swig-runtime.h"
#include "dialog-utils.h"
#include "window-report.h"
#include "guile-mappings.h"
#include "gnc-guile-utils.h"
#include "gnc-ui.h"
}
#include "dialog-report-column-view.hpp"
#include <dialog-options.hpp>
#include <gnc-report.h>
#include <gnc-optiondb-impl.hpp>
enum available_cols
{
AVAILABLE_COL_NAME = 0,
AVAILABLE_COL_GUID,
NUM_AVAILABLE_COLS
};
enum contents_cols
{
CONTENTS_COL_NAME = 0,
CONTENTS_COL_ROW,
CONTENTS_COL_REPORT_ROWS,
CONTENTS_COL_REPORT_COLS,
NUM_CONTENTS_COLS
};
using StrVec = std::vector<std::string>;
struct gncp_column_view_edit
{
GncOptionsDialog * optwin;
GtkTreeView * available;
GtkTreeView * contents;
SCM view;
GncOptionDB * odb;
StrVec available_list;
GncOptionReportPlacementVec contents_list;
int contents_selected;
GtkWidget *add_button;
GtkWidget *remove_button;
GtkWidget *up_button;
GtkWidget *down_button;
GtkWidget *size_button;
};
/* Even though these aren't external nor used outside this file they must be
* declared this way to ensure that they're in the library's symbol table and
* aren't mangled. That's so that dlsym is able to find them when GtkBuilder
* needs to connect the signals to them.
*/
extern "C"
{
void gnc_column_view_edit_add_cb(GtkButton * button, gpointer user_data);
void gnc_column_view_edit_remove_cb(GtkButton * button, gpointer user_data);
void gnc_edit_column_view_move_up_cb(GtkButton * button, gpointer user_data);
void gnc_edit_column_view_move_down_cb(GtkButton * button, gpointer user_data);
void gnc_column_view_edit_size_cb(GtkButton * button, gpointer user_data);
}
static void
gnc_column_view_set_option(GncOptionDB* odb, const char* section,
const char* name, const GncOptionReportPlacementVec& new_value)
{
odb->find_option(section, name)->set_value(new_value);
}
static void
gnc_column_view_edit_destroy(gnc_column_view_edit * view)
{
delete view->optwin;
scm_gc_unprotect_object(view->view);
gnc_option_db_destroy(view->odb);
g_free(view);
}
static StrVec
get_available_reports ()
{
StrVec sv;
auto scm_list{scm_call_0(scm_c_eval_string("gnc:all-report-template-guids"))};
for (auto next{scm_list}; !scm_is_null(next); next = scm_cdr(next))
sv.emplace_back(scm_to_utf8_string(scm_car(next)));
return sv;
}
static void
update_available_lists(gnc_column_view_edit * view)
{
SCM template_menu_name = scm_c_eval_string("gnc:report-template-menu-name/report-guid");
std::string selection;
GtkTreeIter iter;
/* Update the list of available reports (left selection box). */
auto tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view->available));
auto model = gtk_tree_view_get_model (GTK_TREE_VIEW(view->available));
if (gtk_tree_selection_get_selected(tree_selection, &model, &iter))
{
gchar *guid_str;
gtk_tree_model_get(model, &iter,
AVAILABLE_COL_GUID, &guid_str,
-1);
selection = std::string(guid_str);
g_free (guid_str);
}
view->available_list = get_available_reports();
auto store = GTK_LIST_STORE(model);
gtk_list_store_clear(store);
for (auto guid : view->available_list)
{
auto rpt_guid{scm_from_utf8_string(guid.c_str())};
auto name =
gnc_scm_to_utf8_string (scm_call_2(template_menu_name, rpt_guid, SCM_BOOL_F));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
AVAILABLE_COL_NAME, _(name),
AVAILABLE_COL_GUID, guid.c_str(),
-1);
if (guid == selection)
gtk_tree_selection_select_iter (tree_selection, &iter);
g_free (name);
}
}
static void
update_contents_lists(gnc_column_view_edit * view)
{
SCM report_menu_name = scm_c_eval_string("gnc:report-menu-name");
auto contents{view->odb->find_option("__general", "report-list")->get_value<GncOptionReportPlacementVec>()};
GtkTreeIter iter;
GncOptionReportPlacement selection{0, 0, 0};
/* Update the list of selected reports (right selection box). */
auto tree_selection = gtk_tree_view_get_selection(view->contents);
view->contents_list = contents;
if (!contents.empty() && static_cast<size_t>(view->contents_selected) < contents.size())
selection = contents[view->contents_selected];
auto store = GTK_LIST_STORE(gtk_tree_view_get_model(view->contents));
gtk_list_store_clear(store);
for (size_t i = 0; i < contents.size(); ++i)
{
auto [id, wide, high] = contents[i];
auto this_report = gnc_report_find(id);
auto name = gnc_scm_to_utf8_string (scm_call_1(report_menu_name, this_report));
gtk_list_store_append(store, &iter);
gtk_list_store_set
(store, &iter,
CONTENTS_COL_NAME, _(name),
CONTENTS_COL_ROW, i,
CONTENTS_COL_REPORT_COLS, wide,
CONTENTS_COL_REPORT_ROWS, high,
-1);
if (id == std::get<0>(selection))
gtk_tree_selection_select_iter (tree_selection, &iter);
g_free (name);
}
}
static void
gnc_column_view_update_buttons_cb (GtkTreeSelection *selection,
gnc_column_view_edit *r)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean is_selected;
/* compare treeviews to establish which selected treeview */
if (gtk_tree_selection_get_tree_view (selection) == r->available)
{
/* available treeview */
is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_widget_set_sensitive (r->add_button, is_selected);
return;
}
/* contents treeview */
is_selected = gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_widget_set_sensitive (r->size_button, is_selected);
gtk_widget_set_sensitive (r->remove_button, is_selected);
if (is_selected)
{
int len = r->contents_list.size();
gtk_tree_model_get (model, &iter,
CONTENTS_COL_ROW, &r->contents_selected, -1);
if (len > 1)
{
gtk_widget_set_sensitive (r->up_button, TRUE);
gtk_widget_set_sensitive (r->down_button, TRUE);
if (r->contents_selected == len -1)
gtk_widget_set_sensitive (r->down_button, FALSE);
if (r->contents_selected == 0)
gtk_widget_set_sensitive (r->up_button, FALSE);
}
}
else
{
gtk_widget_set_sensitive (r->up_button, FALSE);
gtk_widget_set_sensitive (r->down_button, FALSE);
}
}
static void
gnc_column_view_edit_apply_cb(GncOptionsDialog *dlg, gpointer user_data)
{
SCM dirty_report = scm_c_eval_string("gnc:report-set-dirty?!");
auto win{static_cast<gnc_column_view_edit*>(user_data)};
if (!win) return;
auto results = gnc_option_db_commit (dlg->get_option_db());
for (auto iter = results; iter; iter = iter->next)
{
GtkWidget *dialog =
gtk_message_dialog_new(GTK_WINDOW(dlg->get_widget()),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free (iter->data);
}
g_list_free (results);
scm_call_2(dirty_report, win->view, SCM_BOOL_T);
}
static void
gnc_column_view_edit_close_cb(GncOptionsDialog *win, gpointer user_data)
{
auto r{static_cast<gnc_column_view_edit*>(user_data)};
SCM set_editor = scm_c_eval_string("gnc:report-set-editor-widget!");
scm_call_2(set_editor, r->view, SCM_BOOL_F);
gnc_column_view_edit_destroy(r);
}
/********************************************************************
* gnc_column_view_edit_options
* create the editor.
********************************************************************/
GtkWidget *
gnc_column_view_edit_options(GncOptionDB* odb, SCM view)
{
SCM get_editor = scm_c_eval_string("gnc:report-editor-widget");
SCM ptr;
GtkWidget * editor;
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
ptr = scm_call_1(get_editor, view);
if (ptr != SCM_BOOL_F)
{
#define FUNC_NAME "gtk_window_present"
auto w{static_cast<GtkWindow*>(SWIG_MustGetPtr(ptr, SWIG_TypeQuery("_p_GtkWidget"), 1, 0))};
gtk_window_present(w);
#undef FUNC_NAME
return nullptr;
}
else
{
gnc_column_view_edit * r = g_new0(gnc_column_view_edit, 1);
GtkBuilder *builder;
r->optwin = new GncOptionsDialog(nullptr, GTK_WINDOW(gnc_ui_get_main_window (nullptr)));
/* Hide the generic dialog page list. */
gtk_widget_hide(r->optwin->get_page_list());
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-report.glade", "view_contents_table");
editor = GTK_WIDGET(gtk_builder_get_object (builder, "view_contents_table"));
r->available = GTK_TREE_VIEW (gtk_builder_get_object (builder, "available_view"));
r->contents = GTK_TREE_VIEW (gtk_builder_get_object (builder, "contents_view"));
r->add_button = GTK_WIDGET(gtk_builder_get_object (builder, "add_button1"));
r->remove_button = GTK_WIDGET(gtk_builder_get_object (builder, "remove_button1"));
r->up_button = GTK_WIDGET(gtk_builder_get_object (builder, "up_button1"));
r->down_button = GTK_WIDGET(gtk_builder_get_object (builder, "down_button1"));
r->size_button = GTK_WIDGET(gtk_builder_get_object (builder, "size_button1"));
r->view = view;
r->available_list.clear();
r->contents_selected = 0;
r->contents_list.clear();
r->odb = odb;
r->optwin->build_contents(r->odb);
gtk_notebook_append_page(GTK_NOTEBOOK(r->optwin->get_notebook()),
editor,
gtk_label_new(_("Contents")));
scm_gc_protect_object(r->view);
/* Build the 'available' view */
store = gtk_list_store_new (NUM_AVAILABLE_COLS, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_view_set_model(r->available, GTK_TREE_MODEL(store));
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), AVAILABLE_COL_NAME, GTK_SORT_ASCENDING);
g_object_unref(store);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("", renderer,
"text", AVAILABLE_COL_NAME,
nullptr);
gtk_tree_view_append_column(r->available, column);
/* use the selection cb to update buttons */
selection = gtk_tree_view_get_selection(r->available);
g_signal_connect(selection, "changed",
G_CALLBACK(gnc_column_view_update_buttons_cb), r);
/* Build the 'contents' view */
store = gtk_list_store_new (NUM_CONTENTS_COLS, G_TYPE_STRING, G_TYPE_INT,
G_TYPE_INT, G_TYPE_INT);
gtk_tree_view_set_model(r->contents, GTK_TREE_MODEL(store));
g_object_unref(store);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Report"), renderer,
"text", CONTENTS_COL_NAME,
nullptr);
gtk_tree_view_append_column(r->contents, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Rows"), renderer,
"text", CONTENTS_COL_REPORT_ROWS,
nullptr);
gtk_tree_view_append_column(r->contents, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Cols"), renderer,
"text", CONTENTS_COL_REPORT_COLS,
nullptr);
gtk_tree_view_append_column(r->contents, column);
/* use the selection cb to update buttons */
selection = gtk_tree_view_get_selection(r->contents);
g_signal_connect(selection, "changed",
G_CALLBACK(gnc_column_view_update_buttons_cb), r);
update_available_lists(r);
update_contents_lists(r);
r->optwin->set_apply_cb(gnc_column_view_edit_apply_cb, r);
r->optwin->set_close_cb(gnc_column_view_edit_close_cb, r);
gtk_widget_show(r->optwin->get_widget());
gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, r);
g_object_unref(G_OBJECT(builder));
return r->optwin->get_widget();
}
}
void
gnc_column_view_edit_add_cb(GtkButton * button, gpointer user_data)
{
auto r = static_cast<gnc_column_view_edit *>(user_data);
SCM make_report = scm_c_eval_string("gnc:make-report");
SCM mark_report = scm_c_eval_string("gnc:report-set-needs-save?!");
gchar *guid_str;
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(r->available));
GtkTreeModel *model;
GtkTreeIter iter;
/* make sure there is a selected entry */
if (gtk_tree_selection_get_selected(selection, &model, &iter))
gtk_tree_model_get(model, &iter,
AVAILABLE_COL_GUID, &guid_str, -1);
else
return;
auto template_name = scm_from_utf8_string(guid_str);
auto new_report = scm_call_1(make_report, template_name);
auto id = scm_to_int(new_report);
scm_call_2(mark_report, gnc_report_find(id), SCM_BOOL_T);
auto oldlength = r->contents_list.size();
GncOptionReportPlacement new_rpt_placement{id, 1, 1};
if (oldlength > static_cast<size_t>(r->contents_selected))
r->contents_list.emplace(r->contents_list.begin() + r->contents_selected + 1, id, 1, 1);
else
{
r->contents_list.emplace_back(id, 1, 1);
r->contents_selected = oldlength;
}
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
g_free (guid_str);
r->optwin->changed();
update_contents_lists(r);
}
void
gnc_column_view_edit_remove_cb(GtkButton * button, gpointer user_data)
{
auto r = static_cast<gnc_column_view_edit *>(user_data);
r->contents_list.erase(r->contents_list.begin() + r->contents_selected);
if (r->contents_selected)
--r->contents_selected;
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
r->optwin->changed();
update_contents_lists(r);
}
static void
move_selected_item(gnc_column_view_edit* r, int increment)
{
if (!r || !increment)
return;
auto cur_sel{r->contents_list.begin() + r->contents_selected};
auto move_to{cur_sel + increment};
if (increment > 0)
std::reverse(cur_sel, move_to + 1);
else
std::reverse(move_to, cur_sel + 1);
r->contents_selected += increment;
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
r->optwin->changed();
update_contents_lists(r);
}
void
gnc_edit_column_view_move_up_cb(GtkButton * button, gpointer user_data)
{
auto r = static_cast<gnc_column_view_edit *>(user_data);
move_selected_item(r, -1);
}
void
gnc_edit_column_view_move_down_cb(GtkButton * button, gpointer user_data)
{
auto r = static_cast<gnc_column_view_edit *>(user_data);
move_selected_item(r, 1);
}
void
gnc_column_view_edit_size_cb(GtkButton * button, gpointer user_data)
{
auto r = static_cast<gnc_column_view_edit *>(user_data);
GtkWidget * rowspin;
GtkWidget * colspin;
GtkWidget * dlg;
GtkBuilder *builder;
SCM current;
int length;
int dlg_ret;
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-report.glade", "col_adjustment");
gnc_builder_add_from_file (builder, "dialog-report.glade", "row_adjustment");
gnc_builder_add_from_file (builder, "dialog-report.glade", "edit_report_size");
dlg = GTK_WIDGET(gtk_builder_get_object (builder, "edit_report_size"));
gtk_window_set_transient_for (GTK_WINDOW(dlg),
GTK_WINDOW(gtk_widget_get_toplevel (GTK_WIDGET(button))));
/* get the spinner widgets */
rowspin = GTK_WIDGET(gtk_builder_get_object (builder, "row_spin"));
colspin = GTK_WIDGET(gtk_builder_get_object (builder, "col_spin"));
if (r->contents_list.size() > static_cast<size_t>(r->contents_selected))
{
auto [id, wide, high] = r->contents_list[r->contents_selected];
gtk_spin_button_set_value(GTK_SPIN_BUTTON(colspin),
static_cast<float>(wide));
gtk_spin_button_set_value(GTK_SPIN_BUTTON(rowspin),
static_cast<float>(high));
dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg));
gtk_widget_hide(dlg);
if (dlg_ret == GTK_RESPONSE_OK)
{
std::get<1>(r->contents_list[r->contents_selected]) =
gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(colspin));
std::get<2>(r->contents_list[r->contents_selected]) =
gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rowspin));
gnc_column_view_set_option(r->odb, "__general", "report-list",
r->contents_list);
r->optwin->changed();
update_contents_lists(r);
}
g_object_unref(G_OBJECT(builder));
gtk_widget_destroy(dlg);
}
}

View File

@ -24,10 +24,12 @@
#define GNC_DIALOG_COLUMN_VIEW_H
#include <libguile.h>
extern "C"
{
#include <gtk/gtk.h>
typedef struct gncp_column_view_edit gnc_column_view_edit;
GtkWidget * gnc_column_view_edit_options(SCM options, SCM view);
GtkWidget * gnc_column_view_edit_options(GncOptionDB* odb, SCM view);
}
#endif

View File

@ -22,21 +22,27 @@
* Boston, MA 02110-1301, USA gnu@gnu.org *
********************************************************************/
#include <config.h>
#include <libguile.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
extern "C"
{
#include <config.h>
#include "dialog-report-style-sheet.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "gnc-component-manager.h"
#include "gnc-session.h"
#include "gnc-gtk-utils.h"
#include "gnc-gnome-utils.h"
#include "gnc-guile-utils.h"
#include "gnc-report.h"
#include "gnc-ui.h"
#include <guile-mappings.h>
}
#include "gnc-report.h"
#include <dialog-options.hpp>
#include <gnc-optiondb.h>
#define DIALOG_STYLE_SHEETS_CM_CLASS "style-sheets-dialog"
#define GNC_PREFS_GROUP "dialogs.style-sheet"
@ -55,10 +61,10 @@ struct _stylesheetdialog
typedef struct ss_info
{
GNCOptionWin * odialog;
GNCOptionDB * odb;
SCM stylesheet;
GtkTreeRowReference * row_ref;
GncOptionsDialog * odialog;
GncOptionDB * odb;
SCM stylesheet;
GtkTreeRowReference *row_ref;
} ss_info;
enum
@ -68,13 +74,14 @@ enum
COLUMN_DIALOG,
N_COLUMNS
};
extern "C" // So that gtk_builder_connect_full can find them.
{
void gnc_style_sheet_select_dialog_new_cb (GtkWidget *widget, gpointer user_data);
void gnc_style_sheet_select_dialog_edit_cb (GtkWidget *widget, gpointer user_data);
void gnc_style_sheet_select_dialog_delete_cb (GtkWidget *widget, gpointer user_data);
void gnc_style_sheet_select_dialog_close_cb (GtkWidget *widget, gpointer user_data);
void gnc_style_sheet_select_dialog_destroy_cb (GtkWidget *widget, gpointer user_data);
}
/************************************************************
* Style Sheet Edit Dialog (I.E. an options dialog) *
************************************************************/
@ -82,9 +89,9 @@ void gnc_style_sheet_select_dialog_destroy_cb (GtkWidget *widget, gpointer user_
static void
dirty_same_stylesheet (gpointer key, gpointer val, gpointer data)
{
SCM dirty_ss = data;
auto dirty_ss{static_cast<SCM>(data)};
SCM rep_ss = NULL;
SCM report = val;
auto report{static_cast<SCM>(val)};
SCM func = NULL;
func = scm_c_eval_string ("gnc:report-stylesheet");
@ -103,7 +110,7 @@ dirty_same_stylesheet (gpointer key, gpointer val, gpointer data)
}
static void
gnc_style_sheet_options_apply_cb (GNCOptionWin * propertybox,
gnc_style_sheet_options_apply_cb (GncOptionsDialog * propertybox,
gpointer user_data)
{
ss_info * ssi = (ss_info *)user_data;
@ -118,30 +125,30 @@ gnc_style_sheet_options_apply_cb (GNCOptionWin * propertybox,
results = gnc_option_db_commit (ssi->odb);
for (iter = results; iter; iter = iter->next)
{
GtkWidget *dialog = gtk_message_dialog_new (NULL,
0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
gtk_dialog_run (GTK_DIALOG(dialog));
gtk_widget_destroy (dialog);
GtkWidget *dialog = gtk_message_dialog_new(nullptr,
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free (iter->data);
}
g_list_free (results);
}
static void
gnc_style_sheet_options_close_cb (GNCOptionWin * propertybox,
gnc_style_sheet_options_close_cb (GncOptionsDialog *opt_dialog,
gpointer user_data)
{
ss_info * ssi = user_data;
GtkTreeIter iter;
auto ssi{static_cast<ss_info*>(user_data)};
if (gtk_tree_row_reference_valid (ssi->row_ref))
{
StyleSheetDialog * ss = gnc_style_sheet_dialog;
GtkTreePath *path = gtk_tree_row_reference_get_path (ssi->row_ref);
auto ss = gnc_style_sheet_dialog;
auto path = gtk_tree_row_reference_get_path (ssi->row_ref);
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL(ss->list_store), &iter, path))
gtk_list_store_set (ss->list_store, &iter,
COLUMN_DIALOG, NULL,
@ -149,7 +156,7 @@ gnc_style_sheet_options_close_cb (GNCOptionWin * propertybox,
gtk_tree_path_free (path);
}
gtk_tree_row_reference_free (ssi->row_ref);
gnc_options_dialog_destroy (ssi->odialog);
delete ssi->odialog;
gnc_option_db_destroy (ssi->odb);
scm_gc_unprotect_object (ssi->stylesheet);
g_free (ssi);
@ -163,34 +170,26 @@ 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;
GtkWindow * parent = GTK_WINDOW(gtk_widget_get_toplevel (GTK_WIDGET(ss->list_view)));
title = g_strdup_printf (_("HTML Style Sheet Properties: %s"), name);
ssinfo->odialog = gnc_options_dialog_new (title, parent);
ssinfo->odb = gnc_option_db_new (scm_options);
title = g_strdup_printf(_("HTML Style Sheet Properties: %s"), name);
ssinfo->odialog = new GncOptionsDialog(title, parent);
ssinfo->odb = gnc_get_optiondb_from_dispatcher(scm_dispatch);
ssinfo->stylesheet = sheet_info;
ssinfo->row_ref = row_ref;
g_free (title);
scm_gc_protect_object (ssinfo->stylesheet);
g_object_ref (gnc_options_dialog_widget (ssinfo->odialog));
g_object_ref (ssinfo->odialog->get_widget());
gnc_options_dialog_build_contents (ssinfo->odialog,
ssinfo->odb);
ssinfo->odialog->build_contents(ssinfo->odb);
gnc_options_dialog_set_style_sheet_options_help_cb (ssinfo->odialog);
gnc_options_dialog_set_apply_cb (ssinfo->odialog,
gnc_style_sheet_options_apply_cb,
ssinfo);
gnc_options_dialog_set_close_cb (ssinfo->odialog,
gnc_style_sheet_options_close_cb,
ssinfo);
window = gnc_options_dialog_widget (ssinfo->odialog);
ssinfo->odialog->set_apply_cb(gnc_style_sheet_options_apply_cb, ssinfo);
ssinfo->odialog->set_close_cb(gnc_style_sheet_options_close_cb, ssinfo);
auto window = ssinfo->odialog->get_widget();
gtk_window_set_transient_for (GTK_WINDOW(window),
GTK_WINDOW(gnc_style_sheet_dialog->toplevel));
gtk_window_set_destroy_with_parent (GTK_WINDOW(window), TRUE);
@ -260,9 +259,9 @@ gnc_style_sheet_new (StyleSheetDialog * ssd)
if (dialog_retval == GTK_RESPONSE_OK)
{
gint choice = gtk_combo_box_get_active (GTK_COMBO_BOX(template_combo));
const char *template_str = g_list_nth_data (template_names, choice);
const char *name_str = gtk_entry_get_text (GTK_ENTRY(name_entry));
if (name_str && strlen (name_str) == 0)
auto template_str{static_cast<const char *>(g_list_nth_data (template_names, choice))};
const char *name_str = gtk_entry_get_text(GTK_ENTRY(name_entry));
if (name_str && strlen(name_str) == 0)
{
/* If the name is empty, we display an error dialog but
* refuse to create the new style sheet. */
@ -442,8 +441,7 @@ gnc_style_sheet_select_dialog_delete_event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
StyleSheetDialog *ss = (StyleSheetDialog *)user_data;
// this cb allows the window size to be saved on closing with the X
auto ss{static_cast<StyleSheetDialog*>(user_data)};
gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(ss->toplevel));
return FALSE;
}

View File

@ -23,9 +23,14 @@
#ifndef GNC_DIALOG_STYLE_SHEET_H
#define GNC_DIALOG_STYLE_SHEET_H
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct _stylesheetdialog StyleSheetDialog;
void gnc_style_sheet_dialog_open (GtkWindow *parent);
void gnc_style_sheet_dialog_open(GtkWindow *parent);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -49,7 +49,6 @@
#include "gnc-budget.h"
#include "gnc-features.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "gnc-gnome-utils.h"
#include "gnc-gobject-utils.h"
@ -61,7 +60,6 @@
#include "gnc-tree-view-account.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "option-util.h"
#include "gnc-main-window.h"
#include "gnc-component-manager.h"
#include "gnc-state.h"

View File

@ -44,13 +44,13 @@
#include "swig-runtime.h"
#include "libguile.h"
#include <guile-mappings.h>
#include "gnc-plugin-page-register.h"
#include "gnc-plugin-page-report.h"
#include "gnc-budget.h"
#include "gnc-features.h"
#include "dialog-options.h"
#include "dialog-utils.h"
#include "gnc-gnome-utils.h"
#include "misc-gnome-utils.h"
@ -65,7 +65,6 @@
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-window.h"
#include "option-util.h"
#include "gnc-main-window.h"
#include "gnc-component-manager.h"

View File

@ -36,13 +36,15 @@
@author Copyright (C) 2004 Joshua Sled <jsled@asynchronous.org>
@author Copyright (C) 2005 David Hampton <hampton@employees.org>
*/
#include <config.h>
#include <libguile.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <libguile.h>
extern "C"
{
#include <config.h>
#include <sys/stat.h>
#include <errno.h>
@ -63,18 +65,21 @@
#include "gnc-plugin-page-report.h"
#include "gnc-plugin-file-history.h"
#include "gnc-prefs.h"
#include "gnc-report.h"
#include "gnc-session.h"
#include "gnc-ui-util.h"
#include "gnc-ui.h"
#include "gnc-window.h"
#include "option-util.h"
#include "window-report.h"
#include "swig-runtime.h"
#include "guile-mappings.h"
#include "business-options.h"
#include "gnc-icons.h"
#include "print-session.h"
}
#include <memory>
#include <gnc-report.h>
#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
@ -82,13 +87,13 @@ a gnucash- prefix will do. Then just set a log level
with qof_log_set_level().*/
static QofLogModule log_module = GNC_MOD_GUI;
static GObjectClass *parent_class = NULL;
static GObjectClass *parent_class = nullptr;
// A static GHashTable to record the usage count for each printer
// output name. FIXME: Currently this isn't cleaned up at program
// shutdown because there isn't a place to easily insert a finalize()
// function for this. Oh well.
static GHashTable *static_report_printnames = NULL;
static GHashTable *static_report_printnames = nullptr;
// Property-id values.
enum
@ -106,15 +111,15 @@ typedef struct GncPluginPageReportPrivate
/// The report which this Page is satisfying
SCM cur_report;
/// The Option DB for this report.
GNCOptionDB *cur_odb;
SCM option_change_cb_id;
GncOptionDB *cur_odb;
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;
GncOptionDB * initial_odb;
size_t name_change_cb_id;
/* keep a list of edited reports so that we can destroy them when
* the window is closed. */
@ -273,7 +278,7 @@ gnc_plugin_page_report_class_init (GncPluginPageReportClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GncPluginPageClass *gnc_plugin_page_class = GNC_PLUGIN_PAGE_CLASS(klass);
parent_class = g_type_class_peek_parent (klass);
parent_class = static_cast<GObjectClass*>(g_type_class_peek_parent (klass));
object_class->constructor = gnc_plugin_page_report_constructor;
object_class->finalize = gnc_plugin_page_report_finalize;
@ -294,29 +299,19 @@ gnc_plugin_page_report_class_init (GncPluginPageReportClass *klass)
gnc_plugin_page_class->focus_page_function = gnc_plugin_page_report_focus_widget;
// create the "reportId" property
auto paramspec{static_cast<GParamFlags>(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)};
g_object_class_install_property( object_class,
PROP_REPORT_ID,
g_param_spec_int( "report-id",
_("The numeric ID of the report."),
_("The numeric ID of the report."),
-1, G_MAXINT, -1, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE ) );
/* JSLED: report-selected?
plugin_page_signals[ACCOUNT_SELECTED] =
g_signal_new ("account_selected",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GncPluginPageReportClass, account_selected),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
*/
-1, G_MAXINT, -1,
paramspec));
// Also initialize the report name usage count table
if (!static_report_printnames)
static_report_printnames = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
g_str_equal, g_free, nullptr);
}
static void
@ -353,8 +348,8 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
URLType type;
char * id_name;
char * child_name;
char * url_location = NULL;
char * url_label = NULL;
char * url_location = nullptr;
char * url_label = nullptr;
report = GNC_PLUGIN_PAGE_REPORT(page);
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
@ -363,7 +358,7 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
DEBUG( "Load uri id=%d", priv->reportId );
id_name = g_strdup_printf("id=%d", priv->reportId );
child_name = gnc_build_url( URL_TYPE_REPORT, id_name, NULL );
child_name = gnc_build_url( URL_TYPE_REPORT, id_name, nullptr );
type = gnc_html_parse_url( priv->html, child_name, &url_location, &url_label);
DEBUG( "passing id_name=[%s] child_name=[%s] type=[%s], location=[%s], label=[%s]",
id_name, child_name ? child_name : "(null)",
@ -388,8 +383,8 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
gnc_plugin_page_report_set_progressbar( page, FALSE );
// this resets the window for the progressbar to NULL
gnc_window_set_progressbar_window( NULL );
// this resets the window for the progressbar to nullptr
gnc_window_set_progressbar_window( nullptr );
}
/* used to capture Ctrl+Alt+PgUp/Down for tab selection */
@ -443,8 +438,8 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
URLType type;
char * id_name;
char * child_name;
char * url_location = NULL;
char * url_label = NULL;
char * url_location = nullptr;
char * url_label = nullptr;
ENTER("page %p", page);
@ -458,7 +453,7 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
report = GNC_PLUGIN_PAGE_REPORT(page);
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
topLvl = gnc_ui_get_main_window (NULL);
topLvl = gnc_ui_get_main_window (nullptr);
// priv->html = gnc_html_new( topLvl );
priv->html = gnc_html_factory_create_html();
gnc_html_set_parent( priv->html, topLvl );
@ -468,7 +463,7 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
gnc_plugin_page_report_history_destroy_cb,
(gpointer)priv);
priv->container = GTK_CONTAINER(gtk_frame_new(NULL));
priv->container = GTK_CONTAINER(gtk_frame_new(nullptr));
gtk_frame_set_shadow_type(GTK_FRAME(priv->container), GTK_SHADOW_NONE);
// Set the name for this widget so it can be easily manipulated with css
@ -478,7 +473,7 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
gnc_html_get_widget(priv->html));
priv->component_manager_id =
gnc_register_gui_component(WINDOW_REPORT_CM_CLASS, NULL,
gnc_register_gui_component(WINDOW_REPORT_CM_CLASS, nullptr,
close_handler, page);
gnc_gui_component_set_session(priv->component_manager_id,
gnc_get_current_session());
@ -489,7 +484,7 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
/* We need to call the load call back so the report appears to have been run
so it will get saved properly if the report is not realized in session */
id_name = g_strdup_printf("id=%d", priv->reportId );
child_name = gnc_build_url( URL_TYPE_REPORT, id_name, NULL );
child_name = gnc_build_url( URL_TYPE_REPORT, id_name, nullptr );
type = gnc_html_parse_url( priv->html, child_name, &url_location, &url_label);
gnc_plugin_page_report_load_cb (priv->html, type, id_name, url_label, report);
@ -503,7 +498,7 @@ gnc_plugin_page_report_create_widget( GncPluginPage *page )
g_signal_connect (G_OBJECT(page), "inserted",
G_CALLBACK(gnc_plugin_page_inserted_cb),
NULL);
nullptr);
// used to capture Ctrl+Alt+PgUp/Down for tab selection
webview = gnc_html_get_webview (priv->html);
@ -556,9 +551,9 @@ 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, NULL );
g_object_get( ppage, "report-id", &report_id, nullptr );
PINFO("report-id: %d\n", report_id);
@ -593,7 +588,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;
@ -649,20 +643,19 @@ 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 = gnc_option_db_new(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,
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 != NULL))
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 = NULL;
priv->cur_odb->unregister_callback(priv->option_change_cb_id);
priv->option_change_cb_id = 0;
priv->cur_odb = nullptr;
}
if (priv->cur_report != SCM_BOOL_F)
@ -670,11 +663,11 @@ 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 = gnc_option_db_new(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,
gnc_plugin_page_report_option_change_cb,
report, NULL, NULL);
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)))
{
@ -731,8 +724,9 @@ gnc_plugin_page_report_option_change_cb(gpointer data)
/* Update the page (i.e. the notebook tab and window title) */
old_name = gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(report));
new_name = gnc_option_db_lookup_string_option(priv->cur_odb, "General",
"Report name", NULL);
new_name = g_strdup(gnc_option_db_lookup_string_value(priv->cur_odb,
"General",
"Report name"));
if (strcmp(old_name, new_name) != 0)
{
/* Bug 727130, 760711 - remove only the non-printable
@ -760,8 +754,8 @@ gnc_plugin_page_report_option_change_cb(gpointer data)
gnc_plugin_page_report_set_progressbar( page, FALSE );
// this resets the window for the progressbar to NULL
gnc_window_set_progressbar_window( NULL );
// this resets the window for the progressbar to nullptr
gnc_window_set_progressbar_window( nullptr );
priv->reloading = FALSE;
}
@ -801,7 +795,7 @@ gnc_plugin_page_report_refresh(gpointer data)
{
// FIXME?
DEBUG( "report-refresh called" );
// something like ... gnc_plugin_page_report_redraw( NULL, (GncPluginPageReportPrivate*)data );
// something like ... gnc_plugin_page_report_redraw( nullptr, (GncPluginPageReportPrivate*)data );
return;
}
@ -861,8 +855,8 @@ gnc_plugin_page_report_save_page (GncPluginPage *plugin_page,
gchar *text, *key_name;
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REPORT(plugin_page));
g_return_if_fail (key_file != NULL);
g_return_if_fail (group_name != NULL);
g_return_if_fail (key_file != nullptr);
g_return_if_fail (group_name != nullptr);
ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
group_name);
@ -935,14 +929,14 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
GncPluginPage *page;
gchar **keys;
gsize i, num_keys;
GError *error = NULL;
GError *error = nullptr;
gchar *option_string;
gint report_id;
SCM scm_id, final_id = SCM_BOOL_F;
SCM report;
g_return_val_if_fail(key_file, NULL);
g_return_val_if_fail(group_name, NULL);
g_return_val_if_fail(key_file, nullptr);
g_return_val_if_fail(group_name, nullptr);
ENTER("key_file %p, group_name %s", key_file, group_name);
keys = g_key_file_get_keys(key_file, group_name, &num_keys, &error);
@ -952,7 +946,7 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
group_name, error->message);
g_error_free(error);
LEAVE("no keys");
return NULL;
return nullptr;
}
for (i = 0; i < num_keys; i++)
@ -968,7 +962,7 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
g_error_free(error);
g_strfreev (keys);
LEAVE("bad value");
return NULL;
return nullptr;
}
scm_id = scm_eval_string(scm_from_utf8_string(option_string));
g_free(option_string);
@ -977,7 +971,7 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
{
DEBUG("report id not an integer for key %s", keys[i]);
g_strfreev (keys);
return NULL;
return nullptr;
}
if (final_id == SCM_BOOL_F)
@ -993,7 +987,7 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
if (final_id == SCM_BOOL_F)
{
LEAVE("report not specified");
return NULL;
return nullptr;
}
report_id = scm_to_int(final_id);
@ -1001,7 +995,7 @@ gnc_plugin_page_report_recreate_page (GtkWidget *window,
if (!report)
{
LEAVE("report doesn't exist");
return NULL;
return nullptr;
}
page = gnc_plugin_page_report_new( report_id );
@ -1028,25 +1022,30 @@ gnc_plugin_page_report_name_changed (GncPluginPage *page, const gchar *name)
const gchar *old_name;
g_return_if_fail(GNC_IS_PLUGIN_PAGE_REPORT(page));
g_return_if_fail(name != NULL);
g_return_if_fail(name != nullptr);
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_option(priv->cur_odb, "General",
"Report name", NULL);
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_option(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);
@ -1100,10 +1099,8 @@ gnc_plugin_page_report_destroy(GncPluginPageReportPrivate * priv)
scm_call_2(set_editor, SCM_CAR(edited), SCM_BOOL_F);
if (editor != SCM_BOOL_F)
{
GtkWidget *w = NULL;
#define FUNC_NAME "gtk_widget_destroy"
w = SWIG_MustGetPtr(editor,
SWIG_TypeQuery("_p_GtkWidget"), 1, 0);
auto w{static_cast<GtkWidget*>(SWIG_MustGetPtr(editor, SWIG_TypeQuery("_p_GtkWidget"), 1, 0))};
#undef FUNC_NAME
gtk_widget_destroy(GTK_WIDGET(w));
}
@ -1111,17 +1108,15 @@ gnc_plugin_page_report_destroy(GncPluginPageReportPrivate * priv)
if (priv->initial_odb)
{
gnc_option_db_unregister_change_callback_id(priv->initial_odb,
priv->name_change_cb_id);
//Remove this if there's a double-free
gnc_option_db_destroy(priv->initial_odb);
priv->initial_odb = NULL;
priv->initial_odb = nullptr;
}
gnc_html_destroy(priv->html);
priv->container = NULL;
priv->html = NULL;
priv->container = nullptr;
priv->html = nullptr;
if (priv->cur_report != SCM_BOOL_F)
scm_gc_unprotect_object(priv->cur_report);
@ -1142,12 +1137,12 @@ static action_toolbar_labels toolbar_labels[] =
to be used as toolbar button label. */
{ "ReportSaveAsAction", N_("Save Config As...") },
{ "FilePrintPDFAction", N_("Make Pdf") },
{ NULL, NULL },
{ nullptr, nullptr },
};
static const gchar *initially_insensitive_actions[] =
{
NULL
nullptr
};
static void
@ -1162,14 +1157,13 @@ gnc_plugin_page_report_constructor(GType this_type, guint n_properties, GObjectC
GncPluginPageReportClass *our_class;
GObjectClass *parent_class;
gint reportId = -42;
int i;
our_class = GNC_PLUGIN_PAGE_REPORT_CLASS (
g_type_class_peek (GNC_TYPE_PLUGIN_PAGE_REPORT));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (our_class));
obj = parent_class->constructor(this_type, n_properties, properties);
for (i = 0; i < n_properties; i++)
for (decltype(n_properties) i = 0; i < n_properties; i++)
{
GObjectConstructParam prop = properties[i];
if (strcmp(prop.pspec->name, "report-id") == 0)
@ -1207,7 +1201,7 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
G_CALLBACK(gnc_plugin_page_report_print_cb)
},
{
"FilePrintPDFAction", GNC_ICON_PDF_EXPORT, N_("Export as P_DF..."), NULL,
"FilePrintPDFAction", GNC_ICON_PDF_EXPORT, N_("Export as P_DF..."), nullptr,
N_("Export the current report as a PDF document"),
G_CALLBACK(gnc_plugin_page_report_exportpdf_cb)
},
@ -1215,7 +1209,7 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
{
"EditCutAction", "edit-cut", N_("Cu_t"), "<primary>X",
N_("Cut the current selection and copy it to clipboard"),
NULL
nullptr
},
{
"EditCopyAction", "edit-copy", N_("_Copy"), "<primary>C",
@ -1225,7 +1219,7 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
{
"EditPasteAction", "edit-paste", N_("_Paste"), "<primary>V",
N_("Paste the clipboard content at the cursor position"),
NULL
nullptr
},
{
"ViewRefreshAction", "view-refresh", N_("_Refresh"), "<primary>r",
@ -1241,33 +1235,33 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
report_saveas_str, G_CALLBACK(gnc_plugin_page_report_save_as_cb)
},
{
"ReportExportAction", "go-next", N_("Export _Report"), NULL,
"ReportExportAction", "go-next", N_("Export _Report"), nullptr,
N_("Export HTML-formatted report to file"),
G_CALLBACK(gnc_plugin_page_report_export_cb)
},
{
"ReportOptionsAction", "document-properties", N_("_Report Options"), NULL,
"ReportOptionsAction", "document-properties", N_("_Report Options"), nullptr,
N_("Edit report options"),
G_CALLBACK(gnc_plugin_page_report_options_cb)
},
{
"ReportBackAction", "go-previous", N_("Back"), NULL,
"ReportBackAction", "go-previous", N_("Back"), nullptr,
N_("Move back one step in the history"),
G_CALLBACK(gnc_plugin_page_report_back_cb)
},
{
"ReportForwAction", "go-next", N_("Forward"), NULL,
"ReportForwAction", "go-next", N_("Forward"), nullptr,
N_("Move forward one step in the history"),
G_CALLBACK(gnc_plugin_page_report_forw_cb)
},
{
"ReportReloadAction", "view-refresh", N_("Reload"), NULL,
"ReportReloadAction", "view-refresh", N_("Reload"), nullptr,
N_("Reload the current page"),
G_CALLBACK(gnc_plugin_page_report_reload_cb)
},
{
"ReportStopAction", "process-stop", N_("Stop"), NULL,
"ReportStopAction", "process-stop", N_("Stop"), nullptr,
N_("Cancel outstanding HTML requests"),
G_CALLBACK(gnc_plugin_page_report_stop_cb)
},
@ -1289,7 +1283,7 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
"page-uri", "default:",
"ui-description", "gnc-plugin-page-report-ui.xml",
"use-new-window", use_new,
NULL);
nullptr);
g_free(name);
/* change me when the system supports multiple books */
@ -1316,11 +1310,9 @@ gnc_plugin_page_report_constr_init(GncPluginPageReport *plugin_page, gint report
GncPluginPage*
gnc_plugin_page_report_new( int reportId )
{
GncPluginPageReport *plugin_page;
DEBUG( "report id = %d", reportId );
plugin_page = g_object_new( GNC_TYPE_PLUGIN_PAGE_REPORT,
"report-id", reportId, NULL );
auto plugin_page{g_object_new(GNC_TYPE_PLUGIN_PAGE_REPORT, "report-id",
reportId, nullptr)};
DEBUG( "plugin_page: %p", plugin_page );
DEBUG( "set %d on page %p", reportId, plugin_page );
return GNC_PLUGIN_PAGE( plugin_page );
@ -1356,8 +1348,7 @@ gnc_plugin_page_report_raise_editor(SCM report)
SCM get_editor = scm_c_eval_string("gnc:report-editor-widget");
SCM editor = scm_call_1(get_editor, report);
#define FUNC_NAME "gtk_window_present"
GtkWidget *w = SWIG_MustGetPtr(editor,
SWIG_TypeQuery("_p_GtkWidget"), 1, 0);
auto w{static_cast<GtkWidget *>(SWIG_MustGetPtr(editor, SWIG_TypeQuery("_p_GtkWidget"), 1, 0))};
#undef FUNC_NAME
gtk_window_present(GTK_WINDOW(w));
}
@ -1397,7 +1388,7 @@ static void
gnc_plugin_page_report_forw_cb( GtkAction *action, GncPluginPageReport *report )
{
GncPluginPageReportPrivate *priv;
gnc_html_history_node * node = NULL;
gnc_html_history_node * node = nullptr;
DEBUG( "forw" );
priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
@ -1464,8 +1455,8 @@ gnc_plugin_page_report_reload_cb( GtkAction *action, GncPluginPageReport *report
gnc_plugin_page_report_set_progressbar( page, FALSE );
// this resets the window for the progressbar to NULL
gnc_window_set_progressbar_window( NULL );
// this resets the window for the progressbar to nullptr
gnc_window_set_progressbar_window( nullptr );
priv->reloading = FALSE;
}
@ -1483,7 +1474,7 @@ gnc_plugin_page_report_stop_cb( GtkAction *action, GncPluginPageReport *report )
static SCM
gnc_get_export_type_choice (SCM export_types, GtkWindow *parent)
{
GList * choices = NULL;
GList * choices = nullptr;
gboolean bad = FALSE;
GList * node;
int choice;
@ -1526,7 +1517,7 @@ gnc_get_export_type_choice (SCM export_types, GtkWindow *parent)
choice = gnc_choose_radio_option_dialog
(GTK_WIDGET (parent), _("Choose export format"),
_("Choose the export format for this report:"),
NULL, 0, choices);
nullptr, 0, choices);
}
else
choice = -1;
@ -1568,21 +1559,21 @@ gnc_get_export_filename (SCM choice, GtkWindow *parent)
title = g_strdup_printf (_("Save %s To File"), type);
default_dir = gnc_get_default_directory(GNC_PREFS_GROUP_REPORT);
filepath = gnc_file_dialog (parent, title, NULL, default_dir,
filepath = gnc_file_dialog (parent, title, nullptr, default_dir,
GNC_FILE_DIALOG_EXPORT);
if (filepath != NULL) // test for cancel pressed
if (filepath != nullptr) // test for cancel pressed
{
/* Try to test for extension on file name, add if missing */
if (g_strrstr(filepath, ".") == NULL)
filepath = g_strconcat(filepath, ".", g_ascii_strdown(type, strlen(type)), NULL);
if (g_strrstr(filepath, ".") == nullptr)
filepath = g_strconcat(filepath, ".", g_ascii_strdown(type, strlen(type)), nullptr);
}
g_free (type);
g_free (title);
g_free (default_dir);
if (!filepath)
return NULL;
return nullptr;
default_dir = g_path_get_dirname(filepath);
gnc_set_default_directory (GNC_PREFS_GROUP_REPORT, default_dir);
@ -1598,7 +1589,7 @@ gnc_get_export_filename (SCM choice, GtkWindow *parent)
gnc_error_dialog (parent, format, strerror(errno));
g_free(filepath);
return NULL;
return nullptr;
}
/* Check for a file that isn't a regular file. */
@ -1608,7 +1599,7 @@ gnc_get_export_filename (SCM choice, GtkWindow *parent)
gnc_error_dialog (parent, "%s", message);
g_free(filepath);
return NULL;
return nullptr;
}
if (rc == 0)
@ -1619,7 +1610,7 @@ gnc_get_export_filename (SCM choice, GtkWindow *parent)
if (!gnc_verify_dialog (parent, FALSE, format, filepath))
{
g_free(filepath);
return NULL;
return nullptr;
}
}
@ -1728,8 +1719,10 @@ gnc_plugin_page_report_export_cb( GtkAction *action, GncPluginPageReport *report
SCM get_export_error = scm_c_eval_string ("gnc:html-document-export-error");
if (scm_is_false (scm_call_1 (query_result, document)))
gnc_error_dialog (parent, _("This report must be upgraded to \
return a document object with export-string or export-error."));
gnc_error_dialog (parent, "%s",
_("This report must be upgraded to return a "
"document object with export-string or "
"export-error."));
else
{
SCM export_string = scm_call_1 (get_export_string, document);
@ -1737,7 +1730,7 @@ return a document object with export-string or export-error."));
if (scm_is_string (export_string))
{
GError *err = NULL;
GError *err = nullptr;
gchar *exported = scm_to_utf8_string (export_string);
if (!g_file_set_contents (filepath, exported, -1, &err))
gnc_error_dialog (parent, "Error during export: %s", err->message);
@ -1752,8 +1745,10 @@ return a document object with export-string or export-error."));
g_free (str);
}
else
gnc_error_dialog (parent, _("This report must be upgraded to \
return a document object with export-string or export-error."));
gnc_error_dialog (parent, "%s",
_("This report must be upgraded to return a "
"document object with export-string or "
"export-error."));
}
result = TRUE;
}
@ -1785,11 +1780,13 @@ gnc_plugin_page_report_options_cb( GtkAction *action, GncPluginPageReport *repor
gnc_plugin_page_report_add_edited_report(priv, priv->cur_report);
}
static GncInvoice *lookup_invoice(GncPluginPageReportPrivate *priv)
static GncInvoice*
lookup_invoice(GncPluginPageReportPrivate *priv)
{
g_assert(priv);
return gnc_option_db_lookup_invoice_option(priv->cur_odb, "General",
"Invoice Number", NULL);
const QofInstance* opt_val =
gnc_option_db_lookup_qofinstance_value(priv->cur_odb, "General",
"Invoice Number");
return GNC_INVOICE(opt_val);
}
#define GNC_PREFS_GROUP_REPORT_PDFEXPORT GNC_PREFS_GROUP_GENERAL_REPORT ".pdf-export"
@ -1798,8 +1795,8 @@ static GncInvoice *lookup_invoice(GncPluginPageReportPrivate *priv)
static gchar *report_create_jobname(GncPluginPageReportPrivate *priv)
{
gchar *job_name = NULL;
gchar *report_name = NULL;
gchar *job_name = nullptr;
gchar *report_name = nullptr;
const gchar *report_number = "";
gchar *job_date;
const gchar *default_jobname = N_("GnuCash-Report");
@ -1823,7 +1820,7 @@ static gchar *report_create_jobname(GncPluginPageReportPrivate *priv)
date_format_string = qof_date_format_get_string (date_format_here);
job_date = gnc_print_time64 (gnc_time (NULL), date_format_string);
job_date = gnc_print_time64 (gnc_time (nullptr), date_format_string);
g_free (format_code);
}
@ -1844,8 +1841,9 @@ static gchar *report_create_jobname(GncPluginPageReportPrivate *priv)
* so I added yet another hack below for this. cstim.
*/
GncInvoice *invoice;
report_name = gnc_option_db_lookup_string_option(priv->cur_odb, "General",
"Report name", NULL);
report_name = g_strdup(gnc_option_db_lookup_string_value(priv->cur_odb,
"General",
"Report name"));
if (!report_name)
report_name = g_strdup (_(default_jobname));
if (g_strcmp0(report_name, _("Printable Invoice")) == 0
@ -1901,7 +1899,7 @@ static gchar *report_create_jobname(GncPluginPageReportPrivate *priv)
// Lookup the existing usage count
value = g_hash_table_lookup(static_report_printnames, job_name);
already_found = (value != NULL);
already_found = (value != nullptr);
if (!value)
{
value = GINT_TO_POINTER(0);
@ -1949,7 +1947,7 @@ gnc_plugin_page_report_exportpdf_cb( GtkAction *action, GncPluginPageReport *rep
GncPluginPageReportPrivate *priv = GNC_PLUGIN_PAGE_REPORT_GET_PRIVATE(report);
gchar *job_name = report_create_jobname(priv);
GncInvoice *invoice;
GncOwner *owner = NULL;
GncOwner *owner = nullptr;
// Do we have an invoice report?
invoice = lookup_invoice(priv);
@ -1960,21 +1958,18 @@ gnc_plugin_page_report_exportpdf_cb( GtkAction *action, GncPluginPageReport *rep
if (owner)
{
QofInstance *inst = qofOwnerGetOwner (owner);
gchar *dirname = NULL;
qof_instance_get (inst, "export-pdf-dir", &dirname, NULL);
gchar *dirname = nullptr;
qof_instance_get (inst, "export-pdf-dir", &dirname, nullptr);
// Yes. In the kvp, look up the key for the Export-PDF output
// directory. If it exists, prepend this to the job name so that
// we can export to PDF.
if (dirname)
{
if (g_file_test (dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
{
gchar *tmp = g_build_filename (dirname, job_name, NULL);
g_free (job_name);
job_name = tmp;
}
g_free (dirname);
}
if (dirname && g_file_test(dirname,
(GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
{
gchar *tmp = g_build_filename(dirname, job_name, nullptr);
g_free(job_name);
job_name = tmp;
}
}
}
@ -2000,7 +1995,8 @@ gnc_plugin_page_report_exportpdf_cb( GtkAction *action, GncPluginPageReport *rep
const char* dirname = gtk_print_settings_get(print_settings,
GNC_GTK_PRINT_SETTINGS_EXPORT_DIR);
// Only store the directory if it exists.
if (g_file_test(dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
if (g_file_test(dirname,
(GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
{
QofInstance *inst = qofOwnerGetOwner(owner);
gncOwnerBeginEdit(owner);

View File

@ -34,6 +34,11 @@
#ifndef __GNC_PLUGIN_PAGE_REPORT_H
#define __GNC_PLUGIN_PAGE_REPORT_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <gtk/gtk.h>
#include "gnc-plugin.h"
@ -85,7 +90,9 @@ void gnc_main_window_open_report (int report_id, GncMainWindow *window);
void gnc_main_window_open_report_url (const char * url, GncMainWindow *window);
G_END_DECLS
#ifdef __cplusplus
}
#endif
#endif /* __GNC_PLUGIN_PAGE_REPORT_H */
/** @} */
/** @} */

View File

@ -37,7 +37,6 @@
#include "dialog-commodity.h"
#include "dialog-invoice.h"
#include "dialog-preferences.h"
#include "dialog-options.h"
#include "dialog-sx-editor.h"
#include "dialog-transfer.h"
#include "dialog-totd.h"

View File

@ -24,25 +24,28 @@
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
********************************************************************/
#include <libguile.h>
#include <glib/gi18n.h>
#include <memory>
extern "C"
{
#include <config.h>
#include <glib/gi18n.h>
#include <errno.h>
#include <libguile.h>
#include <sys/stat.h>
#include "swig-runtime.h"
#include "dialog-options.h"
#include "dialog-report-column-view.h"
#include "gnc-guile-utils.h"
#include "gnc-report.h"
#include "gnc-ui.h"
#include "option-util.h"
#include "window-report.h"
#include "guile-mappings.h"
#include "gnc-plugin-page-report.h"
}
#include "gnc-report.h"
#include "dialog-options.hpp"
#include "dialog-report-column-view.hpp"
/********************************************************************
*
@ -51,9 +54,9 @@
void
reportWindow(int report_id, GtkWindow *parent)
{
gnc_set_busy_cursor (NULL, TRUE);
gnc_set_busy_cursor (nullptr, TRUE);
gnc_main_window_open_report(report_id, GNC_MAIN_WINDOW(parent));
gnc_unset_busy_cursor (NULL);
gnc_unset_busy_cursor (nullptr);
}
/********************************************************************
@ -62,31 +65,29 @@ reportWindow(int report_id, GtkWindow *parent)
struct report_default_params_data
{
GNCOptionWin * win;
GNCOptionDB * db;
SCM scm_options;
GncOptionsDialog * win;
GncOptionDB * odb;
SCM cur_report;
};
static void
gnc_options_dialog_apply_cb(GNCOptionWin * propertybox,
gnc_options_dialog_apply_cb(GncOptionsDialog *opt_dialog,
gpointer user_data)
{
SCM dirty_report = scm_c_eval_string("gnc:report-set-dirty?!");
struct report_default_params_data * win = user_data;
GList *results = NULL, *iter;
auto win{static_cast<struct report_default_params_data*>(user_data)};
if (!win) return;
results = gnc_option_db_commit (win->db);
for (iter = results; iter; iter = iter->next)
auto results = gnc_option_db_commit (win->odb);
for (auto iter = results; iter; iter = iter->next)
{
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW (win->win),
0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
auto dialog = gtk_message_dialog_new(GTK_WINDOW (win->win),
static_cast<GtkDialogFlags>(0),
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
(char*)iter->data);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free (iter->data);
@ -97,35 +98,33 @@ gnc_options_dialog_apply_cb(GNCOptionWin * propertybox,
}
static void
gnc_options_dialog_help_cb(GNCOptionWin * propertybox,
gnc_options_dialog_help_cb(GncOptionsDialog *opt_dialog,
gpointer user_data)
{
GtkWidget *dialog, *parent;
struct report_default_params_data * prm = user_data;
auto prm{static_cast<struct report_default_params_data*>(user_data)};
parent = gnc_options_dialog_widget(prm->win);
dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s",
_("Set the report options you want using this dialog."));
auto parent = prm->win->get_widget();
auto dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s",
_("Set the report options you want using this dialog."));
g_signal_connect(G_OBJECT(dialog), "response",
(GCallback)gtk_widget_destroy, NULL);
(GCallback)gtk_widget_destroy, nullptr);
gtk_widget_show(dialog);
}
static void
gnc_options_dialog_close_cb(GNCOptionWin * propertybox,
gnc_options_dialog_close_cb(GncOptionsDialog *opt_dialog,
gpointer user_data)
{
struct report_default_params_data * win = user_data;
auto win{static_cast<struct report_default_params_data*>(user_data)};
SCM set_editor = scm_c_eval_string("gnc:report-set-editor-widget!");
scm_call_2(set_editor, win->cur_report, SCM_BOOL_F);
gnc_options_dialog_destroy(win->win);
gnc_option_db_destroy(win->db);
scm_gc_unprotect_object(win->scm_options);
delete win->win;
gnc_option_db_destroy(win->odb);
g_free(win);
}
@ -137,8 +136,7 @@ gnc_report_raise_editor(SCM report)
if (editor != SCM_BOOL_F)
{
#define FUNC_NAME "gnc-report-raise-editor"
GtkWidget *w = SWIG_MustGetPtr(editor,
SWIG_TypeQuery("_p_GtkWidget"), 1, 0);
auto w{static_cast<GtkWidget *>(SWIG_MustGetPtr(editor, SWIG_TypeQuery("_p_GtkWidget"), 1, 0))};
#undef FUNC_NAME
gtk_window_present(GTK_WINDOW(w));
return TRUE;
@ -149,7 +147,7 @@ gnc_report_raise_editor(SCM report)
GtkWidget *
gnc_report_window_default_params_editor(SCM options, SCM report,
gnc_report_window_default_params_editor(GncOptionDB* odb, SCM report,
GtkWindow *parent)
{
SCM get_report_type = scm_c_eval_string("gnc:report-type");
@ -157,18 +155,17 @@ gnc_report_window_default_params_editor(SCM options, SCM report,
SCM get_template_name = scm_c_eval_string("gnc:report-template-name");
SCM ptr;
const gchar *title = NULL;
const gchar *title = nullptr;
if (gnc_report_raise_editor (report))
return NULL;
return nullptr;
else
{
struct report_default_params_data * prm =
g_new0(struct report_default_params_data, 1);
prm->scm_options = options;
prm->odb = odb;
prm->cur_report = report;
prm->db = gnc_option_db_new(prm->scm_options);
/* Get the title of the report's template. */
ptr = scm_call_1(get_report_type, report);
@ -184,26 +181,18 @@ gnc_report_window_default_params_editor(SCM options, SCM report,
}
/* Don't forget to translate the window title */
prm->win = gnc_options_dialog_new((gchar*) (title && *title ? _(title) : ""), parent);
prm->win = new GncOptionsDialog((gchar*) (title && *title ? _(title) : ""), parent);
g_free ((gpointer *) title);
scm_gc_protect_object(prm->scm_options);
scm_gc_protect_object(prm->cur_report);
gnc_options_dialog_build_contents(prm->win, prm->db);
gnc_option_db_clean(prm->db);
prm->win->build_contents(prm->odb);
gnc_options_dialog_set_apply_cb(prm->win,
gnc_options_dialog_apply_cb,
(gpointer)prm);
gnc_options_dialog_set_help_cb(prm->win,
gnc_options_dialog_help_cb,
(gpointer)prm);
gnc_options_dialog_set_close_cb(prm->win,
gnc_options_dialog_close_cb,
(gpointer)prm);
return gnc_options_dialog_widget(prm->win);
prm->win->set_apply_cb(gnc_options_dialog_apply_cb, (gpointer)prm);
prm->win->set_help_cb(gnc_options_dialog_help_cb, (gpointer)prm);
prm->win->set_close_cb(gnc_options_dialog_close_cb, (gpointer)prm);
return prm->win->get_widget();
}
}
@ -211,19 +200,18 @@ 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;
GtkWidget *options_widget = NULL;
GncOptionDB* odb;
GtkWidget *options_widget = nullptr;
/* If the options editor widget already exists we simply raise it */
if (gnc_report_raise_editor (report))
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."));
@ -236,9 +224,9 @@ gnc_report_edit_options(SCM report, GtkWindow *parent)
{
gchar *rpt_type = gnc_scm_to_utf8_string (ptr);
if (g_strcmp0 (rpt_type, "d8ba4a2e89e8479ca9f6eccdeb164588") == 0)
options_widget = gnc_column_view_edit_options (options, report);
options_widget = gnc_column_view_edit_options (odb, report);
else
options_widget = gnc_report_window_default_params_editor (options, report, parent);
options_widget = gnc_report_window_default_params_editor (odb, report, parent);
g_free (rpt_type);
}
@ -250,3 +238,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

@ -24,16 +24,20 @@
#define GNC_REPORT_WINDOW_H
#include <libguile.h>
#ifdef __cplusplus
extern "C"
{
#endif
//#include "gnc-html.h"
#include "qof.h"
#include <gnc-optiondb.h>
typedef struct gnc_report_window_s gnc_report_window;
/** PROTOTYPES ******************************************************/
// scm-exposed
GtkWidget * gnc_report_window_default_params_editor(SCM options, SCM report, GtkWindow *parent);
GtkWidget * gnc_report_window_default_params_editor(GncOptionDB* odb, SCM report, GtkWindow *parent);
// called from multiple places
// [gnome-business/dialog-invoice.c;gnome/window-register.c]; and
@ -41,4 +45,8 @@ GtkWidget * gnc_report_window_default_params_editor(SCM options, SCM report, Gtk
void reportWindow(int id, GtkWindow *parent);
gboolean gnc_report_edit_options(SCM report, GtkWindow *parent);
#ifdef __cplusplus
}
GncOptionDB* gnc_get_report_optiondb(SCM report_instance);
#endif
#endif

View File

@ -37,7 +37,6 @@ extern "C" {
#include <gnc-prefs.h>
#include <gnc-prefs-utils.h>
#include <gnc-gnome-utils.h>
#include <gnc-report.h>
#include <gnc-session.h>
#include <qoflog.h>
}
@ -45,6 +44,7 @@ extern "C" {
#include <boost/locale.hpp>
#include <fstream>
#include <iostream>
#include <gnc-report.h>
namespace bl = boost::locale;

View File

@ -42,7 +42,6 @@ extern "C" {
#include <gnc-path.h>
#include <gnc-prefs.h>
#include <gnc-gsettings.h>
#include <gnc-report.h>
#include <gnc-splash.h>
#include <gnc-version.h>
#include "gnucash-locale-platform.h"
@ -53,6 +52,7 @@ extern "C" {
#include <iostream>
#include <string>
#include <vector>
#include <gnc-report.h>
namespace bl = boost::locale;

View File

@ -33,12 +33,15 @@
#include "gnucash-core-app.hpp"
extern "C" {
#include <glib/gi18n.h>
#include <dialog-new-user.h>
#include <gfec.h>
#include <gnc-engine.h> // For define GNC_MOD_GUI
#include <gnc-file.h>
#include <gnc-filepath-utils.h>
#include <gnc-gnome-utils.h>
#include <gnc-gsettings.h>
#include <gnc-hooks.h>
#include <gnc-module.h>
#include <gnc-path.h>
#include <gnc-plugin-bi-import.h>
@ -51,7 +54,6 @@ extern "C" {
#include <gnc-plugin-report-system.h>
#include <gnc-prefs.h>
#include <gnc-prefs-utils.h>
#include <gnc-report.h>
#include <gnc-session.h>
#include <gnc-splash.h>
#include <gnucash-register.h>
@ -65,6 +67,7 @@ extern "C" {
#include <boost/nowide/args.hpp>
#endif
#include <iostream>
#include <gnc-report.h>
#include <gnc-locale-utils.hpp>
namespace bl = boost::locale;

View File

@ -27,7 +27,7 @@
// gnc-html.i file. The full gnc-html.h file can't be parsed because of the new
// use of GObject
typedef gchar* URLType;
typedef const char* URLType;
#define URL_TYPE_FILE "file"
#define URL_TYPE_JUMP "jump"

View File

@ -30,7 +30,7 @@ typedef struct _gnc_html_history gnc_html_history;
struct _gnc_html_history_node
{
URLType type;
char* type;
gchar * location;
gchar * label;
};

View File

@ -587,8 +587,8 @@ perform_navigation_policy (WebKitWebView *web_view,
GncHtml *self)
{
WebKitURIRequest *req = NULL;
const gchar* uri; // Can't init it here.
gchar *scheme = NULL, *location = NULL, *label = NULL;
const gchar* uri, *scheme; // Can't init it here.
gchar *location = NULL, *label = NULL;
gboolean ignore = FALSE;
WebKitNavigationAction *action =
webkit_navigation_policy_decision_get_navigation_action (decision);

View File

@ -359,7 +359,7 @@ gnc_html_show_url( GncHtml* self, URLType type,
const gchar* location, const gchar* label,
gboolean new_window_hint )
{
URLType lc_type = NULL;
char* lc_type = NULL;
g_return_if_fail( self != NULL );
g_return_if_fail( GNC_IS_HTML(self) );
@ -629,7 +629,7 @@ gnc_html_set_parent( GncHtml* self, GtkWindow* parent )
gboolean
gnc_html_register_urltype( URLType type, const char *protocol )
{
URLType lc_type = NULL;
char* lc_type = NULL;
char *lc_proto = NULL;
if (!gnc_html_type_to_proto_hash)
@ -697,7 +697,7 @@ gnc_html_initialize( void )
gchar*
gnc_build_url( URLType type, const gchar* location, const gchar* label )
{
URLType lc_type = NULL;
char* lc_type = NULL;
char * type_name;
DEBUG(" ");
@ -931,7 +931,7 @@ gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand )
gnc_html_unregister_stream_handler( url_type );
if ( hand != NULL )
{
URLType lc_type = g_ascii_strdown (url_type, -1);
char* lc_type = g_ascii_strdown (url_type, -1);
g_hash_table_insert( gnc_html_stream_handlers, lc_type, hand );
}
}
@ -939,7 +939,7 @@ gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand )
void
gnc_html_unregister_stream_handler( URLType url_type )
{
URLType lc_type = g_ascii_strdown (url_type, -1);
char* lc_type = g_ascii_strdown (url_type, -1);
g_hash_table_remove( gnc_html_stream_handlers, lc_type );
g_free(lc_type);
}
@ -957,7 +957,7 @@ gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand )
gnc_html_unregister_url_handler( url_type );
if ( hand != NULL )
{
URLType lc_type = g_ascii_strdown (url_type, -1);
char* lc_type = g_ascii_strdown (url_type, -1);
g_hash_table_insert( gnc_html_url_handlers, lc_type, hand );
}
}
@ -965,7 +965,7 @@ gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand )
void
gnc_html_unregister_url_handler( URLType url_type )
{
URLType lc_type = g_ascii_strdown (url_type, -1);
char* lc_type = g_ascii_strdown (url_type, -1);
g_hash_table_remove( gnc_html_url_handlers, lc_type );
g_free(lc_type);
}

View File

@ -294,4 +294,5 @@ void gnc_html_unregister_url_handler( URLType url_type );
const gchar* gnc_html_get_embedded_param( gpointer eb, const gchar* param_name );
G_END_DECLS
#endif

View File

@ -24,7 +24,6 @@
#include <config.h>
#include <gtk/gtk.h>
#include <glib-object.h>
#include <dialog-options.h>
#include <dialog-utils.h>
#include <gnc-amount-edit.h>
#include <gnc-date-edit.h>
@ -34,6 +33,9 @@
#include <gnc-html.h>
%}
#if defined(SWIGGUILE)
%typemap (freearg) const char* "if (must_free$argnum && $1) SWIG_free((char*)$1);";
%{
#include "guile-mappings.h"

View File

@ -14,7 +14,7 @@ gnc_add_swig_guile_command (swig-report-c
)
set (report_SOURCES
gnc-report.c
gnc-report.cpp
)
add_library (gnc-report

View File

@ -30,19 +30,22 @@
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <libguile.h>
extern "C"
{
#include <stdio.h>
#include <string.h>
#include "gfec.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "gnc-filepath-utils.h"
#include "gnc-guile-utils.h"
#include <gfec.h>
#include <gnc-filepath-utils.h>
#include <gnc-guile-utils.h>
#include <gnc-engine.h>
}
#include "gnc-report.h"
#include "gnc-engine.h"
extern SCM scm_init_sw_report_module(void);
extern "C" SCM scm_init_sw_report_module(void);
static QofLogModule log_module = GNC_MOD_GUI;
@ -130,11 +133,11 @@ gnc_report_remove_by_id(gint id)
SCM gnc_report_find(gint id)
{
gpointer report = NULL;
SCM report = nullptr;
if (reports)
{
report = g_hash_table_lookup(reports, &id);
report = static_cast<SCM>(g_hash_table_lookup(reports, &id));
}
if (!report)
@ -303,9 +306,6 @@ gnc_saved_reports_write_internal (const gchar *file, const gchar *contents, gboo
{
gboolean success = TRUE;
gint fd;
#ifndef __MINGW32__
extern int errno;
#endif
ssize_t written;
gint length;
gint flags = O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_APPEND);
@ -393,3 +393,27 @@ gnc_saved_reports_write_to_file (const gchar* report_def, gboolean overwrite)
return success;
}
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();
}

View File

@ -27,6 +27,11 @@
#include <glib.h>
#include <libguile.h>
#ifdef __cplusplus
#include <gnc-optiondb.hpp>
extern "C"
{
#endif
#define SAVED_REPORTS_FILE "saved-reports-2.8"
#define SAVED_REPORTS_FILE_OLD_REV "saved-reports-2.4"
@ -35,34 +40,54 @@
*
* Should be called once before using any of its features.
*/
void gnc_report_init (void);
void gnc_report_init(void);
gboolean gnc_run_report_with_error_handling (gint report_id,
gchar **data,
gchar **errmsg);
gboolean gnc_run_report_id_string_with_error_handling (const char * id_string,
char **data,
gchar **errmsg);
gboolean gnc_run_report_with_error_handling(gint report_id,
gchar** data,
gchar** errmsg);
gboolean gnc_run_report_id_string_with_error_handling(const char* id_string,
char** data,
gchar** errmsg);
/**
* @param report The SCM version of the report.
* @return a caller-owned copy of the name of the report, or NULL if report
* is invalid.
**/
gchar* gnc_report_name( SCM report );
gchar* gnc_report_name(SCM report);
/* returns #f if the report id cannot be found */
SCM gnc_report_find(gint id);
void gnc_report_remove_by_id(gint id);
gint gnc_report_add(SCM report);
void gnc_reports_flush_global(void);
GHashTable *gnc_reports_get_global(void);
GHashTable* gnc_reports_get_global(void);
gchar* gnc_get_default_report_font_family(void);
gboolean gnc_saved_reports_backup (void);
gboolean gnc_saved_reports_write_to_file (const gchar* report_def, gboolean overwrite);
gboolean gnc_saved_reports_backup(void);
gboolean gnc_saved_reports_write_to_file(const gchar* report_def, gboolean overwrite);
#ifdef __cplusplus
} //extern "C"
/**
* 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);
#endif
#endif

View File

@ -80,10 +80,12 @@
(list)))
(define (gnc:register-guid type guid)
(gnc-build-url URL-TYPE-REGISTER (string-append type guid) ""))
(and guid (gnc-build-url URL-TYPE-REGISTER (string-append type guid) "")))
(define (gnc:account-anchor-text acct)
(gnc:register-guid "acct-guid=" (gncAccountGetGUID acct)))
(if acct
(gnc:register-guid "acct-guid=" (gncAccountGetGUID acct))
(format #t "No Account!")))
(define (gnc:split-anchor-text split)
(gnc:register-guid "split-guid=" (gncSplitGetGUID split)))

View File

@ -375,14 +375,7 @@ not found.")))
(let ((options (if (null? rest)
(gnc:report-template-new-options template)
(car rest))))
(gnc:report-set-options! r options)
(gnc:options-register-callback
#f #f
(lambda ()
(gnc:report-set-dirty?! r #t)
(let ((cb (gnc:report-template-options-changed-cb template)))
(if cb (cb r))))
options))
(gnc:report-set-options! r options))
(gnc:report-set-id! r (gnc-report-add r))
(gnc:report-id r)))

View File

@ -143,23 +143,19 @@
(define (accsum-options-generator sx? reportname)
(let* ((options (gnc:new-options))
(add-option
(lambda (new-option)
(gnc:register-option options new-option))))
(odb (gnc:options-get options)))
(add-option
(gnc:make-string-option
(gnc-register-string-option odb
gnc:pagename-general optname-report-title
"a" opthelp-report-title (G_ reportname)))
(add-option
(gnc:make-string-option
"a" opthelp-report-title (G_ reportname))
(gnc-register-string-option odb
gnc:pagename-general optname-party-name
"b" opthelp-party-name ""))
"b" opthelp-party-name "")
;; this should default to company name in (gnc-get-current-book)
;; does anyone know the function to get the company name??
;; date at which to report balance
(if sx?
(if sx?
(gnc:options-add-date-interval!
options gnc:pagename-general
optname-from-date optname-to-date "c")
@ -167,98 +163,83 @@
options gnc:pagename-general optname-date "c"))
;; accounts to work on
(add-option
(gnc:make-account-list-option
(gnc-register-account-list-option odb
gnc:pagename-accounts optname-accounts
"a"
opthelp-accounts
(lambda ()
(gnc:filter-accountlist-type
(list ACCT-TYPE-BANK ACCT-TYPE-CASH ACCT-TYPE-CREDIT
ACCT-TYPE-ASSET ACCT-TYPE-LIABILITY
ACCT-TYPE-STOCK ACCT-TYPE-MUTUAL ACCT-TYPE-CURRENCY
ACCT-TYPE-PAYABLE ACCT-TYPE-RECEIVABLE
ACCT-TYPE-EQUITY ACCT-TYPE-INCOME ACCT-TYPE-EXPENSE)
(gnc-account-get-descendants-sorted (gnc-get-current-root-account))))
#f #t))
(gnc:filter-accountlist-type
(list ACCT-TYPE-BANK ACCT-TYPE-CASH ACCT-TYPE-CREDIT
ACCT-TYPE-ASSET ACCT-TYPE-LIABILITY
ACCT-TYPE-STOCK ACCT-TYPE-MUTUAL ACCT-TYPE-CURRENCY
ACCT-TYPE-PAYABLE ACCT-TYPE-RECEIVABLE
ACCT-TYPE-EQUITY ACCT-TYPE-INCOME ACCT-TYPE-EXPENSE)
(gnc-account-get-descendants-sorted (gnc-get-current-root-account))))
(gnc:options-add-account-levels!
(gnc:options-add-account-levels!
options gnc:pagename-accounts optname-depth-limit
"b" opthelp-depth-limit 3)
(add-option
(gnc:make-multichoice-option
(gnc-register-multichoice-option odb
gnc:pagename-accounts optname-bottom-behavior
"c" opthelp-bottom-behavior 'summarize
"c" opthelp-bottom-behavior "summarize"
(list
(vector 'summarize (N_ "Recursive Balance"))
(vector 'flatten (N_ "Raise Accounts"))
(vector 'truncate (N_ "Omit Accounts")))))
(vector "summarize" (N_ "Recursive Balance"))
(vector "flatten" (N_ "Raise Accounts"))
(vector "truncate" (N_ "Omit Accounts"))))
;; all about currencies
(gnc:options-add-currency!
(gnc:options-add-currency!
options pagename-commodities
optname-report-commodity "a")
(gnc:options-add-price-source!
(gnc:options-add-price-source!
options pagename-commodities
optname-price-source "b" 'pricedb-nearest)
(add-option
(gnc:make-simple-boolean-option
(gnc-register-simple-boolean-option odb
pagename-commodities optname-show-foreign
"c" opthelp-show-foreign #t))
"c" opthelp-show-foreign #t)
(add-option
(gnc:make-simple-boolean-option
(gnc-register-simple-boolean-option odb
pagename-commodities optname-show-rates
"d" opthelp-show-rates #f))
"d" opthelp-show-rates #f)
;; what to show for zero-balance accounts
(add-option
(gnc:make-simple-boolean-option
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-zb-accts
"a" opthelp-show-zb-accts #t))
(add-option
(gnc:make-simple-boolean-option
"a" opthelp-show-zb-accts #t)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-omit-zb-bals
"b" opthelp-omit-zb-bals #f))
"b" opthelp-omit-zb-bals #f)
;; what to show for non-leaf accounts
(gnc:options-add-subtotal-view!
(gnc:options-add-subtotal-view!
options gnc:pagename-display
optname-parent-balance-mode optname-parent-total-mode
"c")
;; some detailed formatting options
(add-option
(gnc:make-simple-boolean-option
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-account-links
"e" opthelp-account-links #t))
(add-option
(gnc:make-simple-boolean-option
"e" opthelp-account-links #t)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-use-rules
"f" opthelp-use-rules #f))
"f" opthelp-use-rules #f)
(add-option
(gnc:make-simple-boolean-option
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-bals
"g" opthelp-show-bals #t))
(add-option
(gnc:make-simple-boolean-option
"g" opthelp-show-bals #t)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-code
"h" opthelp-show-code #t))
(add-option
(gnc:make-simple-boolean-option
"h" opthelp-show-code #t)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-desc
"i" opthelp-show-desc #f))
(add-option
(gnc:make-simple-boolean-option
"i" opthelp-show-desc #f)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-type
"j" opthelp-show-type #f))
(add-option
(gnc:make-simple-boolean-option
"j" opthelp-show-type #f)
(gnc-register-simple-boolean-option odb
gnc:pagename-display optname-show-notes
"k" opthelp-show-notes #f))
"k" opthelp-show-notes #f)
;; Set the general page as default option tab
(gnc:options-set-default-section options gnc:pagename-display)

View File

@ -51,8 +51,8 @@
(gnc:options->sxml uuid options "test-equity-statement" test-title))
(define (test-equity-statement)
(let* ((options (gnc:make-report-options uuid))
(account-alist (create-test-data))
(let* ((account-alist (create-test-data))
(options (gnc:make-report-options uuid))
(gbp-bank (assoc-ref account-alist "GBP Bank"))
(usd-bank (assoc-ref account-alist "Bank"))
(expense (assoc-ref account-alist "Expenses"))

View File

@ -97,8 +97,8 @@
(define (advanced-tests)
(test-group-with-cleanup "advanced-portfolio-tests"
(let ((account-alist (create-stock-test-data))
(options (gnc:make-report-options advanced-uuid)))
(let* ((account-alist (create-stock-test-data))
(options (gnc:make-report-options advanced-uuid)))
(let ((sxml (options->sxml advanced-uuid options "basic average")))
(test-equal "advanced: average basis"
'("AAPL" "AAPL" "NASDAQ" "42.00" "$6.0000" "$484.88" "$252.00" "$800.00"

View File

@ -51,8 +51,8 @@
(gnc:options->sxml uuid options "test-register" test-title))
(define (test-register)
(let* ((options (gnc:make-report-options uuid))
(account-alist (create-test-data))
(let* ((account-alist (create-test-data))
(options (gnc:make-report-options uuid))
(bank (cdr (assoc "Bank" account-alist))))
(gnc-commodity-set-user-symbol

View File

@ -11,6 +11,7 @@
(use-modules (gnucash reports))
(use-modules (tests test-report-extras))
(use-modules (srfi srfi-9))
(use-modules (srfi srfi-26))
(use-modules (srfi srfi-64))
(use-modules (srfi srfi-98))
(use-modules (tests srfi64-extras))
@ -68,7 +69,8 @@
(gnc:options-for-each
(lambda (option)
(when (case (gnc:option-type option)
((multichoice) (pair? (cdr (gnc:option-data option))))
((multichoice)
(> (GncOption-num-permissible-values option) 1))
((boolean) #t)
(else #f))
(set! report-options-tested
@ -76,8 +78,9 @@
(gnc:option-section option)
(gnc:option-name option)
(case (gnc:option-type option)
((multichoice) (map (lambda (d) (vector-ref d 0))
(gnc:option-data option)))
((multichoice)
(map (cut GncOption-permissible-value option <>)
(iota (GncOption-num-permissible-values option))))
((boolean) (list #t #f))))
report-options-tested))))
options)

View File

@ -51,8 +51,8 @@
(gnc:options->sxml uuid options "test-trial-balance" test-title))
(define (test-trial-balance)
(let* ((options (gnc:make-report-options uuid))
(account-alist (create-test-data))
(let* ((account-alist (create-test-data))
(options (gnc:make-report-options uuid))
(gbp-bank (assoc-ref account-alist "GBP Bank"))
(usd-bank (assoc-ref account-alist "Bank"))
(expense (assoc-ref account-alist "Expenses"))

View File

@ -42,8 +42,7 @@
(gnc:register-option options opt))))
;; the report-list is edited by a special add-on page for the
;; options editor.
(opt-register
(gnc:make-internal-option "__general" "report-list" '()))
(gnc-register-report-placement-option (gnc:options-get options) "__general" "report-list")
(opt-register
(gnc:make-number-range-option
@ -53,18 +52,6 @@
options))
(define (make-child-options-callback view child)
(let* ((view-opts (gnc:report-options view))
(child-opts (gnc:report-options child))
(id
(gnc:options-register-callback
#f #f
(lambda ()
(gnc:report-set-dirty?! child #t)
(gnc:options-touch view-opts))
child-opts)))
id))
(define (render-view report)
(let* ((view-doc (gnc:make-html-document))
(options (gnc:report-options report))
@ -80,17 +67,6 @@
(current-width 0)
(current-row-num 0))
;; make sure each subreport has an option change callback that
;; pings the parent
(let loop ((reports reports) (new-reports '()))
(match reports
(() (gnc:option-set-value report-opt (reverse new-reports)))
(((child rowspan colspan callback) . rest)
(let ((callback (or callback
(make-child-options-callback
report (gnc-report-find child)))))
(loop rest (cons (list child rowspan colspan callback) new-reports))))))
;; we really would rather do something smart here with the
;; report's cached text if possible. For the moment, we'll have
;; to rerun every report, every time... FIXME
@ -106,7 +82,6 @@
(let* ((subreport (gnc-report-find (car report-info)))
(colspan (cadr report-info))
(rowspan (caddr report-info))
(opt-callback (cadddr report-info))
(toplevel-cell (gnc:make-html-table-cell/size rowspan colspan))
(report-table (gnc:make-html-table))
(contents-cell (gnc:make-html-table-cell)))

View File

@ -11,11 +11,13 @@ set (app_utils_noinst_HEADERS
calculation/finproto.h
calculation/fin_spl_protos.h
calculation/fin_static_proto.h
gnc-option-date.hpp
gnc-option-impl.hpp
gnc-optiondb-impl.hpp
)
set (app_utils_HEADERS
QuickFill.h
business-options.h
file-utils.h
gfec.h
gnc-basic-gobject.h
@ -28,19 +30,25 @@ set (app_utils_HEADERS
gnc-gsettings.h
gnc-help-utils.h
gnc-helpers.h
gnc-option.hpp
gnc-optiondb.h
gnc-optiondb.hpp
gnc-prefs-utils.h
gnc-state.h
gnc-state.h
gnc-sx-instance-model.h
gnc-ui-util.h
gnc-ui-balances.h
option-util.h
)
# Command to generate the swig-app-utils-guile.c wrapper file
gnc_add_swig_guile_command (swig-apputils-guile-c
SWIG_APP_UTILS_GUILE_C swig-app-utils-guile.c
${CMAKE_CURRENT_SOURCE_DIR}/app-utils.i ""
set(SWIG_ARGS "-c++" "-procdoc" "sw-gnc-option-doc" "-procdocformat" "plain")
gnc_add_swig_guile_command (swig-apputils-guile-cpp #target
SWIG_APP_UTILS_GUILE_CPP swig-app-utils-guile.cpp #outvar, output
${CMAKE_CURRENT_SOURCE_DIR}/app-utils.i #input
"${CMAKE_SOURCE_DIR}/bindings;${CMAKE_SOURCE_DIR}/bindings/guile" #includes
${CMAKE_CURRENT_SOURCE_DIR}/gnc-optiondb.i #additional dependencies
)
unset(SWIG_ARGS)
# Command to generate the swig-app-utils-python.c wrapper file
gnc_add_swig_python_command (swig-app-utils-python
@ -52,7 +60,6 @@ gnc_add_swig_python_command (swig-app-utils-python
set (app_utils_SOURCES
calculation/expression_parser.c
calculation/fin.c
business-options.c
QuickFill.c
file-utils.c
gfec.c
@ -64,12 +71,15 @@ set (app_utils_SOURCES
gnc-exp-parser.c
gnc-gsettings.cpp
gnc-helpers.c
gnc-option-date.cpp
gnc-option.cpp
gnc-option-impl.cpp
gnc-optiondb.cpp
gnc-prefs-utils.c
gnc-sx-instance-model.c
gnc-state.c
gnc-ui-util.c
gnc-ui-balances.c
option-util.c
)
set_source_files_properties (${app_utils_SOURCES} PROPERTIES OBJECT_DEPENDS ${CONFIG_H})
@ -84,6 +94,7 @@ set(app_utils_ALL_LIBRARIES
gnc-engine
gnc-locale-tax
gnucash-guile
${GLIB_LDFLAGS}
${GIO_LDFLAGS}
${LIBXML2_LDFLAGS}
${LIBXSLT_LDFLAGS}
@ -105,7 +116,7 @@ if (WIN32)
endif()
add_library (gnc-app-utils ${app_utils_ALL_SOURCES} ${SWIG_APP_UTILS_GUILE_C})
add_library (gnc-app-utils ${app_utils_ALL_SOURCES} ${SWIG_APP_UTILS_GUILE_CPP})
target_link_libraries(gnc-app-utils ${app_utils_ALL_LIBRARIES})
target_include_directories (gnc-app-utils
@ -178,14 +189,6 @@ set (app_utils_SCHEME_1a
options.scm
)
set (app_utils_SCHEME_1b
business-options.scm
)
set (app_utils_SCHEME_1c
business-prefs.scm
)
set (app_utils_SCHEME_2
app-utils.scm
)
@ -207,22 +210,10 @@ gnc_add_scheme_targets(scm-app-utils-1a
DEPENDS "scm-app-utils-1"
MAKE_LINKS)
gnc_add_scheme_targets(scm-app-utils-1b
SOURCES "${app_utils_SCHEME_1b}"
OUTPUT_DIR "gnucash/app-utils"
DEPENDS "scm-app-utils-1a"
MAKE_LINKS)
gnc_add_scheme_targets(scm-bus-prefs
SOURCES "${app_utils_SCHEME_1c}"
OUTPUT_DIR "gnucash/app-utils"
DEPENDS "scm-app-utils-1b"
MAKE_LINKS)
gnc_add_scheme_targets(scm-app-utils-2
SOURCES "${app_utils_SCHEME_2}"
OUTPUT_DIR "gnucash"
DEPENDS "scm-bus-prefs"
DEPENDS "scm-app-utils-1a"
MAKE_LINKS)
add_custom_target(scm-app-utils ALL DEPENDS scm-app-utils-2 scm-app-utils-1)

View File

@ -21,8 +21,12 @@
%module sw_app_utils
%{
/* Includes the header in the wrapper code */
#include <glib.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include <config.h>
#include <option-util.h>
#include <gnc-euro.h>
#include <gnc-exp-parser.h>
#include <gnc-ui-util.h>
@ -33,14 +37,22 @@
#include <gnc-sx-instance-model.h>
#include "gnc-engine-guile.h"
#ifdef __cplusplus
}
#endif
%}
#if defined(SWIGGUILE)
#if defined(SWIGGUILE) //Always C++
%{
extern "C"
{
#include "guile-mappings.h"
SCM scm_init_sw_app_utils_module (void);
}
%}
%include "gnc-optiondb.i"
#endif
#if defined(SWIGPYTHON)
@ -53,9 +65,6 @@ PyObject* SWIG_init (void);
%import "base-typemaps.i"
typedef void (*GNCOptionChangeCallback) (gpointer user_data);
typedef int GNCOptionDBHandle;
void gnc_prefs_init();
QofBook * gnc_get_current_book (void);
@ -64,11 +73,6 @@ const gchar * gnc_get_current_book_tax_name (void);
const gchar * gnc_get_current_book_tax_type (void);
Account * gnc_get_current_root_account (void);
GNCOptionDB * gnc_option_db_new(SCM guile_options);
void gnc_option_db_destroy(GNCOptionDB *odb);
void gnc_option_db_set_option_selectable_by_name(SCM guile_option,
const char *section, const char *name, gboolean selectable);
#if defined(SWIGGUILE)
%typemap(out) GncCommodityList * {
@ -76,7 +80,7 @@ void gnc_option_db_set_option_selectable_by_name(SCM guile_option,
GList *node;
for (node = $1; node; node = node->next)
list = scm_cons(gnc_quoteinfo2scm(node->data), list);
list = scm_cons(gnc_quoteinfo2scm(static_cast<gnc_commodity*>(node->data)), list);
$result = scm_reverse(list);
}
@ -91,10 +95,6 @@ gnc_commodity_table_get_quotable_commodities(const gnc_commodity_table * table);
gnc_commodity * gnc_default_currency (void);
gnc_commodity * gnc_default_report_currency (void);
void gncp_option_invoke_callback(GNCOptionChangeCallback callback, void *data);
void gnc_option_db_register_option(GNCOptionDBHandle handle,
SCM guile_option);
GNCPrintAmountInfo gnc_default_print_info (gboolean use_symbol);
GNCPrintAmountInfo gnc_account_print_info (const Account *account,
gboolean use_symbol);
@ -119,8 +119,6 @@ gnc_numeric gnc_convert_from_euro(const gnc_commodity * currency,
time64 gnc_accounting_period_fiscal_start(void);
time64 gnc_accounting_period_fiscal_end(void);
void gnc_register_kvp_option_generator(QofIdType id_type, SCM generator);
%typemap(out) GHashTable * {
SCM table = scm_c_make_hash_table (g_hash_table_size($1) + 17);
GHashTableIter iter;

View File

@ -28,11 +28,9 @@
(load-and-reexport (sw_app_utils)
(gnucash app-utils date-utilities)
(gnucash app-utils business-options)
(gnucash app-utils business-prefs)
(gnucash app-utils options)
(gnucash app-utils c-interface))
;; gw-engine-spec.scm
(re-export HOOK-SAVE-OPTIONS)
(export gnc:get-debit-string)

View File

@ -1,92 +0,0 @@
/*
* business-options.c -- Non-GUI Option Utilities for GNC Business Objects
*
* Written By: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2003 Derek Atkins
*
* 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 "business-options.h"
#include "swig-runtime.h"
#include "guile-mappings.h"
#define FUNC_NAME G_STRFUNC
#define LOOKUP_OPTION(fcn) \
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 (value == SCM_BOOL_F) \
return NULL; \
SWIG_GetModule(NULL); /* Work-around for SWIG bug. */ \
if (!SWIG_IsPointer(value)) \
scm_misc_error(fcn, "SCM is not a wrapped pointer.", value)
GncTaxTable*
gnc_option_db_lookup_taxtable_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncTaxTable * default_value)
{
LOOKUP_OPTION("gnc_option_db_lookup_taxtable_option");
return SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncTaxTable"), 1, 0);
}
GncInvoice*
gnc_option_db_lookup_invoice_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncInvoice * default_value)
{
LOOKUP_OPTION("gnc_option_db_lookup_invoice_option");
return SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncInvoice"), 1, 0);
}
GncCustomer*
gnc_option_db_lookup_customer_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncCustomer * default_value)
{
LOOKUP_OPTION("gnc_option_db_lookup_customer_option");
return SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncCustomer"), 1, 0);
}
GncVendor*
gnc_option_db_lookup_vendor_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncVendor * default_value)
{
LOOKUP_OPTION("gnc_option_db_lookup_vendor_option");
return SWIG_MustGetPtr(value, SWIG_TypeQuery("_p__gncVendor"), 1, 0);
}

View File

@ -1,56 +0,0 @@
/*
* business-options.h -- non-GUI Option Utilities for GNC Business Objects
*
* Written By: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2003 Derek Atkins <warlord@MIT.EDU>
*
* 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
*/
#ifndef GNC_BUSINESS_OPTIONS_UTILS_H_
#define GNC_BUSINESS_OPTIONS_UTILS_H_
#include "option-util.h"
#include "gncTaxTable.h"
#include "gncInvoice.h"
#include "gncCustomer.h"
#include "gncVendor.h"
GncTaxTable* gnc_option_db_lookup_taxtable_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncTaxTable * default_value);
GncInvoice* gnc_option_db_lookup_invoice_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncInvoice * default_value);
GncCustomer* gnc_option_db_lookup_customer_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncCustomer * default_value);
GncVendor* gnc_option_db_lookup_vendor_option(GNCOptionDB *odb,
const char *section,
const char *name,
GncVendor * default_value);
#endif /* GNC_BUSINESS_OPTIONS_UTILS_H_ */

View File

@ -1,386 +0,0 @@
;; Scheme code for supporting options for the business modules
;;
;; Created by: Derek Atkins <derek@ihtfp.com>
;;
;; 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
;; Internally, values are always a guid. Externally, both guids and
;; invoice pointers may be used to set the value of the option. The
;; option always returns a single invoice pointer.
(define-module (gnucash app-utils business-options))
(eval-when (compile load eval expand)
(load-extension "libgnc-app-utils" "scm_init_sw_app_utils_module"))
(use-modules (gnucash core-utils))
(use-modules (gnucash engine))
(use-modules (gnucash utilities))
(use-modules (gnucash app-utils options))
(use-modules (sw_app_utils))
(export gnc:*business-label*)
(export gnc:*company-name*)
(export gnc:*company-addy*)
(export gnc:*company-id*)
(export gnc:*company-phone*)
(export gnc:*company-fax*)
(export gnc:*company-url*)
(export gnc:*company-email*)
(export gnc:*company-contact*)
(export gnc:*fancy-date-label*)
(export gnc:*fancy-date-format*)
(export gnc:*tax-label*)
(export gnc:*tax-nr-label*)
(export gnc:company-info)
(export gnc:fancy-date-info)
(export gnc:*option-section-budgeting*)
(export gnc:*option-name-auto-readonly-days*)
(export gnc:*option-name-num-field-source*)
(export gnc:*kvp-option-path*)
(export gnc:options-fancy-date)
(export gnc:*option-name-default-budget*)
(define gnc:*kvp-option-path* (list KVP-OPTION-PATH))
(define gnc:*option-name-auto-readonly-days* OPTION-NAME-AUTO-READONLY-DAYS)
(define gnc:*option-name-num-field-source* OPTION-NAME-NUM-FIELD-SOURCE)
(define gnc:*option-section-budgeting* OPTION-SECTION-BUDGETING)
(define gnc:*option-name-default-budget* OPTION-NAME-DEFAULT-BUDGET)
(define gnc:*business-label* (N_ "Business"))
(define gnc:*company-name* (N_ "Company Name"))
(define gnc:*company-addy* (N_ "Company Address"))
(define gnc:*company-id* (N_ "Company ID"))
(define gnc:*company-phone* (N_ "Company Phone Number"))
(define gnc:*company-fax* (N_ "Company Fax Number"))
(define gnc:*company-url* (N_ "Company Website URL"))
(define gnc:*company-email* (N_ "Company Email Address"))
(define gnc:*company-contact* (N_ "Company Contact Person"))
(define gnc:*fancy-date-label* (N_ "Fancy Date Format"))
(define gnc:*fancy-date-format* (N_ "custom"))
(define gnc:*tax-label* (N_ "Tax"))
(define gnc:*tax-nr-label* (N_ "Tax Number"))
(define (gnc:options-fancy-date book)
(let ((date-format (gnc:fancy-date-info book gnc:*fancy-date-format*)))
(if (boolean? date-format) ;; date-format does not exist
(qof-date-format-get-string (qof-date-format-get))
date-format)))
(define (gnc:company-info book key)
;; Access company info from key-value pairs for current book
(gnc:option-get-value book gnc:*business-label* key))
(define (gnc:fancy-date-info book key)
;; Access fancy date info from key-value pairs for current book
(gnc:option-get-value book gnc:*business-label* (list gnc:*fancy-date-label* key)))
(define (gnc:make-invoice-option
section
name
sort-tag
documentation-string
default-getter
value-validator)
(define (convert-to-guid item)
(if (string? item)
item
(gncInvoiceReturnGUID item)))
(define (convert-to-invoice item)
(if (string? item)
(gncInvoiceLookupFlip item (gnc-get-current-book))
item))
(let* ((option (convert-to-guid (default-getter)))
(option-set #f)
(getter (lambda () (convert-to-invoice
(if option-set
option
(default-getter)))))
(value->string (lambda ()
(string-append
"'" (gnc:value->string (if option-set option #f)))))
(validator
(if (not value-validator)
(lambda (invoice) (list #t invoice))
(lambda (invoice)
(value-validator (convert-to-invoice invoice))))))
(gnc:make-option
section name sort-tag 'invoice documentation-string getter
(lambda (invoice) ;; setter
(if (null? invoice) (set! invoice (default-getter)))
(set! invoice (convert-to-invoice invoice))
(let* ((result (validator invoice))
(valid (car result))
(value (cadr result)))
(if valid
(begin
(set! option (convert-to-guid value))
(set! option-set #t))
(gnc:error "Illegal invoice value set"))))
(lambda () (convert-to-invoice (default-getter)))
(gnc:restore-form-generator value->string)
(lambda (b p) (qof-book-set-option b option p))
(lambda (b p)
(let ((v (qof-book-get-option b p)))
(if (and v (string? v))
(begin
(set! option v)
(set! option-set #t)))))
validator
#f #f #f #f)))
;; Internally, values are always a guid. Externally, both guids and
;; customer pointers may be used to set the value of the option. The
;; option always returns a single customer pointer.
(define (gnc:make-owner-option
section
name
sort-tag
documentation-string
default-getter
value-validator
owner-type)
(let ((option-value (gncOwnerNew)))
(define (convert-to-pair item)
(if (pair? item)
item
(cons (gncOwnerGetType item)
(gncOwnerReturnGUID item))))
(define (convert-to-owner pair)
(if (pair? pair)
(let ((type (car pair)))
(cond
((eqv? type GNC-OWNER-CUSTOMER)
(gncOwnerInitCustomer
option-value
(gncCustomerLookupFlip (cdr pair) (gnc-get-current-book)))
option-value)
((eqv? type GNC-OWNER-VENDOR)
(gncOwnerInitVendor
option-value
(gncVendorLookupFlip (cdr pair) (gnc-get-current-book)))
option-value)
((eqv? type GNC-OWNER-EMPLOYEE)
(gncOwnerInitEmployee
option-value
(gncEmployeeLookupFlip (cdr pair) (gnc-get-current-book)))
option-value)
((eqv? type GNC-OWNER-JOB)
(gncOwnerInitJob
option-value
(gncJobLookupFlip (cdr pair) (gnc-get-current-book)))
option-value)
(else '())))
pair))
(let* ((option (convert-to-pair (default-getter)))
(option-set #f)
(getter (lambda () (convert-to-owner
(if option-set
option
(default-getter)))))
(value->string (lambda ()
(string-append
"'" (gnc:value->string
(if option-set option #f)))))
(validator
(if (not value-validator)
(lambda (owner)
(let ((type (if (pair? owner)
(car owner)
(gncOwnerGetType owner))))
(if (equal? type owner-type)
(list #t owner)
(list #f "Owner-Type Mismatch"))))
(lambda (owner)
(value-validator (convert-to-owner owner))))))
(gnc:make-option
section name sort-tag 'owner documentation-string getter
(lambda (owner)
(if (null? owner) (set! owner (default-getter)))
(set! owner (convert-to-owner owner))
(let* ((result (validator owner))
(valid (car result))
(value (cadr result)))
(if valid
(begin
(set! option (convert-to-pair value))
(set! option-set #t))
(gnc:error "Illegal owner value set"))))
(lambda () (convert-to-owner (default-getter)))
(gnc:restore-form-generator value->string)
(lambda (b p)
(qof-book-set-option b (symbol->string (car option))
(append p '("type")))
(qof-book-set-option b (cdr option)
(append p '("value"))))
(lambda (b p)
(let ((t (qof-book-get-option b (append p '("type"))))
(v (qof-book-get-option b (append p '("value")))))
(if (and t v (string? t) (string? v))
(begin
(set! option (cons (string->symbol t) v))
(set! option-set #t)))))
validator
owner-type #f #f #f))))
;; Internally, values are always a guid. Externally, both guids and
;; taxtable pointers may be used to set the value of the option. The
;; option always returns a single taxtable pointer.
(define (gnc:make-taxtable-option
section
name
sort-tag
documentation-string
default-getter
value-validator)
(define (convert-to-guid item)
(if (string? item)
item
(gncTaxTableReturnGUID item)))
(define (convert-to-taxtable item)
(if (string? item)
(gncTaxTableLookupFlip item (gnc-get-current-book))
item))
(let* ((option (convert-to-guid (default-getter)))
(option-set #f)
(getter (lambda () (convert-to-taxtable
(if option-set
option
(default-getter)))))
(value->string (lambda ()
(string-append
"'" (gnc:value->string (if option-set option #f)))))
(validator
(if (not value-validator)
(lambda (taxtable) (list #t taxtable))
(lambda (taxtable)
(value-validator (convert-to-taxtable taxtable))))))
(gnc:make-option
section name sort-tag 'taxtable documentation-string getter
(lambda (taxtable)
(if (null? taxtable) (set! taxtable (default-getter)))
(set! taxtable (convert-to-taxtable taxtable))
(let* ((result (validator taxtable))
(valid (car result))
(value (cadr result)))
(if valid
(begin
(set! option (convert-to-guid value))
(set! option-set #t))
(gnc:error "Illegal taxtable value set"))))
(lambda () (convert-to-taxtable (default-getter)))
(gnc:restore-form-generator value->string)
(lambda (b p) (qof-book-set-option b option p))
(lambda (b p)
(let ((v (qof-book-get-option b p)))
(if (and v (string? v))
(begin
(set! option v)
(set! option-set #t)))))
validator
#f #f #f #f)))
;; This defines an option to set a counter value. This is a slightly
;; different kind of option: Unlike all other options, the values edited
;; by this option are not saved in the "options"/<section> kvm slot, but
;; in the "counters" slot. This is mostly due to backwards compatibility
;; and partly because counters are a bit different from other options
;; anyway.
;;
;; This is implemented by overriding the scm->kvp and kvp->scm methods
;; to ignore the kvp path passed and replace it with a hardcoded
;; "counters".
(define (gnc:make-counter-option
section
name
key
sort-tag
documentation-string
default-value)
(let ((option (gnc:make-number-range-option
section name sort-tag documentation-string
default-value 0 999999999 0 1)))
(gnc:set-option-scm->kvp
option
(lambda (b p)
(qof-book-set-option
b (inexact->exact ((gnc:option-getter option)))
(list "counters" key))))
(gnc:set-option-kvp->scm
option
(lambda (b p)
(let ((v (qof-book-get-option b (list "counters" key))))
(if (and v (integer? v))
((gnc:option-setter option) v)))))
option))
;; This defines an option to set a counter format, which has the same
;; exception as gnc:make-counter-option above.
;; Note this function uses a hack to make sure there never is a default value
;; (default-value is set to #f and value subsequently set to whatever was passed as default-value)
;; This hack was introduced to fix https://bugs.gnucash.org/show_bug.cgi?id=687504
(define (gnc:make-counter-format-option
section
name
key
sort-tag
documentation-string
default-value)
(let ((option (gnc:make-string-option
section name sort-tag documentation-string #f)))
(gnc:option-set-value option default-value)
(gnc:set-option-scm->kvp
option
(lambda (b p)
(let ((value ((gnc:option-getter option)))
(path (string-concatenate (list "counter_formats/" key))))
(qof-book-set-string-option b path value))))
(gnc:set-option-kvp->scm
option
(lambda (b p)
(let* ((path (string-concatenate (list "counter_formats/" key)))
(v (qof-book-get-string-option b path)))
(if (and v (string? v))
((gnc:option-setter option) v)))))
option))
(export gnc:make-invoice-option)
(export gnc:make-owner-option)
(export gnc:make-taxtable-option)
(export gnc:make-counter-option)
(export gnc:make-counter-format-option)

View File

@ -1,199 +0,0 @@
;; Business Preferences
;;
;; Created by: Derek Atkins <derek@ihtfp.com>
;;
;; 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
(define-module (gnucash app-utils business-prefs))
(eval-when (compile load eval expand)
(load-extension "libgnc-app-utils" "scm_init_sw_app_utils_module"))
(use-modules (sw_app_utils))
(use-modules (gnucash core-utils))
(use-modules (gnucash engine))
(use-modules (gnucash app-utils options))
(use-modules (gnucash app-utils business-options))
(define gnc:*option-section-counters* (N_ "Counters"))
;; This defines all available counter types to show options for. This a
;; list that contains a sublist for each counter type, containing: The
;; (untranslated) counter name, the format label, the previous number
;; label, the format help text and the previous number help text.
(define counter-types
(list (list "gncCustomer" (N_ "Customer number format")
(N_ "Customer number")
(N_ "The format string to use for generating customer numbers. This is a printf-style format string.")
(N_ "The previous customer number generated. This number will be incremented to generate the next customer number."))
(list "gncEmployee" (N_ "Employee number format")
(N_ "Employee number")
(N_ "The format string to use for generating employee numbers. This is a printf-style format string.")
(N_ "The previous employee number generated. This number will be incremented to generate the next employee number."))
(list "gncInvoice" (N_ "Invoice number format")
(N_ "Invoice number")
(N_ "The format string to use for generating invoice numbers. This is a printf-style format string.")
(N_ "The previous invoice number generated. This number will be incremented to generate the next invoice number."))
(list "gncBill" (N_ "Bill number format")
(N_ "Bill number")
(N_ "The format string to use for generating bill numbers. This is a printf-style format string.")
(N_ "The previous bill number generated. This number will be incremented to generate the next bill number."))
(list "gncExpVoucher" (N_ "Expense voucher number format")
(N_ "Expense voucher number")
(N_ "The format string to use for generating expense voucher numbers. This is a printf-style format string.")
(N_ "The previous expense voucher number generated. This number will be incremented to generate the next voucher number."))
(list "gncJob" (N_ "Job number format")
(N_ "Job number")
(N_ "The format string to use for generating job numbers. This is a printf-style format string.")
(N_ "The previous job number generated. This number will be incremented to generate the next job number."))
(list "gncOrder" (N_ "Order number format")
(N_ "Order number")
(N_ "The format string to use for generating order numbers. This is a printf-style format string.")
(N_ "The previous order number generated. This number will be incremented to generate the next order number."))
(list "gncVendor" (N_ "Vendor number format")
(N_ "Vendor number")
(N_ "The format string to use for generating vendor numbers. This is a printf-style format string.")
(N_ "The previous vendor number generated. This number will be incremented to generate the next vendor number."))
))
(define (book-options-generator options)
(define (reg-option new-option)
(gnc:register-option options new-option))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-name*
"a" (N_ "The name of your business.") ""))
(reg-option
(gnc:make-text-option
gnc:*business-label* gnc:*company-addy*
"b1" (N_ "The address of your business.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-contact*
"b2" (N_ "The contact person to print on invoices.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-phone*
"c1" (N_ "The phone number of your business.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-fax*
"c2" (N_ "The fax number of your business.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-email*
"c3" (N_ "The email address of your business.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-url*
"c4" (N_ "The URL address of your website.") ""))
(reg-option
(gnc:make-string-option
gnc:*business-label* gnc:*company-id*
"c5" (N_ "The ID for your company (eg 'Tax-ID: 00-000000).")
""))
(reg-option
(gnc:make-taxtable-option
gnc:*business-label* (N_ "Default Customer TaxTable")
"e" (N_ "The default tax table to apply to customers.")
(lambda () '()) #f))
(reg-option
(gnc:make-taxtable-option
gnc:*business-label* (N_ "Default Vendor TaxTable")
"f" (N_ "The default tax table to apply to vendors.")
(lambda () '()) #f))
(reg-option
(gnc:make-dateformat-option
gnc:*business-label* gnc:*fancy-date-label*
"g" (N_ "The default date format used for fancy printed dates.")
#f))
;; Accounts tab
(reg-option
(gnc:make-number-range-option
gnc:*option-section-accounts* gnc:*option-name-auto-readonly-days*
"a" (N_ "Choose the number of days after which transactions will be read-only and cannot be edited anymore. This threshold is marked by a red line in the account register windows. If zero, all transactions can be edited and none are read-only.")
0 ;; default
0 ;; lower bound
3650 ;; upper bound
0 ;; number of decimals
1 ;; step size
))
(reg-option
(gnc:make-simple-boolean-option
gnc:*option-section-accounts* gnc:*option-name-num-field-source*
"b" (N_ "Check to have split action field used in registers for 'Num' field in place of transaction number; transaction number shown as 'T-Num' on second line of register. Has corresponding effect on business features, reporting and imports/exports.")
#f))
(reg-option
(gnc:make-simple-boolean-option
gnc:*option-section-accounts* gnc:*option-name-trading-accounts*
"a" (N_ "Check to have trading accounts used for transactions involving more than one currency or commodity.")
#f))
;; Budgeting Tab
(reg-option
(gnc:make-budget-option
gnc:*option-section-budgeting* gnc:*option-name-default-budget*
"a" (N_ "Budget to be used when none has been otherwise specified.")))
;; Tax Tab
(reg-option
(gnc:make-string-option
gnc:*tax-label* gnc:*tax-nr-label*
"a" (N_ "The electronic tax number of your business") ""))
;; Counters Tab
(for-each
(lambda (vals)
;; Unpack the list of strings for this counter type
(let* ((key (car vals))
(format-label (cadr vals))
(number-label (caddr vals))
(format-description (cadddr vals))
(number-description (cadddr (cdr vals))))
;; For each counter-type we create an option for the last used
;; number and the format string to use.
(reg-option
(gnc:make-counter-option
gnc:*option-section-counters* number-label key
(string-append key "a") number-description 0))
(reg-option
(gnc:make-counter-format-option
gnc:*option-section-counters* format-label key
(string-append key "b") format-description ""))))
;; Make counter and format option for each defined counter
counter-types))
(gnc-register-kvp-option-generator QOF-ID-BOOK-SCM book-options-generator)

View File

@ -0,0 +1,572 @@
/********************************************************************\
* gnc-option-date.cpp -- Relative Dates for options *
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
* *
* 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 "gnc-option-date.hpp"
#include <array>
#include <gnc-datetime.hpp>
#include <iostream>
#include <cassert>
#include <algorithm>
extern "C"
{
#include <gnc-accounting-period.h>
}
#define N_(string) string //So that xgettext will find it
enum RelativeDateType
{
ABSOLUTE,
LAST,
NEXT,
START,
END
};
enum RelativeDateOffset
{
NONE,
WEEK,
MONTH,
QUARTER,
THREE,
SIX,
YEAR
};
struct GncRelativeDate
{
RelativeDatePeriod m_period;
RelativeDateType m_type;
RelativeDateOffset m_offset;
const char* m_storage;
const char* m_display;
const char* m_description;
};
/* The fixed values and strings for date periods. Accessor functions will use
* the RelativeDatePeriod as an index so any changes need to be reflected in the
* RelativeDatePeriod enum class in gnc-option-date.hpp and vice-versa.
*
* The double curly braces are actually correct and required for a std::array
* initializer list.
*/
static const std::array<GncRelativeDate, 31> reldates
{{
{
RelativeDatePeriod::TODAY,
RelativeDateType::LAST,
RelativeDateOffset::NONE,
"today",
N_("Today"),
N_("The current date.")
},
{
RelativeDatePeriod::ONE_WEEK_AGO,
RelativeDateType::LAST,
RelativeDateOffset::WEEK,
"one-week-ago",
N_("One Week Ago"),
N_("One Week Ago.")
},
{
RelativeDatePeriod::ONE_WEEK_AHEAD,
RelativeDateType::NEXT,
RelativeDateOffset::WEEK,
"one-week-ahead",
N_("One Week Ahead"),
N_("One Week Ahead.")
},
{
RelativeDatePeriod::ONE_MONTH_AGO,
RelativeDateType::LAST,
RelativeDateOffset::MONTH,
"one-month-ago",
N_("One Month Ago"),
N_("One Month Ago.")
},
{
RelativeDatePeriod::ONE_MONTH_AHEAD,
RelativeDateType::NEXT,
RelativeDateOffset::MONTH,
"one-month-ahead",
N_("One Month Ahead"),
N_("One Month Ahead.")
},
{
RelativeDatePeriod::THREE_MONTHS_AGO,
RelativeDateType::LAST,
RelativeDateOffset::THREE,
"three-months-ago",
N_("Three Months Ago"),
N_("Three Months Ago.")
},
{
RelativeDatePeriod::THREE_MONTHS_AHEAD,
RelativeDateType::NEXT,
RelativeDateOffset::THREE,
"three-months-ahead",
N_("Three Months Ahead"),
N_("Three Months Ahead.")
},
{
RelativeDatePeriod::SIX_MONTHS_AGO,
RelativeDateType::LAST,
RelativeDateOffset::SIX,
"six-months-ago",
N_("Six Months Ago"),
N_("Six Months Ago.")
},
{
RelativeDatePeriod::SIX_MONTHS_AHEAD,
RelativeDateType::NEXT,
RelativeDateOffset::SIX,
"six-months-ahead",
N_("Six Months Ahead"),
N_("Six Months Ahead.")
},
{
RelativeDatePeriod::ONE_YEAR_AGO,
RelativeDateType::LAST,
RelativeDateOffset::YEAR,
"one-year-ago",
N_("One Year Ago"),
N_("One Year Ago.")
},
{
RelativeDatePeriod::ONE_YEAR_AHEAD,
RelativeDateType::NEXT,
RelativeDateOffset::YEAR,
"one-year-ahead",
N_("One Year Ahead"),
N_("One Year Ahead.")
},
{
RelativeDatePeriod::START_THIS_MONTH,
RelativeDateType::START,
RelativeDateOffset::MONTH,
"start-this-month",
N_("Start of this month"),
N_("First day of the current month.")
},
{
RelativeDatePeriod::END_THIS_MONTH,
RelativeDateType::END,
RelativeDateOffset::MONTH,
"end-this-month",
N_("End of this month"),
N_("Last day of the current month.")
},
{
RelativeDatePeriod::START_PREV_MONTH,
RelativeDateType::START,
RelativeDateOffset::MONTH,
"start-prev-month",
N_("Start of previous month"),
N_("First day of the previous month.")
},
{
RelativeDatePeriod::END_PREV_MONTH,
RelativeDateType::END,
RelativeDateOffset::MONTH,
"end-prev-month",
N_("End of previous month"),
N_("Last day of previous month.")
},
{
RelativeDatePeriod::START_NEXT_MONTH,
RelativeDateType::START,
RelativeDateOffset::MONTH,
"start-next-month",
N_("Start of next month"),
N_("First day of the next month.")
},
{
RelativeDatePeriod::END_NEXT_MONTH,
RelativeDateType::END,
RelativeDateOffset::MONTH,
"end-next-month",
N_("End of next month"),
N_("Last day of next month.")
},
{
RelativeDatePeriod::START_CURRENT_QUARTER,
RelativeDateType::START,
RelativeDateOffset::QUARTER,
"start-current-quarter",
N_("Start of current quarter"),
N_("First day of the current quarterly accounting period.")
},
{
RelativeDatePeriod::END_CURRENT_QUARTER,
RelativeDateType::END,
RelativeDateOffset::QUARTER,
"end-current-quarter",
N_("End of current quarter"),
N_("Last day of the current quarterly accounting period.")
},
{
RelativeDatePeriod::START_PREV_QUARTER,
RelativeDateType::START,
RelativeDateOffset::QUARTER,
"start-prev-quarter",
N_("Start of previous quarter"),
N_("First day of the previous quarterly accounting period.")
},
{
RelativeDatePeriod::END_PREV_QUARTER,
RelativeDateType::END,
RelativeDateOffset::QUARTER,
"end-prev-quarter",
N_("End of previous quarter"),
N_("Last day of previous quarterly accounting period.")
},
{
RelativeDatePeriod::START_NEXT_QUARTER,
RelativeDateType::START,
RelativeDateOffset::QUARTER,
"start-next-quarter",
N_("Start of next quarter"),
N_("First day of the next quarterly accounting period.")
},
{
RelativeDatePeriod::END_NEXT_QUARTER,
RelativeDateType::END,
RelativeDateOffset::QUARTER,
"end-next-quarter",
N_("End of next quarter"),
N_("Last day of next quarterly accounting period.")
},
{
RelativeDatePeriod::START_CAL_YEAR,
RelativeDateType::START,
RelativeDateOffset::YEAR,
"start-cal-year",
N_("Start of this year"),
N_("First day of the current calendar year.")
},
{
RelativeDatePeriod::END_CAL_YEAR,
RelativeDateType::END,
RelativeDateOffset::YEAR,
"end-cal-year",
N_("End of this year"),
N_("Last day of the current calendar year.")
},
{
RelativeDatePeriod::START_PREV_YEAR,
RelativeDateType::START,
RelativeDateOffset::YEAR,
"start-prev-year",
N_("Start of previous year"),
N_("First day of the previous calendar year.")
},
{
RelativeDatePeriod::END_PREV_YEAR,
RelativeDateType::END,
RelativeDateOffset::YEAR,
"end-prev-year",
N_("End of previous year"),
N_("Last day of the previous calendar year.")
},
{
RelativeDatePeriod::START_NEXT_YEAR,
RelativeDateType::START,
RelativeDateOffset::YEAR,
"start-next-year",
N_("Start of next year"),
N_("First day of the next calendar year.")
},
{
RelativeDatePeriod::END_NEXT_YEAR,
RelativeDateType::END,
RelativeDateOffset::YEAR,
"end-next-year",
N_("End of next year"),
N_("Last day of the next calendar year.")
},
{
RelativeDatePeriod::START_ACCOUNTING_PERIOD,
RelativeDateType::START,
RelativeDateOffset::YEAR,
"start-prev-fin-year",
N_("Start of accounting period"),
N_("First day of the accounting period, as set in the global preferences.")
},
{
RelativeDatePeriod::END_ACCOUNTING_PERIOD,
RelativeDateType::END,
RelativeDateOffset::YEAR,
"end-prev-fin-year",
N_("End of accounting period"),
N_("Last day of the accounting period, as set in the global preferences.")
}
}};
static const GncRelativeDate&
checked_reldate(RelativeDatePeriod per)
{
assert (reldates[static_cast<int>(per)].m_period == per);
return reldates[static_cast<int>(per)];
}
bool
gnc_relative_date_is_single(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return false;
auto reldate = checked_reldate(per);
return reldate.m_type == RelativeDateType::LAST ||
reldate.m_type == RelativeDateType::NEXT;
}
bool
gnc_relative_date_is_starting(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return false;
return checked_reldate(per).m_type == RelativeDateType::START;
}
bool
gnc_relative_date_is_ending(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return false;
return checked_reldate(per).m_type == RelativeDateType::END;
}
const char*
gnc_relative_date_storage_string(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return nullptr;
return checked_reldate(per).m_storage;
}
const char*
gnc_relative_date_display_string(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return nullptr;
return checked_reldate(per).m_display;
}
const char*
gnc_relative_date_description(RelativeDatePeriod per)
{
if (per == RelativeDatePeriod::ABSOLUTE)
return nullptr;
return checked_reldate(per).m_description;
}
RelativeDatePeriod
gnc_relative_date_from_storage_string(const char* str)
{
auto per = std::find_if(reldates.begin(), reldates.end(),
[str](auto rel) -> bool
{
return strcmp(str, rel.m_storage) == 0;
});
return per != reldates.end() ? per->m_period : RelativeDatePeriod::ABSOLUTE;
}
static bool
reldate_is_prev(RelativeDatePeriod per)
{
auto rdate{checked_reldate(per)};
return per == RelativeDatePeriod::START_PREV_YEAR ||
per == RelativeDatePeriod::END_PREV_YEAR ||
per == RelativeDatePeriod::START_PREV_QUARTER ||
per == RelativeDatePeriod::END_PREV_QUARTER ||
per == RelativeDatePeriod::START_PREV_MONTH ||
per == RelativeDatePeriod::END_PREV_MONTH ||
rdate.m_type == LAST;
}
static bool
reldate_is_next(RelativeDatePeriod per)
{
auto rdate{checked_reldate(per)};
return per == RelativeDatePeriod::START_NEXT_YEAR ||
per == RelativeDatePeriod::END_NEXT_YEAR ||
per == RelativeDatePeriod::START_NEXT_QUARTER ||
per == RelativeDatePeriod::END_NEXT_QUARTER ||
per == RelativeDatePeriod::START_NEXT_MONTH ||
per == RelativeDatePeriod::END_NEXT_MONTH ||
rdate.m_type == NEXT;
}
static RelativeDateOffset
reldate_offset(RelativeDatePeriod per)
{
return checked_reldate(per).m_offset;
}
static constexpr int days_in_month[12]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* Normalize the modified struct tm computed in gnc_relative_date_to_time64
* before setting the time and perhaps beginning/end of the month. Using the
* gnc_date API would involve multiple conversions to and from struct tm.
*/
static void
normalize_reldate_tm(struct tm& now)
{
auto factor{abs(now.tm_mon) / 12};
now.tm_mon /= factor > 0 ? factor : 1;
now.tm_year += now.tm_mon < 0 ? -factor: factor;
auto days = [](auto month, int year)
{
auto mon{month % 12 + (month < 0 ? 12 : 0)};
auto num_days{days_in_month[mon]};
//Leap year check.
if (mon == 1 && year % 4 == 0 && !(year % 100 == 0 && (year + 1900) % 400 != 0))
++num_days;
return num_days;
};
while (now.tm_mday < 1)
now.tm_mday += days(--now.tm_mon, now.tm_year);
while (now.tm_mday > days(now.tm_mon, now.tm_year))
now.tm_mday -= days(now.tm_mon++, now.tm_year);
while (now.tm_mon < 0)
{
now.tm_mon += 12;
--now.tm_year;
}
while (now.tm_mon > 11)
{
now.tm_mon -= 12;
++now.tm_year;
}
/* This would happen only if we moved from Feb 29 in a leap year while
* adjusting the months so we don't need to worry about adjusting the year
* again.
*/
if (now.tm_mday > days_in_month[now.tm_mon])
now.tm_mday -= days_in_month[now.tm_mon++];
}
static void
reldate_set_day_and_time(struct tm& now, RelativeDateType type)
{
if (type == RelativeDateType::START)
{
gnc_tm_set_day_start(&now);
now.tm_mday = 1;
}
else if (type == RelativeDateType::END)
{
now.tm_mday = gnc_date_get_last_mday(now.tm_mon, now.tm_year + 1900);
gnc_tm_set_day_end(&now);
}
// Do nothing for LAST and NEXT.
};
time64
gnc_relative_date_to_time64(RelativeDatePeriod period)
{
if (period == RelativeDatePeriod::TODAY)
return static_cast<time64>(GncDateTime());
if (period == RelativeDatePeriod::START_ACCOUNTING_PERIOD)
return gnc_accounting_period_fiscal_start();
if (period == RelativeDatePeriod::END_ACCOUNTING_PERIOD)
return gnc_accounting_period_fiscal_end();
GncDateTime now_t;
if (period == RelativeDatePeriod::TODAY)
return static_cast<time64>(now_t);
auto now{static_cast<tm>(now_t)};
auto acct_per{static_cast<tm>(GncDateTime(gnc_accounting_period_fiscal_start()))};
if (acct_per.tm_mon == now.tm_mon && acct_per.tm_mday == now.tm_mday)
{
//No set accounting period, use the calendar year
acct_per.tm_mon = 0;
acct_per.tm_mday = 0;
}
switch(reldate_offset(period))
{
case RelativeDateOffset::NONE:
// Report on today so nothing to do
break;
case RelativeDateOffset::YEAR:
if (reldate_is_prev(period))
--now.tm_year;
else if (reldate_is_next(period))
++now.tm_year;
if (gnc_relative_date_is_starting(period))
now.tm_mon = 0;
else if (gnc_relative_date_is_ending(period))
now.tm_mon = 11;
break;
case RelativeDateOffset::SIX:
if (reldate_is_prev(period))
now.tm_mon -= 6;
else if (reldate_is_next(period))
now.tm_mon += 6;
break;
case RelativeDateOffset::QUARTER:
{
auto delta = (now.tm_mon > acct_per.tm_mon ?
now.tm_mon - acct_per.tm_mon :
acct_per.tm_mon - now.tm_mon) % 3;
now.tm_mon = now.tm_mon - delta;
}
[[fallthrough]];
case RelativeDateOffset::THREE:
if (reldate_is_prev(period))
now.tm_mon -= 3;
else if (reldate_is_next(period))
now.tm_mon += 3;
if (gnc_relative_date_is_ending(period))
now.tm_mon += 2;
break;
case RelativeDateOffset::MONTH:
if (reldate_is_prev(period))
--now.tm_mon;
else if (reldate_is_next(period))
++now.tm_mon;
break;
case RelativeDateOffset::WEEK:
if (reldate_is_prev(period))
now.tm_mday -= 7;
else if (reldate_is_next(period))
now.tm_mday += 7;
}
normalize_reldate_tm(now);
reldate_set_day_and_time(now, checked_reldate(period).m_type);
return static_cast<time64>(GncDateTime(now));
}
std::ostream&
operator<<(std::ostream& ostr, RelativeDatePeriod per)
{
ostr << "'reldate . " << gnc_relative_date_display_string(per);
return ostr;
}

View File

@ -0,0 +1,189 @@
/********************************************************************\
* gnc-option-date.hpp -- Relative dates for options *
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Options
@{ */
/** @file gnc-option-date.hpp
@brief Relative date enumeration and manipulation functions.
@author Copyright 2019-2021 John Ralls <jralls@ceridwen.us>
*/
#ifndef GNC_OPTION_DATE_HPP_
#define GNC_OPTION_DATE_HPP_
extern "C"
{
#include <gnc-date.h>
}
#include <vector>
#include <iostream>
/**
* Reporting periods relative to the current date.
*
* The original design allowed custom RelativeDatePeriods, but that facility is
* unused so we'll go with compiled-in enums.
*/
enum class RelativeDatePeriod : int
{
ABSOLUTE = -1,
TODAY,
ONE_WEEK_AGO,
ONE_WEEK_AHEAD,
ONE_MONTH_AGO,
ONE_MONTH_AHEAD,
THREE_MONTHS_AGO,
THREE_MONTHS_AHEAD,
SIX_MONTHS_AGO,
SIX_MONTHS_AHEAD,
ONE_YEAR_AGO,
ONE_YEAR_AHEAD,
START_THIS_MONTH,
END_THIS_MONTH,
START_PREV_MONTH,
END_PREV_MONTH,
START_NEXT_MONTH,
END_NEXT_MONTH,
START_CURRENT_QUARTER,
END_CURRENT_QUARTER,
START_PREV_QUARTER,
END_PREV_QUARTER,
START_NEXT_QUARTER,
END_NEXT_QUARTER,
START_CAL_YEAR,
END_CAL_YEAR,
START_PREV_YEAR,
END_PREV_YEAR,
START_NEXT_YEAR,
END_NEXT_YEAR,
START_ACCOUNTING_PERIOD,
END_ACCOUNTING_PERIOD,
};
constexpr unsigned relative_date_periods =
static_cast<unsigned>(RelativeDatePeriod::END_ACCOUNTING_PERIOD) + 2;
using RelativeDatePeriodVec = std::vector<RelativeDatePeriod>;
/**
* Report whether the relative date represents a period offset to today's date
* rather than the beginning or end of a date range. For example ONE_MONTH_AGO
* will be made concrete as the same day as today in the previous month.
*
* @param period The Relative Date Period to check.
* @return true if the date is stand-alone.
*/
bool gnc_relative_date_is_single(RelativeDatePeriod);
/**
* Report whether the relative date represents the beginning of a date
* range. For example START_LAST_MONTH is the beginning of a range.
*
* @param period The Relative Date Period to check.
* @return true if the date is the beginning of a date range
*/
bool gnc_relative_date_is_starting(RelativeDatePeriod);
/**
* Report whether the relative date represents the end of a date range. For
* example END_LAST_MONTH is the end of a range.
*
* @param period The Relative Date Period to check.
* @return true if the date is the end of a date range.
*/
bool gnc_relative_date_is_ending(RelativeDatePeriod);
/**
* Provide the string representation of a relative date for persisting the
* value. This string is not localizable.
*
* @param period The relative date period.
* @return A constant string or nullptr if the period is ABSOLUTE. The string's
* lifetime will be that of the Relative Date Period. It must not be freed and
* should be copied if the period might be destroyed before the using code is
* finished.
*/
const char* gnc_relative_date_storage_string(RelativeDatePeriod);
/**
* Provide the string representation of a relative date for displaying
* value to a user. This string is localizable.
*
* @param period The relative date period.
* @return A constant string or nullptr if the period is ABSOLUTE. The string's
* lifetime will be that of the Relative Date Period. It must not be freed and
* should be copied if the period might be destroyed before the using code is
* finished.
*/
const char* gnc_relative_date_display_string(RelativeDatePeriod);
/**
* Provide the description of a relative date. This string is localizable.
*
* @param period The relative date period.
* @return A constant string or nullptr if the period is ABSOLUTE. The string's
* lifetime will be that of the Relative Date Period. It must not be freed and
* should be copied if the period might be destroyed before the using code is
* finished.
*/
const char* gnc_relative_date_description(RelativeDatePeriod);
/**
* Convert a relative date storage string back to a RelativeDatePeriod value.
*
* @param A string representation obtained from
* gnc_relative_date_storage_string.
* @return A RelativeDatePeriod value.
*/
RelativeDatePeriod gnc_relative_date_from_storage_string(const char*);
/**
* Convert a RelativeDatePeriod value to a concrete time64 by applying the value
* to the current time.
* For example if it is now 3:15:42 PM local time 3 June, calling this with a
* period RelativeDatePeriod::ONE_WEEK_AHEAD will return a time64 representing
* 3:15:42 PM local time 10 June of this year. Times for START periods are
* changed to midnight local time and for END periods to 23:59:59 local time so
* for example if the period is instead RelativeDatePeriod::START_THIS_MONTH the
* time64 will represent 00:00:00 1 June and if it is
* RelativeDatePeriod::END_THIS_MONTH the time64 will be for 23:59:59 30 June,
* both in the current time zone.
*
* @param period The relative date period to use to calculate the concrete date.
* @return a time64.
*/
time64 gnc_relative_date_to_time64(RelativeDatePeriod);
/**
* Add the display string to the provided std::ostream.
*
* @param stream the std::ostream to which to write the period value
* @param period the period value to write
* @return A reference to stream so that the operator can be chained.
*/
std::ostream& operator<<(std::ostream&, const RelativeDatePeriod);
#endif //GNC_OPTION_DATE_HPP_
/** @}
@} */

View File

@ -0,0 +1,986 @@
/********************************************************************\
* gnc-option-impl.cpp -- Application options system *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 "options.h"
#include "gnc-option-impl.hpp"
#include <gnc-datetime.hpp>
#include <guid.hpp>
#include <cassert>
#include <sstream>
#include <numeric>
extern "C"
{
#include "gnc-accounting-period.h"
#include "gnc-ui-util.h"
}
static const QofLogModule log_module{"gnc.options"};
const std::string GncOptionMultichoiceValue::c_empty_string{""};
const std::string GncOptionMultichoiceValue::c_list_string{"multiple values"};
using GncItem = std::pair<QofIdTypeConst, GncGUID>;
static GncItem
make_gnc_item(const QofInstance* inst)
{
if (!inst)
return std::make_pair<QofIdTypeConst, GncGUID>("", guid_new_return());
auto type{qof_collection_get_type(qof_instance_get_collection(inst))};
auto guid{qof_instance_get_guid(inst)};
return std::make_pair(std::move(type), std::move(*const_cast<GncGUID*>(guid)));
}
static const QofInstance*
qof_instance_from_gnc_item(const GncItem& item)
{
auto [type, guid] = item;
auto book{gnc_get_current_book()};
auto coll{qof_book_get_collection(book, type)};
return static_cast<QofInstance*>(qof_collection_lookup_entity(coll, &guid));
}
static bool
operator!=(const GncItem& left, const GncItem& right)
{
auto [ltype, lguid]{left};
auto [rtype, rguid]{right};
return strcmp(rtype, ltype) && !guid_equal(&rguid, &lguid);
}
GncOptionQofInstanceValue::GncOptionQofInstanceValue(
const char* section, const char* name,
const char* key, const char* doc_string,
const QofInstance* value, GncOptionUIType ui_type) :
OptionClassifier{section, name, key, doc_string},
m_ui_type(ui_type), m_value{},
m_default_value{} {
m_value = make_gnc_item(value);
m_default_value = make_gnc_item(value);
}
GncOptionQofInstanceValue::GncOptionQofInstanceValue(const GncOptionQofInstanceValue& from) :
OptionClassifier{from.m_section, from.m_name, from.m_sort_tag,
from.m_doc_string},
m_ui_type(from.get_ui_type()), m_value{from.get_item()},
m_default_value{from.get_default_item()}
{
}
void
GncOptionQofInstanceValue::set_value(const QofInstance* new_value)
{
m_value = make_gnc_item(new_value);
}
void
GncOptionQofInstanceValue::set_default_value(const QofInstance *new_value)
{
m_value = m_default_value = make_gnc_item(new_value);
}
const QofInstance*
GncOptionQofInstanceValue::get_value() const
{
return qof_instance_from_gnc_item(m_value);
}
const QofInstance*
GncOptionQofInstanceValue::get_default_value() const
{
return qof_instance_from_gnc_item(m_default_value);
}
void
GncOptionQofInstanceValue::reset_default_value()
{
m_value = m_default_value;
}
bool
GncOptionQofInstanceValue::is_changed() const noexcept
{
return m_value != m_default_value;
}
bool
GncOptionQofInstanceValue::deserialize(const std::string& str) noexcept
{
QofInstance* inst{};
// Commodities are often serialized as Namespace::Mnemonic or just Mnemonic
try {
auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
inst = qof_instance_from_guid(&guid, m_ui_type);
if (inst)
{
m_value = make_gnc_item(inst);
return true;
}
}
catch (const gnc::guid_syntax_exception& err)
{
PWARN("Failed to convert %s to a GUID", str.c_str());
}
return false;
}
std::string
GncOptionQofInstanceValue::serialize() const noexcept
{
auto inst{get_value()};
std::string retval;
if (GNC_IS_COMMODITY(inst))
{
auto commodity{GNC_COMMODITY(inst)};
if (!gnc_commodity_is_currency(commodity))
{
auto name_space{gnc_commodity_get_namespace(GNC_COMMODITY(inst))};
if (name_space && *name_space != '\0')
{
retval = name_space;
retval += ":";
}
}
retval += gnc_commodity_get_mnemonic(GNC_COMMODITY(inst));
return retval;
}
else
{
gnc::GUID guid{m_value.second};
retval = guid.to_string();
}
return retval;
}
static gnc_commodity*
gnc_commodity_from_namespace_and_mnemonic(std::string_view name_space,
std::string_view mnemonic)
{
auto book{gnc_get_current_book()};
auto table = gnc_commodity_table_get_table(book);
return gnc_commodity_table_lookup(table, name_space.data(),
mnemonic.data());
}
gnc_commodity*
GncOptionCommodityValue::get_value() const
{
return gnc_commodity_from_namespace_and_mnemonic(m_namespace, m_mnemonic);
}
gnc_commodity*
GncOptionCommodityValue::get_default_value() const
{
return gnc_commodity_from_namespace_and_mnemonic(m_default_namespace,
m_default_mnemonic);
}
void
GncOptionCommodityValue::set_value(gnc_commodity* value)
{
if (!validate(value))
throw std::invalid_argument("Value not a currency when required or not a commodity. Value not set.");
m_mnemonic = gnc_commodity_get_mnemonic(value);
m_namespace = gnc_commodity_get_namespace(value);
}
void
GncOptionCommodityValue::set_default_value(gnc_commodity* value)
{
if (!validate(value))
throw std::invalid_argument("Value not a currency when required or not a commodity. Value not set.");
m_mnemonic = m_default_mnemonic = gnc_commodity_get_mnemonic(value);
m_namespace = m_default_namespace = gnc_commodity_get_namespace(value);
}
void
GncOptionCommodityValue::reset_default_value()
{
m_mnemonic = m_default_mnemonic;
m_namespace = m_default_namespace;
}
bool
GncOptionCommodityValue::is_changed() const noexcept
{
return m_namespace == m_default_namespace && m_mnemonic == m_default_mnemonic;
}
bool
GncOptionCommodityValue::validate(gnc_commodity* comm) const noexcept
{
if (!GNC_IS_COMMODITY(comm))
return false;
if (m_is_currency && !gnc_commodity_is_currency(comm))
return false;
return true;
}
std::string
GncOptionCommodityValue::serialize() const noexcept
{
if (m_is_currency)
return m_mnemonic;
else
return m_namespace + ":" + m_mnemonic;
}
bool
GncOptionCommodityValue::deserialize(const std::string& str) noexcept
{
auto sep{str.find(":")};
gnc_commodity* comm{};
std::string mnemonic, name_space;
if (sep != std::string::npos)
{
name_space = str.substr(0, sep);
mnemonic = str.substr(sep + 1, -1);
}
else
{
name_space = "CURRENCY";
mnemonic = str;
}
comm = gnc_commodity_from_namespace_and_mnemonic(name_space, mnemonic);
if (!validate(comm))
return false;
m_namespace = std::move(name_space);
m_mnemonic = std::move(mnemonic);
return true;
}
bool
GncOptionAccountListValue::validate(const GncOptionAccountList& values) const
{
if (values.empty())
return true;
if ((get_ui_type() == GncOptionUIType::ACCOUNT_SEL || !m_multiselect) &&
values.size() != 1)
{
std::cerr << "GncOptionAccountListValue::validate: Multiple values for a non-multiselect option." << std::endl;
return false;
}
if (m_allowed.empty())
return true;
auto book{gnc_get_current_book()};
for(auto& guid : values)
{
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(xaccAccountLookup(&guid, book))) == m_allowed.end())
{
std::cerr << "GncOptionAccountListValue::validate: Account " << gnc::GUID(guid).to_string() << " is not of an allowed type" << std::endl;
return false; }
}
return true;
}
GncOptionAccountList
GncOptionAccountListValue::get_value() const
{
return !m_value.empty() ? m_value : get_default_value();
}
GncOptionAccountList
GncOptionAccountListValue::get_default_value() const
{
if (!m_default_value.empty())
return m_default_value;
/* If no default has been set and there's an allowed set then find the first
* account that matches one of the allowed account types.
*/
GncOptionAccountList retval{};
if (m_allowed.empty())
return retval;
auto root{gnc_get_current_root_account()};
auto account_list{gnc_account_get_descendants_sorted(root)};
if (!account_list)
return retval;
auto book{gnc_get_current_book()};
for (auto node = account_list; node; node = g_list_next (node))
{
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(GNC_ACCOUNT(node->data))) != m_allowed.end())
{
retval.push_back(*qof_entity_get_guid(GNC_ACCOUNT(node->data)));
break;
}
}
g_list_free(account_list);
return retval;
}
static bool
operator==(const GncGUID& l, const GncGUID& r)
{
return guid_equal(&l, &r);
}
bool
GncOptionAccountListValue::is_changed() const noexcept
{
return m_value != m_default_value;
}
/**
* Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
* gnc_account_sel_set_acct_filters copies the list so the intermediary caller
* is responsible for freeing the list.
*
* @return an allocated GList* or nullptr if the list is empty.
*/
GList*
GncOptionAccountListValue::account_type_list() const noexcept
{
if (m_allowed.empty())
return nullptr;
GList* retval{nullptr};
for (auto type : m_allowed)
retval = g_list_prepend(retval, GINT_TO_POINTER(type));
return g_list_reverse(retval);
}
bool
GncOptionAccountSelValue::validate(const Account* value) const
{
if (m_allowed.empty() || !value)
return true;
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(value)) == m_allowed.end())
return false;
return true;
}
const Account*
GncOptionAccountSelValue::get_value() const
{
auto book{gnc_get_current_book()};
return guid_equal(guid_null(), &m_value) ? get_default_value() :
xaccAccountLookup(&m_value, book);
}
const Account*
GncOptionAccountSelValue::get_default_value() const
{
if (!guid_equal(guid_null(), &m_default_value))
{
auto book{gnc_get_current_book()};
return xaccAccountLookup(&m_default_value, book);
}
/* If no default has been set and there's an allowed set then find the first
* account that matches one of the allowed account types.
*/
if (m_allowed.empty())
return nullptr;
const Account* retval{nullptr};
auto root{gnc_get_current_root_account()};
auto account_list{gnc_account_get_descendants_sorted(root)};
if (!account_list)
return nullptr;
for (auto node = account_list; node; node = g_list_next (node))
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(GNC_ACCOUNT(node->data))) != m_allowed.end())
{
retval = GNC_ACCOUNT(node->data);
break;
}
g_list_free(account_list);
return retval;
}
/**
* Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
* gnc_account_sel_set_acct_filters copies the list so the intermediary caller
* is responsible for freeing the list.
*
* @return an allocated GList* or nullptr if the list is empty.
*/
GList*
GncOptionAccountSelValue::account_type_list() const noexcept
{
if (m_allowed.empty())
return nullptr;
GList* retval{nullptr};
for (auto type : m_allowed)
retval = g_list_prepend(retval, GINT_TO_POINTER(type));
return g_list_reverse(retval);
}
bool
GncOptionDateValue::validate(RelativeDatePeriod value) {
if (m_period_set.empty())
return true; // No restrictions
if (std::find(m_period_set.begin(), m_period_set.end(),
value) != m_period_set.end())
return true;
return false;
}
time64
GncOptionDateValue::get_value() const noexcept
{
if (m_period == RelativeDatePeriod::ABSOLUTE)
return m_date;
return gnc_relative_date_to_time64(m_period);
}
time64
GncOptionDateValue::get_default_value() const noexcept
{
if (m_default_period == RelativeDatePeriod::ABSOLUTE)
return m_default_date;
return gnc_relative_date_to_time64(m_default_period);
}
/* Use asserts for pre- and post-conditions to deliberately crash if they're not
* met as the program design should prevent that from happening.
*/
size_t
GncOptionDateValue::get_period_index() const noexcept
{
assert (m_period != RelativeDatePeriod::ABSOLUTE);
assert(!m_period_set.empty());
auto item{std::find(m_period_set.begin(), m_period_set.end(), m_period)};
assert(item != m_period_set.end());
return item - m_period_set.begin();
}
size_t
GncOptionDateValue::get_default_period_index() const noexcept
{
assert(m_period != RelativeDatePeriod::ABSOLUTE);
assert(!m_period_set.empty());
auto item{std::find(m_period_set.begin(), m_period_set.end(),
m_default_period)};
assert (item != m_period_set.end());
return item - m_period_set.begin();
}
void
GncOptionDateValue::set_value(size_t index) noexcept
{
assert(!m_period_set.empty());
assert(index < m_period_set.size());
m_date = INT64_MAX;
m_period = m_period_set[index];
}
size_t
GncOptionDateValue::permissible_value_index(const char* key) const noexcept
{
auto index = std::find_if(m_period_set.begin(), m_period_set.end(),
[key](auto period) -> bool {
return strcmp(gnc_relative_date_display_string(period),
key) == 0;
});
return index != m_period_set.end() ? index - m_period_set.begin() : 0;
}
static const char* date_type_str[] {"absolute", "relative"};
std::ostream&
GncOptionDateValue::out_stream(std::ostream& oss) const noexcept
{
if (m_period == RelativeDatePeriod::ABSOLUTE)
oss << date_type_str[0] << " . " << m_date;
else
oss << date_type_str[1] << " . " <<
gnc_relative_date_storage_string(m_period);
return oss;
}
std::istream&
GncOptionDateValue::in_stream(std::istream& iss)
{
char type_str[10]; //The length of both "absolute" and "relative" plus 1.
iss.getline(type_str, sizeof(type_str), '.');
if(!iss)
throw std::invalid_argument("Date Type separator missing");
/* strcmp is safe, istream::getline null terminates the buffer. */
if (strcmp(type_str, "absolute ") == 0)
{
time64 time;
iss >> time;
set_value(time);
if (iss.get() != ')')
iss.unget();
}
else if (strcmp(type_str, "relative ") == 0)
{
std::string period_str;
iss >> period_str;
if (period_str.back() == ')')
period_str.pop_back();
auto period = gnc_relative_date_from_storage_string(period_str.c_str());
if (period == RelativeDatePeriod::ABSOLUTE)
{
std::string err{"Unknown period string in date option: '"};
err += period_str;
err += "'";
throw std::invalid_argument(err);
}
set_value(period);
}
else
{
std::string err{"Unknown date type string in date option: '"};
err += type_str;
err += "'";
throw std::invalid_argument{err};
}
return iss;
}
QofInstance*
qof_instance_from_guid(GncGUID* guid, GncOptionUIType type)
{
QofIdType qof_type;
switch(type)
{
case GncOptionUIType::BUDGET:
qof_type = "Budget";
break;
case GncOptionUIType::JOB:
qof_type = "gncJob";
break;
case GncOptionUIType::CUSTOMER:
qof_type = "gncCustomer";
break;
case GncOptionUIType::VENDOR:
qof_type = "gncVendor";
break;
case GncOptionUIType::EMPLOYEE:
qof_type = "gncEmployee";
break;
case GncOptionUIType::INVOICE:
qof_type = "gncInvoice";
break;
case GncOptionUIType::TAX_TABLE:
qof_type = "gncTaxtable";
break;
case GncOptionUIType::ACCOUNT_LIST:
case GncOptionUIType::ACCOUNT_SEL:
default:
qof_type = "Account";
break;
}
auto book{gnc_get_current_book()};
auto col{qof_book_get_collection(book, qof_type)};
return QOF_INSTANCE(qof_collection_lookup_entity(col, guid));
}
QofInstance*
qof_instance_from_string(const std::string& str, GncOptionUIType type)
{
QofInstance* retval{nullptr};
try {
auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
retval = qof_instance_from_guid(&guid, type);
}
catch (const gnc::guid_syntax_exception& err)
{
PWARN("Failed to convert %s to a GUID", str.c_str());
}
return retval;
}
std::string
qof_instance_to_string(const QofInstance* inst)
{
std::string retval;
gnc::GUID guid{*qof_instance_get_guid(inst)};
retval = guid.to_string();
return retval;
}
template <typename ValueType> void
GncOptionValue<ValueType>::set_value(ValueType new_value)
{
m_value = new_value;
}
template <typename ValueType> void
GncOptionValue<ValueType>::set_default_value(ValueType new_value)
{
m_value = m_default_value = new_value;
}
template <typename ValueType> void
GncOptionValue<ValueType>::reset_default_value()
{
m_value = m_default_value;
}
/* Missing on purpose: QofQuery because for current usage it's serialized with
* gnc_query2scm. The future is to replace QofQuery with SQL queries so there's
* not much point to spending the time to create a std::string serialization for
* them.
*/
template <typename ValueType> std::string
GncOptionValue<ValueType>::serialize() const noexcept
{
static const std::string no_value{"No Value"};
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
return m_value ? qof_instance_to_string(m_value) : no_value;
if constexpr(std::is_same_v<ValueType, const GncOwner*>)
{
if (!m_value)
return no_value;
auto guid{qof_instance_to_string(qofOwnerGetOwner(m_value))};
auto type{qofOwnerGetType(m_value)};
std::ostringstream ostr{};
ostr << type << " " << guid;
return ostr.str();
}
if constexpr(std::is_same_v<ValueType, GncOptionReportPlacementVec>)
{
std::ostringstream ostr{};
ostr << "'(";
std::for_each(m_value.begin(), m_value.end(),
[&ostr](auto rp){
auto [id, wide, high] = rp;
ostr << "(" << id << " " << wide << " " << high << " #f) ";
});
ostr << ")";
return ostr.str();
}
else if constexpr(is_same_decayed_v<ValueType, std::string>)
return m_value;
else if constexpr(is_same_decayed_v<ValueType, bool>)
return m_value ? "True" : "False";
else if constexpr(std::is_arithmetic_v<ValueType>)
return std::to_string(m_value);
else
return "Serialization not implemented";
}
template <typename ValueType> bool
GncOptionValue<ValueType>::deserialize(const std::string& str) noexcept
{
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
set_value(qof_instance_from_string(str, get_ui_type()));
if constexpr(std::is_same_v<ValueType, const GncOwner*>)
{
std::istringstream istr{str};
std::string type, guid;
istr >> type >> guid;
auto inst{qof_instance_from_string(guid, get_ui_type())};
qofOwnerSetEntity(const_cast<GncOwner*>(m_value), inst);
}
if constexpr(std::is_same_v<ValueType, GncOptionReportPlacementVec>)
{
std::istringstream istr{str};
GncOptionReportPlacementVec rpv;
while (istr)
{
uint32_t id, wide, high;
istr >> id >> wide >> high;
rpv.emplace_back(id, wide, high);
}
set_value(rpv);
}
else if constexpr(is_same_decayed_v<ValueType, std::string>)
set_value(str);
else if constexpr(is_same_decayed_v<ValueType, bool>)
set_value(str == "True");
else if constexpr(is_same_decayed_v<ValueType, int>)
set_value(stoi(str));
else if constexpr(is_same_decayed_v<ValueType, int64_t>)
set_value(stoll(str));
else if constexpr(is_same_decayed_v<ValueType, double>)
set_value(stod(str));
else
return false;
return true;
}
std::string
GncOptionAccountListValue::serialize() const noexcept
{
static const std::string no_value{"No Value"};
std::string retval;
bool first = true;
if (m_value.empty())
return no_value;
for (auto val : m_value)
{
if (!first)
retval += " ";
first = false;
retval += guid_to_string(&val);
}
return retval;
}
bool
GncOptionAccountListValue::deserialize(const std::string& str) noexcept
{
if (str.empty() || str.size() < GUID_ENCODING_LENGTH)
return false;
m_value.clear();
m_value.reserve(str.size() / GUID_ENCODING_LENGTH);
bool first = true;
size_t pos{};
while (pos + GUID_ENCODING_LENGTH < str.size())
{
if (!first)
++pos;
first = false;
GncGUID guid{};
string_to_guid(str.substr(pos, pos + GUID_ENCODING_LENGTH).c_str(), &guid);
m_value.push_back(guid);
pos += GUID_ENCODING_LENGTH;
}
return true;
}
std::string
GncOptionAccountSelValue::serialize() const noexcept
{
static const std::string no_value{"No Value"};
return guid_equal(guid_null(), &m_value) ? no_value : guid_to_string(&m_value);
}
bool
GncOptionAccountSelValue::deserialize(const std::string& str) noexcept
{
set_value(reinterpret_cast<Account*>(qof_instance_from_string(str, get_ui_type())));
return true;
}
std::string
GncOptionMultichoiceValue::serialize() const noexcept
{
static const std::string no_value{"No Value"};
std::string retval;
bool first = true;
if (m_value.empty())
return no_value;
for (auto index : m_value)
{
if (!first)
retval += " ";
first = false;
retval += std::get<0>(m_choices[index]);
}
return retval;
}
bool
GncOptionMultichoiceValue::deserialize(const std::string& str) noexcept
{
static const auto size_t_max = std::numeric_limits<std::size_t>::max();
if (str.empty())
return false;
size_t pos{};
while (pos < str.size())
{
auto endpos{str.find(' ', pos)};
if (endpos == std::string::npos)
endpos = str.size();
//need a null-terminated char* to pass to permissible_value_index
auto index{permissible_value_index(str.substr(pos, endpos).c_str())};
if (index == size_t_max)
return false;
m_value.push_back(index);
pos = endpos + 1;
}
return true;
}
template <typename ValueType> std::string
GncOptionRangeValue<ValueType>::serialize() const noexcept
{
if constexpr (std::is_arithmetic_v<ValueType>)
return std::to_string(m_value);
return "";
}
template <typename ValueType> bool
GncOptionRangeValue<ValueType>::deserialize(const std::string& str) noexcept
{
if constexpr(is_same_decayed_v<ValueType, int>)
set_value(stoi(str));
else if constexpr(is_same_decayed_v<ValueType, double>)
set_value(stod(str));
return true;
}
std::string
GncOptionDateValue::serialize() const noexcept
{
std::string retval{"("};
if (m_period == RelativeDatePeriod::ABSOLUTE)
{
retval += date_type_str[0];
retval += " . ";
retval += std::to_string(m_date);
}
else
{
retval += date_type_str[1];
retval += " . ";
retval += gnc_relative_date_storage_string(m_period);
}
retval += ")";
return retval;
}
bool
GncOptionDateValue::deserialize(const std::string& str) noexcept
{
//The length of both "absolute" and "relative".
static constexpr size_t date_type_len{9};
// date_type_len plus the length of " . ".
static constexpr size_t date_value_pos{12};
auto type_str{str.substr(0, date_type_len)};
auto period_str{str.substr(date_value_pos)};
if (type_str == "absolute")
{
// Need a cast to disambiguate from time64.
set_value(static_cast<size_t>(std::stoll(period_str)));
return true;
}
else if (type_str == "relative ")
{
auto period = gnc_relative_date_from_storage_string(period_str.c_str());
if (period == RelativeDatePeriod::ABSOLUTE)
{
PWARN("Unknown period string in date option: '%s'",
period_str.c_str());
return false;
}
set_value(period);
return true;
}
else
{
PWARN("Unknown date type string in date option: '%s'",
type_str.c_str());
return false;
}
}
std::istream&
operator>> (std::istream& iss, GncOptionCommodityValue& opt)
{
std::string instr;
iss >> instr;
if (!opt.deserialize(instr))
throw std::invalid_argument("Invalid commodity string in stream.");
return iss;
}
template GncOptionValue<bool>::GncOptionValue(const GncOptionValue<bool>&);
template GncOptionValue<int>::GncOptionValue(const GncOptionValue<int>&);
template GncOptionValue<int64_t>::GncOptionValue(const GncOptionValue<int64_t>&);
template GncOptionValue<double>::GncOptionValue(const GncOptionValue<double>&);
template GncOptionValue<char*>::GncOptionValue(const GncOptionValue<char*>&);
template GncOptionValue<const char*>::GncOptionValue(const GncOptionValue<const char*>&);
template GncOptionValue<std::string>::GncOptionValue(const GncOptionValue<std::string>&);
template GncOptionValue<const QofQuery*>::GncOptionValue(const GncOptionValue<const QofQuery*>&);
template GncOptionValue<const GncOwner*>::GncOptionValue(const GncOptionValue<const GncOwner*>&);
template GncOptionValue<RelativeDatePeriod>::GncOptionValue(const GncOptionValue<RelativeDatePeriod>&);
template GncOptionValue<size_t>::GncOptionValue(const GncOptionValue<size_t>&);
template GncOptionValue<GncOptionAccountList>::GncOptionValue(const GncOptionValue<GncOptionAccountList>&);
template GncOptionValue<GncMultichoiceOptionIndexVec>::GncOptionValue(const GncOptionValue<GncMultichoiceOptionIndexVec>&);
template GncOptionValue<GncOptionReportPlacementVec>::GncOptionValue(const GncOptionValue<GncOptionReportPlacementVec>&);
template void GncOptionValue<bool>::set_value(bool);
template void GncOptionValue<int>::set_value(int);
template void GncOptionValue<int64_t>::set_value(int64_t);
template void GncOptionValue<double>::set_value(double);
template void GncOptionValue<char*>::set_value(char*);
template void GncOptionValue<const char*>::set_value(const char*);
template void GncOptionValue<std::string>::set_value(std::string);
template void GncOptionValue<const QofQuery*>::set_value(const QofQuery*);
template void GncOptionValue<const GncOwner*>::set_value(const GncOwner*);
template void GncOptionValue<RelativeDatePeriod>::set_value(RelativeDatePeriod);
template void GncOptionValue<size_t>::set_value(size_t);
template void GncOptionValue<GncOptionAccountList>::set_value(GncOptionAccountList);
template void GncOptionValue<GncMultichoiceOptionIndexVec>::set_value(GncMultichoiceOptionIndexVec);
template void GncOptionValue<GncOptionReportPlacementVec>::set_value(GncOptionReportPlacementVec);
template void GncOptionValue<bool>::set_default_value(bool);
template void GncOptionValue<int>::set_default_value(int);
template void GncOptionValue<int64_t>::set_default_value(int64_t);
template void GncOptionValue<double>::set_default_value(double);
template void GncOptionValue<char*>::set_default_value(char*);
template void GncOptionValue<const char*>::set_default_value(const char*);
template void GncOptionValue<std::string>::set_default_value(std::string);
template void GncOptionValue<const QofQuery*>::set_default_value(const QofQuery*);
template void GncOptionValue<const GncOwner*>::set_default_value(const GncOwner*);
template void GncOptionValue<RelativeDatePeriod>::set_default_value(RelativeDatePeriod);
template void GncOptionValue<size_t>::set_default_value(size_t);
template void GncOptionValue<GncOptionAccountList>::set_default_value(GncOptionAccountList);
template void GncOptionValue<GncMultichoiceOptionIndexVec>::set_default_value(GncMultichoiceOptionIndexVec);
template void GncOptionValue<GncOptionReportPlacementVec>::set_default_value(GncOptionReportPlacementVec);
template void GncOptionValue<bool>::reset_default_value();
template void GncOptionValue<int>::reset_default_value();
template void GncOptionValue<int64_t>::reset_default_value();
template void GncOptionValue<double>::reset_default_value();
template void GncOptionValue<char*>::reset_default_value();
template void GncOptionValue<const char*>::reset_default_value();
template void GncOptionValue<std::string>::reset_default_value();
template void GncOptionValue<const QofQuery*>::reset_default_value();
template void GncOptionValue<const GncOwner*>::reset_default_value();
template void GncOptionValue<RelativeDatePeriod>::reset_default_value();
template void GncOptionValue<size_t>::reset_default_value();
template void GncOptionValue<GncOptionAccountList>::reset_default_value();
template void GncOptionValue<GncMultichoiceOptionIndexVec>::reset_default_value();
template void GncOptionValue<GncOptionReportPlacementVec>::reset_default_value();
template std::string GncOptionValue<bool>::serialize() const noexcept;
template std::string GncOptionValue<int>::serialize() const noexcept;
template std::string GncOptionValue<int64_t>::serialize() const noexcept;
template std::string GncOptionValue<double>::serialize() const noexcept;
template std::string GncOptionValue<char*>::serialize() const noexcept;
template std::string GncOptionValue<const char*>::serialize() const noexcept;
template std::string GncOptionValue<std::string>::serialize() const noexcept;
template std::string GncOptionValue<const QofQuery*>::serialize() const noexcept;
template std::string GncOptionValue<const GncOwner*>::serialize() const noexcept;
template std::string GncOptionValue<GncOptionReportPlacementVec>::serialize() const noexcept;
template std::string GncOptionRangeValue<int>::serialize() const noexcept;
template std::string GncOptionRangeValue<double>::serialize() const noexcept;
template bool GncOptionValue<bool>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<int>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<int64_t>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<double>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<char*>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<const char*>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<std::string>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<const QofQuery*>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<const GncOwner*>::deserialize(const std::string&) noexcept;
template bool GncOptionValue<GncOptionReportPlacementVec>::deserialize(const std::string&) noexcept;
template bool GncOptionRangeValue<int>::deserialize(const std::string&) noexcept;
template bool GncOptionRangeValue<double>::deserialize(const std::string&) noexcept;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
/********************************************************************\
* gnc-option-ui.hpp -- UI association for GncOption *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
#ifndef GNC_OPTION_UI_HPP_
#define GNC_OPTION_UI_HPP_
#include <memory>
#include "gnc-option-uitype.hpp"
class GncOption;
class GncOptionUIItem;
using GncOptionUIItemPtr = std::unique_ptr<GncOptionUIItem>;
/**
* Holds a pointer to the UI item which will control the option and an enum
* representing the type of the option for dispatch purposes; all of that
* happens in gnucash/gnome-utils/dialog-options and
* gnucash/gnome/business-option-gnome.
*
* This class takes no ownership responsibility, so calling code is responsible
* for ensuring that the UI_Item is alive. For convenience the public
* clear_ui_item function can be used as a weak_ptr's destruction callback to
* ensure that the ptr will be nulled if the ui_item is destroyed elsewhere.
*/
class GncOptionUIItem
{
public:
GncOptionUIItem(GncOptionUIType type) : m_type{type} {}
virtual ~GncOptionUIItem() = default;
GncOptionUIType get_ui_type() const noexcept { return m_type; }
virtual void set_dirty(bool status) noexcept { m_dirty = status; }
virtual bool get_dirty() const noexcept { return m_dirty; }
virtual void set_selectable(bool selectable) const noexcept = 0;
virtual void clear_ui_item() = 0;
virtual void set_ui_item_from_option(GncOption& option) noexcept = 0;
virtual void set_option_from_ui_item(GncOption& option) noexcept = 0;
private:
GncOptionUIType m_type;
bool m_dirty = false;
};
#endif //GNC_OPTION_UI_HPP__

View File

@ -1,6 +1,6 @@
/********************************************************************
* test-app-utils.c: GLib g_test test execution file. *
* Copyright 2013 John Ralls <jralls@ceridwen.us> *
/********************************************************************\
* gnc-option-uitype.hpp -- UI Control Enum for GncOption *
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -18,38 +18,59 @@
* 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 *
* *
\********************************************************************/
#ifndef GNC_OPTION_UITYPE_HPP__
#define GNC_OPTION_UITYPE_HPP__
#include <config.h>
#include <glib.h>
#include <qof.h>
#include <libguile.h>
/** @addtogroup Engine
@{ */
/** @addtogroup Options
@{ */
/** @file gnc-option-uitype.hpp
@brief OptionUITypes
@author Copyright 2019-2021 John Ralls <jralls@ceridwen.us>
*/
extern void test_suite_option_util (void);
extern void test_suite_gnc_ui_util (void);
static void
guile_main (void *closure, int argc, char **argv)
/** @enum GncOptionUIType
* Used by GncOptionClassifier to indicate to dialog-options what control
* should be displayed for the option.
*/
enum class GncOptionUIType : unsigned int
{
int retval;
scm_c_use_module("gnucash app-utils");
INTERNAL,
BOOLEAN,
STRING,
TEXT,
CURRENCY,
COMMODITY,
MULTICHOICE,
DATE_ABSOLUTE,
DATE_RELATIVE,
DATE_BOTH,
ACCOUNT_LIST,
ACCOUNT_SEL,
LIST,
NUMBER_RANGE,
COLOR,
FONT,
PLOT_SIZE,
BUDGET,
PIXMAP,
RADIOBUTTON,
DATE_FORMAT,
OWNER,
CUSTOMER,
VENDOR,
EMPLOYEE,
INVOICE,
JOB,
TAX_TABLE,
QUERY,
REPORT_PLACEMENT,
MAX_VALUE, //Nake sure this one is always last
};
test_suite_option_util ();
test_suite_gnc_ui_util ();
retval = g_test_run ();
exit (retval);
}
int
main (int argc, char *argv[])
{
qof_init (); /* Initialize the GObject system */
qof_log_init_filename_special ("stderr"); /* Init the log system */
g_test_init (&argc, &argv, NULL); /* initialize test program */
//qof_log_set_level("gnc", G_LOG_LEVEL_DEBUG);
g_test_bug_base("https://bugs.gnucash.org/show_bug.cgi?id="); /* init the bugzilla URL */
g_setenv ("GNC_UNINSTALLED", "1", TRUE);
scm_boot_guile (argc, argv, guile_main, NULL);
return 0;
}
#endif // GNC_OPTION_UITYPE_H__
/** @}
@} */

View File

@ -0,0 +1,546 @@
/********************************************************************\
* gnc-option.cpp -- Application options system *
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
* *
* 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 "gnc-option.hpp"
#include "gnc-option-impl.hpp"
#include "gnc-option-uitype.hpp"
#include "gnc-option-ui.hpp"
static const char* log_module{"gnc.app-utils.gnc-option"};
extern "C"
{
#include <qoflog.h>
}
template <typename ValueType,
typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
int>>
GncOption::GncOption(const char* section, const char* name,
const char* key, const char* doc_string,
ValueType value, GncOptionUIType ui_type) :
m_option{std::make_unique<GncOptionVariant>(
std::in_place_type<GncOptionValue<ValueType>>,
section, name, key, doc_string, value, ui_type)}
{
}
template <typename ValueType> ValueType
GncOption::get_value() const
{
return std::visit(
[](const auto option)->ValueType {
if constexpr (is_same_decayed_v<decltype(option.get_value()),
ValueType>)
return option.get_value();
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if constexpr (is_same_decayed_v<ValueType,
RelativeDatePeriod>)
return option.get_period();
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_period_index();
return ValueType{};
}
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_index();
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
return option.get_multiple();
}
return ValueType {};
}, *m_option);
}
template <typename ValueType> ValueType
GncOption::get_default_value() const
{
return std::visit(
[](const auto option)->ValueType {
if constexpr (is_same_decayed_v<decltype(option.get_value()),
ValueType>)
return option.get_default_value();
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if constexpr (is_same_decayed_v<ValueType,
RelativeDatePeriod>)
return option.get_default_period();
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_default_period_index();
return ValueType{};
}
if constexpr
(is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
return option.get_default_multiple();
return ValueType {};
}, *m_option);
}
template <typename ValueType> void
GncOption::set_value(ValueType value)
{
std::visit(
[value](auto& option) {
if constexpr
(is_same_decayed_v<decltype(option.get_value()), ValueType> ||
(is_same_decayed_v<decltype(option),
GncOptionDateValue> &&
(is_same_decayed_v<ValueType, RelativeDatePeriod> ||
std::is_same_v<ValueType, size_t>)))
option.set_value(value);
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
option.set_multiple(value);
else if constexpr
(std::is_same_v<ValueType, size_t> ||
is_same_decayed_v<ValueType, std::string> ||
std::is_same_v<std::remove_cv<ValueType>, char*>)
option.set_value(value);
}
}, *m_option);
}
template <typename ValueType> void
GncOption::set_default_value(ValueType value)
{
std::visit(
[value](auto& option) {
if constexpr
(is_same_decayed_v<decltype(option.get_value()), ValueType>||
(is_same_decayed_v<decltype(option), GncOptionDateValue> &&
(is_same_decayed_v<ValueType, RelativeDatePeriod> ||
std::is_same_v<ValueType, size_t>)))
option.set_default_value(value);
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
option.set_default_multiple(value);
else if constexpr
(std::is_same_v<ValueType, size_t> ||
is_same_decayed_v<ValueType, std::string> ||
std::is_same_v<std::remove_cv<ValueType>, char*>)
option.set_default_value(value);
}
}, *m_option);
}
void
GncOption::reset_default_value()
{
std::visit([](auto& option) { option.reset_default_value(); }, *m_option);
}
template <typename ValueType> void
GncOption::get_limits(ValueType& max, ValueType& min, ValueType& step) const noexcept
{
std::visit([&max, &min, &step](const auto& option) {
if constexpr
(is_same_decayed_v<decltype(option),
GncOptionRangeValue<ValueType>>)
option.get_limits(max, min, step);
}, *m_option);
}
const std::string&
GncOption::get_section() const
{
return std::visit([](const auto& option)->const std::string& {
return option.m_section;
}, *m_option);
}
const std::string&
GncOption::get_name() const
{
return std::visit([](const auto& option)->const std::string& {
return option.m_name;
}, *m_option);
}
const std::string&
GncOption::get_key() const
{
return std::visit([](const auto& option)->const std::string& {
return option.m_sort_tag;
}, *m_option);
}
const std::string&
GncOption::get_docstring() const
{
return std::visit([](const auto& option)->const std::string& {
return option.m_doc_string;
}, *m_option);
}
void
GncOption::set_ui_item(GncOptionUIItemPtr&& ui_item)
{
auto opt_ui_type = std::visit([](const auto& option)->GncOptionUIType {
return option.get_ui_type();
}, *m_option);
if (ui_item->get_ui_type() != opt_ui_type)
{
PERR("Setting option %s:%s UI element failed, mismatched UI types.",
get_section().c_str(), get_name().c_str());
return;
}
m_ui_item = std::move(ui_item);
}
void
GncOption::set_ui_item_selectable(bool selectable) const noexcept
{
if (m_ui_item)
m_ui_item->set_selectable(selectable);
}
const GncOptionUIType
GncOption::get_ui_type() const
{
return std::visit([](const auto& option)->GncOptionUIType {
return option.get_ui_type();
}, *m_option);
}
GncOptionUIItem* const
GncOption::get_ui_item() const
{
return m_ui_item.get();
}
void
GncOption::set_ui_item_from_option()
{
if (!m_ui_item)
return;
m_ui_item->set_ui_item_from_option(*this);
}
void
GncOption::set_option_from_ui_item()
{
if (!m_ui_item)
return;
m_ui_item->set_option_from_ui_item(*this);
}
void
GncOption::make_internal()
{
if (m_ui_item)
{
PERR("Option %s:%s has a UI Element, can't be INTERNAL.",
get_section().c_str(), get_name().c_str());
return;
}
std::visit([](auto& option) {
option.make_internal();
}, *m_option);
}
bool
GncOption::is_changed() const noexcept
{
return std::visit([](const auto& option)->bool {
return option.is_changed();
}, *m_option);
}
bool
GncOption::is_multiselect() const noexcept
{
return std::visit(
[](const auto& option)->bool {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionAccountListValue>)
return option.is_multiselect();
else
return false;
}, *m_option);
}
template<typename ValueType> bool
GncOption::validate(ValueType value) const
{
return std::visit(
[value] (const auto& option) -> bool {
if constexpr ((is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
is_same_decayed_v<ValueType, std::string>) ||
(is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>) ||
(is_same_decayed_v<decltype(option),
GncOptionCommodityValue> &&
is_same_decayed_v<ValueType, gnc_commodity*>))
return option.validate(value);
else
return false;
}, *m_option);
}
std::size_t
GncOption::num_permissible_values() const
{
return std::visit(
[] (const auto& option) -> size_t {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> ||
is_same_decayed_v<decltype(option),
GncOptionDateValue>)
return option.num_permissible_values();
else
return size_t_max;
}, *m_option);
}
std::size_t
GncOption::permissible_value_index(const char* value) const
{
return std::visit(
[&value] (const auto& option) -> size_t {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> ||
is_same_decayed_v<decltype(option),
GncOptionDateValue>)
return option.permissible_value_index(value);
else
return size_t_max;
}, *m_option);
}
const char*
GncOption::permissible_value(std::size_t index) const
{
return std::visit([index] (const auto& option) -> const char* {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue>)
return option.permissible_value(index);
else
return "";
}, *m_option);
}
const char*
GncOption::permissible_value_name(std::size_t index) const
{
return std::visit([index] (const auto& option) -> const char* {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue>)
return option.permissible_value_name(index);
else
return "";
}, *m_option);
}
GList*
GncOption::account_type_list() const noexcept
{
return std::visit([] (const auto& option) -> GList* {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionAccountListValue>)
return option.account_type_list();
else
return nullptr;
}, *m_option);
}
bool
GncOption::is_alternate() const noexcept
{
return std::visit([](auto& option) -> bool {
if constexpr(is_RangeValue_v<decltype(option)>)
return option.is_alternate();
return false;
}, *m_option);
}
void
GncOption::set_alternate(bool alt) noexcept
{
std::visit([alt](auto& option) {
if constexpr(is_RangeValue_v<decltype(option)>)
option.set_alternate(alt);
}, *m_option);
}
std::string
GncOption::serialize() const
{
if (m_option->valueless_by_exception())
return "Valueless Option";
return std::visit([&](auto& option) -> std::string {
return option.serialize();
}, *m_option);
}
bool
GncOption::deserialize(const std::string& str)
{
return std::visit([&str](auto& option) -> bool {
return option.deserialize(str);
}, *m_option);
}
std::istream&
GncOption::in_stream(std::istream& iss)
{
return std::visit([&iss](auto& option) -> std::istream& {
iss >> option;
return iss;
}, *m_option);
}
/* We must instantiate all of the templates we need here because we don't expose
* the template implementation in the public header.
*/
template GncOption::GncOption(const char*, const char*, const char*,
const char*, bool, GncOptionUIType);
//template GncOption::GncOption(const char*, const char*, const char*,
// const char*, int, GncOptionUIType);
template GncOption::GncOption(const char*, const char*, const char*,
const char*, int64_t, GncOptionUIType);
//template GncOption::GncOption(const char*, const char*, const char*,
// const char*, const char*, GncOptionUIType);
//template GncOption::GncOption(const char*, const char*, const char*,
// const char*, double, GncOptionUIType);
template GncOption::GncOption(const char*, const char*, const char*,
const char*, std::string, GncOptionUIType);
template GncOption::GncOption(const char*, const char*, const char*,
const char*, const QofQuery*, GncOptionUIType);
template GncOption::GncOption(const char*, const char*, const char*,
const char*, const GncOwner*, GncOptionUIType);
template bool GncOption::get_value<bool>() const;
template int GncOption::get_value<int>() const;
template int64_t GncOption::get_value<int64_t>() const;
template double GncOption::get_value<double>() const;
template size_t GncOption::get_value<size_t>() const;
template const char* GncOption::get_value<const char*>() const;
template std::string GncOption::get_value<std::string>() const;
template const QofInstance* GncOption::get_value<const QofInstance*>() const;
template gnc_commodity* GncOption::get_value<gnc_commodity*>() const;
template const Account* GncOption::get_value<const Account*>() const;
template RelativeDatePeriod GncOption::get_value<RelativeDatePeriod>() const;
template GncOptionAccountList GncOption::get_value<GncOptionAccountList>() const;
template GncMultichoiceOptionIndexVec GncOption::get_value<GncMultichoiceOptionIndexVec>() const;
template GncOptionReportPlacementVec GncOption::get_value<GncOptionReportPlacementVec>() const;
template bool GncOption::get_default_value<bool>() const;
template int GncOption::get_default_value<int>() const;
template int64_t GncOption::get_default_value<int64_t>() const;
template double GncOption::get_default_value<double>() const;
template const char* GncOption::get_default_value<const char*>() const;
template std::string GncOption::get_default_value<std::string>() const;
template const QofInstance* GncOption::get_default_value<const QofInstance*>() const;
template gnc_commodity* GncOption::get_default_value<gnc_commodity*>() const;
template const Account* GncOption::get_default_value<const Account*>() const;
template RelativeDatePeriod GncOption::get_default_value<RelativeDatePeriod>() const;
template GncOptionAccountList GncOption::get_default_value<GncOptionAccountList>() const;
template GncMultichoiceOptionIndexVec GncOption::get_default_value<GncMultichoiceOptionIndexVec>() const;
template GncOptionReportPlacementVec GncOption::get_default_value<GncOptionReportPlacementVec>() const;
template void GncOption::set_value(bool);
template void GncOption::set_value(int);
template void GncOption::set_value(int64_t);
template void GncOption::set_value(double);
template void GncOption::set_value(char*);
template void GncOption::set_value(const char*);
template void GncOption::set_value(std::string);
template void GncOption::set_value(const QofInstance*);
template void GncOption::set_value(gnc_commodity*);
template void GncOption::set_value(const Account*);
template void GncOption::set_value(RelativeDatePeriod);
template void GncOption::set_value(size_t);
template void GncOption::set_value(GncOptionAccountList);
template void GncOption::set_value(GncMultichoiceOptionIndexVec);
template void GncOption::set_value(GncOptionReportPlacementVec);
template void GncOption::set_default_value(bool);
template void GncOption::set_default_value(int);
template void GncOption::set_default_value(int64_t);
template void GncOption::set_default_value(double);
template void GncOption::set_default_value(char*);
template void GncOption::set_default_value(const char*);
template void GncOption::set_default_value(std::string);
template void GncOption::set_default_value(const QofInstance*);
template void GncOption::set_default_value(const Account*);
template void GncOption::set_default_value(RelativeDatePeriod);
template void GncOption::set_default_value(size_t);
template void GncOption::set_default_value(GncOptionAccountList);
template void GncOption::set_default_value(GncMultichoiceOptionIndexVec);
template void GncOption::set_default_value(GncOptionReportPlacementVec);
template void GncOption::get_limits(double&, double&, double&) const noexcept;
template void GncOption::get_limits(int&, int&, int&) const noexcept;
template bool GncOption::validate(bool) const;
template bool GncOption::validate(int) const;
template bool GncOption::validate(int64_t) const;
template bool GncOption::validate(double) const;
template bool GncOption::validate(const char*) const;
template bool GncOption::validate(std::string) const;
template bool GncOption::validate(const QofInstance*) const;
template bool GncOption::validate(gnc_commodity*) const;
template bool GncOption::validate(const Account*) const;
template bool GncOption::validate(const QofQuery*) const;
template bool GncOption::validate(RelativeDatePeriod) const;
template bool GncOption::validate(GncMultichoiceOptionIndexVec) const;
template bool GncOption::validate(GncOptionReportPlacementVec) const;
template GncOption* gnc_make_option<const std::string&>(const char*,
const char*,
const char*,
const char*,
const std::string&,
GncOptionUIType);
template GncOption* gnc_make_option<bool>(const char*, const char*, const char*,
const char*, bool, GncOptionUIType);
template GncOption* gnc_make_option<int64_t>(const char*, const char*,
const char*, const char*, int64_t,
GncOptionUIType);

View File

@ -0,0 +1,261 @@
/********************************************************************\
* gnc-option.hpp -- Application options system *
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Options
@{ */
/** @file gnc-option.hpp
@brief C++ Public interface for individual options.
@author Copyright 2020-2021 John Ralls <jralls@ceridwen.us>
*/
#ifndef GNC_OPTION_HPP_
#define GNC_OPTION_HPP_
#include <glib.h>
#include <libguile.h>
#include <string>
#include <iostream>
#include <iomanip>
#include <variant>
#include <memory>
#include <tuple>
#include "gnc-option-ui.hpp"
#include "gnc-option-date.hpp"
#include <guid.hpp>
struct OptionClassifier;
class GncOptionUIItem;
using GncOptionUIItemPtr = std::unique_ptr<GncOptionUIItem>;
#ifndef SWIG //SWIG pulls in GncOwner from swig-engine.
struct _gncOwner;
using GncOwner = _gncOwner;
#endif
struct _QofQuery;
using QofQuery = _QofQuery;
struct QofInstance_s;
using QofInstance = QofInstance_s;
template <typename ValueType> class GncOptionValue;
class GncOptionQofInstanceValue;
class GncOptionAccountListValue;
class GncOptionAccountSelValue;
class GncOptionMultichoiceValue;
template <typename ValueType> class GncOptionRangeValue;
class GncOptionCommodityValue;
class GncOptionDateValue;
using GncOptionReportPlacement = std::tuple<uint32_t, uint32_t, uint32_t>;
using GncOptionReportPlacementVec = std::vector<GncOptionReportPlacement>;
template <typename T>
struct is_OptionClassifier
{
static constexpr bool value =
std::is_base_of_v<OptionClassifier, std::decay_t<T>>;
};
template <typename T> inline constexpr bool
is_OptionClassifier_v = is_OptionClassifier<T>::value;
template <typename T, typename U>
struct is_same_decayed
{
static constexpr bool value = std::is_same_v<std::decay_t<T>,
std::decay_t<U>>;
};
template <typename T, typename U> inline constexpr bool
is_same_decayed_v = is_same_decayed<T, U>::value;
template <typename T>
struct is_RangeValue
{
static constexpr bool value =
(is_same_decayed_v<T, GncOptionRangeValue<int>> ||
is_same_decayed_v<T, GncOptionRangeValue<double>>);
};
template <typename T> inline constexpr bool
is_RangeValue_v = is_RangeValue<T>::value;
using GncOptionVariant = std::variant<GncOptionValue<std::string>,
GncOptionValue<bool>,
GncOptionValue<int64_t>,
GncOptionQofInstanceValue,
GncOptionValue<const QofQuery*>,
GncOptionValue<const GncOwner*>,
GncOptionValue<GncOptionReportPlacementVec>,
GncOptionAccountListValue,
GncOptionAccountSelValue,
GncOptionMultichoiceValue,
GncOptionRangeValue<int>,
GncOptionRangeValue<double>,
GncOptionCommodityValue,
GncOptionDateValue>;
using GncOptionVariantPtr = std::unique_ptr<GncOptionVariant>;
enum class GncOptionMultichoiceKeyType
{
SYMBOL,
STRING,
NUMBER,
};
/** @class GncOption
* @brief Represents the public interface for an option.
* Polymorphism is provided by a std::variant member containing GncOptionValue
* types.
*/
class GncOption
{
public:
template <typename OptionType,
typename std::enable_if_t<is_OptionClassifier_v<OptionType>,
int> = 0>
GncOption(OptionType option) :
m_option{std::make_unique<GncOptionVariant>(option)} {}
template <typename ValueType,
typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
int> = 0>
GncOption(const char* section, const char* name,
const char* key, const char* doc_string,
ValueType value,
GncOptionUIType ui_type = GncOptionUIType::INTERNAL);
template <typename ValueType> void set_value(ValueType value);
template <typename ValueType> void set_default_value(ValueType value);
template <typename ValueType> ValueType get_default_value() const;
template <typename ValueType> ValueType get_value() const;
void reset_default_value();
const std::string& get_section() const;
const std::string& get_name() const;
const std::string& get_key() const;
const std::string& get_docstring() const;
void set_ui_item(GncOptionUIItemPtr&& ui_elem);
const GncOptionUIType get_ui_type() const;
void set_ui_item_selectable(bool) const noexcept;
GncOptionUIItem* const get_ui_item() const;
void set_ui_item_from_option();
void set_option_from_ui_item();
void make_internal();
bool is_changed() const noexcept;
/** @returns false unless m_option contains a GncOptionMultiselectValue or
* GncOptionAccountListValue for which multiple selections have been enabled.
*/
bool is_multiselect() const noexcept;
/** Implemented only for GncOptionNumericRange */
template <typename ValueType> void get_limits(ValueType&, ValueType&,
ValueType&) const noexcept;
/** Not implemented for GncOptionValue. */
template <typename ValueType> bool validate(ValueType value) const;
/** Implemented only for GncOptionMultiselectValue. */
std::size_t num_permissible_values() const;
/** Implemented only for GncOptionMultiselectValue. */
std::size_t permissible_value_index(const char* value) const;
/** Implemented only for GncOptionMultiselectValue. */
const char* permissible_value(std::size_t index) const;
/** Implemented only for GncOptionMultiselectValue. */
const char* permissible_value_name(std::size_t index) const;
/** Implemented only for GncOptionAccountListValue. */
GList* account_type_list() const noexcept;
bool is_alternate() const noexcept;
void set_alternate(bool) noexcept;
/** Get a string suitable for storage representing the option's value.
* @return a std::string
*/
std::string serialize() const;
/** Set the option's value from a character sequence.
* @param str: The character sequence representing the value
* @return true if the value was set, false otherwise.
*/
bool deserialize(const std::string& str);
/** Set the option's value from an input stream
* @param iss: An input stream reference.
* @return the stream reference for chaining.
*/
std::istream& in_stream(std::istream& iss);
friend GncOptionVariant& swig_get_option(GncOption*);
private:
inline static const std::string c_empty_string{""};
GncOptionVariantPtr m_option;
GncOptionUIItemPtr m_ui_item{nullptr};
};
inline bool
operator<(const GncOption& right, const GncOption& left)
{
return right.get_key() < left.get_key();
}
inline std::ostream&
operator<<(std::ostream& oss, const GncOption& opt)
{
oss << opt.serialize();
return oss;
}
inline std::istream&
operator>>(std::istream& iss, GncOption& opt)
{
return opt.in_stream(iss);
}
inline std::ostream&
output_color_value(std::ostream& oss, const std::string& value)
{
oss << "'(";
oss << std::fixed << std::showpoint << std::setprecision(1);
auto len{value.length() > 8 ? 8 : value.length()};
for (size_t i{}; i < len; i += 2)
{
oss << static_cast<float>(stoi(value.substr(i, 2), nullptr, 16));
if (i < 6)
oss << " ";
}
if (len < 8)
oss << 256.0;
oss << ")";
return oss;
}
/**
* Free function wrapping GncOption's constructor. The type of GncOptionValue to
* create is determined from the UI type. Some GncOptionValue types require more
* parameters for their constructors and can't be created with this function.
*/
template<typename ValueType> GncOption*
gnc_make_option(const char* section, const char* name,
const char* key, const char* doc_string,
ValueType value, GncOptionUIType ui_type)
{
return new GncOption(section, name, key, doc_string, value, ui_type);
}
#endif //GNC_OPTION_HPP_
/** @}
@} */

View File

@ -0,0 +1,191 @@
/********************************************************************\
* gnc-optiondb.hpp -- Collection of GncOption objects *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Options
@{ */
/** @file gnc-optiondb-impl.hpp
@brief Implementation details for GncOptionDB.
@author Copyright 2019-2021 John Ralls <jralls@ceridwen.us>
*/
#ifndef GNC_OPTIONDB_P_HPP_
#define GNC_OPTIONDB_P_HPP_
#include "gnc-option.hpp"
#include "gnc-option-impl.hpp"
#include <functional>
#include <exception>
#include <optional>
#include <iostream>
extern "C"
{
#include <config.h>
#include <qof.h>
#include <gncInvoice.h>
#include <gncCustomer.h>
#include <gncEmployee.h>
#include <gncJob.h>
#include <gncVendor.h>
#include <gncTaxTable.h>
}
using GncOptionVec = std::vector<GncOption>;
/** class GncOptionSection
* The upper-level classification implmentation. Contains the options for a
* section; sections are displayed as separate tabs on the option dialog.
*/
class GncOptionSection
{
std::string m_name;
GncOptionVec m_options;
public:
GncOptionSection(const char* name) : m_name{name}, m_options{} {}
~GncOptionSection() = default;
void foreach_option(std::function<void(GncOption&)> func);
void foreach_option(std::function<void(const GncOption&)> func) const;
const std::string& get_name() const noexcept { return m_name; }
size_t get_num_options() const noexcept { return m_options.size(); }
void add_option(GncOption&& option);
void remove_option(const char* name);
const GncOption* find_option(const char* name) const;
};
using GncOptionSectionPtr = std::shared_ptr<GncOptionSection>;
inline bool
operator<(const GncOptionSectionPtr& right, const GncOptionSectionPtr& left)
{
return right->get_name() < left->get_name();
}
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
* Holds all of the options for a book, report, or stylesheet, organized by
* GncOptionSections.
*/
class GncOptionDB
{
public:
GncOptionDB();
GncOptionDB(QofBook* book);
~GncOptionDB() = default;
/* The non-const version can't be redirected to the const one because the
* function parameters are incompatible.
*/
void foreach_section(std::function<void(GncOptionSectionPtr&)> func)
{
for (auto& section : m_sections)
func(section);
}
void foreach_section(std::function<void(const GncOptionSectionPtr&)> func) const
{
for (auto& section : m_sections)
func(section);
}
size_t num_sections() const noexcept { return m_sections.size(); }
bool get_changed() const noexcept { return m_dirty; }
void register_option(const char* section, GncOption&& option);
void register_option(const char* section, GncOption* option);
void unregister_option(const char* section, const char* name);
void set_default_section(const char* section);
const GncOptionSection* const get_default_section() const noexcept;
std::string lookup_string_option(const char* section, const char* name);
template <typename ValueType>
bool set_option(const char* section, const char* name, ValueType value)
{
try
{
auto option{find_option(section, name)};
if (!option)
return false;
option->set_value(value);
return true;
}
catch(const std::invalid_argument& err)
{
printf("Set Failed: %s\n", err.what());
return false;
}
}
// void set_selectable(const char* section, const char* name);
void make_internal(const char* section, const char* name);
void commit() {};
GncOptionSection* find_section(const std::string& sectname)
{
return const_cast<GncOptionSection*>(static_cast<const GncOptionDB&>(*this).find_section(sectname));
}
const GncOptionSection* find_section(const std::string& sectname) const;
GncOption* find_option(const std::string& section, const char* name)
{
return const_cast<GncOption*>(static_cast<const GncOptionDB&>(*this).find_option(section, name));
}
const GncOption* find_option(const std::string& section, const char* name) const;
std::ostream& save_to_key_value(std::ostream& oss) const noexcept;
std::istream& load_from_key_value(std::istream& iss);
void save_to_kvp(QofBook* book, bool clear_book) const noexcept;
void load_from_kvp(QofBook* book) noexcept;
std::ostream& save_option_key_value(std::ostream& oss,
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;
};
#endif // GNC_OPTIONDB_P_HPP_
/** @}
@} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,175 @@
/********************************************************************\
* gnc-optiondb.h -- Collection of GncOption objects C interface *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Options
GnuCash Options System for Book, Report, and Stylesheet Options.
The GnuCash Options System supports two somewhat different purposes:
- File properties, such as business information and whether to use automatic
trading accounts.
- Report options for configuring and customizing reports. Most report
options are user-configurable through a report options dialog but some are
used as a way of passing enumeration values between the scheme modules
that generate the report.
The options system is centered on an options database or optiondb. A
separate optionsdb is created and instantiated for every use, so the book
gets one at the beginning of the session with its values loaded from KVP,
and every report gets one when the report is run, as do report stylesheets
when they are edited. Customized report and stylesheet options are saved as
Scheme code fragments in files in the user's GnuCash Config directory.
@note
Persistence via text scheme code is a security vulnerability as it
enables an attacker to make GnuCash execute arbitrary code. The Guile
interpreter affords full system access with at least the user's privileges.
@{ */
/** @file gnc-optiondb.h
@brief C public interface for the Options Database.
@author Copyright 2019-2021 John Ralls <jralls@ceridwen.us>
*/
#ifndef GNC_OPTIONDB_H_
#define GNC_OPTIONDB_H_
#ifdef __cplusplus
class GncOption;
class GncOptionDB;
#else
// It's a class in C++ but the C compiler can't tell.
typedef struct GncOption GncOption;
typedef struct GncOptionDB GncOptionDB;
#endif
#include <libguile.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include <config.h>
#include <Account.h>
#include <gnc-budget.h>
#include <gnc-commodity.h>
#include <gncInvoice.h>
#include <gncTaxTable.h>
/**
* Create an empty option database.
*
* @return A newly allocated GncOptionDB. Use delete to destroy it.
*/
GncOptionDB* gnc_option_db_new(void);
/**
* Destruct and release a GncOptionDB.
* @param odb The GncOptionDB.
*/
void gnc_option_db_destroy(GncOptionDB* odb);
/**
* Write all changed ui_item values to their options.
* @param odb The GncOptionDB.
* @return A GList* conatining the names of options that raised exceptions when
* attempting to set their values. The names are const, free only the list.
*/
GList* gnc_option_db_commit(GncOptionDB* odb);
/**
* Reset all ui_items to the option value.
* @param odb The GncOptionDB.
*/
void gnc_option_db_clean(GncOptionDB* odb);
/**
* Load a book's options into the GncOptionDB.
* @param odb The GncOptionDB
* @param book The book in which the options are saved.
*/
void gnc_option_db_load(GncOptionDB* odb, QofBook* book);
/**
* Save the GncOptionDB contents into a book's options store.
* @param odb The GncOptionDB
* @param book The book in which the options are saved.
* @param clear_options TRUE if the books existing options should be removed first.
*/
void gnc_option_db_save(GncOptionDB* odb, QofBook* book,
gboolean clear_options);
/**
* Register the standard option set for a QofBook.
*
* @param odb The GncOptionDB
*/
void gnc_option_db_book_options(GncOptionDB*);
/**
* Retrieve the string value of an option in the GncOptionDB
*
* @param odb the GncOptionDB
* @param section the section in which the option is stored
* @param name the option name
* @return the static char* of the value or nullptr if the option isn't found
* or if its value isn't a string.
*/
const char* gnc_option_db_lookup_string_value(GncOptionDB*, const char*,
const char*);
/**
* Set the string value of an option in the GncOptionDB.
*
* The value will not be saved if the option is not in the GncOptionDB or if the
* type of the option isn't string or text.
*
* @param odb the GncOptionDB
* @param section the section in which the option is stored
* @param name the option name
* @param value the value to be stored in the option.
*/
void gnc_option_db_set_string_value(GncOptionDB*, const char*,
const char*, const char*);
/**
* Retrieve the string value of an option in the GncOptionDB
*
* @param odb the GncOptionDB
* @param section the section in which the option is stored
* @param name the option name
* @return the const QofInstance* of the value or nullptr if the option isn't
* found or if its value isn't a QofInstance*.
*/
const QofInstance* gnc_option_db_lookup_qofinstance_value(GncOptionDB*,
const char*,
const char*);
#ifdef __cplusplus
}
#endif
#endif //GNC_OPTIONDB_H_
/** @}
@} */

View File

@ -0,0 +1,893 @@
/********************************************************************\
* gnc-optiondb.hpp -- Collection of GncOption objects *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Options
@{ */
/** @file gnc-optiondb.hpp
* @brief The primary C++ interface to options for books, reports, and
* stylesheets.
* @author Copyright 2019-2021 John Ralls <jralls@ceridwen.us>
*/
#ifndef GNC_OPTIONDB_HPP_
#define GNC_OPTIONDB_HPP_
#include <string>
#include <functional>
#include <exception>
#include <optional>
#include <iostream>
#include <libguile.h>
extern "C"
{
#include <config.h>
#include <Account.h>
#include <gnc-budget.h>
#include <gnc-commodity.h>
#include <gncInvoice.h>
#include <gncTaxTable.h>
}
#include "gnc-option.hpp"
#include <gnc-datetime.hpp>
class GncOptionDB;
using GncOptionDBPtr = std::unique_ptr<GncOptionDB>;
using GncOptionAccountList = std::vector<GncGUID>;
using GncOptionAccountTypeList = std::vector<GNCAccountType>;
using GncMultichoiceOptionEntry = std::tuple<const std::string,
const std::string,
GncOptionMultichoiceKeyType>;
using GncMultichoiceOptionChoices = std::vector<GncMultichoiceOptionEntry>;
/**
* Extract a list of accounts in the book having one of the GNCAccountTypes in
* types.
*
* Note that in Scheme it's important to use this function and not to create a
* list of accounts using gnc-get-descendants-sorted because the latter method
* produces a SWIGTYPE for the accounts that's incompatible with the SWIGTYPE
* used in this module.
*
* @param book The book whose accounts to search
* @param types A std::vector of GNCAccountType containing the Account types to
* include in ther result
* @return A std::vector<const Account*> of all accounts in the book having the
* Account types in the types parameter.
*/
GncOptionAccountList
gnc_account_list_from_types(QofBook *book,
const GncOptionAccountTypeList& types);
/**
* Create a new string option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_string_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_string_option(const GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
std::string value)
{
gnc_register_string_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new text option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_text_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_text_option(const GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string, std::string value)
{
gnc_register_text_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new font option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_font_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_font_option(const GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
std::string value)
{
gnc_register_font_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new budget option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_budget_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, GncBudget* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_budget_option(const GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
GncBudget* value)
{
gnc_register_budget_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new commodity option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_commodity_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
gnc_commodity* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_commodity_option(const GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
gnc_commodity* value)
{
gnc_register_commodity_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new simple boolean option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_simple_boolean_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
bool value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_simple_boolean_option(const GncOptionDBPtr& db,
const char* section,
const char* name,
const char* key,
const char* doc_string,
bool value)
{
gnc_register_simple_boolean_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new complex boolean option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_complex_boolean_option(GncOptionDB* db,
const char* section, const char* name,
const char* key,
const char* doc_string,
bool value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_complex_boolean_option(const GncOptionDBPtr& db,
const char* section,
const char* name,
const char* key,
const char* doc_string,
bool value)
{
gnc_register_complex_boolean_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new pixmap option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_pixmap_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_pixmap_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
std::string value)
{
gnc_register_pixmap_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new limited account list option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default values for the option.
* @param allowed The accounts which are available for selection.
*/
void gnc_register_account_list_limited_option(GncOptionDB* db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const GncOptionAccountList& value,
GncOptionAccountTypeList&& allowed);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_account_list_limited_option(GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const GncOptionAccountList& value,
GncOptionAccountTypeList&& allowed)
{
gnc_register_account_list_limited_option(db.get(), section, name, key,
doc_string, value,
std::move(allowed));
}
/**
* Create a new account list option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default values for the option.
*/
void gnc_register_account_list_option(GncOptionDB* db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const GncOptionAccountList& value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_account_list_option(GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const GncOptionAccountList& value)
{
gnc_register_account_list_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a limited account selection option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
* @param allowed The accounts which are available for selection.
*/
void gnc_register_account_sel_limited_option(GncOptionDB* db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const Account* value,
GncOptionAccountTypeList&& allowed);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_account_sel_limited_option(GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
const Account* value,
GncOptionAccountTypeList&& allowed)
{
gnc_register_account_sel_limited_option(db.get(), section, name, key,
doc_string, value,
std::move(allowed));
}
/**
* Create a new multichoice option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The set of possible values for the option. Only one can be selected. Note that the value will be moved from the parameter and using the parameter after this call will result in undefined behavior.
*/
void gnc_register_multichoice_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
const char* default_val,
GncMultichoiceOptionChoices&& value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_multichoice_option(GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
const char* default_val,
GncMultichoiceOptionChoices&& value)
{
gnc_register_multichoice_option(db.get(), section, name,
key, doc_string, default_val,
std::move(value));
}
/**
* Create a new list option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
* @param list The values available for selection. Note that this parameter will be moved from so using it after this call will result in undefined behavior.
*/
void gnc_register_list_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, const char* value,
GncMultichoiceOptionChoices&& list);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_list_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string, const char* value,
GncMultichoiceOptionChoices&& list)
{
gnc_register_list_option(db.get(), section, name, key, doc_string,
value, std::move(list));
}
/**
* Create a new number range option and register it in the options database.
*
* These are normally associated with spin controls and ValueType is normally
* double, but it's templated to permit other numeric types if needed.
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
* @param min The minimum value for the spin control.
* @param max The maximum value for the spin control.
* @param step The step size (increment) of the spin control.
*/
template <typename ValueType>
void gnc_register_number_range_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
ValueType value, ValueType min,
ValueType max, ValueType step);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
template <typename ValueType>
void gnc_register_number_range_option(GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
ValueType value, ValueType min,
ValueType max, ValueType step)
{
gnc_register_number_range_option<ValueType>(db.get(), section, name,
key, doc_string, value,
min, max, step);
}
/**
* Create a new plot-size option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_number_plot_size_option(GncOptionDB* db,
const char* section, const char* name,
const char* key,
const char* doc_string,
int value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_number_plot_size_option(const GncOptionDBPtr& db,
const char* section,
const char* name,
const char* key,
const char* doc_string,
int value)
{
gnc_register_number_plot_size_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new QofQuery option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_query_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, const QofQuery* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_query_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
const QofQuery* value)
{
gnc_register_query_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new GncOwner option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_owner_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, const GncOwner* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_owner_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
const GncOwner* value)
{
gnc_register_owner_option(db.get(), section, name, key, doc_string, value);
}
/**
* Create a new color option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_color_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_color_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
std::string value)
{
gnc_register_color_option(db.get(), section, name, key, doc_string, value);
}
void gnc_register_internal_option(GncOptionDBPtr& db,
const char* section, const char* name,
const char* key,
const char* doc_string,
const std::string& value);
void gnc_register_internal_option(GncOptionDBPtr& db,
const char* section, const char* name,
const char* key,
const char* doc_string,
bool value);
void gnc_register_report_placement_option(GncOptionDBPtr& db,
const char* section, const char* name);
/**
* Create a new currency option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option. It is checked with gnc_commodity_is_currency.
*/
void gnc_register_currency_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, gnc_commodity* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_currency_option(const GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
gnc_commodity* value)
{
gnc_register_currency_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new invoice option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_invoice_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, GncInvoice* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_invoice_option(const GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
GncInvoice* value)
{
gnc_register_invoice_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new taxtable option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_taxtable_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, GncTaxTable* value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_taxtable_option(const GncOptionDBPtr& db,
const char* section, const char* name,
const char* key,
const char* doc_string,
GncTaxTable* value)
{
gnc_register_taxtable_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new counter option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_counter_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, double value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_counter_option(const GncOptionDBPtr& db,
const char* section, const char* name,
const char* key, const char* doc_string,
double value)
{
gnc_register_counter_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new counter format option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_counter_format_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_counter_format_option(GncOptionDBPtr& db,
const char* section,
const char* name,
const char* key,
const char* doc_string,
std::string value)
{
gnc_register_counter_format_option(db.get(), section, name, key,
doc_string, value);
}
/**
* Create a new date format option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param value The initial and default value for the option.
*/
void gnc_register_dateformat_option(GncOptionDB* db,
const char* section, const char* name,
const char* key, const char* doc_string,
std::string value);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_dateformat_option(GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string,
std::string value)
{
gnc_register_dateformat_option(db.get(), section, name, key,
doc_string, value);
}
enum RelativeDateUI : uint8_t
{
ABSOLUTE,
RELATIVE,
BOTH
};
/**
* Create a new date option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param period The default/starting relative date value for the option.
* @param ui What UI to display, relative, absolute, or both.
*/
void gnc_register_date_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string,
RelativeDatePeriod period =
RelativeDatePeriod::TODAY,
RelativeDateUI ui = RelativeDateUI::BOTH);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_date_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
RelativeDatePeriod period =
RelativeDatePeriod::TODAY,
RelativeDateUI ui = RelativeDateUI::BOTH)
{
gnc_register_date_option(db.get(), section, name, key, doc_string,
period, ui);
}
/**
* Create a new date option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param time The initial time to set in the option.
* @param ui What UI to display, relative, absolute, or both.
*/
void gnc_register_date_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, time64 time,
RelativeDateUI ui = RelativeDateUI::BOTH);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_date_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string, time64 time,
RelativeDateUI ui = RelativeDateUI::BOTH)
{
gnc_register_date_option(db.get(), section, name, key, doc_string,
time, ui);
}
/**
* Create a new date option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param period_set A vector of relative date periods to display in the relative control.
* @param both Whether to display both a relative and absolute control or a onla a relative control.
*/
void gnc_register_date_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string,
RelativeDatePeriodVec& period_set,
bool both = true);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_date_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string,
RelativeDatePeriodVec& period_set,
bool both = true)
{
gnc_register_date_option(db.get(), section, name, key, doc_string,
period_set, both);
}
/**
* Create a new start-date option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param both Whether to display both a relative and absolute control or a onla a relative control.
*/
void gnc_register_start_date_option(GncOptionDB* db,
const char* section,
const char* name, const char* key,
const char* doc_string, bool both = true);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_start_date_option(GncOptionDBPtr& db,
const char* section,
const char* name, const char* key,
const char* doc_string, bool both = true)
{
gnc_register_start_date_option(db.get(), section, name, key, doc_string,
both);
}
/**
* Create a new end-date option and register it in the options database.
*
* @param db A GncOptionDB* for calling from C. Caller retains ownership.
* @param section The database section for the option.
* @param name The option name.
* @param doc_string A description of the option. This will be used in tooltips and should be marked for translation.
* @param both Whether to display both a relative and absolute control or a onla a relative control.
*/
void gnc_register_end_date_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
const char* doc_string, bool both = true);
/**
* As above but takes a const GncOptionDBPtr& (const std::unique_ptr<GncOptionDB>&) for calling from C++.
*/
inline void gnc_register_end_date_option(GncOptionDBPtr& db, const char* section,
const char* name, const char* key,
const char* doc_string, bool both = true)
{
gnc_register_end_date_option(db.get(), section, name, key, doc_string,
both);
}
#endif //GNC_OPTIONDB_HPP_

File diff suppressed because it is too large Load Diff

View File

@ -421,122 +421,6 @@ gnc_get_current_book_tax_type (void)
}
}
/** Returns TRUE if both book-currency and default gain/loss policy KVPs exist
* and are valid and trading accounts are not used. */
gboolean
gnc_book_use_book_currency (QofBook *book)
{
const gchar *policy;
const gchar *currency;
if (!book) return FALSE;
policy = qof_book_get_default_gains_policy (book);
currency = qof_book_get_book_currency_name (book);
/* If either a default gain/loss policy or a book-currency does not exist,
book-currency accounting method not valid */
if (!policy || !currency)
return FALSE;
/* If both exist, both must be valid */
if (!gnc_valid_policy_name (policy) || !gnc_commodity_table_lookup
(gnc_commodity_table_get_table
(gnc_get_current_book()),
GNC_COMMODITY_NS_CURRENCY,
currency))
return FALSE;
/* If both exist and are valid, there must be no trading accounts flag */
if (qof_book_use_trading_accounts (book))
return FALSE;
return TRUE;
}
/** Returns pointer to Book Currency name for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
const gchar *
gnc_book_get_book_currency_name (QofBook *book)
{
if (!book) return NULL;
if (gnc_book_use_book_currency (book))
return qof_book_get_book_currency_name (book);
return NULL;
}
/** Returns pointer to Book Currency for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
gnc_commodity *
gnc_book_get_book_currency (QofBook *book)
{
if (!book) return NULL;
if (gnc_book_use_book_currency (book))
return gnc_commodity_table_lookup
(gnc_commodity_table_get_table(book),
GNC_COMMODITY_NS_CURRENCY,
qof_book_get_book_currency_name (book));
return NULL;
}
/** Returns pointer to default gain/loss policy for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
const gchar *
gnc_book_get_default_gains_policy (QofBook *book)
{
if (!book) return NULL;
if (gnc_book_use_book_currency (book))
return qof_book_get_default_gains_policy (book);
return NULL;
}
/** Returns pointer to default gain/loss account for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. Also, account must not be hidden or a placeholder, and
* must be of same currency as book-currency and income or expense type */
Account *
gnc_book_get_default_gain_loss_acct (QofBook *book)
{
Account *gains_account = NULL;
if (!book) return NULL;
if (gnc_book_use_book_currency (book))
{
GncGUID *guid = qof_book_get_default_gain_loss_acct_guid (book);
gains_account = xaccAccountLookup (guid, book);
guid_free (guid);
}
if (gains_account &&
!xaccAccountGetPlaceholder(gains_account) &&
!xaccAccountGetHidden(gains_account) &&
(gnc_commodity_equal(xaccAccountGetCommodity(gains_account),
gnc_book_get_book_currency(book))) &&
((xaccAccountGetType(gains_account) == ACCT_TYPE_INCOME) ||
(xaccAccountGetType(gains_account) == ACCT_TYPE_EXPENSE)))
{
return gains_account;
}
else
{
return NULL;
}
}
Account *
gnc_get_current_root_account (void)
{
@ -1151,9 +1035,6 @@ gnc_default_currency_common (gchar *requested_currency,
GNC_COMMODITY_NS_CURRENCY,
requested_currency);
if (gnc_book_use_book_currency (gnc_get_current_book ()))
return gnc_book_get_book_currency (gnc_get_current_book ());
if (gnc_prefs_get_bool (section, GNC_PREF_CURRENCY_CHOICE_OTHER))
{
mnemonic = gnc_prefs_get_string(section, GNC_PREF_CURRENCY_OTHER);

View File

@ -87,40 +87,6 @@ const gchar * gnc_get_current_book_tax_type (void);
* callbacks when num_field_source book option changes so that
* registers/reports can update themselves; sets feature flag */
void gnc_book_option_num_field_source_change_cb (gboolean num_action);
/** Calls gnc_book_option_book_currency_selected to initiate registered
* callbacks when currency accounting book option changes to book-currency so
* that registers/reports can update themselves; sets feature flag */
void gnc_book_option_book_currency_selected_cb (gboolean use_book_currency);
/** Returns TRUE if both book-currency and default gain/loss policy KVPs exist
* and are valid and trading accounts are not used */
gboolean gnc_book_use_book_currency (QofBook *book);
/** Returns pointer to Book Currency name for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
const gchar * gnc_book_get_book_currency_name (QofBook *book);
/** Returns pointer to Book Currency for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
gnc_commodity * gnc_book_get_book_currency (QofBook *book);
/** Returns pointer to default gain/loss policy for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
const gchar * gnc_book_get_default_gains_policy (QofBook *book);
/** Returns pointer to default gain/loss account for book or NULL; determines
* that both book-currency and default gain/loss policy KVPs exist and that
* both are valid, a requirement for the 'book-currency' currency accounting
* method to apply. */
Account * gnc_book_get_default_gain_loss_acct (QofBook *book);
Account * gnc_get_current_root_account (void);
gnc_commodity_table * gnc_get_current_commodities (void);

File diff suppressed because it is too large Load Diff

View File

@ -1,287 +0,0 @@
/********************************************************************\
* option-util.h -- GNOME<->guile option interface *
* Copyright (C) 1998,1999 Linas Vepstas *
* 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 *
\********************************************************************/
#ifndef OPTION_UTIL_H
#define OPTION_UTIL_H
#include <glib.h>
#include <libguile.h>
#include "guile-mappings.h"
#include "gnc-commodity.h"
#include "gnc-engine-guile.h"
#include "qof.h"
typedef struct gnc_option GNCOption;
typedef struct gnc_option_section GNCOptionSection;
/* typedef struct gnc_option_db GNCOptionDB is in qof-book.h */
typedef int GNCOptionDBHandle;
typedef SCM (*GNCOptionGetUIValue) (GNCOption *option);
typedef void (*GNCOptionSetUIValue) (GNCOption *option,
gboolean use_default);
typedef void (*GNCOptionSetSelectable) (GNCOption *option,
gboolean selectable);
typedef void (*GNCOptionChangeCallback) (gpointer user_data);
/***** Prototypes ********************************************************/
void gnc_option_set_changed (GNCOption *option, gboolean changed);
/** Returns an opaque pointer to the widget of this option. The actual
* GUI implementation in dialog-options.c will store a GtkWidget* in
* here. */
gpointer gnc_option_get_widget (GNCOption *option);
/** Store an opaque pointer to the widget of this option. The actual
* GUI implementation in dialog-options.c will store a GtkWidget* in
* here. */
void gnc_option_set_widget (GNCOption *option, gpointer widget);
SCM gnc_option_get_ui_value (GNCOption *option);
void gnc_option_set_ui_value (GNCOption *option, gboolean use_default);
void gnc_option_set_selectable (GNCOption *option, gboolean selectable);
GNCOptionDB * gnc_option_db_new (SCM guile_options);
void gnc_option_db_destroy (GNCOptionDB *odb);
/* Create an option DB for a particular type, and save/load from a kvp.
* This assumes the gnc:*kvp-option-path* location for the options
* in the kvp.
*/
GNCOptionDB * gnc_option_db_new_for_type (QofIdType id_type);
void gnc_option_db_load (GNCOptionDB* odb, QofBook *book);
void gnc_option_db_save (GNCOptionDB* odb, QofBook *book, gboolean clear_all);
void gnc_register_kvp_option_generator (QofIdType id_type, SCM generator);
void gnc_option_db_set_ui_callbacks (GNCOptionDB *odb,
GNCOptionGetUIValue get_ui_value,
GNCOptionSetUIValue set_ui_value,
GNCOptionSetSelectable set_selectable);
SCM gnc_option_db_register_change_callback (GNCOptionDB *odb,
GNCOptionChangeCallback callback,
gpointer data,
const char *section,
const char *name);
void gnc_option_db_unregister_change_callback_id (GNCOptionDB *odb,
SCM callback_id);
char * gnc_option_section (GNCOption *option);
char * gnc_option_name (GNCOption *option);
char * gnc_option_type (GNCOption *option);
char * gnc_option_sort_tag (GNCOption *option);
char * gnc_option_documentation (GNCOption *option);
SCM gnc_option_getter (GNCOption *option);
SCM gnc_option_setter (GNCOption *option);
SCM gnc_option_default_getter (GNCOption *option);
SCM gnc_option_value_validator (GNCOption *option);
SCM gnc_option_widget_changed_proc_getter (GNCOption *option);
SCM gnc_option_get_option_data (GNCOption *option);
int gnc_option_num_permissible_values (GNCOption *option);
int gnc_option_permissible_value_index (GNCOption *option, SCM value);
SCM gnc_option_permissible_value (GNCOption *option, int index);
char * gnc_option_permissible_value_name (GNCOption *option, int index);
gboolean gnc_option_show_time (GNCOption *option);
gboolean gnc_option_multiple_selection (GNCOption *option);
GList * gnc_option_get_account_type_list (GNCOption *option);
gboolean gnc_option_get_range_info (GNCOption *option,
double *lower_bound,
double *upper_bound,
int *num_decimals,
double *step_size);
gdouble gnc_option_color_range (GNCOption *option);
gdouble gnc_option_use_alpha (GNCOption *option);
guint32 gnc_option_get_color_argb (GNCOption *option);
gboolean gnc_option_get_color_info (GNCOption *option,
gboolean use_default,
gdouble *red,
gdouble *green,
gdouble *blue,
gdouble *alpha);
void gnc_option_call_option_widget_changed_proc (GNCOption *option,
gboolean reset_changed);
void gnc_option_set_default (GNCOption *option);
guint gnc_option_db_num_sections (GNCOptionDB *odb);
const char * gnc_option_section_name (GNCOptionSection *section);
guint gnc_option_section_num_options (GNCOptionSection *section);
GNCOptionSection * gnc_option_db_get_section (GNCOptionDB *odb, gint i);
GNCOption * gnc_get_option_section_option (GNCOptionSection *section, int i);
GNCOption * gnc_option_db_get_option_by_name (GNCOptionDB *odb,
const char *section_name,
const char *name);
GNCOption * gnc_option_db_get_option_by_SCM (GNCOptionDB *odb,
SCM guile_option);
gboolean gnc_option_db_dirty (GNCOptionDB *odb);
void gnc_option_db_clean (GNCOptionDB *odb);
gboolean gnc_option_db_get_changed (GNCOptionDB *odb);
GList* gnc_option_db_commit (GNCOptionDB *odb);
char * gnc_option_db_get_default_section (GNCOptionDB *odb);
SCM gnc_option_db_lookup_option (GNCOptionDB *odb,
const char *section,
const char *name,
SCM default_value);
gboolean gnc_option_db_lookup_boolean_option (GNCOptionDB *odb,
const char *section,
const char *name,
gboolean default_value);
char * gnc_option_db_lookup_string_option (GNCOptionDB *odb,
const char *section,
const char *name,
const char *default_value);
char * gnc_option_db_lookup_font_option (GNCOptionDB *odb,
const char *section,
const char *name,
const char *default_value);
char * gnc_option_db_lookup_multichoice_option (GNCOptionDB *odb,
const char *section,
const char *name,
const char *default_value);
gdouble gnc_option_db_lookup_number_option (GNCOptionDB *odb,
const char *section,
const char *name,
gdouble default_value);
gboolean gnc_option_db_lookup_color_option (GNCOptionDB *odb,
const char *section,
const char *name,
gdouble *red,
gdouble *green,
gdouble *blue,
gdouble *alpha);
guint32 gnc_option_db_lookup_color_option_argb (GNCOptionDB *odb,
const char *section,
const char *name,
guint32 default_value);
GSList * gnc_option_db_lookup_list_option (GNCOptionDB *odb,
const char *section,
const char *name,
GSList *default_value);
void gnc_free_list_option_value (GSList *list);
gnc_commodity * gnc_option_db_lookup_currency_option (GNCOptionDB *odb,
const char *section,
const char *name,
gnc_commodity *default_value);
void gnc_option_db_set_option_default (GNCOptionDB *odb,
const char *section,
const char *name);
gboolean gnc_option_db_set_option (GNCOptionDB *odb,
const char *section,
const char *name,
SCM value);
gboolean gnc_option_db_set_number_option (GNCOptionDB *odb,
const char *section,
const char *name,
gdouble value);
gboolean gnc_option_db_set_boolean_option (GNCOptionDB *odb,
const char *section,
const char *name,
gboolean value);
gboolean gnc_option_db_set_string_option (GNCOptionDB *odb,
const char *section,
const char *name,
const char *value);
char * gnc_option_date_option_get_subtype (GNCOption *option);
char * gnc_date_option_value_get_type (SCM option_value);
time64 gnc_date_option_value_get_absolute (SCM option_value);
SCM gnc_date_option_value_get_relative (SCM option_value);
char * gnc_plot_size_option_value_get_type (SCM option_value);
gdouble gnc_plot_size_option_value_get_value (SCM option_value);
char * gnc_currency_accounting_option_currency_documentation (GNCOption *option);
SCM gnc_currency_accounting_option_get_default_currency (GNCOption *option);
char * gnc_currency_accounting_option_policy_documentation (GNCOption *option);
SCM gnc_currency_accounting_option_get_default_policy (GNCOption *option);
char * gnc_currency_accounting_option_gain_loss_account_documentation (GNCOption *option);
SCM gnc_currency_accounting_option_value_get_method (SCM option_value);
SCM gnc_currency_accounting_option_value_get_book_currency (SCM option_value);
SCM gnc_currency_accounting_option_value_get_default_policy (SCM option_value);
SCM gnc_currency_accounting_option_value_get_default_account (SCM option_value);
void gnc_option_db_set_option_selectable_by_name (SCM guile_options,
const char *section,
const char *name,
gboolean selectable);
gboolean gnc_dateformat_option_value_parse (SCM value,
QofDateFormat *format,
GNCDateMonthFormat *months,
gboolean *years, char **custom);
SCM gnc_dateformat_option_set_value (QofDateFormat format,
GNCDateMonthFormat months,
gboolean years,
const char *custom);
void gnc_option_db_register_option (GNCOptionDBHandle handle,
SCM guile_option);
/* private */
void gncp_option_invoke_callback (GNCOptionChangeCallback callback,
gpointer data);
/* Reset all the widgets in one section to their default values */
void gnc_option_db_section_reset_widgets (GNCOptionSection *section);
/* Reset all the widgets to their default values */
void gnc_option_db_reset_widgets (GNCOptionDB *odb);
#endif /* OPTION_UTIL_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
set(MODULEPATH ${CMAKE_SOURCE_DIR}/libgnucash/app-utils)
set(APP_UTILS_TEST_INCLUDE_DIRS
${CMAKE_BINARY_DIR}/common # for config.h
@ -11,8 +12,6 @@ set(APP_UTILS_TEST_INCLUDE_DIRS
set(APP_UTILS_TEST_LIBS gnc-app-utils gnc-test-engine test-core ${GIO_LDFLAGS} ${GUILE_LDFLAGS})
set(test_app_utils_SOURCES test-app-utils.c test-option-util.cpp test-gnc-ui-util.c)
macro(add_app_utils_test _TARGET _SOURCE_FILES)
gnc_add_test(${_TARGET} "${_SOURCE_FILES}" APP_UTILS_TEST_INCLUDE_DIRS APP_UTILS_TEST_LIBS)
endmacro()
@ -28,6 +27,26 @@ gnc_add_test_with_guile(test-scm-query-string test-scm-query-string.cpp
)
add_app_utils_test(test-sx test-sx.cpp)
set(gtest_gnc_option_SOURCES
gtest-gnc-option.cpp
gtest-gnc-optiondb.cpp)
set(gtest_gnc_option_INCLUDES
${MODULEPATH}
${CMAKE_SOURCE_DIR}/libgnucash/engine
${CMAKE_BINARY_DIR}/common # for config.h
${GLIB2_INCLUDE_DIRS}
${GUILE_INCLUDE_DIRS})
set(gtest_gnc_option_LIBS
gnc-app-utils
gnc-engine
${GLIB2_LDFLAGS}
${GUILE_LDFLAGS}
gtest)
gnc_add_test(test-gnc-option "${gtest_gnc_option_SOURCES}" gtest_gnc_option_INCLUDES gtest_gnc_option_LIBS)
set(GUILE_DEPENDS
scm-test-engine
scm-app-utils
@ -60,17 +79,20 @@ gnc_add_scheme_test_targets(scm-test-c-interface
gnc_add_scheme_tests("${test_app_utils_scheme_SOURCES}")
if (HAVE_SRFI64)
gnc_add_scheme_test_targets(scm-test-app-utils-srfi64
SOURCES "${test_app_utils_scheme_SRFI64_SOURCES}"
OUTPUT_DIR "tests"
DEPENDS "${GUILE_DEPENDS};scm-srfi64-extras")
gnc_add_scheme_test_targets(scm-test-app-utils-srfi64
SOURCES "${test_app_utils_scheme_SRFI64_SOURCES}"
OUTPUT_DIR "tests"
DEPENDS "${GUILE_DEPENDS};scm-srfi64-extras")
gnc_add_scheme_tests("${test_app_utils_scheme_SRFI64_SOURCES}")
gnc_add_scheme_test_targets(scm-test-gnc-optiondb
SOURCES "test-gnc-optiondb.scm" "test-gnc-option-scheme-output.scm"
OUTPUT_DIR "tests"
DEPENDS "swig-apputils-guile-cpp;scm-srfi64-extras")
gnc_add_scheme_tests("test-gnc-optiondb.scm")
gnc_add_scheme_tests("test-gnc-option-scheme-output.scm")
gnc_add_scheme_tests("${test_app_utils_scheme_SRFI64_SOURCES}")
endif()
# Doesn't work yet:
gnc_add_test_with_guile(test-app-utils "${test_app_utils_SOURCES}" APP_UTILS_TEST_INCLUDE_DIRS APP_UTILS_TEST_LIBS)
set_dist_list(test_app_utils_DIST
CMakeLists.txt
test-exp-parser.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,408 @@
/********************************************************************
* gtest-gnc-optiondb.cpp -- unit tests for GncOption class. *
* Copyright (C) 2019 John Ralls <jralls@ceridwen.us> *
* *
* 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 <gtest/gtest.h>
#include <gnc-optiondb.hpp>
#include <gnc-optiondb-impl.hpp>
#include <gnc-option-ui.hpp>
#include <kvp-value.hpp>
#include <glib-2.0/glib.h>
extern "C"
{
#include <gnc-ui-util.h>
#include <gnc-session.h>
}
using GncOptionDBPtr = std::unique_ptr<GncOptionDB>;
class GncOptionDBTest : public ::testing::Test
{
protected:
GncOptionDBTest() : m_db{std::make_unique<GncOptionDB>()} {}
GncOptionDBPtr m_db;
};
TEST_F(GncOptionDBTest, test_ctor)
{
EXPECT_NO_THROW ({ GncOptionDB optiondb; });
}
TEST_F(GncOptionDBTest, test_register_option)
{
GncOption option1{"foo", "bar", "baz", "Phony Option",
std::string{"waldo"}};
m_db->register_option("foo", std::move(option1));
EXPECT_EQ(1u, m_db->num_sections());
}
TEST_F(GncOptionDBTest, test_lookup_string_option)
{
GncOption option1{"foo", "bar", "baz", "Phony Option",
std::string{"waldo"}};
m_db->register_option("foo", std::move(option1));
EXPECT_STREQ("waldo", m_db->lookup_string_option("foo", "bar").c_str());
}
TEST_F(GncOptionDBTest, test_unregister_option)
{
GncOption option1{"foo", "bar", "baz", "Phony Option",
std::string{"waldo"}};
m_db->register_option("foo", std::move(option1));
m_db->unregister_option("foo", "bar");
EXPECT_TRUE(m_db->lookup_string_option("foo", "bar").empty());
}
TEST_F(GncOptionDBTest, test_register_string_option)
{
gnc_register_string_option(m_db, "foo", "bar", "baz", "Phony Option",
std::string{"waldo"});
EXPECT_STREQ("waldo", m_db->lookup_string_option("foo", "bar").c_str());
}
TEST_F(GncOptionDBTest, test_register_report_placement_option)
{
uint32_t report_id = 456;
uint32_t wide = 2, high = 2;
GncOptionReportPlacementVec rp{{report_id, wide, high}};
gnc_register_report_placement_option(m_db, "foo", "bar");
auto option{m_db->find_option("foo", "bar")};
option->set_value(rp);
auto value{option->get_value<GncOptionReportPlacementVec>()};
EXPECT_EQ(value.size(), 1);
auto [v_id, v_wide, v_height] = value.at(0);
EXPECT_EQ(report_id, v_id);
}
/* Note: The following test-fixture code is also present in slightly different
* form in gtest-gnc-option.cpp.
*/
struct GncOptionDBAccountTest : public ::testing::Test
{
GncOptionDBAccountTest() :
m_sess{gnc_get_current_session()}, m_book{gnc_get_current_book()},
m_root{gnc_account_create_root(m_book)},
m_db{std::make_unique<GncOptionDB>()}
{
auto create_account = [this](Account* parent, GNCAccountType type,
const char* name)->Account* {
auto account = xaccMallocAccount(this->m_book);
xaccAccountBeginEdit(account);
xaccAccountSetType(account, type);
xaccAccountSetName(account, name);
xaccAccountBeginEdit(parent);
gnc_account_append_child(parent, account);
xaccAccountCommitEdit(parent);
xaccAccountCommitEdit(account);
return account;
};
auto assets = create_account(m_root, ACCT_TYPE_ASSET, "Assets");
auto liabilities = create_account(m_root, ACCT_TYPE_LIABILITY, "Liabilities");
auto expenses = create_account(m_root, ACCT_TYPE_EXPENSE, "Expenses");
create_account(assets, ACCT_TYPE_BANK, "Bank");
auto broker = create_account(assets, ACCT_TYPE_ASSET, "Broker");
auto stocks = create_account(broker, ACCT_TYPE_STOCK, "Stocks");
create_account(stocks, ACCT_TYPE_STOCK, "AAPL");
create_account(stocks, ACCT_TYPE_STOCK, "MSFT");
create_account(stocks, ACCT_TYPE_STOCK, "HPE");
create_account(broker, ACCT_TYPE_BANK, "Cash Management");
create_account(expenses, ACCT_TYPE_EXPENSE, "Food");
create_account(expenses, ACCT_TYPE_EXPENSE, "Gas");
create_account(expenses, ACCT_TYPE_EXPENSE, "Rent");
}
~GncOptionDBAccountTest()
{
xaccAccountBeginEdit(m_root);
xaccAccountDestroy(m_root); //It does the commit
gnc_clear_current_session();
}
QofSession* m_sess;
QofBook* m_book;
Account* m_root;
GncOptionDBPtr m_db;
};
TEST_F(GncOptionDBAccountTest, test_register_account_list_option)
{
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
gnc_register_account_list_option(m_db, "foo", "bar", "baz",
"Phony Option", acclist);
EXPECT_EQ(4U, m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().size());
EXPECT_EQ(acclist[3], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(3));
}
TEST_F(GncOptionDBAccountTest, test_register_account_list_limited_option)
{
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz",
"Phony Option", acclist,
{ACCT_TYPE_STOCK});
EXPECT_EQ(4u, m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().size());
EXPECT_EQ(acclist[3], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(3));
}
TEST_F(GncOptionDBAccountTest, test_register_account_sel_limited_option)
{
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
GncOptionAccountList accsel{acclist[2]};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz",
"Phony Option", accsel,
{ACCT_TYPE_STOCK});
EXPECT_EQ(1u, m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().size());
EXPECT_EQ(accsel[0], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(0));
}
TEST_F(GncOptionDBAccountTest, test_register_account_sel_limited_option_fail_construct)
{
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
GncOptionAccountList accsel{acclist[2]};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz", "Phony Option",
accsel, {ACCT_TYPE_BANK});
EXPECT_FALSE(m_db->find_option("foo", "bar"));
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz",
"Phony Option", acclist,
{ACCT_TYPE_BANK});
EXPECT_FALSE(m_db->find_option("foo", "bar"));
}
using KT = GncOptionMultichoiceKeyType;
TEST_F(GncOptionDBTest, test_register_multichoice_option)
{
GncMultichoiceOptionChoices choices{
{ "plugh", "xyzzy", KT::STRING},
{ "waldo", "pepper", KT::STRING},
{ "pork", "sausage", KT::STRING},
{ "corge", "grault", KT::STRING}};
gnc_register_multichoice_option(m_db, "foo", "bar", "baz",
"Phony Option", "waldo",
std::move(choices));
EXPECT_STREQ("waldo", m_db->lookup_string_option("foo", "bar").c_str());
ASSERT_TRUE(m_db->set_option("foo", "bar", std::string{"corge"}));
EXPECT_STREQ("corge", m_db->lookup_string_option("foo", "bar").c_str());
}
static time64
time64_from_gdate(const GDate* g_date, DayPart when)
{
GncDate date{g_date_get_year(g_date), g_date_get_month(g_date),
g_date_get_day(g_date)};
GncDateTime time1{date, when};
return static_cast<time64>(time1);
}
TEST_F(GncOptionDBTest, test_register_relative_date_option)
{
gnc_register_date_option(m_db, "foo", "bar", "baz", "Phony Option",
RelativeDatePeriod::START_ACCOUNTING_PERIOD);
GDate prev_year_start;
g_date_set_time_t(&prev_year_start, time(nullptr));
gnc_gdate_set_prev_year_start(&prev_year_start);
time64 time1{time64_from_gdate(&prev_year_start, DayPart::start)};
ASSERT_TRUE(m_db->set_option("foo", "bar", time1));
EXPECT_EQ(time1, m_db->find_option("foo", "bar")->get_value<time64>());
}
TEST_F(GncOptionDBTest, test_register_absolute_date_option)
{
time64 time1{static_cast<time64>(GncDateTime("2019-07-19 15:32:26 +05:00"))};
gnc_register_date_option(m_db, "foo", "bar", "baz", "Phony Option",
time1);
GDate prev_year_start;
g_date_set_time_t(&prev_year_start, time(nullptr));
gnc_gdate_set_prev_year_start(&prev_year_start);
ASSERT_TRUE(m_db->set_option("foo", "bar", time1));
EXPECT_EQ(time1,
m_db->find_option("foo", "bar")->get_value<time64>());
}
/* Copied from gnc-optiondb.cpp for the purpose of finding the index of the
* option in the following test.
*/
static const RelativeDatePeriodVec begin_dates
{
RelativeDatePeriod::TODAY,
RelativeDatePeriod::START_THIS_MONTH,
RelativeDatePeriod::START_PREV_MONTH,
RelativeDatePeriod::START_CURRENT_QUARTER,
RelativeDatePeriod::START_PREV_QUARTER,
RelativeDatePeriod::START_CAL_YEAR,
RelativeDatePeriod::START_PREV_YEAR,
RelativeDatePeriod::START_ACCOUNTING_PERIOD
};
TEST_F(GncOptionDBTest, test_register_start_date_option)
{
gnc_register_start_date_option(m_db, "foo", "bar", "baz",
"Phony Option");
GDate prev_year_start;
g_date_set_time_t(&prev_year_start, time(nullptr));
gnc_gdate_set_prev_year_start(&prev_year_start);
time64 time1{time64_from_gdate(&prev_year_start, DayPart::start)};
EXPECT_EQ(RelativeDatePeriod::START_ACCOUNTING_PERIOD,
m_db->find_option("foo", "bar")->get_value<RelativeDatePeriod>());
ASSERT_TRUE(m_db->set_option("foo", "bar", time1));
EXPECT_EQ(time1,
m_db->find_option("foo", "bar")->get_value<time64>());
EXPECT_EQ(RelativeDatePeriod::ABSOLUTE,
m_db->find_option("foo", "bar")->get_value<RelativeDatePeriod>());
m_db->set_option("foo", "bar", RelativeDatePeriod::START_THIS_MONTH);
EXPECT_EQ(RelativeDatePeriod::START_THIS_MONTH,
m_db->find_option("foo", "bar")->get_value<RelativeDatePeriod>());
const RelativeDatePeriod start_this_month {RelativeDatePeriod::START_THIS_MONTH};
auto index =
std::find(begin_dates.begin(), begin_dates.end(), start_this_month);
/* If this fails check that the begin_dates vector above matches the one in
* gnc-optiondb.cpp.
*/
EXPECT_EQ(static_cast<unsigned int>(std::distance(begin_dates.begin(), index)),
m_db->find_option("foo", "bar")->get_value<size_t>());
m_db->set_option("foo", "bar", RelativeDatePeriod::END_THIS_MONTH);
EXPECT_EQ(RelativeDatePeriod::START_THIS_MONTH,
m_db->find_option("foo", "bar")->get_value<RelativeDatePeriod>());
m_db->set_option("foo", "bar", static_cast<size_t>(5));
EXPECT_EQ(5u, m_db->find_option("foo", "bar")->get_value<size_t>());
}
static bool
operator==(const GncGUID& l, const GncGUID& r)
{
return guid_equal(&l, &r);
}
class GncOptionDBIOTest : public ::testing::Test
{
protected:
GncOptionDBIOTest() :
m_book{gnc_get_current_book()}, m_root{gnc_account_create_root(m_book)},
m_db{std::make_unique<GncOptionDB>()}
{
auto create_account = [this](Account* parent, GNCAccountType type,
const char* name)->Account* {
auto account = xaccMallocAccount(this->m_book);
xaccAccountBeginEdit(account);
xaccAccountSetType(account, type);
xaccAccountSetName(account, name);
xaccAccountBeginEdit(parent);
gnc_account_append_child(parent, account);
xaccAccountCommitEdit(parent);
xaccAccountCommitEdit(account);
return account;
};
auto assets = create_account(m_root, ACCT_TYPE_ASSET, "Assets");
auto liabilities = create_account(m_root, ACCT_TYPE_LIABILITY, "Liabilities");
auto expenses = create_account(m_root, ACCT_TYPE_EXPENSE, "Expenses");
create_account(assets, ACCT_TYPE_BANK, "Bank");
auto broker = create_account(assets, ACCT_TYPE_ASSET, "Broker");
auto stocks = create_account(broker, ACCT_TYPE_STOCK, "Stocks");
auto aapl = create_account(stocks, ACCT_TYPE_STOCK, "AAPL");
create_account(stocks, ACCT_TYPE_STOCK, "MSFT");
auto hpe = create_account(stocks, ACCT_TYPE_STOCK, "HPE");
create_account(broker, ACCT_TYPE_BANK, "Cash Management");
create_account(expenses, ACCT_TYPE_EXPENSE, "Food");
create_account(expenses, ACCT_TYPE_EXPENSE, "Gas");
create_account(expenses, ACCT_TYPE_EXPENSE, "Rent");
gnc_register_string_option(m_db, "foo", "bar", "baz",
"Phony Option", std::string{"waldo"});
gnc_register_text_option(m_db, "foo", "sausage", "links",
"Phony Option", std::string{"waldo"});
gnc_register_string_option(m_db, "qux", "grault", "baz",
"Phony Option", std::string{""});
gnc_register_text_option(m_db, "qux", "garply", "fred",
"Phony Option", std::string{"waldo"});
gnc_register_date_option(m_db, "pork", "garply", "first",
"Phony Date Option",
RelativeDatePeriod::START_CURRENT_QUARTER);
gnc_register_account_list_option(m_db, "quux", "xyzzy", "second",
"Phony AccountList Option",
{*qof_entity_get_guid(aapl),
*qof_entity_get_guid(hpe)});
}
~GncOptionDBIOTest()
{
xaccAccountBeginEdit(m_root);
xaccAccountDestroy(m_root); //It does the commit
gnc_clear_current_session();
}
QofBook* m_book;
Account* m_root;
GncOptionDBPtr m_db;
};
TEST_F(GncOptionDBIOTest, test_option_key_value_output)
{
std::ostringstream oss;
m_db->save_option_key_value(oss, "foo", "sausage");
EXPECT_STREQ("", oss.str().c_str());
m_db->set_option("foo", "sausage", std::string{"pepper"});
// EXPECT_STREQ("pepper", m_db->lookup_string_option("foo", "sausage").c_str());
// EXPECT_TRUE(m_db->find_option("foo", "sausage")->get().is_changed());
m_db->save_option_key_value(oss, "foo", "sausage");
EXPECT_STREQ("foo:sausage=pepper;", oss.str().c_str());
}
TEST_F(GncOptionDBIOTest, test_option_key_value_input)
{
std::istringstream iss{"foo:sausage=pepper;"};
EXPECT_STREQ("waldo", m_db->lookup_string_option("foo", "sausage").c_str());
m_db->load_option_key_value(iss);
EXPECT_STREQ("pepper", m_db->lookup_string_option("foo", "sausage").c_str());
}
TEST_F(GncOptionDBIOTest, test_option_kvp_save)
{
m_db->save_to_kvp(m_book, false);
auto foo = "foo";
auto bar = "bar";
auto sausage = "sausage";
auto grault = "grault";
auto garply = "garply";
GSList foo_bar_tail{(void*)bar, nullptr};
GSList foo_bar_head{(void*)foo, &foo_bar_tail};
GSList foo_sausage_tail{(void*)sausage, nullptr};
GSList foo_sausage_head{(void*)foo, &foo_sausage_tail};
GSList qux_grault_tail{(void*)grault, nullptr};
GSList qux_grault_head{(void*)foo, &qux_grault_tail};
GSList qux_garply_tail{(void*)garply, nullptr};
GSList qux_garply_head{(void*)foo, &qux_grault_tail};
m_db->set_option("foo", "sausage", std::string{"pepper"});
m_db->save_to_kvp(m_book, true);
auto foo_bar = qof_book_get_option(m_book, &foo_bar_head);
auto foo_sausage = qof_book_get_option(m_book, &foo_sausage_head);
auto qux_garply = qof_book_get_option(m_book, &qux_garply_head);
auto qux_grault = qof_book_get_option(m_book, &qux_grault_head);
EXPECT_EQ(nullptr, foo_bar);
EXPECT_EQ(nullptr, qux_garply);
EXPECT_EQ(nullptr, qux_grault);
EXPECT_STREQ("pepper", foo_sausage->get<const char*>());
}

View File

@ -0,0 +1,591 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; test-gnc-option-scheme-output.scm -- Test Scheme option i/o. ;
; Copyright (C) 2021 John Ralls <jralls@ceridwen.us> ;
; ;
; 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 ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-modules (srfi srfi-64))
(use-modules (tests srfi64-extras))
(use-modules (gnucash app-utils options))
(use-modules (sw_app_utils))
(use-modules (sw_engine))
(define (run-test)
(test-runner-factory gnc:test-runner)
(test-begin "test-gnc-option-scheme-io")
(test-gnc-string-option-to-scheme)
(test-gnc-text-option-to-scheme)
(test-gnc-font-option-to-scheme)
(test-gnc-currency-option-to-scheme)
(test-gnc-budget-option-to-scheme)
(test-gnc-commodity-option-to-scheme)
(test-gnc-bool-option-to-scheme)
(test-gnc-pixmap-option-to-scheme)
(test-gnc-date-option-to-scheme)
(test-gnc-account-options-to-scheme)
(test-gnc-multichoice-option-to-scheme)
(test-gnc-list-option-to-scheme)
(test-gnc-number-range-option-to-scheme)
(test-gnc-number-plot-size-option-to-scheme)
(test-gnc-query-option-to-scheme)
(test-gnc-color-option-to-scheme)
(test-gnc-invoice-option-to-scheme)
(test-gnc-owner-option-to-scheme)
(test-gnc-internal-option-to-scheme)
(test-end "test-gnc-option-scheme-io"))
(define test-unchanged-section-output-template
"
; Section: foo
"
)
(define (test-string-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o ~s))) option))
" value))
(define (test-literal-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o '~a))) option))
" value))
(define (test-currency-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o ~s))) option))
" value))
(define (test-commodity-output-template value)
(let ((value-parts (string-split value #\:)))
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o ~s ~s))) option))
" (car value-parts) (cadr value-parts))))
(define (test-budget-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (option) (if option ((gnc:option-setter option) (gnc-budget-lookup ~s (gnc-get-current-book))))) option))
"
(gncBudgetGetGUID value)))
(define (test-option-scheme-output name make-option-func get-value-func test-template default value)
(let ((odb (gnc:new-options))
(option (make-option-func "foo" "bar" "baz" "Test Option" default)))
(gnc:register-option odb option)
(test-equal (string-append name " unchanged")
test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(gnc:option-set-value (gnc:lookup-option odb "foo" "bar") value)
(test-equal (string-append name " value")
(test-template (get-value-func (gnc:lookup-option odb "foo" "bar")))
(gnc:generate-restore-forms odb "options"))))
(define (test-gnc-string-option-to-scheme)
(test-begin "test-gnc-string-option-to-scheme")
(test-option-scheme-output "string"
gnc:make-string-option GncOption-get-scm-value
test-string-output-template
"waldo" "pepper")
(test-end "test-gnc-string-option-to-scheme"))
(define (test-gnc-text-option-to-scheme)
(test-begin "test-gnc-text-option-to-scheme")
(test-option-scheme-output "text"
gnc:make-string-option GncOption-get-scm-value
test-string-output-template
""
"Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore
veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(test-end "test-gnc-text-option-to-scheme"))
(define (test-gnc-font-option-to-scheme)
(test-begin "test-gnc-font-option-to-scheme")
(test-option-scheme-output "font"
gnc:make-font-option GncOption-get-scm-value
test-string-output-template
"URW Bookman L Bold Italic 12"
"Helvetica 12")
(test-end "test-gnc-font-option-to-scheme"))
(define (test-gnc-currency-option-to-scheme)
(test-begin "test-gnc-currency-option-to-scheme")
(let ((session (gnc-get-current-session))
(book (gnc-get-current-book))
(table (gnc-commodity-table-new)))
(test-book-set-data book "gnc-commodity-table" table)
(let ((USD (gnc-commodity-new book "United States Dollar" "CURRENCY" "USD" "" 100))
(EUR (gnc-commodity-new book "European Union Euro" "CURRENCY" "EUR" "" 100)))
(gnc-commodity-table-insert table USD)
(gnc-commodity-table-insert table EUR)
(test-option-scheme-output "currency"
gnc:make-currency-option GncOption-serialize
test-currency-output-template
USD EUR)
;; Garbage collection has already eaten USD and EUR.
(test-book-clear-data book "gnc-commodity-table")
(gnc-commodity-table-destroy table)
(gnc-clear-current-session)))
(test-end "test-gnc-currency-option-to-scheme"))
(define (test-gnc-budget-option-to-scheme)
(test-begin "test-gnc-budget-option-to-scheme")
(let* ((book (gnc-get-current-book))
(budget2 (gnc-budget-new book))
(budget1 (gnc-budget-new book))
(guid1 (gncBudgetGetGUID budget1))
(guid2 (gncBudgetGetGUID budget2)))
(test-book-set-default-budget book budget1)
(gnc-budget-set-name budget1 "First Budget")
(gnc-budget-set-name budget2 "Second Budget")
(let ((odb (gnc:new-options))
(option (gnc:make-budget-option "foo" "bar" "baz" "Test Option")))
(gnc:register-option odb option)
(test-equal "budget unchanged"
test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(gnc:option-set-value (gnc:lookup-option odb "foo" "bar") budget2)
(test-equal "default budget value" (gnc-budget-get-default book) budget1)
(test-equal "budget restore form" (test-budget-output-template budget2)
(gnc:generate-restore-forms odb "options")))
(gnc-clear-current-session))
(test-end "test-gnc-budget-option-to-scheme"))
(define (test-gnc-commodity-option-to-scheme)
(test-begin "test-gnc-commodity-option-to-scheme")
(let* ((session (gnc-get-current-session))
(book (gnc-get-current-book))
(comm-tbl (gnc-commodity-table-get-table book))
(AAPL (gnc-commodity-new book "Apple" "NASDAQ" "AAPL" "" 1))
(FMAGX (gnc-commodity-new book "Fidelity Magellan Fund" "FUND" "FMAGX" "" 1000)))
(gnc-commodity-table-insert comm-tbl AAPL)
(gnc-commodity-table-insert comm-tbl FMAGX)
(test-option-scheme-output "commodity"
gnc:make-commodity-option GncOption-serialize
test-commodity-output-template
AAPL FMAGX))
(test-end "test-gnc-commodity-option-to-scheme"))
(define (test-gnc-bool-option-to-scheme)
(test-begin "test-gnc-bool-option-to-scheme")
(test-option-scheme-output "bool"
gnc:make-simple-boolean-option
GncOption-get-scm-value
test-string-output-template #f #t)
(test-end "test-gnc-bool-option-to-scheme"))
(define (test-gnc-pixmap-option-to-scheme)
(test-begin "test-gnc-pixmap-option-to-scheme")
(test-option-scheme-output "pixmap"
gnc:make-pixmap-option GncOption-get-scm-value
test-string-output-template
"" "~/mybusiness/mylogo.png")
(test-end "test-gnc-pixmap-option-to-scheme"))
(define (test-gnc-date-option-to-scheme)
(test-begin "test-gnc-date-option-to-scheme")
(let ((odb (gnc:new-options)))
(gnc:options-make-end-date! odb "foo" "bar" "baz" "Phoney Option")
(test-equal "Date Unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let* ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template)
(time (gnc-dmy2time64 25 12 2020))
(value `(absolute . ,time)))
(gnc:option-set-value option value)
(test-equal "Absolute Date" (test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
(set! value '(relative . end-prev-year))
(gnc:option-set-value option value)
(test-equal "Relative Date Value" value (GncOption-get-scm-value option))
(test-equal "Relative Date" (test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))))
(test-end "test-gnc-date-option-to-scheme"))
(define (test-gnc-account-options-to-scheme)
(define (create-account book parent type name)
(let ((account (xaccMallocAccount book)))
(xaccAccountBeginEdit account)
(xaccAccountSetType account type)
(xaccAccountSetName account name)
(xaccAccountBeginEdit parent)
(gnc-account-append-child parent account)
(xaccAccountCommitEdit parent)
(xaccAccountCommitEdit account)
account))
(define (make-account-tree book root)
(let* ((assets (create-account book root ACCT-TYPE-ASSET "Assets"))
(liabilities (create-account book root ACCT-TYPE-LIABILITY "Liabilities"))
(equity (create-account book root ACCT-TYPE-EQUITY "Equity"))
(expenses (create-account book root ACCT-TYPE-EXPENSE "Expenses"))
(equity (create-account book root ACCT-TYPE-INCOME "Income"))
(broker (create-account book assets ACCT-TYPE-EQUITY "broker"))
(stocks (create-account book broker ACCT-TYPE-STOCK "Stocks")))
(create-account book assets ACCT-TYPE-BANK "Bank")
(create-account book stocks ACCT-TYPE-STOCK "AAPL")
(create-account book stocks ACCT-TYPE-STOCK "MSFT")
(create-account book stocks ACCT-TYPE-STOCK "HPE")
(create-account book broker ACCT-TYPE-BANK "Cash Management")
(create-account book expenses ACCT-TYPE-EXPENSE "Food")
(create-account book expenses ACCT-TYPE-EXPENSE "Gas")
(create-account book expenses ACCT-TYPE-EXPENSE "Rent")))
(define (cleanup book root)
;; Destroying the book destroys the account tree too
(gnc-option-test-book-destroy book))
(define (test-gnc-account-list-option-to-scheme book)
(define (test-account-list-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o '~s))) option))
" (reverse (string-split value #\ ))))
(test-begin "test-gnc-account-list-option-to-scheme")
(let ((odb (gnc:new-options))
(acctlist (gnc-account-list-from-types book
(list ACCT-TYPE-STOCK))))
(gnc:register-option odb
(gnc:make-account-list-option
"foo" "bar" "a" "baz" (lambda () acctlist)
(lambda (ac)
(let ((type (xaccAccountGetAccountType ac)))
(or (eq type ACCT-TYPE-STOCK)
(eq type ACCT-TYPE-BANK)))) #t))
(test-equal "account list unchanged"
test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-account-list-output-template)
(new-acclist (gnc-account-list-from-types book (list ACCT-TYPE-BANK))))
(gnc:option-set-value option new-acclist)
(test-equal "account list form" ;;fails
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-account-list-option-to-scheme"))
(define (test-gnc-account-sel-option-to-scheme book)
(test-begin "test-gnc-account-sel-option-to-scheme")
(let ((odb (gnc:new-options))
(bank (gnc-account-lookup-by-name(gnc-book-get-root-account book)
"Bank")))
(gnc:register-option odb
(gnc:make-account-sel-option
"foo" "bar" "a" "baz" (lambda () '())
(lambda (ac)
(let ((type (xaccAccountGetAccountType ac)))
(or (eq type ACCT-TYPE-STOCK)
(eq type ACCT-TYPE-BANK))))))
(test-equal "account sel unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-string-output-template))
(gnc:option-set-value option bank)
(test-equal "account sel form" ;; fails
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-account-sel-option-to-scheme"))
(let* ((book (gnc-option-test-book-new))
(root-account (gnc-account-create-root book)))
(test-group-with-cleanup "test-gnc-account-options-to-schemes"
(make-account-tree book root-account)
(test-gnc-account-list-option-to-scheme book)
(test-gnc-account-sel-option-to-scheme book)
(cleanup book root-account))))
(define (test-gnc-multichoice-option-to-scheme)
(test-begin "test-gnc-multichoice-option-to-scheme")
(let ((odb (gnc:new-options))
(test-template test-literal-output-template)
(value "5"))
(gnc:register-option
odb
(gnc:make-multichoice-option
"foo" "bar" "baz" "Phoney Option" 3
(list (vector 'all "All")
(vector 1 "1") (vector 2 "2") (vector 3 "3")
(vector 4 "4") (vector 5 "5") (vector 6 "6"))))
(test-equal "multichoice unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar")))
(gnc:option-set-value option value)
(test-equal "multichoice form" (test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))))
(test-end "test-gnc-multichoice-option-to-scheme"))
(define (test-gnc-list-option-to-scheme)
(test-begin "test-gnc-list-option-to-scheme")
(let ((odb (gnc:new-options))
(choices (list (vector 'good "The Good")
(vector 'bad "The Bad")
(vector 'ugly "The Ugly"))))
(gnc:register-option odb
(gnc:make-list-option
"foo" "bar" "a" "baz" '(bad) choices))
(test-equal "list unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template))
(gnc:option-set-value option '(ugly))
(test-equal "list form" (test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-list-option-to-scheme"))
(define (test-gnc-number-range-option-to-scheme)
(test-begin "test-gnc-number-range-option-to-scheme")
(let ((odb (gnc:new-options))
(min-value 0.0)
(max-value 100.0)
(dec-places 2.0)
(step 0.10))
(gnc:register-option odb
(gnc:make-number-range-option
"foo" "bar" "a" "baz" 49.0 min-value
max-value dec-places step))
(test-equal "number-range unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template))
(gnc:option-set-value option 42.0)
(test-equal "number-range form"
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-number-range-option-to-scheme"))
(define (test-gnc-number-plot-size-option-to-scheme)
(test-begin "test-gnc-number-plot-size-option-to-scheme")
(let ((odb (gnc:new-options))
(min-value 10)
(max-value 100)
(dec-places 0)
(step 5))
(gnc:register-option odb
(gnc:make-number-plot-size-option
"foo" "bar" "a" "baz" 49 min-value
max-value dec-places step))
(test-equal "number-plot unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template))
(gnc:option-set-value option 42)
(test-equal "number-plot form"
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-number-plot-size-option-to-scheme"))
(define (test-gnc-query-option-to-scheme)
(define query-unchanged-section-output-template
"
; Section: __reg
"
)
(define (query-literal-output-template value)
(format #f "
; Section: __reg
(let ((option (gnc:lookup-option options
\"__reg\"
\"query\")))
((lambda (o) (if o (gnc:option-set-value o '~a))) option))
" value))
(test-begin "test-gnc-query-option-to-scheme")
(let ((odb (gnc:new-options))
(query-scm '(query-v2
(terms (((("book" "guid") #f guid 3 1 ("3a5a4bc736d84b879b776ea8caadd3b2"))
(("account" "guid") #f guid 3 1 ("b7e4ca23652049fca62a0e4f95296a15")))))
(search-for Split)
(primary-sort (("QofQueryDefaultSort") 0 #t))
(secondary-sort #f)
(tertiary-sort #f)
(max-results -1))))
(gnc:register-option odb
(gnc:make-query-option "__reg" "query" '()))
(test-equal "query unchanged" query-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "__reg" "query"))
(test-template query-literal-output-template))
(gnc:option-set-value option (gnc-scm2query query-scm))
(test-equal "query form" (test-template (GncOption-get-scm-value option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-query-option-to-scheme"))
(define (test-gnc-color-option-to-scheme)
(define (test-color-output-template value)
(let* ((len (string-length value))
(red (string->number (substring/shared value 0 2) 16))
(blue (string->number (substring/shared value 2 4) 16))
(green (string->number (substring/shared value 4 6) 16))
(alpha (if (> len 7)
(string->number (substring/shared value 6 8) 16)
#xff)))
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o '(~f ~f ~f ~f)))) option))
" red blue green alpha)))
(test-begin "test-gnc-coloroption-to-scheme")
(let ((odb (gnc:new-options))
(default-color (list #xb2 #x22 #x22 #xff))
(new-color (list #x00 #xca #x3b #xff)))
(gnc:register-option odb
(gnc:make-color-option
"foo" "bar" "a" "baz" default-color #f #t))
(test-equal "color unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-color-output-template))
(gnc:option-set-value option new-color)
(test-equal "color form"
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-color-option-to-scheme"))
(define (test-gnc-invoice-option-to-scheme)
(test-begin "test-gnc-invoice-option-to-scheme")
(let ((odb (gnc:new-options)))
(gnc:register-option odb
(gnc:make-invoice-option "foo" "bar" "a" "baz"
(lambda () '()) (lambda () #t)))
(test-equal "invoice unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let* ((book (gnc-get-current-book))
(inv (gncInvoiceCreate book))
(option (gnc:lookup-option odb "foo" "bar"))
(test-template test-string-output-template))
(gnc:option-set-value option inv)
(test-equal "invoice form" (test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-invoice-option-to-scheme"))
(define (test-gnc-owner-option-to-scheme)
(test-begin "test-owner-option-to-scheme")
(let ((odb (gnc:new-options)))
(gnc:register-option odb
(gnc:make-owner-option "foo" "bar" "a" "baz"
(lambda () '()) (lambda () #t)
GNC-OWNER-CUSTOMER))
(test-equal "owner unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let* ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template)
(book (gnc-get-current-book))
(owner (gncOwnerNew)))
(gncOwnerInitCustomer owner (gncCustomerCreate book))
(gnc:option-set-value option owner)
(test-equal "owner form"
(test-template (cons (gncOwnerGetType owner)
(gncOwnerReturnGUID owner)))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-owner-option-to-scheme"))
(define (test-gnc-internal-option-to-scheme)
(define (test-output-template name value)
(format #f "
(let ((option (gnc:lookup-option options
\"__reg\"
~s)))
((lambda (o) (if o (gnc:option-set-value o ~s))) option))
" name value))
(test-begin "test-gnc-internal-option-to-scheme")
(let ((odb (gnc:new-options))
(option-b (gnc:make-internal-option "__reg" "bar" #f))
(option-s (gnc:make-internal-option "__reg" "baz" "waldo")))
(gnc:register-option odb option-b)
(gnc:register-option odb option-s)
(test-equal "Internal unchanged" "
; Section: __reg
"
(gnc:generate-restore-forms odb "options"))
(gnc:option-set-value (gnc:lookup-option odb "__reg" "bar") #t)
(gnc:option-set-value (gnc:lookup-option odb "__reg" "baz") "pepper")
(test-equal "internal form" (format #f "
; Section: __reg
~a~a
"
(test-output-template "bar" #t)
(test-output-template "baz" "pepper"))
(gnc:generate-restore-forms odb "options"))
)
(test-end "test-gnc-internal-option-to-scheme"))
;; The following are saved only to KVP, no Scheme generator needed:
;;(define (test-gnc-dateformat-option-to-scheme)
;;(define (test-gnc-taxtable-option-to-scheme)
;;(define (test-gnc-counter-option-to-scheme)
;;(define (test-gnc-counter-format-option-to-scheme)

View File

@ -0,0 +1,249 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; test-gnc-option.scm -- unit tests for GncOption class. ;
; Copyright (C) 2019 John Ralls <jralls@ceridwen.us> ;
; ;
; 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 ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-modules (srfi srfi-64))
(use-modules (tests srfi64-extras))
;; This is a special case where we can't use the exported registration function
;; because we need to transform the default argument first depending on its
;; Scheme type.
(define (gnc:register-multichoice-option options section name key docstring default multichoice)
(issue-deprecation-warning "gnc:make-multichoice-option is deprecated. Make and register the option in one command with gnc-register-multichoice-option.")
(let ((defval (cond ((symbol? default)
(symbol->string default))
((number? default)
(number->string default))
(else default))))
(gnc-register-multichoice-option options section name key docstring defval multichoice)))
;; Load the C++ option implementation, avoiding the options.scm ones.
(eval-when
(compile load eval expand)
(load-extension "libgnc-app-utils" "scm_init_sw_app_utils_module"))
(use-modules (gnucash engine))
(use-modules (sw_app_utils))
(define (run-test)
(test-runner-factory gnc:test-runner)
(test-begin "test-gnc-optiondb-scheme")
(test-gnc-make-text-option)
(test-gnc-make-account-list-options)
(test-gnc-make-multichoice-option)
(test-gnc-make-list-option)
(test-gnc-make-date-option)
(test-gnc-make-date-set-option)
(test-gnc-make-number-range-option)
(test-gnc-make-report-placement-option)
(test-end "test-gnc-optiondb-scheme"))
(define (test-gnc-make-text-option)
(test-begin "test-gnc-test-string-option")
(let* ((option-db (new-gnc-optiondb))
(string-opt (gnc-register-string-option option-db "foo" "bar" "baz"
"Phony Option" "waldo")))
(test-equal "waldo" (gnc-option-value option-db "foo" "bar"))
(gnc-set-option option-db "foo" "bar" "pepper")
(test-equal "pepper" (gnc-option-value option-db "foo" "bar")))
(test-end "test-gnc-make-string-option"))
(define (test-gnc-make-account-list-options)
(define (create-account book parent type name)
(let ((account (xaccMallocAccount book)))
(xaccAccountBeginEdit account)
(xaccAccountSetType account type)
(xaccAccountSetName account name)
(xaccAccountBeginEdit parent)
(gnc-account-append-child parent account)
(xaccAccountCommitEdit parent)
(xaccAccountCommitEdit account)
account))
(define (make-account-tree book root)
(let* ((assets (create-account book root ACCT-TYPE-ASSET "Assets"))
(liabilities (create-account book root ACCT-TYPE-LIABILITY "Liabilities"))
(equity (create-account book root ACCT-TYPE-EQUITY "Equity"))
(expenses (create-account book root ACCT-TYPE-EXPENSE "Expenses"))
(equity (create-account book root ACCT-TYPE-INCOME "Income"))
(broker (create-account book assets ACCT-TYPE-EQUITY "broker"))
(stocks (create-account book broker ACCT-TYPE-STOCK "Stocks")))
(create-account book assets ACCT-TYPE-BANK "Bank")
(create-account book stocks ACCT-TYPE-STOCK "AAPL")
(create-account book stocks ACCT-TYPE-STOCK "MSFT")
(create-account book stocks ACCT-TYPE-STOCK "HPE")
(create-account book broker ACCT-TYPE-BANK "Cash Management")
(create-account book expenses ACCT-TYPE-EXPENSE "Food")
(create-account book expenses ACCT-TYPE-EXPENSE "Gas")
(create-account book expenses ACCT-TYPE-EXPENSE "Rent")))
(define (cleanup book root)
;; Destroying the book destroys the account tree too
(gnc-option-test-book-destroy book))
(define (test-make-account-list-option book)
(test-group "test-make-account-list-option"
(let ((option-db (new-gnc-optiondb))
(acctlist (gnc-account-list-from-types book
(list ACCT-TYPE-STOCK))))
(gnc-register-account-list-option option-db "foo" "bar" "baz"
"Phony Option" acctlist)
(let ((acct-list (gnc-option-value option-db "foo" "bar")))
(test-equal (length acctlist) (length acct-list))
(test-equal (car acctlist) (car acct-list))) )))
(define (test-make-account-list-limited-option book)
(test-group "test-make-account-list-limited-option"
(let ((option-db (new-gnc-optiondb))
(acctlist (gnc-account-list-from-types book
(list ACCT-TYPE-STOCK))))
(gnc-register-account-list-limited-option ;; Error not account type twice
option-db "foo" "bar" "baz"
"Phony Option" acctlist (list ACCT-TYPE-STOCK))
(let ((acct-list (gnc-option-value option-db "foo" "bar")))
(test-equal (length acctlist) (length acct-list)) ;; fails acct-list 4 vs #f
(test-equal (cadr acctlist) (cadr acct-list))) ;; fails () vs. #f both wrong
(gnc-register-account-list-limited-option
option-db "waldo" "pepper" "baz"
"Phony Option" acctlist (list ACCT-TYPE-BANK))
(let ((acct-list (gnc-option-value option-db "waldo" "pepper")))
(test-equal #f (length acct-list))))))
(define (test-make-account-sel-limited-option book)
(test-group "test-make-account-list-option"
(let ((option-db (new-gnc-optiondb))
(acctlist (gnc-account-list-from-types book
(list ACCT-TYPE-STOCK))))
(gnc-register-account-sel-limited-option
option-db "salt" "pork" "baz"
"Phony Option" (cadr acctlist) (list ACCT-TYPE-STOCK))
(let ((acct (gnc-option-value option-db "salt" "pork")))
(test-equal (cadr acctlist) acct)))))
(let* ((book (gnc-option-test-book-new))
(root-account (gnc-account-create-root book)))
(test-group-with-cleanup "test-gnc-make-account-list-options"
(make-account-tree book root-account)
(test-make-account-list-option book)
(test-make-account-list-limited-option book)
(test-make-account-sel-limited-option book)
(cleanup book root-account))))
(define (test-gnc-make-multichoice-option)
(define (keylist->vectorlist keylist)
(map
(lambda (item)
(vector
(car item)
(keylist-get-info keylist (car item) 'text)
(keylist-get-info keylist (car item) 'tip)))
keylist))
(define (keylist-get-info keylist key info)
(assq-ref (assq-ref keylist key) info))
(test-begin "test-gnc-test-multichoice-option")
(let* ((option-db (new-gnc-optiondb))
(multilist (list
(list "plugh" (cons 'text "xyzzy") (cons 'tip "thud"))
(list 'waldo (cons 'text "pepper") (cons 'tip "salt"))
(list "pork" (cons 'text "sausage") (cons 'tip "links"))
(list "corge" (cons 'text "grault") (cons 'tip "garply"))))
(multichoice (keylist->vectorlist multilist))
(multi-opt (gnc:register-multichoice-option option-db "foo" "bar" "baz"
"Phony Option" 'waldo multichoice)))
(test-equal 'waldo (gnc-option-value option-db "foo" "bar"))
(gnc-set-option option-db "foo" "bar" "corge")
(test-equal "corge" (gnc-option-value option-db "foo" "bar"))
(test-equal 'waldo (gnc-option-default-value option-db "foo" "bar")))
(test-end "test-gnc-test-multichoice-option"))
(define (test-gnc-make-list-option)
(test-begin "test-gnc-test-list-option")
(let* ((option-db (new-gnc-optiondb))
(value-list (list (vector "AvgBalPlot" "Average" "Average Balance")
(vector "GainPlot" "Profit" "Profit (Gain minus Loss)")
(vector "GLPlot" "Gain/Loss" "Gain and Loss")))
(list-op (gnc-register-list-option option-db "foo" "bar" "baz"
"Phony Option" "AvgBalPlot"
value-list)))
(test-equal '("AvgBalPlot") (gnc-option-value option-db "foo" "bar"))
(gnc-set-option option-db "foo" "bar" '("GainPlot" "GLPlot"))
(test-equal '("GainPlot" "GLPlot") (gnc-option-value option-db "foo" "bar"))
(test-equal '("AvgBalPlot") (gnc-option-default-value option-db "foo" "bar")))
(test-end "test-gnc-test-list-option"))
(define (test-gnc-make-date-option)
(test-begin "test-gnc-test-date-option")
(let* ((option-db (new-gnc-optiondb))
(date-opt (gnc-register-date-option option-db "foo" "bar"
"baz" "Phony Option"
(RelativeDatePeriod-TODAY)))
(a-time (gnc-dmy2time64 11 07 2019)))
(test-equal '(relative . today) (gnc-option-value option-db "foo" "bar"))
(gnc-set-option option-db "foo" "bar" a-time)
(test-equal `(absolute . ,a-time) (gnc-option-value option-db "foo" "bar")))
(test-end "test-gnc-test-date-option"))
(define (test-gnc-make-date-set-option)
(test-begin "test-gnc-test-date-set-option")
(let* ((option-db (new-gnc-optiondb))
(date-opt (gnc-register-date-option-set
option-db "foo" "bar" "baz" "Phony Option"
'(today
start-this-month
start-prev-month
start-current-quarter
start-prev-quarter
start-cal-year
start-cal-year
start-prev-year
start-accounting-period) #t)))
(test-equal '(relative . start-accounting-period)
(gnc-option-value option-db "foo" "bar")))
(test-end "test-gnc-test-date-set-option"))
(define (test-gnc-make-number-range-option)
(test-begin "test-gnc-number-range-option")
(let* ((option-db (new-gnc-optiondb))
(number-opt (gnc-register-number-range-option-double option-db "foo" "bar"
"baz" "Phony Option"
15 5 30 1)))
(test-equal 15.0 (gnc-option-value option-db "foo" "bar"))
(gnc-set-option option-db "foo" "bar" 20)
(test-equal 20.0 (gnc-option-value option-db "foo" "bar")))
(test-end "test-gnc-number-range-option"))
(define (test-gnc-make-report-placement-option)
(test-begin "test-gnc-report-placement-option")
(let* ((report1 123)
(report2 456)
(rp (list (list report1 2 3) (list report2 3 2)))
(option-db (new-gnc-optiondb)))
(gnc-register-report-placement-option option-db "foo" "bar")
(gnc-set-option option-db "foo" "bar" rp)
(test-equal report2 (car (cadr (gnc-option-value option-db "foo" "bar")))))
(test-end "test-gnc-report-placement-option"))

View File

@ -1,262 +0,0 @@
/********************************************************************
* test-gnc-ui-util.c: GLib g_test test suite for gnc-ui-util.c. *
* Copyright 2015 Alex Aycinena <alex.aycinena@gmail.com> *
* *
* 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, you can retrieve it from *
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.html *
* or 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.h>
#include <unittest-support.h>
#include <qof.h>
#include "test-engine-stuff.h"
#include "../gnc-ui-util.h"
static const gchar *suitename = "/app-utils/gnc-ui-util";
void test_suite_gnc_ui_util (void);
typedef struct
{
QofBook *book;
GSList *hdlrs;
} Fixture;
/* Expose a mostly-private QofInstance function to load options into
* the Book.
*/
/*extern KvpFrame *qof_instance_get_slots (const QofInstance*); */
static void
setup (Fixture *fixture, gconstpointer pData)
{
fixture->book = qof_book_new ();
fixture->hdlrs = NULL;
}
static void
teardown (Fixture *fixture, gconstpointer pData)
{
qof_book_destroy (fixture->book);
g_slist_free_full (fixture->hdlrs, test_free_log_handler);
test_clear_error_list();
}
static void
test_book_use_book_currency( Fixture *fixture, gconstpointer pData )
{
const gchar *cur;
const gchar *pol;
Account *acct, *acc;
g_test_message( "Testing with no currency accounting method selected" );
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
g_test_message( "Testing with trading accounts set to true - t" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"trading-accts", "t",
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with valid book-currency but default-gains-policy set to nonsense and default-gain-loss-account-guid set to random valid acct" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "USD",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "random",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
/* g_test_message( "Testing with valid default-gains-policy but book-currency set to nonsense and default-gain-loss-account-guid set to random valid acct" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "myMoney",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "fifo",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with book-currency and default-gains-policy set to nonsense and default-gain-loss-account-guid set to random valid acct" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "myMoney",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "random",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with book-currency set and no default-gains-policy and default-gain-loss-account-guid set to random valid acct" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "USD",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with default-gains-policy set and no book-currency and default-gain-loss-account-guid set to random valid acct" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "fifo",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with book-currency, default-gains-policy and default-gain-loss-account-guid set to valid values and with trading accounts set to true - t" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"trading-accts", "t",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "USD",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "fifo",
NULL);
acc = get_random_account( fixture-> book );
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , NULL );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , NULL );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert (acct == NULL );
g_assert( !gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book);
qof_book_destroy( fixture->book );
fixture->book = qof_book_new();
g_test_message( "Testing with book-currency, default-gains-policy and default-gain-loss-account-guid set to valid values and no trading accounts flag" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "USD",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "fifo",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)),
NULL);
cur = gnc_book_get_book_currency_name( fixture-> book );
g_assert_cmpstr( cur, == , "USD" );
pol = gnc_book_get_default_gains_policy( fixture-> book );
g_assert_cmpstr( pol, == , "fifo" );
acct = gnc_book_get_default_gain_loss_acct ( fixture-> book );
g_assert ( xaccAccountEqual(acct, acc, TRUE) );
g_assert( gnc_book_use_book_currency ( fixture-> book ));
qof_book_commit_edit (fixture->book); */
}
void
test_suite_gnc_ui_util (void)
{
GNC_TEST_ADD( suitename, "use book-currency", Fixture, NULL, setup, test_book_use_book_currency, teardown );
}

View File

@ -1,137 +0,0 @@
/********************************************************************
* test-option-util.cpp: GLib test suite for option-util.c. *
* Copyright 2013 John Ralls <jralls@ceridwen.us> *
* *
* 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, you can retrieve it from *
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.html *
* or 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 <kvp-frame.hpp>
#include <gmp.h>
#include <config.h>
#include <glib.h>
extern "C"
{
#include <unittest-support.h>
#include <qofbookslots.h>
#include "test-engine-stuff.h"
#include "../option-util.h"
}
static const gchar *suitename = "/app-utils/option-util";
extern "C" void test_suite_option_util (void);
typedef struct
{
QofBook *book;
GSList *hdlrs;
} Fixture;
/* Expose a mostly-private QofInstance function to load options into
* the Book.
*/
extern "C" KvpFrame *qof_instance_get_slots (const QofInstance*);
static void
setup (Fixture *fixture, gconstpointer pData)
{
fixture->book = qof_book_new ();
fixture->hdlrs = NULL;
}
static void
setup_kvp (Fixture *fixture, gconstpointer pData)
{
QofBook *book;
KvpFrame *slots;
setup (fixture, pData);
book = fixture->book;
slots = qof_instance_get_slots (QOF_INSTANCE (book));
qof_begin_edit (QOF_INSTANCE (book));
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",
"split-action-num-field", "t",
"autoreadonly-days", (double)21,
NULL);
slots->set_path({"options", "Business", "Company Name"},
new KvpValue(g_strdup ("Bogus Company")));
qof_commit_edit (QOF_INSTANCE (book));
}
static void
teardown (Fixture *fixture, gconstpointer pData)
{
qof_book_destroy (fixture->book);
g_slist_free_full (fixture->hdlrs, test_free_log_handler);
test_clear_error_list();
}
static void
test_option_load (Fixture *fixture, gconstpointer pData)
{
gchar *str = NULL;
SCM symbol_value;
QofBook *book = fixture->book;
GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
qof_book_load_options (book, gnc_option_db_load, odb);
g_assert (gnc_option_db_lookup_boolean_option (odb, OPTION_SECTION_ACCOUNTS, OPTION_NAME_TRADING_ACCOUNTS, FALSE));
g_assert (gnc_option_db_lookup_boolean_option (odb,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_NUM_FIELD_SOURCE, FALSE));
g_assert_cmpstr (gnc_option_db_lookup_string_option (odb, "Business", "Company Name", FALSE), ==, "Bogus Company");
g_assert_cmpfloat (gnc_option_db_lookup_number_option (odb, OPTION_SECTION_ACCOUNTS, OPTION_NAME_AUTO_READONLY_DAYS, FALSE), ==, 21);
gnc_option_db_destroy (odb);
}
static void
test_option_save (Fixture *fixture, gconstpointer pData)
{
QofBook *book = fixture->book;
GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
g_assert (gnc_option_db_set_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS,
TRUE));
g_assert (gnc_option_db_set_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_NUM_FIELD_SOURCE,
TRUE));
g_assert (gnc_option_db_set_string_option (odb, "Business", "Company Name",
"Bogus Company"));
g_assert (gnc_option_db_set_number_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_AUTO_READONLY_DAYS,
17));
qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
g_assert_cmpstr (slots->get_slot({"options", "Accounts", "Use Trading Accounts"})->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot({"options", "Accounts", "Use Split Action Field for Number"})->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot({"options", "Business", "Company Name"})->get<const char*>(), ==, "Bogus Company");
g_assert_cmpfloat (slots->get_slot({"options", "Accounts", "Day Threshold for Read-Only Transactions (red line)"})->get<double>(), ==, 17);
gnc_option_db_destroy (odb);
}
extern "C" void
test_suite_option_util (void)
{
GNC_TEST_ADD (suitename, "Option DB Load", Fixture, NULL, setup_kvp, test_option_load, teardown);
GNC_TEST_ADD (suitename, "Option DB Save", Fixture, NULL, setup, test_option_save, teardown);
}

View File

@ -1,4 +1,9 @@
(use-modules (gnucash app-utils))
;;(use-modules (gnucash app-utils))
;; Load the C++ option implementation, avoiding the options.scm ones.
(eval-when
(compile load eval expand)
(load-extension "libgnc-app-utils" "scm_init_sw_app_utils_module"))
(use-modules (sw_app_utils))
(use-modules (srfi srfi-64))
(use-modules (tests srfi64-extras))
@ -9,19 +14,16 @@
(test-end "test-options"))
(define (test-lookup-option)
(let ((options (gnc:new-options)))
(gnc:register-option
(let* ((options (new-gnc-optiondb))
(string-opt (gnc-register-string-option options "Section" "Start Date"
"sort-tag" "docstring" "waldo")
))
(gnc-register-simple-boolean-option
options
(gnc:make-simple-boolean-option
"Section" "Start Date" "sort-tag" "docstring" 'default-val))
(gnc:register-option
options
(gnc:make-simple-boolean-option
"Filter" "Void Transactions" "sort-tag" "docstring" 'default-val))
(test-assert "lookup-option changed name"
(gnc:lookup-option options "Section" "From"))
(test-assert "lookup-option changed section and name"
(gnc:lookup-option options "Section" "Void Transactions?"))))
"Filter" "Void Transactions" "sort-tag" "docstring" 'default-val)
;; Testing that the old option name aliases work.
(let ((option (gnc-lookup-option options "Section" "From")))
(test-assert "lookup-option changed name" option))
(let ((option (gnc-lookup-option options "Section" "Void Transactions?")))
(test-assert "lookup-option changed section and name" option))))

View File

@ -188,22 +188,6 @@ gnc_book_option_num_field_source_change (gboolean num_action)
g_hook_list_invoke(bo_final_hook_list, TRUE);
}
/** Calls registered callbacks when book_currency book option changes so that
* registers/reports can update themselves */
void
gnc_book_option_book_currency_selected (gboolean use_book_currency)
{
GHookList *hook_list;
const gchar *key = OPTION_NAME_BOOK_CURRENCY;
g_once(&bo_init_once, bo_init, NULL);
hook_list = g_hash_table_lookup(bo_callback_hash, key);
if (hook_list != NULL)
g_hook_list_marshal(hook_list, TRUE, bo_call_hook, &use_book_currency);
g_hook_list_invoke(bo_final_hook_list, TRUE);
}
void
gnc_book_option_register_cb (gchar *key, GncBOCb func, gpointer user_data)
{

View File

@ -74,11 +74,6 @@ void gnc_set_num_action (Transaction *trans, Split *split,
void
gnc_book_option_num_field_source_change (gboolean num_action);
/** Calls registered callbacks when book_currency book option changes so that
* registers/reports can update themselves */
void
gnc_book_option_book_currency_selected (gboolean use_book_currency);
/** Registers callbacks to be called when the book option changes for the
* specified book option key */
void

View File

@ -1548,15 +1548,15 @@ gnc_gdate_set_quarter_end (GDate *date)
void
gnc_gdate_set_prev_quarter_start (GDate *date)
{
gnc_gdate_set_quarter_start(date);
g_date_subtract_months(date, 3);
gnc_gdate_set_quarter_start(date);
}
void
gnc_gdate_set_prev_quarter_end (GDate *date)
{
gnc_gdate_set_quarter_end(date);
g_date_subtract_months(date, 3);
gnc_gdate_set_quarter_end(date);
}
/* ================================================= */

View File

@ -45,7 +45,6 @@ static gncFeature known_features[] =
{ GNC_FEATURE_CREDIT_NOTES, "Customer and vendor credit notes (requires at least GnuCash 2.5.0)" },
{ GNC_FEATURE_NUM_FIELD_SOURCE, "User specifies source of 'num' field'; either transaction number or split action (requires at least GnuCash 2.5.0)" },
{ GNC_FEATURE_KVP_EXTRA_DATA, "Extra data for addresses, jobs or invoice entries (requires at least GnuCash 2.6.4)" },
{ GNC_FEATURE_BOOK_CURRENCY, "User specifies a 'book-currency'; costs of other currencies/commodities tracked in terms of book-currency (requires at least GnuCash 2.7.0)" },
{ GNC_FEATURE_GUID_BAYESIAN, "Use account GUID as key for Bayesian data (requires at least GnuCash 2.6.12)" },
{ GNC_FEATURE_GUID_FLAT_BAYESIAN, "Use account GUID as key for bayesian data and store KVP flat (requires at least Gnucash 2.6.19)" },
{ GNC_FEATURE_SQLITE3_ISO_DATES, "Use ISO formatted date-time strings in SQLite3 databases (requires at least GnuCash 2.6.20)"},

View File

@ -48,7 +48,6 @@ extern "C" {
#define GNC_FEATURE_CREDIT_NOTES "Credit Notes"
#define GNC_FEATURE_NUM_FIELD_SOURCE "Number Field Source"
#define GNC_FEATURE_KVP_EXTRA_DATA "Extra data in addresses, jobs or invoice entries"
#define GNC_FEATURE_BOOK_CURRENCY "Use a Book-Currency"
#define GNC_FEATURE_GUID_BAYESIAN "Account GUID based Bayesian data"
#define GNC_FEATURE_GUID_FLAT_BAYESIAN "Account GUID based bayesian with flat KVP"
#define GNC_FEATURE_SQLITE3_ISO_DATES "ISO-8601 formatted date strings in SQLite3 databases."

View File

@ -1090,7 +1090,7 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
}
catch (const std::exception& err)
{
PWARN("%s", err.what());
DEBUG("%s", err.what());
return FALSE;
}
}

View File

@ -29,6 +29,8 @@
#include <iomanip>
#include <stdexcept>
using boost::typeindex::type_id;
KvpValueImpl::KvpValueImpl(KvpValueImpl const & other) noexcept
{
duplicate(other);
@ -58,7 +60,7 @@ KvpValueImpl *
KvpValueImpl::add(KvpValueImpl * val) noexcept
{
/* If already a glist here, just append */
if (this->datastore.type() == typeid(GList*))
if (this->datastore.type() == type_id<GList*>())
{
GList * list = boost::get<GList*>(datastore);
datastore = g_list_append (list, val);
@ -75,23 +77,23 @@ KvpValueImpl::add(KvpValueImpl * val) noexcept
KvpValue::Type
KvpValueImpl::get_type() const noexcept
{
if (datastore.type() == typeid(int64_t))
if (datastore.type() == type_id<int64_t>())
return KvpValue::Type::INT64;
else if (datastore.type() == typeid(double))
else if (datastore.type() == type_id<double>())
return KvpValue::Type::DOUBLE;
else if (datastore.type() == typeid(gnc_numeric))
else if (datastore.type() == type_id<gnc_numeric>())
return KvpValue::Type::NUMERIC;
else if (datastore.type() == typeid(const gchar *))
else if (datastore.type() == type_id<const gchar *>())
return KvpValue::Type::STRING;
else if (datastore.type() == typeid(GncGUID *))
else if (datastore.type() == type_id<GncGUID *>())
return KvpValue::Type::GUID;
else if (datastore.type() == typeid(Time64))
else if (datastore.type() == type_id<Time64>())
return KvpValue::Type::TIME64;
else if (datastore.type() == typeid(GList *))
else if (datastore.type() == type_id<GList *>())
return KvpValue::Type::GLIST;
else if (datastore.type() == typeid(KvpFrameImpl *))
else if (datastore.type() == type_id<KvpFrameImpl *>())
return KvpValue::Type::FRAME;
else if (datastore.type() == typeid(GDate))
else if (datastore.type() == type_id<GDate>())
return KvpValue::Type::GDATE;
return KvpValue::Type::INVALID;
@ -100,7 +102,7 @@ KvpValueImpl::get_type() const noexcept
KvpFrame *
KvpValueImpl::replace_frame_nc (KvpFrame * new_value) noexcept
{
if (datastore.type() != typeid(KvpFrame *))
if (datastore.type() != type_id<KvpFrame *>())
return {};
auto ret = boost::get<KvpFrame *>(datastore);
datastore = new_value;
@ -110,7 +112,7 @@ KvpValueImpl::replace_frame_nc (KvpFrame * new_value) noexcept
GList *
KvpValueImpl::replace_glist_nc (GList * new_value) noexcept
{
if (datastore.type() != typeid(GList *))
if (datastore.type() != type_id<GList *>())
return {};
auto ret = boost::get<GList *>(datastore);
datastore = new_value;
@ -206,7 +208,7 @@ struct to_string_visitor : boost::static_visitor<void>
std::string
KvpValueImpl::to_string(std::string const & prefix) const noexcept
{
if (this->datastore.type() == typeid(KvpFrame*))
if (this->datastore.type() == type_id<KvpFrame*>())
return this->get<KvpFrame*>()->to_string(prefix);
std::ostringstream ret;
to_string_visitor visitor {ret};
@ -390,13 +392,13 @@ KvpValueImpl::~KvpValueImpl() noexcept
void
KvpValueImpl::duplicate(const KvpValueImpl& other) noexcept
{
if (other.datastore.type() == typeid(const gchar *))
if (other.datastore.type() == type_id<const gchar *>())
this->datastore = const_cast<const gchar *>(g_strdup(other.get<const gchar *>()));
else if (other.datastore.type() == typeid(GncGUID*))
else if (other.datastore.type() == type_id<GncGUID*>())
this->datastore = guid_copy(other.get<GncGUID *>());
else if (other.datastore.type() == typeid(GList*))
else if (other.datastore.type() == type_id<GList*>())
this->datastore = kvp_glist_copy(other.get<GList *>());
else if (other.datastore.type() == typeid(KvpFrame*))
else if (other.datastore.type() == type_id<KvpFrame*>())
this->datastore = new KvpFrame(*other.get<KvpFrame *>());
else
this->datastore = other.datastore;

View File

@ -174,7 +174,7 @@ KvpValueImpl::KvpValueImpl(T newvalue) noexcept:
template <typename T> T
KvpValueImpl::get() const noexcept
{
if (this->datastore.type() != typeid(T)) return {};
if (this->datastore.type() != boost::typeindex::type_id<T>()) return {};
return boost::get<T>(datastore);
}

View File

@ -63,9 +63,6 @@
struct gncpolicy_s
{
char *name;
char *description;
char *hint;
GNCLot * (*PolicyGetLot) (GNCPolicy *, Split *split);
Split * (*PolicyGetSplit) (GNCPolicy *, GNCLot *lot);
void (*PolicyGetLotOpening) (GNCPolicy *, GNCLot *lot,

View File

@ -63,47 +63,6 @@
//static QofLogModule log_module = GNC_MOD_LOT;
GList *
gnc_get_valid_policy_list (void)
{
GList *return_list = NULL;
/* return_list = g_list_prepend (return_list, xaccGetManualPolicy());
return_list = g_list_prepend (return_list, xaccGetAveragePolicy()); */
return_list = g_list_prepend (return_list, xaccGetLIFOPolicy());
return_list = g_list_prepend (return_list, xaccGetFIFOPolicy());
return return_list;
}
gboolean
gnc_valid_policy_name (const gchar *policy_name)
{
GList *list_of_policies = NULL;
gboolean ret_val = FALSE;
if (!policy_name)
return ret_val;
list_of_policies = gnc_get_valid_policy_list();
if (!list_of_policies)
{
return ret_val;
}
else
{
GList *l = NULL;
for (l = list_of_policies; l != NULL; l = l->next)
{
GNCPolicy *list_pcy = l->data;
if (g_strcmp0(PolicyGetName (list_pcy), policy_name) == 0)
ret_val = TRUE;
}
g_list_free(list_of_policies);
return ret_val;
}
}
static Split *
DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
{
@ -189,26 +148,6 @@ donext:
return NULL;
}
const char *
PolicyGetName (const GNCPolicy *pcy)
{
if(!pcy) return NULL;
return pcy->name;
}
const char *
PolicyGetDescription (const GNCPolicy *pcy)
{
if(!pcy) return NULL;
return pcy->description;
}
const char *
PolicyGetHint (const GNCPolicy *pcy)
{
if(!pcy) return NULL;
return pcy->hint;
}
/* ============================================================== */
static GNCLot *
@ -255,9 +194,6 @@ xaccGetFIFOPolicy (void)
if (!pcy)
{
pcy = g_new (GNCPolicy, 1);
pcy->name = FIFO_POLICY;
pcy->description = FIFO_POLICY_DESC;
pcy->hint = FIFO_POLICY_HINT;
pcy->PolicyGetLot = FIFOPolicyGetLot;
pcy->PolicyGetSplit = FIFOPolicyGetSplit;
pcy->PolicyGetLotOpening = FIFOPolicyGetLotOpening;
@ -304,23 +240,4 @@ LIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split)
return (split == opening_split);
}
GNCPolicy *
xaccGetLIFOPolicy (void)
{
static GNCPolicy *pcy = NULL;
if (!pcy)
{
pcy = g_new (GNCPolicy, 1);
pcy->name = LIFO_POLICY;
pcy->description = LIFO_POLICY_DESC;
pcy->hint = LIFO_POLICY_HINT;
pcy->PolicyGetLot = LIFOPolicyGetLot;
pcy->PolicyGetSplit = LIFOPolicyGetSplit;
pcy->PolicyGetLotOpening = LIFOPolicyGetLotOpening;
pcy->PolicyIsOpeningSplit = LIFOPolicyIsOpeningSplit;
}
return pcy;
}
/* =========================== END OF FILE ======================= */

Some files were not shown because too many files have changed in this diff Show More