GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dialog-tax-table.c
1 /*
2  * dialog-tax-table.c -- Dialog to create and edit tax-tables
3  * Copyright (C) 2002 Derek Atkins
4  * Author: Derek Atkins <[email protected]>
5  *
6  * Copyright (c) 2006 David Hampton <[email protected]>
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
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, contact:
20  *
21  * Free Software Foundation Voice: +1-617-542-5942
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
23  * Boston, MA 02110-1301, USA [email protected]
24  */
25 
26 #include "config.h"
27 
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 
31 #include "dialog-utils.h"
32 #include "gnc-component-manager.h"
33 #include "gnc-ui.h"
34 #include "gnc-gui-query.h"
35 #include "gnc-gtk-utils.h"
36 #include "gnc-ui-util.h"
37 #include "qof.h"
38 #include "gnc-amount-edit.h"
39 #include "gnc-tree-view-account.h"
40 
41 #include "gncTaxTable.h"
42 #include "dialog-tax-table.h"
43 
44 #define DIALOG_TAX_TABLE_CM_CLASS "tax-table-dialog"
45 #define GNC_PREFS_GROUP "dialogs.business.tax-tables"
46 
47 enum tax_table_cols
48 {
49  TAX_TABLE_COL_NAME = 0,
50  TAX_TABLE_COL_POINTER,
51  NUM_TAX_TABLE_COLS
52 };
53 
54 enum tax_entry_cols
55 {
56  TAX_ENTRY_COL_NAME = 0,
57  TAX_ENTRY_COL_POINTER,
58  TAX_ENTRY_COL_AMOUNT,
59  NUM_TAX_ENTRY_COLS
60 };
61 
62 void tax_table_new_table_cb (GtkButton *button, TaxTableWindow *ttw);
63 void tax_table_delete_table_cb (GtkButton *button, TaxTableWindow *ttw);
64 void tax_table_new_entry_cb (GtkButton *button, TaxTableWindow *ttw);
65 void tax_table_edit_entry_cb (GtkButton *button, TaxTableWindow *ttw);
66 void tax_table_delete_entry_cb (GtkButton *button, TaxTableWindow *ttw);
67 void tax_table_window_close (GtkWidget *widget, gpointer data);
68 void tax_table_window_destroy_cb (GtkWidget *widget, gpointer data);
69 
71 {
72  GtkWidget * dialog;
73  GtkWidget * names_view;
74  GtkWidget * entries_view;
75 
76  GncTaxTable * current_table;
77  GncTaxTableEntry * current_entry;
78  QofBook * book;
79  gint component_id;
80 };
81 
82 typedef struct _new_taxtable
83 {
84  GtkWidget * dialog;
85  GtkWidget * name_entry;
86  GtkWidget * amount_entry;
87  GtkWidget * acct_tree;
88 
89  GncTaxTable * created_table;
90  TaxTableWindow * ttw;
91  GncTaxTableEntry * entry;
92  gint type;
93  gboolean new_table;
94 } NewTaxTable;
95 
96 static gboolean
97 new_tax_table_ok_cb (NewTaxTable *ntt)
98 {
99  TaxTableWindow *ttw;
100  const char *name = NULL;
101  char *message;
102  Account *acc;
103  gnc_numeric amount;
104 
105  g_return_val_if_fail (ntt, FALSE);
106  ttw = ntt->ttw;
107 
108  /* Verify that we've got real, valid data */
109 
110  /* verify the name, maybe */
111  if (ntt->new_table)
112  {
113  name = gtk_entry_get_text (GTK_ENTRY (ntt->name_entry));
114  if (name == NULL || *name == '\0')
115  {
116  message = _("You must provide a name for this Tax Table.");
117  gnc_error_dialog (ntt->dialog, "%s", message);
118  return FALSE;
119  }
120  if (gncTaxTableLookupByName (ttw->book, name))
121  {
122  message = g_strdup_printf(_(
123  "You must provide a unique name for this Tax Table. "
124  "Your choice \"%s\" is already in use."), name);
125  gnc_error_dialog (ntt->dialog, "%s", message);
126  g_free (message);
127  return FALSE;
128  }
129  }
130 
131  /* verify the amount. Note that negative values are allowed (required for European tax rules) */
132  amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (ntt->amount_entry));
133  if (ntt->type == GNC_AMT_TYPE_PERCENT &&
135  gnc_numeric_create (100, 1)) > 0)
136  {
137  message = _("Percentage amount must be between -100 and 100.");
138  gnc_error_dialog (ntt->dialog, "%s", message);
139  return FALSE;
140  }
141 
142  /* verify the account */
143  acc = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(ntt->acct_tree));
144  if (acc == NULL)
145  {
146  message = _("You must choose a Tax Account.");
147  gnc_error_dialog (ntt->dialog, "%s", message);
148  return FALSE;
149  }
150 
151  gnc_suspend_gui_refresh ();
152 
153  /* Ok, it's all valid, now either change to add this thing */
154  if (ntt->new_table)
155  {
156  GncTaxTable *table = gncTaxTableCreate (ttw->book);
157  gncTaxTableBeginEdit (table);
158  gncTaxTableSetName (table, name);
159  /* Reset the current table */
160  ttw->current_table = table;
161  ntt->created_table = table;
162  }
163  else
164  gncTaxTableBeginEdit (ttw->current_table);
165 
166  /* Create/edit the entry */
167  {
168  GncTaxTableEntry *entry;
169 
170  if (ntt->entry)
171  {
172  entry = ntt->entry;
173  }
174  else
175  {
176  entry = gncTaxTableEntryCreate ();
177  gncTaxTableAddEntry (ttw->current_table, entry);
178  ttw->current_entry = entry;
179  }
180 
181  gncTaxTableEntrySetAccount (entry, acc);
182  gncTaxTableEntrySetType (entry, ntt->type);
183  gncTaxTableEntrySetAmount (entry, amount);
184  }
185 
186  /* Mark the table as changed and commit it */
187  gncTaxTableChanged (ttw->current_table);
188  gncTaxTableCommitEdit (ttw->current_table);
189 
190  gnc_resume_gui_refresh();
191  return TRUE;
192 }
193 
194 static void
195 combo_changed (GtkWidget *widget, NewTaxTable *ntt)
196 {
197  gint index;
198 
199  g_return_if_fail(GTK_IS_COMBO_BOX(widget));
200  g_return_if_fail(ntt);
201 
202  index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
203  ntt->type = index + 1;
204 }
205 
206 static GncTaxTable *
207 new_tax_table_dialog (TaxTableWindow *ttw, gboolean new_table,
208  GncTaxTableEntry *entry, const char *name)
209 {
210  GncTaxTable *created_table = NULL;
211  NewTaxTable *ntt;
212  GtkBuilder *builder;
213  GtkWidget *box, *widget, *combo;
214  gboolean done;
215  gint response, index;
216 
217  if (!ttw) return NULL;
218  if (new_table && entry) return NULL;
219 
220  ntt = g_new0 (NewTaxTable, 1);
221  ntt->ttw = ttw;
222  ntt->entry = entry;
223  ntt->new_table = new_table;
224 
225  if (entry)
226  ntt->type = gncTaxTableEntryGetType (entry);
227  else
228  ntt->type = GNC_AMT_TYPE_PERCENT;
229 
230  /* Open and read the Glade File */
231  builder = gtk_builder_new();
232  gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "type_liststore");
233  gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "New Tax Table Dialog");
234 
235  ntt->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "New Tax Table Dialog"));
236  ntt->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
237  if (name)
238  gtk_entry_set_text (GTK_ENTRY (ntt->name_entry), name);
239 
240  /* Create the menu */
241  combo = GTK_WIDGET(gtk_builder_get_object (builder, "type_combobox"));
242  index = ntt->type ? ntt->type : GNC_AMT_TYPE_VALUE;
243  gtk_combo_box_set_active(GTK_COMBO_BOX(combo), index - 1);
244  g_signal_connect (combo, "changed", G_CALLBACK (combo_changed), ntt);
245 
246  /* Attach our own widgets */
247  box = GTK_WIDGET(gtk_builder_get_object (builder, "amount_box"));
248  ntt->amount_entry = widget = gnc_amount_edit_new ();
249  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (widget), TRUE);
250  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (widget), 100000);
251  gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
252 
253  box = GTK_WIDGET(gtk_builder_get_object (builder, "acct_window"));
254  ntt->acct_tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
255  gtk_container_add (GTK_CONTAINER (box), ntt->acct_tree);
256  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(ntt->acct_tree), FALSE);
257 
258  /* Make 'enter' do the right thing */
259  gtk_entry_set_activates_default(GTK_ENTRY (gnc_amount_edit_gtk_entry
260  (GNC_AMOUNT_EDIT (ntt->amount_entry))),
261  TRUE);
262 
263  /* Fix mnemonics for generated target widgets */
264  widget = GTK_WIDGET(gtk_builder_get_object (builder, "value_label"));
265  gtk_label_set_mnemonic_widget (GTK_LABEL (widget), ntt->amount_entry);
266  widget = GTK_WIDGET(gtk_builder_get_object (builder, "account_label"));
267  gtk_label_set_mnemonic_widget (GTK_LABEL (widget), ntt->acct_tree);
268 
269  /* Fill in the widgets appropriately */
270  if (entry)
271  {
272  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (ntt->amount_entry),
273  gncTaxTableEntryGetAmount (entry));
274  gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT (ntt->acct_tree),
275  gncTaxTableEntryGetAccount (entry));
276  }
277 
278  /* Set our parent */
279  gtk_window_set_transient_for (GTK_WINDOW(ntt->dialog), GTK_WINDOW(ttw->dialog));
280 
281  /* Setup signals */
282  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ntt);
283 
284  /* Show what we should */
285  gtk_widget_show_all (ntt->dialog);
286  if (new_table == FALSE)
287  {
288  gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "table_title")));
289  gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "table_name")));
290  gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "spacer")));
291  gtk_widget_hide (ntt->name_entry);
292  /* Tables are great for layout, but a pain when you hide widgets */
293  widget = GTK_WIDGET(gtk_builder_get_object (builder, "ttd_table"));
294  gtk_table_set_row_spacing (GTK_TABLE(widget), 0, 0);
295  gtk_table_set_row_spacing (GTK_TABLE(widget), 1, 0);
296  gtk_table_set_row_spacing (GTK_TABLE(widget), 2, 0);
297  gtk_widget_grab_focus (gnc_amount_edit_gtk_entry
298  (GNC_AMOUNT_EDIT (ntt->amount_entry)));
299  }
300  else
301  gtk_widget_grab_focus (ntt->name_entry);
302 
303  /* Display the dialog now that we're done manipulating it */
304  gtk_widget_show (ntt->dialog);
305 
306  done = FALSE;
307  while (!done)
308  {
309  response = gtk_dialog_run (GTK_DIALOG (ntt->dialog));
310  switch (response)
311  {
312  case GTK_RESPONSE_OK:
313  if (new_tax_table_ok_cb (ntt))
314  {
315  created_table = ntt->created_table;
316  done = TRUE;
317  }
318  break;
319  default:
320  done = TRUE;
321  break;
322  }
323  }
324 
325  g_object_unref(G_OBJECT(builder));
326 
327  gtk_widget_destroy(ntt->dialog);
328  g_free(ntt);
329 
330  return created_table;
331 }
332 
333 /***********************************************************************/
334 
335 static void
336 tax_table_entries_refresh (TaxTableWindow *ttw)
337 {
338  GList *list, *node;
339  GtkTreeView *view;
340  GtkListStore *store;
341  GtkTreeIter iter;
342  GtkTreePath *path;
343  GtkTreeSelection *selection;
344  GtkTreeRowReference *reference = NULL;
345  GncTaxTableEntry *selected_entry;
346 
347  g_return_if_fail (ttw);
348 
349  view = GTK_TREE_VIEW (ttw->entries_view);
350  store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
351 
352  /* Clear the list */
353  selected_entry = ttw->current_entry;
354  gtk_list_store_clear (store);
355  if (ttw->current_table == NULL)
356  return;
357 
358  /* Add the items to the list */
359  list = gncTaxTableGetEntries (ttw->current_table);
360  if (list)
361  list = g_list_reverse (g_list_copy (list));
362 
363  for (node = list ; node; node = node->next)
364  {
365  char *row_text[3];
366  GncTaxTableEntry *entry = node->data;
367  Account *acc = gncTaxTableEntryGetAccount (entry);
368  gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
369 
370  row_text[0] = gnc_account_get_full_name (acc);
371  switch (gncTaxTableEntryGetType (entry))
372  {
374  row_text[1] =
375  g_strdup_printf ("%s%%",
376  xaccPrintAmount (amount,
377  gnc_default_print_info (FALSE)));
378  break;
379  default:
380  row_text[1] =
381  g_strdup_printf ("%s",
382  xaccPrintAmount (amount,
383  gnc_default_print_info (TRUE)));
384  break;
385  }
386 
387  gtk_list_store_prepend(store, &iter);
388  gtk_list_store_set(store, &iter,
389  TAX_ENTRY_COL_NAME, row_text[0],
390  TAX_ENTRY_COL_POINTER, entry,
391  TAX_ENTRY_COL_AMOUNT, row_text[1],
392  -1);
393  if (entry == selected_entry)
394  {
395  path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
396  reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path);
397  gtk_tree_path_free(path);
398  }
399 
400  g_free (row_text[0]);
401  g_free (row_text[1]);
402  }
403 
404  if (reference)
405  {
406  path = gtk_tree_row_reference_get_path(reference);
407  gtk_tree_row_reference_free(reference);
408  if (path)
409  {
410  selection = gtk_tree_view_get_selection(view);
411  gtk_tree_selection_select_path(selection, path);
412  gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.5, 0.0);
413  gtk_tree_path_free(path);
414  }
415  }
416 }
417 
418 static void
419 tax_table_window_refresh (TaxTableWindow *ttw)
420 {
421  GList *list, *node;
422  GtkTreeView *view;
423  GtkListStore *store;
424  GtkTreeIter iter;
425  GtkTreePath *path;
426  GtkTreeSelection *selection;
427  GtkTreeRowReference *reference = NULL;
428 
429  g_return_if_fail (ttw);
430  view = GTK_TREE_VIEW (ttw->names_view);
431  store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
432 
433  /* Clear the list */
434  gtk_list_store_clear(store);
435 
436  gnc_gui_component_clear_watches (ttw->component_id);
437 
438  /* Add the items to the list */
439  list = gncTaxTableGetTables (ttw->book);
440  if (list)
441  list = g_list_reverse (g_list_copy (list));
442 
443  for (node = list; node; node = node->next)
444  {
445  GncTaxTable *table = node->data;
446 
447  gnc_gui_component_watch_entity (ttw->component_id,
448  gncTaxTableGetGUID (table),
449  QOF_EVENT_MODIFY);
450 
451  gtk_list_store_prepend(store, &iter);
452  gtk_list_store_set(store, &iter,
453  TAX_TABLE_COL_NAME, gncTaxTableGetName (table),
454  TAX_TABLE_COL_POINTER, table,
455  -1);
456  if (table == ttw->current_table)
457  {
458  path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
459  reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path);
460  gtk_tree_path_free(path);
461  }
462  }
463 
464  if (list)
465  g_list_free (list);
466 
467  gnc_gui_component_watch_entity_type (ttw->component_id,
468  GNC_TAXTABLE_MODULE_NAME,
469  QOF_EVENT_CREATE | QOF_EVENT_DESTROY);
470 
471  if (reference)
472  {
473  path = gtk_tree_row_reference_get_path(reference);
474  gtk_tree_row_reference_free(reference);
475  if (path)
476  {
477  selection = gtk_tree_view_get_selection(view);
478  gtk_tree_selection_select_path(selection, path);
479  gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.5, 0.0);
480  gtk_tree_path_free(path);
481  }
482  }
483  ;;
484  tax_table_entries_refresh (ttw);
485  /* select_row() above will refresh the entries window */
486 }
487 
488 static void
489 tax_table_selection_changed (GtkTreeSelection *selection,
490  gpointer user_data)
491 {
492  TaxTableWindow *ttw = user_data;
493  GncTaxTable *table;
494  GtkTreeModel *model;
495  GtkTreeIter iter;
496 
497  g_return_if_fail (ttw);
498 
499  if (!gtk_tree_selection_get_selected(selection, &model, &iter))
500  return;
501 
502  gtk_tree_model_get(model, &iter, TAX_TABLE_COL_POINTER, &table, -1);
503  g_return_if_fail (table);
504 
505  /* If we've changed, then reset the entry list */
506  if (table != ttw->current_table)
507  {
508  ttw->current_table = table;
509  ttw->current_entry = NULL;
510  }
511  /* And force a refresh of the entries */
512  tax_table_entries_refresh (ttw);
513 }
514 
515 static void
516 tax_table_entry_selection_changed (GtkTreeSelection *selection,
517  gpointer user_data)
518 {
519  TaxTableWindow *ttw = user_data;
520  GtkTreeModel *model;
521  GtkTreeIter iter;
522 
523  g_return_if_fail (ttw);
524 
525  if (!gtk_tree_selection_get_selected(selection, &model, &iter))
526  {
527  ttw->current_entry = NULL;
528  return;
529  }
530 
531  gtk_tree_model_get(model, &iter, TAX_ENTRY_COL_POINTER, &ttw->current_entry, -1);
532 }
533 
534 static void
535 tax_table_entry_row_activated (GtkTreeView *tree_view,
536  GtkTreePath *path,
537  GtkTreeViewColumn *column,
538  gpointer user_data)
539 {
540  TaxTableWindow *ttw = user_data;
541 
542  new_tax_table_dialog (ttw, FALSE, ttw->current_entry, NULL);
543 }
544 
545 void
546 tax_table_new_table_cb (GtkButton *button, TaxTableWindow *ttw)
547 {
548  g_return_if_fail (ttw);
549  new_tax_table_dialog (ttw, TRUE, NULL, NULL);
550 }
551 
552 void
553 tax_table_delete_table_cb (GtkButton *button, TaxTableWindow *ttw)
554 {
555  g_return_if_fail (ttw);
556 
557  if (!ttw->current_table)
558  return;
559 
560  if (gncTaxTableGetRefcount (ttw->current_table) > 0)
561  {
562  char *message =
563  g_strdup_printf (_("Tax table \"%s\" is in use. You cannot delete it."),
564  gncTaxTableGetName (ttw->current_table));
565  gnc_error_dialog (ttw->dialog, "%s", message);
566  g_free (message);
567  return;
568  }
569 
570  if (gnc_verify_dialog (ttw->dialog, FALSE,
571  _("Are you sure you want to delete \"%s\"?"),
572  gncTaxTableGetName (ttw->current_table)))
573  {
574  /* Ok, let's remove it */
575  gnc_suspend_gui_refresh ();
576  gncTaxTableBeginEdit (ttw->current_table);
577  gncTaxTableDestroy (ttw->current_table);
578  ttw->current_table = NULL;
579  ttw->current_entry = NULL;
580  gnc_resume_gui_refresh ();
581  }
582 }
583 
584 void
585 tax_table_new_entry_cb (GtkButton *button, TaxTableWindow *ttw)
586 {
587  g_return_if_fail (ttw);
588  if (!ttw->current_table)
589  return;
590  new_tax_table_dialog (ttw, FALSE, NULL, NULL);
591 }
592 
593 void
594 tax_table_edit_entry_cb (GtkButton *button, TaxTableWindow *ttw)
595 {
596  g_return_if_fail (ttw);
597  if (!ttw->current_entry)
598  return;
599  new_tax_table_dialog (ttw, FALSE, ttw->current_entry, NULL);
600 }
601 
602 void
603 tax_table_delete_entry_cb (GtkButton *button, TaxTableWindow *ttw)
604 {
605  g_return_if_fail (ttw);
606  if (!ttw->current_table || !ttw->current_entry)
607  return;
608 
609  if (g_list_length (gncTaxTableGetEntries (ttw->current_table)) <= 1)
610  {
611  char *message = _("You cannot remove the last entry from the tax table. "
612  "Try deleting the tax table if you want to do that.");
613  gnc_error_dialog (ttw->dialog, "%s", message);
614  return;
615  }
616 
617  if (gnc_verify_dialog (ttw->dialog, FALSE, "%s",
618  _("Are you sure you want to delete this entry?")))
619  {
620  /* Ok, let's remove it */
621  gnc_suspend_gui_refresh ();
622  gncTaxTableBeginEdit (ttw->current_table);
623  gncTaxTableRemoveEntry (ttw->current_table, ttw->current_entry);
624  gncTaxTableEntryDestroy (ttw->current_entry);
625  gncTaxTableChanged (ttw->current_table);
626  gncTaxTableCommitEdit (ttw->current_table);
627  ttw->current_entry = NULL;
628  gnc_resume_gui_refresh ();
629  }
630 }
631 
632 static void
633 tax_table_window_refresh_handler (GHashTable *changes, gpointer data)
634 {
635  TaxTableWindow *ttw = data;
636 
637  g_return_if_fail (data);
638  tax_table_window_refresh (ttw);
639 }
640 
641 static void
642 tax_table_window_close_handler (gpointer data)
643 {
644  TaxTableWindow *ttw = data;
645  g_return_if_fail (ttw);
646 
647  gtk_widget_destroy (ttw->dialog);
648 }
649 
650 void
651 tax_table_window_close (GtkWidget *widget, gpointer data)
652 {
653  TaxTableWindow *ttw = data;
654 
655  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW (ttw->dialog));
656  gnc_ui_tax_table_window_destroy (ttw);
657 }
658 
659 void
660 tax_table_window_destroy_cb (GtkWidget *widget, gpointer data)
661 {
662  TaxTableWindow *ttw = data;
663 
664  if (!ttw) return;
665 
666  gnc_unregister_gui_component (ttw->component_id);
667 
668  g_free (ttw);
669 }
670 
671 static gboolean
672 find_handler (gpointer find_data, gpointer user_data)
673 {
674  TaxTableWindow *ttw = user_data;
675  QofBook *book = find_data;
676 
677  return (ttw != NULL && ttw->book == book);
678 }
679 
680 /* Create a tax-table window */
682 gnc_ui_tax_table_window_new (QofBook *book)
683 {
684  TaxTableWindow *ttw;
685  GtkBuilder *builder;
686  GtkTreeView *view;
687  GtkTreeViewColumn *column;
688  GtkCellRenderer *renderer;
689  GtkListStore *store;
690  GtkTreeSelection *selection;
691 
692  if (!book) return NULL;
693 
694  /*
695  * Find an existing tax-table window. If found, bring it to
696  * the front. If we have an actual owner, then set it in
697  * the window.
698  */
699  ttw = gnc_find_first_gui_component (DIALOG_TAX_TABLE_CM_CLASS, find_handler,
700  book);
701  if (ttw)
702  {
703  gtk_window_present (GTK_WINDOW(ttw->dialog));
704  return ttw;
705  }
706 
707  /* Didn't find one -- create a new window */
708  ttw = g_new0 (TaxTableWindow, 1);
709  ttw->book = book;
710 
711  /* Open and read the Glade File */
712  builder = gtk_builder_new();
713  gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "Tax Table Window");
714  ttw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Tax Table Window"));
715  ttw->names_view = GTK_WIDGET(gtk_builder_get_object (builder, "tax_tables_view"));
716  ttw->entries_view = GTK_WIDGET(gtk_builder_get_object (builder, "tax_table_entries"));
717 
718  /* Create the tax tables view */
719  view = GTK_TREE_VIEW(ttw->names_view);
720  store = gtk_list_store_new (NUM_TAX_TABLE_COLS, G_TYPE_STRING,
721  G_TYPE_POINTER);
722  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
723  g_object_unref(store);
724 
725  renderer = gtk_cell_renderer_text_new();
726  column = gtk_tree_view_column_new_with_attributes("", renderer,
727  "text", TAX_TABLE_COL_NAME,
728  NULL);
729  gtk_tree_view_append_column(view, column);
730 
731  selection = gtk_tree_view_get_selection(view);
732  g_signal_connect(selection, "changed",
733  G_CALLBACK(tax_table_selection_changed), ttw);
734 
735  /* Create the tax table entries view */
736  view = GTK_TREE_VIEW(ttw->entries_view);
737  store = gtk_list_store_new (NUM_TAX_ENTRY_COLS, G_TYPE_STRING,
738  G_TYPE_POINTER, G_TYPE_STRING);
739  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
740  g_object_unref(store);
741 
742  renderer = gtk_cell_renderer_text_new();
743  column = gtk_tree_view_column_new_with_attributes("", renderer,
744  "text", TAX_ENTRY_COL_NAME,
745  NULL);
746  gtk_tree_view_append_column(view, column);
747 
748  selection = gtk_tree_view_get_selection(view);
749  g_signal_connect(selection, "changed",
750  G_CALLBACK(tax_table_entry_selection_changed), ttw);
751  g_signal_connect(view, "row-activated",
752  G_CALLBACK(tax_table_entry_row_activated), ttw);
753 
754  /* Setup signals */
755  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ttw);
756 
757  /* register with component manager */
758  ttw->component_id =
759  gnc_register_gui_component (DIALOG_TAX_TABLE_CM_CLASS,
760  tax_table_window_refresh_handler,
761  tax_table_window_close_handler,
762  ttw);
763 
764  tax_table_window_refresh (ttw);
765  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW (ttw->dialog));
766  gtk_widget_show_all (ttw->dialog);
767 
768  g_object_unref(G_OBJECT(builder));
769 
770  return ttw;
771 }
772 
773 /* Destroy a tax-table window */
774 void
775 gnc_ui_tax_table_window_destroy (TaxTableWindow *ttw)
776 {
777  if (!ttw)
778  return;
779 
780  gnc_close_gui_component (ttw->component_id);
781 }
782 
783 /* Create a new tax-table by name */
784 GncTaxTable *
785 gnc_ui_tax_table_new_from_name (QofBook *book, const char *name)
786 {
787  TaxTableWindow *ttw;
788 
789  if (!book) return NULL;
790 
791  ttw = gnc_ui_tax_table_window_new (book);
792  if (!ttw) return NULL;
793 
794  return new_tax_table_dialog (ttw, TRUE, NULL, name);
795 }
utility functions for the GnuCash UI
gtk helper routines.
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:3038
#define gncTaxTableGetGUID(x)
Definition: gncTaxTable.h:203
GtkTreeView implementation for gnucash account tree.
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Tax Table programming interface.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)