GnuCash c935c2f+
Loading...
Searching...
No Matches
dialog-billterms.c
1/*
2 * dialog-billterms.c -- Dialog to create and edit billing terms
3 * Copyright (C) 2002 Derek Atkins
4 * Author: Derek Atkins <warlord@MIT.EDU>
5 * Copyright (c) 2006 David Hampton <hampton@employees.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, contact:
19 *
20 * Free Software Foundation Voice: +1-617-542-5942
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
22 * Boston, MA 02110-1301, USA gnu@gnu.org
23 */
24
25#include <config.h>
26
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29
30#include "dialog-utils.h"
31#include "gnc-component-manager.h"
32#include "gnc-session.h"
33#include "gnc-ui.h"
34#include "gnc-gui-query.h"
35#include "gnc-ui-util.h"
36#include "qof.h"
37
38#include "gncBillTerm.h"
39#include "dialog-billterms.h"
40
41#define DIALOG_BILLTERMS_CM_CLASS "billterms-dialog"
42#define GNC_PREFS_GROUP "dialogs.bill-terms"
43
44enum term_cols
45{
46 BILL_TERM_COL_NAME = 0,
47 BILL_TERM_COL_TERM,
48 NUM_BILL_TERM_COLS
49};
50
51void billterms_new_term_cb (GtkButton *button, BillTermsWindow *btw);
52void billterms_delete_term_cb (GtkButton *button, BillTermsWindow *btw);
53void billterms_edit_term_cb (GtkButton *button, BillTermsWindow *btw);
54void billterms_window_close (GtkWidget *widget, gpointer data);
55void billterms_window_destroy_cb (GtkWidget *widget, gpointer data);
56void billterms_type_combobox_changed (GtkComboBox *cb, gpointer data);
57
58typedef struct _billterm_notebook
59{
60 GtkWidget *notebook;
61
62 /* "Days" widgets */
63 GtkWidget *days_due_days;
64 GtkWidget *days_disc_days;
65 GtkWidget *days_disc;
66
67 /* "Proximo" widgets */
68 GtkWidget *prox_due_day;
69 GtkWidget *prox_disc_day;
70 GtkWidget *prox_disc;
71 GtkWidget *prox_cutoff;
72
73 /* What kind of term is this? */
74 GncBillTermType type;
76
78{
79 GtkWidget *window;
80 GtkWidget *terms_view;
81 GtkWidget *desc_entry;
82 GtkWidget *type_label;
83 GtkWidget *term_vbox;
84 BillTermNB notebook;
85
86 GncBillTerm *current_term;
87 QofBook *book;
88 gint component_id;
89 QofSession *session;
90};
91
92typedef struct _new_billterms
93{
94 GtkWidget *dialog;
95 GtkWidget *name_entry;
96 GtkWidget *desc_entry;
97 BillTermNB notebook;
98
99 BillTermsWindow *btw;
100 GncBillTerm *this_term;
102
103
104static GtkWidget *
105read_widget (GtkBuilder *builder, char *name, gboolean read_only)
106{
107 GtkWidget *widget = GTK_WIDGET(gtk_builder_get_object (builder, name));
108 if (read_only)
109 {
110 GtkAdjustment *adj;
111 gtk_editable_set_editable (GTK_EDITABLE(widget), FALSE);
112 adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(widget));
113 gtk_adjustment_set_step_increment (adj, 0.0);
114 gtk_adjustment_set_page_increment (adj, 0.0);
115 }
116
117 return widget;
118}
119
120/* NOTE: The caller needs to unref once they attach */
121static void
122init_notebook_widgets (BillTermNB *notebook, gboolean read_only,
123 gpointer user_data)
124{
125 GtkBuilder *builder;
126 GtkWidget *parent;
127
128 /* Load the notebook from Glade File */
129 builder = gtk_builder_new ();
130 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "discount_adj");
131 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "discount_days_adj");
132 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "due_days_adj");
133 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "pdiscount_adj");
134 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "pdiscount_day_adj");
135 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "pdue_day_adj");
136 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "pcutoff_day_adj");
137 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "terms_notebook_window");
138 notebook->notebook = GTK_WIDGET(gtk_builder_get_object (builder, "term_notebook"));
139 parent = GTK_WIDGET(gtk_builder_get_object (builder, "terms_notebook_window"));
140
141 // Set the name for this dialog so it can be easily manipulated with css
142 gtk_widget_set_name (GTK_WIDGET(notebook->notebook), "gnc-id-bill-term");
143 gnc_widget_style_context_add_class (GTK_WIDGET(notebook->notebook), "gnc-class-bill-terms");
144
145 /* load the "days" widgets */
146 notebook->days_due_days = read_widget (builder, "days:due_days", read_only);
147 notebook->days_disc_days = read_widget (builder, "days:discount_days", read_only);
148 notebook->days_disc = read_widget (builder, "days:discount", read_only);
149
150 /* load the "proximo" widgets */
151 notebook->prox_due_day = read_widget (builder, "prox:due_day", read_only);
152 notebook->prox_disc_day = read_widget (builder, "prox:discount_day", read_only);
153 notebook->prox_disc = read_widget (builder, "prox:discount", read_only);
154 notebook->prox_cutoff = read_widget (builder, "prox:cutoff_day", read_only);
155
156 /* Disconnect the notebook from the window */
157 g_object_ref (notebook->notebook);
158 gtk_container_remove (GTK_CONTAINER(parent), notebook->notebook);
159 g_object_unref (G_OBJECT(builder));
160 gtk_widget_destroy (parent);
161
162 /* NOTE: The caller needs to unref once they attach */
163}
164
165static void
166set_numeric (GtkWidget *widget, GncBillTerm *term,
167 void (*func)(GncBillTerm *, gnc_numeric))
168{
169 gnc_numeric val;
170 gdouble fl = 0.0;
171
172 fl = gtk_spin_button_get_value (GTK_SPIN_BUTTON(widget));
173 val = double_to_gnc_numeric (fl, 100000, GNC_HOW_RND_ROUND_HALF_UP);
174 func (term, val);
175}
176
177static void
178get_numeric (GtkWidget *widget, GncBillTerm *term,
179 gnc_numeric (*func)(const GncBillTerm *))
180{
181 gnc_numeric val;
182 gdouble fl;
183
184 val = func (term);
185 fl = gnc_numeric_to_double (val);
186 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), fl);
187}
188
189static void
190set_int (GtkWidget *widget, GncBillTerm *term,
191 void (*func)(GncBillTerm *, gint))
192{
193 gint val;
194
195 val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(widget));
196 func (term, val);
197}
198
199static void
200get_int (GtkWidget *widget, GncBillTerm *term,
201 gint (*func)(const GncBillTerm *))
202{
203 gint val;
204
205 val = func (term);
206 gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), (gfloat)val);
207}
208
209/* return TRUE if anything truly changed */
210static gboolean
211ui_to_billterm (NewBillTerm *nbt)
212{
213 BillTermNB *notebook;
214 GncBillTerm *term;
215 const char *text;
216
217 term = nbt->this_term;
218 notebook = &nbt->notebook;
219
220 text = gtk_entry_get_text (GTK_ENTRY(nbt->desc_entry));
221 if (text)
222 gncBillTermSetDescription (term, text);
223
224 gncBillTermSetType (nbt->this_term, nbt->notebook.type);
225
226 switch (nbt->notebook.type)
227 {
228 case GNC_TERM_TYPE_DAYS:
229 set_int (notebook->days_due_days, term, gncBillTermSetDueDays);
230 set_int (notebook->days_disc_days, term, gncBillTermSetDiscountDays);
231 set_numeric (notebook->days_disc, term, gncBillTermSetDiscount);
232 break;
233
234 case GNC_TERM_TYPE_PROXIMO:
235 set_int (notebook->prox_due_day, term, gncBillTermSetDueDays);
236 set_int (notebook->prox_disc_day, term, gncBillTermSetDiscountDays);
237 set_numeric (notebook->prox_disc, term, gncBillTermSetDiscount);
238 set_int (notebook->prox_cutoff, term, gncBillTermSetCutoff);
239 break;
240 }
241
242 return gncBillTermIsDirty (term);
243}
244
245static void
246billterm_to_ui (GncBillTerm *term, GtkWidget *desc, BillTermNB *notebook)
247{
248 gtk_entry_set_text (GTK_ENTRY(desc), gncBillTermGetDescription (term));
249 notebook->type = gncBillTermGetType (term);
250
251 switch (notebook->type)
252 {
253 case GNC_TERM_TYPE_DAYS:
254 get_int (notebook->days_due_days, term, gncBillTermGetDueDays);
255 get_int (notebook->days_disc_days, term, gncBillTermGetDiscountDays);
256 get_numeric (notebook->days_disc, term, gncBillTermGetDiscount);
257 break;
258
259 case GNC_TERM_TYPE_PROXIMO:
260 get_int (notebook->prox_due_day, term, gncBillTermGetDueDays);
261 get_int (notebook->prox_disc_day, term, gncBillTermGetDiscountDays);
262 get_numeric (notebook->prox_disc, term, gncBillTermGetDiscount);
263 get_int (notebook->prox_cutoff, term, gncBillTermGetCutoff);
264 break;
265 }
266}
267
268static gboolean
269verify_term_ok (NewBillTerm *nbt)
270{
271 char *message = _("Discount days cannot be more than due days.");
272 gboolean result;
273 BillTermNB *notebook;
274 gint days_due_days, days_disc_days;
275 gint prox_due_days, prox_disc_days;
276
277 notebook = &nbt->notebook;
278 result = TRUE;
279
280
281 days_due_days = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(notebook->days_due_days));
282 days_disc_days = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(notebook->days_disc_days));
283 prox_due_days = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(notebook->prox_due_day));
284 prox_disc_days = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(notebook->prox_disc_day));
285
286 switch (nbt->notebook.type)
287 {
288 case GNC_TERM_TYPE_DAYS:
289 if (days_due_days<days_disc_days)
290 {
291 gnc_error_dialog (GTK_WINDOW(nbt->dialog), "%s", message);
292 result = FALSE;
293 }
294 break;
295 case GNC_TERM_TYPE_PROXIMO:
296 if (prox_due_days<prox_disc_days)
297 {
298 gnc_error_dialog (GTK_WINDOW(nbt->dialog), "%s", message);
299 result = FALSE;
300 }
301 break;
302 }
303
304 return result;
305}
306
307static gboolean
308new_billterm_ok_cb (NewBillTerm *nbt)
309{
310 BillTermsWindow *btw;
311 const char *name = NULL;
312 char *message;
313
314 g_return_val_if_fail (nbt, FALSE);
315 btw = nbt->btw;
316
317 /* Verify that we've got real, valid data */
318
319 /* verify the name, maybe */
320 if (nbt->this_term == NULL)
321 {
322 name = gtk_entry_get_text (GTK_ENTRY(nbt->name_entry));
323 if (name == NULL || *name == '\0')
324 {
325 message = _("You must provide a name for this Billing Term.");
326 gnc_error_dialog (GTK_WINDOW(nbt->dialog), "%s", message);
327 return FALSE;
328 }
329 if (gncBillTermLookupByName (btw->book, name))
330 {
331 message = g_strdup_printf (_(
332 "You must provide a unique name for this Billing Term. "
333 "Your choice \"%s\" is already in use."), name);
334 gnc_error_dialog (GTK_WINDOW(nbt->dialog), "%s", message);
335 g_free (message);
336 return FALSE;
337 }
338 }
339
340 /* Verify the actual data */
341 if (!verify_term_ok (nbt))
342 return FALSE;
343
344 gnc_suspend_gui_refresh ();
345
346 /* Ok, it's all valid, now either change or add this thing */
347 if (nbt->this_term == NULL)
348 {
349 nbt->this_term = gncBillTermCreate (btw->book);
350 gncBillTermBeginEdit (nbt->this_term);
351 gncBillTermSetName (nbt->this_term, name);
352 /* Reset the current term */
353 btw->current_term = nbt->this_term;
354 }
355 else
356 gncBillTermBeginEdit (btw->current_term);
357
358 /* Fill in the rest of the term */
359 if (ui_to_billterm (nbt))
360 gncBillTermChanged (btw->current_term);
361
362 /* Mark the table as changed and commit it */
363 gncBillTermCommitEdit (btw->current_term);
364
365 gnc_resume_gui_refresh ();
366 return TRUE;
367}
368
369static void
370show_notebook (BillTermNB *notebook)
371{
372 g_return_if_fail (notebook->type > 0);
373 gtk_notebook_set_current_page (GTK_NOTEBOOK(notebook->notebook),
374 notebook->type - 1);
375}
376
377static void
378maybe_set_type (NewBillTerm *nbt, GncBillTermType type)
379{
380 /* See if anything to do? */
381 if (type == nbt->notebook.type)
382 return;
383
384 /* Yep. Let's refresh */
385 nbt->notebook.type = type;
386 show_notebook (&nbt->notebook);
387}
388
389void
390billterms_type_combobox_changed (GtkComboBox *cb, gpointer data)
391{
392 NewBillTerm *nbt = data;
393 gint value;
394
395 value = gtk_combo_box_get_active (cb);
396 maybe_set_type (nbt, value + 1);
397}
398
399static GncBillTerm *
400new_billterm_dialog (BillTermsWindow *btw, GncBillTerm *term,
401 const char *name)
402{
403 GncBillTerm *created_term = NULL;
404 NewBillTerm *nbt;
405 GtkBuilder *builder;
406 GtkWidget *box, *combo_box;
407 gint response;
408 gboolean done;
409 const gchar *dialog_name;
410 const gchar *dialog_desc;
411 const gchar *dialog_combo;
412 const gchar *dialog_nb;
413
414 if (!btw) return NULL;
415
416 nbt = g_new0 (NewBillTerm, 1);
417 nbt->btw = btw;
418 nbt->this_term = term;
419
420 /* Open and read the Glade File */
421 if (term == NULL)
422 {
423 dialog_name = "new_term_dialog";
424 dialog_desc = "description_entry";
425 dialog_combo = "type_combobox";
426 dialog_nb = "note_book_hbox";
427 }
428 else
429 {
430 dialog_name = "edit_term_dialog";
431 dialog_desc = "entry_desc";
432 dialog_combo = "type_combo";
433 dialog_nb = "notebook_hbox";
434 }
435 builder = gtk_builder_new ();
436 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "type_liststore");
437 gnc_builder_add_from_file (builder, "dialog-billterms.glade", dialog_name);
438 nbt->dialog = GTK_WIDGET(gtk_builder_get_object (builder, dialog_name));
439 nbt->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
440 nbt->desc_entry = GTK_WIDGET(gtk_builder_get_object (builder, dialog_desc));
441
442 // Set the name for this dialog so it can be easily manipulated with css
443 gtk_widget_set_name (GTK_WIDGET(nbt->dialog), "gnc-id-new-bill-terms");
444 gnc_widget_style_context_add_class (GTK_WIDGET(nbt->dialog), "gnc-class-bill-terms");
445
446 if (name)
447 gtk_entry_set_text (GTK_ENTRY(nbt->name_entry), name);
448
449 /* Initialize the notebook widgets */
450 init_notebook_widgets (&nbt->notebook, FALSE, nbt);
451
452 /* Attach the notebook */
453 box = GTK_WIDGET(gtk_builder_get_object (builder, dialog_nb));
454 gtk_box_pack_start (GTK_BOX(box), nbt->notebook.notebook, TRUE, TRUE, 0);
455 g_object_unref (nbt->notebook.notebook);
456
457 /* Fill in the widgets appropriately */
458 if (term)
459 billterm_to_ui (term, nbt->desc_entry, &nbt->notebook);
460 else
461 nbt->notebook.type = GNC_TERM_TYPE_DAYS;
462
463 /* Create the menu */
464 combo_box = GTK_WIDGET(gtk_builder_get_object (builder, dialog_combo));
465 gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box), nbt->notebook.type - 1);
466
467 /* Show the right notebook page */
468 show_notebook (&nbt->notebook);
469
470 /* Setup signals */
471 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, nbt);
472
473 gtk_window_set_transient_for (GTK_WINDOW(nbt->dialog),
474 GTK_WINDOW(btw->window));
475
476 /* Show what we should */
477 gtk_widget_show_all (nbt->dialog);
478 if (term)
479 {
480 gtk_widget_grab_focus (nbt->desc_entry);
481 }
482 else
483 gtk_widget_grab_focus (nbt->name_entry);
484
485 done = FALSE;
486 while (!done)
487 {
488 response = gtk_dialog_run (GTK_DIALOG(nbt->dialog));
489 switch (response)
490 {
491 case GTK_RESPONSE_OK:
492 if (new_billterm_ok_cb (nbt))
493 {
494 created_term = nbt->this_term;
495 done = TRUE;
496 }
497 break;
498 default:
499 done = TRUE;
500 break;
501 }
502 }
503
504 g_object_unref (G_OBJECT(builder));
505
506 gtk_widget_destroy (nbt->dialog);
507 g_free (nbt);
508
509 return created_term;
510}
511
512/***********************************************************************/
513
514static void
515billterms_term_refresh (BillTermsWindow *btw)
516{
517 char *type_label;
518
519 g_return_if_fail (btw);
520
521 if (!btw->current_term)
522 {
523 gtk_widget_hide (btw->term_vbox);
524 return;
525 }
526
527 gtk_widget_show_all (btw->term_vbox);
528 billterm_to_ui (btw->current_term, btw->desc_entry, &btw->notebook);
529 switch (gncBillTermGetType (btw->current_term))
530 {
531 case GNC_TERM_TYPE_DAYS:
532 type_label = _("Days");
533 break;
534 case GNC_TERM_TYPE_PROXIMO:
535 type_label = _("Proximo");
536 break;
537 default:
538 type_label = _("Unknown");
539 break;
540 }
541 show_notebook (&btw->notebook);
542 gtk_label_set_text (GTK_LABEL(btw->type_label), type_label);
543}
544
545static void
546billterms_window_refresh (BillTermsWindow *btw)
547{
548 GList *list, *node;
549 GncBillTerm *term;
550 GtkTreeView *view;
551 GtkListStore *store;
552 GtkTreeIter iter;
553 GtkTreePath *path;
554 GtkTreeSelection *selection;
555 GtkTreeRowReference *reference = NULL;
556
557 g_return_if_fail (btw);
558 view = GTK_TREE_VIEW(btw->terms_view);
559 store = GTK_LIST_STORE(gtk_tree_view_get_model (view));
560 selection = gtk_tree_view_get_selection (view);
561
562 /* Clear the list */
563 gtk_list_store_clear (store);
564 gnc_gui_component_clear_watches (btw->component_id);
565
566 /* Add the items to the list */
567 list = gncBillTermGetTerms (btw->book);
568
569 /* If there are no terms, clear the term display */
570 if (list == NULL)
571 {
572 btw->current_term = NULL;
573 billterms_term_refresh (btw);
574 }
575 else
576 {
577 list = g_list_reverse (g_list_copy (list));
578 }
579
580 for ( node = list; node; node = node->next)
581 {
582 term = node->data;
583 gnc_gui_component_watch_entity (btw->component_id,
584 gncBillTermGetGUID (term),
585 QOF_EVENT_MODIFY);
586
587 gtk_list_store_prepend (store, &iter);
588 gtk_list_store_set (store, &iter,
589 BILL_TERM_COL_NAME, gncBillTermGetName (term),
590 BILL_TERM_COL_TERM, term,
591 -1);
592 if (term == btw->current_term)
593 {
594 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store), &iter);
595 reference = gtk_tree_row_reference_new (GTK_TREE_MODEL(store), path);
596 gtk_tree_path_free (path);
597 }
598 }
599
600 g_list_free (list);
601
602 gnc_gui_component_watch_entity_type (btw->component_id,
603 GNC_BILLTERM_MODULE_NAME,
604 QOF_EVENT_CREATE | QOF_EVENT_DESTROY);
605
606 if (reference)
607 {
608 path = gtk_tree_row_reference_get_path (reference);
609 gtk_tree_row_reference_free (reference);
610 if (path)
611 {
612 gtk_tree_selection_select_path (selection, path);
613 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
614 gtk_tree_path_free (path);
615 }
616 }
617 else
618 {
619 GtkTreeIter iter;
620 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter))
621 gtk_tree_selection_select_iter (selection, &iter);
622 }
623}
624
625static void
626billterm_selection_changed (GtkTreeSelection *selection,
627 BillTermsWindow *btw)
628{
629 GncBillTerm *term = NULL;
630 GtkTreeModel *model;
631 GtkTreeIter iter;
632
633 g_return_if_fail (btw);
634
635 if (gtk_tree_selection_get_selected (selection, &model, &iter))
636 gtk_tree_model_get (model, &iter, BILL_TERM_COL_TERM, &term, -1);
637
638 /* If we've changed, then reset the term list */
639 if (GNC_IS_BILLTERM(term) && (term != btw->current_term))
640 btw->current_term = term;
641
642 /* And force a refresh of the entries */
643 billterms_term_refresh (btw);
644}
645
646static void
647billterm_selection_activated (GtkTreeView *tree_view,
648 GtkTreePath *path,
649 GtkTreeViewColumn *column,
650 BillTermsWindow *btw)
651{
652 new_billterm_dialog (btw, btw->current_term, NULL);
653}
654
655void
656billterms_new_term_cb (GtkButton *button, BillTermsWindow *btw)
657{
658 g_return_if_fail (btw);
659 new_billterm_dialog (btw, NULL, NULL);
660}
661
662void
663billterms_delete_term_cb (GtkButton *button, BillTermsWindow *btw)
664{
665 g_return_if_fail (btw);
666
667 if (!btw->current_term)
668 return;
669
670 if (gncBillTermGetRefcount (btw->current_term) > 0)
671 {
672 gnc_error_dialog (GTK_WINDOW(btw->window),
673 _("Term \"%s\" is in use. You cannot delete it."),
674 gncBillTermGetName (btw->current_term));
675 return;
676 }
677
678 if (gnc_verify_dialog (GTK_WINDOW(btw->window), FALSE,
679 _("Are you sure you want to delete \"%s\"?"),
680 gncBillTermGetName (btw->current_term)))
681 {
682 /* Ok, let's remove it */
683 gnc_suspend_gui_refresh ();
684 gncBillTermBeginEdit (btw->current_term);
685 gncBillTermDestroy (btw->current_term);
686 btw->current_term = NULL;
687 gnc_resume_gui_refresh ();
688 }
689}
690
691void
692billterms_edit_term_cb (GtkButton *button, BillTermsWindow *btw)
693{
694 g_return_if_fail (btw);
695 if (!btw->current_term)
696 return;
697 new_billterm_dialog (btw, btw->current_term, NULL);
698}
699
700static void
701billterms_window_refresh_handler (GHashTable *changes, gpointer data)
702{
703 BillTermsWindow *btw = data;
704
705 g_return_if_fail (data);
706 billterms_window_refresh (btw);
707}
708
709static void
710billterms_window_close_handler (gpointer data)
711{
712 BillTermsWindow *btw = data;
713
714 g_return_if_fail (btw);
715
716 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(btw->window));
717 gtk_widget_destroy (btw->window);
718}
719
720void
721billterms_window_close (GtkWidget *widget, gpointer data)
722{
723 BillTermsWindow *btw = data;
724
725 gnc_close_gui_component (btw->component_id);
726}
727
728static gboolean
729billterms_window_delete_event_cb (GtkWidget *widget,
730 GdkEvent *event,
731 gpointer data)
732{
733 BillTermsWindow *btw = data;
734
735 if (!btw) return FALSE;
736
737 // this cb allows the window size to be saved on closing with the X
738 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(btw->window));
739 return FALSE;
740}
741
742void
743billterms_window_destroy_cb (GtkWidget *widget, gpointer data)
744{
745 BillTermsWindow *btw = data;
746
747 if (!btw) return;
748
749 gnc_unregister_gui_component (btw->component_id);
750
751 if (btw->window)
752 {
753 gtk_widget_destroy (btw->window);
754 btw->window = NULL;
755 }
756 g_free (btw);
757}
758
759static gboolean
760billterms_window_key_press_cb (GtkWidget *widget, GdkEventKey *event,
761 gpointer data)
762{
763 BillTermsWindow *btw = data;
764
765 if (event->keyval == GDK_KEY_Escape)
766 {
767 billterms_window_close_handler (btw);
768 return TRUE;
769 }
770 else
771 return FALSE;
772}
773
774static gboolean
775find_handler (gpointer find_data, gpointer data)
776{
777 BillTermsWindow *btw = data;
778 QofBook *book = find_data;
779
780 return (btw != NULL && btw->book == book);
781}
782
783/* Create a billterms window */
784BillTermsWindow *
785gnc_ui_billterms_window_new (GtkWindow *parent, QofBook *book)
786{
787 BillTermsWindow *btw;
788 GtkBuilder *builder;
789 GtkWidget *widget;
790 GtkTreeView *view;
791 GtkTreeViewColumn *column;
792 GtkCellRenderer *renderer;
793 GtkListStore *store;
794 GtkTreeSelection *selection;
795
796 if (!book) return NULL;
797
798 /*
799 * Find an existing billterm window. If found, bring it to
800 * the front. If we have an actual owner, then set it in
801 * the window.
802 */
803 btw = gnc_find_first_gui_component (DIALOG_BILLTERMS_CM_CLASS,
804 find_handler, book);
805 if (btw)
806 {
807 gtk_window_present (GTK_WINDOW(btw->window));
808 return btw;
809 }
810
811 /* Didn't find one -- create a new window */
812 btw = g_new0 (BillTermsWindow, 1);
813 btw->book = book;
814 btw->session = gnc_get_current_session ();
815
816 /* Open and read the Glade File */
817 builder = gtk_builder_new ();
818 gnc_builder_add_from_file (builder, "dialog-billterms.glade", "terms_window");
819 btw->window = GTK_WIDGET(gtk_builder_get_object (builder, "terms_window"));
820 btw->terms_view = GTK_WIDGET(gtk_builder_get_object (builder, "terms_view"));
821 btw->desc_entry = GTK_WIDGET(gtk_builder_get_object (builder, "desc_entry"));
822 btw->type_label = GTK_WIDGET(gtk_builder_get_object (builder, "type_label"));
823 btw->term_vbox = GTK_WIDGET(gtk_builder_get_object (builder, "term_vbox"));
824
825 // Set the name for this dialog so it can be easily manipulated with css
826 gtk_widget_set_name (GTK_WIDGET(btw->window), "gnc-id-bill-terms");
827 gnc_widget_style_context_add_class (GTK_WIDGET(btw->window), "gnc-class-bill-terms");
828
829 g_signal_connect (btw->window, "key_press_event",
830 G_CALLBACK(billterms_window_key_press_cb), btw);
831
832 /* Initialize the view */
833 view = GTK_TREE_VIEW(btw->terms_view);
834 store = gtk_list_store_new (NUM_BILL_TERM_COLS, G_TYPE_STRING, G_TYPE_POINTER);
835 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
836 g_object_unref (store);
837
838 renderer = gtk_cell_renderer_text_new ();
839 column = gtk_tree_view_column_new_with_attributes ("", renderer,
840 "text", BILL_TERM_COL_NAME,
841 NULL);
842 gtk_tree_view_append_column (view, column);
843
844 g_signal_connect (view, "row-activated",
845 G_CALLBACK(billterm_selection_activated), btw);
846 selection = gtk_tree_view_get_selection (view);
847 g_signal_connect (selection, "changed",
848 G_CALLBACK(billterm_selection_changed), btw);
849
850 /* Initialize the notebook widgets */
851 init_notebook_widgets (&btw->notebook, TRUE, btw);
852
853 /* Attach the notebook */
854 widget = GTK_WIDGET(gtk_builder_get_object (builder, "notebook_box"));
855 gtk_box_pack_start (GTK_BOX(widget), btw->notebook.notebook,
856 TRUE, TRUE, 0);
857 g_object_unref (btw->notebook.notebook);
858
859 /* Setup signals */
860 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, btw);
861
862 /* register with component manager */
863 btw->component_id =
864 gnc_register_gui_component (DIALOG_BILLTERMS_CM_CLASS,
865 billterms_window_refresh_handler,
866 billterms_window_close_handler,
867 btw);
868
869 gnc_gui_component_set_session (btw->component_id, btw->session);
870
871 g_signal_connect (G_OBJECT(btw->window), "delete-event",
872 G_CALLBACK(billterms_window_delete_event_cb), btw);
873
874 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(btw->window), GTK_WINDOW(parent));
875
876 gtk_widget_show_all (btw->window);
877 billterms_window_refresh (btw);
878
879 g_object_unref (G_OBJECT(builder));
880
881 return btw;
882}
883
884#if 0
885/* Create a new billterms by name */
886GncBillTerm *
887gnc_ui_billterms_new_from_name (GtkWindow *parent, QofBook *book, const char *name)
888{
889 BillTermsWindow *btw;
890
891 if (!book) return NULL;
892
893 btw = gnc_ui_billterms_window_new (parent, book);
894 if (!btw) return NULL;
895
896 return new_billterm_dialog (btw, NULL, name);
897}
898#endif
utility functions for the GnuCash UI
Billing Term interface.
double gnc_numeric_to_double(gnc_numeric in)
Convert numeric to floating-point value.
gnc_numeric double_to_gnc_numeric(double in, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
QofBook reference.
Definition qofbook-p.hpp:47