GnuCash c935c2f+
Loading...
Searching...
No Matches
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 <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
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 gnu@gnu.org
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-session.h"
34#include "gnc-ui.h"
35#include "gnc-gui-query.h"
36#include "gnc-gtk-utils.h"
37#include "gnc-ui-util.h"
38#include "qof.h"
39#include "gnc-amount-edit.h"
41
42#include "gncTaxTable.h"
43#include "dialog-tax-table.h"
44
45#define DIALOG_TAX_TABLE_CM_CLASS "tax-table-dialog"
46#define GNC_PREFS_GROUP "dialogs.business.tax-tables"
47
48enum tax_table_cols
49{
50 TAX_TABLE_COL_NAME = 0,
51 TAX_TABLE_COL_POINTER,
52 NUM_TAX_TABLE_COLS
53};
54
55enum tax_entry_cols
56{
57 TAX_ENTRY_COL_NAME = 0,
58 TAX_ENTRY_COL_POINTER,
59 TAX_ENTRY_COL_AMOUNT,
60 NUM_TAX_ENTRY_COLS
61};
62
63void tax_table_new_table_cb (GtkButton *button, TaxTableWindow *ttw);
64void tax_table_rename_table_cb (GtkButton *button, TaxTableWindow *ttw);
65void tax_table_delete_table_cb (GtkButton *button, TaxTableWindow *ttw);
66void tax_table_new_entry_cb (GtkButton *button, TaxTableWindow *ttw);
67void tax_table_edit_entry_cb (GtkButton *button, TaxTableWindow *ttw);
68void tax_table_delete_entry_cb (GtkButton *button, TaxTableWindow *ttw);
69void tax_table_window_close (GtkWidget *widget, gpointer data);
70void tax_table_window_destroy_cb (GtkWidget *widget, gpointer data);
71
73{
74 GtkWidget *dialog;
75 GtkWidget *names_view;
76 GtkWidget *entries_view;
77
78 GncTaxTable *current_table;
79 GncTaxTableEntry *current_entry;
80 QofBook *book;
81 gint component_id;
82 QofSession *session;
83};
84
85typedef struct _new_taxtable
86{
87 GtkWidget *dialog;
88 GtkWidget *name_entry;
89 GtkWidget *amount_entry;
90 GtkWidget *acct_tree;
91
92 GncTaxTable *created_table;
93 TaxTableWindow *ttw;
94 GncTaxTableEntry *entry;
95 gint type;
96 gboolean new_table;
98
99static gboolean
100new_tax_table_check_entry (NewTaxTable *ntt, GError **error)
101{
102 GNCPrintAmountInfo print_info;
103 gnc_numeric value;
104 gint result;
105 GError *tmp_error = NULL;
106
107 if (ntt->type == GNC_AMT_TYPE_VALUE)
108 {
109 Account *acc = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(ntt->acct_tree));
110 gnc_commodity *currency = xaccAccountGetCommodity (acc);
111 print_info = gnc_commodity_print_info (currency, FALSE);
112 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT(ntt->amount_entry),
113 gnc_commodity_get_fraction (currency));
114 }
115 else
116 {
117 print_info = gnc_integral_print_info ();
118 print_info.max_decimal_places = 5;
119 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (ntt->amount_entry), 100000);
120 }
121
122 gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT(ntt->amount_entry), print_info);
123
124 result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(ntt->amount_entry),
125 &value, TRUE, &tmp_error);
126
127 if (result == 1)
128 {
129 if (error)
130 g_propagate_error (error, tmp_error);
131 else
132 g_error_free (tmp_error);
133 return FALSE;
134 }
135 return TRUE;
136}
137
138static gboolean
139new_tax_table_ok_cb (NewTaxTable *ntt)
140{
141 TaxTableWindow *ttw;
142 const char *name = NULL;
143 char *message;
144 Account *acc;
145 gnc_numeric amount;
146 GError *error = NULL;
147
148 g_return_val_if_fail (ntt, FALSE);
149 ttw = ntt->ttw;
150
151 /* Verify that we've got real, valid data */
152
153 /* verify the name, maybe */
154 if (ntt->new_table)
155 {
156 name = gtk_entry_get_text (GTK_ENTRY(ntt->name_entry));
157 if (name == NULL || *name == '\0')
158 {
159 message = _("You must provide a name for this Tax Table.");
160 gnc_error_dialog (GTK_WINDOW(ntt->dialog), "%s", message);
161 return FALSE;
162 }
163 if (gncTaxTableLookupByName (ttw->book, name))
164 {
165 message = g_strdup_printf (_(
166 "You must provide a unique name for this Tax Table. "
167 "Your choice \"%s\" is already in use."), name);
168 gnc_error_dialog (GTK_WINDOW(ntt->dialog), "%s", message);
169 g_free (message);
170 return FALSE;
171 }
172 }
173
174 /* test for valid value */
175 if (!new_tax_table_check_entry (ntt, &error))
176 {
177 message = g_strdup (error->message);
178 gnc_error_dialog (GTK_WINDOW(ntt->dialog), "%s", message);
179 g_free (message);
180 g_error_free (error);
181 return FALSE;
182 }
183
184 /* verify the amount. Note that negative values are allowed (required for European tax rules) */
185 amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT(ntt->amount_entry));
186 if (ntt->type == GNC_AMT_TYPE_PERCENT &&
188 gnc_numeric_create (100, 1)) > 0)
189 {
190 message = _("Percentage amount must be between -100 and 100.");
191 gnc_error_dialog (GTK_WINDOW(ntt->dialog), "%s", message);
192 return FALSE;
193 }
194
195 /* verify the account */
196 acc = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(ntt->acct_tree));
197 if (acc == NULL)
198 {
199 message = _("You must choose a Tax Account.");
200 gnc_error_dialog (GTK_WINDOW(ntt->dialog), "%s", message);
201 return FALSE;
202 }
203
204 gnc_suspend_gui_refresh ();
205
206 /* Ok, it's all valid, now either change to add this thing */
207 if (ntt->new_table)
208 {
209 GncTaxTable *table = gncTaxTableCreate (ttw->book);
210 gncTaxTableBeginEdit (table);
211 gncTaxTableSetName (table, name);
212 /* Reset the current table */
213 ttw->current_table = table;
214 ntt->created_table = table;
215 }
216 else
217 gncTaxTableBeginEdit (ttw->current_table);
218
219 /* Create/edit the entry */
220 {
221 GncTaxTableEntry *entry;
222
223 if (ntt->entry)
224 {
225 entry = ntt->entry;
226 }
227 else
228 {
229 entry = gncTaxTableEntryCreate ();
230 gncTaxTableAddEntry (ttw->current_table, entry);
231 ttw->current_entry = entry;
232 }
233
234 gncTaxTableEntrySetAccount (entry, acc);
235 gncTaxTableEntrySetType (entry, ntt->type);
236 gncTaxTableEntrySetAmount (entry, amount);
237 }
238
239 /* Mark the table as changed and commit it */
240 gncTaxTableChanged (ttw->current_table);
241 gncTaxTableCommitEdit (ttw->current_table);
242
243 gnc_resume_gui_refresh ();
244 return TRUE;
245}
246
247static void
248combo_changed (GtkWidget *widget, NewTaxTable *ntt)
249{
250 gint index;
251
252 g_return_if_fail (GTK_IS_COMBO_BOX(widget));
253 g_return_if_fail (ntt);
254
255 index = gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
256 ntt->type = index + 1;
257
258 new_tax_table_check_entry (ntt, NULL);
259}
260
261static void
262tax_table_account_selection_changed_cb (GtkTreeSelection *treeselection,
263 NewTaxTable *ntt)
264{
265 new_tax_table_check_entry (ntt, NULL);
266}
267
268static GncTaxTable *
269new_tax_table_dialog (TaxTableWindow *ttw, gboolean new_table,
270 GncTaxTableEntry *entry, const char *name)
271{
272 GncTaxTable *created_table = NULL;
273 NewTaxTable *ntt;
274 GtkBuilder *builder;
275 GtkWidget *box, *widget, *combo;
276 gboolean done;
277 gint response, index;
278 GtkTreeSelection *selection;
279
280 if (!ttw) return NULL;
281 if (new_table && entry) return NULL;
282
283 ntt = g_new0 (NewTaxTable, 1);
284 ntt->ttw = ttw;
285 ntt->entry = entry;
286 ntt->new_table = new_table;
287
288 if (entry)
289 ntt->type = gncTaxTableEntryGetType (entry);
290 else
291 ntt->type = GNC_AMT_TYPE_PERCENT;
292
293 /* Open and read the Glade File */
294 builder = gtk_builder_new ();
295 gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "type_liststore");
296 gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "new_tax_table_dialog");
297
298 ntt->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "new_tax_table_dialog"));
299
300 // Set the name for this dialog so it can be easily manipulated with css
301 gtk_widget_set_name (GTK_WIDGET(ntt->dialog), "gnc-id-tax-table");
302 gnc_widget_style_context_add_class (GTK_WIDGET(ntt->dialog), "gnc-class-taxes");
303
304 ntt->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
305 if (name)
306 gtk_entry_set_text (GTK_ENTRY(ntt->name_entry), name);
307
308 /* Create the menu */
309 combo = GTK_WIDGET(gtk_builder_get_object (builder, "type_combobox"));
310 index = ntt->type ? ntt->type : GNC_AMT_TYPE_VALUE;
311 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), index - 1);
312 g_signal_connect (combo, "changed", G_CALLBACK(combo_changed), ntt);
313
314 /* Attach our own widgets */
315 box = GTK_WIDGET(gtk_builder_get_object (builder, "amount_box"));
316 ntt->amount_entry = widget = gnc_amount_edit_new ();
317 gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT(widget), TRUE);
318 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT(widget), 100000);
319 gtk_box_pack_start (GTK_BOX(box), widget, TRUE, TRUE, 0);
320
321 box = GTK_WIDGET(gtk_builder_get_object (builder, "acct_window"));
322 ntt->acct_tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
323 gtk_container_add (GTK_CONTAINER(box), ntt->acct_tree);
324 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(ntt->acct_tree), FALSE);
325
326 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(ntt->acct_tree));
327 g_signal_connect (G_OBJECT(selection), "changed",
328 G_CALLBACK(tax_table_account_selection_changed_cb), ntt);
329
330 /* Make 'enter' do the right thing */
331 gtk_entry_set_activates_default (GTK_ENTRY(gnc_amount_edit_gtk_entry
332 (GNC_AMOUNT_EDIT(ntt->amount_entry))),
333 TRUE);
334
335 /* Fix mnemonics for generated target widgets */
336 widget = GTK_WIDGET(gtk_builder_get_object (builder, "value_label"));
337 gnc_amount_edit_make_mnemonic_target (GNC_AMOUNT_EDIT(ntt->amount_entry), widget);
338 widget = GTK_WIDGET(gtk_builder_get_object (builder, "account_label"));
339 gtk_label_set_mnemonic_widget (GTK_LABEL(widget), ntt->acct_tree);
340
341 /* Fill in the widgets appropriately */
342 if (entry)
343 {
344 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(ntt->amount_entry),
345 gncTaxTableEntryGetAmount (entry));
346 gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(ntt->acct_tree),
347 gncTaxTableEntryGetAccount (entry));
348 }
349
350 /* Set our parent */
351 gtk_window_set_transient_for (GTK_WINDOW(ntt->dialog), GTK_WINDOW(ttw->dialog));
352
353 /* Setup signals */
354 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ntt);
355
356 /* Show what we should */
357 gtk_widget_show_all (ntt->dialog);
358 if (new_table == FALSE)
359 {
360 gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "table_title")));
361 gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "table_name")));
362 gtk_widget_hide (GTK_WIDGET(gtk_builder_get_object (builder, "spacer")));
363 gtk_widget_hide (ntt->name_entry);
364 /* Tables are great for layout, but a pain when you hide widgets */
365 GTK_WIDGET(gtk_builder_get_object (builder, "ttd_table"));
366 gtk_widget_grab_focus (gnc_amount_edit_gtk_entry
367 (GNC_AMOUNT_EDIT(ntt->amount_entry)));
368 }
369 else
370 gtk_widget_grab_focus (ntt->name_entry);
371
372 /* Display the dialog now that we're done manipulating it */
373 gtk_widget_show (ntt->dialog);
374
375 done = FALSE;
376 while (!done)
377 {
378 response = gtk_dialog_run (GTK_DIALOG(ntt->dialog));
379 switch (response)
380 {
381 case GTK_RESPONSE_OK:
382 if (new_tax_table_ok_cb (ntt))
383 {
384 created_table = ntt->created_table;
385 done = TRUE;
386 }
387 break;
388 default:
389 done = TRUE;
390 break;
391 }
392 }
393
394 g_object_unref (G_OBJECT(builder));
395
396 gtk_widget_destroy (ntt->dialog);
397 g_free (ntt);
398
399 return created_table;
400}
401
402/***********************************************************************/
403
404static void
405tax_table_entries_refresh (TaxTableWindow *ttw)
406{
407 GList *list, *node;
408 GtkTreeView *view;
409 GtkListStore *store;
410 GtkTreeIter iter;
411 GtkTreePath *path;
412 GtkTreeSelection *selection;
413 GtkTreeRowReference *reference = NULL;
414 GncTaxTableEntry *selected_entry;
415
416 g_return_if_fail (ttw);
417
418 view = GTK_TREE_VIEW(ttw->entries_view);
419 store = GTK_LIST_STORE(gtk_tree_view_get_model (view));
420
421 /* Clear the list */
422 selected_entry = ttw->current_entry;
423 gtk_list_store_clear (store);
424 if (ttw->current_table == NULL)
425 return;
426
427 /* Add the items to the list */
428 list = gncTaxTableGetEntries (ttw->current_table);
429 if (list)
430 list = g_list_reverse (g_list_copy (list));
431
432 for (node = list ; node; node = node->next)
433 {
434 char *row_text[3];
435 GncTaxTableEntry *entry = node->data;
436 Account *acc = gncTaxTableEntryGetAccount (entry);
437 gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
438
439 row_text[0] = gnc_account_get_full_name (acc);
440 switch (gncTaxTableEntryGetType (entry))
441 {
443 row_text[1] =
444 g_strdup_printf ("%s%%",
445 xaccPrintAmount (amount,
446 gnc_default_print_info (FALSE)));
447 break;
449 row_text[1] =
450 g_strdup_printf ("%s",
451 xaccPrintAmount (amount,
452 gnc_default_print_info (TRUE)));
453 break;
454 default:
455 row_text[1] = NULL;
456 break;
457 }
458
459 gtk_list_store_prepend (store, &iter);
460 gtk_list_store_set (store, &iter,
461 TAX_ENTRY_COL_NAME, row_text[0],
462 TAX_ENTRY_COL_POINTER, entry,
463 TAX_ENTRY_COL_AMOUNT, row_text[1],
464 -1);
465 if (entry == selected_entry)
466 {
467 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store), &iter);
468 reference = gtk_tree_row_reference_new (GTK_TREE_MODEL(store), path);
469 gtk_tree_path_free (path);
470 }
471
472 g_free (row_text[0]);
473 g_free (row_text[1]);
474 }
475
476 if (list)
477 g_list_free (list);
478
479 if (reference)
480 {
481 path = gtk_tree_row_reference_get_path (reference);
482 gtk_tree_row_reference_free (reference);
483 if (path)
484 {
485 selection = gtk_tree_view_get_selection (view);
486 gtk_tree_selection_select_path (selection, path);
487 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
488 gtk_tree_path_free (path);
489 }
490 }
491}
492
493static void
494tax_table_window_refresh (TaxTableWindow *ttw)
495{
496 GList *list, *node;
497 GtkTreeView *view;
498 GtkListStore *store;
499 GtkTreeIter iter;
500 GtkTreePath *path;
501 GtkTreeSelection *selection;
502 GtkTreeRowReference *reference = NULL;
503 GncTaxTable *saved_current_table = ttw->current_table;
504
505 g_return_if_fail (ttw);
506 view = GTK_TREE_VIEW(ttw->names_view);
507 store = GTK_LIST_STORE(gtk_tree_view_get_model (view));
508
509 /* Clear the list */
510 gtk_list_store_clear(store);
511
512 gnc_gui_component_clear_watches (ttw->component_id);
513
514 /* Add the items to the list */
515 list = gncTaxTableGetTables (ttw->book);
516 if (list)
517 list = g_list_reverse (g_list_copy (list));
518
519 for (node = list; node; node = node->next)
520 {
521 GncTaxTable *table = node->data;
522
523 gnc_gui_component_watch_entity (ttw->component_id,
525 QOF_EVENT_MODIFY);
526
527 gtk_list_store_prepend (store, &iter);
528 gtk_list_store_set (store, &iter,
529 TAX_TABLE_COL_NAME, gncTaxTableGetName (table),
530 TAX_TABLE_COL_POINTER, table,
531 -1);
532
533 if (table == saved_current_table)
534 {
535 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store), &iter);
536 reference = gtk_tree_row_reference_new (GTK_TREE_MODEL(store), path);
537 gtk_tree_path_free (path);
538 }
539 }
540
541 if (list)
542 g_list_free (list);
543
544 gnc_gui_component_watch_entity_type (ttw->component_id,
545 GNC_TAXTABLE_MODULE_NAME,
546 QOF_EVENT_CREATE | QOF_EVENT_DESTROY);
547
548 if (reference)
549 {
550 path = gtk_tree_row_reference_get_path (reference);
551 gtk_tree_row_reference_free (reference);
552 if (path)
553 {
554 selection = gtk_tree_view_get_selection (view);
555 gtk_tree_selection_select_path (selection, path);
556 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
557 gtk_tree_path_free (path);
558 }
559 }
560
561 tax_table_entries_refresh (ttw);
562 /* select_row() above will refresh the entries window */
563}
564
565static void
566tax_table_selection_changed (GtkTreeSelection *selection,
567 gpointer user_data)
568{
569 TaxTableWindow *ttw = user_data;
571 GtkTreeModel *model;
572 GtkTreeIter iter;
573
574 g_return_if_fail (ttw);
575
576 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
577 return;
578
579 gtk_tree_model_get (model, &iter, TAX_TABLE_COL_POINTER, &table, -1);
580 g_return_if_fail (table);
581
582 /* If we've changed, then reset the entry list */
583 if (table != ttw->current_table)
584 {
585 ttw->current_table = table;
586 ttw->current_entry = NULL;
587 }
588 /* And force a refresh of the entries */
589 tax_table_entries_refresh (ttw);
590}
591
592static void
593tax_table_entry_selection_changed (GtkTreeSelection *selection,
594 gpointer user_data)
595{
596 TaxTableWindow *ttw = user_data;
597 GtkTreeModel *model;
598 GtkTreeIter iter;
599
600 g_return_if_fail (ttw);
601
602 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
603 {
604 ttw->current_entry = NULL;
605 return;
606 }
607
608 gtk_tree_model_get (model, &iter, TAX_ENTRY_COL_POINTER, &ttw->current_entry, -1);
609}
610
611static void
612tax_table_entry_row_activated (GtkTreeView *tree_view,
613 GtkTreePath *path,
614 GtkTreeViewColumn *column,
615 gpointer user_data)
616{
617 TaxTableWindow *ttw = user_data;
618
619 new_tax_table_dialog (ttw, FALSE, ttw->current_entry, NULL);
620}
621
622void
623tax_table_new_table_cb (GtkButton *button, TaxTableWindow *ttw)
624{
625 g_return_if_fail (ttw);
626 new_tax_table_dialog (ttw, TRUE, NULL, NULL);
627}
628
629
630static const char
631*rename_tax_table_dialog (GtkWidget *parent,
632 const char *title,
633 const char *msg,
634 const char *button_name,
635 const char *text)
636{
637 GtkWidget *vbox;
638 GtkWidget *main_vbox;
639 GtkWidget *label;
640 GtkWidget *textbox;
641 GtkWidget *dialog;
642 GtkWidget *dvbox;
643
644 main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
645 gtk_box_set_homogeneous (GTK_BOX(main_vbox), FALSE);
646 gtk_container_set_border_width (GTK_CONTAINER(main_vbox), 6);
647 gtk_widget_show (main_vbox);
648
649 label = gtk_label_new (msg);
650 gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT);
651 gtk_box_pack_start (GTK_BOX(main_vbox), label, FALSE, FALSE, 0);
652 gtk_widget_show (label);
653
654 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
655 gtk_box_set_homogeneous (GTK_BOX(vbox), TRUE);
656 gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
657 gtk_container_add (GTK_CONTAINER(main_vbox), vbox);
658 gtk_widget_show (vbox);
659
660 textbox = gtk_entry_new ();
661 gtk_widget_show (textbox);
662 gtk_entry_set_text (GTK_ENTRY(textbox), text);
663 gtk_box_pack_start (GTK_BOX(vbox), textbox, FALSE, FALSE, 0);
664
665 dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW(parent),
666 GTK_DIALOG_DESTROY_WITH_PARENT,
667 _("_Cancel"), GTK_RESPONSE_CANCEL,
668 button_name, GTK_RESPONSE_OK,
669 NULL);
670 gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
671
672 dvbox = gtk_dialog_get_content_area (GTK_DIALOG(dialog));
673 gtk_box_pack_start (GTK_BOX(dvbox), main_vbox, TRUE, TRUE, 0);
674
675 if (gtk_dialog_run (GTK_DIALOG(dialog)) != GTK_RESPONSE_OK)
676 {
677 gtk_widget_destroy (dialog);
678 return NULL;
679 }
680
681 text = g_strdup (gtk_entry_get_text (GTK_ENTRY(textbox)));
682 gtk_widget_destroy (dialog);
683 return text;
684}
685
686void
687tax_table_rename_table_cb (GtkButton *button, TaxTableWindow *ttw)
688{
689 const char *oldname;
690 const char *newname;
691 g_return_if_fail (ttw);
692
693 if (!ttw->current_table)
694 return;
695
696 oldname = gncTaxTableGetName (ttw->current_table);
697 newname = rename_tax_table_dialog (ttw->dialog, (_("Rename")),
698 (_("Please enter new name")),
699 (_("_Rename")), oldname);
700
701 if (newname && *newname != '\0' && (g_strcmp0 (oldname, newname) != 0))
702 {
703 if (gncTaxTableLookupByName (ttw->book, newname))
704 {
705 char *message = g_strdup_printf (_("Tax table name \"%s\" already exists."),
706 newname);
707 gnc_error_dialog (GTK_WINDOW(ttw->dialog), "%s", message);
708 g_free (message);
709 }
710 else
711 {
712 gncTaxTableSetName (ttw->current_table, newname);
713 }
714 }
715}
716
717
718void
719tax_table_delete_table_cb (GtkButton *button, TaxTableWindow *ttw)
720{
721 g_return_if_fail (ttw);
722
723 if (!ttw->current_table)
724 return;
725
726 if (gncTaxTableGetRefcount (ttw->current_table) > 0)
727 {
728 char *message =
729 g_strdup_printf (_("Tax table \"%s\" is in use. You cannot delete it."),
730 gncTaxTableGetName (ttw->current_table));
731 gnc_error_dialog (GTK_WINDOW(ttw->dialog), "%s", message);
732 g_free (message);
733 return;
734 }
735
736 if (gnc_verify_dialog (GTK_WINDOW(ttw->dialog), FALSE,
737 _("Are you sure you want to delete \"%s\"?"),
738 gncTaxTableGetName (ttw->current_table)))
739 {
740 /* Ok, let's remove it */
741 gnc_suspend_gui_refresh ();
742 gncTaxTableBeginEdit (ttw->current_table);
743 gncTaxTableDestroy (ttw->current_table);
744 ttw->current_table = NULL;
745 ttw->current_entry = NULL;
746 gnc_resume_gui_refresh ();
747 }
748}
749
750void
751tax_table_new_entry_cb (GtkButton *button, TaxTableWindow *ttw)
752{
753 g_return_if_fail (ttw);
754 if (!ttw->current_table)
755 return;
756 new_tax_table_dialog (ttw, FALSE, NULL, NULL);
757}
758
759void
760tax_table_edit_entry_cb (GtkButton *button, TaxTableWindow *ttw)
761{
762 g_return_if_fail (ttw);
763 if (!ttw->current_entry)
764 return;
765 new_tax_table_dialog (ttw, FALSE, ttw->current_entry, NULL);
766}
767
768void
769tax_table_delete_entry_cb (GtkButton *button, TaxTableWindow *ttw)
770{
771 g_return_if_fail (ttw);
772 if (!ttw->current_table || !ttw->current_entry)
773 return;
774
775 if (g_list_length (gncTaxTableGetEntries (ttw->current_table)) <= 1)
776 {
777 char *message = _("You cannot remove the last entry from the tax table. "
778 "Try deleting the tax table if you want to do that.");
779 gnc_error_dialog (GTK_WINDOW(ttw->dialog) , "%s", message);
780 return;
781 }
782
783 if (gnc_verify_dialog (GTK_WINDOW(ttw->dialog), FALSE, "%s",
784 _("Are you sure you want to delete this entry?")))
785 {
786 /* Ok, let's remove it */
787 gnc_suspend_gui_refresh ();
788 gncTaxTableBeginEdit (ttw->current_table);
789 gncTaxTableRemoveEntry (ttw->current_table, ttw->current_entry);
790 gncTaxTableEntryDestroy (ttw->current_entry);
791 gncTaxTableChanged (ttw->current_table);
792 gncTaxTableCommitEdit (ttw->current_table);
793 ttw->current_entry = NULL;
794 gnc_resume_gui_refresh ();
795 }
796}
797
798static void
799tax_table_window_refresh_handler (GHashTable *changes, gpointer data)
800{
801 TaxTableWindow *ttw = data;
802
803 g_return_if_fail (data);
804 tax_table_window_refresh (ttw);
805}
806
807static void
808tax_table_window_close_handler (gpointer data)
809{
810 TaxTableWindow *ttw = data;
811 g_return_if_fail (ttw);
812
813 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(ttw->dialog));
814 gtk_widget_destroy (ttw->dialog);
815}
816
817void
818tax_table_window_close (GtkWidget *widget, gpointer data)
819{
820 TaxTableWindow *ttw = data;
821 gnc_close_gui_component (ttw->component_id);
822}
823
824static gboolean
825tax_table_window_delete_event_cb (GtkWidget *widget,
826 GdkEvent *event,
827 gpointer user_data)
828{
829 TaxTableWindow *ttw = user_data;
830 // this cb allows the window size to be saved on closing with the X
831 gnc_save_window_size (GNC_PREFS_GROUP,
832 GTK_WINDOW(ttw->dialog));
833 return FALSE;
834}
835
836void
837tax_table_window_destroy_cb (GtkWidget *widget, gpointer data)
838{
839 TaxTableWindow *ttw = data;
840
841 if (!ttw) return;
842
843 gnc_unregister_gui_component (ttw->component_id);
844
845 if (ttw->dialog)
846 {
847 gtk_widget_destroy (ttw->dialog);
848 ttw->dialog = NULL;
849 }
850 g_free (ttw);
851}
852
853static gboolean
854tax_table_window_key_press_cb (GtkWidget *widget, GdkEventKey *event,
855 gpointer data)
856{
857 TaxTableWindow *ttw = data;
858
859 if (event->keyval == GDK_KEY_Escape)
860 {
861 tax_table_window_close_handler (ttw);
862 return TRUE;
863 }
864 else
865 return FALSE;
866}
867
868static gboolean
869find_handler (gpointer find_data, gpointer data)
870{
871 TaxTableWindow *ttw = data;
872 QofBook *book = find_data;
873
874 return (ttw != NULL && ttw->book == book);
875}
876
877/* Create a tax-table window */
878TaxTableWindow *
879gnc_ui_tax_table_window_new (GtkWindow *parent, QofBook *book)
880{
881 TaxTableWindow *ttw;
882 GtkBuilder *builder;
883 GtkTreeView *view;
884 GtkTreeViewColumn *column;
885 GtkCellRenderer *renderer;
886 GtkListStore *store;
887 GtkTreeSelection *selection;
888
889 if (!book) return NULL;
890
891 /*
892 * Find an existing tax-table window. If found, bring it to
893 * the front. If we have an actual owner, then set it in
894 * the window.
895 */
896 ttw = gnc_find_first_gui_component (DIALOG_TAX_TABLE_CM_CLASS, find_handler,
897 book);
898 if (ttw)
899 {
900 gtk_window_present (GTK_WINDOW(ttw->dialog));
901 return ttw;
902 }
903
904 /* Didn't find one -- create a new window */
905 ttw = g_new0 (TaxTableWindow, 1);
906 ttw->book = book;
907 ttw->session = gnc_get_current_session ();
908
909 /* Open and read the Glade File */
910 builder = gtk_builder_new ();
911 gnc_builder_add_from_file (builder, "dialog-tax-table.glade", "tax_table_window");
912 ttw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "tax_table_window"));
913 ttw->names_view = GTK_WIDGET(gtk_builder_get_object (builder, "tax_tables_view"));
914 ttw->entries_view = GTK_WIDGET(gtk_builder_get_object (builder, "tax_table_entries"));
915
916 // Set the name for this dialog so it can be easily manipulated with css
917 gtk_widget_set_name (GTK_WIDGET(ttw->dialog), "gnc-id-new-tax-table");
918 gnc_widget_style_context_add_class (GTK_WIDGET(ttw->dialog), "gnc-class-taxes");
919
920 g_signal_connect (ttw->dialog, "delete-event",
921 G_CALLBACK(tax_table_window_delete_event_cb), ttw);
922
923 g_signal_connect (ttw->dialog, "key_press_event",
924 G_CALLBACK (tax_table_window_key_press_cb), ttw);
925
926 /* Create the tax tables view */
927 view = GTK_TREE_VIEW(ttw->names_view);
928 store = gtk_list_store_new (NUM_TAX_TABLE_COLS, G_TYPE_STRING,
929 G_TYPE_POINTER);
930 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
931 g_object_unref (store);
932
933 /* default sort order */
934 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
935 TAX_TABLE_COL_NAME,
936 GTK_SORT_ASCENDING);
937
938 renderer = gtk_cell_renderer_text_new ();
939 column = gtk_tree_view_column_new_with_attributes ("", renderer,
940 "text", TAX_TABLE_COL_NAME,
941 NULL);
942 g_object_set (G_OBJECT(column), "reorderable", TRUE, NULL);
943 gtk_tree_view_append_column (view, column);
944 gtk_tree_view_column_set_sort_column_id (column, TAX_TABLE_COL_NAME);
945
946 selection = gtk_tree_view_get_selection (view);
947 g_signal_connect (selection, "changed",
948 G_CALLBACK(tax_table_selection_changed), ttw);
949
950 /* Create the tax table entries view */
951 view = GTK_TREE_VIEW(ttw->entries_view);
952 store = gtk_list_store_new (NUM_TAX_ENTRY_COLS, G_TYPE_STRING,
953 G_TYPE_POINTER, G_TYPE_STRING);
954 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
955 g_object_unref (store);
956
957 /* default sort order */
958 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
959 TAX_ENTRY_COL_NAME,
960 GTK_SORT_ASCENDING);
961
962 renderer = gtk_cell_renderer_text_new ();
963 column = gtk_tree_view_column_new_with_attributes ("", renderer,
964 "text", TAX_ENTRY_COL_NAME,
965 NULL);
966 g_object_set (G_OBJECT(column), "reorderable", TRUE, NULL);
967 gtk_tree_view_append_column (view, column);
968 gtk_tree_view_column_set_sort_column_id (column, TAX_ENTRY_COL_NAME);
969
970 selection = gtk_tree_view_get_selection (view);
971 g_signal_connect (selection, "changed",
972 G_CALLBACK(tax_table_entry_selection_changed), ttw);
973 g_signal_connect (view, "row-activated",
974 G_CALLBACK(tax_table_entry_row_activated), ttw);
975
976 /* Setup signals */
977 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ttw);
978
979 /* register with component manager */
980 ttw->component_id =
981 gnc_register_gui_component (DIALOG_TAX_TABLE_CM_CLASS,
982 tax_table_window_refresh_handler,
983 tax_table_window_close_handler,
984 ttw);
985
986 gnc_gui_component_set_session (ttw->component_id, ttw->session);
987
988 tax_table_window_refresh (ttw);
989 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(ttw->dialog), parent);
990 gtk_widget_show_all (ttw->dialog);
991
992 g_object_unref (G_OBJECT(builder));
993
994 return ttw;
995}
996
997/* Create a new tax-table by name */
999gnc_ui_tax_table_new_from_name (GtkWindow *parent, QofBook *book, const char *name)
1000{
1001 TaxTableWindow *ttw;
1002
1003 if (!book) return NULL;
1004
1005 ttw = gnc_ui_tax_table_window_new (parent, book);
1006 if (!ttw) return NULL;
1007
1008 return new_tax_table_dialog (ttw, TRUE, NULL, name);
1009}
gtk helper routines.
GtkTreeView implementation for gnucash account tree.
utility functions for the GnuCash UI
Tax Table programming interface.
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition Account.cpp:3305
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
This function returns the account associated with the selected item in the account tree view.
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
This function selects an account in the account tree view.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b
#define gncTaxTableGetGUID(x)
@ GNC_AMT_TYPE_VALUE
tax is a number
Definition gncTaxTable.h:80
@ GNC_AMT_TYPE_PERCENT
tax is a percentage
Definition gncTaxTable.h:81
STRUCTS.
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability....
QofBook reference.
Definition qofbook-p.hpp:47