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.
This commit is contained in:
Robert Fewell
2023-02-01 16:26:38 +00:00
parent b41e491ec5
commit 07f3f536cc
6 changed files with 328 additions and 11 deletions

View File

@@ -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

View File

@@ -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 -->

View File

@@ -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."),

View File

@@ -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)

View File

@@ -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);

View File

@@ -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")
/** @} */