gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Thu Feb 2 16:59:15 EST 2023
Updated via https://github.com/Gnucash/gnucash/commit/12db8eaa (commit)
via https://github.com/Gnucash/gnucash/commit/cbf39074 (commit)
via https://github.com/Gnucash/gnucash/commit/07f3f536 (commit)
via https://github.com/Gnucash/gnucash/commit/b41e491e (commit)
via https://github.com/Gnucash/gnucash/commit/b49b5c86 (commit)
via https://github.com/Gnucash/gnucash/commit/019214f1 (commit)
from https://github.com/Gnucash/gnucash/commit/63f8e731 (commit)
commit 12db8eaaf268f2b2e49f908e92f706f22a4be9db
Merge: 63f8e7314 cbf39074c
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Feb 2 13:27:51 2023 -0800
Merge Bob Fewell's 'bug753307master' into master.
diff --cc po/POTFILES.in
index 2e80b84b3,2e80b84b3..d7bd709b4
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@@ -185,6 -185,6 +185,7 @@@ gnucash/gnome-utils/gnc-plugin-menu-add
gnucash/gnome-utils/gnc-plugin-page.c
gnucash/gnome-utils/gnc-query-view.c
gnucash/gnome-utils/gnc-recurrence.c
++gnucash/gnome-utils/gnc-report-combo.c
gnucash/gnome-utils/gnc-splash.c
gnucash/gnome-utils/gnc-sx-instance-dense-cal-adapter.c
gnucash/gnome-utils/gnc-sx-list-tree-model-adapter.c
commit cbf39074c2b3b552dd53f526d2a60036527fb7f7
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Wed Feb 1 16:27:56 2023 +0000
Remove the old preference setting for default invoice report
Remove preference setting and set the schema to be depreciated in
version 5000 and removed in version 6000.
diff --git a/gnucash/gschemas/pref_transformations.xml b/gnucash/gschemas/pref_transformations.xml
index 55af940bf..4220b0073 100644
--- a/gnucash/gschemas/pref_transformations.xml
+++ b/gnucash/gschemas/pref_transformations.xml
@@ -2152,4 +2152,16 @@
<obsolete old-path="org.gnucash.window.pages.account-tree.summary"
old-key="end-period"/>
+<deprecate old-path="org.gnucash.GnuCash.dialogs.business.invoice"
+ old-key="invoice-printreport" />
+
</release>
+
+<!--
+<release version="6000">
+
+<obsolete old-path="org.gnucash.GnuCash.dialogs.business.invoice"
+ old-key="invoice-printreport"/>
+
+</release>
+-->
diff --git a/gnucash/gtkbuilder/business-prefs.glade b/gnucash/gtkbuilder/business-prefs.glade
index 4e2664af5..770c973cb 100644
--- a/gnucash/gtkbuilder/business-prefs.glade
+++ b/gnucash/gtkbuilder/business-prefs.glade
@@ -16,26 +16,6 @@
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
- <object class="GtkListStore" id="liststore_printinvoice">
- <columns>
- <!-- column-name item -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">Printable Invoice</col>
- </row>
- <row>
- <col id="0" translatable="yes">Tax Invoice</col>
- </row>
- <row>
- <col id="0" translatable="yes">Easy Invoice</col>
- </row>
- <row>
- <col id="0" translatable="yes">Fancy Invoice</col>
- </row>
- </data>
- </object>
<object class="GtkWindow" id="preferences_window">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -158,18 +138,6 @@
<property name="top-attach">6</property>
</packing>
</child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Report for printing</property>
- </object>
- <packing>
- <property name="left-attach">0</property>
- <property name="top-attach">7</property>
- </packing>
- </child>
<child>
<object class="GtkCheckButton" id="pref/dialogs.business.invoice/tax-included">
<property name="label" translatable="yes">_Tax included</property>
@@ -185,7 +153,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">8</property>
+ <property name="top-attach">7</property>
</packing>
</child>
<child>
@@ -203,7 +171,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">9</property>
+ <property name="top-attach">8</property>
</packing>
</child>
<child>
@@ -311,27 +279,6 @@
<property name="top-attach">12</property>
</packing>
</child>
- <child>
- <object class="GtkComboBox" id="pref/dialogs.business.invoice/invoice-printreport">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="has-tooltip">True</property>
- <property name="tooltip-markup">The invoice report to be used for printing.</property>
- <property name="tooltip-text" translatable="yes">The invoice report to be used for printing.</property>
- <property name="model">liststore_printinvoice</property>
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext2"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="left-attach">1</property>
- <property name="top-attach">7</property>
- <property name="width">2</property>
- </packing>
- </child>
<child>
<object class="GtkSpinButton" id="pref/dialogs.business.invoice/days-in-advance">
<property name="visible">True</property>
@@ -431,6 +378,15 @@
<child>
<placeholder/>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
</child>
</object>
commit 07f3f536cc09209308c1b6c011a2ba684e24f1ae
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Wed Feb 1 16:26:38 2023 +0000
Allow to select saved report on print invoice button
This change was inspired by mildred's #PR1247 and uses the new
GncReportCombo to allow selection of 'Saved Invoice reports' when the
invoice print button is used or when printing multiple invoices.
This change presents a dialog with the default for the report combo set
to the properties setting. This dialog has a timeout which is
adjustable under properties and will stop if a key is pressed or combo
popped so that a different report template can be selected and used.
There is also an 'OK' button that stops the time out and prints and a
'Cancel' button which cancels the print.
diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index aeca0844e..786da9655 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -79,6 +79,7 @@
#include "dialog-doclink-utils.h"
#include "dialog-transfer.h"
#include "gnc-uri-utils.h"
+#include "gnc-report-combo.h"
#define DIALOG_NEW_INVOICE_CM_CLASS "dialog-new-invoice"
#define DIALOG_VIEW_INVOICE_CM_CLASS "dialog-view-invoice"
@@ -778,15 +779,159 @@ gnc_invoice_window_blankCB (GtkWidget *widget, gpointer data)
}
}
+typedef struct dialog_args
+{
+ GtkProgressBar *pb;
+ GtkWidget *dialog;
+ gdouble timeout;
+} dialog_args;
+
+static gboolean
+update_progress_bar (gpointer user_data)
+{
+ dialog_args *args = user_data;
+ GtkProgressBar *pb = args->pb;
+ gdouble frac = gtk_progress_bar_get_fraction (pb);
+ gdouble step = 0.1 / (args->timeout);
+
+ frac -= step;
+
+ if (frac < step)
+ {
+ gtk_dialog_response (GTK_DIALOG(args->dialog), GTK_RESPONSE_OK);
+ return FALSE;
+ }
+ gtk_progress_bar_set_fraction (pb, frac);
+ return TRUE;
+}
+
+static void
+combo_popped_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ gboolean popup_shown;
+
+ g_object_get (G_OBJECT(gobject), "popup-shown", &popup_shown, NULL);
+
+ if (popup_shown)
+ g_source_remove_by_user_data (user_data);
+}
+
+static gboolean
+dialog_key_press_event_cb (GtkWidget *widget, GdkEventKey *event,
+ gpointer user_data)
+{
+ g_source_remove_by_user_data (user_data);
+ return FALSE;
+}
+
+static void
+combo_changed_cb (GtkComboBox *widget, gpointer user_data)
+{
+ g_source_remove_by_user_data (user_data);
+}
+
+/* This function will return the selected invoice report guid if
+ * the countdown times out or a selection is made and OK pressed.
+ *
+ * If cancel is pressed then it return a NULL
+ */
+static char*
+use_default_report_template_or_change (GtkWindow *parent)
+{
+ QofBook *book = gnc_get_current_book ();
+ GtkWidget *combo;
+ GtkBuilder *builder;
+ GtkWidget *dialog;
+ GtkWidget *ok_button;
+ GtkWidget *report_combo_hbox;
+ GtkWidget *progress_bar;
+ gchar *ret_guid = NULL;
+ gchar *rep_guid = NULL;
+ gchar *rep_name = NULL;
+ gint result;
+ gdouble timeout;
+ dialog_args *args;
+
+ timeout = qof_book_get_default_invoice_report_timeout (book);
+
+ if (timeout == 0)
+ return gnc_get_default_invoice_print_report ();
+
+ combo = gnc_default_invoice_report_combo ("gnc:custom-report-invoice-template-guids");
+
+ builder = gtk_builder_new ();
+ gnc_builder_add_from_file (builder, "dialog-invoice.glade", "invoice_print_dialog");
+
+ dialog = GTK_WIDGET(gtk_builder_get_object (builder, "invoice_print_dialog"));
+
+ gtk_window_set_transient_for (GTK_WINDOW(dialog), parent);
+
+ gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+
+ ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
+ report_combo_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "report_combo_hbox"));
+ progress_bar = GTK_WIDGET(gtk_builder_get_object (builder, "progress_bar"));
+
+ gtk_box_pack_start (GTK_BOX(report_combo_hbox), GTK_WIDGET(combo), TRUE, TRUE, 0);
+
+ gtk_widget_grab_focus (ok_button);
+
+ rep_name = qof_book_get_default_invoice_report_name (book);
+ rep_guid = gnc_get_default_invoice_print_report ();
+
+ gnc_report_combo_set_active (GNC_REPORT_COMBO(combo),
+ rep_guid,
+ rep_name);
+ g_free (rep_guid);
+ g_free (rep_name);
+
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar), 1);
+
+ args = g_malloc (sizeof(dialog_args));
+ args->dialog = dialog;
+ args->pb = GTK_PROGRESS_BAR(progress_bar);
+ args->timeout = timeout;
+
+ gtk_widget_show_all (dialog);
+
+ g_object_unref (G_OBJECT(builder));
+
+ g_signal_connect (G_OBJECT(combo), "changed",
+ G_CALLBACK(combo_changed_cb), args);
+
+ g_signal_connect (G_OBJECT(dialog), "key_press_event",
+ G_CALLBACK(dialog_key_press_event_cb), args);
+
+ g_signal_connect (G_OBJECT(combo), "notify::popup-shown",
+ G_CALLBACK (combo_popped_cb), args);
+
+ g_timeout_add (100, update_progress_bar, args);
+
+ result = gtk_dialog_run (GTK_DIALOG(dialog));
+
+ g_source_remove_by_user_data (args);
+
+ if (result == GTK_RESPONSE_OK)
+ ret_guid = gnc_report_combo_get_active_guid (GNC_REPORT_COMBO(combo));
+
+ gtk_widget_destroy (dialog);
+ g_free (args);
+
+ return ret_guid;
+}
+
static GncPluginPage *
-gnc_invoice_window_print_invoice(GtkWindow *parent, GncInvoice *invoice)
+gnc_invoice_window_print_invoice (GtkWindow *parent, GncInvoice *invoice,
+ const gchar *report_guid)
{
SCM func, arg, arg2;
SCM args = SCM_EOL;
SCM is_invoice_guid;
SCM scm_guid;
int report_id;
- char *report_guid = gnc_get_default_invoice_print_report ();
+ const gchar *use_report_guid = NULL;
GncPluginPage *reportPage = NULL;
g_return_val_if_fail (invoice, NULL);
@@ -795,13 +940,15 @@ gnc_invoice_window_print_invoice(GtkWindow *parent, GncInvoice *invoice)
scm_guid = scm_from_utf8_string (report_guid);
if (scm_is_false (scm_call_1 (is_invoice_guid, scm_guid)))
- report_guid = g_strdup (gnc_get_builtin_default_invoice_print_report ()); // fallback if the option lookup failed
+ use_report_guid = gnc_get_builtin_default_invoice_print_report (); // fallback if the option lookup failed
+ else
+ use_report_guid = report_guid;
func = scm_c_eval_string ("gnc:invoice-report-create");
g_return_val_if_fail (scm_is_procedure (func), NULL);
arg = SWIG_NewPointerObj(invoice, SWIG_TypeQuery("_p__gncInvoice"), 0);
- arg2 = scm_from_utf8_string (report_guid);
+ arg2 = scm_from_utf8_string (use_report_guid);
args = scm_cons2 (arg, arg2, args);
/* scm_gc_protect_object(func); */
@@ -816,7 +963,6 @@ gnc_invoice_window_print_invoice(GtkWindow *parent, GncInvoice *invoice)
reportPage = gnc_plugin_page_report_new (report_id);
gnc_main_window_open_page (GNC_MAIN_WINDOW (parent), reportPage);
}
- g_free (report_guid);
return reportPage;
}
@@ -841,9 +987,17 @@ gnc_invoice_window_printCB (GtkWindow* parent, gpointer data)
iw->reportPage))
gnc_plugin_page_report_reload (GNC_PLUGIN_PAGE_REPORT (iw->reportPage));
else
- iw->reportPage = gnc_invoice_window_print_invoice
- (parent, iw_get_invoice (iw));
+ {
+ gchar *report_guid = use_default_report_template_or_change (parent);
+
+ if (!report_guid)
+ return;
+ iw->reportPage = gnc_invoice_window_print_invoice (parent,
+ iw_get_invoice (iw),
+ report_guid);
+ g_free (report_guid);
+ }
gnc_main_window_open_page (GNC_MAIN_WINDOW (iw->dialog), iw->reportPage);
}
@@ -3104,8 +3258,9 @@ edit_invoice_cb (GtkWindow *dialog, gpointer inv, gpointer user_data)
struct multi_edit_invoice_data
{
- gpointer user_data;
+ gpointer user_data;
GtkWindow *parent;
+ gchar *report_guid;
};
static void
@@ -3272,27 +3427,37 @@ multi_post_invoice_cb (GtkWindow *dialog, GList *invoice_list, gpointer user_dat
static void print_one_invoice_cb(GtkWindow *dialog, gpointer data, gpointer user_data)
{
GncInvoice *invoice = data;
- gnc_invoice_window_print_invoice (dialog, invoice);
+ struct multi_edit_invoice_data *meid = user_data;
+ gnc_invoice_window_print_invoice (dialog, invoice, meid->report_guid);
}
static void
multi_print_invoice_one (gpointer data, gpointer user_data)
{
struct multi_edit_invoice_data *meid = user_data;
- print_one_invoice_cb (gnc_ui_get_main_window (GTK_WIDGET(meid->parent)), data, meid->user_data);
+ print_one_invoice_cb (gnc_ui_get_main_window (GTK_WIDGET(meid->parent)), data, meid);
}
static void
multi_print_invoice_cb (GtkWindow *dialog, GList *invoice_list, gpointer user_data)
{
+ gchar *report_guid = NULL;
struct multi_edit_invoice_data meid;
if (!gnc_list_length_cmp (invoice_list, 0))
return;
+ report_guid = use_default_report_template_or_change (dialog);
+
+ if (!report_guid)
+ return;
+
meid.user_data = user_data;
meid.parent = dialog;
+ meid.report_guid = report_guid;
+
g_list_foreach (invoice_list, multi_print_invoice_one, &meid);
+ g_free (report_guid);
}
static gpointer
diff --git a/gnucash/gtkbuilder/dialog-invoice.glade b/gnucash/gtkbuilder/dialog-invoice.glade
index 9e42c84d6..eba6cd0fb 100644
--- a/gnucash/gtkbuilder/dialog-invoice.glade
+++ b/gnucash/gtkbuilder/dialog-invoice.glade
@@ -628,6 +628,133 @@
</object>
</child>
</object>
+ <object class="GtkDialog" id="invoice_print_dialog">
+ <property name="can-focus">False</property>
+ <property name="title" translatable="yes">Report template</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok_button">
+ <property name="label" translatable="yes">_OK</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="is-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="labe">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Use template report</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="report_combo_hbox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Choose a different report template before timeout</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar" id="progress_bar">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">24</property>
+ <property name="margin-end">24</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancel_button</action-widget>
+ <action-widget response="-5">ok_button</action-widget>
+ </action-widgets>
+ </object>
<object class="GtkListStore" id="terms_store">
<columns>
<!-- column-name label -->
diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp
index a3bd62990..cb13ed7b9 100644
--- a/libgnucash/engine/gnc-optiondb.cpp
+++ b/libgnucash/engine/gnc-optiondb.cpp
@@ -1277,9 +1277,13 @@ gnc_option_db_book_options(GncOptionDB* odb)
N_("The ID for your company (eg 'Tax-ID: 00-000000)."),
empty_string);
gnc_register_invoice_print_report_option(odb, business_section,
- OPTION_NAME_DEFAULT_INVOICE_REPORT, "e",
+ OPTION_NAME_DEFAULT_INVOICE_REPORT, "e1",
N_("The invoice report to be used for printing."),
empty_string);
+ gnc_register_number_range_option<double>(odb, business_section,
+ OPTION_NAME_DEFAULT_INVOICE_REPORT_TIMEOUT, "e2",
+ N_("Length of time to change the used invoice report. A value of 0 means disabled."),
+ 0.0, 0.0, 10.0, 1.0);
gnc_register_taxtable_option(odb, business_section,
N_("Default Customer TaxTable"), "f1",
N_("The default tax table to apply to customers."),
diff --git a/libgnucash/engine/qofbook.cpp b/libgnucash/engine/qofbook.cpp
index d2a9a76ec..f34c1d579 100644
--- a/libgnucash/engine/qofbook.cpp
+++ b/libgnucash/engine/qofbook.cpp
@@ -1098,6 +1098,21 @@ qof_book_get_default_invoice_report_name (const QofBook *book)
return report_name;
}
+gdouble
+qof_book_get_default_invoice_report_timeout (const QofBook *book)
+{
+ double ret = 0;
+ KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE(book));
+ KvpValue *value = root->get_slot ({KVP_OPTION_PATH,
+ OPTION_SECTION_BUSINESS,
+ OPTION_NAME_DEFAULT_INVOICE_REPORT_TIMEOUT});
+
+ if (value)
+ ret = {value->get<double>()};
+
+ return ret;
+}
+
/* Note: this will fail if the book slots we're looking for here are flattened at some point !
* When that happens, this function can be removed. */
static Path opt_name_to_path (const char* opt_name)
diff --git a/libgnucash/engine/qofbook.h b/libgnucash/engine/qofbook.h
index 3ab6c0953..dc52cf4aa 100644
--- a/libgnucash/engine/qofbook.h
+++ b/libgnucash/engine/qofbook.h
@@ -305,6 +305,11 @@ gchar * qof_book_get_default_invoice_report_guid (const QofBook *book);
*/
gchar * qof_book_get_default_invoice_report_name (const QofBook *book);
+/** Get the length of time available to change the used Invoice Report
+ * when printing Invoices
+ */
+gdouble qof_book_get_default_invoice_report_timeout (const QofBook *book);
+
/** Returns TRUE if this book uses split action field as the 'Num' field, FALSE
* if it uses transaction number field */
gboolean qof_book_use_split_action_for_num_field (const QofBook *book);
diff --git a/libgnucash/engine/qofbookslots.h b/libgnucash/engine/qofbookslots.h
index ea0e32bcd..5b9eae8bd 100644
--- a/libgnucash/engine/qofbookslots.h
+++ b/libgnucash/engine/qofbookslots.h
@@ -72,6 +72,7 @@
#define OPTION_SECTION_BUSINESS N_("Business")
#define OPTION_NAME_DEFAULT_INVOICE_REPORT N_("Default Invoice Report")
+#define OPTION_NAME_DEFAULT_INVOICE_REPORT_TIMEOUT N_("Default Invoice Report Timeout")
/** @} */
commit b41e491ec5757ebf1b71e2739ac6f92de2d419fe
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Wed Feb 1 16:10:04 2023 +0000
Modify proposed code to use new GncReportCombo widget.
diff --git a/gnucash/gnome/business-gnome-utils.c b/gnucash/gnome/business-gnome-utils.c
index 5b56f10e8..c65028d2c 100644
--- a/gnucash/gnome/business-gnome-utils.c
+++ b/gnucash/gnome/business-gnome-utils.c
@@ -54,6 +54,7 @@
#include "gnc-guile-utils.h"
#include "gnc-prefs.h"
#include "gnc-commodity.h"
+#include "gnc-report-combo.h"
typedef enum
{
@@ -106,7 +107,7 @@ gnc_get_builtin_default_invoice_print_report (void)
return PRINTABLE_INVOICE_GUID;
}
-const char *
+const char *
gnc_migrate_default_invoice_print_report (void)
{
QofBook *book = gnc_get_current_book ();
@@ -136,171 +137,41 @@ gnc_get_default_invoice_print_report (void)
return default_guid;
}
-static gboolean
-select_default (GtkWidget *combo, const gchar *default_guid)
-{
- GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo));
- GtkTreeIter iter;
- gboolean found = FALSE;
- gboolean valid_iter = gtk_tree_model_get_iter_first (model, &iter);
-
- while (valid_iter)
- {
- gchar *guid;
- gtk_tree_model_get (model, &iter, COL_INV_GUID, &guid, -1);
-
- if (g_strcmp0 (default_guid, guid) == 0)
- {
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX(combo), &iter);
- g_free (guid);
- found = TRUE;
- break;
- }
- g_free (guid);
- valid_iter = gtk_tree_model_iter_next (model, &iter);
- }
- return found;
-}
-
-/********************************************************************
- * update_invoice_list
- *
- * this procedure does the real work of displaying a sorted list of
- * available invoice reports
- ********************************************************************/
-static gchar *
-update_invoice_list (GtkWidget *combo)
+GtkWidget *
+gnc_default_invoice_report_combo (const char* guid_scm_function)
{
- SCM get_rpt_guids = scm_c_eval_string ("gnc:custom-report-invoice-template-guids");
+ GSList *invoice_list = NULL;
SCM template_menu_name = scm_c_eval_string ("gnc:report-template-menu-name/report-guid");
+ SCM get_rpt_guids = scm_c_eval_string (guid_scm_function);
SCM reportlist;
SCM rpt_guids;
- GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo));
- GtkListStore *store = GTK_LIST_STORE(model);
- gchar *default_guid = gnc_get_default_invoice_print_report ();
- gchar *default_name = NULL;
- gboolean have_default = FALSE;
-
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(model),
- COL_INV_NAME, GTK_SORT_ASCENDING);
+ if (!scm_is_procedure (get_rpt_guids))
+ return NULL;
reportlist = scm_call_0 (get_rpt_guids);
rpt_guids = reportlist;
- gtk_list_store_clear (store);
-
if (scm_is_list (rpt_guids))
{
- int i;
- GtkTreeIter iter;
-
- for (i = 0; !scm_is_null (rpt_guids); i++)
+ for (int i = 0; !scm_is_null (rpt_guids); i++)
{
gchar *guid_str = scm_to_utf8_string (SCM_CAR(rpt_guids));
gchar *name = gnc_scm_to_utf8_string (scm_call_2(template_menu_name,
SCM_CAR(rpt_guids), SCM_BOOL_F));
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- COL_INV_NAME, name,
- COL_INV_GUID, guid_str,
- COL_INV_MISSING, FALSE,
- -1);
- g_free (name);
- g_free (guid_str);
-
- rpt_guids = SCM_CDR(rpt_guids);
- }
- }
-
- have_default = select_default (combo, default_guid);
-
- if (!have_default)
- {
- GtkTreeIter iter;
- QofBook *book = gnc_get_current_book ();
- default_name = qof_book_get_default_invoice_report_name (book);
-
- gtk_list_store_prepend (store, &iter);
- gtk_list_store_set (store, &iter,
- COL_INV_NAME, default_name,
- COL_INV_GUID, default_guid,
- COL_INV_MISSING, TRUE,
- -1);
-
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX(combo), &iter);
- }
- g_free (default_guid);
- return default_name;
-}
-
-static void
-combo_changed_cb (GtkComboBox *widget, gpointer user_data)
-{
- GtkTreeIter iter;
-
- if (gtk_combo_box_get_active_iter (widget, &iter))
- {
- GtkTreeModel *model = gtk_combo_box_get_model (widget);
- gboolean missing;
- gtk_tree_model_get (model, &iter, COL_INV_MISSING, &missing, -1);
- // set visibility of the warning image
- gtk_widget_set_visible (GTK_WIDGET(user_data), missing);
- gtk_widget_queue_resize (GTK_WIDGET(widget));
- }
-}
-
-void
-gnc_default_print_report_list (GtkWidget *combo, GtkWidget *warning)
-{
- gchar *default_name = update_invoice_list (combo);
-
- if (default_name)
- {
- /* Translators: %s is the default invoice report name. */
- gchar *tool_tip = g_strdup_printf (_("'%s' is missing"),
- default_name);
- gtk_widget_show (warning);
+ // Note: invoice_list and entries freed in report combo
+ ReportListEntry *rle = g_new0 (ReportListEntry, 1);
- gtk_widget_set_tooltip_text (warning, tool_tip);
- g_free (tool_tip);
- }
- g_free (default_name);
- g_signal_connect (G_OBJECT(combo), "changed",
- G_CALLBACK(combo_changed_cb), warning);
-}
+ rle->report_guid = guid_str;
+ rle->report_name = name;
-void
-gnc_default_print_report_list_combo_set_report (GtkComboBox *cbox,
- const gchar *guid)
-{
- if (guid && *guid)
- select_default (GTK_WIDGET(cbox), guid);
- else
- select_default (GTK_WIDGET(cbox), gnc_get_builtin_default_invoice_print_report ());
-}
+ invoice_list = g_slist_append (invoice_list, rle);
-gchar*
-gnc_default_print_report_list_combo_get_report (GtkComboBox *cbox)
-{
- GtkTreeModel *model = gtk_combo_box_get_model (cbox);
- GtkTreeIter iter;
- gchar *report = NULL;
-
- if (gtk_combo_box_get_active_iter (cbox, &iter))
- {
- gchar *report_guid;
- gchar *report_name;
- gtk_tree_model_get (model, &iter, COL_INV_NAME, &report_name,
- COL_INV_GUID, &report_guid,
- -1);
-
- report = g_strconcat (report_guid, "/", report_name, NULL);
- g_free (report_guid);
- g_free (report_name);
+ rpt_guids = SCM_CDR(rpt_guids);
+ }
}
- return report;
+ return gnc_report_combo_new (invoice_list);
}
static GtkWidget * gnc_owner_new (GtkWidget *label, GtkWidget *hbox,
diff --git a/gnucash/gnome/business-gnome-utils.h b/gnucash/gnome/business-gnome-utils.h
index a5c5356c7..96fef1be5 100644
--- a/gnucash/gnome/business-gnome-utils.h
+++ b/gnucash/gnome/business-gnome-utils.h
@@ -50,7 +50,7 @@ const char *gnc_get_builtin_default_invoice_print_report (void);
/** Migrate the Default Invoice Report from prefs to book properties
* used to print Invoices
- *
+ *
* @return The guid of the saved Invoice Report
*/
const char * gnc_migrate_default_invoice_print_report (void);
@@ -71,24 +71,14 @@ char *gnc_get_default_invoice_print_report (void);
*/
void gnc_default_print_report_list (GtkWidget *combo, GtkWidget *warning);
-/** Retrieve the string representing the Invoice Report used as the default
- * to print Invoices. This is a concatination of report name and guid
+/** Create a report combo to show a list of Invoice reports so that
+ * a default Invoice Report can be selected.
*
- * @param combo The GtkComboBox that presents the list.
- *
- * @return The string used to represent the selected Invoice Report
- */
-gchar *gnc_default_print_report_list_combo_get_report (GtkComboBox *cbox);
-
-/** Set the active report to the guid string
+ * @param guid_scm_function The SCM function to create the report list
*
- * @param combo The GtkComboBox that presents the list.
- *
- * @param guid The guid of the Invoice Report
+ * @return The Widget for the report combo
*/
-void gnc_default_print_report_list_combo_set_report (GtkComboBox *cbox,
- const gchar *guid);
-
+GtkWidget * gnc_default_invoice_report_combo (const char* guid_scm_function);
GtkWidget * gnc_owner_select_create (GtkWidget *label, GtkWidget *hbox,
QofBook *book, GncOwner *owner);
diff --git a/gnucash/gnome/business-options-gnome.cpp b/gnucash/gnome/business-options-gnome.cpp
index 4e7f9dcdd..f8155ab77 100644
--- a/gnucash/gnome/business-options-gnome.cpp
+++ b/gnucash/gnome/business-options-gnome.cpp
@@ -33,6 +33,10 @@
#include <gnc-general-search.h> // for GNC_GENERAL_SEARCH
#include "dialog-utils.h" // for gnc_builder_add_from_file
+extern "C"
+{
+#include "gnc-report-combo.h"
+}
#include <iostream>
#include <sstream>
@@ -190,13 +194,23 @@ public:
GncOptionGtkUIItem(widget, GncOptionUIType::INV_REPORT) {}
void set_ui_item_from_option(GncOption& option) noexcept override
{
- auto guid_string{option.get_value<std::string>()};
- gnc_default_print_report_list_combo_set_report (GTK_COMBO_BOX(get_widget()),
- guid_string.c_str());
+ std::string guid_string;
+ auto str{option.get_value<std::string>()};
+
+ if (str.empty())
+ {
+ static const std::string default_guid_string(gnc_get_builtin_default_invoice_print_report ());
+ guid_string = default_guid_string + "/ ";
+ }
+ else
+ guid_string = str;
+
+ gnc_report_combo_set_active_guid_name (GNC_REPORT_COMBO(get_widget()),
+ guid_string.c_str());
}
void set_option_from_ui_item(GncOption& option) noexcept override
{
- auto report_guid_name = gnc_default_print_report_list_combo_get_report (GTK_COMBO_BOX(get_widget()));
+ auto report_guid_name = gnc_report_combo_get_active_guid_name (GNC_REPORT_COMBO(get_widget()));
option.set_value(std::string{report_guid_name});
g_free (report_guid_name);
}
@@ -207,28 +221,15 @@ create_option_widget<GncOptionUIType::INV_REPORT>(GncOption& option,
GtkGrid *page_box,
int row)
{
- constexpr const char* glade_file{"business-options-gnome.glade"};
- constexpr const char* glade_store{"liststore_print_invoice"};
- constexpr const char* glade_hbox{"invoice_report_hbox"};
- constexpr const char* glade_menu{"invoice_report_combo"};
- constexpr const char* glade_warning{"invoice_warning_image"};
- auto builder{gtk_builder_new()};
-
- gnc_builder_add_from_file(builder, glade_file, glade_store);
- gnc_builder_add_from_file(builder, glade_file, glade_hbox);
- auto widget{GTK_WIDGET(gtk_builder_get_object(builder, glade_menu))};
- auto widget_hbox{GTK_WIDGET(gtk_builder_get_object(builder, glade_hbox))};
- auto widget_warning{GTK_WIDGET(gtk_builder_get_object(builder, glade_warning))};
- g_object_set_data(G_OBJECT(widget), "warning-image", widget_warning);
- gnc_default_print_report_list (GTK_WIDGET(widget), GTK_WIDGET(widget_warning));
+ constexpr const char* inv_report{"gnc:custom-report-invoice-template-guids"};
+ auto widget = gnc_default_invoice_report_combo (inv_report);
option.set_ui_item(std::make_unique<GncGtkInvReportUIItem>(widget));
option.set_ui_item_from_option();
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (gnc_option_changed_widget_cb), &option);
- wrap_widget (option, widget_hbox, page_box, row);
- g_object_unref(builder); // Needs to wait until after widget has been reffed.
+ wrap_widget (option, widget, page_box, row);
}
void
diff --git a/gnucash/gtkbuilder/business-options-gnome.glade b/gnucash/gtkbuilder/business-options-gnome.glade
index 00fd7f999..99f03f625 100644
--- a/gnucash/gtkbuilder/business-options-gnome.glade
+++ b/gnucash/gtkbuilder/business-options-gnome.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 -->
+<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkListStore" id="liststore_print_invoice">
@@ -12,46 +12,6 @@
<column type="gboolean"/>
</columns>
</object>
- <object class="GtkWindow" id="dummy_toplevel_window2">
- <property name="can-focus">False</property>
- <child>
- <object class="GtkBox" id="invoice_report_hbox">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkComboBox" id="invoice_report_combo">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="model">liststore_print_invoice</property>
- <child>
- <object class="GtkCellRendererText" id="cell_renderer_text"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="invoice_warning_image">
- <property name="can-focus">False</property>
- <property name="no-show-all">True</property>
- <property name="icon-name">dialog-warning</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
<object class="GtkListStore" id="taxtable_store">
<columns>
<!-- column-name taxtable_name -->
commit b49b5c86bb2a3f7ba8622c485d678462fd168dde
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Wed Feb 1 15:38:16 2023 +0000
Create a new widget GncReportCombo to list reports
This widget will provide a combo and populate a model with guids, names
and a warning value that controls the visibility of a warning image.
diff --git a/gnucash/gnome-utils/CMakeLists.txt b/gnucash/gnome-utils/CMakeLists.txt
index 220fdd417..82c0c9aeb 100644
--- a/gnucash/gnome-utils/CMakeLists.txt
+++ b/gnucash/gnome-utils/CMakeLists.txt
@@ -86,6 +86,7 @@ set (gnome_utils_SOURCES
gnc-plugin.c
gnc-period-select.c
gnc-query-view.c
+ gnc-report-combo.c
gnc-splash.c
gnc-sx-instance-dense-cal-adapter.c
gnc-sx-list-tree-model-adapter.c
@@ -172,6 +173,7 @@ set (gnome_utils_HEADERS
gnc-plugin.h
gnc-period-select.h
gnc-query-view.h
+ gnc-report-combo.h
gnc-splash.h
gnc-sx-instance-dense-cal-adapter.h
gnc-sx-list-tree-model-adapter.h
diff --git a/gnucash/gnome-utils/gnc-report-combo.c b/gnucash/gnome-utils/gnc-report-combo.c
new file mode 100644
index 000000000..68d552e39
--- /dev/null
+++ b/gnucash/gnome-utils/gnc-report-combo.c
@@ -0,0 +1,551 @@
+/********************************************************************\
+ * gnc-report-combo.c -- report select widget for GnuCash *
+ * *
+ * Copyright (C) 2022 Bob Fewell *
+ * *
+ * 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 at gnu.org *
+ * *
+\********************************************************************/
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "gnc-report-combo.h"
+#include "gnc-ui-util.h"
+#include "gnc-engine.h"
+#include "dialog-utils.h"
+
+/** The debugging module used by this file. */
+static QofLogModule log_module = GNC_MOD_GUI;
+
+static void gnc_report_combo_init (GncReportCombo *grc);
+static void gnc_report_combo_class_init (GncReportComboClass *klass);
+static void gnc_report_combo_dispose (GObject *object);
+static void gnc_report_combo_finalize (GObject *object);
+
+#define GNC_REPORT_COMBO_PATH "gnc-report-combo-path"
+
+enum
+{
+ RC_NAME,
+ RC_GUID,
+ RC_MISSING
+};
+
+/** The instance private data for a content plugin. */
+typedef struct _GncReportComboPrivate
+{
+ GtkWidget *combo;
+ GtkWidget *warning_image;
+
+ const gchar *rpt_guids;
+
+ gboolean block_signal;
+ gboolean popup_shown;
+
+ gchar *active_report_guid;
+ gchar *active_report_name;
+
+} GncReportComboPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE(GncReportCombo, gnc_report_combo, GTK_TYPE_BOX)
+
+#define GET_PRIVATE(o) \
+ ((GncReportComboPrivate*)g_type_instance_get_private ((GTypeInstance*)o, GNC_TYPE_REPORT_COMBO))
+
+enum
+{
+ SIGNAL_0,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint report_combo_signals [LAST_SIGNAL] = {0};
+
+enum
+{
+ PROP_0,
+ PROP_POPUP_SHOWN,
+ N_PROPERTIES
+};
+
+static GParamSpec *report_combo_properties [N_PROPERTIES] = {NULL,};
+
+static void
+gnc_report_combo_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GncReportCombo *grc = GNC_REPORT_COMBO(object);
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+
+ switch (property_id)
+ {
+ case PROP_POPUP_SHOWN:
+ g_value_set_boolean (value, priv->popup_shown);
+ break;
+
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+/** Initialize the GncReportCombo class object.
+ *
+ * @internal
+ *
+ * @param klass A pointer to the newly created class object.
+ */
+static void
+gnc_report_combo_class_init (GncReportComboClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ object_class->get_property = gnc_report_combo_get_property;
+ object_class->dispose = gnc_report_combo_dispose;
+ object_class->finalize = gnc_report_combo_finalize;
+
+ report_combo_signals [CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(GncReportComboClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ report_combo_properties [PROP_POPUP_SHOWN] =
+ g_param_spec_boolean ("popup-shown",
+ "State of PopUp",
+ "State of PopUp",
+ FALSE /* default value */,
+ G_PARAM_READABLE);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ report_combo_properties);
+}
+
+/** Initialize a GncReportCombo object.
+ *
+ * @internal
+ *
+ * @param grc A pointer to the newly created object.
+ */
+static void
+gnc_report_combo_init (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv;
+
+ g_return_if_fail (grc != NULL);
+ g_return_if_fail (GNC_IS_REPORT_COMBO(grc));
+
+ priv = GET_PRIVATE(grc);
+
+ // Set the name for this widget so it can be easily manipulated with css
+ gtk_widget_set_name (GTK_WIDGET(grc), "gnc-id-report-combo");
+
+ priv->block_signal = FALSE;
+ priv->active_report_guid = NULL;
+ priv->active_report_name = NULL;
+ priv->popup_shown = FALSE;
+}
+
+/** Dispopse the GncReportCombo object. This function is called from
+ * the G_Object level to complete the destruction of the object. It
+ * should release any memory not previously released by the destroy
+ * function (i.e. the private data structure), then chain up to the
+ * parent's destroy function.
+ *
+ * @param object The object being destroyed.
+ *
+ * @internal
+ */
+static void
+gnc_report_combo_dispose (GObject *object)
+{
+ /* Do not free the private data structure itself. It is part of
+ * a larger memory block allocated by the type system. */
+
+ G_OBJECT_CLASS (gnc_report_combo_parent_class)->dispose (object);
+}
+
+/** Finalize the GncReportCombo object. This function is called from
+ * the G_Object level to complete the destruction of the object. It
+ * should release any memory not previously released by the destroy
+ * function (i.e. the private data structure), then chain up to the
+ * parent's finalize function.
+ *
+ * @param object The object being finalized.
+ *
+ * @internal
+ */
+static void
+gnc_report_combo_finalize (GObject *object)
+{
+ GncReportComboPrivate *priv;
+ GncReportCombo *grc;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_REPORT_COMBO(object));
+
+ grc = GNC_REPORT_COMBO(object);
+ priv = GET_PRIVATE(grc);
+
+ g_free (priv->active_report_guid);
+ g_free (priv->active_report_name);
+
+ G_OBJECT_CLASS (gnc_report_combo_parent_class)->finalize (object);
+}
+
+/** This function sets the active combo entry based on the private
+ * report guid and also checks to see if the report guid is in the
+ * list of reports, if not a warning image and tooltip is shown.
+ *
+ * @internal
+ *
+ * @param grc The report combo.
+ *
+ * @return TRUE if report guid is in the list, other wise FALSE.
+ */
+static gboolean
+select_active_and_check_exists (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(priv->combo));
+ GtkTreeIter iter;
+ gboolean valid_iter = gtk_tree_model_get_iter_first (model, &iter);
+ QofBook *book = gnc_get_current_book ();
+ gchar *tmp;
+
+ while (valid_iter)
+ {
+ gchar *guid;
+ gtk_tree_model_get (model, &iter, RC_GUID, &guid, -1);
+
+ if (g_strcmp0 (priv->active_report_guid, guid) == 0)
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX(priv->combo), &iter);
+ g_free (guid);
+ return TRUE;
+ }
+ g_free (guid);
+ valid_iter = gtk_tree_model_iter_next (model, &iter);
+ }
+
+ if (priv->active_report_name)
+ tmp = g_strdup (priv->active_report_name);
+ else
+ tmp = g_strdup (_("Selected Report is Missing"));
+
+ gtk_list_store_prepend (GTK_LIST_STORE(model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+ RC_NAME, tmp,
+ RC_GUID, priv->active_report_guid,
+ RC_MISSING, TRUE,
+ -1);
+
+ g_free (tmp);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX(priv->combo), &iter);
+ return FALSE;
+}
+
+static void
+update_report_list (GncReportCombo *grc, GSList *report_list)
+{
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(priv->combo));
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(model),
+ RC_NAME, GTK_SORT_ASCENDING);
+
+ gtk_list_store_clear (GTK_LIST_STORE(model));
+
+ if (report_list)
+ {
+ GtkTreeIter iter;
+
+ for (GSList* node = report_list; node != NULL; node = g_slist_next (node))
+ {
+ ReportListEntry *rle = node->data;
+
+ gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+ RC_NAME, rle->report_name,
+ RC_GUID, rle->report_guid,
+ RC_MISSING, FALSE,
+ -1);
+ g_free (rle->report_name);
+ g_free (rle->report_guid);
+ g_free (rle);
+ }
+ }
+ g_slist_free (report_list);
+}
+
+static void
+update_warning_tooltip (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+ gchar *tool_tip;
+
+ if (priv->active_report_name)
+ /* Translators: %s is the report name. */
+ tool_tip = g_strdup_printf (_("'%s' is missing"),
+ priv->active_report_name);
+ else
+ /* Translators: %s is the internal report guid. */
+ tool_tip = g_strdup_printf (_("Report with GUID '%s' is missing"),
+ priv->active_report_guid);
+
+ gtk_widget_show (priv->warning_image);
+ gtk_widget_set_tooltip_text (priv->warning_image, tool_tip);
+ g_free (tool_tip);
+}
+
+void
+gnc_report_combo_set_active (GncReportCombo *grc,
+ const char* active_report_guid,
+ const char* active_report_name)
+{
+ GncReportComboPrivate *priv;
+
+ g_return_if_fail (grc != NULL);
+ g_return_if_fail (GNC_IS_REPORT_COMBO(grc));
+
+ priv = GET_PRIVATE(grc);
+
+ g_free (priv->active_report_guid);
+
+ priv->active_report_guid = g_strdup (active_report_guid);
+
+ g_free (priv->active_report_name);
+
+ priv->active_report_name = g_strdup (active_report_name);
+
+ priv->block_signal = TRUE;
+
+ if (!select_active_and_check_exists (grc))
+ update_warning_tooltip (grc);
+
+ priv->block_signal = FALSE;
+}
+
+gchar *
+gnc_report_combo_get_active_guid (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv;
+ gchar *guid = NULL;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (grc != NULL, NULL);
+ g_return_val_if_fail (GNC_IS_REPORT_COMBO(grc), NULL);
+
+ priv = GET_PRIVATE(grc);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(priv->combo), &iter))
+ {
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(priv->combo));
+ gtk_tree_model_get (model, &iter, RC_GUID, &guid, -1);
+ }
+ return guid;
+}
+
+gchar *
+gnc_report_combo_get_active_name (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv;
+ gchar *name = NULL;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (grc != NULL, NULL);
+ g_return_val_if_fail (GNC_IS_REPORT_COMBO(grc), NULL);
+
+ priv = GET_PRIVATE(grc);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(priv->combo), &iter))
+ {
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(priv->combo));
+ gtk_tree_model_get (model, &iter, RC_NAME, &name, -1);
+ }
+ return name;
+}
+
+gchar*
+gnc_report_combo_get_active_guid_name (GncReportCombo *grc)
+{
+ GncReportComboPrivate *priv;
+ gchar *report = NULL;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (grc != NULL, NULL);
+ g_return_val_if_fail (GNC_IS_REPORT_COMBO(grc), NULL);
+
+ priv = GET_PRIVATE(grc);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(priv->combo), &iter))
+ {
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(priv->combo));
+ gchar *report_guid;
+ gchar *report_name;
+ gtk_tree_model_get (model, &iter, RC_NAME, &report_name,
+ RC_GUID, &report_guid,
+ -1);
+
+ report = g_strconcat (report_guid, "/", report_name, NULL);
+ g_free (report_guid);
+ g_free (report_name);
+ }
+ return report;
+}
+
+void
+gnc_report_combo_set_active_guid_name (GncReportCombo *grc,
+ const gchar *guid_name)
+{
+ GncReportComboPrivate *priv;
+
+ g_return_if_fail (grc != NULL);
+ g_return_if_fail (GNC_IS_REPORT_COMBO(grc));
+
+ priv = GET_PRIVATE(grc);
+
+ if (guid_name && *guid_name)
+ {
+ gchar *guid = NULL;
+ gchar *name = g_strstr_len (guid_name, -1, "/");
+
+ if (name)
+ {
+ guid = g_strndup (guid_name, (name - guid_name));
+ gnc_report_combo_set_active (grc, guid, name + 1);
+ }
+ g_free (guid);
+ }
+}
+
+static void
+combo_changed_cb (GtkComboBox *widget, gpointer user_data)
+{
+ GncReportCombo *grc = GNC_REPORT_COMBO(user_data);
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+ GtkTreeIter iter;
+
+ if (gtk_combo_box_get_active_iter (widget, &iter))
+ {
+ GtkTreeModel *model = gtk_combo_box_get_model (widget);
+ gboolean missing;
+ gtk_tree_model_get (model, &iter, RC_MISSING, &missing, -1);
+ // set visibility of the warning image
+ gtk_widget_set_visible (priv->warning_image, missing);
+
+ if (!priv->block_signal)
+ g_signal_emit (grc, report_combo_signals [CHANGED], 0);
+
+ gtk_widget_queue_resize (GTK_WIDGET(widget));
+ }
+}
+
+static void
+combo_popped_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GncReportCombo *grc = GNC_REPORT_COMBO(user_data);
+ GncReportComboPrivate *priv = GET_PRIVATE(grc);
+ gboolean popup_shown;
+
+ g_object_get (G_OBJECT(gobject), "popup-shown", &popup_shown, NULL);
+
+ priv->popup_shown = popup_shown;
+ g_object_notify (G_OBJECT(grc), "popup-shown");
+}
+
+void
+gnc_report_combo_refresh (GncReportCombo *grc, GSList *report_list)
+{
+ GncReportComboPrivate *priv;
+
+ g_return_if_fail (grc != NULL);
+ g_return_if_fail (GNC_IS_REPORT_COMBO(grc));
+ g_return_if_fail (report_list != NULL);
+
+ priv = GET_PRIVATE(grc);
+
+ priv->block_signal = TRUE;
+
+ update_report_list (grc, report_list);
+
+ if (!select_active_and_check_exists (grc))
+ update_warning_tooltip (grc);
+
+ priv->block_signal = FALSE;
+}
+
+/* Create a new GncReportCombo widget which can be used to select
+ * a report from a GtkComboBox.
+ *
+ * @return A GncReportCombo widget.
+ */
+GtkWidget *
+gnc_report_combo_new (GSList *report_list)
+{
+ GncReportCombo *grc;
+ GncReportComboPrivate *priv;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+
+ store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ grc = g_object_new (GNC_TYPE_REPORT_COMBO, NULL);
+
+ priv = GET_PRIVATE(grc);
+
+ priv->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
+ g_object_unref (store);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(priv->combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(priv->combo), renderer,
+ "text", RC_NAME, NULL);
+
+ gtk_box_pack_start (GTK_BOX(grc), GTK_WIDGET(priv->combo), TRUE, TRUE, 0);
+ priv->warning_image = gtk_image_new_from_icon_name ("dialog-warning",
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_box_pack_start (GTK_BOX(grc), GTK_WIDGET(priv->warning_image), FALSE, FALSE, 6);
+ gtk_widget_set_no_show_all (GTK_WIDGET(priv->warning_image), TRUE);
+ gtk_widget_hide (GTK_WIDGET(priv->warning_image));
+
+ update_report_list (grc, report_list);
+
+ g_signal_connect (G_OBJECT(priv->combo), "changed",
+ G_CALLBACK(combo_changed_cb), grc);
+
+ g_signal_connect (G_OBJECT(priv->combo), "notify::popup-shown",
+ G_CALLBACK(combo_popped_cb), grc);
+
+ gtk_widget_show_all (GTK_WIDGET(grc));
+
+ return GTK_WIDGET(grc);
+}
diff --git a/gnucash/gnome-utils/gnc-report-combo.h b/gnucash/gnome-utils/gnc-report-combo.h
new file mode 100644
index 000000000..ff811ed42
--- /dev/null
+++ b/gnucash/gnome-utils/gnc-report-combo.h
@@ -0,0 +1,123 @@
+/********************************************************************\
+ * gnc-report-combo.h -- report select widget for GnuCash *
+ * *
+ * Copyright (C) 2022 Bob Fewell *
+ * *
+ * 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 at gnu.org *
+ * *
+\********************************************************************/
+
+#ifndef GNC_REPORT_COMBO_H
+#define GNC_REPORT_COMBO_H
+
+#define GNC_TYPE_REPORT_COMBO (gnc_report_combo_get_type())
+#define GNC_REPORT_COMBO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_REPORT_COMBO, GncReportCombo))
+#define GNC_REPORT_COMBO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GNC_TYPE_REPORT_COMBO, GncReportComboClass))
+#define GNC_IS_REPORT_COMBO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_REPORT_COMBO))
+#define GNC_IS_REPORT_COMBO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GNC_TYPE_REPORT_COMBO))
+#define GNC_REPORT_COMBO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_REPORT_COMBO, GncReportComboClass))
+
+typedef struct
+{
+ GtkBox box;
+
+} GncReportCombo;
+
+typedef struct
+{
+ GtkBoxClass parent_class;
+ void (*changed) (GncReportCombo *grc);
+
+} GncReportComboClass;
+
+typedef struct
+{
+ char *report_guid;
+ char *report_name;
+} ReportListEntry;
+
+/** Return the GType for the GncReportCombo widget.
+ *
+ * @return A GType value.
+ */
+GType gnc_report_combo_get_type (void) G_GNUC_CONST;
+
+/** Create a new GncReportCombo widget which can be used to provide
+ * a list of reports and select one.
+ *
+ * @param report_list The list of report guids to populate the model
+ *
+ * @return A GncReportCombo widget.
+ */
+GtkWidget *gnc_report_combo_new (GSList *report_list);
+
+/** Refresh the report combo model.
+ *
+ * @param grc The report combo widget.
+ *
+ * @param report_list The report list to update the combo with.
+ */
+void gnc_report_combo_refresh (GncReportCombo *grc, GSList *report_list);
+
+/** Set the active report in the GncReportCombo widget.
+ *
+ * @param grc The report combo widget.
+ *
+ * @param active_report_guid A string representing the report guid
+ *
+ * @param active_report_name A string representing the report name
+ */
+void gnc_report_combo_set_active (GncReportCombo *grc,
+ const char* active_report_guid,
+ const char* active_report_name);
+
+/** Get the active report guid string.
+ *
+ * @param grc The report combo widget.
+ *
+ * @return The string guid of the selected report or NULL if none active
+ */
+gchar * gnc_report_combo_get_active_guid (GncReportCombo *grc);
+
+/** Get the active report name string.
+ *
+ * @param grc The report combo widget.
+ *
+ * @return The string name of the selected report or NULL if none active
+ */
+gchar * gnc_report_combo_get_active_name (GncReportCombo *grc);
+
+/** Set the active report to the guid string
+ *
+ * @param combo The GtkComboBox that presents the list.
+ *
+ * @param guid_name The concatination of the guid/name of the Invoice Report
+ */
+void gnc_report_combo_set_active_guid_name (GncReportCombo *grc,
+ const gchar *guid_name);
+
+/** Get the active report name string.
+ *
+ * @param grc The report combo widget.
+ *
+ * @return The concatinated string of report guid and name of the selected
+ * report or NULL if none active
+ */
+gchar * gnc_report_combo_get_active_guid_name (GncReportCombo *grc);
+
+#endif /* __GNC_REPORT_COMBO_H__ */
commit 019214f1c2151e922131ed25671680a8fee989bf
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Fri May 6 15:05:12 2022 +0100
Bug753307 - Custom Report be selectable as default Report for Printing
This commit changes the preference in Business->'Report for Printing'
to be saved as a book property and allow the selection of any Invoice
Report to be used as the default.
diff --git a/gnucash/gnome/business-gnome-utils.c b/gnucash/gnome/business-gnome-utils.c
index 1f09bc573..5b56f10e8 100644
--- a/gnucash/gnome/business-gnome-utils.c
+++ b/gnucash/gnome/business-gnome-utils.c
@@ -42,6 +42,7 @@
#include "gnc-general-search.h"
#include "qof.h"
+#include "qofbook.h"
#include "business-gnome-utils.h"
#include "dialog-customer.h"
#include "dialog-job.h"
@@ -49,6 +50,9 @@
#include "dialog-employee.h"
#include "dialog-invoice.h"
+#include "guile-mappings.h"
+#include "gnc-guile-utils.h"
+#include "gnc-prefs.h"
#include "gnc-commodity.h"
typedef enum
@@ -57,6 +61,248 @@ typedef enum
GNCSEARCH_TYPE_EDIT
} GNCSearchType;
+enum
+{
+ COL_INV_NAME = 0,
+ COL_INV_GUID,
+ COL_INV_MISSING,
+ NUM_INV_COLS
+};
+
+#define PRINTABLE_INVOICE_GUID "5123a759ceb9483abf2182d01c140e8d"
+#define TAX_INVOICE_GUID "0769e242be474010b4acf264a5512e6e"
+#define EASY_INVOICE_GUID "67112f318bef4fc496bdc27d106bbda4"
+#define FANCY_INVOICE_GUID "3ce293441e894423a2425d7a22dd1ac6"
+
+enum
+{
+ PRINTABLE_INVOICE_PREF_NUM = 0,
+ TAX_INVOICE_PREF_NUM,
+ EASY_INVOICE_PREF_NUM,
+ FANCY_INVOICE_PREF_NUM,
+};
+
+static const char* invoice_printreport_values[] =
+{
+ /* The list below are the guids of reports that can
+ * be used to print an invoice.
+ *
+ * Important: This list matches the order of existing saved
+ * preference entries.
+ */
+ PRINTABLE_INVOICE_GUID,
+ TAX_INVOICE_GUID,
+ EASY_INVOICE_GUID,
+ FANCY_INVOICE_GUID,
+ NULL
+};
+
+#define GNC_PREFS_GROUP_INVOICE "dialogs.business.invoice"
+#define GNC_PREF_INV_PRINT_RPT "invoice-printreport"
+
+const char *
+gnc_get_builtin_default_invoice_print_report (void)
+{
+ return PRINTABLE_INVOICE_GUID;
+}
+
+const char *
+gnc_migrate_default_invoice_print_report (void)
+{
+ QofBook *book = gnc_get_current_book ();
+ int old_style_value = gnc_prefs_get_int (GNC_PREFS_GROUP_INVOICE,
+ GNC_PREF_INV_PRINT_RPT);
+
+ if (old_style_value >= TAX_INVOICE_PREF_NUM &&
+ old_style_value <= FANCY_INVOICE_PREF_NUM)
+ {
+ const gchar *ret = invoice_printreport_values[old_style_value];
+ qof_book_set_default_invoice_report (book, ret, " ");
+ return ret;
+ }
+ else
+ return gnc_get_builtin_default_invoice_print_report ();
+}
+
+char *
+gnc_get_default_invoice_print_report (void)
+{
+ QofBook *book = gnc_get_current_book ();
+ gchar *default_guid = qof_book_get_default_invoice_report_guid (book);
+
+ if (!default_guid)
+ return g_strdup (gnc_migrate_default_invoice_print_report ());
+
+ return default_guid;
+}
+
+static gboolean
+select_default (GtkWidget *combo, const gchar *default_guid)
+{
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo));
+ GtkTreeIter iter;
+ gboolean found = FALSE;
+ gboolean valid_iter = gtk_tree_model_get_iter_first (model, &iter);
+
+ while (valid_iter)
+ {
+ gchar *guid;
+ gtk_tree_model_get (model, &iter, COL_INV_GUID, &guid, -1);
+
+ if (g_strcmp0 (default_guid, guid) == 0)
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX(combo), &iter);
+ g_free (guid);
+ found = TRUE;
+ break;
+ }
+ g_free (guid);
+ valid_iter = gtk_tree_model_iter_next (model, &iter);
+ }
+ return found;
+}
+
+/********************************************************************
+ * update_invoice_list
+ *
+ * this procedure does the real work of displaying a sorted list of
+ * available invoice reports
+ ********************************************************************/
+static gchar *
+update_invoice_list (GtkWidget *combo)
+{
+ SCM get_rpt_guids = scm_c_eval_string ("gnc:custom-report-invoice-template-guids");
+ SCM template_menu_name = scm_c_eval_string ("gnc:report-template-menu-name/report-guid");
+ SCM reportlist;
+ SCM rpt_guids;
+
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo));
+ GtkListStore *store = GTK_LIST_STORE(model);
+ gchar *default_guid = gnc_get_default_invoice_print_report ();
+ gchar *default_name = NULL;
+ gboolean have_default = FALSE;
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(model),
+ COL_INV_NAME, GTK_SORT_ASCENDING);
+
+ reportlist = scm_call_0 (get_rpt_guids);
+ rpt_guids = reportlist;
+
+ gtk_list_store_clear (store);
+
+ if (scm_is_list (rpt_guids))
+ {
+ int i;
+ GtkTreeIter iter;
+
+ for (i = 0; !scm_is_null (rpt_guids); i++)
+ {
+ gchar *guid_str = scm_to_utf8_string (SCM_CAR(rpt_guids));
+ gchar *name = gnc_scm_to_utf8_string (scm_call_2(template_menu_name,
+ SCM_CAR(rpt_guids), SCM_BOOL_F));
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_INV_NAME, name,
+ COL_INV_GUID, guid_str,
+ COL_INV_MISSING, FALSE,
+ -1);
+ g_free (name);
+ g_free (guid_str);
+
+ rpt_guids = SCM_CDR(rpt_guids);
+ }
+ }
+
+ have_default = select_default (combo, default_guid);
+
+ if (!have_default)
+ {
+ GtkTreeIter iter;
+ QofBook *book = gnc_get_current_book ();
+ default_name = qof_book_get_default_invoice_report_name (book);
+
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_INV_NAME, default_name,
+ COL_INV_GUID, default_guid,
+ COL_INV_MISSING, TRUE,
+ -1);
+
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX(combo), &iter);
+ }
+ g_free (default_guid);
+ return default_name;
+}
+
+static void
+combo_changed_cb (GtkComboBox *widget, gpointer user_data)
+{
+ GtkTreeIter iter;
+
+ if (gtk_combo_box_get_active_iter (widget, &iter))
+ {
+ GtkTreeModel *model = gtk_combo_box_get_model (widget);
+ gboolean missing;
+ gtk_tree_model_get (model, &iter, COL_INV_MISSING, &missing, -1);
+ // set visibility of the warning image
+ gtk_widget_set_visible (GTK_WIDGET(user_data), missing);
+ gtk_widget_queue_resize (GTK_WIDGET(widget));
+ }
+}
+
+void
+gnc_default_print_report_list (GtkWidget *combo, GtkWidget *warning)
+{
+ gchar *default_name = update_invoice_list (combo);
+
+ if (default_name)
+ {
+ /* Translators: %s is the default invoice report name. */
+ gchar *tool_tip = g_strdup_printf (_("'%s' is missing"),
+ default_name);
+ gtk_widget_show (warning);
+
+ gtk_widget_set_tooltip_text (warning, tool_tip);
+ g_free (tool_tip);
+ }
+ g_free (default_name);
+ g_signal_connect (G_OBJECT(combo), "changed",
+ G_CALLBACK(combo_changed_cb), warning);
+}
+
+void
+gnc_default_print_report_list_combo_set_report (GtkComboBox *cbox,
+ const gchar *guid)
+{
+ if (guid && *guid)
+ select_default (GTK_WIDGET(cbox), guid);
+ else
+ select_default (GTK_WIDGET(cbox), gnc_get_builtin_default_invoice_print_report ());
+}
+
+gchar*
+gnc_default_print_report_list_combo_get_report (GtkComboBox *cbox)
+{
+ GtkTreeModel *model = gtk_combo_box_get_model (cbox);
+ GtkTreeIter iter;
+ gchar *report = NULL;
+
+ if (gtk_combo_box_get_active_iter (cbox, &iter))
+ {
+ gchar *report_guid;
+ gchar *report_name;
+ gtk_tree_model_get (model, &iter, COL_INV_NAME, &report_name,
+ COL_INV_GUID, &report_guid,
+ -1);
+
+ report = g_strconcat (report_guid, "/", report_name, NULL);
+ g_free (report_guid);
+ g_free (report_name);
+ }
+ return report;
+}
+
static GtkWidget * gnc_owner_new (GtkWidget *label, GtkWidget *hbox,
QofBook *book, GncOwner *owner,
GNCSearchType type)
diff --git a/gnucash/gnome/business-gnome-utils.h b/gnucash/gnome/business-gnome-utils.h
index de298743c..a5c5356c7 100644
--- a/gnucash/gnome/business-gnome-utils.h
+++ b/gnucash/gnome/business-gnome-utils.h
@@ -41,6 +41,54 @@ extern "C" {
#define GNC_PREF_AUTO_PAY "auto-pay"
+/** Retrieve the buitin guid for the Invoice Report to be
+ * used as the default to print Invoices
+ *
+ * @return The guid of the saved Invoice Report
+ */
+const char *gnc_get_builtin_default_invoice_print_report (void);
+
+/** Migrate the Default Invoice Report from prefs to book properties
+ * used to print Invoices
+ *
+ * @return The guid of the saved Invoice Report
+ */
+const char * gnc_migrate_default_invoice_print_report (void);
+
+/** Retrieve the guid of the Invoice Report to be used to
+ * print Invoices
+ *
+ * @return The guid of the saved Invoice Report
+ */
+char *gnc_get_default_invoice_print_report (void);
+
+/** Setup a combo used for displaying list of Invoice Reports.
+ *
+ * @param combo The GtkComboBox that presents the list.
+ *
+ * @param warning The warning image, displayed if the default guid is
+ * not in the Invoice list.
+ */
+void gnc_default_print_report_list (GtkWidget *combo, GtkWidget *warning);
+
+/** Retrieve the string representing the Invoice Report used as the default
+ * to print Invoices. This is a concatination of report name and guid
+ *
+ * @param combo The GtkComboBox that presents the list.
+ *
+ * @return The string used to represent the selected Invoice Report
+ */
+gchar *gnc_default_print_report_list_combo_get_report (GtkComboBox *cbox);
+
+/** Set the active report to the guid string
+ *
+ * @param combo The GtkComboBox that presents the list.
+ *
+ * @param guid The guid of the Invoice Report
+ */
+void gnc_default_print_report_list_combo_set_report (GtkComboBox *cbox,
+ const gchar *guid);
+
GtkWidget * gnc_owner_select_create (GtkWidget *label, GtkWidget *hbox,
QofBook *book, GncOwner *owner);
diff --git a/gnucash/gnome/business-options-gnome.cpp b/gnucash/gnome/business-options-gnome.cpp
index eb1041e58..4e7f9dcdd 100644
--- a/gnucash/gnome/business-options-gnome.cpp
+++ b/gnucash/gnome/business-options-gnome.cpp
@@ -183,6 +183,54 @@ create_option_widget<GncOptionUIType::TAX_TABLE>(GncOption& option,
wrap_widget(option, widget, page_box, row);
}
+class GncGtkInvReportUIItem : public GncOptionGtkUIItem
+{
+public:
+ GncGtkInvReportUIItem(GtkWidget* widget) :
+ GncOptionGtkUIItem(widget, GncOptionUIType::INV_REPORT) {}
+ void set_ui_item_from_option(GncOption& option) noexcept override
+ {
+ auto guid_string{option.get_value<std::string>()};
+ gnc_default_print_report_list_combo_set_report (GTK_COMBO_BOX(get_widget()),
+ guid_string.c_str());
+ }
+ void set_option_from_ui_item(GncOption& option) noexcept override
+ {
+ auto report_guid_name = gnc_default_print_report_list_combo_get_report (GTK_COMBO_BOX(get_widget()));
+ option.set_value(std::string{report_guid_name});
+ g_free (report_guid_name);
+ }
+};
+
+template<> void
+create_option_widget<GncOptionUIType::INV_REPORT>(GncOption& option,
+ GtkGrid *page_box,
+ int row)
+{
+ constexpr const char* glade_file{"business-options-gnome.glade"};
+ constexpr const char* glade_store{"liststore_print_invoice"};
+ constexpr const char* glade_hbox{"invoice_report_hbox"};
+ constexpr const char* glade_menu{"invoice_report_combo"};
+ constexpr const char* glade_warning{"invoice_warning_image"};
+ auto builder{gtk_builder_new()};
+
+ gnc_builder_add_from_file(builder, glade_file, glade_store);
+ gnc_builder_add_from_file(builder, glade_file, glade_hbox);
+ auto widget{GTK_WIDGET(gtk_builder_get_object(builder, glade_menu))};
+ auto widget_hbox{GTK_WIDGET(gtk_builder_get_object(builder, glade_hbox))};
+ auto widget_warning{GTK_WIDGET(gtk_builder_get_object(builder, glade_warning))};
+ g_object_set_data(G_OBJECT(widget), "warning-image", widget_warning);
+ gnc_default_print_report_list (GTK_WIDGET(widget), GTK_WIDGET(widget_warning));
+ option.set_ui_item(std::make_unique<GncGtkInvReportUIItem>(widget));
+ option.set_ui_item_from_option();
+
+ g_signal_connect (G_OBJECT (widget), "changed",
+ G_CALLBACK (gnc_option_changed_widget_cb), &option);
+
+ wrap_widget (option, widget_hbox, page_box, row);
+ g_object_unref(builder); // Needs to wait until after widget has been reffed.
+}
+
void
gnc_business_options_gnome_initialize(void)
{
@@ -198,4 +246,6 @@ gnc_business_options_gnome_initialize(void)
create_option_widget<GncOptionUIType::INVOICE>);
GncOptionUIFactory::set_func(GncOptionUIType::TAX_TABLE,
create_option_widget<GncOptionUIType::TAX_TABLE>);
+ GncOptionUIFactory::set_func(GncOptionUIType::INV_REPORT,
+ create_option_widget<GncOptionUIType::INV_REPORT>);
}
diff --git a/gnucash/gnome/dialog-custom-report.c b/gnucash/gnome/dialog-custom-report.c
index 6a58d5be5..5436c46ba 100644
--- a/gnucash/gnome/dialog-custom-report.c
+++ b/gnucash/gnome/dialog-custom-report.c
@@ -28,6 +28,7 @@
#include <libguile.h>
#include "swig-runtime.h"
+#include "business-gnome-utils.h"
#include "dialog-custom-report.h"
#include "dialog-utils.h"
#include "gnc-main-window.h"
@@ -36,6 +37,7 @@
#include "gnc-guile-utils.h"
#include "gnc-gui-query.h"
#include "gnc-ui.h"
+#include "gnc-ui-util.h"
#include "gnc-report.h"
#include "gnc-plugin-page-report.h"
@@ -469,7 +471,23 @@ custom_report_name_edited_cb(GtkCellRendererText *renderer, gchar *path, gchar *
return;
if (scm_is_true (scm_call_2 (unique_name_func, guid, new_name_scm)))
+ {
+ gchar *default_guid = gnc_get_default_invoice_print_report ();
+
custom_report_edit_report_name (guid, crd, new_text);
+
+ // check to see if default report name has been changed
+ if (g_strcmp0 (default_guid, scm_to_utf8_string (guid)) == 0)
+ {
+ QofBook *book = gnc_get_current_book ();
+ gchar *default_name = qof_book_get_default_invoice_report_name (book);
+
+ if (g_strcmp0 (default_name, new_text) != 0)
+ qof_book_set_default_invoice_report (book, default_guid, new_text);
+ g_free (default_name);
+ }
+ g_free (default_guid);
+ }
else
gnc_error_dialog (GTK_WINDOW (crd->dialog), "%s",
_("A saved report configuration with this name already exists, please choose another name.") );
diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index 09ad5ac58..aeca0844e 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -783,19 +783,25 @@ gnc_invoice_window_print_invoice(GtkWindow *parent, GncInvoice *invoice)
{
SCM func, arg, arg2;
SCM args = SCM_EOL;
+ SCM is_invoice_guid;
+ SCM scm_guid;
int report_id;
- const char *reportname = gnc_plugin_business_get_invoice_printreport();
+ char *report_guid = gnc_get_default_invoice_print_report ();
GncPluginPage *reportPage = NULL;
g_return_val_if_fail (invoice, NULL);
- if (!reportname)
- reportname = "5123a759ceb9483abf2182d01c140e8d"; // fallback if the option lookup failed
+
+ is_invoice_guid = scm_c_eval_string ("gnc:report-is-invoice-report?");
+ scm_guid = scm_from_utf8_string (report_guid);
+
+ if (scm_is_false (scm_call_1 (is_invoice_guid, scm_guid)))
+ report_guid = g_strdup (gnc_get_builtin_default_invoice_print_report ()); // fallback if the option lookup failed
func = scm_c_eval_string ("gnc:invoice-report-create");
g_return_val_if_fail (scm_is_procedure (func), NULL);
arg = SWIG_NewPointerObj(invoice, SWIG_TypeQuery("_p__gncInvoice"), 0);
- arg2 = scm_from_utf8_string(reportname);
+ arg2 = scm_from_utf8_string (report_guid);
args = scm_cons2 (arg, arg2, args);
/* scm_gc_protect_object(func); */
@@ -810,7 +816,7 @@ gnc_invoice_window_print_invoice(GtkWindow *parent, GncInvoice *invoice)
reportPage = gnc_plugin_page_report_new (report_id);
gnc_main_window_open_page (GNC_MAIN_WINDOW (parent), reportPage);
}
-
+ g_free (report_guid);
return reportPage;
}
diff --git a/gnucash/gnome/gnc-plugin-business.c b/gnucash/gnome/gnc-plugin-business.c
index b877be8dc..b2196535a 100644
--- a/gnucash/gnome/gnc-plugin-business.c
+++ b/gnucash/gnome/gnc-plugin-business.c
@@ -112,7 +112,6 @@ static void bind_extra_toolbuttons_visibility (GncMainWindow *mainwindow);
#define PLUGIN_UI_FILENAME "gnc-plugin-business.ui"
#define GNC_PREF_EXTRA_TOOLBUTTONS "enable-toolbuttons"
-#define GNC_PREF_INV_PRINT_RPT "invoice-printreport"
/** This variable maintains a pointer to the last window where a
* Business command was executed. It is used to determine where new
@@ -1050,27 +1049,3 @@ gnc_plugin_business_add_to_window (GncPlugin *plugin,
G_CALLBACK(gnc_plugin_business_main_window_menu_changed),
plugin);
}
-
-static const char* invoice_printreport_values[] =
-{
- /* The list below are the guids of reports that can
- * be used to print an invoice.
- * Important: this list must be kept in sync with the one at the end
- * of business-prefs.glade
- */
- "5123a759ceb9483abf2182d01c140e8d", // "Printable Invoice"
- "0769e242be474010b4acf264a5512e6e", // "Tax Invoice"
- "67112f318bef4fc496bdc27d106bbda4", // "Easy Invoice"
- "3ce293441e894423a2425d7a22dd1ac6", // "Fancy Invoice"
- NULL
-};
-
-const char *
-gnc_plugin_business_get_invoice_printreport (void)
-{
- int value = gnc_prefs_get_int (GNC_PREFS_GROUP_INVOICE, GNC_PREF_INV_PRINT_RPT);
- if (value >= 0 && value < 4)
- return invoice_printreport_values[value];
- else
- return NULL;
-}
diff --git a/gnucash/gnome/gnc-plugin-business.h b/gnucash/gnome/gnc-plugin-business.h
index 9ded6cf98..73027cd58 100644
--- a/gnucash/gnome/gnc-plugin-business.h
+++ b/gnucash/gnome/gnc-plugin-business.h
@@ -64,8 +64,6 @@ void gnc_invoice_remind_bills_due (GtkWindow *parent);
void gnc_invoice_remind_invoices_due (GtkWindow *parent);
void gnc_invoice_remind_bills_due_cb (void);
void gnc_invoice_remind_invoices_due_cb (void);
-const char *gnc_plugin_business_get_invoice_printreport(void);
-
void gnc_plugin_business_split_reg_ui_update (GncPluginPage *plugin_page);
diff --git a/gnucash/gtkbuilder/business-options-gnome.glade b/gnucash/gtkbuilder/business-options-gnome.glade
index 23dd3ee34..00fd7f999 100644
--- a/gnucash/gtkbuilder/business-options-gnome.glade
+++ b/gnucash/gtkbuilder/business-options-gnome.glade
@@ -2,6 +2,56 @@
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.22"/>
+ <object class="GtkListStore" id="liststore_print_invoice">
+ <columns>
+ <!-- column-name title -->
+ <column type="gchararray"/>
+ <!-- column-name guid -->
+ <column type="gchararray"/>
+ <!-- column-name missing -->
+ <column type="gboolean"/>
+ </columns>
+ </object>
+ <object class="GtkWindow" id="dummy_toplevel_window2">
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkBox" id="invoice_report_hbox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkComboBox" id="invoice_report_combo">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="model">liststore_print_invoice</property>
+ <child>
+ <object class="GtkCellRendererText" id="cell_renderer_text"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="invoice_warning_image">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="icon-name">dialog-warning</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
<object class="GtkListStore" id="taxtable_store">
<columns>
<!-- column-name taxtable_name -->
diff --git a/gnucash/report/report-core.scm b/gnucash/report/report-core.scm
index f215836f1..c12bfdbd8 100644
--- a/gnucash/report/report-core.scm
+++ b/gnucash/report/report-core.scm
@@ -32,6 +32,7 @@
(use-modules (gnucash gnome-utils))
(use-modules (ice-9 match))
(use-modules (srfi srfi-1))
+(use-modules (srfi srfi-2))
(use-modules (srfi srfi-9))
(use-modules (srfi srfi-26))
(use-modules (gnucash report report-register-hooks))
@@ -46,6 +47,7 @@
(export <report>)
(export gnc:all-report-template-guids)
(export gnc:custom-report-template-guids)
+(export gnc:custom-report-invoice-template-guids)
(export gnc:define-report)
(export gnc:delete-report)
(export gnc:find-report-template)
@@ -75,6 +77,7 @@
(export gnc:report-export-thunk)
(export gnc:report-export-types)
(export gnc:report-id)
+(export gnc:report-is-invoice-report?)
(export gnc:report-menu-name)
(export gnc:report-name)
(export gnc:report-needs-save?)
@@ -169,7 +172,7 @@
(make-new-record-template version name report-guid parent-type options-generator
options-cleanup-cb options-changed-cb
renderer in-menu? menu-path menu-name
- menu-tip export-types export-thunk)
+ menu-tip hook export-types export-thunk)
report-template?
(version report-template-version)
(report-guid report-template-report-guid report-template-set-report-guid!)
@@ -183,11 +186,12 @@
(menu-path report-template-menu-path)
(menu-name report-template-menu-name)
(menu-tip report-template-menu-tip)
+ (hook report-template-hook)
(export-types report-template-export-types)
(export-thunk report-template-export-thunk))
(define (make-report-template)
- (make-new-record-template #f #f #f #f #f #f #f #f #t #f #f #f #f #f))
+ (make-new-record-template #f #f #f #f #f #f #f #f #t #f #f #f #f #f #f))
(define gnc:report-template-version report-template-version)
(define gnc:report-template-report-guid report-template-report-guid)
(define gnc:report-template-set-report-guid! report-template-set-report-guid!)
@@ -203,6 +207,7 @@
(define gnc:report-template-menu-path report-template-menu-path)
(define gnc:report-template-menu-name report-template-menu-name)
(define gnc:report-template-menu-tip report-template-menu-tip)
+(define gnc:report-template-hook report-template-hook)
(define gnc:report-template-export-types report-template-export-types)
(define gnc:report-template-export-thunk report-template-export-thunk)
@@ -450,6 +455,21 @@ not found.")))
(define (gnc:custom-report-template-guids)
(map car (gnc:custom-report-templates-list)))
+(define (gnc:report-is-invoice-report? guid)
+ (let ((tmpl (gnc:find-report-template guid)))
+ (cond
+ ((not tmpl) #f)
+ ((eq? (gnc:report-template-hook tmpl) 'invoice) #t)
+ (else (and-let* ((type (gnc:report-template-parent-type tmpl))
+ (template (gnc:find-report-template type)))
+ (eq? (gnc:report-template-hook template) 'invoice))))))
+
+;; return a list of the invoice report template guids.
+(define (gnc:custom-report-invoice-template-guids)
+ (hash-fold
+ (lambda (k v p) (if (gnc:report-is-invoice-report? k) (cons k p) p))
+ '() *gnc:_report-templates_*))
+
(define (gnc:find-report-template guid)
(hash-ref *gnc:_report-templates_* guid))
diff --git a/gnucash/report/reports/standard/invoice.scm b/gnucash/report/reports/standard/invoice.scm
index 20d0353b4..f04560313 100644
--- a/gnucash/report/reports/standard/invoice.scm
+++ b/gnucash/report/reports/standard/invoice.scm
@@ -851,6 +851,7 @@ for styling the invoice. Please see the exported report for the CSS class names.
'menu-path (list gnc:menuname-business-reports)
'options-generator (lambda () (options-generator 'invoice))
'renderer reg-renderer
+ 'hook 'invoice
'in-menu? #t)
(gnc:define-report
@@ -860,6 +861,7 @@ for styling the invoice. Please see the exported report for the CSS class names.
'menu-path (list gnc:menuname-business-reports)
'options-generator (lambda () (options-generator 'easy-invoice))
'renderer reg-renderer
+ 'hook 'invoice
'in-menu? #t)
(gnc:define-report
@@ -869,5 +871,6 @@ for styling the invoice. Please see the exported report for the CSS class names.
'menu-path (list gnc:menuname-business-reports)
'options-generator (lambda () (options-generator 'fancy-invoice))
'renderer reg-renderer
+ 'hook 'invoice
'in-menu? #t)
diff --git a/gnucash/report/reports/standard/taxinvoice.scm b/gnucash/report/reports/standard/taxinvoice.scm
index dbe2f35e2..085f06cb2 100644
--- a/gnucash/report/reports/standard/taxinvoice.scm
+++ b/gnucash/report/reports/standard/taxinvoice.scm
@@ -304,6 +304,7 @@
'menu-name (N_ "Tax Invoice")
'menu-tip (N_ "Display a customer invoice with tax columns (using eguile template)")
'menu-path (list gnc:menuname-business-reports)
+ 'hook 'invoice
'options-generator options-generator
'renderer report-renderer)
@@ -330,5 +331,6 @@
'menu-name (N_ "Australian Tax Invoice")
'menu-tip (N_ "Display an Australian customer invoice with tax columns (using eguile template)")
'menu-path (list gnc:menuname-business-reports)
+ 'hook 'invoice
'options-generator au-tax-options-generator
'renderer report-renderer)
diff --git a/libgnucash/engine/gnc-option-uitype.hpp b/libgnucash/engine/gnc-option-uitype.hpp
index 83b0f9347..7f856ef5d 100644
--- a/libgnucash/engine/gnc-option-uitype.hpp
+++ b/libgnucash/engine/gnc-option-uitype.hpp
@@ -66,6 +66,7 @@ enum class GncOptionUIType : unsigned int
INVOICE,
JOB,
TAX_TABLE,
+ INV_REPORT,
QUERY,
REPORT_PLACEMENT,
MAX_VALUE, //Nake sure this one is always last
diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp
index 9251618ca..a3bd62990 100644
--- a/libgnucash/engine/gnc-optiondb.cpp
+++ b/libgnucash/engine/gnc-optiondb.cpp
@@ -883,6 +883,16 @@ gnc_register_taxtable_option(GncOptionDB* db, const char* section,
db->register_option(section, std::move(option));
}
+void
+gnc_register_invoice_print_report_option(GncOptionDB* db, const char* section,
+ const char* name, const char* key,
+ const char* doc_string, std::string value)
+{
+ GncOption option{section, name, key, doc_string,
+ value, GncOptionUIType::INV_REPORT};
+ db->register_option(section, std::move(option));
+}
+
void
gnc_register_counter_option(GncOptionDB* db, const char* section,
const char* name, const char* key,
@@ -1266,13 +1276,16 @@ gnc_option_db_book_options(GncOptionDB* odb)
gnc_register_string_option(odb, business_section, N_("Company ID"), "c5",
N_("The ID for your company (eg 'Tax-ID: 00-000000)."),
empty_string);
-
+ gnc_register_invoice_print_report_option(odb, business_section,
+ OPTION_NAME_DEFAULT_INVOICE_REPORT, "e",
+ N_("The invoice report to be used for printing."),
+ empty_string);
gnc_register_taxtable_option(odb, business_section,
- N_("Default Customer TaxTable"), "e",
+ N_("Default Customer TaxTable"), "f1",
N_("The default tax table to apply to customers."),
nullptr);
gnc_register_taxtable_option(odb, business_section,
- N_("Default Vendor TaxTable"), "f",
+ N_("Default Vendor TaxTable"), "f2",
N_("The default tax table to apply to vendors."),
nullptr);
gnc_register_dateformat_option(odb, business_section,
diff --git a/libgnucash/engine/gnc-optiondb.hpp b/libgnucash/engine/gnc-optiondb.hpp
index 7147001f3..6a587d41e 100644
--- a/libgnucash/engine/gnc-optiondb.hpp
+++ b/libgnucash/engine/gnc-optiondb.hpp
@@ -713,6 +713,31 @@ inline void gnc_register_taxtable_option(const GncOptionDBPtr& db,
doc_string, value);
}
+/**
+ * Create a new print report 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_print_report_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_invoice_print_report_option(const GncOptionDBPtr& db,
+ const char* section, const char* name,
+ const char* key, const char* doc_string,
+ std::string value)
+{
+ gnc_register_invoice_print_report_option(db.get(), section, name, key,
+ doc_string, value);
+}
+
/**
* Create a new counter option and register it in the options database.
*
diff --git a/libgnucash/engine/qofbook.cpp b/libgnucash/engine/qofbook.cpp
index 5c4b8a8fb..d2a9a76ec 100644
--- a/libgnucash/engine/qofbook.cpp
+++ b/libgnucash/engine/qofbook.cpp
@@ -1014,6 +1014,90 @@ qof_book_option_num_autoreadonly_changed_cb (GObject *gobject,
book->cached_num_days_autoreadonly_isvalid = FALSE;
}
+static KvpValue*
+get_option_default_invoice_report_value (QofBook *book)
+{
+ KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE(book));
+ return root->get_slot ({KVP_OPTION_PATH,
+ OPTION_SECTION_BUSINESS,
+ OPTION_NAME_DEFAULT_INVOICE_REPORT});
+}
+
+void
+qof_book_set_default_invoice_report (QofBook *book, const gchar *guid,
+ const gchar *name)
+{
+ const gchar *existing_guid_name = nullptr;
+ gchar *new_guid_name;
+
+ if (!guid)
+ return;
+
+ KvpValue *value = get_option_default_invoice_report_value (book);
+
+ if (value)
+ existing_guid_name = {value->get<const char*>()};
+
+ new_guid_name = g_strconcat (guid, "/", name, nullptr);
+
+ if (g_strcmp0 (existing_guid_name, new_guid_name) != 0)
+ {
+ auto value = new KvpValue {g_strdup(new_guid_name)};
+ KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE(book));
+ qof_book_begin_edit (book);
+ delete root->set_path ({KVP_OPTION_PATH,
+ OPTION_SECTION_BUSINESS,
+ OPTION_NAME_DEFAULT_INVOICE_REPORT}, value);
+ qof_instance_set_dirty (QOF_INSTANCE(book));
+ qof_book_commit_edit (book);
+ }
+ g_free (new_guid_name);
+}
+
+gchar *
+qof_book_get_default_invoice_report_guid (const QofBook *book)
+{
+ KvpValue *value = get_option_default_invoice_report_value (const_cast<QofBook*>(book));
+ gchar *report_guid = nullptr;
+
+ if (value)
+ {
+ auto str {value->get<const char*>()};
+ auto ptr = strchr (str, '/');
+ if (ptr)
+ {
+ if (ptr - str == GUID_ENCODING_LENGTH)
+ {
+ if (strlen (str) > GUID_ENCODING_LENGTH + 1)
+ report_guid = g_strndup (&str[0], GUID_ENCODING_LENGTH);
+ }
+ }
+ }
+ return report_guid;
+}
+
+gchar *
+qof_book_get_default_invoice_report_name (const QofBook *book)
+{
+ KvpValue *value = get_option_default_invoice_report_value (const_cast<QofBook*>(book));
+ gchar *report_name = nullptr;
+
+ if (value)
+ {
+ auto str {value->get<const char*>()};
+ auto ptr = strchr (str, '/');
+ if (ptr)
+ {
+ if (ptr - str == GUID_ENCODING_LENGTH)
+ {
+ if (strlen (str) > GUID_ENCODING_LENGTH + 1)
+ report_name = g_strdup (&str[GUID_ENCODING_LENGTH + 1]);
+ }
+ }
+ }
+ return report_name;
+}
+
/* Note: this will fail if the book slots we're looking for here are flattened at some point !
* When that happens, this function can be removed. */
static Path opt_name_to_path (const char* opt_name)
diff --git a/libgnucash/engine/qofbook.h b/libgnucash/engine/qofbook.h
index 3dba3e957..3ab6c0953 100644
--- a/libgnucash/engine/qofbook.h
+++ b/libgnucash/engine/qofbook.h
@@ -289,6 +289,22 @@ gint qof_book_get_num_days_autoreadonly (const QofBook *book);
* g_date_free() the object afterwards. */
GDate* qof_book_get_autoreadonly_gdate (const QofBook *book);
+/** Save the Invoice Report name / guid to be used as the default for printing
+ * Invoices
+ */
+void qof_book_set_default_invoice_report (QofBook *book, const gchar *guid,
+ const gchar *name);
+
+/** Get the guid of the Invoice Report to be used as the default for printing
+ * Invoices
+ */
+gchar * qof_book_get_default_invoice_report_guid (const QofBook *book);
+
+/** Get the name of the Invoice Report to be used as the default for printing
+ * Invoices
+ */
+gchar * qof_book_get_default_invoice_report_name (const QofBook *book);
+
/** Returns TRUE if this book uses split action field as the 'Num' field, FALSE
* if it uses transaction number field */
gboolean qof_book_use_split_action_for_num_field (const QofBook *book);
diff --git a/libgnucash/engine/qofbookslots.h b/libgnucash/engine/qofbookslots.h
index 4ed5fd8c2..ea0e32bcd 100644
--- a/libgnucash/engine/qofbookslots.h
+++ b/libgnucash/engine/qofbookslots.h
@@ -69,6 +69,10 @@
#define OPTION_SECTION_BUDGETING N_("Budgeting")
#define OPTION_NAME_DEFAULT_BUDGET N_("Default Budget")
+#define OPTION_SECTION_BUSINESS N_("Business")
+
+#define OPTION_NAME_DEFAULT_INVOICE_REPORT N_("Default Invoice Report")
+
/** @} */
/* For the grep-happy:
Summary of changes:
gnucash/gnome-utils/CMakeLists.txt | 2 +
gnucash/gnome-utils/gnc-report-combo.c | 551 ++++++++++++++++++++++++
gnucash/gnome-utils/gnc-report-combo.h | 123 ++++++
gnucash/gnome/business-gnome-utils.c | 117 +++++
gnucash/gnome/business-gnome-utils.h | 38 ++
gnucash/gnome/business-options-gnome.cpp | 51 +++
gnucash/gnome/dialog-custom-report.c | 18 +
gnucash/gnome/dialog-invoice.c | 193 ++++++++-
gnucash/gnome/gnc-plugin-business.c | 25 --
gnucash/gnome/gnc-plugin-business.h | 2 -
gnucash/gschemas/pref_transformations.xml | 12 +
gnucash/gtkbuilder/business-options-gnome.glade | 12 +-
gnucash/gtkbuilder/business-prefs.glade | 66 +--
gnucash/gtkbuilder/dialog-invoice.glade | 127 ++++++
gnucash/report/report-core.scm | 24 +-
gnucash/report/reports/standard/invoice.scm | 3 +
gnucash/report/reports/standard/taxinvoice.scm | 2 +
libgnucash/engine/gnc-option-uitype.hpp | 1 +
libgnucash/engine/gnc-optiondb.cpp | 23 +-
libgnucash/engine/gnc-optiondb.hpp | 25 ++
libgnucash/engine/qofbook.cpp | 99 +++++
libgnucash/engine/qofbook.h | 21 +
libgnucash/engine/qofbookslots.h | 5 +
po/POTFILES.in | 1 +
24 files changed, 1442 insertions(+), 99 deletions(-)
create mode 100644 gnucash/gnome-utils/gnc-report-combo.c
create mode 100644 gnucash/gnome-utils/gnc-report-combo.h
More information about the gnucash-changes
mailing list