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