* src/gnome-utils/dialog-query-list*: the glade and C code for

a general QueryList Dialog.
	* src/gnome-utils/Makefile.am: compile the new dialog.
	* src/business/business-gnome/business-gnome.scm: use the new
	  querylist dialog to display the due bills
	* src/business/business-gnome/dialog-invoice.[ch]: create a new
	  API to run a due-bills dialog.
	* src/business/businss-gnome/gw-business-gnome-spec.scm: wrap the
	  new due-bills api
	* src/engine/gnc-book.c: forcibly signal a book destroy event


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@8340 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins 2003-05-19 15:59:29 +00:00
parent e2dbe1e10b
commit 220e6dac33
10 changed files with 623 additions and 23 deletions

View File

@ -8,6 +8,17 @@
* src/engine/gnc-event*: add an api to force an event even when
events are suspended. Without such an API, events can be lost
if the event system is suspended when the event comes in.
* src/gnome-utils/dialog-query-list*: the glade and C code for
a general QueryList Dialog.
* src/gnome-utils/Makefile.am: compile the new dialog.
* src/business/business-gnome/business-gnome.scm: use the new
querylist dialog to display the due bills
* src/business/business-gnome/dialog-invoice.[ch]: create a new
API to run a due-bills dialog.
* src/business/businss-gnome/gw-business-gnome-spec.scm: wrap the
new due-bills api
* src/engine/gnc-book.c: forcibly signal a book destroy event
2003-05-18 Derek Atkins <derek@ihtfp.com>

View File

