From c82722fdab2b15c5dac7e15165d74b27b0335059 Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Wed, 13 Feb 2002 00:35:42 +0000 Subject: [PATCH] - Add Account Search widget(s) Some of the QueryNew ACCOUNT_* names conflicted with entries in the AccountFieldCode enumeration. Hopefully, eventually, the two sets of names can be combined. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6712 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/QueryCore.c | 2 +- src/engine/QueryNew.h | 10 +- src/engine/QueryObject.c | 10 +- src/gnome-search/Makefile.am | 2 + src/gnome-search/dialog-search.c | 30 ++- src/gnome-search/search-account.c | 359 ++++++++++++++++++++++++++++ src/gnome-search/search-account.h | 56 +++++ src/gnome-search/search-core-type.c | 5 + 8 files changed, 455 insertions(+), 19 deletions(-) create mode 100644 src/gnome-search/search-account.c create mode 100644 src/gnome-search/search-account.h diff --git a/src/engine/QueryCore.c b/src/engine/QueryCore.c index 276e78a214..fff0db5daf 100644 --- a/src/engine/QueryCore.c +++ b/src/engine/QueryCore.c @@ -429,7 +429,7 @@ static int guid_match_predicate (gpointer object, QueryAccess get_fcn, { query_guid_t pdata = (query_guid_t)pd; GList *node; - const GUID *guid; + const GUID *guid = NULL; VERIFY_PREDICATE (query_guid_type); diff --git a/src/engine/QueryNew.h b/src/engine/QueryNew.h index 90c07b4af1..56b9ba616d 100644 --- a/src/engine/QueryNew.h +++ b/src/engine/QueryNew.h @@ -73,11 +73,11 @@ typedef enum { #define ACCOUNT_KVP "kvp" #define ACCOUNT_GUID "guid" -#define ACCOUNT_NAME "name" -#define ACCOUNT_CODE "code" -#define ACCOUNT_DESCRIPTION "desc" -#define ACCOUNT_NOTES "notes" -#define ACCOUNT_BALANCE "balance" +#define ACCOUNT_NAME_ "name" +#define ACCOUNT_CODE_ "code" +#define ACCOUNT_DESCRIPTION_ "desc" +#define ACCOUNT_NOTES_ "notes" +#define ACCOUNT_BALANCE_ "balance" #define ACCOUNT_CLEARED_BALANCE "cleared-balance" #define ACCOUNT_RECONCILED_BALANCE "reconciled-balance" #define ACCOUNT_TAX_RELATED "tax-related-p" diff --git a/src/engine/QueryObject.c b/src/engine/QueryObject.c index ba488424ee..d5e5d9403c 100644 --- a/src/engine/QueryObject.c +++ b/src/engine/QueryObject.c @@ -100,11 +100,11 @@ static void init_account (void) static QueryObjectDef params[] = { { ACCOUNT_KVP, QUERYCORE_KVP, (QueryAccess)xaccAccountGetSlots }, { ACCOUNT_GUID, QUERYCORE_GUID, (QueryAccess)xaccAccountGetGUID }, - { ACCOUNT_NAME, QUERYCORE_STRING, (QueryAccess)xaccAccountGetName }, - { ACCOUNT_CODE, QUERYCORE_STRING, (QueryAccess)xaccAccountGetCode }, - { ACCOUNT_DESCRIPTION, QUERYCORE_STRING, (QueryAccess)xaccAccountGetDescription }, - { ACCOUNT_NOTES, QUERYCORE_STRING, (QueryAccess)xaccAccountGetNotes }, - { ACCOUNT_BALANCE, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetBalance }, + { ACCOUNT_NAME_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetName }, + { ACCOUNT_CODE_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetCode }, + { ACCOUNT_DESCRIPTION_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetDescription }, + { ACCOUNT_NOTES_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetNotes }, + { ACCOUNT_BALANCE_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetBalance }, { ACCOUNT_CLEARED_BALANCE, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetClearedBalance }, { ACCOUNT_RECONCILED_BALANCE, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetReconciledBalance }, { ACCOUNT_TAX_RELATED, QUERYCORE_BOOLEAN, (QueryAccess)xaccAccountGetTaxRelated }, diff --git a/src/gnome-search/Makefile.am b/src/gnome-search/Makefile.am index 2b741bb71a..0d2c41d565 100644 --- a/src/gnome-search/Makefile.am +++ b/src/gnome-search/Makefile.am @@ -18,6 +18,7 @@ AM_CFLAGS = \ libgncmod_gnome_search_la_SOURCES = \ gncmod-gnome-search.c \ dialog-search.c \ + search-account.c \ search-boolean.c \ search-core-type.c \ search-date.c \ @@ -28,6 +29,7 @@ libgncmod_gnome_search_la_SOURCES = \ search-string.c noinst_HEADERS = \ + search-account.h \ search-boolean.h \ search-core-type.h \ search-date.h \ diff --git a/src/gnome-search/dialog-search.c b/src/gnome-search/dialog-search.c index 7c5b63d9fd..5fe5d4719f 100644 --- a/src/gnome-search/dialog-search.c +++ b/src/gnome-search/dialog-search.c @@ -375,12 +375,14 @@ gnc_search_dialog_destroy (GNCSearchWindow *sw) static GNCSearchParam * make_param (GNCIdTypeConst type, const char *title, const char *path1, - const char *path2) + const char *path2, const char *path3) { GSList *l = NULL; GNCSearchParam *param = gnc_search_param_new (); gnc_search_param_set_title (param, title); + if (path3) + l = g_slist_prepend (l, (gpointer) path3); if (path2) l = g_slist_prepend (l, (gpointer) path2); l = g_slist_prepend (l, (gpointer) path1); @@ -394,21 +396,33 @@ static GList * get_params_list (GNCIdTypeConst type) { GList *list = NULL; + GNCSearchParam *param; + + param = make_param (type, "Txn: All Accounts", + SPLIT_TRANS, TRANS_SPLITLIST, SPLIT_ACCOUNT_GUID); + gnc_search_param_override_param_type (param, "account-match-all"); + list = g_list_prepend (list, param); + + param = make_param (type, "Split Account", SPLIT_ACCOUNT, ACCOUNT_GUID, + NULL); + gnc_search_param_override_param_type (param, GNC_ID_ACCOUNT); + list = g_list_prepend (list, param); list = g_list_prepend (list, make_param (type, "Split->Txn->Void?", - SPLIT_TRANS, TRANS_VOID_STATUS)); + SPLIT_TRANS, TRANS_VOID_STATUS, + NULL)); list = g_list_prepend (list, make_param (type, "Split Int64", - "d-share-int64", NULL)); + "d-share-int64", NULL, NULL)); list = g_list_prepend (list, make_param (type, "Split Amount (double)", - "d-share-amount", NULL)); + "d-share-amount", NULL, NULL)); list = g_list_prepend (list, make_param (type, "Split Value (debcred)", - SPLIT_VALUE, NULL)); + SPLIT_VALUE, NULL, NULL)); list = g_list_prepend (list, make_param (type, "Split Amount (numeric)", - SPLIT_AMOUNT, NULL)); + SPLIT_AMOUNT, NULL, NULL)); list = g_list_prepend (list, make_param (type, "Date Reconciled (date)", - SPLIT_DATE_RECONCILED, NULL)); + SPLIT_DATE_RECONCILED, NULL, NULL)); list = g_list_prepend (list, make_param (type, "Split Memo (string)", - SPLIT_MEMO, NULL)); + SPLIT_MEMO, NULL, NULL)); return list; } diff --git a/src/gnome-search/search-account.c b/src/gnome-search/search-account.c new file mode 100644 index 0000000000..00629b3ca8 --- /dev/null +++ b/src/gnome-search/search-account.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2002 Derek Atkins + * + * Authors: Derek Atkins + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "Account.h" +#include "QueryCore.h" +#include "gnc-account-tree.h" +#include "gnc-gui-query.h" + +#include "search-account.h" + +#define d(x) + +static GNCSearchCoreType *clone(GNCSearchCoreType *fe); +static gboolean validate (GNCSearchCoreType *fe); +static GtkWidget *get_widget(GNCSearchCoreType *fe); +static QueryPredData_t get_predicate (GNCSearchCoreType *fe); + +static void gnc_search_account_class_init (GNCSearchAccountClass *class); +static void gnc_search_account_init (GNCSearchAccount *gspaper); +static void gnc_search_account_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((GNCSearchAccount *)(x))->priv) + +struct _GNCSearchAccountPrivate { + gboolean match_all; + GList * selected_accounts; +}; + +static GNCSearchCoreTypeClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +gnc_search_account_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "GNCSearchAccount", + sizeof(GNCSearchAccount), + sizeof(GNCSearchAccountClass), + (GtkClassInitFunc)gnc_search_account_class_init, + (GtkObjectInitFunc)gnc_search_account_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gnc_search_core_type_get_type (), &type_info); + } + + return type; +} + +static void +gnc_search_account_class_init (GNCSearchAccountClass *class) +{ + GtkObjectClass *object_class; + GNCSearchCoreTypeClass *gnc_search_core_type = (GNCSearchCoreTypeClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gnc_search_core_type_get_type ()); + + object_class->finalize = gnc_search_account_finalise; + + /* override methods */ + gnc_search_core_type->validate = validate; + gnc_search_core_type->get_widget = get_widget; + gnc_search_core_type->get_predicate = get_predicate; + gnc_search_core_type->clone = clone; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +gnc_search_account_init (GNCSearchAccount *o) +{ + o->priv = g_malloc0 (sizeof (*o->priv)); + o->how = GUID_MATCH_ANY; +} + +static void +gnc_search_account_finalise (GtkObject *obj) +{ + GNCSearchAccount *o = (GNCSearchAccount *)obj; + g_assert (IS_GNCSEARCH_ACCOUNT (o)); + + g_free(o->priv); + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * gnc_search_account_new: + * + * Create a new GNCSearchAccount object. + * + * Return value: A new #GNCSearchAccount object. + **/ +GNCSearchAccount * +gnc_search_account_new (void) +{ + GNCSearchAccount *o = (GNCSearchAccount *)gtk_type_new(gnc_search_account_get_type ()); + return o; +} + +/** + * gnc_search_account_matchall_new: + * + * Create a new GNCSearchAccount object. + * + * Return value: A new #GNCSearchAccount object. + **/ +GNCSearchAccount * +gnc_search_account_matchall_new (void) +{ + GNCSearchAccount *o = (GNCSearchAccount *)gtk_type_new(gnc_search_account_get_type ()); + o->priv->match_all = TRUE; + o->how = GUID_MATCH_ALL; + return o; +} + +static gboolean +validate (GNCSearchCoreType *fe) +{ + GNCSearchAccount *fi = (GNCSearchAccount *)fe; + gboolean valid = TRUE; + + g_return_val_if_fail (fi, FALSE); + g_return_val_if_fail (IS_GNCSEARCH_ACCOUNT (fi), FALSE); + + if (fi->priv->selected_accounts == NULL && fi->how ) { + valid = FALSE; + gnc_error_dialog (_("You have not selected any accounts")); + } + + /* XXX */ + + return valid; +} + +static void +option_changed (GtkWidget *widget, GNCSearchAccount *fe) +{ + fe->how = (query_compare_t) + gtk_object_get_data (GTK_OBJECT (widget), "option"); +} + +static GtkWidget * +add_menu_item (GtkWidget *menu, gpointer user_data, char *label, + query_compare_t option) +{ + GtkWidget *item = gtk_menu_item_new_with_label (label); + gtk_object_set_data (GTK_OBJECT (item), "option", (gpointer) option); + gtk_signal_connect (GTK_OBJECT (item), "activate", option_changed, user_data); + gtk_menu_append (GTK_MENU (menu), item); + gtk_widget_show (item); + return item; +} + +#define ADD_MENU_ITEM(str,op) { \ + item = add_menu_item (menu, fe, str, op); \ + if (fi->how == op) { current = index; first = item; } \ + index++; \ +} + +static GtkWidget * +make_menu (GNCSearchCoreType *fe) +{ + GNCSearchAccount *fi = (GNCSearchAccount *)fe; + GtkWidget *menu, *item, *first, *opmenu; + int current = 0, index = 0; + + menu = gtk_menu_new (); + + if (fi->priv->match_all) { + ADD_MENU_ITEM (_("matches all accounts"), GUID_MATCH_ALL); + first = item; + } else { + ADD_MENU_ITEM (_("matches any account"), GUID_MATCH_ANY); + first = item; /* Force one */ + ADD_MENU_ITEM (_("matches no accounts"), GUID_MATCH_NONE); + } + + opmenu = gtk_option_menu_new (); + gtk_option_menu_set_menu (GTK_OPTION_MENU (opmenu), menu); + + gtk_signal_emit_by_name (GTK_OBJECT (first), "activate", fe); + gtk_option_menu_set_history (GTK_OPTION_MENU (opmenu), current); + + return opmenu; +} + +static char * +describe_button (GNCSearchAccount *fi) +{ + if (fi->priv->selected_accounts) + return (_("Selected Accounts")); + return (_("Choose Accounts")); +} + +static void +button_clicked (GtkButton *button, GNCSearchAccount *fi) +{ + GnomeDialog *dialog; + GtkWidget *account_tree; + GtkWidget *accounts_scroller; + GtkWidget *label; + char *desc; + + /* Create the account tree */ + account_tree = gnc_account_tree_new (); + gtk_clist_column_titles_hide(GTK_CLIST(account_tree)); + gnc_account_tree_hide_all_but_name(GNC_ACCOUNT_TREE(account_tree)); + gnc_account_tree_refresh(GNC_ACCOUNT_TREE(account_tree)); + gtk_clist_set_selection_mode(GTK_CLIST(account_tree), + GTK_SELECTION_MULTIPLE); + + /* Select the currently-selected accounts */ + if (fi->priv->selected_accounts) + gnc_account_tree_select_accounts (GNC_ACCOUNT_TREE(account_tree), + fi->priv->selected_accounts, FALSE); + + /* Create the account scroller and put the tree in it */ + accounts_scroller = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add(GTK_CONTAINER(accounts_scroller), account_tree); + gtk_widget_set_usize(GTK_WIDGET(accounts_scroller), 300, 300); + + /* Create the label */ + label = gtk_label_new (_("Select Accounts to Match")); + + /* Create the dialog */ + dialog = + (GnomeDialog *) gnome_dialog_new (_("Select the Accounts to Compare"), + GNOME_STOCK_BUTTON_OK, + GNOME_STOCK_BUTTON_CANCEL, + NULL); + gnome_dialog_close_hides (dialog, TRUE); + + /* Put the dialog together */ + gtk_box_pack_start ((GtkBox *)dialog->vbox, label, + TRUE, TRUE, 3); + gtk_box_pack_start ((GtkBox *)dialog->vbox, accounts_scroller, + TRUE, TRUE, 3); + + gtk_widget_show_all (GTK_WIDGET (dialog)); + + /* Now run the dialog */ + switch (gnome_dialog_run (dialog)) { + case -1: /* wm close */ + case 0: /* ok */ + if (fi->priv->selected_accounts) + g_list_free (fi->priv->selected_accounts); + + fi->priv->selected_accounts = + gnc_account_tree_get_current_accounts (GNC_ACCOUNT_TREE (account_tree)); + + desc = describe_button (fi); + gtk_label_set_text (GTK_LABEL (GTK_BIN (button)->child), desc); + break; + + case 1: /* cancel */ + break; + } + + gtk_widget_destroy (dialog); +} + +static GtkWidget * +get_widget (GNCSearchCoreType *fe) +{ + GtkWidget *button, *label, *menu, *box; + GNCSearchAccount *fi = (GNCSearchAccount *)fe; + char *desc; + + g_return_val_if_fail (fi, NULL); + g_return_val_if_fail (IS_GNCSEARCH_ACCOUNT (fi), NULL); + + box = gtk_hbox_new (FALSE, 3); + + /* Build and connect the option menu */ + menu = make_menu (fe); + gtk_box_pack_start (GTK_BOX (box), menu, FALSE, FALSE, 3); + + /* Build and connect the account entry window */ + desc = describe_button (fi); + label = gtk_label_new (desc); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + + button = gtk_button_new (); + gtk_container_add (GTK_CONTAINER (button), label); + gtk_signal_connect (GTK_OBJECT (button), "clicked", button_clicked, fe); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3); + + /* And return the box */ + return box; +} + +static QueryPredData_t get_predicate (GNCSearchCoreType *fe) +{ + GNCSearchAccount *fi = (GNCSearchAccount *)fe; + GList *l = NULL, *node; + + g_return_val_if_fail (fi, NULL); + g_return_val_if_fail (IS_GNCSEARCH_ACCOUNT (fi), NULL); + + for (node = fi->priv->selected_accounts; node; node = node->next) { + Account *acc = node->data; + const GUID *guid = xaccAccountGetGUID (acc); + l = g_list_prepend (l, (gpointer)guid); + } + l = g_list_reverse (l); + + return gncQueryGUIDPredicate (fi->how, l); +} + +static GNCSearchCoreType *clone(GNCSearchCoreType *fe) +{ + GNCSearchAccount *se, *fse = (GNCSearchAccount *)fe; + + g_return_val_if_fail (fse, NULL); + g_return_val_if_fail (IS_GNCSEARCH_ACCOUNT (fse), NULL); + + se = gnc_search_account_new (); + se->how = fse->how; + se->priv->match_all = fse->priv->match_all; + se->priv->selected_accounts = g_list_copy (fse->priv->selected_accounts); + + return (GNCSearchCoreType *)se; +} diff --git a/src/gnome-search/search-account.h b/src/gnome-search/search-account.h new file mode 100644 index 0000000000..73ad5452cb --- /dev/null +++ b/src/gnome-search/search-account.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2002 Derek Atkins + * + * Authors: Derek Atkins + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GNCSEARCH_ACCOUNT_H +#define _GNCSEARCH_ACCOUNT_H + +#include "search-core-type.h" +#include "QueryNew.h" + +#define GNCSEARCH_ACCOUNT(obj) GTK_CHECK_CAST (obj, gnc_search_account_get_type (), GNCSearchAccount) +#define GNCSEARCH_ACCOUNT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gnc_search_account_get_type (), GNCSearchAccountClass) +#define IS_GNCSEARCH_ACCOUNT(obj) GTK_CHECK_TYPE (obj, gnc_search_account_get_type ()) + +typedef struct _GNCSearchAccount GNCSearchAccount; +typedef struct _GNCSearchAccountClass GNCSearchAccountClass; + +struct _GNCSearchAccount { + GNCSearchCoreType parent; + struct _GNCSearchAccountPrivate *priv; + + guid_match_t how; +}; + +struct _GNCSearchAccountClass { + GNCSearchCoreTypeClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint gnc_search_account_get_type (void); +GNCSearchAccount *gnc_search_account_new (void); +GNCSearchAccount *gnc_search_account_matchall_new (void); + +/* methods */ + +#endif /* ! _GNCSEARCH_ACCOUNT_H */ + diff --git a/src/gnome-search/search-core-type.c b/src/gnome-search/search-core-type.c index 63c20c8a02..50f11012cc 100644 --- a/src/gnome-search/search-core-type.c +++ b/src/gnome-search/search-core-type.c @@ -34,6 +34,7 @@ #include "search-int64.h" #include "search-numeric.h" #include "search-boolean.h" +#include "search-account.h" static gboolean validate (GNCSearchCoreType *fe); @@ -198,6 +199,10 @@ gnc_search_core_type_new_type_name (const char *type) return (GNCSearchCoreType *)gnc_search_numeric_debcred_new (); } else if (!strcmp (type, QUERYCORE_BOOLEAN)) { return (GNCSearchCoreType *)gnc_search_boolean_new (); + } else if (!strcmp (type, GNC_ID_ACCOUNT)) { + return (GNCSearchCoreType *)gnc_search_account_new (); + } else if (!strcmp (type, "account-match-all")) { + return (GNCSearchCoreType *)gnc_search_account_matchall_new (); } else { g_warning("Unknown search type '%s'", type); return 0;