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