@ -25,6 +25,16 @@
(define (option-value name)
(gnc:option-value (gnc:lookup-global-option gnc:*business-label* name)))
(let ((check-bills? (option-value "Notify Bills Due?")))
(if (and session check-bills?)
(let* ((book (gnc:session-get-book session))
(days (option-value "Bills Due Days")))
(gnc:invoice-show-bills-due book days)))))
(define (old-remind-bills-due session)
(define (option-value name)
(gnc:option-value (gnc:lookup-global-option gnc:*business-label* name)))
(define (get-payables book)
(let* ((group (gnc:book-get-group book))
(acct-list (gnc:group-get-subaccounts group))
@ -527,6 +537,6 @@
(gnc:hook-add-dangler gnc:*report-hook* business-report-function)
(gnc:hook-add-dangler gnc:*ui-startup-hook* add-business-items)
(gnc:hook-add-dangler gnc:*ui-post-startup-hook* business-ui-started)
;(gnc:hook-add-dangler gnc:*book-opened-hook* business-book-opened)
;(gnc:hook-add-dangler gnc:*ui-post-startup-hook* business-ui-started)
(gnc:hook-add-dangler gnc:*book-opened-hook* business-book-opened)
(gnc:hook-add-dangler gnc:*add-extension-hook* add-business-test)

View File

@ -43,6 +43,8 @@
#include "AccWindow.h"
#include "guile-mappings.h"
#include "dialog-query-list.h"
#define DIALOG_NEW_INVOICE_CM_CLASS "dialog-new-invoice"
#define DIALOG_VIEW_INVOICE_CM_CLASS "dialog-view-invoice"
@ -2192,39 +2194,44 @@ gnc_ui_invoice_new (GncOwner *ownerp, GNCBook *bookp)
/* Functions for invoice selection widgets */
static void
edit_invoice_direct (gpointer invoice, gpointer user_data)
{
g_return_if_fail (invoice);
gnc_ui_invoice_edit (invoice);
}
static void
edit_invoice_cb (gpointer *invoice_p, gpointer user_data)
{
GncInvoice *invoice;
g_return_if_fail (invoice_p && user_data);
invoice = *invoice_p;
if (!invoice)
if (! *invoice_p)
return;
edit_invoice_direct (*invoice_p, user_data);
}
gnc_ui_invoice_edit (invoice);
static void
pay_invoice_direct (gpointer inv, gpointer user_data)
{
GncInvoice *invoice = inv;
GNCLot *lot;
gnc_numeric val;
g_return_if_fail (invoice);
lot = gncInvoiceGetPostedLot (invoice);
val = gnc_numeric_abs (gnc_lot_get_balance (lot));
gnc_ui_payment_new_with_value (gncInvoiceGetOwner (invoice),
gncInvoiceGetBook (invoice), val);
}
static void
pay_invoice_cb (gpointer *invoice_p, gpointer user_data)
{
struct _invoice_select_window *sw = user_data;
GncInvoice *invoice;
GNCLot *lot;
gnc_numeric val;
g_return_if_fail (invoice_p && user_data);
invoice = *invoice_p;
if (!invoice)
if (! *invoice_p)
return;
lot = gncInvoiceGetPostedLot (invoice);
val = gnc_numeric_abs (gnc_lot_get_balance (lot));
gnc_ui_payment_new_with_value (gncInvoiceGetOwner (invoice), sw->book, val);
pay_invoice_direct (*invoice_p, user_data);
}
static gpointer
@ -2389,3 +2396,71 @@ gnc_invoice_search_edit (gpointer start, gpointer book)
return NULL;
}
DialogQueryList *
gnc_invoice_show_bills_due (GNCBook *book, int days_in_advance)
{
GNCIdType type = GNC_INVOICE_MODULE_NAME;
Query *q;
QueryPredData_t pred_data;
time_t end_date;
GList *res;
gint len;
static GList *param_list = NULL;
static GNCDisplayListButton buttons[] = {
{ N_("View/Edit Bill"), edit_invoice_direct },
{ N_("Process Payment"), pay_invoice_direct },
{ NULL },
};
/* create the param list (in reverse order) */
if (param_list == NULL) {
param_list = gnc_search_param_prepend (param_list, _("Amount"), NULL, type,
INVOICE_POST_LOT, LOT_BALANCE, NULL);
param_list = gnc_search_param_prepend (param_list, _("Company"), NULL, type,
INVOICE_OWNER, OWNER_NAME, NULL);
param_list = gnc_search_param_prepend (param_list, _("Due"), NULL, type,
INVOICE_DUE, NULL);
}
/* Create the query to search for invoices; set the book */
q = gncQueryCreate();
gncQuerySearchFor(q, GNC_INVOICE_MODULE_NAME);
gncQuerySetBook (q, book);
/* we want to find all invoices where:
* invoice -> is_posted == TRUE
* AND invoice -> lot -> is_closed? == FALSE
* AND invoice -> type != _("Invoice")
* AND invoice -> due >= (today - days_in_advance)
*/
gncQueryAddBooleanMatch (q, g_slist_prepend(NULL, INVOICE_IS_POSTED), TRUE,
QUERY_AND);
gncQueryAddBooleanMatch (q, g_slist_prepend(g_slist_prepend(NULL, LOT_IS_CLOSED),
INVOICE_POST_LOT), FALSE, QUERY_AND);
pred_data = gncQueryStringPredicate (COMPARE_NEQ, _("Invoice"),
STRING_MATCH_NORMAL, FALSE);
gncQueryAddTerm (q, g_slist_prepend(NULL, INVOICE_TYPE), pred_data, QUERY_AND);
end_date = time(NULL);
if (days_in_advance < 0)
days_in_advance = 0;
end_date += days_in_advance*60*60*24;
xaccQueryAddDateMatchTT(q, FALSE, 0, TRUE, end_date, QUERY_AND);
res = gncQueryRun(q);
len = g_list_length (res);
if (!res || len <= 0)
return NULL;
return gnc_dialog_query_list_create(param_list, q,
_("Due Bills Reminder"),
(len > 1) ?
_("The following bills are due") :
_("The following bill is due"),
TRUE, FALSE,
buttons, NULL);
}

View File

@ -13,6 +13,7 @@ typedef struct _invoice_window InvoiceWindow;
#include "gncInvoice.h"
#include "gncOwner.h"
#include "dialog-search.h"
#include "dialog-query-list.h"
/* Create and edit an invoice */
InvoiceWindow * gnc_ui_invoice_edit (GncInvoice *invoice);
@ -32,4 +33,6 @@ GNCSearchWindow * gnc_invoice_search_edit (gpointer start, gpointer book);
void gnc_business_call_owner_report (GncOwner *owner, Account *acc);
DialogQueryList *gnc_invoice_show_bills_due (GNCBook *book, int days_in_advance);
#endif /* GNC_DIALOG_INVOICE_H_ */

View File

@ -163,6 +163,14 @@
"Dialog: Select a GncInvoice. Either start_selection or "
"owner may be NULL.")
(gw:wrap-function
ws
'gnc:invoice-show-bills-due
'<gw:void>
"gnc_invoice_show_bills_due"
'((<gnc:Book*> book) (<gw:int> days_in_advance))
"Dialog: display the bills due within the next \"days\"")
;;
;; dialog-job.h
;;

View File

@ -123,7 +123,7 @@ gnc_book_destroy (GNCBook *book)
if (!book) return;
ENTER ("book=%p", book);
gnc_engine_generate_event (&book->guid, GNC_EVENT_DESTROY);
gnc_engine_force_event (&book->guid, GNC_EVENT_DESTROY);
gncObjectBookEnd (book);

View File

@ -25,6 +25,7 @@ libgncmod_gnome_utils_la_SOURCES = \
dialog-account-pick.c \
dialog-commodity.c \
dialog-options.c \
dialog-query-list.c \
dialog-transfer.c \
dialog-utils.c \
druid-utils.c \
@ -59,6 +60,7 @@ gncinclude_HEADERS = \
dialog-account-pick.h \
dialog-commodity.h \
dialog-options.h \
dialog-query-list.h \
dialog-transfer.h \
dialog-utils.h \
druid-utils.h \
@ -125,6 +127,7 @@ gncscm_DATA = gnc-menu-extensions.scm
gladedir = $(GNC_GLADE_DIR)
glade_DATA = \
commodity.glade \
dialog-query-list.glade \
exchange-dialog.glade \
transfer.glade

View File

@ -0,0 +1,302 @@
/*
* dialog-query-list.c -- a simple dialog to display a querylist and
* allow users to select items (or close the list)
*
* Created By: Derek Atkins <derek@ihtfp.com>
*
*/
#include "config.h"
#include <gnome.h>
#include "dialog-utils.h"
#include "gnc-component-manager.h"
#include "dialog-query-list.h"
#include "gnc-query-list.h"
struct _DialogQueryList {
GtkWidget * dialog;
GtkWidget * label;
GtkWidget * qlist;
GtkWidget * button_box;
GNCDisplayListButton * buttons;
gpointer user_data;
GList * books;
gint component_id;
};
static void
dql_clear_booklist (DialogQueryList *dql)
{
GList *node;
g_return_if_fail (dql);
for (node = dql->books; node; node = node->next)
xaccGUIDFree ((GUID*)node->data);
g_list_free (dql->books);
dql->books = NULL;
}
static void
dql_build_booklist (DialogQueryList *dql, Query *q)
{
GList *node;
g_return_if_fail (dql);
for (node = gncQueryGetBooks(q); node; node=node->next) {
GNCBook *book = node->data;
GUID *guid = xaccGUIDMalloc();
*guid = *(gnc_book_get_guid(book));
dql->books = g_list_prepend(dql->books, guid);
}
}
static void
gnc_dialog_query_run_callback (GNCDisplayListButton *cb, gpointer item,
DialogQueryList *dql)
{
if (!cb)
return;
if (cb->cb_fcn)
(cb->cb_fcn)(item, dql->user_data);
}
static void
gnc_dialog_query_list_button_clicked (GtkButton *button, DialogQueryList *dql)
{
GNCDisplayListButton *cb;
gpointer current;
g_return_if_fail (dql);
current = gnc_query_list_get_current_entry (GNC_QUERY_LIST (dql->qlist));
if (!current)
return;
cb = gtk_object_get_data (GTK_OBJECT (button), "data");
g_return_if_fail (cb);
gnc_dialog_query_run_callback (cb, current, dql);
}
static void
gnc_dialog_query_list_double_click_entry (GNCQueryList *list, gpointer item,
gpointer user_data)
{
DialogQueryList *dql = user_data;
g_return_if_fail (dql);
g_return_if_fail (item);
if (!dql->buttons)
return;
gnc_dialog_query_run_callback (dql->buttons, item, dql);
}
static void
close_handler (gpointer data)
{
DialogQueryList * dql = data;
g_return_if_fail (dql);
gnome_dialog_close (GNOME_DIALOG (dql->dialog));
}
static void
gnc_dialog_query_list_refresh_handler (GHashTable *changes, gpointer user_data)
{
DialogQueryList *dql = (DialogQueryList *)user_data;
const EventInfo *info;
GList *node;
if (changes)
{
for (node = dql->books; node; node = node->next)
{
info = gnc_gui_get_entity_events (changes, (GUID*)(node->data));
if (info && (info->event_mask & GNC_EVENT_DESTROY))
{
gnc_close_gui_component (dql->component_id);
return;
}
}
}
}
static int
gnc_dialog_query_list_close_cb (GnomeDialog *dialog, DialogQueryList *dql)
{
g_return_val_if_fail (dql, TRUE);
gnc_unregister_gui_component (dql->component_id);
/* XXX: Clear/destroy the param_list? */
/* destroy the book list */
dql_clear_booklist (dql);
/* Destroy and exit */
g_free (dql);
return FALSE;
}
static void
gnc_dialog_query_list_close (GtkButton *button, DialogQueryList *dql)
{
/* Don't select anything */
gnc_dialog_query_list_destroy (dql);
}
/*****************************************************************/
/* PUBLIC INTERFACES */
DialogQueryList *
gnc_dialog_query_list_new (GList *param_list, Query *q)
{
GladeXML *xml;
DialogQueryList *dql;
GtkWidget *scroller, *close;
GList *node;
dql = g_new0 (DialogQueryList, 1);
xml = gnc_glade_xml_new ("dialog-query-list.glade", "Query List Dialog");
/* Grab the dialog, save the dialog info */
dql->dialog = glade_xml_get_widget (xml, "Query List Dialog");
gtk_object_set_data (GTK_OBJECT (dql->dialog), "dialog-info", dql);
/* grab the widgets */
dql->label = glade_xml_get_widget (xml, "dialog_label");
dql->button_box = glade_xml_get_widget (xml, "button_vbox");
scroller = glade_xml_get_widget (xml, "result_scroller");
close = glade_xml_get_widget (xml, "close_button");
/* build the query list */
dql->qlist = gnc_query_list_new (param_list, q);
gtk_container_add (GTK_CONTAINER (scroller), dql->qlist);
/* connect the double-click signal of the qlist */
gtk_signal_connect (GTK_OBJECT (dql->qlist), "double_click_entry",
gnc_dialog_query_list_double_click_entry, dql);
/* connect to the close button */
gtk_signal_connect (GTK_OBJECT (close), "clicked",
GTK_SIGNAL_FUNC (gnc_dialog_query_list_close), dql);
/* connect to the cleanup */
gtk_signal_connect (GTK_OBJECT (dql->dialog), "close",
GTK_SIGNAL_FUNC (gnc_dialog_query_list_close_cb), dql);
/* register ourselves */
dql->component_id =
gnc_register_gui_component ("GNC Dialog Query List",
gnc_dialog_query_list_refresh_handler,
close_handler, dql);
/* Build the book list */
dql_build_booklist (dql, q);
/* and register the books */
for (node = dql->books; node; node = node->next)
gnc_gui_component_watch_entity (dql->component_id, (GUID*)node->data,
GNC_EVENT_DESTROY);
return dql;
}
void gnc_dialog_query_list_set_title (DialogQueryList *dql, const char *title)
{
if (!dql || !title) return;
gtk_window_set_title (GTK_WINDOW (dql->dialog), title);
}
void gnc_dialog_query_list_set_label (DialogQueryList *dql, const char *label)
{
if (!dql || !label) return;
gtk_label_set_text (GTK_LABEL(dql->label), label);
}
void gnc_dialog_query_list_set_buttons (DialogQueryList *dql,
GNCDisplayListButton *buttons,
gpointer user_data)
{
GtkWidget *button;
int i;
if (!dql || !buttons) return;
g_return_if_fail (dql->buttons == NULL);
dql->buttons = buttons;
dql->user_data = user_data;
/* build up the buttons */
for (i = 0; buttons[i].label; i++) {
button = gtk_button_new_with_label (buttons[i].label);
gtk_object_set_data (GTK_OBJECT (button), "data", &(dql->buttons[i]));
gtk_signal_connect (GTK_OBJECT (button), "clicked",
gnc_dialog_query_list_button_clicked, dql);
gtk_box_pack_start (GTK_BOX (dql->button_box), button, FALSE, FALSE, 3);
}
}
void gnc_dialog_query_list_set_numerics (DialogQueryList *dql, gboolean abs,
gboolean inv_sort)
{
if (!dql) return;
gnc_query_list_set_numerics (GNC_QUERY_LIST(dql->qlist), abs, inv_sort);
}
void gnc_dialog_query_list_refresh (DialogQueryList *dql)
{
if (!dql) return;
gnc_query_list_refresh (GNC_QUERY_LIST(dql->qlist));
gtk_widget_show_all (dql->dialog);
}
void gnc_dialog_query_list_destroy (DialogQueryList *dql)
{
if (!dql) return;
gnc_close_gui_component (dql->component_id);
}
DialogQueryList *
gnc_dialog_query_list_create (GList *param_list, Query *q,
const char *title, const char *label,
gboolean abs, gboolean inv_sort,
GNCDisplayListButton *buttons, gpointer user_data)
{
DialogQueryList *dql;
if (!param_list || !q)
return NULL;
dql = gnc_dialog_query_list_new (param_list, q);
if (!dql)
return NULL;
if (title)
gnc_dialog_query_list_set_title (dql, title);
if (label)
gnc_dialog_query_list_set_label (dql, label);
gnc_dialog_query_list_set_numerics (dql, abs, inv_sort);
if (buttons)
gnc_dialog_query_list_set_buttons (dql, buttons, user_data);
gnc_dialog_query_list_refresh (dql);
return dql;
}

View File

@ -0,0 +1,145 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>Dialog Query List</name>
<program_name>dialog-query-list</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GnomeDialog</class>
<name>Query List Dialog</name>
<visible>False</visible>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox1</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area1</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>close_button</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_CLOSE</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>dialog_label</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>True</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>3</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>result_scroller</name>
<width>250</width>
<height>150</height>
<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>Placeholder</class>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>button_vbox</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>Placeholder</class>
</widget>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@ -0,0 +1,43 @@
/*
* dialog-query-list.h -- a simple dialog to display a querylist and
* allow users to select items (or close the list)
*
* Created By: Derek Atkins <derek@ihtfp.com>
*
*/
#ifndef GNC_DIALOG_QUERY_LIST_H
#define GNC_DIALOG_QUERY_LIST_H
#include "Query.h"
typedef struct _DialogQueryList DialogQueryList;
typedef void (*GNCDisplayListCB)(gpointer obj, gpointer user_data);
typedef struct {
const char * label;
GNCDisplayListCB cb_fcn;
} GNCDisplayListButton;
DialogQueryList *
gnc_dialog_query_list_new (GList *param_list, Query *q);
void gnc_dialog_query_list_set_title (DialogQueryList *dql, const char *title);
void gnc_dialog_query_list_set_label (DialogQueryList *dql, const char *label);
void gnc_dialog_query_list_set_buttons (DialogQueryList *dql,
GNCDisplayListButton *buttons,
gpointer user_data);
void gnc_dialog_query_list_set_numerics (DialogQueryList *dql, gboolean abs,
gboolean inv_sort);
void gnc_dialog_query_list_refresh (DialogQueryList *dql);
void gnc_dialog_query_list_destroy (DialogQueryList *dql);
DialogQueryList *
gnc_dialog_query_list_create (GList *param_list, Query *q,
const char *title, const char *label,
gboolean abs, gboolean inv_sort,
GNCDisplayListButton *buttons, gpointer user_data);
#endif /* GNC_DIALOG_QUERY_LIST_H */