GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dialog-account.c
1 /********************************************************************\
2  * dialog-account.c -- window for creating and editing accounts for *
3  * GnuCash *
4  * Copyright (C) 2000 Dave Peticolas <[email protected]> *
5  * Copyright (C) 2003,2005,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 #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 "#ededececebeb"
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 
108  GtkWidget * opening_balance_edit;
109  GtkWidget * opening_balance_date_edit;
110  GtkWidget * opening_balance_page;
111 
112  GtkWidget * opening_equity_radio;
113  GtkWidget * transfer_account_scroll;
114  GtkWidget * transfer_tree;
115 
116  GtkWidget * tax_related_button;
117  GtkWidget * placeholder_button;
118  GtkWidget * hidden_button;
119 
120  gint component_id;
121 } AccountWindow;
122 
123 typedef struct _RenumberDialog
124 {
125  GtkWidget *dialog;
126  GtkWidget *prefix;
127  GtkWidget *interval;
128  GtkWidget *example1;
129  GtkWidget *example2;
130 
131  Account *parent;
132  gint num_children;
134 
136 static QofLogModule log_module = GNC_MOD_GUI;
137 
138 static GNCAccountType last_used_account_type = ACCT_TYPE_BANK;
139 
140 static GList *ac_destroy_cb_list = NULL;
141 
143 static void gnc_account_window_set_name (AccountWindow *aw);
144 
145 void gnc_account_renumber_prefix_changed_cb (GtkEditable *editable, RenumberDialog *data);
146 void gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
147 void gnc_account_renumber_response_cb (GtkDialog *dialog, gint response, RenumberDialog *data);
148 
149 void gnc_account_window_destroy_cb (GtkObject *object, gpointer data);
150 void opening_equity_cb (GtkWidget *w, gpointer data);
151 void gnc_account_name_changed_cb(GtkWidget *widget, gpointer data);
152 void gnc_account_color_default_cb(GtkWidget *widget, gpointer data);
153 void gnc_account_name_insert_text_cb (GtkWidget *entry,
154  const gchar *text,
155  gint length,
156  gint *position,
157  gpointer data);
158 
161 static void
162 aw_call_destroy_callbacks (Account* acc)
163 {
164  GList *node;
165  void (*cb)(Account*);
166 
167  for (node = ac_destroy_cb_list; node; node = node->next)
168  {
169  cb = node->data;
170  (cb)(acc);
171  }
172 }
173 
174 static Account *
175 aw_get_account (AccountWindow *aw)
176 {
177  if (!aw)
178  return NULL;
179 
180  return xaccAccountLookup (&aw->account, aw->book);
181 }
182 
183 static void
184 gnc_account_commodity_from_type (AccountWindow * aw, gboolean update)
185 {
186  dialog_commodity_mode new_mode;
187 
188  if (aw->type == ACCT_TYPE_TRADING)
189  new_mode = DIAG_COMM_ALL;
190  else if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
191  new_mode = DIAG_COMM_NON_CURRENCY;
192  else
193  new_mode = DIAG_COMM_CURRENCY;
194 
195  if (update && (new_mode != aw->commodity_mode))
196  {
197  gnc_general_select_set_selected(GNC_GENERAL_SELECT (aw->commodity_edit),
198  NULL);
199  }
200 
201  aw->commodity_mode = new_mode;
202 }
203 
204 /* Copy the account values to the GUI widgets */
205 static void
206 gnc_account_to_ui(AccountWindow *aw)
207 {
208  Account *account;
209  gnc_commodity * commodity;
210  const char *string;
211  GdkColor color;
212  gboolean flag, nonstd_scu;
213  gint index;
214 
215  ENTER("%p", aw);
216  account = aw_get_account (aw);
217  if (!account)
218  {
219  LEAVE("no account");
220  return;
221  }
222 
223  string = xaccAccountGetName (account);
224  if (string == NULL) string = "";
225  gtk_entry_set_text(GTK_ENTRY(aw->name_entry), string);
226 
227  string = xaccAccountGetDescription (account);
228  if (string == NULL) string = "";
229  gtk_entry_set_text(GTK_ENTRY(aw->description_entry), string);
230 
231  string = xaccAccountGetColor (account);
232  if (string == NULL) string = "";
233  if (gdk_color_parse(string, &color))
234  {
235  gtk_color_button_set_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color);
236  }
237 
238  commodity = xaccAccountGetCommodity (account);
239  gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
240  commodity);
241  gnc_account_commodity_from_type (aw, FALSE);
242 
243  nonstd_scu = xaccAccountGetNonStdSCU (account);
244  if (nonstd_scu)
245  {
246  index = xaccAccountGetCommoditySCUi(account);
247  index = log10(index) + 1;
248  }
249  else
250  {
251  index = 0;
252  }
253  gtk_combo_box_set_active(GTK_COMBO_BOX(aw->account_scu), index);
254 
255  string = xaccAccountGetCode (account);
256  if (string == NULL) string = "";
257  gtk_entry_set_text(GTK_ENTRY(aw->code_entry), string);
258 
259  string = xaccAccountGetNotes (account);
260  if (string == NULL) string = "";
261 
262  gtk_text_buffer_set_text (aw->notes_text_buffer, string, strlen(string));
263 
264  flag = xaccAccountGetTaxRelated (account);
265  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->tax_related_button),
266  flag);
267 
268  flag = xaccAccountGetPlaceholder (account);
269  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->placeholder_button),
270  flag);
271 
272  flag = xaccAccountGetHidden (account);
273  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->hidden_button),
274  flag);
275  LEAVE(" ");
276 }
277 
278 
279 static gboolean
280 gnc_account_create_transfer_balance (QofBook *book,
281  Account *account,
282  Account *transfer,
283  gnc_numeric balance,
284  time64 date)
285 {
286  Transaction *trans;
287  Split *split;
288 
289  if (gnc_numeric_zero_p (balance))
290  return TRUE;
291 
292  g_return_val_if_fail (account != NULL, FALSE);
293  g_return_val_if_fail (transfer != NULL, FALSE);
294 
295  xaccAccountBeginEdit (account);
296  xaccAccountBeginEdit (transfer);
297 
298  trans = xaccMallocTransaction (book);
299 
300  xaccTransBeginEdit (trans);
301 
302  xaccTransSetCurrency (trans, gnc_account_or_default_currency (account, NULL));
304  xaccTransSetDescription (trans, _("Opening Balance"));
305 
306  split = xaccMallocSplit (book);
307 
308  xaccTransAppendSplit (trans, split);
309  xaccAccountInsertSplit (account, split);
310 
311  xaccSplitSetAmount (split, balance);
312  xaccSplitSetValue (split, balance);
313 
314  balance = gnc_numeric_neg (balance);
315 
316  split = xaccMallocSplit (book);
317 
318  xaccTransAppendSplit (trans, split);
319  xaccAccountInsertSplit (transfer, split);
320 
321  xaccSplitSetAmount (split, balance);
322  xaccSplitSetValue (split, balance);
323 
324  xaccTransCommitEdit (trans);
325  xaccAccountCommitEdit (transfer);
326  xaccAccountCommitEdit (account);
327 
328  return TRUE;
329 }
330 
331 /* Record the GUI values into the Account structure */
332 static void
333 gnc_ui_to_account(AccountWindow *aw)
334 {
335  Account *account;
336  gnc_commodity *commodity;
337  Account *parent_account;
338  const char *old_string;
339  const char *string;
340  GdkColor color;
341  gboolean flag;
342  gnc_numeric balance;
343  gboolean use_equity, nonstd;
344  time64 date;
345  gint index, old_scu, new_scu;
346  GtkTextIter start, end;
347 
348  account = aw_get_account (aw);
349  if (!account)
350  {
351  LEAVE("no account");
352  return;
353  }
354 
355  if (aw->dialog_type == EDIT_ACCOUNT
356  && aw->type != xaccAccountGetType (account))
357  {
358  /* Just refreshing won't work. */
359  aw_call_destroy_callbacks (account);
360  }
361 
362  xaccAccountBeginEdit (account);
363 
364  if (aw->type != xaccAccountGetType (account))
365  xaccAccountSetType (account, aw->type);
366 
367  last_used_account_type = aw->type;
368 
369  string = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
370  old_string = xaccAccountGetName (account);
371  if (g_strcmp0 (string, old_string) != 0)
372  xaccAccountSetName (account, string);
373 
374  string = gtk_entry_get_text (GTK_ENTRY(aw->description_entry));
375  old_string = xaccAccountGetDescription (account);
376  if (g_strcmp0 (string, old_string) != 0)
377  xaccAccountSetDescription (account, string);
378 
379  gtk_color_button_get_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color );
380  string = gdk_color_to_string(&color);
381  if (g_strcmp0 (string, DEFAULT_COLOR) == 0)
382  string = "Not Set";
383 
384  old_string = xaccAccountGetColor (account);
385  if (g_strcmp0 (string, old_string) != 0)
386  xaccAccountSetColor (account, string);
387 
388  commodity = (gnc_commodity *)
389  gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
390  if (commodity &&
391  !gnc_commodity_equiv(commodity, xaccAccountGetCommodity (account)))
392  {
393  xaccAccountSetCommodity (account, commodity);
394  old_scu = 0;
395  }
396  else
397  {
398  old_scu = xaccAccountGetCommoditySCU(account);
399  }
400 
401  index = gtk_combo_box_get_active(GTK_COMBO_BOX(aw->account_scu));
402  nonstd = (index != 0);
403  if (nonstd != xaccAccountGetNonStdSCU(account))
404  xaccAccountSetNonStdSCU(account, nonstd);
405  new_scu = (nonstd ? pow(10, index - 1) : gnc_commodity_get_fraction(commodity));
406  if (old_scu != new_scu)
407  xaccAccountSetCommoditySCU(account, new_scu);
408 
409  string = gtk_entry_get_text (GTK_ENTRY(aw->code_entry));
410  old_string = xaccAccountGetCode (account);
411  if (g_strcmp0 (string, old_string) != 0)
412  xaccAccountSetCode (account, string);
413 
414  gtk_text_buffer_get_start_iter (aw->notes_text_buffer, &start);
415  gtk_text_buffer_get_end_iter (aw->notes_text_buffer, &end);
416  string = gtk_text_buffer_get_text (aw->notes_text_buffer, &start, &end, FALSE);
417  old_string = xaccAccountGetNotes (account);
418  if (null_strcmp (string, old_string) != 0)
419  xaccAccountSetNotes (account, string);
420 
421  flag =
422  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->tax_related_button));
423  if (xaccAccountGetTaxRelated (account) != flag)
424  xaccAccountSetTaxRelated (account, flag);
425 
426  flag =
427  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->placeholder_button));
428  if (xaccAccountGetPlaceholder (account) != flag)
429  xaccAccountSetPlaceholder (account, flag);
430 
431  flag =
432  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->hidden_button));
433  if (xaccAccountGetHidden (account) != flag)
434  xaccAccountSetHidden (account, flag);
435 
436  parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
437 
438  if (parent_account == NULL)
439  parent_account = gnc_book_get_root_account(aw->book);
440  if (parent_account != gnc_account_get_parent (account))
441  gnc_account_append_child (parent_account, account);
442 
443  xaccAccountCommitEdit (account);
444 
445  balance = gnc_amount_edit_get_amount
446  (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
447 
448  if (gnc_numeric_zero_p (balance))
449  {
450  LEAVE("zero balance");
451  return;
452  }
453 
454  if (gnc_reverse_balance (account))
455  balance = gnc_numeric_neg (balance);
456 
457  date = gnc_date_edit_get_date (
458  GNC_DATE_EDIT (aw->opening_balance_date_edit));
459 
460  use_equity = gtk_toggle_button_get_active
461  (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
462 
463  if (use_equity)
464  {
465  if (!gnc_account_create_opening_balance (account, balance, date, aw->book))
466  {
467  const char *message = _("Could not create opening balance.");
468  gnc_error_dialog(aw->dialog, "%s", message);
469  }
470  }
471  else
472  {
473  Account *transfer = NULL;
474 
475  transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
476  if (!transfer)
477  {
478  LEAVE("no transfer account");
479  return;
480  }
481 
482  gnc_account_create_transfer_balance (aw->book, account, transfer, balance, date);
483  }
484  LEAVE(" ");
485 }
486 
487 
488 static void
489 set_children_types (Account *account, GNCAccountType type)
490 {
491  GList *children, *iter;
492 
493  children = gnc_account_get_children(account);
494  if (children == NULL)
495  return;
496 
497  for (iter = children; iter; iter = iter->next)
498  {
499  account = iter->data;
500  if (type == xaccAccountGetType(account))
501  continue;
502 
503  /* Just refreshing won't work. */
504  aw_call_destroy_callbacks (account);
505 
506  xaccAccountBeginEdit (account);
507  xaccAccountSetType (account, type);
508  xaccAccountCommitEdit (account);
509 
510  set_children_types (account, type);
511  }
512  g_list_free(children);
513 }
514 
515 static void
516 make_children_compatible (AccountWindow *aw)
517 {
518  Account *account;
519 
520  g_return_if_fail (aw);
521 
522  if (aw->dialog_type == NEW_ACCOUNT)
523  return;
524 
525  account = aw_get_account (aw);
526  g_return_if_fail (account);
527 
528  if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
529  return;
530 
531  set_children_types (account, aw->type);
532 }
533 
534 
535 static void
536 gnc_finish_ok (AccountWindow *aw)
537 {
538  ENTER("aw %p", aw);
539  gnc_suspend_gui_refresh ();
540 
541  /* make the account changes */
542  make_children_compatible (aw);
543  gnc_ui_to_account (aw);
544 
545  gnc_resume_gui_refresh ();
546 
547  /* do it all again, if needed */
548  if ((aw->dialog_type == NEW_ACCOUNT) && aw->next_name && *aw->next_name)
549  {
550  gnc_commodity *commodity;
551  Account *parent;
552  Account *account;
553 
554  gnc_suspend_gui_refresh ();
555 
556  parent = aw_get_account (aw);
557  account = xaccMallocAccount (aw->book);
558  aw->account = *xaccAccountGetGUID (account);
559  aw->type = xaccAccountGetType (parent);
560 
561  xaccAccountSetName (account, *aw->next_name);
562  aw->next_name++;
563 
564  gnc_account_to_ui (aw);
565 
566  gnc_account_window_set_name (aw);
567 
568  commodity = xaccAccountGetCommodity (parent);
569  gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
570  commodity);
571  gnc_account_commodity_from_type (aw, FALSE);
572 
574  GNC_TREE_VIEW_ACCOUNT (aw->parent_tree), parent);
575 
576  gnc_resume_gui_refresh ();
577  LEAVE("1");
578  return;
579  }
580 
581  /* save for posterity */
582  aw->created_account = aw_get_account (aw);
583 
584  /* so it doesn't get freed on close */
585  aw->account = *guid_null ();
586 
587  gnc_close_gui_component (aw->component_id);
588  LEAVE("2");
589 }
590 
591 
592 static void
593 add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data)
594 {
595  GtkExpander *expander = GTK_EXPANDER (object);
596  Account *account = data;
597  GtkWidget *scrolled_window;
598  GtkTreeView *view;
599 
600  if (gtk_expander_get_expanded (expander) &&
601  !gtk_bin_get_child (GTK_BIN (expander)))
602  {
603 
604  view = gnc_tree_view_account_new_with_root (account, FALSE);
605 
606  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
607  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
608  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
609  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
610  GTK_SHADOW_IN);
611  gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (view));
612 
613  gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
614  gtk_widget_show_all (scrolled_window);
615  }
616 }
617 
618 /* Check whether there are children needing a type adjustment because of a
619  a change to an incompatible type (like after some reparenting) and let the
620  user decide whether he wants that */
621 static gboolean
622 verify_children_compatible (AccountWindow *aw)
623 {
624  Account *account;
625  GtkWidget *dialog, *vbox, *hbox, *label, *expander;
626  gchar *str;
627  gboolean result;
628 
629  if (aw == NULL)
630  return FALSE;
631 
632  account = aw_get_account (aw);
633  if (!account)
634  return FALSE;
635 
636  if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
637  return TRUE;
638 
639  if (gnc_account_n_children(account) == 0)
640  return TRUE;
641 
642  dialog = gtk_dialog_new_with_buttons ("",
643  GTK_WINDOW(aw->dialog),
644  GTK_DIALOG_DESTROY_WITH_PARENT |
645  GTK_DIALOG_MODAL,
646  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
647  GTK_STOCK_OK, GTK_RESPONSE_OK,
648  NULL);
649 
650  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
651 
652  hbox = gtk_hbox_new (FALSE, 12);
653  vbox = gtk_vbox_new (FALSE, 12);
654 
655  gtk_box_pack_start (
656  GTK_BOX (hbox),
657  gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG),
658  FALSE, FALSE, 0);
659 
660  /* primary label */
661  label = gtk_label_new (_("Give the children the same type?"));
662  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
663  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
664  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
665  {
666  gint size;
667  PangoFontDescription *font_desc;
668 
669  size = pango_font_description_get_size (label->style->font_desc);
670  font_desc = pango_font_description_new ();
671  pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
672  pango_font_description_set_size (font_desc, size * PANGO_SCALE_LARGE);
673  gtk_widget_modify_font (label, font_desc);
674  pango_font_description_free (font_desc);
675  }
676  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
677 
678  /* secondary label */
679  str = g_strdup_printf (_("The children of the edited account have to be "
680  "changed to type \"%s\" to make them compatible."),
681  xaccAccountGetTypeStr (aw->type));
682  label = gtk_label_new (str);
683  g_free (str);
684  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
685  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
686  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
687  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
688 
689  /* children */
690  expander = gtk_expander_new_with_mnemonic (_("_Show children accounts"));
691  gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
692  g_signal_connect (G_OBJECT (expander), "notify::expanded",
693  G_CALLBACK (add_children_to_expander), account);
694  gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
695 
696  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
697 
698  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
699  TRUE, TRUE, 0);
700 
701  /* spacings */
702  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
703  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
704  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
705  gtk_container_set_border_width (
706  GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
707  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
708 
709  gtk_widget_show_all (hbox);
710 
711  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
712 
713  result = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
714 
715  gtk_widget_destroy(dialog);
716 
717  return result;
718 }
719 
720 
721 static gboolean
722 gnc_filter_parent_accounts (Account *account, gpointer data)
723 {
724  AccountWindow *aw = data;
725  Account *aw_account = aw_get_account (aw);
726 
727  if (account == NULL)
728  return FALSE;
729 
730  if (aw_account == NULL)
731  return FALSE;
732 
733  if (gnc_account_is_root(account))
734  return TRUE;
735 
736  if (account == aw_account)
737  return FALSE;
738 
739  if (xaccAccountHasAncestor(account, aw_account))
740  return FALSE;
741 
742  return TRUE;
743 }
744 
745 
746 static gboolean
747 gnc_common_ok (AccountWindow *aw)
748 {
749  Account *root, *account, *parent;
750  gnc_commodity * commodity;
751  gchar *fullname, *fullname_parent;
752  const gchar *name, *separator;
753 
754  ENTER("aw %p", aw);
755  root = gnc_book_get_root_account (aw->book);
756 
757  separator = gnc_get_account_separator_string();
758 
759  /* check for valid name */
760  name = gtk_entry_get_text(GTK_ENTRY(aw->name_entry));
761  if (g_strcmp0(name, "") == 0)
762  {
763  const char *message = _("The account must be given a name.");
764  gnc_error_dialog(aw->dialog, "%s", message);
765  LEAVE("bad name");
766  return FALSE;
767  }
768 
769  /* check for a duplicate name */
771  (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
772  if (parent == NULL)
773  {
774  account = gnc_account_lookup_by_full_name(root, name);
775  }
776  else
777  {
778  fullname_parent = gnc_account_get_full_name(parent);
779  fullname = g_strconcat(fullname_parent, separator, name, NULL);
780 
781  account = gnc_account_lookup_by_full_name(root, fullname);
782 
783  g_free(fullname_parent);
784  g_free(fullname);
785  }
786  if ((account != NULL) &&
787  !guid_equal(&aw->account, xaccAccountGetGUID (account)))
788  {
789  const char *message = _("There is already an account with that name.");
790  gnc_error_dialog(aw->dialog, "%s", message);
791  LEAVE("duplicate name");
792  return FALSE;
793  }
794 
795  /* Parent check, probably not needed, but be safe */
796  if (!gnc_filter_parent_accounts(parent, aw))
797  {
798  const char *message = _("You must choose a valid parent account.");
799  gnc_error_dialog(aw->dialog, "%s", message);
800  LEAVE("invalid parent");
801  return FALSE;
802  }
803 
804  /* check for valid type */
805  if (aw->type == ACCT_TYPE_INVALID)
806  {
807  const char *message = _("You must select an account type.");
808  gnc_error_dialog(aw->dialog, "%s", message);
809  LEAVE("invalid type");
810  return FALSE;
811  }
812 
813  /* check whether the types of child and parent are compatible */
814  if (!xaccAccountTypesCompatible (aw->type, xaccAccountGetType (parent)))
815  {
816  const char *message = _("The selected account type is incompatible with "
817  "the one of the selected parent.");
818  gnc_error_dialog(aw->dialog, "%s", message);
819  LEAVE("incompatible types");
820  return FALSE;
821  }
822 
823  /* check for commodity */
824  commodity = (gnc_commodity *)
825  gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
826  if (!commodity)
827  {
828  const char *message = _("You must choose a commodity.");
829  gnc_error_dialog(aw->dialog, "%s", message);
830  LEAVE("invalid commodity");
831  return FALSE;
832  }
833 
834  LEAVE("passed");
835  return TRUE;
836 }
837 
838 static void
839 gnc_edit_account_ok(AccountWindow *aw)
840 {
841  Account *account;
842 
843  ENTER("aw %p", aw);
844 
845  account = aw_get_account (aw);
846  if (!account)
847  {
848  LEAVE(" ");
849  return;
850  }
851 
852  if (!gnc_common_ok(aw))
853  {
854  LEAVE(" ");
855  return;
856  }
857 
858  if (!verify_children_compatible (aw))
859  {
860  LEAVE(" ");
861  return;
862  }
863 
864  gnc_finish_ok (aw);
865  LEAVE(" ");
866 }
867 
868 
869 static void
870 gnc_new_account_ok (AccountWindow *aw)
871 {
872  gnc_numeric balance;
873 
874  ENTER("aw %p", aw);
875 
876  if (!gnc_common_ok(aw))
877  {
878  LEAVE(" ");
879  return;
880  }
881 
882  if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (aw->opening_balance_edit)))
883  {
884  const char *message = _("You must enter a valid opening balance "
885  "or leave it blank.");
886  gnc_error_dialog(aw->dialog, "%s", message);
887  LEAVE(" ");
888  return;
889  }
890 
891  balance = gnc_amount_edit_get_amount
892  (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
893 
894  if (!gnc_numeric_zero_p (balance))
895  {
896  gboolean use_equity;
897 
898  use_equity = gtk_toggle_button_get_active
899  (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
900 
901  if (!use_equity)
902  {
903  Account *transfer = NULL;
904 
905  transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
906  if (!transfer)
907  {
908  const char *message = _("You must select a transfer account or choose"
909  " the opening balances equity account.");
910  gnc_error_dialog(aw->dialog, "%s", message);
911  LEAVE(" ");
912  return;
913  }
914  }
915  }
916 
917  gnc_finish_ok (aw);
918  LEAVE(" ");
919 }
920 
921 static void
922 gnc_account_window_response_cb (GtkDialog *dialog,
923  gint response,
924  gpointer data)
925 {
926  AccountWindow *aw = data;
927 
928  ENTER("dialog %p, response %d, aw %p", dialog, response, aw);
929  switch (response)
930  {
931  case GTK_RESPONSE_OK:
932  switch (aw->dialog_type)
933  {
934  case NEW_ACCOUNT:
935  DEBUG("new acct dialog, OK");
936  gnc_new_account_ok (aw);
937  break;
938  case EDIT_ACCOUNT:
939  DEBUG("edit acct dialog, OK");
940  gnc_edit_account_ok (aw);
941  break;
942  default:
943  g_assert_not_reached ();
944  return;
945  }
946  break;
947  case GTK_RESPONSE_HELP:
948  switch (aw->dialog_type)
949  {
950  case NEW_ACCOUNT:
951  DEBUG("new acct dialog, HELP");
952  gnc_gnome_help(HF_HELP, HL_ACC);
953  break;
954  case EDIT_ACCOUNT:
955  DEBUG("edit acct dialog, HELP");
956  gnc_gnome_help(HF_HELP, HL_ACCEDIT);
957  break;
958  default:
959  g_assert_not_reached ();
960  return;
961  }
962  break;
963  case GTK_RESPONSE_CANCEL:
964  default:
965  DEBUG("CANCEL");
966  gnc_close_gui_component (aw->component_id);
967  break;
968  }
969  LEAVE(" ");
970 }
971 
972 void
973 gnc_account_window_destroy_cb (GtkObject *object, gpointer data)
974 {
975  AccountWindow *aw = data;
976  Account *account;
977 
978  ENTER("object %p, aw %p", object, aw);
979  account = aw_get_account (aw);
980 
981  gnc_suspend_gui_refresh ();
982 
983  switch (aw->dialog_type)
984  {
985  case NEW_ACCOUNT:
986  if (account != NULL)
987  {
988  xaccAccountBeginEdit (account);
989  xaccAccountDestroy (account);
990  aw->account = *guid_null ();
991  }
992 
993  DEBUG ("account add window destroyed\n");
994  break;
995 
996  case EDIT_ACCOUNT:
997  break;
998 
999  default:
1000  PERR ("unexpected dialog type\n");
1001  gnc_resume_gui_refresh ();
1002  LEAVE(" ");
1003  return;
1004  }
1005 
1006  gnc_unregister_gui_component (aw->component_id);
1007 
1008  gnc_resume_gui_refresh ();
1009 
1010  if (aw->subaccount_names)
1011  {
1012  g_strfreev(aw->subaccount_names);
1013  aw->subaccount_names = NULL;
1014  aw->next_name = NULL;
1015  }
1016 
1017  g_free (aw);
1018  LEAVE(" ");
1019 }
1020 
1021 static void
1022 gnc_account_parent_changed_cb (GtkTreeSelection *selection, gpointer data)
1023 {
1024  AccountWindow *aw = data;
1025  Account *parent_account;
1026  guint32 types, old_types;
1027  GtkTreeModel *type_model;
1028  GtkTreeSelection *type_selection;
1029  gboolean scroll_to = FALSE;
1030 
1031  g_return_if_fail (aw);
1032 
1034  GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
1035  if (!parent_account)
1036  return;
1037 
1038  if (gnc_account_is_root(parent_account))
1039  {
1040  types = aw->valid_types;
1041  }
1042  else
1043  {
1044  types = aw->valid_types &
1046  }
1047 
1048  type_model = gtk_tree_view_get_model (GTK_TREE_VIEW (aw->type_view));
1049  if (!type_model)
1050  return;
1051 
1052  if (aw->type != aw->preferred_account_type &&
1053  (types & (1 << aw->preferred_account_type)) != 0)
1054  {
1055  /* we can change back to the preferred account type */
1056  aw->type = aw->preferred_account_type;
1057  scroll_to = TRUE;
1058  }
1059  else if ((types & (1 << aw->type)) == 0)
1060  {
1061  /* our type is invalid now */
1062  aw->type = ACCT_TYPE_INVALID;
1063  }
1064  else
1065  {
1066  /* no type change, but maybe list of valid types changed */
1067  old_types = gnc_tree_model_account_types_get_mask (type_model);
1068  if (old_types != types)
1069  scroll_to = TRUE;
1070  }
1071 
1072  gnc_tree_model_account_types_set_mask (type_model, types);
1073 
1074  if (scroll_to)
1075  {
1076  type_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->type_view));
1077  gnc_tree_model_account_types_set_selection(type_selection, 1 << aw->type);
1078  }
1079 
1080  gnc_account_window_set_name(aw);
1081 }
1082 
1083 static void
1084 gnc_account_type_changed_cb (GtkTreeSelection *selection, gpointer data)
1085 {
1086  AccountWindow *aw = data;
1087  gboolean sensitive;
1088  GNCAccountType type_id;
1089 
1090  g_return_if_fail (aw != NULL);
1091 
1092  sensitive = FALSE;
1093 
1094  type_id = gnc_tree_model_account_types_get_selection_single(selection);
1095  if (type_id == ACCT_TYPE_NONE)
1096  {
1097  aw->type = ACCT_TYPE_INVALID;
1098  }
1099  else
1100  {
1101  aw->type = type_id;
1102  aw->preferred_account_type = type_id;
1103 
1104  gnc_account_commodity_from_type (aw, TRUE);
1105 
1106  sensitive = (aw->type != ACCT_TYPE_EQUITY &&
1107  aw->type != ACCT_TYPE_CURRENCY &&
1108  aw->type != ACCT_TYPE_STOCK &&
1109  aw->type != ACCT_TYPE_MUTUAL &&
1110  aw->type != ACCT_TYPE_TRADING);
1111  }
1112 
1113  gtk_widget_set_sensitive (aw->opening_balance_page, sensitive);
1114 
1115  if (!sensitive)
1116  {
1117  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
1118  gnc_numeric_zero ());
1119  }
1120 }
1121 
1122 static void
1123 gnc_account_type_view_create (AccountWindow *aw)
1124 {
1125  GtkTreeModel *model;
1126  GtkTreeSelection *selection;
1127  GtkCellRenderer *renderer;
1128  GtkTreeView *view;
1129 
1130  if (aw->valid_types == 0)
1131  {
1132  /* no type restrictions, choose aw->type */
1133  aw->valid_types = xaccAccountTypesValid () | (1 << aw->type);
1134  aw->preferred_account_type = aw->type;
1135  }
1136  else if ((aw->valid_types & (1 << aw->type)) != 0)
1137  {
1138  /* aw->type is valid */
1139  aw->preferred_account_type = aw->type;
1140  }
1141  else if ((aw->valid_types & (1 << last_used_account_type)) != 0)
1142  {
1143  /* last used account type is valid */
1144  aw->type = last_used_account_type;
1145  aw->preferred_account_type = last_used_account_type;
1146  }
1147  else
1148  {
1149  /* choose first valid account type */
1150  int i;
1151  aw->preferred_account_type = aw->type;
1152  aw->type = ACCT_TYPE_INVALID;
1153  for (i = 0; i < 32; i++)
1154  if ((aw->valid_types & (1 << i)) != 0)
1155  {
1156  aw->type = i;
1157  break;
1158  }
1159  }
1160 
1161  model = gnc_tree_model_account_types_filter_using_mask (aw->valid_types);
1162 
1163  view = GTK_TREE_VIEW (aw->type_view);
1164  gtk_tree_view_set_model (view, model);
1165  g_object_unref (G_OBJECT (model));
1166 
1167  renderer = gtk_cell_renderer_text_new ();
1168  gtk_tree_view_insert_column_with_attributes (
1169  view, -1, NULL, renderer,
1170  "text", GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME,
1171  NULL);
1172  gtk_tree_view_set_search_column (view, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME);
1173 
1174  selection = gtk_tree_view_get_selection (view);
1175  g_signal_connect (G_OBJECT (selection), "changed",
1176  G_CALLBACK (gnc_account_type_changed_cb), aw);
1177 
1178  gnc_tree_model_account_types_set_selection(selection, 1 << aw->type);
1179 }
1180 
1181 void
1182 gnc_account_name_insert_text_cb (GtkWidget *entry,
1183  const gchar *text,
1184  gint length,
1185  gint *position,
1186  gpointer data)
1187 {
1188  GtkEditable *editable = GTK_EDITABLE( entry );
1189  const gchar *separator = NULL;
1190  gchar **strsplit;
1191 
1192  separator = gnc_get_account_separator_string();
1193  strsplit = g_strsplit ( text, separator, 0 );
1194  if ( strsplit[1] != NULL )
1195  {
1196  gchar *result = g_strjoinv ( NULL, strsplit );
1197  g_signal_handlers_block_by_func ( G_OBJECT ( editable ),
1198  G_CALLBACK ( gnc_account_name_insert_text_cb ),
1199  data );
1200  gtk_editable_insert_text ( editable, result, g_utf8_strlen ( result, -1 ), position );
1201  g_signal_handlers_unblock_by_func ( G_OBJECT ( editable ),
1202  G_CALLBACK ( gnc_account_name_insert_text_cb ),
1203  data );
1204  g_signal_stop_emission_by_name (G_OBJECT ( editable ), "insert_text");
1205  g_free (result);
1206  }
1207 
1208  g_strfreev ( strsplit );
1209 }
1210 
1211 void
1212 gnc_account_name_changed_cb(GtkWidget *widget, gpointer data)
1213 {
1214  AccountWindow *aw = data;
1215 
1216  gnc_account_window_set_name (aw);
1217 }
1218 
1219 void
1220 gnc_account_color_default_cb(GtkWidget *widget, gpointer data)
1221 {
1222  GdkColor color;
1223  AccountWindow *aw = data;
1224 
1225  gdk_color_parse( DEFAULT_COLOR, &color);
1226  gtk_color_button_set_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color);
1227 
1228 }
1229 
1230 static void
1231 commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
1232 {
1233  AccountWindow *aw = data;
1234  gnc_commodity *currency;
1235  GtkTreeSelection *selection;
1236 
1237  currency = (gnc_commodity *) gnc_general_select_get_selected (gsl);
1238  if (!currency)
1239  return;
1240 
1241  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
1242  gnc_commodity_get_fraction (currency));
1243  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
1244  gnc_commodity_print_info (currency, FALSE));
1245 
1246  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->transfer_tree));
1247  gtk_tree_selection_unselect_all (selection);
1248 }
1249 
1250 static gboolean
1251 account_commodity_filter (GtkTreeSelection *selection,
1252  GtkTreeModel *unused_model,
1253  GtkTreePath *s_path,
1254  gboolean path_currently_selected,
1255  gpointer user_data)
1256 {
1257  gnc_commodity *commodity;
1258  AccountWindow *aw;
1259  Account *account;
1260 
1261  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
1262 
1263  aw = user_data;
1264 
1265  if (path_currently_selected)
1266  {
1267  /* already selected, don't waste time. */
1268  return TRUE;
1269  }
1270 
1271  account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree), s_path);
1272  if (!account)
1273  {
1274  return FALSE;
1275  }
1276 
1277  commodity = (gnc_commodity *)
1278  gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
1279 
1280  return gnc_commodity_equiv (xaccAccountGetCommodity (account), commodity);
1281 }
1282 
1283 void
1284 opening_equity_cb (GtkWidget *w, gpointer data)
1285 {
1286  AccountWindow *aw = data;
1287  gboolean use_equity;
1288 
1289  use_equity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
1290 
1291  gtk_widget_set_sensitive (aw->transfer_account_scroll, !use_equity);
1292 }
1293 
1294 /********************************************************************\
1295  * gnc_account_window_create *
1296  * creates a window to create a new account. *
1297  * *
1298  * Args: aw - the information structure for this window *
1299  * Return: the created window *
1300  \*******************************************************************/
1301 static void
1302 gnc_account_window_create(AccountWindow *aw)
1303 {
1304  GtkWidget *amount;
1305  GtkWidget *date_edit;
1306  GObject *awo;
1307  GtkWidget *box;
1308  GtkWidget *label;
1309  GtkBuilder *builder;
1310  GtkTreeSelection *selection;
1311 
1312  ENTER("aw %p, modal %d", aw, aw->modal);
1313  builder = gtk_builder_new();
1314  gnc_builder_add_from_file (builder, "dialog-account.glade", "fraction_liststore");
1315  gnc_builder_add_from_file (builder, "dialog-account.glade", "Account Dialog");
1316 
1317  aw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Account Dialog"));
1318  awo = G_OBJECT (aw->dialog);
1319 
1320  g_object_set_data (awo, "dialog_info", aw);
1321 
1322  if (!aw->modal)
1323  g_signal_connect (awo, "response",
1324  G_CALLBACK (gnc_account_window_response_cb), aw);
1325  else
1326  gtk_window_set_modal (GTK_WINDOW (aw->dialog), TRUE);
1327 
1328  aw->notebook = GTK_WIDGET(gtk_builder_get_object (builder, "account_notebook"));
1329  aw->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
1330  aw->description_entry = GTK_WIDGET(gtk_builder_get_object (builder, "description_entry"));
1331  aw->color_entry_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_entry_button"));
1332  aw->color_default_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_default_button"));
1333  aw->code_entry = GTK_WIDGET(gtk_builder_get_object (builder, "code_entry"));
1334  aw->notes_text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (GTK_WIDGET(gtk_builder_get_object (builder, "notes_text"))));
1335 
1336  box = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_hbox"));
1337  aw->commodity_edit = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
1338  gnc_commodity_edit_get_string,
1339  gnc_commodity_edit_new_select,
1340  &aw->commodity_mode);
1341  gtk_box_pack_start(GTK_BOX(box), aw->commodity_edit, TRUE, TRUE, 0);
1342  gtk_widget_show (aw->commodity_edit);
1343 
1344  label = GTK_WIDGET(gtk_builder_get_object (builder, "security_label"));
1345  gnc_general_select_make_mnemonic_target (GNC_GENERAL_SELECT(aw->commodity_edit), label);
1346 
1347  g_signal_connect (G_OBJECT (aw->commodity_edit), "changed",
1348  G_CALLBACK (commodity_changed_cb), aw);
1349 
1350  aw->account_scu = GTK_WIDGET(gtk_builder_get_object (builder, "account_scu"));
1351 
1352  box = GTK_WIDGET(gtk_builder_get_object (builder, "parent_scroll"));
1353 
1354  aw->parent_tree = gnc_tree_view_account_new(TRUE);
1355  gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->parent_tree));
1356  gtk_widget_show(GTK_WIDGET(aw->parent_tree));
1357  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->parent_tree));
1358  g_signal_connect (G_OBJECT (selection), "changed",
1359  G_CALLBACK (gnc_account_parent_changed_cb), aw);
1360 
1361  aw->tax_related_button = GTK_WIDGET(gtk_builder_get_object (builder, "tax_related_button"));
1362  aw->placeholder_button = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_button"));
1363  aw->hidden_button = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_button"));
1364 
1365  box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_box"));
1366  amount = gnc_amount_edit_new ();
1367  aw->opening_balance_edit = amount;
1368  gtk_box_pack_start(GTK_BOX(box), amount, TRUE, TRUE, 0);
1369  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
1370  gtk_widget_show (amount);
1371 
1372  label = GTK_WIDGET(gtk_builder_get_object (builder, "balance_label"));
1373  gtk_label_set_mnemonic_widget (GTK_LABEL(label), amount);
1374 
1375  box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_date_box"));
1376  date_edit = gnc_date_edit_new (gnc_time (NULL), 1, 1);
1377  aw->opening_balance_date_edit = date_edit;
1378  gtk_box_pack_start(GTK_BOX(box), date_edit, TRUE, TRUE, 0);
1379  gtk_widget_show (date_edit);
1380 
1381  aw->opening_balance_page =
1382  gtk_notebook_get_nth_page (GTK_NOTEBOOK (aw->notebook), 1);
1383 
1384  aw->opening_equity_radio = GTK_WIDGET(gtk_builder_get_object (builder,
1385  "opening_equity_radio"));
1386 
1387  box = GTK_WIDGET(gtk_builder_get_object (builder, "transfer_account_scroll"));
1388  aw->transfer_account_scroll = box;
1389 
1390  aw->transfer_tree = GTK_WIDGET(gnc_tree_view_account_new(FALSE));
1391  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->transfer_tree));
1392  gtk_tree_selection_set_select_function(selection, account_commodity_filter, aw, NULL);
1393 
1394  gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->transfer_tree));
1395  gtk_widget_show (GTK_WIDGET(aw->transfer_tree));
1396 
1397  label = GTK_WIDGET(gtk_builder_get_object (builder, "parent_label"));
1398  gtk_label_set_mnemonic_widget (GTK_LABEL(label), GTK_WIDGET(aw->parent_tree));
1399 
1400  /* This goes at the end so the select callback has good data. */
1401  aw->type_view = GTK_WIDGET(gtk_builder_get_object (builder, "type_view"));
1402  gnc_account_type_view_create (aw);
1403 
1404  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog));
1405 
1406  gtk_widget_grab_focus(GTK_WIDGET(aw->name_entry));
1407 
1408  gtk_builder_connect_signals(builder, aw);
1409  g_object_unref(G_OBJECT(builder));
1410 
1411  LEAVE(" ");
1412 }
1413 
1414 
1415 static char *
1416 get_ui_fullname (AccountWindow *aw)
1417 {
1418  Account *parent_account;
1419  char *fullname;
1420  const gchar *name;
1421 
1422  name = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
1423  if (!name || *name == '\0')
1424  name = _("<No name>");
1425 
1426  parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
1427 
1428  if (parent_account && !gnc_account_is_root(parent_account))
1429  {
1430  char *parent_name;
1431  const gchar *separator;
1432 
1433  parent_name = gnc_account_get_full_name (parent_account);
1434 
1435  separator = gnc_get_account_separator_string ();
1436  fullname = g_strconcat (parent_name, separator, name, NULL);
1437 
1438  g_free (parent_name);
1439  }
1440  else
1441  fullname = g_strdup (name);
1442 
1443  return fullname;
1444 }
1445 
1446 static void
1447 gnc_account_window_set_name (AccountWindow *aw)
1448 {
1449  char *fullname;
1450  char *title;
1451 
1452  if (!aw || !aw->parent_tree)
1453  return;
1454 
1455  fullname = get_ui_fullname (aw);
1456 
1457  if (aw->dialog_type == EDIT_ACCOUNT)
1458  title = g_strconcat(_("Edit Account"), " - ", fullname, NULL);
1459  else if (aw->next_name && (g_strv_length(aw->next_name) > 0))
1460  {
1461  const char *format = _("(%d) New Accounts");
1462  char *prefix;
1463 
1464  prefix = g_strdup_printf (format, g_strv_length(aw->next_name) + 1);
1465 
1466  title = g_strconcat (prefix, " - ", fullname, " ...", NULL);
1467 
1468  g_free (prefix);
1469  }
1470  else
1471  title = g_strconcat (_("New Account"), " - ", fullname, NULL);
1472 
1473  gtk_window_set_title (GTK_WINDOW(aw->dialog), title);
1474 
1475  g_free (fullname);
1476  g_free (title);
1477 }
1478 
1479 
1480 static void
1481 close_handler (gpointer user_data)
1482 {
1483  AccountWindow *aw = user_data;
1484 
1485  ENTER("aw %p, modal %d", aw, aw->modal);
1486  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog));
1487 
1488  gtk_widget_destroy (GTK_WIDGET (aw->dialog));
1489  LEAVE(" ");
1490 }
1491 
1492 
1493 /********************************************************************\
1494  * gnc_ui_refresh_account_window *
1495  * refreshes the edit window *
1496  * *
1497  * Args: aw - the account window to refresh *
1498  * Return: none *
1499 \********************************************************************/
1500 static void
1501 gnc_ui_refresh_account_window (AccountWindow *aw)
1502 {
1503  if (aw == NULL)
1504  return;
1505 
1506  /* gnc_account_tree_refresh (GNC_ACCOUNT_TREE(aw->parent_tree));*/
1507 
1508  gnc_account_window_set_name (aw);
1509 }
1510 
1511 
1512 static void
1513 refresh_handler (GHashTable *changes, gpointer user_data)
1514 {
1515  AccountWindow *aw = user_data;
1516  const EventInfo *info;
1517  Account *account;
1518 
1519  account = aw_get_account (aw);
1520  if (!account)
1521  {
1522  gnc_close_gui_component (aw->component_id);
1523  return;
1524  }
1525 
1526  if (changes)
1527  {
1528  info = gnc_gui_get_entity_events (changes, &aw->account);
1529  if (info && (info->event_mask & QOF_EVENT_DESTROY))
1530  {
1531  gnc_close_gui_component (aw->component_id);
1532  return;
1533  }
1534  }
1535 
1536  gnc_ui_refresh_account_window (aw);
1537 }
1538 
1539 
1540 static AccountWindow *
1541 gnc_ui_new_account_window_internal (QofBook *book,
1542  Account *base_account,
1543  gchar **subaccount_names,
1544  GList *valid_types,
1545  const gnc_commodity * default_commodity,
1546  gboolean modal)
1547 {
1548  const gnc_commodity *commodity, *parent_commodity;
1549  AccountWindow *aw;
1550  Account *account;
1551  GList *list;
1552 
1553  g_return_val_if_fail(book, NULL);
1554 
1555  aw = g_new0 (AccountWindow, 1);
1556 
1557  aw->book = book;
1558  aw->modal = modal;
1559  aw->dialog_type = NEW_ACCOUNT;
1560 
1561  aw->valid_types = 0;
1562  for (list = valid_types; list; list = list->next)
1563  aw->valid_types |= (1 << GPOINTER_TO_INT (list->data));
1564 
1565  account = xaccMallocAccount (book);
1566  aw->account = *xaccAccountGetGUID (account);
1567 
1568  if (base_account)
1569  {
1570  aw->type = xaccAccountGetType (base_account);
1571  parent_commodity = xaccAccountGetCommodity (base_account);
1572  }
1573  else
1574  {
1575  aw->type = last_used_account_type;
1576  parent_commodity = gnc_default_currency ();
1577  }
1578 
1579  gnc_suspend_gui_refresh ();
1580 
1581  if (subaccount_names && *subaccount_names)
1582  {
1583  xaccAccountSetName (account, subaccount_names[0]);
1584  aw->subaccount_names = subaccount_names;
1585  aw->next_name = subaccount_names + 1;
1586  }
1587 
1588  gnc_account_window_create (aw);
1589  gnc_account_to_ui (aw);
1590 
1591  gnc_resume_gui_refresh ();
1592 
1593  if (default_commodity != NULL)
1594  {
1595  commodity = default_commodity;
1596  if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
1597  {
1598  gtk_entry_set_text(GTK_ENTRY(aw->name_entry),
1599  (gpointer) gnc_commodity_get_mnemonic(commodity));
1600  gtk_entry_set_text(GTK_ENTRY(aw->description_entry),
1601  (gpointer) gnc_commodity_get_fullname(commodity));
1602  }
1603  }
1604  else if ((aw->type != ACCT_TYPE_STOCK) && (aw->type != ACCT_TYPE_MUTUAL))
1605  {
1606  commodity = parent_commodity;
1607  }
1608  else
1609  {
1610  commodity = NULL;
1611  }
1612  gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
1613  (gpointer) commodity);
1614  gnc_account_commodity_from_type (aw, FALSE);
1615 
1616  if (base_account == NULL)
1617  {
1618  base_account = gnc_book_get_root_account(book);
1619  }
1620 
1621  gtk_tree_view_collapse_all (aw->parent_tree);
1623  GNC_TREE_VIEW_ACCOUNT (aw->parent_tree), base_account);
1624 
1625  gtk_widget_show (aw->dialog);
1626 
1627  gnc_window_adjust_for_screen (GTK_WINDOW(aw->dialog));
1628 
1629  gnc_account_window_set_name (aw);
1630 
1631  aw->component_id = gnc_register_gui_component (DIALOG_NEW_ACCOUNT_CM_CLASS,
1632  refresh_handler,
1633  modal ? NULL : close_handler,
1634  aw);
1635 
1636  gnc_gui_component_set_session (aw->component_id, gnc_get_current_session());
1637  gnc_gui_component_watch_entity_type (aw->component_id,
1638  GNC_ID_ACCOUNT,
1639  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
1640  return aw;
1641 }
1642 
1643 
1644 static gchar **
1645 gnc_split_account_name (QofBook *book, const char *in_name, Account **base_account)
1646 {
1647  Account *root, *account;
1648  gchar **names, **ptr, **out_names;
1649  GList *list, *node;
1650 
1651  root = gnc_book_get_root_account (book);
1652  list = gnc_account_get_children(root);
1653  names = g_strsplit(in_name, gnc_get_account_separator_string(), -1);
1654 
1655  for (ptr = names; *ptr; ptr++)
1656  {
1657  /* Stop if there are no children at the current level. */
1658  if (list == NULL)
1659  break;
1660 
1661  /* Look for the first name in the children. */
1662  for (node = list; node; node = g_list_next(node))
1663  {
1664  account = node->data;
1665 
1666  if (g_strcmp0(xaccAccountGetName (account), *ptr) == 0)
1667  {
1668  /* We found an account. */
1669  *base_account = account;
1670  break;
1671  }
1672  }
1673 
1674  /* Was there a match? If no, stop the traversal. */
1675  if (node == NULL)
1676  break;
1677 
1678  g_list_free(list);
1679  list = gnc_account_get_children (account);
1680  }
1681 
1682  out_names = g_strdupv(ptr);
1683  g_strfreev(names);
1684  if (list)
1685  g_list_free(list);
1686  return out_names;
1687 }
1688 
1689 
1690 /************************************************************
1691  * Entry points for a Modal Dialog *
1692  ************************************************************/
1693 
1694 Account *
1696 {
1697  return gnc_ui_new_accounts_from_name_with_defaults (name, NULL, NULL, NULL);
1698 }
1699 
1700 Account *
1702  GList *valid_types)
1703 {
1704  return gnc_ui_new_accounts_from_name_with_defaults(name, valid_types, NULL, NULL);
1705 }
1706 
1707 Account *
1709  GList *valid_types,
1710  const gnc_commodity * default_commodity,
1711  Account * parent)
1712 {
1713  QofBook *book;
1714  AccountWindow *aw;
1715  Account *base_account = NULL;
1716  Account *created_account = NULL;
1717  gchar ** subaccount_names;
1718  gint response;
1719  gboolean done = FALSE;
1720 
1721  ENTER("name %s, valid %p, commodity %p, account %p",
1722  name, valid_types, default_commodity, parent);
1723  book = gnc_get_current_book();
1724  if (!name || *name == '\0')
1725  {
1726  subaccount_names = NULL;
1727  base_account = NULL;
1728  }
1729  else
1730  subaccount_names = gnc_split_account_name (book, name, &base_account);
1731 
1732  if (parent != NULL)
1733  {
1734  base_account = parent;
1735  }
1736  aw = gnc_ui_new_account_window_internal (book, base_account, subaccount_names,
1737  valid_types, default_commodity,
1738  TRUE);
1739 
1740  while (!done)
1741  {
1742  response = gtk_dialog_run (GTK_DIALOG(aw->dialog));
1743 
1744  /* This can destroy the dialog */
1745  gnc_account_window_response_cb (GTK_DIALOG(aw->dialog), response, (gpointer)aw);
1746 
1747  switch (response)
1748  {
1749  case GTK_RESPONSE_OK:
1750  created_account = aw->created_account;
1751  done = (created_account != NULL);
1752  break;
1753 
1754  case GTK_RESPONSE_HELP:
1755  done = FALSE;
1756  break;
1757 
1758  default:
1759  done = TRUE;
1760  break;
1761  }
1762  }
1763 
1764  close_handler(aw);
1765  LEAVE("created %s (%p)", xaccAccountGetName(created_account), created_account);
1766  return created_account;
1767 }
1768 
1769 /************************************************************
1770  * Entry points for a non-Modal Dialog *
1771  ************************************************************/
1772 
1773 static gboolean
1774 find_by_account (gpointer find_data, gpointer user_data)
1775 {
1776  Account *account = find_data;
1777  AccountWindow *aw = user_data;
1778 
1779  if (!aw)
1780  return FALSE;
1781 
1782  return guid_equal (&aw->account, xaccAccountGetGUID (account));
1783 }
1784 
1785 /*
1786  * opens up a window to edit an account
1787  *
1788  * Args: account - the account to edit
1789  * Return: EditAccountWindow object
1790  */
1791 void
1793 {
1794  AccountWindow * aw;
1795  Account *parent;
1796 
1797  if (account == NULL)
1798  return;
1799 
1800  aw = gnc_find_first_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
1801  find_by_account, account);
1802  if (aw)
1803  {
1804  gtk_window_present(GTK_WINDOW(aw->dialog));
1805  return;
1806  }
1807 
1808  aw = g_new0 (AccountWindow, 1);
1809 
1810  aw->book = gnc_account_get_book(account);
1811  aw->modal = FALSE;
1812  aw->dialog_type = EDIT_ACCOUNT;
1813  aw->account = *xaccAccountGetGUID (account);
1814  aw->subaccount_names = NULL;
1815  aw->type = xaccAccountGetType (account);
1816 
1817  gnc_suspend_gui_refresh ();
1818 
1819  gnc_account_window_create (aw);
1820  gnc_account_to_ui (aw);
1821 
1822  gnc_resume_gui_refresh ();
1823 
1824  gtk_widget_show_all (aw->dialog);
1825  gtk_widget_hide (aw->opening_balance_page);
1826 
1827  parent = gnc_account_get_parent (account);
1828  if (parent == NULL)
1829  parent = account; /* must be at the root */
1830 
1831  gtk_tree_view_collapse_all (aw->parent_tree);
1833  GNC_TREE_VIEW_ACCOUNT(aw->parent_tree), parent);
1834 
1835  gnc_account_window_set_name (aw);
1836 
1837  gnc_window_adjust_for_screen(GTK_WINDOW(aw->dialog));
1838 
1839  aw->component_id = gnc_register_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
1840  refresh_handler,
1841  close_handler, aw);
1842 
1843  gnc_gui_component_set_session (aw->component_id, gnc_get_current_session());
1844  gnc_gui_component_watch_entity_type (aw->component_id,
1845  GNC_ID_ACCOUNT,
1846  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
1847 
1848  gtk_window_present(GTK_WINDOW(aw->dialog));
1849 }
1850 
1851 
1852 /*
1853  * opens up a window to create a new account
1854  *
1855  * Args: book - containing book for the new account
1856  * parent - The initial parent for the new account (optional)
1857  */
1858 void
1860 {
1861  g_return_if_fail(book != NULL);
1862  if (parent && book)
1863  g_return_if_fail(gnc_account_get_book(parent) == book);
1864 
1865  gnc_ui_new_account_window_internal (book, parent, NULL, NULL, NULL, FALSE);
1866 }
1867 
1868 void
1870  GList *valid_types )
1871 {
1872  gnc_ui_new_account_window_internal( book, NULL, NULL, valid_types, NULL, FALSE );
1873 }
1874 
1875 /************************************************************
1876  * Callbacks for a non-Modal Dialog *
1877  ************************************************************/
1878 
1879 /*
1880  * register a callback that gets called when the account has changed
1881  * so significantly that you need to destroy yourself. In particular
1882  * this is used by the ledger display to destroy ledgers when the
1883  * account type has changed.
1884  */
1885 void
1886 gnc_ui_register_account_destroy_callback (void (*cb)(Account *))
1887 {
1888  if (!cb)
1889  return;
1890 
1891  if (g_list_index (ac_destroy_cb_list, cb) == -1)
1892  ac_destroy_cb_list = g_list_append (ac_destroy_cb_list, cb);
1893 
1894  return;
1895 }
1896 
1897 /**************************************************/
1898 
1899 static void
1900 gnc_account_renumber_update_examples (RenumberDialog *data)
1901 {
1902  gchar *str;
1903  gchar *prefix;
1904  gint interval;
1905  unsigned int num_digits = 1;
1906 
1907  g_return_if_fail (data->num_children > 0);
1908  prefix = gtk_editable_get_chars(GTK_EDITABLE(data->prefix), 0, -1);
1909  interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->interval));
1910  if (interval <= 0)
1911  interval = 10;
1912  num_digits = (unsigned int)log10((double)(data->num_children * interval)) + 1;
1913 
1914  if (strlen (prefix))
1915  str = g_strdup_printf("%s-%0*d", prefix, num_digits, interval);
1916  else
1917  str = g_strdup_printf("%0*d", num_digits, interval);
1918 
1919  gtk_label_set_text(GTK_LABEL(data->example1), str);
1920  g_free(str);
1921 
1922  if (strlen (prefix))
1923  str = g_strdup_printf("%s-%0*d", prefix, num_digits,
1924  interval * data->num_children);
1925  else
1926  str = g_strdup_printf("%0*d", num_digits,
1927  interval * data->num_children);
1928 
1929  gtk_label_set_text(GTK_LABEL(data->example2), str);
1930  g_free(str);
1931 
1932  g_free(prefix);
1933 }
1934 
1935 void
1936 gnc_account_renumber_prefix_changed_cb (GtkEditable *editable,
1937  RenumberDialog *data)
1938 {
1939  gnc_account_renumber_update_examples(data);
1940 }
1941 
1942 void
1943 gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton,
1944  RenumberDialog *data)
1945 {
1946  gnc_account_renumber_update_examples(data);
1947 }
1948 
1949 void
1950 gnc_account_renumber_response_cb (GtkDialog *dialog,
1951  gint response,
1952  RenumberDialog *data)
1953 {
1954  GList *children = NULL, *tmp;
1955  gchar *str;
1956  gchar *prefix;
1957  gint interval;
1958  unsigned int num_digits, i;
1959 
1960  if (response == GTK_RESPONSE_OK)
1961  {
1962  gtk_widget_hide(data->dialog);
1963  children = gnc_account_get_children_sorted(data->parent);
1964  if (children == NULL)
1965  {
1966  PWARN ("Can't renumber children of an account with no children!");
1967  g_free (data);
1968  return;
1969  }
1970  prefix = gtk_editable_get_chars(GTK_EDITABLE(data->prefix), 0, -1);
1971  interval =
1972  gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->interval));
1973  if (interval <= 0)
1974  interval = 10;
1975  num_digits = (unsigned int)log10 ((double)(data->num_children * interval) + 1);
1976 
1977  gnc_set_busy_cursor (NULL, TRUE);
1978  for (tmp = children, i = 1; tmp; tmp = g_list_next(tmp), i += 1)
1979  {
1980  if (strlen (prefix))
1981  str = g_strdup_printf("%s-%0*d", prefix,
1982  num_digits, interval * i);
1983  else
1984  str = g_strdup_printf("%0*d", num_digits, interval * i);
1985  xaccAccountSetCode(tmp->data, str);
1986  g_free(str);
1987  }
1988  gnc_unset_busy_cursor (NULL);
1989  g_list_free(children);
1990  }
1991 
1992  gtk_widget_destroy(data->dialog);
1993  g_free(data);
1994 }
1995 
1996 void
1997 gnc_account_renumber_create_dialog (GtkWidget *window, Account *account)
1998 {
1999  RenumberDialog *data;
2000  GtkBuilder *builder;
2001  GtkWidget *widget;
2002  gchar *string;
2003 
2004  /* This is a safety check; the menu item calling this dialog
2005  * should be disabled if the account has no children.
2006  */
2007  g_return_if_fail (gnc_account_n_children (account) > 0);
2008  data = g_new(RenumberDialog, 1);
2009  data->parent = account;
2010  data->num_children = gnc_account_n_children(account);
2011 
2012  builder = gtk_builder_new();
2013  gnc_builder_add_from_file (builder, "dialog-account.glade",
2014  "interval_adjustment");
2015  gnc_builder_add_from_file (builder, "dialog-account.glade",
2016  "Renumber Accounts");
2017  data->dialog = GTK_WIDGET(gtk_builder_get_object (builder,
2018  "Renumber Accounts"));
2019  gtk_window_set_transient_for(GTK_WINDOW(data->dialog), GTK_WINDOW(window));
2020  g_object_set_data_full(G_OBJECT(data->dialog), "builder", builder,
2021  g_object_unref);
2022 
2023  widget = GTK_WIDGET(gtk_builder_get_object (builder, "header_label"));
2024  string = g_strdup_printf(_( "Renumber the immediate sub-accounts of %s? "
2025  "This will replace the account code field of "
2026  "each child account with a newly generated code."),
2027  gnc_account_get_full_name(account));
2028  gtk_label_set_text(GTK_LABEL(widget), string);
2029  g_free(string);
2030 
2031  data->prefix = GTK_WIDGET(gtk_builder_get_object (builder, "prefix_entry"));
2032  data->interval = GTK_WIDGET(gtk_builder_get_object (builder, "interval_spin"));
2033  data->example1 = GTK_WIDGET(gtk_builder_get_object (builder, "example1_label"));
2034  data->example2 = GTK_WIDGET(gtk_builder_get_object (builder, "example2_label"));
2035 
2036  gtk_entry_set_text(GTK_ENTRY(data->prefix), xaccAccountGetCode(account));
2037  gnc_account_renumber_update_examples(data);
2038 
2039  gtk_builder_connect_signals(builder, data);
2040 
2041  gtk_widget_show_all(data->dialog);
2042 }
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Definition: Account.c:2208
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1294
Account * gnc_account_get_parent(const Account *acc)
Definition: Account.c:2623
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:357
Transaction * xaccMallocTransaction(QofBook *book)
Definition: Transaction.c:513
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
Definition: Transaction.c:1920
int gnc_commodity_get_fraction(const gnc_commodity *cm)
void gnc_account_append_child(Account *new_parent, Account *child)
Definition: Account.c:2525
gboolean gnc_account_is_root(const Account *account)
Definition: Account.c:2647
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
int xaccAccountGetCommoditySCUi(const Account *acc)
Definition: Account.c:2451
gboolean xaccAccountGetNonStdSCU(const Account *acc)
Definition: Account.c:2487
Dialog for create/edit an account.
void xaccAccountSetNotes(Account *acc, const char *str)
Definition: Account.c:2368
utility functions for the GnuCash UI
GNCAccountType xaccAccountGetType(const Account *acc)
Definition: Account.c:3009
int xaccAccountGetCommoditySCU(const Account *acc)
Definition: Account.c:2458
const char * xaccAccountGetCode(const Account *acc)
Definition: Account.c:3086
gnc_numeric gnc_numeric_neg(gnc_numeric a)
void xaccAccountSetTaxRelated(Account *acc, gboolean tax_related)
Definition: Account.c:3815
#define DEBUG(format, args...)
Definition: qoflog.h:255
void xaccAccountSetCode(Account *acc, const char *str)
Definition: Account.c:2249
Account * gnc_ui_new_accounts_from_name_window(const char *name)
void xaccTransSetDescription(Transaction *trans, const char *desc)
Definition: Transaction.c:2085
guint32 xaccAccountTypesValid(void)
Definition: Account.c:4203
gboolean gnc_numeric_zero_p(gnc_numeric a)
#define PERR(format, args...)
Definition: qoflog.h:237
#define ENTER(format, args...)
Definition: qoflog.h:261
Account * gnc_ui_new_accounts_from_name_window_with_types(const char *name, GList *valid_types)
void gnc_ui_edit_account_window(Account *account)
Definition: guid.h:65
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Definition: Transaction.c:1354
gnc_commodity * gnc_default_currency(void)
Definition: gnc-ui-util.c:939
void xaccAccountDestroy(Account *acc)
Definition: Account.c:1400
#define PWARN(format, args...)
Definition: qoflog.h:243
const char * xaccAccountGetColor(const Account *acc)
Definition: Account.c:3100
#define xaccAccountGetGUID(X)
Definition: Account.h:239
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Definition: Split.c:1258
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:3038
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
Definition: Account.c:3923
gboolean xaccAccountTypesCompatible(GNCAccountType parent_type, GNCAccountType child_type)
Definition: Account.c:4194
void xaccAccountSetColor(Account *acc, const char *str)
Definition: Account.c:2287
GtkTreeView implementation for gnucash account tree.
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
GtkTreeView * gnc_tree_view_account_new_with_root(Account *root, gboolean show_root)
const char * xaccAccountGetDescription(const Account *acc)
Definition: Account.c:3093
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
gint null_strcmp(const gchar *da, const gchar *db)
GList * gnc_account_get_children_sorted(const Account *account)
Definition: Account.c:2661
dialog_commodity_mode
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
Definition: Account.c:2915
Account * gnc_tree_view_account_get_account_from_path(GncTreeViewAccount *view, GtkTreePath *s_path)
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
gboolean xaccAccountGetTaxRelated(const Account *acc)
Definition: Account.c:3808
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
gint gnc_account_n_children(const Account *account)
Definition: Account.c:2676
void gnc_gnome_help(const char *file_name, const char *anchor)
All type declarations for the whole Gnucash engine.
void xaccAccountSetCommoditySCU(Account *acc, int scu)
Definition: Account.c:2435
GNCAccountType
Definition: Account.h:96
gboolean xaccAccountGetHidden(const Account *acc)
Definition: Account.c:3959
GtkTreeModel implementation to display account types in a GtkTreeView.
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
gnc_commodity * gnc_account_or_default_currency(const Account *account, gboolean *currency_from_account_found)
Definition: gnc-ui-util.c:944
void gnc_ui_new_account_with_types(QofBook *book, GList *valid_types)
guint32 xaccParentAccountTypesCompatibleWith(GNCAccountType type)
Definition: Account.c:4147
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
GList * gnc_account_get_children(const Account *account)
Definition: Account.c:2654
Definition: SplitP.h:71
void xaccAccountSetHidden(Account *acc, gboolean val)
Definition: Account.c:3970
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1280
gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor)
Definition: Account.c:4004
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
const GncGUID * guid_null(void)
void gnc_ui_new_account_window(QofBook *book, Account *parent)
#define xaccAccountInsertSplit(acc, s)
Definition: Account.h:972
gboolean xaccAccountGetPlaceholder(const Account *acc)
Definition: Account.c:3912
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
#define LEAVE(format, args...)
Definition: qoflog.h:271
Account * xaccMallocAccount(QofBook *book)
Definition: Account.c:1083
Account * gnc_ui_new_accounts_from_name_with_defaults(const char *name, GList *valid_types, const gnc_commodity *default_commodity, Account *parent)
time64 gnc_time(time64 *tbuf)
get the current local time
gint64 time64
Definition: gnc-date.h:83
void xaccAccountSetDescription(Account *acc, const char *str)
Definition: Account.c:2268
void xaccAccountSetNonStdSCU(Account *acc, gboolean flag)
Definition: Account.c:2471
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:3031
const char * xaccAccountGetTypeStr(GNCAccountType type)
Definition: Account.c:4137
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1321
void xaccAccountSetName(Account *acc, const char *str)
Definition: Account.c:2229
"select" and "new" commodity windows
Commodity handling public routines.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
const gchar * QofLogModule
Definition: qofid.h:89
const gchar * gnc_get_account_separator_string(void)
Definition: Account.c:129
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Definition: Account.c:2389
const char * xaccAccountGetNotes(const Account *acc)
Definition: Account.c:3121
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827