00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026
00027 #include <gnome.h>
00028 #include <glib/gi18n.h>
00029 #include <math.h>
00030 #ifdef G_OS_WIN32
00031 #include <pow.h>
00032 #endif
00033 #include <string.h>
00034
00035 #include "Transaction.h"
00036 #include "dialog-account.h"
00037 #include "dialog-commodity.h"
00038 #include "dialog-utils.h"
00039 #include "gnc-amount-edit.h"
00040 #include "gnc-general-select.h"
00041 #include "gnc-commodity.h"
00042 #include "gnc-commodity-edit.h"
00043 #include "gnc-component-manager.h"
00044 #include "gnc-engine.h"
00045 #include "gnc-gui-query.h"
00046 #include "gnc-session.h"
00047 #include "gnc-tree-model-account-types.h"
00048 #include "gnc-tree-view-account.h"
00049 #include "gnc-ui.h"
00050 #include "gnc-ui-util.h"
00051
00052
00053 #define DIALOG_NEW_ACCOUNT_CM_CLASS "dialog-new-account"
00054 #define DIALOG_EDIT_ACCOUNT_CM_CLASS "dialog-edit-account"
00055 #define GCONF_SECTION "dialogs/account"
00056
00057 enum account_cols {
00058 ACCOUNT_COL_FULLNAME = 0,
00059 ACCOUNT_COL_FIELDNAME,
00060 ACCOUNT_COL_OLD_VALUE,
00061 ACCOUNT_COL_NEW_VALUE,
00062 NUM_ACCOUNT_COLS
00063 };
00064
00065 typedef enum
00066 {
00067 NEW_ACCOUNT,
00068 EDIT_ACCOUNT
00069 } AccountDialogType;
00070
00071 typedef struct _AccountWindow
00072 {
00073 QofBook *book;
00074 gboolean modal;
00075 GtkWidget *dialog;
00076
00077 AccountDialogType dialog_type;
00078
00079 GUID account;
00080 Account *created_account;
00081
00082 gchar **subaccount_names;
00083 gchar **next_name;
00084
00085 GNCAccountType type;
00086
00087 GtkWidget * notebook;
00088
00089 GtkWidget * name_entry;
00090 GtkWidget * description_entry;
00091 GtkWidget * code_entry;
00092 GtkTextBuffer * notes_text_buffer;
00093
00094 GtkWidget * commodity_edit;
00095 dialog_commodity_mode commodity_mode;
00096 GtkWidget * account_scu;
00097
00098 guint32 valid_types;
00099 GNCAccountType preferred_account_type;
00100 GtkWidget * type_view;
00101 GtkTreeView * parent_tree;
00102
00103 GtkWidget * opening_balance_edit;
00104 GtkWidget * opening_balance_date_edit;
00105 GtkWidget * opening_balance_page;
00106
00107 GtkWidget * opening_equity_radio;
00108 GtkWidget * transfer_account_scroll;
00109 GtkWidget * transfer_tree;
00110
00111 GtkWidget * tax_related_button;
00112 GtkWidget * placeholder_button;
00113 GtkWidget * hidden_button;
00114
00115 gint component_id;
00116 } AccountWindow;
00117
00118 typedef struct _RenumberDialog
00119 {
00120 GtkWidget *dialog;
00121 GtkWidget *prefix;
00122 GtkWidget *interval;
00123 GtkWidget *example1;
00124 GtkWidget *example2;
00125
00126 Account *parent;
00127 gint num_children;
00128 } RenumberDialog;
00129
00131 static QofLogModule log_module = GNC_MOD_GUI;
00132
00133 static GNCAccountType last_used_account_type = ACCT_TYPE_BANK;
00134
00135 static GList *ac_destroy_cb_list = NULL;
00136
00138 static void gnc_account_window_set_name (AccountWindow *aw);
00139
00140 void gnc_account_renumber_prefix_changed_cb (GtkEditable *editable, RenumberDialog *data);
00141 void gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
00142 void gnc_account_renumber_response_cb (GtkDialog *dialog, gint response, RenumberDialog *data);
00143
00146 static void
00147 aw_call_destroy_callbacks (Account* acc)
00148 {
00149 GList *node;
00150 void (*cb)(Account*);
00151
00152 for (node = ac_destroy_cb_list; node; node = node->next) {
00153 cb = node->data;
00154 (cb)(acc);
00155 }
00156 }
00157
00158 static Account *
00159 aw_get_account (AccountWindow *aw)
00160 {
00161 if (!aw)
00162 return NULL;
00163
00164 return xaccAccountLookup (&aw->account, aw->book);
00165 }
00166
00167 static void
00168 gnc_account_commodity_from_type (AccountWindow * aw, gboolean update)
00169 {
00170 dialog_commodity_mode new_mode;
00171
00172 if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
00173 new_mode = DIAG_COMM_NON_CURRENCY;
00174 else
00175 new_mode = DIAG_COMM_CURRENCY;
00176
00177 if (update && (new_mode != aw->commodity_mode)) {
00178 gnc_general_select_set_selected(GNC_GENERAL_SELECT (aw->commodity_edit),
00179 NULL);
00180 }
00181
00182 aw->commodity_mode = new_mode;
00183 }
00184
00185
00186 static void
00187 gnc_account_to_ui(AccountWindow *aw)
00188 {
00189 Account *account;
00190 gnc_commodity * commodity;
00191 const char *string;
00192 gboolean flag, nonstd_scu;
00193 gint index;
00194
00195 ENTER("%p", aw);
00196 account = aw_get_account (aw);
00197 if (!account) {
00198 LEAVE("no account");
00199 return;
00200 }
00201
00202 string = xaccAccountGetName (account);
00203 if (string == NULL) string = "";
00204 gtk_entry_set_text(GTK_ENTRY(aw->name_entry), string);
00205
00206 string = xaccAccountGetDescription (account);
00207 if (string == NULL) string = "";
00208 gtk_entry_set_text(GTK_ENTRY(aw->description_entry), string);
00209
00210 commodity = xaccAccountGetCommodity (account);
00211 gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
00212 commodity);
00213 gnc_account_commodity_from_type (aw, FALSE);
00214
00215 nonstd_scu = xaccAccountGetNonStdSCU (account);
00216 if (nonstd_scu) {
00217 index = xaccAccountGetCommoditySCUi(account);
00218 index = log10(index) + 1;
00219 } else {
00220 index = 0;
00221 }
00222 gtk_combo_box_set_active(GTK_COMBO_BOX(aw->account_scu), index);
00223
00224 string = xaccAccountGetCode (account);
00225 if (string == NULL) string = "";
00226 gtk_entry_set_text(GTK_ENTRY(aw->code_entry), string);
00227
00228 string = xaccAccountGetNotes (account);
00229 if (string == NULL) string = "";
00230
00231 gtk_text_buffer_set_text (aw->notes_text_buffer, string, strlen(string));
00232
00233 flag = xaccAccountGetTaxRelated (account);
00234 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->tax_related_button),
00235 flag);
00236
00237 flag = xaccAccountGetPlaceholder (account);
00238 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->placeholder_button),
00239 flag);
00240
00241 flag = xaccAccountGetHidden (account);
00242 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->hidden_button),
00243 flag);
00244 LEAVE(" ");
00245 }
00246
00247
00248 static gboolean
00249 gnc_account_create_transfer_balance (QofBook *book,
00250 Account *account,
00251 Account *transfer,
00252 gnc_numeric balance,
00253 time_t date)
00254 {
00255 Transaction *trans;
00256 Split *split;
00257
00258 if (gnc_numeric_zero_p (balance))
00259 return TRUE;
00260
00261 g_return_val_if_fail (account != NULL, FALSE);
00262 g_return_val_if_fail (transfer != NULL, FALSE);
00263
00264 xaccAccountBeginEdit (account);
00265 xaccAccountBeginEdit (transfer);
00266
00267 trans = xaccMallocTransaction (book);
00268
00269 xaccTransBeginEdit (trans);
00270
00271 xaccTransSetCurrency (trans, xaccAccountGetCommodity (account));
00272 xaccTransSetDateSecs (trans, date);
00273 xaccTransSetDescription (trans, _("Opening Balance"));
00274
00275 split = xaccMallocSplit (book);
00276
00277 xaccTransAppendSplit (trans, split);
00278 xaccAccountInsertSplit (account, split);
00279
00280 xaccSplitSetAmount (split, balance);
00281 xaccSplitSetValue (split, balance);
00282
00283 balance = gnc_numeric_neg (balance);
00284
00285 split = xaccMallocSplit (book);
00286
00287 xaccTransAppendSplit (trans, split);
00288 xaccAccountInsertSplit (transfer, split);
00289
00290 xaccSplitSetAmount (split, balance);
00291 xaccSplitSetValue (split, balance);
00292
00293 xaccTransCommitEdit (trans);
00294 xaccAccountCommitEdit (transfer);
00295 xaccAccountCommitEdit (account);
00296
00297 return TRUE;
00298 }
00299
00300
00301 static void
00302 gnc_ui_to_account(AccountWindow *aw)
00303 {
00304 Account *account;
00305 gnc_commodity *commodity;
00306 Account *parent_account;
00307 const char *old_string;
00308 const char *string;
00309 gboolean flag;
00310 gnc_numeric balance;
00311 gboolean use_equity, nonstd;
00312 time_t date;
00313 gint index, old_scu, new_scu;
00314 GtkTextIter start, end;
00315
00316 account = aw_get_account (aw);
00317 if (!account) {
00318 LEAVE("no account");
00319 return;
00320 }
00321
00322 if (aw->dialog_type == EDIT_ACCOUNT
00323 && aw->type != xaccAccountGetType (account)) {
00324
00325 aw_call_destroy_callbacks (account);
00326 }
00327
00328 xaccAccountBeginEdit (account);
00329
00330 if (aw->type != xaccAccountGetType (account))
00331 xaccAccountSetType (account, aw->type);
00332
00333 last_used_account_type = aw->type;
00334
00335 string = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
00336 old_string = xaccAccountGetName (account);
00337 if (safe_strcmp (string, old_string) != 0)
00338 xaccAccountSetName (account, string);
00339
00340 string = gtk_entry_get_text (GTK_ENTRY(aw->description_entry));
00341 old_string = xaccAccountGetDescription (account);
00342 if (safe_strcmp (string, old_string) != 0)
00343 xaccAccountSetDescription (account, string);
00344
00345 commodity = (gnc_commodity *)
00346 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
00347 if (commodity &&
00348 !gnc_commodity_equiv(commodity, xaccAccountGetCommodity (account))) {
00349 xaccAccountSetCommodity (account, commodity);
00350 old_scu = 0;
00351 } else {
00352 old_scu = xaccAccountGetCommoditySCU(account);
00353 }
00354
00355 index = gtk_combo_box_get_active(GTK_COMBO_BOX(aw->account_scu));
00356 nonstd = (index != 0);
00357 if (nonstd != xaccAccountGetNonStdSCU(account))
00358 xaccAccountSetNonStdSCU(account, nonstd);
00359 new_scu = (nonstd ? pow(10,index-1) : gnc_commodity_get_fraction(commodity));
00360 if (old_scu != new_scu)
00361 xaccAccountSetCommoditySCU(account, new_scu);
00362
00363 string = gtk_entry_get_text (GTK_ENTRY(aw->code_entry));
00364 old_string = xaccAccountGetCode (account);
00365 if (safe_strcmp (string, old_string) != 0)
00366 xaccAccountSetCode (account, string);
00367
00368 gtk_text_buffer_get_start_iter (aw->notes_text_buffer, &start);
00369 gtk_text_buffer_get_end_iter (aw->notes_text_buffer, &end);
00370 string = gtk_text_buffer_get_text (aw->notes_text_buffer, &start, &end, FALSE);
00371 old_string = xaccAccountGetNotes (account);
00372 if (safe_strcmp (string, old_string) != 0)
00373 xaccAccountSetNotes (account, string);
00374
00375 flag =
00376 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->tax_related_button));
00377 xaccAccountSetTaxRelated (account, flag);
00378
00379 flag =
00380 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->placeholder_button));
00381 xaccAccountSetPlaceholder (account, flag);
00382
00383 flag =
00384 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->hidden_button));
00385 xaccAccountSetHidden (account, flag);
00386
00387 parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
00388
00389 if (parent_account == NULL)
00390 parent_account = gnc_book_get_root_account(aw->book);
00391 if (parent_account != gnc_account_get_parent (account))
00392 gnc_account_append_child (parent_account, account);
00393
00394 xaccAccountCommitEdit (account);
00395
00396 balance = gnc_amount_edit_get_amount
00397 (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
00398
00399 if (gnc_numeric_zero_p (balance)) {
00400 LEAVE("zero balance");
00401 return;
00402 }
00403
00404 if (gnc_reverse_balance (account))
00405 balance = gnc_numeric_neg (balance);
00406
00407 date = gnome_date_edit_get_time (
00408 GNOME_DATE_EDIT (aw->opening_balance_date_edit));
00409
00410 use_equity = gtk_toggle_button_get_active
00411 (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
00412
00413 if (use_equity)
00414 {
00415 if (!gnc_account_create_opening_balance (account, balance, date, aw->book))
00416 {
00417 const char *message = _("Could not create opening balance.");
00418 gnc_error_dialog(aw->dialog, message);
00419 }
00420 }
00421 else
00422 {
00423 Account *transfer = NULL;
00424
00425 transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
00426 if (!transfer) {
00427 LEAVE("no transfer account");
00428 return;
00429 }
00430
00431 gnc_account_create_transfer_balance (aw->book, account, transfer, balance, date);
00432 }
00433 LEAVE(" ");
00434 }
00435
00436
00437 static void
00438 set_children_types (Account *account, GNCAccountType type)
00439 {
00440 GList *children, *iter;
00441
00442 children = gnc_account_get_children(account);
00443 if (children == NULL)
00444 return;
00445
00446 for (iter=children; iter; iter=iter->next) {
00447 account = iter->data;
00448 if (type == xaccAccountGetType(account))
00449 continue;
00450
00451
00452 aw_call_destroy_callbacks (account);
00453
00454 xaccAccountBeginEdit (account);
00455 xaccAccountSetType (account, type);
00456 xaccAccountCommitEdit (account);
00457
00458 set_children_types (account, type);
00459 }
00460 g_list_free(children);
00461 }
00462
00463 static void
00464 make_children_compatible (AccountWindow *aw)
00465 {
00466 Account *account;
00467
00468 g_return_if_fail (aw);
00469
00470 if (aw->dialog_type == NEW_ACCOUNT)
00471 return;
00472
00473 account = aw_get_account (aw);
00474 g_return_if_fail (account);
00475
00476 if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
00477 return;
00478
00479 set_children_types (account, aw->type);
00480 }
00481
00482
00483 static void
00484 gnc_finish_ok (AccountWindow *aw)
00485 {
00486 ENTER("aw %p", aw);
00487 gnc_suspend_gui_refresh ();
00488
00489
00490 make_children_compatible (aw);
00491 gnc_ui_to_account (aw);
00492
00493 gnc_resume_gui_refresh ();
00494
00495
00496 if ((aw->dialog_type == NEW_ACCOUNT) && aw->next_name && *aw->next_name)
00497 {
00498 gnc_commodity *commodity;
00499 Account *parent;
00500 Account *account;
00501
00502 gnc_suspend_gui_refresh ();
00503
00504 parent = aw_get_account (aw);
00505 account = xaccMallocAccount (aw->book);
00506 aw->account = *xaccAccountGetGUID (account);
00507 aw->type = xaccAccountGetType (parent);
00508
00509 xaccAccountSetName (account, *aw->next_name);
00510 aw->next_name++;
00511
00512 gnc_account_to_ui (aw);
00513
00514 gnc_account_window_set_name (aw);
00515
00516 commodity = xaccAccountGetCommodity (parent);
00517 gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
00518 commodity);
00519 gnc_account_commodity_from_type (aw, FALSE);
00520
00521 gnc_tree_view_account_set_selected_account (
00522 GNC_TREE_VIEW_ACCOUNT (aw->parent_tree), parent);
00523
00524 gnc_resume_gui_refresh ();
00525 LEAVE("1");
00526 return;
00527 }
00528
00529
00530 aw->created_account = aw_get_account (aw);
00531
00532
00533 aw->account = *xaccGUIDNULL ();
00534
00535 gnc_close_gui_component (aw->component_id);
00536 LEAVE("2");
00537 }
00538
00539
00540 static void
00541 add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data)
00542 {
00543 GtkExpander *expander = GTK_EXPANDER (object);
00544 Account *account = data;
00545 GtkWidget *scrolled_window;
00546 GtkTreeView *view;
00547
00548 if (gtk_expander_get_expanded (expander) &&
00549 !gtk_bin_get_child (GTK_BIN (expander))) {
00550
00551 view = gnc_tree_view_account_new_with_root (account, FALSE);
00552
00553 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
00554 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
00555 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00556 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
00557 GTK_SHADOW_IN);
00558 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (view));
00559
00560 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
00561 gtk_widget_show_all (scrolled_window);
00562 }
00563 }
00564
00565
00566
00567
00568 static gboolean
00569 verify_children_compatible (AccountWindow *aw)
00570 {
00571 Account *account;
00572 GtkWidget *dialog, *vbox, *hbox, *label, *expander;
00573 gchar *str;
00574 gboolean result;
00575
00576 if (aw == NULL)
00577 return FALSE;
00578
00579 account = aw_get_account (aw);
00580 if (!account)
00581 return FALSE;
00582
00583 if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
00584 return TRUE;
00585
00586 if (gnc_account_n_children(account) == 0)
00587 return TRUE;
00588
00589 dialog = gtk_dialog_new_with_buttons ("",
00590 GTK_WINDOW(aw->dialog),
00591 GTK_DIALOG_DESTROY_WITH_PARENT |
00592 GTK_DIALOG_MODAL,
00593 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00594 GTK_STOCK_OK, GTK_RESPONSE_OK,
00595 NULL);
00596
00597 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
00598
00599 hbox = gtk_hbox_new (FALSE, 12);
00600 vbox = gtk_vbox_new (FALSE, 12);
00601
00602 gtk_box_pack_start (
00603 GTK_BOX (hbox),
00604 gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG),
00605 FALSE, FALSE, 0);
00606
00607
00608 label = gtk_label_new (_("Give the children the same type?"));
00609 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
00610 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00611 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
00612 {
00613 gint size;
00614 PangoFontDescription *font_desc;
00615
00616 size = pango_font_description_get_size (label->style->font_desc);
00617 font_desc = pango_font_description_new ();
00618 pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
00619 pango_font_description_set_size (font_desc, size * PANGO_SCALE_LARGE);
00620 gtk_widget_modify_font (label, font_desc);
00621 pango_font_description_free (font_desc);
00622 }
00623 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
00624
00625
00626 str = g_strdup_printf (_("The children of the edited account have to be "
00627 "changed to type \"%s\" to make them compatible."),
00628 xaccAccountGetTypeStr (aw->type));
00629 label = gtk_label_new (str);
00630 g_free (str);
00631 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
00632 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00633 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
00634 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
00635
00636
00637 expander = gtk_expander_new_with_mnemonic (_("_Show children accounts"));
00638 gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
00639 g_signal_connect (G_OBJECT (expander), "notify::expanded",
00640 G_CALLBACK (add_children_to_expander), account);
00641 gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
00642
00643 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
00644
00645 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
00646 TRUE, TRUE, 0);
00647
00648
00649 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
00650 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
00651 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
00652 gtk_container_set_border_width (
00653 GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
00654 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
00655
00656 gtk_widget_show_all (hbox);
00657
00658 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
00659
00660 result = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
00661
00662 gtk_widget_destroy(dialog);
00663
00664 return result;
00665 }
00666
00667
00668 static gboolean
00669 gnc_filter_parent_accounts (Account *account, gpointer data)
00670 {
00671 AccountWindow *aw = data;
00672 Account *aw_account = aw_get_account (aw);
00673
00674 if (account == NULL)
00675 return FALSE;
00676
00677 if (aw_account == NULL)
00678 return FALSE;
00679
00680 if (gnc_account_is_root(account))
00681 return TRUE;
00682
00683 if (account == aw_account)
00684 return FALSE;
00685
00686 if (xaccAccountHasAncestor(account, aw_account))
00687 return FALSE;
00688
00689 return TRUE;
00690 }
00691
00692
00693 static gboolean
00694 gnc_common_ok (AccountWindow *aw)
00695 {
00696 Account *root, *account, *parent;
00697 gnc_commodity * commodity;
00698 gchar *fullname, *fullname_parent;
00699 const gchar *name, *separator;
00700
00701 ENTER("aw %p", aw);
00702 root = gnc_book_get_root_account (aw->book);
00703
00704 separator = gnc_get_account_separator_string();
00705
00706
00707 name = gtk_entry_get_text(GTK_ENTRY(aw->name_entry));
00708 if (safe_strcmp(name, "") == 0) {
00709 const char *message = _("The account must be given a name.");
00710 gnc_error_dialog(aw->dialog, message);
00711 LEAVE("bad name");
00712 return FALSE;
00713 }
00714
00715
00716 parent = gnc_tree_view_account_get_selected_account
00717 (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
00718 if (parent == NULL) {
00719 account = gnc_account_lookup_by_full_name(root, name);
00720 } else {
00721 fullname_parent = xaccAccountGetFullName(parent);
00722 fullname = g_strconcat(fullname_parent, separator, name, NULL);
00723
00724 account = gnc_account_lookup_by_full_name(root, fullname);
00725
00726 g_free(fullname_parent);
00727 g_free(fullname);
00728 }
00729 if ((account != NULL) &&
00730 !guid_equal(&aw->account, xaccAccountGetGUID (account))) {
00731 const char *message = _("There is already an account with that name.");
00732 gnc_error_dialog(aw->dialog, message);
00733 LEAVE("duplicate name");
00734 return FALSE;
00735 }
00736
00737
00738 if (!gnc_filter_parent_accounts(parent, aw)) {
00739 const char *message = _("You must choose a valid parent account.");
00740 gnc_error_dialog(aw->dialog, message);
00741 LEAVE("invalid parent");
00742 return FALSE;
00743 }
00744
00745
00746 if (aw->type == ACCT_TYPE_INVALID) {
00747 const char *message = _("You must select an account type.");
00748 gnc_error_dialog(aw->dialog, message);
00749 LEAVE("invalid type");
00750 return FALSE;
00751 }
00752
00753
00754 if (!xaccAccountTypesCompatible (aw->type, xaccAccountGetType (parent))) {
00755 const char *message = _("The selected account type is incompatible with "
00756 "the one of the selected parent.");
00757 gnc_error_dialog(aw->dialog, message);
00758 LEAVE("incompatible types");
00759 return FALSE;
00760 }
00761
00762
00763 commodity = (gnc_commodity *)
00764 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
00765 if (!commodity) {
00766 const char *message = _("You must choose a commodity.");
00767 gnc_error_dialog(aw->dialog, message);
00768 LEAVE("invalid commodity");
00769 return FALSE;
00770 }
00771
00772 LEAVE("passed");
00773 return TRUE;
00774 }
00775
00776 static void
00777 gnc_edit_account_ok(AccountWindow *aw)
00778 {
00779 Account *account;
00780
00781 ENTER("aw %p", aw);
00782
00783 account = aw_get_account (aw);
00784 if (!account) {
00785 LEAVE(" ");
00786 return;
00787 }
00788
00789 if (!gnc_common_ok(aw)) {
00790 LEAVE(" ");
00791 return;
00792 }
00793
00794 if (!verify_children_compatible (aw)) {
00795 LEAVE(" ");
00796 return;
00797 }
00798
00799 gnc_finish_ok (aw);
00800 LEAVE(" ");
00801 }
00802
00803
00804 static void
00805 gnc_new_account_ok (AccountWindow *aw)
00806 {
00807 gnc_numeric balance;
00808
00809 ENTER("aw %p", aw);
00810
00811 if (!gnc_common_ok(aw)) {
00812 LEAVE(" ");
00813 return;
00814 }
00815
00816 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (aw->opening_balance_edit)))
00817 {
00818 const char *message = _("You must enter a valid opening balance "
00819 "or leave it blank.");
00820 gnc_error_dialog(aw->dialog, message);
00821 LEAVE(" ");
00822 return;
00823 }
00824
00825 balance = gnc_amount_edit_get_amount
00826 (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
00827
00828 if (!gnc_numeric_zero_p (balance))
00829 {
00830 gboolean use_equity;
00831
00832 use_equity = gtk_toggle_button_get_active
00833 (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
00834
00835 if (!use_equity)
00836 {
00837 Account *transfer = NULL;
00838
00839 transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
00840 if (!transfer)
00841 {
00842 const char *message = _("You must select a transfer account or choose"
00843 " the opening balances equity account.");
00844 gnc_error_dialog(aw->dialog, message);
00845 LEAVE(" ");
00846 return;
00847 }
00848 }
00849 }
00850
00851 gnc_finish_ok (aw);
00852 LEAVE(" ");
00853 }
00854
00855 static void
00856 gnc_account_window_response_cb (GtkDialog *dialog,
00857 gint response,
00858 gpointer data)
00859 {
00860 AccountWindow *aw = data;
00861
00862 ENTER("dialog %p, response %d, aw %p", dialog, response, aw);
00863 switch (response) {
00864 case GTK_RESPONSE_OK:
00865 switch (aw->dialog_type) {
00866 case NEW_ACCOUNT:
00867 DEBUG("new acct dialog, OK");
00868 gnc_new_account_ok (aw);
00869 break;
00870 case EDIT_ACCOUNT:
00871 DEBUG("edit acct dialog, OK");
00872 gnc_edit_account_ok (aw);
00873 break;
00874 default:
00875 g_assert_not_reached ();
00876 return;
00877 }
00878 break;
00879 case GTK_RESPONSE_HELP:
00880 switch (aw->dialog_type) {
00881 case NEW_ACCOUNT:
00882 DEBUG("new acct dialog, HELP");
00883 gnc_gnome_help(HF_HELP, HL_ACC);
00884 break;
00885 case EDIT_ACCOUNT:
00886 DEBUG("edit acct dialog, HELP");
00887 gnc_gnome_help(HF_HELP, HL_ACCEDIT);
00888 break;
00889 default:
00890 g_assert_not_reached ();
00891 return;
00892 }
00893 break;
00894 case GTK_RESPONSE_CANCEL:
00895 default:
00896 DEBUG("CANCEL");
00897 gnc_close_gui_component (aw->component_id);
00898 break;
00899 }
00900 LEAVE(" ");
00901 }
00902
00903 static void
00904 gnc_account_window_destroy_cb (GtkObject *object, gpointer data)
00905 {
00906 AccountWindow *aw = data;
00907 Account *account;
00908
00909 ENTER("object %p, aw %p", object, aw);
00910 account = aw_get_account (aw);
00911
00912 gnc_suspend_gui_refresh ();
00913
00914 switch (aw->dialog_type)
00915 {
00916 case NEW_ACCOUNT:
00917 if (account != NULL)
00918 {
00919 xaccAccountBeginEdit (account);
00920 xaccAccountDestroy (account);
00921 aw->account = *xaccGUIDNULL ();
00922 }
00923
00924 DEBUG ("account add window destroyed\n");
00925 break;
00926
00927 case EDIT_ACCOUNT:
00928 break;
00929
00930 default:
00931 PERR ("unexpected dialog type\n");
00932 gnc_resume_gui_refresh ();
00933 LEAVE(" ");
00934 return;
00935 }
00936
00937 gnc_unregister_gui_component (aw->component_id);
00938
00939 gnc_resume_gui_refresh ();
00940
00941 if (aw->subaccount_names) {
00942 g_strfreev(aw->subaccount_names);
00943 aw->subaccount_names = NULL;
00944 aw->next_name = NULL;
00945 }
00946
00947 g_free (aw);
00948 LEAVE(" ");
00949 }
00950
00951 static void
00952 gnc_account_parent_changed_cb (GtkTreeSelection *selection, gpointer data)
00953 {
00954 AccountWindow *aw = data;
00955 Account *parent_account;
00956 guint32 types, old_types;
00957 GtkTreeModel *type_model;
00958 GtkTreeSelection *type_selection;
00959 gboolean scroll_to = FALSE;
00960
00961 g_return_if_fail (aw);
00962
00963 parent_account = gnc_tree_view_account_get_selected_account (
00964 GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
00965 if (!parent_account)
00966 return;
00967
00968 if (gnc_account_is_root(parent_account)) {
00969 types = aw->valid_types;
00970 } else {
00971 types = aw->valid_types &
00972 xaccParentAccountTypesCompatibleWith (xaccAccountGetType (parent_account));
00973 }
00974
00975 type_model = gtk_tree_view_get_model (GTK_TREE_VIEW (aw->type_view));
00976 if (!type_model)
00977 return;
00978
00979 if (aw->type != aw->preferred_account_type &&
00980 (types & (1 << aw->preferred_account_type)) != 0) {
00981
00982 aw->type = aw->preferred_account_type;
00983 scroll_to = TRUE;
00984 }
00985 else if ((types & (1 << aw->type)) == 0) {
00986
00987 aw->type = ACCT_TYPE_INVALID;
00988 }
00989 else {
00990
00991 old_types = gnc_tree_model_account_types_get_mask (type_model);
00992 if (old_types != types)
00993 scroll_to = TRUE;
00994 }
00995
00996 gnc_tree_model_account_types_set_mask (type_model, types);
00997
00998 if (scroll_to) {
00999 type_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->type_view));
01000 gnc_tree_model_account_types_set_selection(type_selection, 1 << aw->type);
01001 }
01002
01003 gnc_account_window_set_name(aw);
01004 }
01005
01006 static void
01007 gnc_account_type_changed_cb (GtkTreeSelection *selection, gpointer data)
01008 {
01009 AccountWindow *aw = data;
01010 gboolean sensitive;
01011 GNCAccountType type_id;
01012
01013 g_return_if_fail (aw != NULL);
01014
01015 sensitive = FALSE;
01016
01017 type_id = gnc_tree_model_account_types_get_selection_single(selection);
01018 if (type_id == ACCT_TYPE_NONE) {
01019 aw->type = ACCT_TYPE_INVALID;
01020 } else {
01021 aw->type = type_id;
01022 aw->preferred_account_type = type_id;
01023
01024 gnc_account_commodity_from_type (aw, TRUE);
01025
01026 sensitive = (aw->type != ACCT_TYPE_EQUITY &&
01027 aw->type != ACCT_TYPE_CURRENCY &&
01028 aw->type != ACCT_TYPE_STOCK &&
01029 aw->type != ACCT_TYPE_MUTUAL);
01030 }
01031
01032 gtk_widget_set_sensitive (aw->opening_balance_page, sensitive);
01033
01034 if (!sensitive) {
01035 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01036 gnc_numeric_zero ());
01037 }
01038 }
01039
01040 static void
01041 gnc_account_type_view_create (AccountWindow *aw)
01042 {
01043 GtkTreeModel *model;
01044 GtkTreeSelection *selection;
01045 GtkCellRenderer *renderer;
01046 GtkTreeView *view;
01047
01048 if (aw->valid_types == 0) {
01049
01050 aw->valid_types = xaccAccountTypesValid () | (1 << aw->type);
01051 aw->preferred_account_type = aw->type;
01052 }
01053 else if ((aw->valid_types & (1 << aw->type)) != 0) {
01054
01055 aw->preferred_account_type = aw->type;
01056 }
01057 else if ((aw->valid_types & (1 << last_used_account_type)) != 0) {
01058
01059 aw->type = last_used_account_type;
01060 aw->preferred_account_type = last_used_account_type;
01061 }
01062 else {
01063
01064 int i;
01065 aw->preferred_account_type = aw->type;
01066 aw->type = ACCT_TYPE_INVALID;
01067 for (i=0; i<32; i++)
01068 if ((aw->valid_types & (1 << i)) != 0) {
01069 aw->type = i;
01070 break;
01071 }
01072 }
01073
01074 model = gnc_tree_model_account_types_filter_using_mask (aw->valid_types);
01075
01076 view = GTK_TREE_VIEW (aw->type_view);
01077 gtk_tree_view_set_model (view, model);
01078 g_object_unref (G_OBJECT (model));
01079
01080 renderer = gtk_cell_renderer_text_new ();
01081 gtk_tree_view_insert_column_with_attributes (
01082 view, -1, NULL, renderer,
01083 "text", GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME,
01084 NULL);
01085 gtk_tree_view_set_search_column (view, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME);
01086
01087 selection = gtk_tree_view_get_selection (view);
01088 g_signal_connect (G_OBJECT (selection), "changed",
01089 G_CALLBACK (gnc_account_type_changed_cb), aw);
01090
01091 gnc_tree_model_account_types_set_selection(selection, 1 << aw->type);
01092 }
01093
01094 static void
01095 gnc_account_name_changed_cb(GtkWidget *widget, gpointer data)
01096 {
01097 AccountWindow *aw = data;
01098
01099 gnc_account_window_set_name (aw);
01100 }
01101
01102 static void
01103 commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
01104 {
01105 AccountWindow *aw = data;
01106 gnc_commodity *currency;
01107 GtkTreeSelection *selection;
01108
01109 currency = (gnc_commodity *) gnc_general_select_get_selected (gsl);
01110 if (!currency)
01111 return;
01112
01113 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01114 gnc_commodity_get_fraction (currency));
01115 gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01116 gnc_commodity_print_info (currency, FALSE));
01117
01118 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->transfer_tree));
01119 gtk_tree_selection_unselect_all (selection);
01120 }
01121
01122 static gboolean
01123 account_commodity_filter (GtkTreeSelection *selection,
01124 GtkTreeModel *unused_model,
01125 GtkTreePath *s_path,
01126 gboolean path_currently_selected,
01127 gpointer user_data)
01128 {
01129 gnc_commodity *commodity;
01130 AccountWindow *aw;
01131 Account *account;
01132
01133 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
01134
01135 aw = user_data;
01136
01137 if (path_currently_selected) {
01138
01139 return TRUE;
01140 }
01141
01142 account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree), s_path);
01143 if (!account) {
01144 return FALSE;
01145 }
01146
01147 commodity = (gnc_commodity *)
01148 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
01149
01150 return gnc_commodity_equiv (xaccAccountGetCommodity (account), commodity);
01151 }
01152
01153 static void
01154 opening_equity_cb (GtkWidget *w, gpointer data)
01155 {
01156 AccountWindow *aw = data;
01157 gboolean use_equity;
01158
01159 use_equity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
01160
01161 gtk_widget_set_sensitive (aw->transfer_account_scroll, !use_equity);
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171 static void
01172 gnc_account_window_create(AccountWindow *aw)
01173 {
01174 GtkWidget *amount;
01175 GObject *awo;
01176 GtkWidget *box;
01177 GtkWidget *label;
01178 GladeXML *xml;
01179 GtkTreeSelection *selection;
01180
01181 ENTER("aw %p, modal %d", aw, aw->modal);
01182 xml = gnc_glade_xml_new ("account.glade", "Account Dialog");
01183
01184 aw->dialog = glade_xml_get_widget (xml, "Account Dialog");
01185 awo = G_OBJECT (aw->dialog);
01186
01187 g_object_set_data (awo, "dialog_info", aw);
01188
01189 g_signal_connect (awo, "destroy",
01190 G_CALLBACK (gnc_account_window_destroy_cb), aw);
01191
01192 if (!aw->modal)
01193 g_signal_connect (awo, "response",
01194 G_CALLBACK (gnc_account_window_response_cb), aw);
01195 else
01196 gtk_window_set_modal (GTK_WINDOW (aw->dialog), TRUE);
01197
01198 aw->notebook = glade_xml_get_widget (xml, "account_notebook");
01199
01200 aw->name_entry = glade_xml_get_widget (xml, "name_entry");
01201 g_signal_connect (G_OBJECT (aw->name_entry), "changed",
01202 G_CALLBACK (gnc_account_name_changed_cb), aw);
01203
01204 aw->description_entry = glade_xml_get_widget (xml, "description_entry");
01205 aw->code_entry = glade_xml_get_widget (xml, "code_entry");
01206 aw->notes_text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (glade_xml_get_widget (xml, "notes_text")));
01207
01208 box = glade_xml_get_widget (xml, "commodity_hbox");
01209 aw->commodity_edit = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
01210 gnc_commodity_edit_get_string,
01211 gnc_commodity_edit_new_select,
01212 &aw->commodity_mode);
01213 gtk_box_pack_start(GTK_BOX(box), aw->commodity_edit, TRUE, TRUE, 0);
01214 gtk_widget_show (aw->commodity_edit);
01215
01216 label = glade_xml_get_widget (xml, "security_label");
01217 gnc_general_select_make_mnemonic_target (GNC_GENERAL_SELECT(aw->commodity_edit), label);
01218
01219 g_signal_connect (G_OBJECT (aw->commodity_edit), "changed",
01220 G_CALLBACK (commodity_changed_cb), aw);
01221
01222 aw->account_scu = glade_xml_get_widget (xml, "account_scu");
01223
01224 box = glade_xml_get_widget (xml, "parent_scroll");
01225
01226 aw->parent_tree = gnc_tree_view_account_new(TRUE);
01227 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->parent_tree));
01228 gtk_widget_show(GTK_WIDGET(aw->parent_tree));
01229 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->parent_tree));
01230 g_signal_connect (G_OBJECT (selection), "changed",
01231 G_CALLBACK (gnc_account_parent_changed_cb), aw);
01232
01233 aw->tax_related_button = glade_xml_get_widget (xml, "tax_related_button");
01234 aw->placeholder_button = glade_xml_get_widget (xml