GnuCash  5.6-150-g038405b370+
search-account.c
1 /*
2  * Copyright (C) 2002 Derek Atkins
3  *
4  * Authors: Derek Atkins <warlord@MIT.EDU>
5  *
6  * Copyright (c) 2006 David Hampton <hampton@employees.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 
31 #include "Account.h"
32 #include "qof.h"
33 #include "gnc-tree-view-account.h"
34 #include "gnc-gui-query.h"
35 #include "dialog-utils.h"
36 
37 #include "search-account.h"
38 #include "search-core-utils.h"
39 
40 #define d(x)
41 
42 static void pass_parent (GNCSearchCoreType *fe, gpointer parent);
43 static GNCSearchCoreType *gncs_clone(GNCSearchCoreType *fe);
44 static gboolean gncs_validate (GNCSearchCoreType *fe);
45 static GtkWidget *gncs_get_widget(GNCSearchCoreType *fe);
46 static QofQueryPredData* gncs_get_predicate (GNCSearchCoreType *fe);
47 
48 static void gnc_search_account_finalize (GObject *obj);
49 
51 {
52  GNCSearchCoreType parent;
53 
54  QofGuidMatch how;
55 };
56 
57 typedef struct _GNCSearchAccountPrivate GNCSearchAccountPrivate;
58 
60 {
61  gboolean match_all;
62  GList * selected_accounts;
63  GtkWindow *parent;
64 };
65 
66 G_DEFINE_TYPE_WITH_PRIVATE(GNCSearchAccount, gnc_search_account, GNC_TYPE_SEARCH_CORE_TYPE)
67 
68 #define _PRIVATE(o) \
69  ((GNCSearchAccountPrivate*)gnc_search_account_get_instance_private((GNCSearchAccount*)o))
70 
71 static void
72 gnc_search_account_class_init (GNCSearchAccountClass *klass)
73 {
74  GObjectClass *object_class;
75  GNCSearchCoreTypeClass *gnc_search_core_type = (GNCSearchCoreTypeClass *)klass;
76 
77  object_class = G_OBJECT_CLASS (klass);
78 
79  object_class->finalize = gnc_search_account_finalize;
80 
81  /* override methods */
82  gnc_search_core_type->pass_parent = pass_parent;
83  gnc_search_core_type->validate = gncs_validate;
84  gnc_search_core_type->get_widget = gncs_get_widget;
85  gnc_search_core_type->get_predicate = gncs_get_predicate;
86  gnc_search_core_type->clone = gncs_clone;
87 }
88 
89 static void
90 gnc_search_account_init (GNCSearchAccount *o)
91 {
92  o->how = QOF_GUID_MATCH_ANY;
93 }
94 
95 static void
96 gnc_search_account_finalize (GObject *obj)
97 {
98  GNCSearchAccount *o = (GNCSearchAccount *)obj;
99  g_assert (GNC_IS_SEARCH_ACCOUNT (o));
100 
101  G_OBJECT_CLASS (gnc_search_account_parent_class)->finalize(obj);
102 }
103 
111 GNCSearchAccount *
112 gnc_search_account_new (void)
113 {
114  GNCSearchAccount *o = g_object_new(GNC_TYPE_SEARCH_ACCOUNT, NULL);
115  return o;
116 }
117 
125 GNCSearchAccount *
126 gnc_search_account_matchall_new (void)
127 {
128  GNCSearchAccount *o;
129  GNCSearchAccountPrivate *priv;
130 
131  o = g_object_new(GNC_TYPE_SEARCH_ACCOUNT, NULL);
132  priv = _PRIVATE(o);
133  priv->match_all = TRUE;
134  o->how = QOF_GUID_MATCH_ALL;
135  return o;
136 }
137 
138 static gboolean
139 gncs_validate (GNCSearchCoreType *fe)
140 {
141  GNCSearchAccount *fi = (GNCSearchAccount *)fe;
142  GNCSearchAccountPrivate *priv;
143  gboolean valid = TRUE;
144 
145  g_return_val_if_fail (fi, FALSE);
146  g_return_val_if_fail (GNC_IS_SEARCH_ACCOUNT (fi), FALSE);
147 
148  priv = _PRIVATE(fi);
149 
150  if (priv->selected_accounts == NULL && fi->how )
151  {
152  valid = FALSE;
153  gnc_error_dialog (GTK_WINDOW(priv->parent), "%s", _("You have not selected any accounts"));
154  }
155 
156  /* XXX */
157 
158  return valid;
159 }
160 
161 static GtkWidget *
162 make_menu (GNCSearchCoreType *fe)
163 {
164  GNCSearchAccount *fi = (GNCSearchAccount *)fe;
165  GNCSearchAccountPrivate *priv;
166  GtkComboBox *combo;
167  int initial = 0;
168 
169  combo = GTK_COMBO_BOX(gnc_combo_box_new_search());
170 
171  priv = _PRIVATE(fi);
172  if (priv->match_all)
173  {
174  gnc_combo_box_search_add(combo, _("matches all accounts"), QOF_GUID_MATCH_ALL);
175  initial = QOF_GUID_MATCH_ALL;
176  }
177  else
178  {
179  gnc_combo_box_search_add(combo, _("matches any account"), QOF_GUID_MATCH_ANY);
180  gnc_combo_box_search_add(combo, _("matches no accounts"), QOF_GUID_MATCH_NONE);
181  initial = QOF_GUID_MATCH_ANY;
182  }
183 
184  gnc_combo_box_search_changed(combo, &fi->how);
185  gnc_combo_box_search_set_active(combo, fi->how ? fi->how : initial);
186 
187  return GTK_WIDGET(combo);
188 }
189 
190 static char *
191 describe_button (GNCSearchAccount *fi)
192 {
193  GNCSearchAccountPrivate *priv;
194 
195  priv = _PRIVATE(fi);
196  if (priv->selected_accounts)
197  return (_("Selected Accounts"));
198  return (_("Choose Accounts"));
199 }
200 
201 static void
202 button_clicked (GtkButton *button, GNCSearchAccount *fi)
203 {
204  GNCSearchAccountPrivate *priv;
205  GtkDialog *dialog;
206  GtkWidget *account_tree;
207  GtkWidget *accounts_scroller;
208  GtkWidget *label;
209  char *desc;
210  GtkTreeSelection *selection;
211 
212  /* Create the account tree */
213  account_tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
214  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(account_tree), FALSE);
215  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(account_tree));
216  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
217 
218  /* Select the currently-selected accounts */
219  priv = _PRIVATE(fi);
220  if (priv->selected_accounts)
221  gnc_tree_view_account_set_selected_accounts (GNC_TREE_VIEW_ACCOUNT(account_tree),
222  priv->selected_accounts, FALSE);
223 
224  /* Create the account scroller and put the tree in it */
225  accounts_scroller = gtk_scrolled_window_new (NULL, NULL);
226  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(accounts_scroller),
227  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
228  gtk_container_add(GTK_CONTAINER(accounts_scroller), account_tree);
229  gtk_widget_set_size_request(GTK_WIDGET(accounts_scroller), 300, 300);
230 
231  /* Create the label */
232  label = gtk_label_new (_("Select Accounts to Match"));
233 
234  /* Create the dialog */
235  dialog =
236  GTK_DIALOG(gtk_dialog_new_with_buttons(_("Select the Accounts to Compare"),
237  GTK_WINDOW(priv->parent),
238  0,
239  _("_Cancel"), GTK_RESPONSE_CANCEL,
240  _("_OK"), GTK_RESPONSE_OK,
241  NULL));
242 
243  /* Put the dialog together */
244  gtk_box_pack_start ((GtkBox *) gtk_dialog_get_content_area (dialog), label,
245  FALSE, FALSE, 3);
246  gtk_box_pack_start ((GtkBox *) gtk_dialog_get_content_area (dialog), accounts_scroller,
247  TRUE, TRUE, 3);
248 
249  gtk_widget_show_all (GTK_WIDGET (dialog));
250 
251  /* Now run the dialog */
252  if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
253  {
254  if (priv->selected_accounts)
255  g_list_free (priv->selected_accounts);
256 
257  priv->selected_accounts =
258  gnc_tree_view_account_get_selected_accounts (GNC_TREE_VIEW_ACCOUNT (account_tree));
259 
260  desc = describe_button (fi);
261  gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (button))), desc);
262  }
263 
264  gtk_widget_destroy (GTK_WIDGET (dialog));
265 }
266 
267 static GtkWidget *
268 gncs_get_widget (GNCSearchCoreType *fe)
269 {
270  GtkWidget *button, *label, *menu, *box;
271  GNCSearchAccount *fi = (GNCSearchAccount *)fe;
272  char *desc;
273 
274  g_return_val_if_fail (fi, NULL);
275  g_return_val_if_fail (GNC_IS_SEARCH_ACCOUNT (fi), NULL);
276 
277  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
278  gtk_box_set_homogeneous (GTK_BOX (box), FALSE);
279 
280  /* Build and connect the option menu */
281  menu = make_menu (fe);
282  gtk_box_pack_start (GTK_BOX (box), menu, FALSE, FALSE, 3);
283 
284  /* Build and connect the account entry window */
285  desc = describe_button (fi);
286  label = gtk_label_new (desc);
287  gnc_label_set_alignment (label, 0.5, 0.5);
288 
289  button = gtk_button_new ();
290  gtk_container_add (GTK_CONTAINER (button), label);
291  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (button_clicked), fe);
292  gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
293 
294  /* And return the box */
295  return box;
296 }
297 
298 static QofQueryPredData* gncs_get_predicate (GNCSearchCoreType *fe)
299 {
300  GNCSearchAccountPrivate *priv;
301  GNCSearchAccount *fi = (GNCSearchAccount *)fe;
302  GList *l = NULL, *node;
303 
304  g_return_val_if_fail (fi, NULL);
305  g_return_val_if_fail (GNC_IS_SEARCH_ACCOUNT (fi), NULL);
306 
307  priv = _PRIVATE(fi);
308  for (node = priv->selected_accounts; node; node = node->next)
309  {
310  Account *acc = node->data;
311  const GncGUID *guid = xaccAccountGetGUID (acc);
312  l = g_list_prepend (l, (gpointer)guid);
313  }
314  l = g_list_reverse (l);
315 
316  return qof_query_guid_predicate (fi->how, l);
317 }
318 
319 static GNCSearchCoreType *gncs_clone(GNCSearchCoreType *fe)
320 {
321  GNCSearchAccount *se, *fse = (GNCSearchAccount *)fe;
322  GNCSearchAccountPrivate *se_priv, *fse_priv;
323 
324  g_return_val_if_fail (fse, NULL);
325  g_return_val_if_fail (GNC_IS_SEARCH_ACCOUNT (fse), NULL);
326  fse_priv = _PRIVATE(fse);
327 
328  se = gnc_search_account_new ();
329  se_priv = _PRIVATE(se);
330  se->how = fse->how;
331  se_priv->match_all = fse_priv->match_all;
332  se_priv->selected_accounts = g_list_copy (fse_priv->selected_accounts);
333 
334  return (GNCSearchCoreType *)se;
335 }
336 
337 static void
338 pass_parent (GNCSearchCoreType *fe, gpointer parent)
339 {
340  GNCSearchAccount *fi = (GNCSearchAccount *)fe;
341  GNCSearchAccountPrivate *priv;
342 
343  g_return_if_fail (fi);
344  g_return_if_fail (GNC_IS_SEARCH_ACCOUNT (fi));
345 
346  priv = _PRIVATE(fi);
347  priv->parent = GTK_WINDOW(parent);
348 }
GList * gnc_tree_view_account_get_selected_accounts(GncTreeViewAccount *view)
This function returns a list of the accounts associated with the selected items in the account tree v...
STRUCTS.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
Definition: qofquerycore.h:113
void gnc_tree_view_account_set_selected_accounts(GncTreeViewAccount *view, GList *account_list, gboolean show_last)
This function selects a set of accounts in the account tree view.
#define xaccAccountGetGUID(X)
Definition: Account.h:248
Account handling public routines.
QofGuidMatch
Definition: qofquerycore.h:109
GtkTreeView implementation for gnucash account tree.
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
These expect a GList* of objects and calls the QofAccessFunc routine on each item in the list to obta...
Definition: qofquerycore.h:118
The type used to store guids in C.
Definition: guid.h:75