|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * import-account-matcher.c - flexible account picker/matcher * 00003 * * 00004 * Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca> * 00005 * Copyright (C) 2012 Robert Fewell * 00006 * * 00007 * This program is free software; you can redistribute it and/or * 00008 * modify it under the terms of the GNU General Public License as * 00009 * published by the Free Software Foundation; either version 2 of * 00010 * the License, or (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License* 00018 * along with this program; if not, contact: * 00019 * * 00020 * Free Software Foundation Voice: +1-617-542-5942 * 00021 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00022 * Boston, MA 02110-1301, USA gnu@gnu.org * 00023 \********************************************************************/ 00031 #include "config.h" 00032 00033 #include <gtk/gtk.h> 00034 #include <glib/gi18n.h> 00035 00036 #include "import-account-matcher.h" 00037 #include "import-utilities.h" 00038 #include "dialog-account.h" 00039 #include "dialog-utils.h" 00040 00041 #include "gnc-commodity.h" 00042 #include "gnc-engine.h" 00043 #include "gnc-tree-view-account.h" 00044 #include "gnc-ui.h" 00045 00046 static QofLogModule log_module = GNC_MOD_IMPORT; 00047 00048 #define GCONF_SECTION "dialogs/import/generic_matcher/account_matcher" 00049 00050 /*-******************************************************************\ 00051 * Functions needed by gnc_import_select_account 00052 * 00053 \********************************************************************/ 00057 static AccountPickerDialog* gnc_import_new_account_picker(void) 00058 { 00059 AccountPickerDialog* picker = g_new(AccountPickerDialog, 1); 00060 picker->dialog = NULL; 00061 picker->assistant = NULL; 00062 picker->account_tree = NULL; 00063 picker->account_tree_sw = NULL; 00064 picker->auto_create = TRUE; 00065 picker->account_human_description = NULL; 00066 picker->account_online_id_value = NULL; 00067 picker->account_online_id_label = NULL; 00068 picker->new_account_default_commodity = NULL; 00069 picker->new_account_default_type = 0; 00070 picker->default_account = NULL; 00071 picker->retAccount = NULL; 00072 return picker; 00073 } 00074 00075 00076 /************************************************** 00077 * test_acct_online_id_match 00078 * 00079 * test for match of kvp_frame of account 00080 **************************************************/ 00081 static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id) 00082 { 00083 const gchar * current_online_id = gnc_import_get_acc_online_id(acct); 00084 if ( (current_online_id != NULL 00085 && param_online_id != NULL ) 00086 && strcmp( current_online_id, param_online_id ) == 0 ) 00087 { 00088 return (gpointer *) acct; 00089 } 00090 else 00091 { 00092 return NULL; 00093 } 00094 } 00095 00096 00097 /*********************************************************** 00098 * build_acct_tree 00099 * 00100 * build the account tree with the custome column, online_id 00101 ************************************************************/ 00102 static void 00103 build_acct_tree(AccountPickerDialog *picker) 00104 { 00105 GtkTreeView *account_tree; 00106 GtkTreeViewColumn *col; 00107 00108 /* Build a new account tree */ 00109 DEBUG("Begin"); 00110 account_tree = gnc_tree_view_account_new(FALSE); 00111 picker->account_tree = GNC_TREE_VIEW_ACCOUNT(account_tree); 00112 gtk_tree_view_set_headers_visible (account_tree, TRUE); 00113 col = gnc_tree_view_find_column_by_name(GNC_TREE_VIEW(account_tree), "type"); 00114 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00115 00116 /* Add our custom column. */ 00117 col = gnc_tree_view_account_add_kvp_column (picker->account_tree, 00118 _("Account ID"), "online_id"); 00119 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1)); 00120 00121 gtk_container_add(GTK_CONTAINER(picker->account_tree_sw), 00122 GTK_WIDGET(picker->account_tree)); 00123 00124 /* Configure the columns */ 00125 gnc_tree_view_configure_columns (GNC_TREE_VIEW(picker->account_tree)); 00126 g_object_set(account_tree, 00127 "gconf-section", GCONF_SECTION, 00128 "show-column-menu", TRUE, 00129 (gchar*) NULL); 00130 } 00131 00132 00133 /******************************************************* 00134 * gnc_import_add_account 00135 * 00136 * Callback for when user clicks to create a new account 00137 *******************************************************/ 00138 static void 00139 gnc_import_add_account(GtkWidget *button, AccountPickerDialog *picker) 00140 { 00141 Account *selected_account, *new_account; 00142 GList * valid_types = NULL; 00143 /*DEBUG("Begin"); */ 00144 if (picker->new_account_default_type != ACCT_TYPE_NONE) 00145 { 00146 /*Yes, this is weird, but we really DO want to pass the value instead of the pointer...*/ 00147 valid_types = g_list_prepend(valid_types, GINT_TO_POINTER(picker->new_account_default_type)); 00148 } 00149 selected_account = gnc_tree_view_account_get_selected_account(picker->account_tree); 00150 new_account = gnc_ui_new_accounts_from_name_with_defaults ( picker->account_human_description, 00151 valid_types, 00152 picker->new_account_default_commodity, 00153 selected_account); 00154 g_list_free(valid_types); 00155 gnc_tree_view_account_set_selected_account(picker->account_tree, new_account); 00156 } 00157 00158 00159 /******************************************************* 00160 * account_tree_row_activated_cb 00161 * 00162 * Callback for when user double clicks on an account 00163 *******************************************************/ 00164 static void 00165 account_tree_row_activated_cb(GtkTreeView *view, GtkTreePath *path, 00166 GtkTreeViewColumn *column, 00167 AccountPickerDialog *picker) 00168 { 00169 const gchar *retval_name = NULL; 00170 Account *old_id_acc; 00171 00172 /* See if we have a dialog, if not we are an assistant */ 00173 if (picker->dialog == NULL) 00174 { 00175 GtkAssistant *assistant = GTK_ASSISTANT(picker->assistant); 00176 gint num = gtk_assistant_get_current_page (assistant); 00177 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num); 00178 00179 picker->retAccount = gnc_tree_view_account_get_selected_account(picker->account_tree); 00180 if (picker->retAccount) 00181 retval_name = xaccAccountGetName(picker->retAccount); 00182 if (!retval_name) 00183 retval_name = "(null)"; 00184 DEBUG("Selected account %p, %s", picker->retAccount, retval_name); 00185 00186 /* See if the selected account is a placeholder. */ 00187 if (picker->retAccount && xaccAccountGetPlaceholder (picker->retAccount)) 00188 { 00189 gnc_error_dialog (picker->dialog, 00190 _("The account %s is a placeholder account and does not allow " 00191 "transactions. Please choose a different account."), 00192 retval_name); 00193 } 00194 else if ( picker->account_online_id_value != NULL) 00195 { 00196 /* find the old account for this on line id value and reset it */ 00197 old_id_acc = 00198 gnc_account_foreach_descendant_until(gnc_get_current_root_account (), 00199 test_acct_online_id_match, 00200 /* This argument will only be used as a "const char*" */ 00201 (void*)picker->account_online_id_value); 00202 00203 if (old_id_acc != NULL) 00204 gnc_import_set_acc_online_id(old_id_acc, ""); 00205 00206 gnc_import_set_acc_online_id(picker->retAccount, picker->account_online_id_value); 00207 gtk_assistant_set_page_complete (assistant, page, TRUE); 00208 } 00209 else 00210 gtk_assistant_set_page_complete (assistant, page, TRUE); 00211 } 00212 else 00213 { 00214 gtk_dialog_response(GTK_DIALOG(picker->dialog), GTK_RESPONSE_OK); 00215 } 00216 } 00217 00218 00219 /******************************************************* 00220 * gnc_import_select_account 00221 * 00222 * Main call for use with a dialog 00223 *******************************************************/ 00224 Account * gnc_import_select_account(GtkWidget *parent, 00225 const gchar * account_online_id_value, 00226 gboolean auto_create, 00227 const gchar * account_human_description, 00228 const gnc_commodity * new_account_default_commodity, 00229 GNCAccountType new_account_default_type, 00230 Account * default_selection, 00231 gboolean * ok_pressed) 00232 { 00233 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255 00234 AccountPickerDialog * picker; 00235 gint response; 00236 Account * retval = NULL; 00237 const gchar *retval_name = NULL; 00238 GtkBuilder *builder; 00239 GtkWidget * online_id_label, *button, *box, *pbox; 00240 gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = ""; 00241 gboolean ok_pressed_retval = FALSE; 00242 00243 ENTER("Default commodity received: %s", gnc_commodity_get_fullname( new_account_default_commodity)); 00244 DEBUG("Default account type received: %s", xaccAccountGetTypeStr( new_account_default_type)); 00245 picker = g_new0(AccountPickerDialog, 1); 00246 00247 picker->account_online_id_value = account_online_id_value; 00248 picker->account_human_description = account_human_description; 00249 picker->new_account_default_commodity = new_account_default_commodity; 00250 picker->new_account_default_type = new_account_default_type; 00251 00252 /*DEBUG("Looking for account with online_id: %s", account_online_id_value);*/ 00253 if (account_online_id_value != NULL) 00254 { 00255 retval = 00256 gnc_account_foreach_descendant_until(gnc_get_current_root_account (), 00257 test_acct_online_id_match, 00258 /* This argument will only be used as a "const char*" */ 00259 (void*)account_online_id_value); 00260 } 00261 if (retval == NULL && auto_create != 0) 00262 { 00263 /* load the interface */ 00264 builder = gtk_builder_new(); 00265 gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker"); 00266 gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker_content"); 00267 /* connect the signals in the interface */ 00268 if (builder == NULL) 00269 { 00270 PERR("Error opening the glade builder interface"); 00271 } 00272 picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker")); 00273 if (parent) 00274 gtk_window_set_transient_for (GTK_WINDOW (picker->dialog), 00275 GTK_WINDOW (parent)); 00276 00277 /* Pack the content into the dialog vbox */ 00278 pbox = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_vbox")); 00279 box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content")); 00280 gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE, 0); 00281 00282 picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw")); 00283 online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label")); 00284 button = GTK_WIDGET(gtk_builder_get_object (builder, "newbutton")); 00285 gtk_button_set_use_stock (GTK_BUTTON(button), TRUE); 00286 00287 //printf("gnc_import_select_account(): Fin get widget\n"); 00288 00289 if (account_human_description != NULL) 00290 { 00291 strncat(account_description_text, account_human_description, 00292 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00293 strncat(account_description_text, "\n", 00294 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00295 } 00296 if (account_online_id_value != NULL) 00297 { 00298 strncat(account_description_text, _("(Full account ID: "), 00299 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00300 strncat(account_description_text, account_online_id_value, 00301 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00302 strncat(account_description_text, ")", 00303 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00304 } 00305 gtk_label_set_text((GtkLabel*)online_id_label, account_description_text); 00306 build_acct_tree(picker); 00307 gnc_tree_view_account_set_selected_account(picker->account_tree, default_selection); 00308 00309 gtk_window_set_modal(GTK_WINDOW(picker->dialog), TRUE); 00310 g_signal_connect(picker->account_tree, "row-activated", 00311 G_CALLBACK(account_tree_row_activated_cb), picker); 00312 do 00313 { 00314 response = gtk_dialog_run(GTK_DIALOG(picker->dialog)); 00315 switch (response) 00316 { 00317 case GTK_RESPONSE_OK: 00318 retval = gnc_tree_view_account_get_selected_account(picker->account_tree); 00319 if (retval) 00320 retval_name = xaccAccountGetName(retval); 00321 if (!retval_name) 00322 retval_name = "(null)"; 00323 DEBUG("Selected account %p, %s", retval, retval_name); 00324 00325 /* See if the selected account is a placeholder. */ 00326 if (retval && xaccAccountGetPlaceholder (retval)) 00327 { 00328 gnc_error_dialog 00329 (picker->dialog, 00330 _("The account %s is a placeholder account and does not allow " 00331 "transactions. Please choose a different account."), 00332 retval_name); 00333 response = GNC_RESPONSE_NEW; 00334 break; 00335 } 00336 00337 if ( account_online_id_value != NULL) 00338 { 00339 gnc_import_set_acc_online_id(retval, account_online_id_value); 00340 } 00341 ok_pressed_retval = TRUE; 00342 break; 00343 case GNC_RESPONSE_NEW: 00344 gnc_import_add_account(NULL, picker); 00345 ok_pressed_retval = TRUE; 00346 break; 00347 default: 00348 ok_pressed_retval = FALSE; 00349 break; 00350 } 00351 } 00352 while (response == GNC_RESPONSE_NEW); 00353 00354 g_object_unref(G_OBJECT(builder)); 00355 gtk_widget_destroy(picker->dialog); 00356 } 00357 else 00358 { 00359 retval_name = retval ? xaccAccountGetName(retval) : NULL; 00360 ok_pressed_retval = TRUE; /* There was no dialog involved, so the computer "pressed" ok */ 00361 } 00362 /*FIXME: DEBUG("WRITEME: gnc_import_select_account() Here we should check if account type is compatible, currency matches, etc.\n"); */ 00363 g_free(picker); 00364 /*DEBUG("Return value: %p%s%s%s",retval,", account name:",xaccAccountGetName(retval),"\n");*/ 00365 if (ok_pressed != NULL) 00366 { 00367 *ok_pressed = ok_pressed_retval; 00368 } 00369 LEAVE("Selected account %p, %s", retval, retval_name ? retval_name : "(null)"); 00370 return retval; 00371 } 00372 00373 00374 /********************************************************************** 00375 * These are the routines for use with an Assistant page 00376 **********************************************************************/ 00377 00378 /******************************************************* 00379 * gnc_import_account_assist_setup 00380 * 00381 * Main call for page setup in an assistant 00382 *******************************************************/ 00383 AccountPickerDialog* gnc_import_account_assist_setup(GtkWidget *parent) 00384 { 00385 AccountPickerDialog * picker; 00386 GtkBuilder *builder; 00387 GtkWidget *button, *box; 00388 00389 /* Init the account picker structure */ 00390 picker = gnc_import_new_account_picker(); 00391 00392 /* load the interface */ 00393 builder = gtk_builder_new(); 00394 gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker_content"); 00395 /* connect the signals in the interface */ 00396 if (builder == NULL) 00397 { 00398 PERR("Error opening the glade builder interface"); 00399 } 00400 00401 picker->assistant = gtk_widget_get_parent(parent); 00402 /* Pack content into Assistant page widget */ 00403 box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content")); 00404 gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6); 00405 00406 picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw")); 00407 picker->account_online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label")); 00408 00409 /* Add the New Account Button */ 00410 button = gtk_button_new_with_mnemonic ("_New Account"); 00411 gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 6); 00412 gtk_button_set_use_stock (GTK_BUTTON(button), TRUE); 00413 gtk_widget_show (button); 00414 g_signal_connect(button, "clicked", 00415 G_CALLBACK(gnc_import_add_account), picker); 00416 00417 build_acct_tree(picker); 00418 00419 g_signal_connect(picker->account_tree, "row-activated", 00420 G_CALLBACK(account_tree_row_activated_cb), picker); 00421 00422 g_object_unref(G_OBJECT(builder)); 00423 return picker; 00424 } 00425 00426 00427 /******************************************************* 00428 * gnc_import_account_assist_update 00429 * 00430 * updates the page and returns account found. 00431 *******************************************************/ 00432 Account * gnc_import_account_assist_update (AccountPickerDialog *picker) 00433 { 00434 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255 00435 00436 const gchar *retval_name = NULL; 00437 gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = ""; 00438 00439 ENTER("Default commodity received: %s", gnc_commodity_get_fullname( picker->new_account_default_commodity)); 00440 DEBUG("Default account type received: %s", xaccAccountGetTypeStr( picker->new_account_default_type)); 00441 00442 /*DEBUG("Looking for account with online_id: %s", picker->account_online_id_value);*/ 00443 if (picker->account_online_id_value != NULL) 00444 { 00445 picker->retAccount = 00446 gnc_account_foreach_descendant_until(gnc_get_current_root_account (), 00447 test_acct_online_id_match, 00448 /* This argument will only be used as a "const char*" */ 00449 (void*)picker->account_online_id_value); 00450 } 00451 00452 if (picker->account_human_description != NULL) 00453 { 00454 strncat(account_description_text, picker->account_human_description, 00455 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00456 strncat(account_description_text, "\n", 00457 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00458 } 00459 if (picker->account_online_id_value != NULL) 00460 { 00461 strncat(account_description_text, _("(Full account ID: "), 00462 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00463 strncat(account_description_text, picker->account_online_id_value, 00464 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00465 strncat(account_description_text, ")", 00466 ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text)); 00467 } 00468 gtk_label_set_text(GTK_LABEL( picker->account_online_id_label), account_description_text); 00469 00470 if (picker->default_account == NULL) 00471 gnc_tree_view_account_set_selected_account(picker->account_tree, picker->retAccount); 00472 else 00473 gnc_tree_view_account_set_selected_account(picker->account_tree, picker->default_account); 00474 00475 /*FIXME: DEBUG("WRITEME: Here we should check if an account type is compatible, currency matches, etc.\n"); */ 00476 00477 /*DEBUG("Return value: %p%s%s%s",picker->retAccount,", account name:",xaccAccountGetName(picker->retAccount),"\n");*/ 00478 retval_name = picker->retAccount ? xaccAccountGetName(picker->retAccount) : NULL; 00479 LEAVE("Selected account %p, %s", picker->retAccount, retval_name ? retval_name : "(null)"); 00480 return picker->retAccount; 00481 } 00482
1.7.4