GnuCash  4.11-148-gc20d717b33+
dialog-account.c
1 /********************************************************************\
2  * dialog-account.c -- window for creating and editing accounts for *
3  * GnuCash *
4  * Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
5  * Copyright (C) 2003,2005,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 #include <math.h>
30 #ifdef G_OS_WIN32
31 #include <pow.h>
32 #endif
33 #include <string.h>
34 
35 #include "Transaction.h"
36 #include "dialog-account.h"
37 #include "dialog-commodity.h"
38 #include "dialog-utils.h"
39 #include "gnc-amount-edit.h"
40 #include "gnc-general-select.h"
41 #include "gnc-commodity.h"
42 #include "gnc-commodity-edit.h"
43 #include "gnc-component-manager.h"
44 #include "gnc-date-edit.h"
45 #include "gnc-engine.h"
46 #include "gnc-gui-query.h"
47 #include "gnc-session.h"
49 #include "gnc-tree-view-account.h"
50 #include "gnc-ui.h"
51 #include "gnc-ui-util.h"
52 
53 
54 #define DIALOG_NEW_ACCOUNT_CM_CLASS "dialog-new-account"
55 #define DIALOG_EDIT_ACCOUNT_CM_CLASS "dialog-edit-account"
56 #define GNC_PREFS_GROUP "dialogs.account"
57 #define DEFAULT_COLOR "rgb(237,236,235)"
58 
59 enum account_cols
60 {
61  ACCOUNT_COL_FULLNAME = 0,
62  ACCOUNT_COL_FIELDNAME,
63  ACCOUNT_COL_OLD_VALUE,
64  ACCOUNT_COL_NEW_VALUE,
65  NUM_ACCOUNT_COLS
66 };
67 
68 typedef enum
69 {
70  NEW_ACCOUNT,
71  EDIT_ACCOUNT
72 } AccountDialogType;
73 
74 typedef struct _AccountWindow
75 {
76  QofBook *book;
77  gboolean modal;
78  GtkWidget *dialog;
79 
80  AccountDialogType dialog_type;
81 
82  GncGUID account;
83  Account *created_account;
84 
85  gchar **subaccount_names;
86  gchar **next_name;
87 
88  GNCAccountType type;
89 
90  GtkWidget *notebook;
91 
92  GtkWidget *name_entry;
93  GtkWidget *description_entry;
94  GtkWidget *color_entry_button;
95  GtkWidget *color_default_button;
96  GtkWidget *code_entry;
97  GtkTextBuffer *notes_text_buffer;
98 
99  GtkWidget *commodity_edit;
100  dialog_commodity_mode commodity_mode;
101  GtkWidget *account_scu;
102 
103  guint32 valid_types;
104  GNCAccountType preferred_account_type;
105  GtkWidget *type_view;
106  GtkTreeView *parent_tree;
107  GtkWidget *parent_scroll;
108 
109  GtkWidget *opening_balance_button;
110  GtkWidget *opening_balance_edit;
111  GtkWidget *opening_balance_date_edit;
112  GtkWidget *opening_balance_page;
113 
114  GtkWidget *opening_equity_radio;
115  GtkWidget *transfer_account_scroll;
116  GtkWidget *transfer_tree;
117 
118  GtkWidget *tax_related_button;
119  GtkWidget *placeholder_button;
120  GtkWidget *hidden_button;
121  GtkWidget *auto_interest_button;
122 
123  gint component_id;
124 } AccountWindow;
125 
126 typedef struct _RenumberDialog
127 {
128  GtkWidget *dialog;
129  GtkWidget *prefix;
130  GtkWidget *interval;
131  GtkWidget *digits;
132  GtkWidget *example1;
133  GtkWidget *example2;
134 
135  Account *parent;
136  gint num_children;
138 
140 static QofLogModule log_module = GNC_MOD_GUI;
141 
142 static GNCAccountType last_used_account_type = ACCT_TYPE_BANK;
143 
144 static GList *ac_destroy_cb_list = NULL;
145 
147 static void gnc_account_window_set_name (AccountWindow *aw);
148 
149 void gnc_account_renumber_prefix_changed_cb (GtkEditable *editable, RenumberDialog *data);
150 void gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
151 void gnc_account_renumber_digits_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
152 void gnc_account_renumber_response_cb (GtkDialog *dialog, gint response, RenumberDialog *data);
153 
154 void gnc_account_window_destroy_cb (GtkWidget *object, gpointer data);
155 void opening_equity_cb (GtkWidget *w, gpointer data);
156 static void gnc_account_parent_changed_cb (GtkTreeSelection *selection, gpointer data);
157 void gnc_account_name_changed_cb (GtkWidget *widget, gpointer data);
158 void gnc_account_color_default_cb (GtkWidget *widget, gpointer data);
159 void gnc_account_name_insert_text_cb (GtkWidget *entry,
160  const gchar *text,
161  gint length,
162  gint *position,
163  gpointer data);
164 static void set_auto_interest_box (AccountWindow *aw);
165 
168 static void
169 aw_call_destroy_callbacks (Account* acc)
170 {
171  GList *node;
172  void (*cb)(Account*);
173 
174  for (node = ac_destroy_cb_list; node; node = node->next)
175  {
176  cb = node->data;
177  (cb)(acc);
178  }
179 }
180 
181 static Account *
182 aw_get_account (AccountWindow *aw)
183 {
184  if (!aw)
185  return NULL;
186 
187  return xaccAccountLookup (&aw->account, aw->book);
188 }
189 
190 static void
191 gnc_account_commodity_from_type (AccountWindow * aw, gboolean update)
192 {
193  dialog_commodity_mode new_mode;
194 
195  if (aw->type == ACCT_TYPE_TRADING)
196  new_mode = DIAG_COMM_ALL;
197  else if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
199  else
200  new_mode = DIAG_COMM_CURRENCY;
201 
202  if (update && (new_mode != aw->commodity_mode))
203  {
204  gnc_general_select_set_selected (GNC_GENERAL_SELECT(aw->commodity_edit),
205  NULL);
206  }
207  aw->commodity_mode = new_mode;
208 }
209 
210 static void
211 gnc_account_opening_balance_button_update (AccountWindow *aw, gnc_commodity *commodity)
212 {
213  Account *account = aw_get_account (aw);
214  Account *ob_account = gnc_account_lookup_by_opening_balance (gnc_book_get_root_account (aw->book), commodity);
215  gboolean has_splits = (xaccAccountGetSplitList (account) != NULL);
216 
217  if (aw->type != ACCT_TYPE_EQUITY)
218  {
219  gtk_widget_set_sensitive (aw->opening_balance_button, FALSE);
220  return;
221  }
222 
223  /* The opening balance flag can be edited, if the associated feature is enabled and
224  * there is no opening balance account or we are editing the only opening balance account
225  * and it has no splits assigned.
226  */
227  if (!gnc_using_equity_type_opening_balance_account (gnc_get_current_book()))
228  return;
229 
230  switch (aw->dialog_type)
231  {
232  case EDIT_ACCOUNT:
233  gtk_widget_set_sensitive (aw->opening_balance_button, (ob_account == NULL ||
234  ob_account == account) &&
235  has_splits == 0);
236  break;
237  case NEW_ACCOUNT:
238  gtk_widget_set_sensitive (aw->opening_balance_button, ob_account == NULL);
239  break;
240  }
241 }
242 
243 /* Copy the account values to the GUI widgets */
244 static void
245 gnc_account_to_ui (AccountWindow *aw)
246 {
247  Account *account;
248  gnc_commodity * commodity;
249  const char *string;
250  GdkRGBA color;
251  gboolean flag, nonstd_scu;
252  gint index;
253 
254  ENTER("%p", aw);
255  account = aw_get_account (aw);
256  if (!account)
257  {
258  LEAVE("no account");
259  return;
260  }
261 
262  string = xaccAccountGetName (account);
263  if (string == NULL)
264  string = "";
265  gtk_entry_set_text (GTK_ENTRY(aw->name_entry), string);
266 
267  string = xaccAccountGetDescription (account);
268  if (string == NULL)
269  string = "";
270  gtk_entry_set_text (GTK_ENTRY(aw->description_entry), string);
271 
272  string = xaccAccountGetColor (account);
273 
274  if (!string)
275  string = DEFAULT_COLOR;
276 
277  if (!gdk_rgba_parse (&color, string))
278  gdk_rgba_parse (&color, DEFAULT_COLOR);
279 
280  gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER(aw->color_entry_button), &color);
281 
282  commodity = xaccAccountGetCommodity (account);
283  gnc_general_select_set_selected (GNC_GENERAL_SELECT(aw->commodity_edit),
284  commodity);
285  gnc_account_commodity_from_type (aw, FALSE);
286 
287  nonstd_scu = xaccAccountGetNonStdSCU (account);
288  if (nonstd_scu)
289  {
290  index = xaccAccountGetCommoditySCUi (account);
291  index = log10 (index) + 1;
292  }
293  else
294  {
295  index = 0;
296  }
297  gtk_combo_box_set_active (GTK_COMBO_BOX(aw->account_scu), index);
298 
299  string = xaccAccountGetCode (account);
300  if (string == NULL)
301  string = "";
302  gtk_entry_set_text (GTK_ENTRY(aw->code_entry), string);
303 
304  string = xaccAccountGetNotes (account);
305  if (string == NULL)
306  string = "";
307 
308  gtk_text_buffer_set_text (aw->notes_text_buffer, string, strlen(string));
309 
310  gnc_account_opening_balance_button_update (aw, commodity);
311 
312  flag = xaccAccountGetIsOpeningBalance (account);
313  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->opening_balance_button),
314  flag);
315 
316  flag = xaccAccountGetTaxRelated (account);
317  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->tax_related_button),
318  flag);
319 
320  flag = xaccAccountGetPlaceholder (account);
321  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->placeholder_button),
322  flag);
323 
324  flag = xaccAccountGetHidden (account);
325  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->hidden_button),
326  flag);
327 
328  set_auto_interest_box (aw);
329  LEAVE(" ");
330 }
331 
332 static gboolean
333 gnc_account_create_transfer_balance (QofBook *book,
334  Account *account,
335  Account *transfer,
336  gnc_numeric balance,
337  time64 date)
338 {
339  Transaction *trans;
340  Split *split;
341 
342  if (gnc_numeric_zero_p (balance))
343  return TRUE;
344 
345  g_return_val_if_fail (account != NULL, FALSE);
346  g_return_val_if_fail (transfer != NULL, FALSE);
347 
348  xaccAccountBeginEdit (account);
349  xaccAccountBeginEdit (transfer);
350 
351  trans = xaccMallocTransaction (book);
352 
353  xaccTransBeginEdit (trans);
354 
355  xaccTransSetCurrency (trans, gnc_account_or_default_currency (account, NULL));
357  xaccTransSetDescription (trans, _("Opening Balance"));
358 
359  split = xaccMallocSplit (book);
360 
361  xaccTransAppendSplit (trans, split);
362  xaccAccountInsertSplit (account, split);
363 
364  xaccSplitSetAmount (split, balance);
365  xaccSplitSetValue (split, balance);
366 
367  balance = gnc_numeric_neg (balance);
368 
369  split = xaccMallocSplit (book);
370 
371  xaccTransAppendSplit (trans, split);
372  xaccAccountInsertSplit (transfer, split);
373 
374  xaccSplitSetAmount (split, balance);
375  xaccSplitSetValue (split, balance);
376 
377  xaccTransCommitEdit (trans);
378  xaccAccountCommitEdit (transfer);
379  xaccAccountCommitEdit (account);
380 
381  return TRUE;
382 }
383 
384 /* Record the GUI values into the Account structure */
385 static void
386 gnc_ui_to_account (AccountWindow *aw)
387 {
388  Account *account;
389  gnc_commodity *commodity;
390  Account *parent_account;
391  const char *old_string;
392  const char *string;
393  GdkRGBA color;
394  gboolean flag;
395  gnc_numeric balance;
396  gboolean use_equity, nonstd;
397  time64 date;
398  gint index, old_scu, new_scu;
399  GtkTextIter start, end;
400 
401  account = aw_get_account (aw);
402  if (!account)
403  {
404  LEAVE("no account");
405  return;
406  }
407 
408  if (aw->dialog_type == EDIT_ACCOUNT
409  && aw->type != xaccAccountGetType (account))
410  {
411  /* Just refreshing won't work. */
412  aw_call_destroy_callbacks (account);
413  }
414 
415  xaccAccountBeginEdit (account);
416 
417  if (aw->type != xaccAccountGetType (account))
418  xaccAccountSetType (account, aw->type);
419 
420  last_used_account_type = aw->type;
421 
422  string = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
423  old_string = xaccAccountGetName (account);
424  if (g_strcmp0 (string, old_string) != 0)
425  xaccAccountSetName (account, string);
426 
427  string = gtk_entry_get_text (GTK_ENTRY(aw->description_entry));
428  old_string = xaccAccountGetDescription (account);
429  if (g_strcmp0 (string, old_string) != 0)
430  xaccAccountSetDescription (account, string);
431 
432  gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER(aw->color_entry_button), &color);
433  string = gdk_rgba_to_string (&color);
434 
435  if (g_strcmp0 (string, DEFAULT_COLOR) == 0)
436  string = NULL;
437 
438  old_string = xaccAccountGetColor (account);
439 
440  if (!string && old_string)
441  xaccAccountSetColor (account, ""); // remove entry
442  else
443  {
444  if (g_strcmp0 (string, old_string) != 0)
445  xaccAccountSetColor (account, string); // update entry
446  }
447 
448  commodity = (gnc_commodity *)
449  gnc_general_select_get_selected (GNC_GENERAL_SELECT(aw->commodity_edit));
450  if (commodity &&
451  !gnc_commodity_equiv (commodity, xaccAccountGetCommodity (account)))
452  {
453  xaccAccountSetCommodity (account, commodity);
454  old_scu = 0;
455  }
456  else
457  {
458  old_scu = xaccAccountGetCommoditySCU (account);
459  }
460 
461  index = gtk_combo_box_get_active (GTK_COMBO_BOX(aw->account_scu));
462  nonstd = (index != 0);
463  if (nonstd != xaccAccountGetNonStdSCU (account))
464  xaccAccountSetNonStdSCU (account, nonstd);
465  new_scu = (nonstd ? pow (10, index - 1) : gnc_commodity_get_fraction (commodity));
466  if (old_scu != new_scu)
467  xaccAccountSetCommoditySCU (account, new_scu);
468 
469  string = gtk_entry_get_text (GTK_ENTRY(aw->code_entry));
470  old_string = xaccAccountGetCode (account);
471  if (g_strcmp0 (string, old_string) != 0)
472  xaccAccountSetCode (account, string);
473 
474  gtk_text_buffer_get_start_iter (aw->notes_text_buffer, &start);
475  gtk_text_buffer_get_end_iter (aw->notes_text_buffer, &end);
476  string = gtk_text_buffer_get_text (aw->notes_text_buffer, &start, &end, FALSE);
477  old_string = xaccAccountGetNotes (account);
478  if (null_strcmp (string, old_string) != 0)
479  xaccAccountSetNotes (account, string);
480 
481  flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->opening_balance_button));
482  if (xaccAccountGetIsOpeningBalance (account) != flag)
483  xaccAccountSetIsOpeningBalance (account, flag);
484 
485  flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->tax_related_button));
486  if (xaccAccountGetTaxRelated (account) != flag)
487  xaccAccountSetTaxRelated (account, flag);
488 
489  flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->placeholder_button));
490  if (xaccAccountGetPlaceholder (account) != flag)
491  xaccAccountSetPlaceholder (account, flag);
492 
493  flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->hidden_button));
494  if (xaccAccountGetHidden (account) != flag)
495  xaccAccountSetHidden (account, flag);
496 
497  flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->auto_interest_button));
498  if (xaccAccountGetAutoInterest (account) != flag)
499  xaccAccountSetAutoInterest (account, flag);
500 
501  parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(aw->parent_tree));
502 
503  if (parent_account == NULL)
504  parent_account = gnc_book_get_root_account (aw->book);
505  if (parent_account != gnc_account_get_parent (account))
506  gnc_account_append_child (parent_account, account);
507 
508  xaccAccountCommitEdit (account);
509 
510  balance = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT(aw->opening_balance_edit));
511 
512  if (gnc_numeric_zero_p (balance))
513  {
514  LEAVE("zero balance");
515  return;
516  }
517 
518  if (gnc_reverse_balance (account))
519  balance = gnc_numeric_neg (balance);
520 
521  date = gnc_date_edit_get_date (GNC_DATE_EDIT(aw->opening_balance_date_edit));
522 
523  use_equity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(aw->opening_equity_radio));
524 
525  if (use_equity)
526  {
527  if (!gnc_account_create_opening_balance (account, balance, date, aw->book))
528  {
529  const char *message = _("Could not create opening balance.");
530  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
531  }
532  }
533  else
534  {
535  Account *transfer = NULL;
536 
537  transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(aw->transfer_tree));
538  if (!transfer)
539  {
540  LEAVE("no transfer account");
541  return;
542  }
543 
544  gnc_account_create_transfer_balance (aw->book, account, transfer, balance, date);
545  }
546  LEAVE(" ");
547 }
548 
549 static void
550 set_children_types (Account *account, GNCAccountType type)
551 {
552  GList *children, *iter;
553 
554  children = gnc_account_get_children (account);
555  if (children == NULL)
556  return;
557 
558  for (iter = children; iter; iter = iter->next)
559  {
560  account = iter->data;
561  if (type == xaccAccountGetType (account))
562  continue;
563 
564  /* Just refreshing won't work. */
565  aw_call_destroy_callbacks (account);
566 
567  xaccAccountBeginEdit (account);
568  xaccAccountSetType (account, type);
569  xaccAccountCommitEdit (account);
570 
571  set_children_types (account, type);
572  }
573  g_list_free (children);
574 }
575 
576 static void
577 make_children_compatible (AccountWindow *aw)
578 {
579  Account *account;
580 
581  g_return_if_fail (aw);
582 
583  if (aw->dialog_type == NEW_ACCOUNT)
584  return;
585 
586  account = aw_get_account (aw);
587  g_return_if_fail (account);
588 
589  if (xaccAccountTypesCompatible (aw->type, xaccAccountGetType (account)))
590  return;
591 
592  set_children_types (account, aw->type);
593 }
594 
595 static void
596 gnc_finish_ok (AccountWindow *aw)
597 {
598  ENTER("aw %p", aw);
599  gnc_suspend_gui_refresh ();
600 
601  /* make the account changes */
602  make_children_compatible (aw);
603  gnc_ui_to_account (aw);
604 
605  gnc_resume_gui_refresh ();
606 
607  /* do it all again, if needed */
608  if ((aw->dialog_type == NEW_ACCOUNT) && aw->next_name && *aw->next_name)
609  {
610  gnc_commodity *commodity;
611  Account *parent;
612  Account *account;
613  GtkTreeSelection *selection;
614 
615  /* Drop the old parent_tree so we can update it with an up to date one */
616  gtk_container_remove (GTK_CONTAINER(aw->parent_scroll), GTK_WIDGET(aw->parent_tree));
617  aw->parent_tree = gnc_tree_view_account_new (TRUE);
618  gtk_container_add (GTK_CONTAINER(aw->parent_scroll), GTK_WIDGET(aw->parent_tree));
619  gtk_widget_show (GTK_WIDGET(aw->parent_tree));
620 
621  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->parent_tree));
622  g_signal_connect (G_OBJECT(selection), "changed",
623  G_CALLBACK(gnc_account_parent_changed_cb), aw);
624 
625  gnc_suspend_gui_refresh ();
626 
627  parent = aw_get_account (aw);
628  account = xaccMallocAccount (aw->book);
629  aw->account = *xaccAccountGetGUID (account);
630  aw->type = xaccAccountGetType (parent);
631 
632  xaccAccountSetName (account, *aw->next_name);
633  aw->next_name++;
634 
635  gnc_account_to_ui (aw);
636 
637  gnc_account_window_set_name (aw);
638 
639  commodity = xaccAccountGetCommodity (parent);
640  gnc_general_select_set_selected (GNC_GENERAL_SELECT(aw->commodity_edit),
641  commodity);
642  gnc_account_commodity_from_type (aw, FALSE);
643 
644  gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(
645  aw->parent_tree),
646  parent);
647 
648  gnc_resume_gui_refresh ();
649  LEAVE("1");
650  return;
651  }
652 
653  /* save for posterity */
654  aw->created_account = aw_get_account (aw);
655 
656  /* so it doesn't get freed on close */
657  aw->account = *guid_null ();
658 
659  gnc_close_gui_component (aw->component_id);
660  LEAVE("2");
661 }
662 
663 static void
664 add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data)
665 {
666  GtkExpander *expander = GTK_EXPANDER(object);
667  Account *account = data;
668  GtkWidget *scrolled_window;
669  GtkTreeView *view;
670 
671  if (gtk_expander_get_expanded (expander) &&
672  !gtk_bin_get_child (GTK_BIN(expander)))
673  {
674  view = gnc_tree_view_account_new_with_root (account, FALSE);
675 
676  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
677  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled_window),
678  GTK_POLICY_AUTOMATIC,
679  GTK_POLICY_AUTOMATIC);
680  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window),
681  GTK_SHADOW_IN);
682  gtk_container_add (GTK_CONTAINER(scrolled_window), GTK_WIDGET(view));
683 
684  gtk_container_add (GTK_CONTAINER(expander), scrolled_window);
685  gtk_widget_set_vexpand (GTK_WIDGET(scrolled_window), TRUE);
686  gtk_widget_show_all (scrolled_window);
687  }
688 }
689 
690 /* Check whether there are children needing a type adjustment because of a
691  a change to an incompatible type (like after some reparenting) and let the
692  user decide whether he wants that */
693 static gboolean
694 verify_children_compatible (AccountWindow *aw)
695 {
696  Account *account;
697  GtkWidget *dialog, *vbox, *hbox, *label, *expander;
698  gchar *str;
699  gboolean result;
700 
701  if (aw == NULL)
702  return FALSE;
703 
704  account = aw_get_account (aw);
705  if (!account)
706  return FALSE;
707 
708  if (xaccAccountTypesCompatible (aw->type, xaccAccountGetType (account)))
709  return TRUE;
710 
711  if (gnc_account_n_children (account) == 0)
712  return TRUE;
713 
714  dialog = gtk_dialog_new_with_buttons ("",
715  GTK_WINDOW(aw->dialog),
716  GTK_DIALOG_DESTROY_WITH_PARENT |
717  GTK_DIALOG_MODAL,
718  _("_Cancel"), GTK_RESPONSE_CANCEL,
719  _("_OK"), GTK_RESPONSE_OK,
720  NULL);
721 
722  gtk_window_set_skip_taskbar_hint (GTK_WINDOW(dialog), TRUE);
723 
724  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
725  gtk_box_set_homogeneous (GTK_BOX(hbox), FALSE);
726  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
727  gtk_box_set_homogeneous (GTK_BOX(vbox), FALSE);
728 
729  gtk_box_pack_start (GTK_BOX(hbox),
730  gtk_image_new_from_icon_name ("dialog-information",
731  GTK_ICON_SIZE_DIALOG), FALSE, FALSE, 0);
732 
733  /* primary label */
734  label = gtk_label_new (_("Give the children the same type?"));
735  gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
736  gtk_label_set_selectable (GTK_LABEL(label), TRUE);
737  gnc_label_set_alignment (label, 0.0, 0.0);
738 
739  /* make label large */
740  gnc_widget_style_context_add_class (GTK_WIDGET(label), "gnc-class-title");
741 
742  gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
743 
744  /* secondary label */
745  str = g_strdup_printf (_("The children of the edited account have to be "
746  "changed to type \"%s\" to make them compatible."),
747  xaccAccountGetTypeStr (aw->type));
748  label = gtk_label_new (str);
749  g_free (str);
750  gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
751  gtk_label_set_selectable (GTK_LABEL(label), TRUE);
752  gnc_label_set_alignment (label, 0.0, 0.0);
753  gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
754 
755  /* children */
756  expander = gtk_expander_new_with_mnemonic (_("_Show children accounts"));
757  gtk_expander_set_spacing (GTK_EXPANDER(expander), 6);
758  g_signal_connect (G_OBJECT(expander), "notify::expanded",
759  G_CALLBACK(add_children_to_expander), account);
760  gtk_box_pack_start (GTK_BOX(vbox), expander, TRUE, TRUE, 0);
761 
762  gtk_box_pack_start (GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
763 
764  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area (GTK_DIALOG(dialog))),
765  hbox, TRUE, TRUE, 0);
766 
767  /* spacings */
768  gtk_container_set_border_width (GTK_CONTAINER(dialog), 5);
769  gtk_container_set_border_width (GTK_CONTAINER(hbox), 5);
770  gtk_box_set_spacing (GTK_BOX(gtk_dialog_get_content_area (GTK_DIALOG(dialog))), 14);
771 
772  gtk_widget_show_all (hbox);
773 
774  gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
775 
776  result = (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
777 
778  gtk_widget_destroy (dialog);
779 
780  return result;
781 }
782 
783 static gboolean
784 gnc_filter_parent_accounts (Account *account, gpointer data)
785 {
786  AccountWindow *aw = data;
787  Account *aw_account = aw_get_account (aw);
788 
789  if (account == NULL)
790  return FALSE;
791 
792  if (aw_account == NULL)
793  return FALSE;
794 
795  if (gnc_account_is_root (account))
796  return TRUE;
797 
798  if (account == aw_account)
799  return FALSE;
800 
801  if (xaccAccountHasAncestor (account, aw_account))
802  return FALSE;
803 
804  return TRUE;
805 }
806 
807 static gboolean
808 gnc_common_ok (AccountWindow *aw)
809 {
810  Account *root, *account, *parent;
811  gnc_commodity * commodity;
812  gchar *fullname, *fullname_parent;
813  const gchar *name, *separator;
814 
815  ENTER("aw %p", aw);
816  root = gnc_book_get_root_account (aw->book);
817 
818  separator = gnc_get_account_separator_string ();
819 
820  /* check for valid name */
821  name = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
822  if (g_strcmp0 (name, "") == 0)
823  {
824  const char *message = _("The account must be given a name.");
825  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
826  LEAVE("bad name");
827  return FALSE;
828  }
829 
830  /* check for a duplicate name */
832  (GNC_TREE_VIEW_ACCOUNT(aw->parent_tree));
833  if (parent == NULL)
834  {
835  account = gnc_account_lookup_by_full_name (root, name);
836  }
837  else
838  {
839  fullname_parent = gnc_account_get_full_name (parent);
840  fullname = g_strconcat (fullname_parent, separator, name, NULL);
841 
842  account = gnc_account_lookup_by_full_name (root, fullname);
843 
844  g_free (fullname_parent);
845  g_free (fullname);
846  }
847  if ((account != NULL) &&
848  !guid_equal (&aw->account, xaccAccountGetGUID (account)))
849  {
850  const char *message = _("There is already an account with that name.");
851  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
852  LEAVE("duplicate name");
853  return FALSE;
854  }
855 
856  /* Parent check, probably not needed, but be safe */
857  if (!gnc_filter_parent_accounts (parent, aw))
858  {
859  const char *message = _("You must choose a valid parent account.");
860  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
861  LEAVE("invalid parent");
862  return FALSE;
863  }
864 
865  /* check for valid type */
866  if (aw->type == ACCT_TYPE_INVALID)
867  {
868  const char *message = _("You must select an account type.");
869  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
870  LEAVE("invalid type");
871  return FALSE;
872  }
873 
874  /* check whether the types of child and parent are compatible */
875  if (!xaccAccountTypesCompatible (xaccAccountGetType (parent), aw->type))
876  {
877  const char *message = _("The selected account type is incompatible with "
878  "the one of the selected parent.");
879  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
880  LEAVE("incompatible types");
881  return FALSE;
882  }
883 
884  /* check for commodity */
885  commodity = (gnc_commodity *)
886  gnc_general_select_get_selected (GNC_GENERAL_SELECT(aw->commodity_edit));
887  if (!commodity)
888  {
889  const char *message = _("You must choose a commodity.");
890  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
891  LEAVE("invalid commodity");
892  return FALSE;
893  }
894 
895  LEAVE("passed");
896  return TRUE;
897 }
898 
899 static void
900 gnc_edit_account_ok (AccountWindow *aw)
901 {
902  Account *account;
903 
904  ENTER("aw %p", aw);
905 
906  account = aw_get_account (aw);
907  if (!account)
908  {
909  LEAVE(" ");
910  return;
911  }
912 
913  if (!gnc_common_ok (aw))
914  {
915  LEAVE(" ");
916  return;
917  }
918 
919  if (!verify_children_compatible (aw))
920  {
921  LEAVE(" ");
922  return;
923  }
924 
925  gnc_finish_ok (aw);
926  LEAVE(" ");
927 }
928 
929 static void
930 gnc_new_account_ok (AccountWindow *aw)
931 {
932  gnc_numeric balance;
933 
934  ENTER("aw %p", aw);
935 
936  if (!gnc_common_ok (aw))
937  {
938  LEAVE(" ");
939  return;
940  }
941 
942  if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT(aw->opening_balance_edit), NULL))
943  {
944  const char *message = _("You must enter a valid opening balance "
945  "or leave it blank.");
946  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
947  LEAVE(" ");
948  return;
949  }
950 
951  balance = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT(aw->opening_balance_edit));
952 
953  if (!gnc_numeric_zero_p (balance))
954  {
955  gboolean use_equity;
956 
957  use_equity = gtk_toggle_button_get_active
958  (GTK_TOGGLE_BUTTON(aw->opening_equity_radio));
959 
960  if (!use_equity)
961  {
962  Account *transfer = NULL;
963 
964  transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(
965  aw->transfer_tree));
966  if (!transfer)
967  {
968  const char *message = _("You must select a transfer account or choose"
969  " the opening balances equity account.");
970  gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
971  LEAVE(" ");
972  return;
973  }
974  }
975  }
976 
977  gnc_finish_ok (aw);
978  LEAVE(" ");
979 }
980 
981 static void
982 gnc_account_window_response_cb (GtkDialog *dialog,
983  gint response,
984  gpointer data)
985 {
986  AccountWindow *aw = data;
987 
988  ENTER("dialog %p, response %d, aw %p", dialog, response, aw);
989  switch (response)
990  {
991  case GTK_RESPONSE_OK:
992  switch (aw->dialog_type)
993  {
994  case NEW_ACCOUNT:
995  DEBUG("new acct dialog, OK");
996  gnc_new_account_ok (aw);
997  break;
998  case EDIT_ACCOUNT:
999  DEBUG("edit acct dialog, OK");
1000  gnc_edit_account_ok (aw);
1001  break;
1002  default:
1003  g_assert_not_reached ();
1004  return;
1005  }
1006  break;
1007  case GTK_RESPONSE_HELP:
1008  switch (aw->dialog_type)
1009  {
1010  case NEW_ACCOUNT:
1011  DEBUG("new acct dialog, HELP");
1012  gnc_gnome_help (GTK_WINDOW(dialog), HF_HELP, HL_ACC);
1013  break;
1014  case EDIT_ACCOUNT:
1015  DEBUG("edit acct dialog, HELP");
1016  gnc_gnome_help (GTK_WINDOW(dialog), HF_HELP, HL_ACCEDIT);
1017  break;
1018  default:
1019  g_assert_not_reached ();
1020  return;
1021  }
1022  break;
1023  case GTK_RESPONSE_CANCEL:
1024  default:
1025  DEBUG("CANCEL");
1026  gnc_close_gui_component (aw->component_id);
1027  break;
1028  }
1029  LEAVE(" ");
1030 }
1031 
1032 void
1033 gnc_account_window_destroy_cb (GtkWidget *object, gpointer data)
1034 {
1035  AccountWindow *aw = data;
1036  Account *account;
1037 
1038  ENTER("object %p, aw %p", object, aw);
1039  account = aw_get_account (aw);
1040 
1041  gnc_suspend_gui_refresh ();
1042 
1043  switch (aw->dialog_type)
1044  {
1045  case NEW_ACCOUNT:
1046  if (account != NULL)
1047  {
1048  xaccAccountBeginEdit (account);
1049  xaccAccountDestroy (account);
1050  aw->account = *guid_null ();
1051  }
1052 
1053  DEBUG ("account add window destroyed\n");
1054  break;
1055 
1056  case EDIT_ACCOUNT:
1057  break;
1058 
1059  default:
1060  PERR ("unexpected dialog type\n");
1061  gnc_resume_gui_refresh ();
1062  LEAVE(" ");
1063  return;
1064  }
1065 
1066  gnc_unregister_gui_component (aw->component_id);
1067 
1068  gnc_resume_gui_refresh ();
1069 
1070  if (aw->subaccount_names)
1071  {
1072  g_strfreev (aw->subaccount_names);
1073  aw->subaccount_names = NULL;
1074  aw->next_name = NULL;
1075  }
1076 
1077  g_free (aw);
1078  LEAVE(" ");
1079 }
1080 
1081 static void
1082 gnc_account_parent_changed_cb (GtkTreeSelection *selection, gpointer data)
1083 {
1084  AccountWindow *aw = data;
1085  Account *parent_account;
1086  guint32 types, old_types;
1087  GtkTreeModel *type_model;
1088  GtkTreeSelection *type_selection;
1089  gboolean scroll_to = FALSE;
1090 
1091  g_return_if_fail (aw);
1092 
1094  GNC_TREE_VIEW_ACCOUNT(aw->parent_tree));
1095  if (!parent_account)
1096  return;
1097 
1098  if (gnc_account_is_root (parent_account))
1099  {
1100  types = aw->valid_types;
1101  }
1102  else
1103  {
1104  types = aw->valid_types &
1106  }
1107 
1108  type_model = gtk_tree_view_get_model (GTK_TREE_VIEW(aw->type_view));
1109  if (!type_model)
1110  return;
1111 
1112  if (aw->type != aw->preferred_account_type &&
1113  (types & (1 << aw->preferred_account_type)) != 0)
1114  {
1115  /* we can change back to the preferred account type */
1116  aw->type = aw->preferred_account_type;
1117  scroll_to = TRUE;
1118  }
1119  else if ((types & (1 << aw->type)) == 0)
1120  {
1121  /* our type is invalid now */
1122  aw->type = ACCT_TYPE_INVALID;
1123  }
1124  else
1125  {
1126  /* no type change, but maybe list of valid types changed */
1127  old_types = gnc_tree_model_account_types_get_mask (type_model);
1128  if (old_types != types)
1129  scroll_to = TRUE;
1130  }
1131 
1132  gnc_tree_model_account_types_set_mask (type_model, types);
1133 
1134  if (scroll_to)
1135  {
1136  type_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->type_view));
1137  gnc_tree_model_account_types_set_selection (type_selection, 1 << aw->type);
1138  }
1139 
1140  gnc_account_window_set_name (aw);
1141 }
1142 
1143 static void
1144 set_auto_interest_box(AccountWindow *aw)
1145 {
1146  Account* account = aw_get_account (aw);
1147  gboolean type_ok = account_type_has_auto_interest_xfer (aw->type);
1148  gboolean pref_set = xaccAccountGetAutoInterest (account);
1149  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->auto_interest_button),
1150  type_ok && pref_set);
1151  gtk_widget_set_sensitive (GTK_WIDGET(aw->auto_interest_button), type_ok);
1152 }
1153 
1154 static void
1155 gnc_account_type_changed_cb (GtkTreeSelection *selection, gpointer data)
1156 {
1157  AccountWindow *aw = data;
1158  gboolean sensitive;
1159  GNCAccountType type_id;
1160 
1161  g_return_if_fail (aw != NULL);
1162 
1163  sensitive = FALSE;
1164 
1165  type_id = gnc_tree_model_account_types_get_selection_single (selection);
1166  if (type_id == ACCT_TYPE_NONE)
1167  {
1168  aw->type = ACCT_TYPE_INVALID;
1169  }
1170  else
1171  {
1172  aw->type = type_id;
1173  aw->preferred_account_type = type_id;
1174 
1175  gnc_account_commodity_from_type (aw, TRUE);
1176 
1177  sensitive = (aw->type != ACCT_TYPE_EQUITY &&
1178  aw->type != ACCT_TYPE_CURRENCY &&
1179  aw->type != ACCT_TYPE_STOCK &&
1180  aw->type != ACCT_TYPE_MUTUAL &&
1181  aw->type != ACCT_TYPE_TRADING);
1182  }
1183 
1184  gtk_widget_set_sensitive (aw->opening_balance_page, sensitive);
1185 
1186  if (!sensitive)
1187  {
1188  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(aw->opening_balance_edit),
1189  gnc_numeric_zero ());
1190  }
1191  set_auto_interest_box (aw);
1192 }
1193 
1194 static void
1195 gnc_account_type_view_create (AccountWindow *aw, guint32 compat_types)
1196 {
1197  GtkTreeModel *model;
1198  GtkTreeSelection *selection;
1199  GtkCellRenderer *renderer;
1200  GtkTreeView *view;
1201 
1202  aw->valid_types &= compat_types;
1203  if (aw->valid_types == 0)
1204  {
1205  /* no type restrictions, choose aw->type */
1206  aw->valid_types = compat_types | (1 << aw->type);
1207  aw->preferred_account_type = aw->type;
1208  }
1209  else if ((aw->valid_types & (1 << aw->type)) != 0)
1210  {
1211  /* aw->type is valid */
1212  aw->preferred_account_type = aw->type;
1213  }
1214  else if ((aw->valid_types & (1 << last_used_account_type)) != 0)
1215  {
1216  /* last used account type is valid */
1217  aw->type = last_used_account_type;
1218  aw->preferred_account_type = last_used_account_type;
1219  }
1220  else
1221  {
1222  /* choose first valid account type */
1223  int i;
1224  aw->preferred_account_type = aw->type;
1225  aw->type = ACCT_TYPE_INVALID;
1226  for (i = 0; i < 32; i++)
1227  if ((aw->valid_types & (1 << i)) != 0)
1228  {
1229  aw->type = i;
1230  break;
1231  }
1232  }
1233 
1234  model = gnc_tree_model_account_types_filter_using_mask (aw->valid_types);
1235 
1236  view = GTK_TREE_VIEW(aw->type_view);
1237  gtk_tree_view_set_model (view, model);
1238  g_object_unref (G_OBJECT(model));
1239 
1240  renderer = gtk_cell_renderer_text_new ();
1241  gtk_tree_view_insert_column_with_attributes (view, -1, NULL, renderer, "text",
1242  GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME,
1243  NULL);
1244  gtk_tree_view_set_search_column (view, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME);
1245 
1246  selection = gtk_tree_view_get_selection (view);
1247  g_signal_connect (G_OBJECT(selection), "changed",
1248  G_CALLBACK(gnc_account_type_changed_cb), aw);
1249 
1250  gnc_tree_model_account_types_set_selection (selection, 1 << aw->type);
1251 }
1252 
1253 void
1254 gnc_account_name_insert_text_cb (GtkWidget *entry,
1255  const gchar *text,
1256  gint length,
1257  gint *position,
1258  gpointer data)
1259 {
1260  GtkEditable *editable = GTK_EDITABLE(entry);
1261  const gchar *separator = NULL;
1262  gchar **strsplit;
1263 
1264  separator = gnc_get_account_separator_string ();
1265  strsplit = g_strsplit (text, separator, 0);
1266  if (strsplit[1] != NULL)
1267  {
1268  gchar *result = g_strjoinv (NULL, strsplit);
1269  g_signal_handlers_block_by_func (G_OBJECT(editable),
1270  G_CALLBACK(gnc_account_name_insert_text_cb),
1271  data);
1272  gtk_editable_insert_text (editable, result, g_utf8_strlen (result, -1), position);
1273  g_signal_handlers_unblock_by_func (G_OBJECT(editable),
1274  G_CALLBACK(gnc_account_name_insert_text_cb),
1275  data);
1276  g_signal_stop_emission_by_name (G_OBJECT(editable), "insert_text");
1277  g_free (result);
1278  }
1279 
1280  g_strfreev (strsplit);
1281 }
1282 
1283 void
1284 gnc_account_name_changed_cb (GtkWidget *widget, gpointer data)
1285 {
1286  AccountWindow *aw = data;
1287 
1288  gnc_account_window_set_name (aw);
1289 }
1290 
1291 void
1292 gnc_account_color_default_cb (GtkWidget *widget, gpointer data)
1293 {
1294  GdkRGBA color;
1295  AccountWindow *aw = data;
1296 
1297  gdk_rgba_parse (&color, DEFAULT_COLOR);
1298  gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER(aw->color_entry_button), &color);
1299 
1300 }
1301 
1302 static void
1303 commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
1304 {
1305  AccountWindow *aw = data;
1306  gnc_commodity *currency;
1307  GtkTreeSelection *selection;
1308  Account *account = aw_get_account (aw);
1309 
1310  currency = (gnc_commodity *) gnc_general_select_get_selected (gsl);
1311  if (!currency)
1312  return;
1313 
1314  if (xaccAccountGetIsOpeningBalance (account))
1315  {
1316  Account *ob_account = gnc_account_lookup_by_opening_balance (gnc_book_get_root_account (aw->book), currency);
1317  if (ob_account != account)
1318  {
1319  gchar *dialog_msg = _("An account with opening balance already exists for the desired currency.");
1320  gchar *dialog_title = _("Cannot change currency");
1321  GtkWidget *dialog = gtk_message_dialog_new (gnc_ui_get_main_window (NULL),
1322  0,
1323  GTK_MESSAGE_ERROR,
1324  GTK_BUTTONS_OK,
1325  "%s", dialog_title);
1326  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
1327  "%s", dialog_msg);
1328  gtk_dialog_run (GTK_DIALOG(dialog));
1329  gtk_widget_destroy (dialog);
1330  g_signal_handlers_block_by_func (gsl, commodity_changed_cb, data);
1331  gnc_general_select_set_selected (gsl, xaccAccountGetCommodity (account));
1332  g_signal_handlers_unblock_by_func (gsl, commodity_changed_cb, data);
1333  return;
1334  }
1335  }
1336 
1337  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT(aw->opening_balance_edit),
1338  gnc_commodity_get_fraction (currency));
1339  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT(aw->opening_balance_edit),
1340  gnc_commodity_print_info (currency, FALSE));
1341 
1342  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->transfer_tree));
1343  gtk_tree_selection_unselect_all (selection);
1344  gnc_account_opening_balance_button_update (aw, currency);
1345 }
1346 
1347 static gboolean
1348 account_commodity_filter (GtkTreeSelection *selection,
1349  GtkTreeModel *unused_model,
1350  GtkTreePath *s_path,
1351  gboolean path_currently_selected,
1352  gpointer user_data)
1353 {
1354  gnc_commodity *commodity;
1355  AccountWindow *aw;
1356  Account *account;
1357 
1358  g_return_val_if_fail (GTK_IS_TREE_SELECTION(selection), FALSE);
1359 
1360  aw = user_data;
1361 
1362  if (path_currently_selected)
1363  {
1364  /* already selected, don't waste time. */
1365  return TRUE;
1366  }
1367 
1368  account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT(aw->transfer_tree), s_path);
1369  if (!account)
1370  {
1371  return FALSE;
1372  }
1373 
1374  commodity = (gnc_commodity *)
1375  gnc_general_select_get_selected (GNC_GENERAL_SELECT(aw->commodity_edit));
1376 
1377  return gnc_commodity_equiv (xaccAccountGetCommodity (account), commodity);
1378 }
1379 
1380 void
1381 opening_equity_cb (GtkWidget *w, gpointer data)
1382 {
1383  AccountWindow *aw = data;
1384  gboolean use_equity;
1385 
1386  use_equity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(w));
1387 
1388  gtk_widget_set_sensitive (aw->transfer_account_scroll, !use_equity);
1389 }
1390 
1391 /********************************************************************\
1392  * gnc_account_window_create *
1393  * creates a window to create a new account. *
1394  * *
1395  * Args: parent - the parent window dialog *
1396  * Args: aw - the information structure for this window *
1397  * Return: the created window *
1398  \*******************************************************************/
1399 static void
1400 gnc_account_window_create (GtkWindow *parent, AccountWindow *aw)
1401 {
1402  GtkWidget *amount;
1403  GtkWidget *date_edit;
1404  GObject *awo;
1405  GtkWidget *box;
1406  GtkWidget *label;
1407  GtkBuilder *builder;
1408  GtkTreeSelection *selection;
1409  const gchar *tt = _("This Account contains Transactions.\nChanging this option is not possible.");
1410  guint32 compat_types = xaccAccountTypesValid ();
1411 
1412  ENTER("aw %p, modal %d", aw, aw->modal);
1413  builder = gtk_builder_new ();
1414  gnc_builder_add_from_file (builder, "dialog-account.glade", "fraction_liststore");
1415  gnc_builder_add_from_file (builder, "dialog-account.glade", "account_dialog");
1416 
1417  aw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_dialog"));
1418  awo = G_OBJECT(aw->dialog);
1419 
1420  if (parent)
1421  gtk_window_set_transient_for (GTK_WINDOW(aw->dialog), parent);
1422 
1423  // Set the name for this dialog so it can be easily manipulated with css
1424  gtk_widget_set_name (GTK_WIDGET(aw->dialog), "gnc-id-account");
1425  gnc_widget_style_context_add_class (GTK_WIDGET(aw->dialog), "gnc-class-account");
1426 
1427 
1428  g_object_set_data (awo, "dialog_info", aw);
1429 
1430  if (!aw->modal)
1431  g_signal_connect (awo, "response",
1432  G_CALLBACK(gnc_account_window_response_cb), aw);
1433  else
1434  gtk_window_set_modal (GTK_WINDOW(aw->dialog), TRUE);
1435 
1436  aw->notebook = GTK_WIDGET(gtk_builder_get_object (builder, "account_notebook"));
1437  aw->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
1438  aw->description_entry = GTK_WIDGET(gtk_builder_get_object (builder, "description_entry"));
1439  aw->color_entry_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_entry_button"));
1440  aw->color_default_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_default_button"));
1441  aw->code_entry = GTK_WIDGET(gtk_builder_get_object (builder, "code_entry"));
1442  aw->notes_text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(GTK_WIDGET(
1443  gtk_builder_get_object (builder,
1444  "notes_text"))));
1445 
1446  box = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_hbox"));
1447  aw->commodity_edit = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
1448  gnc_commodity_edit_get_string,
1449  gnc_commodity_edit_new_select,
1450  &aw->commodity_mode);
1451 
1452  // If the account has transactions, prevent changes by displaying a label and tooltip
1453  if (xaccAccountGetSplitList (aw_get_account (aw)) != NULL)
1454  {
1455  const gchar *sec_name = gnc_commodity_get_printname (xaccAccountGetCommodity (
1456  aw_get_account (aw)));
1457  GtkWidget *label = gtk_label_new (sec_name);
1458  gtk_widget_set_tooltip_text (label, tt);
1459  gtk_box_pack_start (GTK_BOX(box), label, FALSE, FALSE, 0);
1460  gtk_widget_show (label);
1461  }
1462  else
1463  {
1464  gtk_box_pack_start (GTK_BOX(box), aw->commodity_edit, TRUE, TRUE, 0);
1465  gtk_widget_show (aw->commodity_edit);
1466  }
1467 
1468  label = GTK_WIDGET(gtk_builder_get_object (builder, "security_label"));
1469  gnc_general_select_make_mnemonic_target (GNC_GENERAL_SELECT(aw->commodity_edit), label);
1470 
1471  g_signal_connect (G_OBJECT(aw->commodity_edit), "changed",
1472  G_CALLBACK(commodity_changed_cb), aw);
1473 
1474  aw->account_scu = GTK_WIDGET(gtk_builder_get_object (builder, "account_scu"));
1475 
1476  aw->parent_scroll = GTK_WIDGET(gtk_builder_get_object (builder, "parent_scroll"));
1477 
1478  aw->parent_tree = gnc_tree_view_account_new (TRUE);
1479  gtk_container_add (GTK_CONTAINER(aw->parent_scroll), GTK_WIDGET(aw->parent_tree));
1480  gtk_widget_show (GTK_WIDGET(aw->parent_tree));
1481  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->parent_tree));
1482 
1483  g_signal_connect (G_OBJECT(selection), "changed",
1484  G_CALLBACK(gnc_account_parent_changed_cb), aw);
1485 
1486  aw->opening_balance_button = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_button"));
1487  aw->tax_related_button = GTK_WIDGET(gtk_builder_get_object (builder, "tax_related_button"));
1488  aw->placeholder_button = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_button"));
1489  aw->hidden_button = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_button"));
1490  aw->auto_interest_button = GTK_WIDGET(gtk_builder_get_object (builder, "auto_interest_button"));
1491  set_auto_interest_box (aw);
1492 
1493 
1494  box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_box"));
1495  amount = gnc_amount_edit_new ();
1496  aw->opening_balance_edit = amount;
1497  gtk_box_pack_start (GTK_BOX(box), amount, TRUE, TRUE, 0);
1498  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT(amount), TRUE);
1499  gtk_widget_show (amount);
1500 
1501  label = GTK_WIDGET(gtk_builder_get_object (builder, "balance_label"));
1502  gnc_amount_edit_make_mnemonic_target (GNC_AMOUNT_EDIT(amount), label);
1503 
1504  box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_date_box"));
1505  label = GTK_WIDGET(gtk_builder_get_object (builder, "date_label"));
1506  date_edit = gnc_date_edit_new (gnc_time (NULL), 0, 0);
1507  gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date_edit), label);
1508  aw->opening_balance_date_edit = date_edit;
1509  gtk_box_pack_start (GTK_BOX(box), date_edit, TRUE, TRUE, 0);
1510  gtk_widget_show (date_edit);
1511 
1512  aw->opening_balance_page =
1513  gtk_notebook_get_nth_page (GTK_NOTEBOOK(aw->notebook), 1);
1514 
1515  aw->opening_equity_radio = GTK_WIDGET(gtk_builder_get_object (builder,
1516  "opening_equity_radio"));
1517 
1518  box = GTK_WIDGET(gtk_builder_get_object (builder, "transfer_account_scroll"));
1519  aw->transfer_account_scroll = box;
1520 
1521  aw->transfer_tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
1522  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->transfer_tree));
1523  gtk_tree_selection_set_select_function (selection, account_commodity_filter, aw, NULL);
1524 
1525  gtk_container_add (GTK_CONTAINER(box), GTK_WIDGET(aw->transfer_tree));
1526  gtk_widget_show (GTK_WIDGET(aw->transfer_tree));
1527 
1528  label = GTK_WIDGET(gtk_builder_get_object (builder, "parent_label"));
1529  gtk_label_set_mnemonic_widget (GTK_LABEL(label), GTK_WIDGET(aw->parent_tree));
1530 
1531  /* This goes at the end so the select callback has good data. */
1532  aw->type_view = GTK_WIDGET(gtk_builder_get_object (builder, "type_view"));
1533 
1534  // If the account has transactions, reduce the available account types
1535  // to change the current account type to based on the following
1536  // restrictions:
1537  // - the new account type should not force a change of commodity
1538  // - the old/new type is not an immutable type. Types are marked as
1539  // immutable if gnucash depends on details that would be lost/missing
1540  // if changing from/to such a type. At the time of this writing the
1541  // immutable types are AR, AP and trading types.
1542  if (xaccAccountGetSplitList (aw_get_account (aw)) != NULL)
1543  {
1544  GNCAccountType atype = xaccAccountGetType (aw_get_account (aw));
1545  compat_types = xaccAccountTypesCompatibleWith (atype);
1546  if (!compat_types)
1547  compat_types = xaccAccountTypesValid ();
1548  }
1549  gnc_account_type_view_create (aw, compat_types);
1550 
1551  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog), parent);
1552 
1553  gtk_widget_grab_focus (GTK_WIDGET(aw->name_entry));
1554 
1555  gtk_builder_connect_signals (builder, aw);
1556  g_object_unref (G_OBJECT(builder));
1557 
1558  LEAVE(" ");
1559 }
1560 
1561 static char *
1562 get_ui_fullname (AccountWindow *aw)
1563 {
1564  Account *parent_account;
1565  char *fullname;
1566  const gchar *name;
1567 
1568  name = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
1569  if (!name || *name == '\0')
1570  name = _("<No name>");
1571 
1572  parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(aw->parent_tree));
1573 
1574  if (parent_account && !gnc_account_is_root (parent_account))
1575  {
1576  char *parent_name = gnc_account_get_full_name (parent_account);
1577  const gchar *separator = gnc_get_account_separator_string ();
1578 
1579  fullname = g_strconcat (parent_name, separator, name, NULL);
1580  g_free (parent_name);
1581  }
1582  else
1583  fullname = g_strdup (name);
1584 
1585  return fullname;
1586 }
1587 
1588 static void
1589 gnc_account_window_set_name (AccountWindow *aw)
1590 {
1591  char *fullname;
1592  char *title;
1593 
1594  if (!aw || !aw->parent_tree)
1595  return;
1596 
1597  fullname = get_ui_fullname (aw);
1598 
1599  if (aw->dialog_type == EDIT_ACCOUNT)
1600  title = g_strconcat(_("Edit Account"), " - ", fullname, NULL);
1601  else if (aw->next_name && (g_strv_length (aw->next_name) > 0))
1602  {
1603  const char *format = _("(%d) New Accounts");
1604  char *prefix = g_strdup_printf (format,
1605  g_strv_length (aw->next_name) + 1);
1606 
1607  title = g_strconcat (prefix, " - ", fullname, " ...", NULL);
1608  g_free (prefix);
1609  }
1610  else
1611  title = g_strconcat (_("New Account"), " - ", fullname, NULL);
1612 
1613  gtk_window_set_title (GTK_WINDOW(aw->dialog), title);
1614 
1615  g_free (fullname);
1616  g_free (title);
1617 }
1618 
1619 static void
1620 close_handler (gpointer user_data)
1621 {
1622  AccountWindow *aw = user_data;
1623 
1624  ENTER("aw %p, modal %d", aw, aw->modal);
1625  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog));
1626 
1627  gtk_widget_destroy (GTK_WIDGET(aw->dialog));
1628  LEAVE(" ");
1629 }
1630 
1631 /********************************************************************\
1632  * gnc_ui_refresh_account_window *
1633  * refreshes the edit window *
1634  * *
1635  * Args: aw - the account window to refresh *
1636  * Return: none *
1637 \********************************************************************/
1638 static void
1639 gnc_ui_refresh_account_window (AccountWindow *aw)
1640 {
1641  if (aw == NULL)
1642  return;
1643 
1644  /* gnc_account_tree_refresh (GNC_ACCOUNT_TREE(aw->parent_tree));*/
1645 
1646  gnc_account_window_set_name (aw);
1647 }
1648 
1649 static void
1650 refresh_handler (GHashTable *changes, gpointer user_data)
1651 {
1652  AccountWindow *aw = user_data;
1653  Account *account;
1654 
1655  account = aw_get_account (aw);
1656  if (!account)
1657  {
1658  gnc_close_gui_component (aw->component_id);
1659  return;
1660  }
1661 
1662  if (changes)
1663  {
1664  const EventInfo *info = gnc_gui_get_entity_events (changes, &aw->account);
1665  if (info && (info->event_mask & QOF_EVENT_DESTROY))
1666  {
1667  gnc_close_gui_component (aw->component_id);
1668  return;
1669  }
1670  }
1671  gnc_ui_refresh_account_window (aw);
1672 }
1673 
1674 static AccountWindow *
1675 gnc_ui_new_account_window_internal (GtkWindow *parent,
1676  QofBook *book,
1677  Account *base_account,
1678  gchar **subaccount_names,
1679  GList *valid_types,
1680  const gnc_commodity * default_commodity,
1681  gboolean modal)
1682 {
1683  const gnc_commodity *commodity, *parent_commodity;
1684  AccountWindow *aw;
1685  Account *account;
1686  GList *list;
1687 
1688  g_return_val_if_fail(book, NULL);
1689 
1690  aw = g_new0 (AccountWindow, 1);
1691 
1692  aw->book = book;
1693  aw->modal = modal;
1694  aw->dialog_type = NEW_ACCOUNT;
1695 
1696  aw->valid_types = 0;
1697  for (list = valid_types; list; list = list->next)
1698  aw->valid_types |= (1 << GPOINTER_TO_INT (list->data));
1699 
1700  account = xaccMallocAccount (book);
1701  aw->account = *xaccAccountGetGUID (account);
1702 
1703  if (base_account)
1704  {
1705  aw->type = xaccAccountGetType (base_account);
1706  parent_commodity = xaccAccountGetCommodity (base_account);
1707  }
1708  else
1709  {
1710  aw->type = last_used_account_type;
1711  parent_commodity = gnc_default_currency ();
1712  }
1713 
1714  gnc_suspend_gui_refresh ();
1715 
1716  if (subaccount_names && *subaccount_names)
1717  {
1718  xaccAccountSetName (account, subaccount_names[0]);
1719  aw->subaccount_names = subaccount_names;
1720  aw->next_name = subaccount_names + 1;
1721  }
1722 
1723  gnc_account_window_create (parent, aw);
1724  gnc_account_to_ui (aw);
1725 
1726  gnc_resume_gui_refresh ();
1727 
1728  if (default_commodity != NULL)
1729  {
1730  commodity = default_commodity;
1731  if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
1732  {
1733  gtk_entry_set_text (GTK_ENTRY(aw->name_entry),
1734  (gpointer) gnc_commodity_get_mnemonic (commodity));
1735  gtk_entry_set_text (GTK_ENTRY(aw->description_entry),
1736  (gpointer) gnc_commodity_get_fullname (commodity));
1737  }
1738  }
1739  else if ((aw->type != ACCT_TYPE_STOCK) && (aw->type != ACCT_TYPE_MUTUAL))
1740  {
1741  commodity = parent_commodity;
1742  }
1743  else
1744  {
1745  commodity = NULL;
1746  }
1747  gnc_general_select_set_selected (GNC_GENERAL_SELECT(aw->commodity_edit),
1748  (gpointer) commodity);
1749  gnc_account_commodity_from_type (aw, FALSE);
1750 
1751  if (base_account == NULL)
1752  {
1753  base_account = gnc_book_get_root_account (book);
1754  }
1755 
1756  gtk_tree_view_collapse_all (aw->parent_tree);
1757  gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(
1758  aw->parent_tree),
1759  base_account);
1760 
1761  gtk_widget_show (aw->dialog);
1762 
1763  gnc_window_adjust_for_screen (GTK_WINDOW(aw->dialog));
1764 
1765  gnc_account_window_set_name (aw);
1766 
1767  aw->component_id = gnc_register_gui_component (DIALOG_NEW_ACCOUNT_CM_CLASS,
1768  refresh_handler,
1769  modal ? NULL : close_handler,
1770  aw);
1771 
1772  gnc_gui_component_set_session (aw->component_id, gnc_get_current_session());
1773  gnc_gui_component_watch_entity_type (aw->component_id,
1774  GNC_ID_ACCOUNT,
1775  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
1776  return aw;
1777 }
1778 
1779 static gchar **
1780 gnc_split_account_name (QofBook *book, const char *in_name, Account **base_account)
1781 {
1782  Account *root, *account;
1783  gchar **names, **ptr, **out_names;
1784  GList *list, *node;
1785 
1786  root = gnc_book_get_root_account (book);
1787  list = gnc_account_get_children (root);
1788  names = g_strsplit (in_name, gnc_get_account_separator_string (), -1);
1789 
1790  for (ptr = names; *ptr; ptr++)
1791  {
1792  /* Stop if there are no children at the current level. */
1793  if (list == NULL)
1794  break;
1795 
1796  /* Look for the first name in the children. */
1797  for (node = list; node; node = g_list_next (node))
1798  {
1799  account = node->data;
1800 
1801  if (g_strcmp0 (xaccAccountGetName (account), *ptr) == 0)
1802  {
1803  /* We found an account. */
1804  *base_account = account;
1805  break;
1806  }
1807  }
1808 
1809  /* Was there a match? If no, stop the traversal. */
1810  if (node == NULL)
1811  break;
1812 
1813  g_list_free (list);
1814  list = gnc_account_get_children (account);
1815  }
1816 
1817  out_names = g_strdupv (ptr);
1818  g_strfreev (names);
1819  if (list)
1820  g_list_free (list);
1821  return out_names;
1822 }
1823 
1824 /************************************************************
1825  * Entry points for a Modal Dialog *
1826  ************************************************************/
1827 
1828 Account *
1829 gnc_ui_new_accounts_from_name_window (GtkWindow *parent, const char *name)
1830 {
1831  return gnc_ui_new_accounts_from_name_with_defaults (parent, name, NULL,
1832  NULL, NULL);
1833 }
1834 
1835 Account *
1837  const char *name,
1838  GList *valid_types)
1839 {
1840  return gnc_ui_new_accounts_from_name_with_defaults (parent, name,
1841  valid_types, NULL, NULL);
1842 }
1843 
1844 Account *
1846  const char *name,
1847  GList *valid_types,
1848  const gnc_commodity * default_commodity,
1849  Account * parent_acct)
1850 {
1851  QofBook *book;
1852  AccountWindow *aw;
1853  Account *base_account = NULL;
1854  Account *created_account = NULL;
1855  gchar ** subaccount_names;
1856  gint response;
1857  gboolean done = FALSE;
1858 
1859  ENTER("name %s, valid %p, commodity %p, account %p",
1860  name, valid_types, default_commodity, parent_acct);
1861  book = gnc_get_current_book ();
1862  if (!name || *name == '\0')
1863  {
1864  subaccount_names = NULL;
1865  base_account = NULL;
1866  }
1867  else
1868  subaccount_names = gnc_split_account_name (book, name, &base_account);
1869 
1870  if (parent_acct != NULL)
1871  {
1872  base_account = parent_acct;
1873  }
1874  aw = gnc_ui_new_account_window_internal (parent, book, base_account,
1875  subaccount_names,
1876  valid_types,
1877  default_commodity,
1878  TRUE);
1879 
1880  while (!done)
1881  {
1882  response = gtk_dialog_run (GTK_DIALOG(aw->dialog));
1883 
1884  /* This can destroy the dialog */
1885  gnc_account_window_response_cb (GTK_DIALOG(aw->dialog), response, (gpointer)aw);
1886 
1887  switch (response)
1888  {
1889  case GTK_RESPONSE_OK:
1890  created_account = aw->created_account;
1891  done = (created_account != NULL);
1892  break;
1893 
1894  case GTK_RESPONSE_HELP:
1895  done = FALSE;
1896  break;
1897 
1898  default:
1899  done = TRUE;
1900  break;
1901  }
1902  }
1903 
1904  close_handler (aw);
1905  LEAVE("created %s (%p)", xaccAccountGetName (created_account), created_account);
1906  return created_account;
1907 }
1908 
1909 /************************************************************
1910  * Entry points for a non-Modal Dialog *
1911  ************************************************************/
1912 
1913 static gboolean
1914 find_by_account (gpointer find_data, gpointer user_data)
1915 {
1916  Account *account = find_data;
1917  AccountWindow *aw = user_data;
1918 
1919  if (!aw)
1920  return FALSE;
1921 
1922  return guid_equal (&aw->account, xaccAccountGetGUID (account));
1923 }
1924 
1925 /*
1926  * opens up a window to edit an account
1927  *
1928  * Args: account - the account to edit
1929  * Return: EditAccountWindow object
1930  */
1931 void
1932 gnc_ui_edit_account_window (GtkWindow *parent, Account *account)
1933 {
1934  AccountWindow * aw;
1935  Account *parent_acct;
1936 
1937  if (account == NULL)
1938  return;
1939 
1940  aw = gnc_find_first_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
1941  find_by_account, account);
1942  if (aw)
1943  {
1944  gtk_window_present (GTK_WINDOW(aw->dialog));
1945  return;
1946  }
1947 
1948  aw = g_new0 (AccountWindow, 1);
1949 
1950  aw->book = gnc_account_get_book (account);
1951  aw->modal = FALSE;
1952  aw->dialog_type = EDIT_ACCOUNT;
1953  aw->account = *xaccAccountGetGUID (account);
1954  aw->subaccount_names = NULL;
1955  aw->type = xaccAccountGetType (account);
1956 
1957  gnc_suspend_gui_refresh ();
1958 
1959  gnc_account_window_create (parent, aw);
1960  gnc_account_to_ui (aw);
1961 
1962  gnc_resume_gui_refresh ();
1963 
1964  gtk_widget_show_all (aw->dialog);
1965  if (xaccAccountGetSplitList (account) != NULL)
1966  gtk_widget_hide (aw->opening_balance_page);
1967 
1968  parent_acct = gnc_account_get_parent (account);
1969  if (parent_acct == NULL)
1970  parent_acct = account; // must be at the root
1971 
1972  gtk_tree_view_collapse_all (aw->parent_tree);
1973  gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT(
1974  aw->parent_tree),
1975  parent_acct);
1976 
1977  gnc_account_window_set_name (aw);
1978 
1979  gnc_window_adjust_for_screen (GTK_WINDOW(aw->dialog));
1980 
1981  aw->component_id = gnc_register_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
1982  refresh_handler,
1983  close_handler, aw);
1984 
1985  gnc_gui_component_set_session (aw->component_id, gnc_get_current_session ());
1986  gnc_gui_component_watch_entity_type (aw->component_id,
1987  GNC_ID_ACCOUNT,
1988  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
1989 
1990  gtk_window_present (GTK_WINDOW(aw->dialog));
1991 }
1992 
1993 /*
1994  * opens up a window to create a new account
1995  *
1996  * Args: book - containing book for the new account
1997  * parent_acct - The initial parent for the new account (optional)
1998  */
1999 void
2000 gnc_ui_new_account_window (GtkWindow *parent, QofBook *book,
2001  Account *parent_acct)
2002 {
2003  g_return_if_fail(book != NULL);
2004  if (parent_acct && book)
2005  g_return_if_fail(gnc_account_get_book (parent_acct) == book);
2006 
2007  gnc_ui_new_account_window_internal (parent, book, parent_acct, NULL, NULL,
2008  NULL, FALSE);
2009 }
2010 
2011 void
2012 gnc_ui_new_account_with_types (GtkWindow *parent, QofBook *book,
2013  GList *valid_types)
2014 {
2015  gnc_ui_new_account_window_internal (parent, book, NULL, NULL,
2016  valid_types, NULL, FALSE);
2017 }
2018 
2019 /************************************************************
2020  * Callbacks for a non-Modal Dialog *
2021  ************************************************************/
2022 
2023 /*
2024  * register a callback that gets called when the account has changed
2025  * so significantly that you need to destroy yourself. In particular
2026  * this is used by the ledger display to destroy ledgers when the
2027  * account type has changed.
2028  */
2029 void
2030 gnc_ui_register_account_destroy_callback (void (*cb)(Account *))
2031 {
2032  if (!cb)
2033  return;
2034 
2035  if (g_list_index (ac_destroy_cb_list, cb) == -1)
2036  ac_destroy_cb_list = g_list_append (ac_destroy_cb_list, cb);
2037 
2038  return;
2039 }
2040 
2041 /**************************************************/
2042 
2043 static void
2044 gnc_account_renumber_update_examples (RenumberDialog *data)
2045 {
2046  gchar *str;
2047  gchar *prefix;
2048  gint interval;
2049  gint digits;
2050  unsigned int num_digits = 1;
2051 
2052  g_return_if_fail (data->num_children > 0);
2053 
2054  prefix = gtk_editable_get_chars (GTK_EDITABLE(data->prefix), 0, -1);
2055  interval = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(data->interval));
2056  digits = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(data->digits));
2057 
2058  if (interval <= 0)
2059  interval = 10;
2060 
2061  num_digits = (unsigned int)log10((double)(data->num_children * interval)) + 1;
2062 
2063  if (digits <= num_digits)
2064  {
2065  g_signal_handlers_block_by_func (GTK_SPIN_BUTTON(data->digits),
2066  (gpointer)gnc_account_renumber_digits_changed_cb,
2067  data);
2068  gtk_spin_button_set_value (GTK_SPIN_BUTTON(data->digits), num_digits);
2069  g_signal_handlers_unblock_by_func (GTK_SPIN_BUTTON(data->digits),
2070  (gpointer)gnc_account_renumber_digits_changed_cb,
2071  data);
2072  }
2073  else
2074  num_digits = digits;
2075 
2076  if (strlen (prefix))
2077  str = g_strdup_printf ("%s-%0*d", prefix, num_digits, interval);
2078  else
2079  str = g_strdup_printf ("%0*d", num_digits, interval);
2080 
2081  gtk_label_set_text (GTK_LABEL(data->example1), str);
2082  g_free (str);
2083 
2084  if (strlen (prefix))
2085  str = g_strdup_printf ("%s-%0*d", prefix, num_digits,
2086  interval * data->num_children);
2087  else
2088  str = g_strdup_printf ("%0*d", num_digits,
2089  interval * data->num_children);
2090 
2091  gtk_label_set_text (GTK_LABEL(data->example2), str);
2092 
2093  g_free (str);
2094  g_free (prefix);
2095 }
2096 
2097 void
2098 gnc_account_renumber_prefix_changed_cb (GtkEditable *editable,
2099  RenumberDialog *data)
2100 {
2101  gnc_account_renumber_update_examples (data);
2102 }
2103 
2104 void
2105 gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton,
2106  RenumberDialog *data)
2107 {
2108  gnc_account_renumber_update_examples (data);
2109 }
2110 
2111 void
2112 gnc_account_renumber_digits_changed_cb (GtkSpinButton *spinbutton,
2113  RenumberDialog *data)
2114 {
2115  gnc_account_renumber_update_examples (data);
2116 }
2117 
2118 void
2119 gnc_account_renumber_response_cb (GtkDialog *dialog,
2120  gint response,
2121  RenumberDialog *data)
2122 {
2123  if (response == GTK_RESPONSE_OK)
2124  {
2125  GList *children = gnc_account_get_children_sorted (data->parent);
2126  GList *tmp;
2127  gchar *prefix;
2128  gint interval;
2129  unsigned int num_digits, i;
2130 
2131  gtk_widget_hide (data->dialog);
2132 
2133  if (children == NULL)
2134  {
2135  PWARN("Can't renumber children of an account with no children!");
2136  g_free (data);
2137  return;
2138  }
2139  prefix = gtk_editable_get_chars (GTK_EDITABLE(data->prefix), 0, -1);
2140  interval = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(data->interval));
2141  num_digits = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(data->digits));
2142 
2143  gnc_set_busy_cursor (NULL, TRUE);
2144  for (tmp = children, i = 1; tmp; tmp = g_list_next (tmp), i += 1)
2145  {
2146  gchar *str;
2147  if (strlen (prefix))
2148  str = g_strdup_printf ("%s-%0*d", prefix,
2149  num_digits, interval * i);
2150  else
2151  str = g_strdup_printf ("%0*d", num_digits, interval * i);
2152 
2153  xaccAccountSetCode (tmp->data, str);
2154  g_free (str);
2155  }
2156  gnc_unset_busy_cursor (NULL);
2157  g_free (prefix);
2158  g_list_free (children);
2159  }
2160  gtk_widget_destroy (data->dialog);
2161  g_free (data);
2162 }
2163 
2164 void
2165 gnc_account_renumber_create_dialog (GtkWidget *window, Account *account)
2166 {
2167  RenumberDialog *data;
2168  GtkBuilder *builder;
2169  GtkWidget *widget;
2170  gchar *string, *fullname;
2171 
2172  /* This is a safety check; the menu item calling this dialog
2173  * should be disabled if the account has no children.
2174  */
2175  g_return_if_fail (gnc_account_n_children (account) > 0);
2176 
2177  data = g_new (RenumberDialog, 1);
2178  data->parent = account;
2179  data->num_children = gnc_account_n_children (account);
2180 
2181  builder = gtk_builder_new ();
2182  gnc_builder_add_from_file (builder, "dialog-account.glade", "interval_adjustment");
2183  gnc_builder_add_from_file (builder, "dialog-account.glade", "digit_spin_adjustment");
2184  gnc_builder_add_from_file (builder, "dialog-account.glade", "account_renumber_dialog");
2185  data->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_renumber_dialog"));
2186  gtk_window_set_transient_for (GTK_WINDOW(data->dialog), GTK_WINDOW(window));
2187 
2188  g_object_set_data_full (G_OBJECT(data->dialog), "builder", builder,
2189  g_object_unref);
2190 
2191  widget = GTK_WIDGET(gtk_builder_get_object (builder, "header_label"));
2192  fullname = gnc_account_get_full_name (account);
2193  string = g_strdup_printf (_("Renumber the immediate sub-accounts of '%s'?"),
2194  fullname);
2195  gtk_label_set_text (GTK_LABEL(widget), string);
2196  g_free (string);
2197  g_free (fullname);
2198 
2199  data->prefix = GTK_WIDGET(gtk_builder_get_object (builder, "prefix_entry"));
2200  data->interval = GTK_WIDGET(gtk_builder_get_object (builder, "interval_spin"));
2201  data->digits = GTK_WIDGET(gtk_builder_get_object (builder, "digit_spin"));
2202  data->example1 = GTK_WIDGET(gtk_builder_get_object (builder, "example1_label"));
2203  data->example2 = GTK_WIDGET(gtk_builder_get_object (builder, "example2_label"));
2204 
2205  gtk_entry_set_text (GTK_ENTRY(data->prefix), xaccAccountGetCode (account));
2206  gnc_account_renumber_update_examples (data);
2207 
2208  gtk_builder_connect_signals (builder, data);
2209 
2210  gtk_widget_show_all (data->dialog);
2211 }
2212 
2213 static void
2214 default_color_button_cb (GtkButton *button, gpointer user_data)
2215 {
2216  GdkRGBA color;
2217 
2218  if (gdk_rgba_parse (&color, DEFAULT_COLOR))
2219  gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER(user_data), &color);
2220 }
2221 
2222 static void
2223 update_account_color (Account *acc, const gchar *old_color, const gchar *new_color, gboolean replace)
2224 {
2225  PINFO("Account is '%s', old_color is '%s', new_color is '%s', replace is %d",
2226  xaccAccountGetName (acc), old_color, new_color, replace);
2227 
2228  // have a new color, update if we can
2229  if (new_color)
2230  {
2231  if (!old_color || replace)
2232  {
2233  // check to see if the color is different from old one
2234  if (g_strcmp0 (new_color, old_color) != 0)
2235  xaccAccountSetColor (acc, new_color);
2236  }
2237  }
2238  else // change from a color to default one, remove color entry if we can
2239  {
2240  if (old_color && replace)
2241  xaccAccountSetColor (acc, ""); // remove entry
2242  }
2243 }
2244 
2245 static void
2246 enable_box_cb (GtkToggleButton *toggle_button, gpointer user_data)
2247 {
2248  gboolean sensitive = FALSE;
2249 
2250  if (gtk_toggle_button_get_active (toggle_button))
2251  sensitive = TRUE;
2252 
2253  gtk_widget_set_sensitive (GTK_WIDGET(user_data), sensitive);
2254 }
2255 
2256 void
2257 gnc_account_cascade_properties_dialog (GtkWidget *window, Account *account)
2258 {
2259  GtkWidget *dialog;
2260  GtkBuilder *builder;
2261  GtkWidget *label;
2262  GtkWidget *color_button, *over_write, *color_button_default;
2263  GtkWidget *enable_color, *enable_placeholder, *enable_hidden;
2264  GtkWidget *color_box, *placeholder_box, *hidden_box;
2265  GtkWidget *placeholder_button, *hidden_button;
2266 
2267  gchar *string, *fullname;
2268  const char *color_string;
2269  gchar *old_color_string = NULL;
2270  GdkRGBA color;
2271  gint response;
2272 
2273  // check if we actually do have sub accounts
2274  g_return_if_fail (gnc_account_n_children (account) > 0);
2275 
2276  builder = gtk_builder_new ();
2277  gnc_builder_add_from_file (builder, "dialog-account.glade", "account_cascade_dialog");
2278  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_cascade_dialog"));
2279  gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(window));
2280 
2281  // Color section
2282  enable_color = GTK_WIDGET(gtk_builder_get_object (builder, "enable_cascade_color"));
2283  color_box = GTK_WIDGET(gtk_builder_get_object (builder, "color_box"));
2284 
2285  label = GTK_WIDGET(gtk_builder_get_object (builder, "color_label"));
2286  over_write = GTK_WIDGET(gtk_builder_get_object (builder, "replace_check"));
2287  color_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_button"));
2288  color_button_default = GTK_WIDGET(gtk_builder_get_object (builder, "color_button_default"));
2289 
2290  gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER(color_button), FALSE);
2291 
2292  g_signal_connect (G_OBJECT(enable_color), "toggled",
2293  G_CALLBACK(enable_box_cb), (gpointer)color_box);
2294 
2295  g_signal_connect (G_OBJECT(color_button_default), "clicked",
2296  G_CALLBACK(default_color_button_cb), (gpointer)color_button);
2297 
2298  fullname = gnc_account_get_full_name (account);
2299  string = g_strdup_printf (_( "Set the account color for account '%s' "
2300  "including all sub-accounts to the selected color"),
2301  fullname);
2302  gtk_label_set_text (GTK_LABEL(label), string);
2303  g_free (string);
2304 
2305  color_string = xaccAccountGetColor (account); // get existing account color
2306 
2307  if (!color_string)
2308  color_string = DEFAULT_COLOR;
2309  else
2310  old_color_string = g_strdup (color_string); // save the old color string
2311 
2312  if (!gdk_rgba_parse (&color, color_string))
2313  gdk_rgba_parse (&color, DEFAULT_COLOR);
2314 
2315  // set the color chooser to account color
2316  gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER(color_button), &color);
2317 
2318  // Placeholder section
2319  enable_placeholder = GTK_WIDGET(gtk_builder_get_object (builder, "enable_cascade_placeholder"));
2320  placeholder_box = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_box"));
2321  label = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_label"));
2322  placeholder_button = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_check_button"));
2323  g_signal_connect (G_OBJECT(enable_placeholder), "toggled",
2324  G_CALLBACK(enable_box_cb), (gpointer)placeholder_box);
2325 
2326  string = g_strdup_printf (_( "Set the account placeholder value for account '%s' "
2327  "including all sub-accounts"),
2328  fullname);
2329  gtk_label_set_text (GTK_LABEL(label), string);
2330  g_free (string);
2331 
2332  // Hidden section
2333  enable_hidden = GTK_WIDGET(gtk_builder_get_object (builder, "enable_cascade_hidden"));
2334  hidden_box = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_box"));
2335  label = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_label"));
2336  hidden_button = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_check_button"));
2337  g_signal_connect (G_OBJECT(enable_hidden), "toggled",
2338  G_CALLBACK(enable_box_cb), (gpointer)hidden_box);
2339 
2340  string = g_strdup_printf (_( "Set the account hidden value for account '%s' "
2341  "including all sub-accounts"),
2342  fullname);
2343  gtk_label_set_text (GTK_LABEL(label), string);
2344  g_free (string);
2345  g_free (fullname);
2346 
2347  /* default to cancel */
2348  gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
2349 
2350  gtk_builder_connect_signals (builder, dialog);
2351  g_object_unref (G_OBJECT(builder));
2352 
2353  gtk_widget_show_all (dialog);
2354 
2355  response = gtk_dialog_run (GTK_DIALOG(dialog));
2356 
2357  if (response == GTK_RESPONSE_OK)
2358  {
2359  GList *accounts = gnc_account_get_descendants (account);
2360  GdkRGBA new_color;
2361  const gchar *new_color_string = NULL;
2362  gboolean color_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(enable_color));
2363  gboolean placeholder_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(enable_placeholder));
2364  gboolean hidden_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(enable_hidden));
2365  gboolean replace = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(over_write));
2366  gboolean placeholder = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(placeholder_button));
2367  gboolean hidden = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(hidden_button));
2368 
2369  // Update Account Colors
2370  if (color_active)
2371  {
2372  gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER(color_button), &new_color);
2373  new_color_string = gdk_rgba_to_string (&new_color);
2374 
2375  if (g_strcmp0 (new_color_string, DEFAULT_COLOR) == 0)
2376  new_color_string = NULL;
2377 
2378  // check/update selected account
2379  update_account_color (account, old_color_string, new_color_string, replace);
2380  }
2381 
2382  // Update Account Placeholder value
2383  if (placeholder_active)
2384  xaccAccountSetPlaceholder (account, placeholder);
2385 
2386  // Update Account Hidden value
2387  if (hidden_active)
2388  xaccAccountSetHidden (account, hidden);
2389 
2390  // Update SubAccounts
2391  if (accounts)
2392  {
2393  for (GList *acct = accounts; acct; acct = g_list_next(acct))
2394  {
2395  // Update SubAccount Colors
2396  if (color_active)
2397  {
2398  const char *string = xaccAccountGetColor (acct->data);
2399  update_account_color (acct->data, string, new_color_string, replace);
2400  }
2401  // Update SubAccount PlaceHolder
2402  if (placeholder_active)
2403  xaccAccountSetPlaceholder (acct->data, placeholder);
2404  // Update SubAccount Hidden
2405  if (hidden_active)
2406  xaccAccountSetHidden (acct->data, hidden);
2407  }
2408  }
2409  g_list_free (accounts);
2410  }
2411  if (old_color_string)
2412  g_free (old_color_string);
2413 
2414  gtk_widget_destroy (dialog);
2415 }
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account&#39;s type.
Definition: Account.cpp:2426
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:92
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
Definition: Account.cpp:2899
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
Definition: Transaction.h:370
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
Definition: Transaction.c:511
gboolean xaccAccountGetAutoInterest(const Account *acc)
Get the "auto interest" flag for an account.
Definition: Account.cpp:4336
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
Dialog box should only allow selection of a currency.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
Account * gnc_ui_new_accounts_from_name_window(GtkWindow *parent, const char *name)
Display a modal window for creating a new account.
guint32 xaccAccountTypesCompatibleWith(GNCAccountType type)
Return the bitmask of account types compatible with a given type.
Definition: Account.cpp:4528
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship, and will then add the account as a child of the new parent.
Definition: Account.cpp:2801
gboolean gnc_account_is_root(const Account *account)
This routine indicates whether the specified account is the root node of an account tree...
Definition: Account.cpp:2923
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
Definition: Account.cpp:4007
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
int xaccAccountGetCommoditySCUi(const Account *acc)
Return the &#39;internal&#39; SCU setting.
Definition: Account.cpp:2694
gboolean xaccAccountGetNonStdSCU(const Account *acc)
Return boolean, indicating whether this account uses a non-standard SCU.
Definition: Account.cpp:2730
This file contains the functions to present a gui to the user for creating a new account or editing a...
void xaccAccountSetNotes(Account *acc, const char *str)
Set the account&#39;s notes.
Definition: Account.cpp:2622
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
utility functions for the GnuCash UI
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3279
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition: Account.cpp:2701
const char * xaccAccountGetCode(const Account *acc)
Get the account&#39;s accounting code.
Definition: Account.cpp:3356
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
void xaccAccountSetTaxRelated(Account *acc, gboolean tax_related)
DOCUMENT ME!
Definition: Account.cpp:4152
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
Mutual Fund accounts will typically be shown in registers which show three columns: price...
Definition: Account.h:128
void xaccAccountSetCode(Account *acc, const char *str)
Set the account&#39;s accounting code.
Definition: Account.cpp:2467
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
guint32 xaccAccountTypesValid(void)
Returns the bitmask of the account type enums that are valid.
Definition: Account.cpp:4633
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
void gnc_ui_edit_account_window(GtkWindow *parent, Account *account)
Display a window for editing the attributes of an existing account.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
Definition: Transaction.c:1426
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
Definition: gnc-ui-util.c:1197
Account used to record multiple commodity transactions.
Definition: Account.h:158
Dialog box should allow selection of anything.
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Definition: Account.cpp:1569
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
Definition: Account.h:125
const char * xaccAccountGetColor(const Account *acc)
Get the account&#39;s color.
Definition: Account.cpp:3370
#define xaccAccountGetGUID(X)
Definition: Account.h:248
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account&#39;s commodity that the split should have...
Definition: gmock-Split.cpp:77
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:3308
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
Set the "placeholder" flag for an account.
Definition: Account.cpp:4268
gboolean xaccAccountTypesCompatible(GNCAccountType parent_type, GNCAccountType child_type)
Return TRUE if accounts of type parent_type can have accounts of type child_type as children...
Definition: Account.cpp:4615
void xaccAccountSetColor(Account *acc, const char *str)
Set the account&#39;s Color.
Definition: Account.cpp:2566
GtkTreeView implementation for gnucash account tree.
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome&#39;s yelp for linux, and open to a given link within a gi...
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition: guid.cpp:204
GtkTreeView * gnc_tree_view_account_new_with_root(Account *root, gboolean show_root)
Create a new account tree view.
Dialog box should allow selection of anything but a currency and should include the "ALL" namespace t...
const char * xaccAccountGetDescription(const Account *acc)
Get the account&#39;s description.
Definition: Account.cpp:3363
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
gint null_strcmp(const gchar *da, const gchar *db)
The null_strcmp compares strings a and b the same way that strcmp() does, except that either may be n...
Definition: qofutil.cpp:123
GList * gnc_account_get_children_sorted(const Account *account)
This routine returns a GList of all children accounts of the specified account, ordered by xaccAccoun...
Definition: Account.cpp:2937
The bank account type denotes a savings or checking account held at a bank.
Definition: Account.h:110
dialog_commodity_mode
The dialog commodity types are used to determine what commodity namespaces the currency dialog will p...
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name, but uses fully-qualified names using the given separator.
Definition: Account.cpp:3163
Account * gnc_tree_view_account_get_account_from_path(GncTreeViewAccount *view, GtkTreePath *s_path)
This function returns the account associated with the specified path.
Account * gnc_ui_new_accounts_from_name_window_with_types(GtkWindow *parent, const char *name, GList *valid_types)
Display a modal window for creating a new account.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccAccountSetIsOpeningBalance(Account *acc, gboolean val)
Set the "opening-balance" flag for an account.
Definition: Account.cpp:4302
gboolean xaccAccountGetTaxRelated(const Account *acc)
DOCUMENT ME!
Definition: Account.cpp:4146
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gint gnc_account_n_children(const Account *account)
Return the number of children of the specified account.
Definition: Account.cpp:2952
All type declarations for the whole Gnucash engine.
void gnc_ui_new_account_window(GtkWindow *parent, QofBook *book, Account *parent_acct)
Display a window for creating a new account.
The currency account type indicates that the account is a currency trading account.
Definition: Account.h:132
void xaccAccountSetCommoditySCU(Account *acc, int scu)
Set the SCU for the account.
Definition: Account.cpp:2678
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:105
gboolean xaccAccountGetHidden(const Account *acc)
Get the "hidden" flag for an account.
Definition: Account.cpp:4351
GtkTreeModel implementation to display account types in a GtkTreeView.
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: gmock-Split.cpp:37
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition: Account.cpp:3036
void xaccAccountSetAutoInterest(Account *acc, gboolean val)
Set the "auto interest" flag for an account.
Definition: Account.cpp:4342
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
Returns a gnc_commodity that is a currency, suitable for being a Transaction&#39;s currency.
Definition: gnc-ui-util.c:1202
gboolean xaccAccountGetIsOpeningBalance(const Account *acc)
Get the "opening-balance" flag for an account.
Definition: Account.cpp:4286
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
Retrieve the &#39;print&#39; name for the specified commodity.
guint32 xaccParentAccountTypesCompatibleWith(GNCAccountType type)
Return the bitmask of parent account types compatible with a given type.
Definition: Account.cpp:4568
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
This function selects an account in the account tree view.
Not a type.
Definition: Account.h:107
GList * gnc_account_get_children(const Account *account)
This routine returns a GList of all children accounts of the specified account.
Definition: Account.cpp:2930
Account * gnc_ui_new_accounts_from_name_with_defaults(GtkWindow *parent, const char *name, GList *valid_types, const gnc_commodity *default_commodity, Account *parent_acct)
Display a modal window for creating a new account.
void xaccAccountSetHidden(Account *acc, gboolean val)
Set the "hidden" flag for an account.
Definition: Account.cpp:4357
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1449
gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor)
Returns true if the account is &#39;ancestor&#39; or has &#39;ancestor&#39; as an ancestor.
Definition: Account.cpp:4385
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account&#39;s commodity.
Definition: Account.cpp:3448
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:131
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
Definition: Account.h:1038
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition: Account.cpp:4262
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_ui_new_account_with_types(GtkWindow *parent, QofBook *book, GList *valid_types)
Display a window for creating a new account.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * xaccMallocAccount(QofBook *book)
Constructor.
Definition: Account.cpp:1228
time64 gnc_time(time64 *tbuf)
get the current local time
Definition: gnc-date.cpp:273
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
void xaccAccountSetDescription(Account *acc, const char *str)
Set the account&#39;s description.
Definition: Account.cpp:2486
void xaccAccountSetNonStdSCU(Account *acc, gboolean flag)
Set the flag indicating that this account uses a non-standard SCU.
Definition: Account.cpp:2714
Account * gnc_account_lookup_by_opening_balance(Account *account, gnc_commodity *commodity)
Find the opening balance account for the currency.
Definition: Account.cpp:3111
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3301
Equity account is used to balance the balance sheet.
Definition: Account.h:149
const char * xaccAccountGetTypeStr(GNCAccountType type)
The xaccAccountGetTypeStr() routine returns a string suitable for use in the GUI/Interface.
Definition: Account.cpp:4518
Not a type.
Definition: Account.h:108
API for Transactions and Splits (journal entries)
The type used to store guids in C.
Definition: guid.h:75
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1490
void xaccAccountSetName(Account *acc, const char *str)
Set the account&#39;s name.
Definition: Account.cpp:2447
"select" and "new" commodity windows
Commodity handling public routines.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
const gchar * gnc_get_account_separator_string(void)
Returns the account separation character chosen by the user.
Definition: Account.cpp:201
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account&#39;s commodity.
Definition: Account.cpp:2632
const char * xaccAccountGetNotes(const Account *acc)
Get the account&#39;s notes.
Definition: Account.cpp:3416
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...
Definition: Account.cpp:2050