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 <gtk/gtk.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-date-edit.h"
00045 #include "gnc-engine.h"
00046 #include "gnc-gui-query.h"
00047 #include "gnc-session.h"
00048 #include "gnc-tree-model-account-types.h"
00049 #include "gnc-tree-view-account.h"
00050 #include "gnc-ui.h"
00051 #include "gnc-ui-util.h"
00052
00053
00054 #define DIALOG_NEW_ACCOUNT_CM_CLASS "dialog-new-account"
00055 #define DIALOG_EDIT_ACCOUNT_CM_CLASS "dialog-edit-account"
00056 #define GCONF_SECTION "dialogs/account"
00057 #define DEFAULT_COLOR "#ededececebeb"
00058
00059 enum account_cols
00060 {
00061 ACCOUNT_COL_FULLNAME = 0,
00062 ACCOUNT_COL_FIELDNAME,
00063 ACCOUNT_COL_OLD_VALUE,
00064 ACCOUNT_COL_NEW_VALUE,
00065 NUM_ACCOUNT_COLS
00066 };
00067
00068 typedef enum
00069 {
00070 NEW_ACCOUNT,
00071 EDIT_ACCOUNT
00072 } AccountDialogType;
00073
00074 typedef struct _AccountWindow
00075 {
00076 QofBook *book;
00077 gboolean modal;
00078 GtkWidget *dialog;
00079
00080 AccountDialogType dialog_type;
00081
00082 GncGUID account;
00083 Account *created_account;
00084
00085 gchar **subaccount_names;
00086 gchar **next_name;
00087
00088 GNCAccountType type;
00089
00090 GtkWidget * notebook;
00091
00092 GtkWidget * name_entry;
00093 GtkWidget * description_entry;
00094 GtkWidget * color_entry_button;
00095 GtkWidget * color_default_button;
00096 GtkWidget * code_entry;
00097 GtkTextBuffer * notes_text_buffer;
00098
00099 GtkWidget * commodity_edit;
00100 dialog_commodity_mode commodity_mode;
00101 GtkWidget * account_scu;
00102
00103 guint32 valid_types;
00104 GNCAccountType preferred_account_type;
00105 GtkWidget * type_view;
00106 GtkTreeView * parent_tree;
00107
00108 GtkWidget * opening_balance_edit;
00109 GtkWidget * opening_balance_date_edit;
00110 GtkWidget * opening_balance_page;
00111
00112 GtkWidget * opening_equity_radio;
00113 GtkWidget * transfer_account_scroll;
00114 GtkWidget * transfer_tree;
00115
00116 GtkWidget * tax_related_button;
00117 GtkWidget * placeholder_button;
00118 GtkWidget * hidden_button;
00119
00120 gint component_id;
00121 } AccountWindow;
00122
00123 typedef struct _RenumberDialog
00124 {
00125 GtkWidget *dialog;
00126 GtkWidget *prefix;
00127 GtkWidget *interval;
00128 GtkWidget *example1;
00129 GtkWidget *example2;
00130
00131 Account *parent;
00132 gint num_children;
00133 } RenumberDialog;
00134
00136 static QofLogModule log_module = GNC_MOD_GUI;
00137
00138 static GNCAccountType last_used_account_type = ACCT_TYPE_BANK;
00139
00140 static GList *ac_destroy_cb_list = NULL;
00141
00143 static void gnc_account_window_set_name (AccountWindow *aw);
00144
00145 void gnc_account_renumber_prefix_changed_cb (GtkEditable *editable, RenumberDialog *data);
00146 void gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
00147 void gnc_account_renumber_response_cb (GtkDialog *dialog, gint response, RenumberDialog *data);
00148
00149 void gnc_account_window_destroy_cb (GtkObject *object, gpointer data);
00150 void opening_equity_cb (GtkWidget *w, gpointer data);
00151 void gnc_account_name_changed_cb(GtkWidget *widget, gpointer data);
00152 void gnc_account_color_default_cb(GtkWidget *widget, gpointer data);
00153 void gnc_account_name_insert_text_cb (GtkWidget *entry,
00154 const gchar *text,
00155 gint length,
00156 gint *position,
00157 gpointer data);
00158
00161 static void
00162 aw_call_destroy_callbacks (Account* acc)
00163 {
00164 GList *node;
00165 void (*cb)(Account*);
00166
00167 for (node = ac_destroy_cb_list; node; node = node->next)
00168 {
00169 cb = node->data;
00170 (cb)(acc);
00171 }
00172 }
00173
00174 static Account *
00175 aw_get_account (AccountWindow *aw)
00176 {
00177 if (!aw)
00178 return NULL;
00179
00180 return xaccAccountLookup (&aw->account, aw->book);
00181 }
00182
00183 static void
00184 gnc_account_commodity_from_type (AccountWindow * aw, gboolean update)
00185 {
00186 dialog_commodity_mode new_mode;
00187
00188 if (aw->type == ACCT_TYPE_TRADING)
00189 new_mode = DIAG_COMM_ALL;
00190 else if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
00191 new_mode = DIAG_COMM_NON_CURRENCY;
00192 else
00193 new_mode = DIAG_COMM_CURRENCY;
00194
00195 if (update && (new_mode != aw->commodity_mode))
00196 {
00197 gnc_general_select_set_selected(GNC_GENERAL_SELECT (aw->commodity_edit),
00198 NULL);
00199 }
00200
00201 aw->commodity_mode = new_mode;
00202 }
00203
00204
00205 static void
00206 gnc_account_to_ui(AccountWindow *aw)
00207 {
00208 Account *account;
00209 gnc_commodity * commodity;
00210 const char *string;
00211 GdkColor color;
00212 gboolean flag, nonstd_scu;
00213 gint index;
00214
00215 ENTER("%p", aw);
00216 account = aw_get_account (aw);
00217 if (!account)
00218 {
00219 LEAVE("no account");
00220 return;
00221 }
00222
00223 string = xaccAccountGetName (account);
00224 if (string == NULL) string = "";
00225 gtk_entry_set_text(GTK_ENTRY(aw->name_entry), string);
00226
00227 string = xaccAccountGetDescription (account);
00228 if (string == NULL) string = "";
00229 gtk_entry_set_text(GTK_ENTRY(aw->description_entry), string);
00230
00231 string = xaccAccountGetColor (account);
00232 if (string == NULL) string = "";
00233 if (gdk_color_parse(string, &color))
00234 {
00235 gtk_color_button_set_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color);
00236 }
00237
00238 commodity = xaccAccountGetCommodity (account);
00239 gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
00240 commodity);
00241 gnc_account_commodity_from_type (aw, FALSE);
00242
00243 nonstd_scu = xaccAccountGetNonStdSCU (account);
00244 if (nonstd_scu)
00245 {
00246 index = xaccAccountGetCommoditySCUi(account);
00247 index = log10(index) + 1;
00248 }
00249 else
00250 {
00251 index = 0;
00252 }
00253 gtk_combo_box_set_active(GTK_COMBO_BOX(aw->account_scu), index);
00254
00255 string = xaccAccountGetCode (account);
00256 if (string == NULL) string = "";
00257 gtk_entry_set_text(GTK_ENTRY(aw->code_entry), string);
00258
00259 string = xaccAccountGetNotes (account);
00260 if (string == NULL) string = "";
00261
00262 gtk_text_buffer_set_text (aw->notes_text_buffer, string, strlen(string));
00263
00264 flag = xaccAccountGetTaxRelated (account);
00265 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->tax_related_button),
00266 flag);
00267
00268 flag = xaccAccountGetPlaceholder (account);
00269 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->placeholder_button),
00270 flag);
00271
00272 flag = xaccAccountGetHidden (account);
00273 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (aw->hidden_button),
00274 flag);
00275 LEAVE(" ");
00276 }
00277
00278
00279 static gboolean
00280 gnc_account_create_transfer_balance (QofBook *book,
00281 Account *account,
00282 Account *transfer,
00283 gnc_numeric balance,
00284 time_t date)
00285 {
00286 Transaction *trans;
00287 Split *split;
00288
00289 if (gnc_numeric_zero_p (balance))
00290 return TRUE;
00291
00292 g_return_val_if_fail (account != NULL, FALSE);
00293 g_return_val_if_fail (transfer != NULL, FALSE);
00294
00295 xaccAccountBeginEdit (account);
00296 xaccAccountBeginEdit (transfer);
00297
00298 trans = xaccMallocTransaction (book);
00299
00300 xaccTransBeginEdit (trans);
00301
00302 xaccTransSetCurrency (trans, xaccAccountGetCommodity (account));
00303 xaccTransSetDatePostedSecs (trans, date);
00304 xaccTransSetDescription (trans, _("Opening Balance"));
00305
00306 split = xaccMallocSplit (book);
00307
00308 xaccTransAppendSplit (trans, split);
00309 xaccAccountInsertSplit (account, split);
00310
00311 xaccSplitSetAmount (split, balance);
00312 xaccSplitSetValue (split, balance);
00313
00314 balance = gnc_numeric_neg (balance);
00315
00316 split = xaccMallocSplit (book);
00317
00318 xaccTransAppendSplit (trans, split);
00319 xaccAccountInsertSplit (transfer, split);
00320
00321 xaccSplitSetAmount (split, balance);
00322 xaccSplitSetValue (split, balance);
00323
00324 xaccTransCommitEdit (trans);
00325 xaccAccountCommitEdit (transfer);
00326 xaccAccountCommitEdit (account);
00327
00328 return TRUE;
00329 }
00330
00331
00332 static void
00333 gnc_ui_to_account(AccountWindow *aw)
00334 {
00335 Account *account;
00336 gnc_commodity *commodity;
00337 Account *parent_account;
00338 const char *old_string;
00339 const char *string;
00340 GdkColor color;
00341 gboolean flag;
00342 gnc_numeric balance;
00343 gboolean use_equity, nonstd;
00344 time_t date;
00345 gint index, old_scu, new_scu;
00346 GtkTextIter start, end;
00347
00348 account = aw_get_account (aw);
00349 if (!account)
00350 {
00351 LEAVE("no account");
00352 return;
00353 }
00354
00355 if (aw->dialog_type == EDIT_ACCOUNT
00356 && aw->type != xaccAccountGetType (account))
00357 {
00358
00359 aw_call_destroy_callbacks (account);
00360 }
00361
00362 xaccAccountBeginEdit (account);
00363
00364 if (aw->type != xaccAccountGetType (account))
00365 xaccAccountSetType (account, aw->type);
00366
00367 last_used_account_type = aw->type;
00368
00369 string = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
00370 old_string = xaccAccountGetName (account);
00371 if (safe_strcmp (string, old_string) != 0)
00372 xaccAccountSetName (account, string);
00373
00374 string = gtk_entry_get_text (GTK_ENTRY(aw->description_entry));
00375 old_string = xaccAccountGetDescription (account);
00376 if (safe_strcmp (string, old_string) != 0)
00377 xaccAccountSetDescription (account, string);
00378
00379 gtk_color_button_get_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color );
00380 string = gdk_color_to_string(&color);
00381 if (safe_strcmp (string, DEFAULT_COLOR) == 0)
00382 string = "Not Set";
00383
00384 old_string = xaccAccountGetColor (account);
00385 if (safe_strcmp (string, old_string) != 0)
00386 xaccAccountSetColor (account, string);
00387
00388 commodity = (gnc_commodity *)
00389 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
00390 if (commodity &&
00391 !gnc_commodity_equiv(commodity, xaccAccountGetCommodity (account)))
00392 {
00393 xaccAccountSetCommodity (account, commodity);
00394 old_scu = 0;
00395 }
00396 else
00397 {
00398 old_scu = xaccAccountGetCommoditySCU(account);
00399 }
00400
00401 index = gtk_combo_box_get_active(GTK_COMBO_BOX(aw->account_scu));
00402 nonstd = (index != 0);
00403 if (nonstd != xaccAccountGetNonStdSCU(account))
00404 xaccAccountSetNonStdSCU(account, nonstd);
00405 new_scu = (nonstd ? pow(10, index - 1) : gnc_commodity_get_fraction(commodity));
00406 if (old_scu != new_scu)
00407 xaccAccountSetCommoditySCU(account, new_scu);
00408
00409 string = gtk_entry_get_text (GTK_ENTRY(aw->code_entry));
00410 old_string = xaccAccountGetCode (account);
00411 if (safe_strcmp (string, old_string) != 0)
00412 xaccAccountSetCode (account, string);
00413
00414 gtk_text_buffer_get_start_iter (aw->notes_text_buffer, &start);
00415 gtk_text_buffer_get_end_iter (aw->notes_text_buffer, &end);
00416 string = gtk_text_buffer_get_text (aw->notes_text_buffer, &start, &end, FALSE);
00417 old_string = xaccAccountGetNotes (account);
00418 if (null_strcmp (string, old_string) != 0)
00419 xaccAccountSetNotes (account, string);
00420
00421 flag =
00422 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->tax_related_button));
00423 if (xaccAccountGetTaxRelated (account) != flag)
00424 xaccAccountSetTaxRelated (account, flag);
00425
00426 flag =
00427 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->placeholder_button));
00428 if (xaccAccountGetPlaceholder (account) != flag)
00429 xaccAccountSetPlaceholder (account, flag);
00430
00431 flag =
00432 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (aw->hidden_button));
00433 if (xaccAccountGetHidden (account) != flag)
00434 xaccAccountSetHidden (account, flag);
00435
00436 parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
00437
00438 if (parent_account == NULL)
00439 parent_account = gnc_book_get_root_account(aw->book);
00440 if (parent_account != gnc_account_get_parent (account))
00441 gnc_account_append_child (parent_account, account);
00442
00443 xaccAccountCommitEdit (account);
00444
00445 balance = gnc_amount_edit_get_amount
00446 (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
00447
00448 if (gnc_numeric_zero_p (balance))
00449 {
00450 LEAVE("zero balance");
00451 return;
00452 }
00453
00454 if (gnc_reverse_balance (account))
00455 balance = gnc_numeric_neg (balance);
00456
00457 date = gnc_date_edit_get_date (
00458 GNC_DATE_EDIT (aw->opening_balance_date_edit));
00459
00460 use_equity = gtk_toggle_button_get_active
00461 (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
00462
00463 if (use_equity)
00464 {
00465 if (!gnc_account_create_opening_balance (account, balance, date, aw->book))
00466 {
00467 const char *message = _("Could not create opening balance.");
00468 gnc_error_dialog(aw->dialog, "%s", message);
00469 }
00470 }
00471 else
00472 {
00473 Account *transfer = NULL;
00474
00475 transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
00476 if (!transfer)
00477 {
00478 LEAVE("no transfer account");
00479 return;
00480 }
00481
00482 gnc_account_create_transfer_balance (aw->book, account, transfer, balance, date);
00483 }
00484 LEAVE(" ");
00485 }
00486
00487
00488 static void
00489 set_children_types (Account *account, GNCAccountType type)
00490 {
00491 GList *children, *iter;
00492
00493 children = gnc_account_get_children(account);
00494 if (children == NULL)
00495 return;
00496
00497 for (iter = children; iter; iter = iter->next)
00498 {
00499 account = iter->data;
00500 if (type == xaccAccountGetType(account))
00501 continue;
00502
00503
00504 aw_call_destroy_callbacks (account);
00505
00506 xaccAccountBeginEdit (account);
00507 xaccAccountSetType (account, type);
00508 xaccAccountCommitEdit (account);
00509
00510 set_children_types (account, type);
00511 }
00512 g_list_free(children);
00513 }
00514
00515 static void
00516 make_children_compatible (AccountWindow *aw)
00517 {
00518 Account *account;
00519
00520 g_return_if_fail (aw);
00521
00522 if (aw->dialog_type == NEW_ACCOUNT)
00523 return;
00524
00525 account = aw_get_account (aw);
00526 g_return_if_fail (account);
00527
00528 if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
00529 return;
00530
00531 set_children_types (account, aw->type);
00532 }
00533
00534
00535 static void
00536 gnc_finish_ok (AccountWindow *aw)
00537 {
00538 ENTER("aw %p", aw);
00539 gnc_suspend_gui_refresh ();
00540
00541
00542 make_children_compatible (aw);
00543 gnc_ui_to_account (aw);
00544
00545 gnc_resume_gui_refresh ();
00546
00547
00548 if ((aw->dialog_type == NEW_ACCOUNT) && aw->next_name && *aw->next_name)
00549 {
00550 gnc_commodity *commodity;
00551 Account *parent;
00552 Account *account;
00553
00554 gnc_suspend_gui_refresh ();
00555
00556 parent = aw_get_account (aw);
00557 account = xaccMallocAccount (aw->book);
00558 aw->account = *xaccAccountGetGUID (account);
00559 aw->type = xaccAccountGetType (parent);
00560
00561 xaccAccountSetName (account, *aw->next_name);
00562 aw->next_name++;
00563
00564 gnc_account_to_ui (aw);
00565
00566 gnc_account_window_set_name (aw);
00567
00568 commodity = xaccAccountGetCommodity (parent);
00569 gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
00570 commodity);
00571 gnc_account_commodity_from_type (aw, FALSE);
00572
00573 gnc_tree_view_account_set_selected_account (
00574 GNC_TREE_VIEW_ACCOUNT (aw->parent_tree), parent);
00575
00576 gnc_resume_gui_refresh ();
00577 LEAVE("1");
00578 return;
00579 }
00580
00581
00582 aw->created_account = aw_get_account (aw);
00583
00584
00585 aw->account = *guid_null ();
00586
00587 gnc_close_gui_component (aw->component_id);
00588 LEAVE("2");
00589 }
00590
00591
00592 static void
00593 add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data)
00594 {
00595 GtkExpander *expander = GTK_EXPANDER (object);
00596 Account *account = data;
00597 GtkWidget *scrolled_window;
00598 GtkTreeView *view;
00599
00600 if (gtk_expander_get_expanded (expander) &&
00601 !gtk_bin_get_child (GTK_BIN (expander)))
00602 {
00603
00604 view = gnc_tree_view_account_new_with_root (account, FALSE);
00605
00606 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
00607 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
00608 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00609 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
00610 GTK_SHADOW_IN);
00611 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (view));
00612
00613 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
00614 gtk_widget_show_all (scrolled_window);
00615 }
00616 }
00617
00618
00619
00620
00621 static gboolean
00622 verify_children_compatible (AccountWindow *aw)
00623 {
00624 Account *account;
00625 GtkWidget *dialog, *vbox, *hbox, *label, *expander;
00626 gchar *str;
00627 gboolean result;
00628
00629 if (aw == NULL)
00630 return FALSE;
00631
00632 account = aw_get_account (aw);
00633 if (!account)
00634 return FALSE;
00635
00636 if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
00637 return TRUE;
00638
00639 if (gnc_account_n_children(account) == 0)
00640 return TRUE;
00641
00642 dialog = gtk_dialog_new_with_buttons ("",
00643 GTK_WINDOW(aw->dialog),
00644 GTK_DIALOG_DESTROY_WITH_PARENT |
00645 GTK_DIALOG_MODAL,
00646 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00647 GTK_STOCK_OK, GTK_RESPONSE_OK,
00648 NULL);
00649
00650 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
00651
00652 hbox = gtk_hbox_new (FALSE, 12);
00653 vbox = gtk_vbox_new (FALSE, 12);
00654
00655 gtk_box_pack_start (
00656 GTK_BOX (hbox),
00657 gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG),
00658 FALSE, FALSE, 0);
00659
00660
00661 label = gtk_label_new (_("Give the children the same type?"));
00662 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
00663 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00664 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
00665 {
00666 gint size;
00667 PangoFontDescription *font_desc;
00668
00669 size = pango_font_description_get_size (label->style->font_desc);
00670 font_desc = pango_font_description_new ();
00671 pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
00672 pango_font_description_set_size (font_desc, size * PANGO_SCALE_LARGE);
00673 gtk_widget_modify_font (label, font_desc);
00674 pango_font_description_free (font_desc);
00675 }
00676 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
00677
00678
00679 str = g_strdup_printf (_("The children of the edited account have to be "
00680 "changed to type \"%s\" to make them compatible."),
00681 xaccAccountGetTypeStr (aw->type));
00682 label = gtk_label_new (str);
00683 g_free (str);
00684 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
00685 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00686 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
00687 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
00688
00689
00690 expander = gtk_expander_new_with_mnemonic (_("_Show children accounts"));
00691 gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
00692 g_signal_connect (G_OBJECT (expander), "notify::expanded",
00693 G_CALLBACK (add_children_to_expander), account);
00694 gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
00695
00696 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
00697
00698 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
00699 TRUE, TRUE, 0);
00700
00701
00702 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
00703 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
00704 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
00705 gtk_container_set_border_width (
00706 GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
00707 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
00708
00709 gtk_widget_show_all (hbox);
00710
00711 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
00712
00713 result = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
00714
00715 gtk_widget_destroy(dialog);
00716
00717 return result;
00718 }
00719
00720
00721 static gboolean
00722 gnc_filter_parent_accounts (Account *account, gpointer data)
00723 {
00724 AccountWindow *aw = data;
00725 Account *aw_account = aw_get_account (aw);
00726
00727 if (account == NULL)
00728 return FALSE;
00729
00730 if (aw_account == NULL)
00731 return FALSE;
00732
00733 if (gnc_account_is_root(account))
00734 return TRUE;
00735
00736 if (account == aw_account)
00737 return FALSE;
00738
00739 if (xaccAccountHasAncestor(account, aw_account))
00740 return FALSE;
00741
00742 return TRUE;
00743 }
00744
00745
00746 static gboolean
00747 gnc_common_ok (AccountWindow *aw)
00748 {
00749 Account *root, *account, *parent;
00750 gnc_commodity * commodity;
00751 gchar *fullname, *fullname_parent;
00752 const gchar *name, *separator;
00753
00754 ENTER("aw %p", aw);
00755 root = gnc_book_get_root_account (aw->book);
00756
00757 separator = gnc_get_account_separator_string();
00758
00759
00760 name = gtk_entry_get_text(GTK_ENTRY(aw->name_entry));
00761 if (safe_strcmp(name, "") == 0)
00762 {
00763 const char *message = _("The account must be given a name.");
00764 gnc_error_dialog(aw->dialog, "%s", message);
00765 LEAVE("bad name");
00766 return FALSE;
00767 }
00768
00769
00770 parent = gnc_tree_view_account_get_selected_account
00771 (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
00772 if (parent == NULL)
00773 {
00774 account = gnc_account_lookup_by_full_name(root, name);
00775 }
00776 else
00777 {
00778 fullname_parent = gnc_account_get_full_name(parent);
00779 fullname = g_strconcat(fullname_parent, separator, name, NULL);
00780
00781 account = gnc_account_lookup_by_full_name(root, fullname);
00782
00783 g_free(fullname_parent);
00784 g_free(fullname);
00785 }
00786 if ((account != NULL) &&
00787 !guid_equal(&aw->account, xaccAccountGetGUID (account)))
00788 {
00789 const char *message = _("There is already an account with that name.");
00790 gnc_error_dialog(aw->dialog, "%s", message);
00791 LEAVE("duplicate name");
00792 return FALSE;
00793 }
00794
00795
00796 if (!gnc_filter_parent_accounts(parent, aw))
00797 {
00798 const char *message = _("You must choose a valid parent account.");
00799 gnc_error_dialog(aw->dialog, "%s", message);
00800 LEAVE("invalid parent");
00801 return FALSE;
00802 }
00803
00804
00805 if (aw->type == ACCT_TYPE_INVALID)
00806 {
00807 const char *message = _("You must select an account type.");
00808 gnc_error_dialog(aw->dialog, "%s", message);
00809 LEAVE("invalid type");
00810 return FALSE;
00811 }
00812
00813
00814 if (!xaccAccountTypesCompatible (aw->type, xaccAccountGetType (parent)))
00815 {
00816 const char *message = _("The selected account type is incompatible with "
00817 "the one of the selected parent.");
00818 gnc_error_dialog(aw->dialog, "%s", message);
00819 LEAVE("incompatible types");
00820 return FALSE;
00821 }
00822
00823
00824 commodity = (gnc_commodity *)
00825 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
00826 if (!commodity)
00827 {
00828 const char *message = _("You must choose a commodity.");
00829 gnc_error_dialog(aw->dialog, "%s", message);
00830 LEAVE("invalid commodity");
00831 return FALSE;
00832 }
00833
00834 LEAVE("passed");
00835 return TRUE;
00836 }
00837
00838 static void
00839 gnc_edit_account_ok(AccountWindow *aw)
00840 {
00841 Account *account;
00842
00843 ENTER("aw %p", aw);
00844
00845 account = aw_get_account (aw);
00846 if (!account)
00847 {
00848 LEAVE(" ");
00849 return;
00850 }
00851
00852 if (!gnc_common_ok(aw))
00853 {
00854 LEAVE(" ");
00855 return;
00856 }
00857
00858 if (!verify_children_compatible (aw))
00859 {
00860 LEAVE(" ");
00861 return;
00862 }
00863
00864 gnc_finish_ok (aw);
00865 LEAVE(" ");
00866 }
00867
00868
00869 static void
00870 gnc_new_account_ok (AccountWindow *aw)
00871 {
00872 gnc_numeric balance;
00873
00874 ENTER("aw %p", aw);
00875
00876 if (!gnc_common_ok(aw))
00877 {
00878 LEAVE(" ");
00879 return;
00880 }
00881
00882 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (aw->opening_balance_edit)))
00883 {
00884 const char *message = _("You must enter a valid opening balance "
00885 "or leave it blank.");
00886 gnc_error_dialog(aw->dialog, "%s", message);
00887 LEAVE(" ");
00888 return;
00889 }
00890
00891 balance = gnc_amount_edit_get_amount
00892 (GNC_AMOUNT_EDIT (aw->opening_balance_edit));
00893
00894 if (!gnc_numeric_zero_p (balance))
00895 {
00896 gboolean use_equity;
00897
00898 use_equity = gtk_toggle_button_get_active
00899 (GTK_TOGGLE_BUTTON (aw->opening_equity_radio));
00900
00901 if (!use_equity)
00902 {
00903 Account *transfer = NULL;
00904
00905 transfer = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree));
00906 if (!transfer)
00907 {
00908 const char *message = _("You must select a transfer account or choose"
00909 " the opening balances equity account.");
00910 gnc_error_dialog(aw->dialog, "%s", message);
00911 LEAVE(" ");
00912 return;
00913 }
00914 }
00915 }
00916
00917 gnc_finish_ok (aw);
00918 LEAVE(" ");
00919 }
00920
00921 static void
00922 gnc_account_window_response_cb (GtkDialog *dialog,
00923 gint response,
00924 gpointer data)
00925 {
00926 AccountWindow *aw = data;
00927
00928 ENTER("dialog %p, response %d, aw %p", dialog, response, aw);
00929 switch (response)
00930 {
00931 case GTK_RESPONSE_OK:
00932 switch (aw->dialog_type)
00933 {
00934 case NEW_ACCOUNT:
00935 DEBUG("new acct dialog, OK");
00936 gnc_new_account_ok (aw);
00937 break;
00938 case EDIT_ACCOUNT:
00939 DEBUG("edit acct dialog, OK");
00940 gnc_edit_account_ok (aw);
00941 break;
00942 default:
00943 g_assert_not_reached ();
00944 return;
00945 }
00946 break;
00947 case GTK_RESPONSE_HELP:
00948 switch (aw->dialog_type)
00949 {
00950 case NEW_ACCOUNT:
00951 DEBUG("new acct dialog, HELP");
00952 gnc_gnome_help(HF_HELP, HL_ACC);
00953 break;
00954 case EDIT_ACCOUNT:
00955 DEBUG("edit acct dialog, HELP");
00956 gnc_gnome_help(HF_HELP, HL_ACCEDIT);
00957 break;
00958 default:
00959 g_assert_not_reached ();
00960 return;
00961 }
00962 break;
00963 case GTK_RESPONSE_CANCEL:
00964 default:
00965 DEBUG("CANCEL");
00966 gnc_close_gui_component (aw->component_id);
00967 break;
00968 }
00969 LEAVE(" ");
00970 }
00971
00972 void
00973 gnc_account_window_destroy_cb (GtkObject *object, gpointer data)
00974 {
00975 AccountWindow *aw = data;
00976 Account *account;
00977
00978 ENTER("object %p, aw %p", object, aw);
00979 account = aw_get_account (aw);
00980
00981 gnc_suspend_gui_refresh ();
00982
00983 switch (aw->dialog_type)
00984 {
00985 case NEW_ACCOUNT:
00986 if (account != NULL)
00987 {
00988 xaccAccountBeginEdit (account);
00989 xaccAccountDestroy (account);
00990 aw->account = *guid_null ();
00991 }
00992
00993 DEBUG ("account add window destroyed\n");
00994 break;
00995
00996 case EDIT_ACCOUNT:
00997 break;
00998
00999 default:
01000 PERR ("unexpected dialog type\n");
01001 gnc_resume_gui_refresh ();
01002 LEAVE(" ");
01003 return;
01004 }
01005
01006 gnc_unregister_gui_component (aw->component_id);
01007
01008 gnc_resume_gui_refresh ();
01009
01010 if (aw->subaccount_names)
01011 {
01012 g_strfreev(aw->subaccount_names);
01013 aw->subaccount_names = NULL;
01014 aw->next_name = NULL;
01015 }
01016
01017 g_free (aw);
01018 LEAVE(" ");
01019 }
01020
01021 static void
01022 gnc_account_parent_changed_cb (GtkTreeSelection *selection, gpointer data)
01023 {
01024 AccountWindow *aw = data;
01025 Account *parent_account;
01026 guint32 types, old_types;
01027 GtkTreeModel *type_model;
01028 GtkTreeSelection *type_selection;
01029 gboolean scroll_to = FALSE;
01030
01031 g_return_if_fail (aw);
01032
01033 parent_account = gnc_tree_view_account_get_selected_account (
01034 GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
01035 if (!parent_account)
01036 return;
01037
01038 if (gnc_account_is_root(parent_account))
01039 {
01040 types = aw->valid_types;
01041 }
01042 else
01043 {
01044 types = aw->valid_types &
01045 xaccParentAccountTypesCompatibleWith (xaccAccountGetType (parent_account));
01046 }
01047
01048 type_model = gtk_tree_view_get_model (GTK_TREE_VIEW (aw->type_view));
01049 if (!type_model)
01050 return;
01051
01052 if (aw->type != aw->preferred_account_type &&
01053 (types & (1 << aw->preferred_account_type)) != 0)
01054 {
01055
01056 aw->type = aw->preferred_account_type;
01057 scroll_to = TRUE;
01058 }
01059 else if ((types & (1 << aw->type)) == 0)
01060 {
01061
01062 aw->type = ACCT_TYPE_INVALID;
01063 }
01064 else
01065 {
01066
01067 old_types = gnc_tree_model_account_types_get_mask (type_model);
01068 if (old_types != types)
01069 scroll_to = TRUE;
01070 }
01071
01072 gnc_tree_model_account_types_set_mask (type_model, types);
01073
01074 if (scroll_to)
01075 {
01076 type_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->type_view));
01077 gnc_tree_model_account_types_set_selection(type_selection, 1 << aw->type);
01078 }
01079
01080 gnc_account_window_set_name(aw);
01081 }
01082
01083 static void
01084 gnc_account_type_changed_cb (GtkTreeSelection *selection, gpointer data)
01085 {
01086 AccountWindow *aw = data;
01087 gboolean sensitive;
01088 GNCAccountType type_id;
01089
01090 g_return_if_fail (aw != NULL);
01091
01092 sensitive = FALSE;
01093
01094 type_id = gnc_tree_model_account_types_get_selection_single(selection);
01095 if (type_id == ACCT_TYPE_NONE)
01096 {
01097 aw->type = ACCT_TYPE_INVALID;
01098 }
01099 else
01100 {
01101 aw->type = type_id;
01102 aw->preferred_account_type = type_id;
01103
01104 gnc_account_commodity_from_type (aw, TRUE);
01105
01106 sensitive = (aw->type != ACCT_TYPE_EQUITY &&
01107 aw->type != ACCT_TYPE_CURRENCY &&
01108 aw->type != ACCT_TYPE_STOCK &&
01109 aw->type != ACCT_TYPE_MUTUAL &&
01110 aw->type != ACCT_TYPE_TRADING);
01111 }
01112
01113 gtk_widget_set_sensitive (aw->opening_balance_page, sensitive);
01114
01115 if (!sensitive)
01116 {
01117 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01118 gnc_numeric_zero ());
01119 }
01120 }
01121
01122 static void
01123 gnc_account_type_view_create (AccountWindow *aw)
01124 {
01125 GtkTreeModel *model;
01126 GtkTreeSelection *selection;
01127 GtkCellRenderer *renderer;
01128 GtkTreeView *view;
01129
01130 if (aw->valid_types == 0)
01131 {
01132
01133 aw->valid_types = xaccAccountTypesValid () | (1 << aw->type);
01134 aw->preferred_account_type = aw->type;
01135 }
01136 else if ((aw->valid_types & (1 << aw->type)) != 0)
01137 {
01138
01139 aw->preferred_account_type = aw->type;
01140 }
01141 else if ((aw->valid_types & (1 << last_used_account_type)) != 0)
01142 {
01143
01144 aw->type = last_used_account_type;
01145 aw->preferred_account_type = last_used_account_type;
01146 }
01147 else
01148 {
01149
01150 int i;
01151 aw->preferred_account_type = aw->type;
01152 aw->type = ACCT_TYPE_INVALID;
01153 for (i = 0; i < 32; i++)
01154 if ((aw->valid_types & (1 << i)) != 0)
01155 {
01156 aw->type = i;
01157 break;
01158 }
01159 }
01160
01161 model = gnc_tree_model_account_types_filter_using_mask (aw->valid_types);
01162
01163 view = GTK_TREE_VIEW (aw->type_view);
01164 gtk_tree_view_set_model (view, model);
01165 g_object_unref (G_OBJECT (model));
01166
01167 renderer = gtk_cell_renderer_text_new ();
01168 gtk_tree_view_insert_column_with_attributes (
01169 view, -1, NULL, renderer,
01170 "text", GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME,
01171 NULL);
01172 gtk_tree_view_set_search_column (view, GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME);
01173
01174 selection = gtk_tree_view_get_selection (view);
01175 g_signal_connect (G_OBJECT (selection), "changed",
01176 G_CALLBACK (gnc_account_type_changed_cb), aw);
01177
01178 gnc_tree_model_account_types_set_selection(selection, 1 << aw->type);
01179 }
01180
01181 void
01182 gnc_account_name_insert_text_cb (GtkWidget *entry,
01183 const gchar *text,
01184 gint length,
01185 gint *position,
01186 gpointer data)
01187 {
01188 GtkEditable *editable = GTK_EDITABLE( entry );
01189 const gchar *separator = NULL;
01190 gchar **strsplit;
01191
01192 separator = gnc_get_account_separator_string();
01193 strsplit = g_strsplit ( text, separator, 0 );
01194 if ( strsplit[1] != NULL )
01195 {
01196 gchar *result = g_strjoinv ( NULL, strsplit );
01197 g_signal_handlers_block_by_func ( G_OBJECT ( editable ),
01198 G_CALLBACK ( gnc_account_name_insert_text_cb ),
01199 data );
01200 gtk_editable_insert_text ( editable, result, g_utf8_strlen ( result, -1 ), position );
01201 g_signal_handlers_unblock_by_func ( G_OBJECT ( editable ),
01202 G_CALLBACK ( gnc_account_name_insert_text_cb ),
01203 data );
01204 g_signal_stop_emission_by_name (G_OBJECT ( editable ), "insert_text");
01205 g_free (result);
01206 }
01207
01208 g_strfreev ( strsplit );
01209 }
01210
01211 void
01212 gnc_account_name_changed_cb(GtkWidget *widget, gpointer data)
01213 {
01214 AccountWindow *aw = data;
01215
01216 gnc_account_window_set_name (aw);
01217 }
01218
01219 void
01220 gnc_account_color_default_cb(GtkWidget *widget, gpointer data)
01221 {
01222 GdkColor color;
01223 AccountWindow *aw = data;
01224
01225 gdk_color_parse( DEFAULT_COLOR, &color);
01226 gtk_color_button_set_color(GTK_COLOR_BUTTON(aw->color_entry_button), &color);
01227
01228 }
01229
01230 static void
01231 commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
01232 {
01233 AccountWindow *aw = data;
01234 gnc_commodity *currency;
01235 GtkTreeSelection *selection;
01236
01237 currency = (gnc_commodity *) gnc_general_select_get_selected (gsl);
01238 if (!currency)
01239 return;
01240
01241 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01242 gnc_commodity_get_fraction (currency));
01243 gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (aw->opening_balance_edit),
01244 gnc_commodity_print_info (currency, FALSE));
01245
01246 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->transfer_tree));
01247 gtk_tree_selection_unselect_all (selection);
01248 }
01249
01250 static gboolean
01251 account_commodity_filter (GtkTreeSelection *selection,
01252 GtkTreeModel *unused_model,
01253 GtkTreePath *s_path,
01254 gboolean path_currently_selected,
01255 gpointer user_data)
01256 {
01257 gnc_commodity *commodity;
01258 AccountWindow *aw;
01259 Account *account;
01260
01261 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
01262
01263 aw = user_data;
01264
01265 if (path_currently_selected)
01266 {
01267
01268 return TRUE;
01269 }
01270
01271 account = gnc_tree_view_account_get_account_from_path (GNC_TREE_VIEW_ACCOUNT (aw->transfer_tree), s_path);
01272 if (!account)
01273 {
01274 return FALSE;
01275 }
01276
01277 commodity = (gnc_commodity *)
01278 gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
01279
01280 return gnc_commodity_equiv (xaccAccountGetCommodity (account), commodity);
01281 }
01282
01283 void
01284 opening_equity_cb (GtkWidget *w, gpointer data)
01285 {
01286 AccountWindow *aw = data;
01287 gboolean use_equity;
01288
01289 use_equity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
01290
01291 gtk_widget_set_sensitive (aw->transfer_account_scroll, !use_equity);
01292 }
01293
01294
01295
01296
01297
01298
01299
01300
01301 static void
01302 gnc_account_window_create(AccountWindow *aw)
01303 {
01304 GtkWidget *amount;
01305 GtkWidget *date_edit;
01306 GObject *awo;
01307 GtkWidget *box;
01308 GtkWidget *label;
01309 GtkBuilder *builder;
01310 GtkTreeSelection *selection;
01311
01312 ENTER("aw %p, modal %d", aw, aw->modal);
01313 builder = gtk_builder_new();
01314 gnc_builder_add_from_file (builder, "account.glade", "fraction_liststore");
01315 gnc_builder_add_from_file (builder, "account.glade", "Account Dialog");
01316
01317 aw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Account Dialog"));
01318 awo = G_OBJECT (aw->dialog);
01319
01320 g_object_set_data (awo, "dialog_info", aw);
01321
01322 if (!aw->modal)
01323 g_signal_connect (awo, "response",
01324 G_CALLBACK (gnc_account_window_response_cb), aw);
01325 else
01326 gtk_window_set_modal (GTK_WINDOW (aw->dialog), TRUE);
01327
01328 aw->notebook = GTK_WIDGET(gtk_builder_get_object (builder, "account_notebook"));
01329 aw->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
01330 aw->description_entry = GTK_WIDGET(gtk_builder_get_object (builder, "description_entry"));
01331 aw->color_entry_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_entry_button"));
01332 aw->color_default_button = GTK_WIDGET(gtk_builder_get_object (builder, "color_default_button"));
01333 aw->code_entry = GTK_WIDGET(gtk_builder_get_object (builder, "code_entry"));
01334 aw->notes_text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (GTK_WIDGET(gtk_builder_get_object (builder, "notes_text"))));
01335
01336 box = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_hbox"));
01337 aw->commodity_edit = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
01338 gnc_commodity_edit_get_string,
01339 gnc_commodity_edit_new_select,
01340 &aw->commodity_mode);
01341 gtk_box_pack_start(GTK_BOX(box), aw->commodity_edit, TRUE, TRUE, 0);
01342 gtk_widget_show (aw->commodity_edit);
01343
01344 label = GTK_WIDGET(gtk_builder_get_object (builder, "security_label"));
01345 gnc_general_select_make_mnemonic_target (GNC_GENERAL_SELECT(aw->commodity_edit), label);
01346
01347 g_signal_connect (G_OBJECT (aw->commodity_edit), "changed",
01348 G_CALLBACK (commodity_changed_cb), aw);
01349
01350 aw->account_scu = GTK_WIDGET(gtk_builder_get_object (builder, "account_scu"));
01351
01352 box = GTK_WIDGET(gtk_builder_get_object (builder, "parent_scroll"));
01353
01354 aw->parent_tree = gnc_tree_view_account_new(TRUE);
01355 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->parent_tree));
01356 gtk_widget_show(GTK_WIDGET(aw->parent_tree));
01357 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (aw->parent_tree));
01358 g_signal_connect (G_OBJECT (selection), "changed",
01359 G_CALLBACK (gnc_account_parent_changed_cb), aw);
01360
01361 aw->tax_related_button = GTK_WIDGET(gtk_builder_get_object (builder, "tax_related_button"));
01362 aw->placeholder_button = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_button"));
01363 aw->hidden_button = GTK_WIDGET(gtk_builder_get_object (builder, "hidden_button"));
01364
01365 box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_box"));
01366 amount = gnc_amount_edit_new ();
01367 aw->opening_balance_edit = amount;
01368 gtk_box_pack_start(GTK_BOX(box), amount, TRUE, TRUE, 0);
01369 gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
01370 gtk_widget_show (amount);
01371
01372 label = GTK_WIDGET(gtk_builder_get_object (builder, "balance_label"));
01373 gtk_label_set_mnemonic_widget (GTK_LABEL(label), amount);
01374
01375 box = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_date_box"));
01376 date_edit = gnc_date_edit_new (time (NULL), 1, 1);
01377 aw->opening_balance_date_edit = date_edit;
01378 gtk_box_pack_start(GTK_BOX(box), date_edit, TRUE, TRUE, 0);
01379 gtk_widget_show (date_edit);
01380
01381 aw->opening_balance_page =
01382 gtk_notebook_get_nth_page (GTK_NOTEBOOK (aw->notebook), 1);
01383
01384 aw->opening_equity_radio = GTK_WIDGET(gtk_builder_get_object (builder,
01385 "opening_equity_radio"));
01386
01387 box = GTK_WIDGET(gtk_builder_get_object (builder, "transfer_account_scroll"));
01388 aw->transfer_account_scroll = box;
01389
01390 aw->transfer_tree = GTK_WIDGET(gnc_tree_view_account_new(FALSE));
01391 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(aw->transfer_tree));
01392 gtk_tree_selection_set_select_function(selection, account_commodity_filter, aw, NULL);
01393
01394 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->transfer_tree));
01395 gtk_widget_show (GTK_WIDGET(aw->transfer_tree));
01396
01397 label = GTK_WIDGET(gtk_builder_get_object (builder, "parent_label"));
01398 gtk_label_set_mnemonic_widget (GTK_LABEL(label), GTK_WIDGET(aw->parent_tree));
01399
01400
01401 aw->type_view = GTK_WIDGET(gtk_builder_get_object (builder, "type_view"));
01402 gnc_account_type_view_create (aw);
01403
01404 gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW(aw->dialog));
01405
01406 gtk_widget_grab_focus(GTK_WIDGET(aw->name_entry));
01407
01408 gtk_builder_connect_signals(builder, aw);
01409 g_object_unref(G_OBJECT(builder));
01410
01411 LEAVE(" ");
01412 }
01413
01414
01415 static char *
01416 get_ui_fullname (AccountWindow *aw)
01417 {
01418 Account *parent_account;
01419 char *fullname;
01420 const gchar *name;
01421
01422 name = gtk_entry_get_text (GTK_ENTRY(aw->name_entry));
01423 if (!name || *name == '\0')
01424 name = _("<No name>");
01425
01426 parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
01427
01428 if (parent_account && !gnc_account_is_root(parent_account))
01429 {
01430 char *parent_name;
01431 const gchar *separator;
01432
01433 parent_name = gnc_account_get_full_name (parent_account);
01434
01435 separator = gnc_get_account_separator_string ();
01436 fullname = g_strconcat (parent_name, separator, name, NULL);
01437
01438 g_free (parent_name);
01439 }
01440 else
01441 fullname = g_strdup (name);
01442
01443 return fullname;
01444 }
01445
01446 static void
01447 gnc_account_window_set_name (AccountWindow *aw)
01448 {
01449 char *fullname;
01450 char *title;
01451
01452 if (!aw || !aw->parent_tree)
01453 return;
01454
01455 fullname = get_ui_fullname (aw);
01456
01457 if (aw->dialog_type == EDIT_ACCOUNT)
01458 title = g_strconcat(_("Edit Account"), " - ", fullname, NULL);
01459 else if (aw->next_name && (g_strv_length(aw->next_name) > 0))
01460 {
01461 const char *format = _("(%d) New Accounts");
01462 char *prefix;
01463
01464 prefix = g_strdup_printf (format, g_strv_length(aw->next_name) + 1);
01465
01466 title = g_strconcat (prefix, " - ", fullname, " ...", NULL);
01467
01468 g_free (prefix);
01469 }
01470 else
01471 title = g_strconcat (_("New Account"), " - ", fullname, NULL);
01472
01473 gtk_window_set_title (GTK_WINDOW(aw->dialog), title);
01474
01475 g_free (fullname);
01476 g_free (title);
01477 }
01478
01479
01480 static void
01481 close_handler (gpointer user_data)
01482 {
01483 AccountWindow *aw = user_data;
01484
01485 ENTER("aw %p, modal %d", aw, aw->modal);
01486 gnc_save_window_size (GCONF_SECTION, GTK_WINDOW(aw->dialog));
01487
01488 gtk_widget_destroy (GTK_WIDGET (aw->dialog));
01489 LEAVE(" ");
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 static void
01501 gnc_ui_refresh_account_window (AccountWindow *aw)
01502 {
01503 if (aw == NULL)
01504 return;
01505
01506
01507
01508 gnc_account_window_set_name (aw);
01509 }
01510
01511
01512 static void
01513 refresh_handler (GHashTable *changes, gpointer user_data)
01514 {
01515 AccountWindow *aw = user_data;
01516 const EventInfo *info;
01517 Account *account;
01518
01519 account = aw_get_account (aw);
01520 if (!account)
01521 {
01522 gnc_close_gui_component (aw->component_id);
01523 return;
01524 }
01525
01526 if (changes)
01527 {
01528 info = gnc_gui_get_entity_events (changes, &aw->account);
01529 if (info && (info->event_mask & QOF_EVENT_DESTROY))
01530 {
01531 gnc_close_gui_component (aw->component_id);
01532 return;
01533 }
01534 }
01535
01536 gnc_ui_refresh_account_window (aw);
01537 }
01538
01539
01540 static AccountWindow *
01541 gnc_ui_new_account_window_internal (QofBook *book,
01542 Account *base_account,
01543 gchar **subaccount_names,
01544 GList *valid_types,
01545 const gnc_commodity * default_commodity,
01546 gboolean modal)
01547 {
01548 const gnc_commodity *commodity, *parent_commodity;
01549 AccountWindow *aw;
01550 Account *account;
01551 GList *list;
01552
01553 g_return_val_if_fail(book, NULL);
01554
01555 aw = g_new0 (AccountWindow, 1);
01556
01557 aw->book = book;
01558 aw->modal = modal;
01559 aw->dialog_type = NEW_ACCOUNT;
01560
01561 aw->valid_types = 0;
01562 for (list = valid_types; list; list = list->next)
01563 aw->valid_types |= (1 << GPOINTER_TO_INT (list->data));
01564
01565 account = xaccMallocAccount (book);
01566 aw->account = *xaccAccountGetGUID (account);
01567
01568 if (base_account)
01569 {
01570 aw->type = xaccAccountGetType (base_account);
01571 parent_commodity = xaccAccountGetCommodity (base_account);
01572 }
01573 else
01574 {
01575 aw->type = last_used_account_type;
01576 parent_commodity = gnc_default_currency ();
01577 }
01578
01579 gnc_suspend_gui_refresh ();
01580
01581 if (subaccount_names && *subaccount_names)
01582 {
01583 xaccAccountSetName (account, subaccount_names[0]);
01584 aw->subaccount_names = subaccount_names;
01585 aw->next_name = subaccount_names + 1;
01586 }
01587
01588 gnc_account_window_create (aw);
01589 gnc_account_to_ui (aw);
01590
01591 gnc_resume_gui_refresh ();
01592
01593 if (default_commodity != NULL)
01594 {
01595 commodity = default_commodity;
01596 if ((aw->type == ACCT_TYPE_STOCK) || (aw->type == ACCT_TYPE_MUTUAL))
01597 {
01598 gtk_entry_set_text(GTK_ENTRY(aw->name_entry),
01599 (gpointer) gnc_commodity_get_mnemonic(commodity));
01600 gtk_entry_set_text(GTK_ENTRY(aw->description_entry),
01601 (gpointer) gnc_commodity_get_fullname(commodity));
01602 }
01603 }
01604 else if ((aw->type != ACCT_TYPE_STOCK) && (aw->type != ACCT_TYPE_MUTUAL))
01605 {
01606 commodity = parent_commodity;
01607 }
01608 else
01609 {
01610 commodity = NULL;
01611 }
01612 gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
01613 (gpointer) commodity);
01614 gnc_account_commodity_from_type (aw, FALSE);
01615
01616 if (base_account == NULL)
01617 {
01618 base_account = gnc_book_get_root_account(book);
01619 }
01620
01621 gtk_tree_view_collapse_all (aw->parent_tree);
01622 gnc_tree_view_account_set_selected_account (
01623 GNC_TREE_VIEW_ACCOUNT (aw->parent_tree), base_account);
01624
01625 gtk_widget_show (aw->dialog);
01626
01627 gnc_window_adjust_for_screen (GTK_WINDOW(aw->dialog));
01628
01629 gnc_account_window_set_name (aw);
01630
01631 aw->component_id = gnc_register_gui_component (DIALOG_NEW_ACCOUNT_CM_CLASS,
01632 refresh_handler,
01633 modal ? NULL : close_handler,
01634 aw);
01635
01636 gnc_gui_component_set_session (aw->component_id, gnc_get_current_session());
01637 gnc_gui_component_watch_entity_type (aw->component_id,
01638 GNC_ID_ACCOUNT,
01639 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
01640 return aw;
01641 }
01642
01643
01644 static gchar **
01645 gnc_split_account_name (QofBook *book, const char *in_name, Account **base_account)
01646 {
01647 Account *root, *account;
01648 gchar **names, **ptr, **out_names;
01649 GList *list, *node;
01650
01651 root = gnc_book_get_root_account (book);
01652 list = gnc_account_get_children(root);
01653 names = g_strsplit(in_name, gnc_get_account_separator_string(), -1);
01654
01655 for (ptr = names; *ptr; ptr++)
01656 {
01657
01658 if (list == NULL)
01659 break;
01660
01661
01662 for (node = list; node; node = g_list_next(node))
01663 {
01664 account = node->data;
01665
01666 if (safe_strcmp(xaccAccountGetName (account), *ptr) == 0)
01667 {
01668
01669 *base_account = account;
01670 break;
01671 }
01672 }
01673
01674
01675 if (node == NULL)
01676 break;
01677
01678 g_list_free(list);
01679 list = gnc_account_get_children (account);
01680 }
01681
01682 out_names = g_strdupv(ptr);
01683 g_strfreev(names);
01684 if (list)
01685 g_list_free(list);
01686 return out_names;
01687 }
01688
01689
01690
01691
01692
01693
01694 Account *
01695 gnc_ui_new_accounts_from_name_window (const char *name)
01696 {
01697 return gnc_ui_new_accounts_from_name_with_defaults (name, NULL, NULL, NULL);
01698 }
01699
01700 Account *
01701 gnc_ui_new_accounts_from_name_window_with_types (const char *name,
01702 GList *valid_types)
01703 {
01704 return gnc_ui_new_accounts_from_name_with_defaults(name, valid_types, NULL, NULL);
01705 }
01706
01707 Account *
01708 gnc_ui_new_accounts_from_name_with_defaults (const char *name,
01709 GList *valid_types,
01710 const gnc_commodity * default_commodity,
01711 Account * parent)
01712 {
01713 QofBook *book;
01714 AccountWindow *aw;
01715 Account *base_account = NULL;
01716 Account *created_account = NULL;
01717 gchar ** subaccount_names;
01718 gint response;
01719 gboolean done = FALSE;
01720
01721 ENTER("name %s, valid %p, commodity %p, account %p",
01722 name, valid_types, default_commodity, parent);
01723 book = gnc_get_current_book();
01724 if (!name || *name == '\0')
01725 {
01726 subaccount_names = NULL;
01727 base_account = NULL;
01728 }
01729 else
01730 subaccount_names = gnc_split_account_name (book, name, &base_account);
01731
01732 if (parent != NULL)
01733 {
01734 base_account = parent;
01735 }
01736 aw = gnc_ui_new_account_window_internal (book, base_account, subaccount_names,
01737 valid_types, default_commodity,
01738 TRUE);
01739
01740 while (!done)
01741 {
01742 response = gtk_dialog_run (GTK_DIALOG(aw->dialog));
01743
01744
01745 gnc_account_window_response_cb (GTK_DIALOG(aw->dialog), response, (gpointer)aw);
01746
01747 switch (response)
01748 {
01749 case GTK_RESPONSE_OK:
01750 created_account = aw->created_account;
01751 done = (created_account != NULL);
01752 break;
01753
01754 case GTK_RESPONSE_HELP:
01755 done = FALSE;
01756 break;
01757
01758 default:
01759 done = TRUE;
01760 break;
01761 }
01762 }
01763
01764 close_handler(aw);
01765 LEAVE("created %s (%p)", xaccAccountGetName(created_account), created_account);
01766 return created_account;
01767 }
01768
01769
01770
01771
01772
01773 static gboolean
01774 find_by_account (gpointer find_data, gpointer user_data)
01775 {
01776 Account *account = find_data;
01777 AccountWindow *aw = user_data;
01778
01779 if (!aw)
01780 return FALSE;
01781
01782 return guid_equal (&aw->account, xaccAccountGetGUID (account));
01783 }
01784
01785
01786
01787
01788
01789
01790
01791 void
01792 gnc_ui_edit_account_window(Account *account)
01793 {
01794 AccountWindow * aw;
01795 Account *parent;
01796
01797 if (account == NULL)
01798 return;
01799
01800 aw = gnc_find_first_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
01801 find_by_account, account);
01802 if (aw)
01803 {
01804 gtk_window_present(GTK_WINDOW(aw->dialog));
01805 return;
01806 }
01807
01808 aw = g_new0 (AccountWindow, 1);
01809
01810 aw->book = gnc_account_get_book(account);
01811 aw->modal = FALSE;
01812 aw->dialog_type = EDIT_ACCOUNT;
01813 aw->account = *xaccAccountGetGUID (account);
01814 aw->subaccount_names = NULL;
01815 aw->type = xaccAccountGetType (account);
01816
01817 gnc_suspend_gui_refresh ();
01818
01819 gnc_account_window_create (aw);
01820 gnc_account_to_ui (aw);
01821
01822 gnc_resume_gui_refresh ();
01823
01824 gtk_widget_show_all (aw->dialog);
01825 gtk_widget_hide (aw->opening_balance_page);
01826
01827 parent = gnc_account_get_parent (account);
01828 if (parent == NULL)
01829 parent = account;
01830
01831 gtk_tree_view_collapse_all (aw->parent_tree);
01832 gnc_tree_view_account_set_selected_account (
01833 GNC_TREE_VIEW_ACCOUNT(aw->parent_tree), parent);
01834
01835 gnc_account_window_set_name (aw);
01836
01837 gnc_window_adjust_for_screen(GTK_WINDOW(aw->dialog));
01838
01839 aw->component_id = gnc_register_gui_component (DIALOG_EDIT_ACCOUNT_CM_CLASS,
01840 refresh_handler,
01841 close_handler, aw);
01842
01843 gnc_gui_component_set_session (aw->component_id, gnc_get_current_session());
01844 gnc_gui_component_watch_entity_type (aw->component_id,
01845 GNC_ID_ACCOUNT,
01846 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
01847
01848 gtk_window_present(GTK_WINDOW(aw->dialog));
01849 }
01850
01851
01852
01853
01854
01855
01856
01857
01858 void
01859 gnc_ui_new_account_window(QofBook *book, Account *parent)
01860 {
01861 g_return_if_fail(book != NULL);
01862 if (parent && book)
01863 g_return_if_fail(gnc_account_get_book(parent) == book);
01864
01865 gnc_ui_new_account_window_internal (book, parent, NULL, NULL, NULL, FALSE);
01866 }
01867
01868 void
01869 gnc_ui_new_account_with_types( QofBook *book,
01870 GList *valid_types )
01871 {
01872 gnc_ui_new_account_window_internal( book, NULL, NULL, valid_types, NULL, FALSE );
01873 }
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885 void
01886 gnc_ui_register_account_destroy_callback (void (*cb)(Account *))
01887 {
01888 if (!cb)
01889 return;
01890
01891 if (g_list_index (ac_destroy_cb_list, cb) == -1)
01892 ac_destroy_cb_list = g_list_append (ac_destroy_cb_list, cb);
01893
01894 return;
01895 }
01896
01897
01898
01899 static void
01900 gnc_account_renumber_update_examples (RenumberDialog *data)
01901 {
01902 gchar *str;
01903 gchar *prefix;
01904 gint interval, num_digits;
01905
01906 prefix = gtk_editable_get_chars(GTK_EDITABLE(data->prefix), 0, -1);
01907 interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->interval));
01908 num_digits = log10(data->num_children * interval) + 1;
01909
01910 str = g_strdup_printf("%s-%0*d", prefix, num_digits, interval);
01911 gtk_label_set_text(GTK_LABEL(data->example1), str);
01912 g_free(str);
01913
01914 str = g_strdup_printf("%s-%0*d", prefix, num_digits,
01915 interval * data->num_children);
01916 gtk_label_set_text(GTK_LABEL(data->example2), str);
01917 g_free(str);
01918
01919 g_free(prefix);
01920 }
01921
01922 void
01923 gnc_account_renumber_prefix_changed_cb (GtkEditable *editable,
01924 RenumberDialog *data)
01925 {
01926 gnc_account_renumber_update_examples(data);
01927 }
01928
01929 void
01930 gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton,
01931 RenumberDialog *data)
01932 {
01933 gnc_account_renumber_update_examples(data);
01934 }
01935
01936 void
01937 gnc_account_renumber_response_cb (GtkDialog *dialog,
01938 gint response,
01939 RenumberDialog *data)
01940 {
01941 GList *children, *tmp;
01942 gchar *str;
01943 gchar *prefix;
01944 gint interval, num_digits, i;
01945
01946 if (response == GTK_RESPONSE_OK)
01947 {
01948 gtk_widget_hide(data->dialog);
01949 children = gnc_account_get_children(data->parent);
01950 prefix = gtk_editable_get_chars(GTK_EDITABLE(data->prefix), 0, -1);
01951 interval =
01952 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->interval));
01953 num_digits = log10(data->num_children * interval) + 1;
01954
01955 gnc_set_busy_cursor (NULL, TRUE);
01956 for (tmp = children, i = 1; tmp; tmp = g_list_next(tmp), i += 1)
01957 {
01958 str = g_strdup_printf("%s-%0*d", prefix, num_digits, interval * i);
01959 xaccAccountSetCode(tmp->data, str);
01960 g_free(str);
01961 }
01962 gnc_unset_busy_cursor (NULL);
01963 g_list_free(children);
01964 }
01965
01966 gtk_widget_destroy(data->dialog);
01967 g_free(data);
01968 }
01969
01970 void
01971 gnc_account_renumber_create_dialog (GtkWidget *window, Account *account)
01972 {
01973 RenumberDialog *data;
01974 GtkBuilder *builder;
01975 GtkWidget *widget;
01976 gchar *string;
01977
01978 data = g_new(RenumberDialog, 1);
01979 data->parent = account;
01980 data->num_children = gnc_account_n_children(account);
01981
01982 builder = gtk_builder_new();
01983 gnc_builder_add_from_file (builder, "account.glade", "interval_adjustment");
01984 gnc_builder_add_from_file (builder, "account.glade", "Renumber Accounts");
01985 data->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Renumber Accounts"));
01986 gtk_window_set_transient_for(GTK_WINDOW(data->dialog), GTK_WINDOW(window));
01987 g_object_set_data_full(G_OBJECT(data->dialog), "builder", builder, g_object_unref);
01988
01989 widget = GTK_WIDGET(gtk_builder_get_object (builder, "header_label"));
01990 string = g_strdup_printf(_( "Renumber the immediate sub-accounts of %s? "
01991 "This will replace the account code field of "
01992 "each child account with a newly generated code."),
01993 gnc_account_get_full_name(account));
01994 gtk_label_set_text(GTK_LABEL(widget), string);
01995 g_free(string);
01996
01997 data->prefix = GTK_WIDGET(gtk_builder_get_object (builder, "prefix_entry"));
01998 data->interval = GTK_WIDGET(gtk_builder_get_object (builder, "interval_spin"));
01999 data->example1 = GTK_WIDGET(gtk_builder_get_object (builder, "example1_label"));
02000 data->example2 = GTK_WIDGET(gtk_builder_get_object (builder, "example2_label"));
02001
02002 gtk_entry_set_text(GTK_ENTRY(data->prefix), xaccAccountGetCode(account));
02003 gnc_account_renumber_update_examples(data);
02004
02005 gtk_builder_connect_signals(builder, data);
02006
02007 gtk_widget_show_all(data->dialog);
02008 }