|
GnuCash 2.4.99
|
00001 /* 00002 * assistant-ab-initial.c -- Initialise the AqBanking wizard 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License as 00006 * published by the Free Software Foundation; either version 2 of 00007 * the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, contact: 00016 * 00017 * Free Software Foundation Voice: +1-617-542-5942 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00019 * Boston, MA 02110-1301, USA gnu@gnu.org 00020 */ 00021 00032 #include "config.h" 00033 00034 #include <aqbanking/banking.h> 00035 #include <glib.h> 00036 #include <glib/gi18n.h> 00037 #include <glib/gstdio.h> 00038 #include <gdk/gdkkeysyms.h> 00039 #ifdef HAVE_SYS_WAIT_H 00040 # include <sys/wait.h> 00041 #endif 00042 #include <fcntl.h> 00043 #include <unistd.h> 00044 00045 #include "dialog-utils.h" 00046 #include "assistant-ab-initial.h" 00047 #include "assistant-utils.h" 00048 #include "gnc-ab-kvp.h" 00049 #include "gnc-ab-utils.h" 00050 #include "gnc-component-manager.h" 00051 #include "gnc-glib-utils.h" 00052 #include "gnc-ui.h" 00053 #include "gnc-ui-util.h" 00054 #include "gnc-session.h" 00055 #include "import-account-matcher.h" 00056 00057 #if AQBANKING_VERSION_INT > 49908 00058 /* For aqbanking > 4.99.8. See below. */ 00059 # include <aqbanking/dlg_setup.h> 00060 #endif 00061 00062 /* This static indicates the debugging module that this .o belongs to. */ 00063 static QofLogModule log_module = GNC_MOD_ASSISTANT; 00064 00065 #define ASSISTANT_AB_INITIAL_CM_CLASS "assistant-ab-initial" 00066 00067 typedef struct _ABInitialInfo ABInitialInfo; 00068 typedef struct _DeferredInfo DeferredInfo; 00069 typedef struct _AccCbData AccCbData; 00070 typedef struct _RevLookupData RevLookupData; 00071 00072 void aai_on_prepare (GtkAssistant *assistant, GtkWidget *page, 00073 gpointer user_data); 00074 00075 void aai_on_finish (GtkAssistant *gtkassistant, gpointer user_data); 00076 void aai_on_cancel (GtkAssistant *assistant, gpointer user_data); 00077 void aai_destroy_cb(GtkObject *object, gpointer user_data); 00078 00079 gboolean aai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data); 00080 00081 void aai_wizard_page_prepare (GtkAssistant *assistant, gpointer user_data); 00082 void aai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data); 00083 00084 void aai_match_page_prepare (GtkAssistant *assistant, gpointer user_data); 00085 00086 static gboolean banking_has_accounts(AB_BANKING *banking); 00087 static void hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data); 00088 00089 static void child_exit_cb(GPid pid, gint status, gpointer data); 00090 static gchar *ab_account_longname(const AB_ACCOUNT *ab_acc); 00091 static AB_ACCOUNT *update_account_list_acc_cb(AB_ACCOUNT *ab_acc, gpointer user_data); 00092 static void update_account_list(ABInitialInfo *info); 00093 static gboolean find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data); 00094 static gboolean clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data); 00095 static void account_list_clicked_cb (GtkTreeView *view, GtkTreePath *path, 00096 GtkTreeViewColumn *col, gpointer user_data); 00097 static void clear_kvp_acc_cb(Account *gnc_acc, gpointer user_data); 00098 static void save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data); 00099 static void aai_close_handler(gpointer user_data); 00100 00101 struct _ABInitialInfo 00102 { 00103 GtkWidget *window; 00104 GtkWidget *assistant; 00105 00106 /* account match page */ 00107 gboolean match_page_prepared; 00108 GtkTreeView *account_view; 00109 GtkListStore *account_store; 00110 00111 /* managed by child_exit_cb */ 00112 DeferredInfo *deferred_info; 00113 00114 /* AqBanking stuff */ 00115 AB_BANKING *api; 00116 /* AB_ACCOUNT* -> Account* -- DO NOT DELETE THE KEYS! */ 00117 GHashTable *gnc_hash; 00118 }; 00119 00120 struct _DeferredInfo 00121 { 00122 ABInitialInfo *initial_info; 00123 gchar *wizard_path; 00124 gboolean qt_probably_unavailable; 00125 }; 00126 00127 struct _AccCbData 00128 { 00129 AB_BANKING *api; 00130 GHashTable *hash; 00131 }; 00132 00133 struct _RevLookupData 00134 { 00135 Account *gnc_acc; 00136 AB_ACCOUNT *ab_acc; 00137 }; 00138 00139 enum account_list_cols 00140 { 00141 ACCOUNT_LIST_COL_INDEX = 0, 00142 ACCOUNT_LIST_COL_AB_NAME, 00143 ACCOUNT_LIST_COL_AB_ACCT, 00144 ACCOUNT_LIST_COL_GNC_NAME, 00145 ACCOUNT_LIST_COL_CHECKED, 00146 NUM_ACCOUNT_LIST_COLS 00147 }; 00148 00149 gboolean 00150 aai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) 00151 { 00152 if (event->keyval == GDK_Escape) 00153 { 00154 gtk_widget_destroy(widget); 00155 return TRUE; 00156 } 00157 else 00158 { 00159 return FALSE; 00160 } 00161 } 00162 00163 void 00164 aai_on_cancel (GtkAssistant *gtkassistant, gpointer user_data) 00165 { 00166 ABInitialInfo *info = user_data; 00167 00168 gtk_widget_destroy(info->window); 00169 } 00170 00171 void 00172 aai_destroy_cb(GtkObject *object, gpointer user_data) 00173 { 00174 ABInitialInfo *info = user_data; 00175 00176 gnc_unregister_gui_component_by_data(ASSISTANT_AB_INITIAL_CM_CLASS, info); 00177 00178 if (info->deferred_info) 00179 { 00180 g_message("Online Banking assistant is being closed but the wizard is still " 00181 "running. Inoring."); 00182 00183 /* Tell child_exit_cb() that there is no assistant anymore */ 00184 info->deferred_info->initial_info = NULL; 00185 } 00186 00187 if (info->gnc_hash) 00188 { 00189 #ifdef AQBANKING_VERSION_4_EXACTLY 00190 AB_Banking_OnlineFini(info->api, 0); 00191 #else 00192 AB_Banking_OnlineFini(info->api); 00193 #endif 00194 g_hash_table_destroy(info->gnc_hash); 00195 info->gnc_hash = NULL; 00196 } 00197 00198 if (info->api) 00199 { 00200 gnc_AB_BANKING_delete(info->api); 00201 info->api = NULL; 00202 } 00203 00204 gtk_widget_destroy(info->window); 00205 info->window = NULL; 00206 00207 g_free(info); 00208 } 00209 00210 void 00211 aai_wizard_page_prepare (GtkAssistant *assistant, gpointer user_data) 00212 { 00213 ABInitialInfo *info = user_data; 00214 gint num = gtk_assistant_get_current_page (assistant); 00215 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num); 00216 00217 g_return_if_fail(info->api); 00218 00219 /* Enable the Assistant Buttons if we accounts */ 00220 if (banking_has_accounts(info->api)) 00221 gtk_assistant_set_page_complete (assistant, page, TRUE); 00222 else 00223 gtk_assistant_set_page_complete (assistant, page, FALSE); 00224 } 00225 00226 void 00227 aai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data) 00228 { 00229 ABInitialInfo *info = user_data; 00230 gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(info->window)); 00231 GtkWidget *page = gtk_assistant_get_nth_page (GTK_ASSISTANT(info->window), num); 00232 00233 AB_BANKING *banking = info->api; 00234 GWEN_BUFFER *buf; 00235 gboolean wizard_exists; 00236 const gchar *wizard_path; 00237 gboolean qt_probably_unavailable = FALSE; 00238 00239 g_return_if_fail(banking); 00240 00241 ENTER("user_data: %p", user_data); 00242 00243 if (info->deferred_info) 00244 { 00245 LEAVE("Wizard is still running"); 00246 return; 00247 } 00248 00249 #if AQBANKING_VERSION_INT > 49908 00250 /* For aqbanking5 > 4.99.8: Use AB_Banking_GetNewUserDialog(). */ 00251 { 00252 GWEN_DIALOG *dlg = 00253 AB_SetupDialog_new(banking); 00254 00255 if (AB_Banking_OnlineInit(banking) != 0) 00256 { 00257 PERR("Got error on AB_Banking_OnlineInit!"); 00258 } 00259 00260 if (!dlg) 00261 { 00262 PERR("Could not lookup Setup Dialog of aqbanking!"); 00263 } 00264 else 00265 { 00266 int rv = GWEN_Gui_ExecDialog(dlg, 0); 00267 if (rv <= 0) 00268 { 00269 /* Dialog was aborted/rejected */ 00270 PERR("Setup Dialog of aqbanking aborted/rejected !"); 00271 } 00272 GWEN_Dialog_free(dlg); 00273 } 00274 00275 if (AB_Banking_OnlineFini(banking) != 0) 00276 { 00277 PERR("Got error on AB_Banking_OnlineFini!"); 00278 } 00279 } 00280 #else 00281 /* Previous implementation for aqbanking <= 4.99.8: Use the 00282 * external application. */ 00283 00284 00285 /* This is the point where we look for and start an external 00286 * application shipped with aqbanking that contains the setup assistant 00287 * for AqBanking related stuff. It requires qt (but not kde). This 00288 * application contains the very verbose step-by-step setup wizard 00289 * for the AqBanking account, and the application is shared with 00290 * other AqBanking-based financial managers that offer the AqBanking 00291 * features (e.g. KMyMoney). See gnucash-devel discussion here 00292 * https://lists.gnucash.org/pipermail/gnucash-devel/2004-December/012351.html 00293 */ 00294 buf = GWEN_Buffer_new(NULL, 300, 0, 0); 00295 AB_Banking_FindWizard(banking, "", NULL, buf); 00296 wizard_exists = *GWEN_Buffer_GetStart(buf) != 0; 00297 wizard_path = GWEN_Buffer_GetStart(buf); 00298 00299 if (wizard_exists) 00300 { 00301 /* Really check whether the file exists */ 00302 gint fd = g_open(wizard_path, O_RDONLY, 0); 00303 if (fd == -1) 00304 wizard_exists = FALSE; 00305 else 00306 close(fd); 00307 } 00308 00309 #ifdef G_OS_WIN32 00310 { 00311 const char *check_file = "qtdemo.exe"; 00312 gchar *found_program = g_find_program_in_path(check_file); 00313 if (found_program) 00314 { 00315 g_debug("Yes, we found the Qt demo program in %s\n", found_program); 00316 g_free(found_program); 00317 } 00318 else 00319 { 00320 g_warning("Ouch, no Qt demo program was found. Qt not installed?\n"); 00321 qt_probably_unavailable = TRUE; 00322 } 00323 } 00324 #endif 00325 00326 if (wizard_exists) 00327 { 00328 /* Call the qt wizard. See the note above about why this 00329 * approach is chosen. */ 00330 00331 GPid pid; 00332 GError *error = NULL; 00333 gchar *argv[2]; 00334 gboolean spawned; 00335 00336 argv[0] = g_strdup (wizard_path); 00337 argv[1] = NULL; 00338 spawned = g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, 00339 NULL, NULL, &pid, &error); 00340 g_free (argv[0]); 00341 00342 if (error) 00343 g_critical( 00344 "Error on starting AqBanking setup wizard: Code %d: %s", 00345 error->code, error->message ? error->message : "(null)"); 00346 00347 if (!spawned) 00348 { 00349 g_critical("Could not start AqBanking setup wizard: %s", 00350 error->message ? error->message : "(null)"); 00351 g_error_free (error); 00352 } 00353 else 00354 { 00355 /* Keep a reference to info that can survive info */ 00356 info->deferred_info = g_new0(DeferredInfo, 1); 00357 info->deferred_info->initial_info = info; 00358 info->deferred_info->wizard_path = g_strdup(wizard_path); 00359 info->deferred_info->qt_probably_unavailable = 00360 qt_probably_unavailable; 00361 00362 g_child_watch_add (pid, child_exit_cb, info->deferred_info); 00363 } 00364 } 00365 else 00366 { 00367 g_warning("on_aqhbci_button: Oops, no aqhbci setup wizard found."); 00368 gnc_error_dialog 00369 (info->window, 00370 _("The external program \"AqBanking Setup Wizard\" has not " 00371 "been found. \n\n" 00372 "The %s package should include the " 00373 "program \"qt3-wizard\". Please check your installation to " 00374 "ensure this program is present. On some distributions this " 00375 "may require installing additional packages."), 00376 QT3_WIZARD_PACKAGE); 00377 } 00378 00379 GWEN_Buffer_free(buf); 00380 #endif 00381 00382 /* Enable the Assistant Buttons if we accounts */ 00383 if (banking_has_accounts(info->api)) 00384 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, TRUE); 00385 else 00386 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, FALSE); 00387 00388 LEAVE(" "); 00389 } 00390 00391 void 00392 aai_match_page_prepare (GtkAssistant *assistant, gpointer user_data) 00393 { 00394 ABInitialInfo *info = user_data; 00395 gint num = gtk_assistant_get_current_page (assistant); 00396 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num); 00397 00398 Account *root; 00399 AccCbData data; 00400 00401 g_return_if_fail(info && info->api); 00402 00403 /* Do not run this twice */ 00404 if (!info->match_page_prepared) 00405 { 00406 /* Load aqbanking accounts */ 00407 #ifdef AQBANKING_VERSION_4_EXACTLY 00408 AB_Banking_OnlineInit(info->api, 0); 00409 #else 00410 AB_Banking_OnlineInit(info->api); 00411 #endif 00412 /* Determine current mapping */ 00413 root = gnc_book_get_root_account(gnc_get_current_book()); 00414 info->gnc_hash = g_hash_table_new(&g_direct_hash, &g_direct_equal); 00415 data.api = info->api; 00416 data.hash = info->gnc_hash; 00417 gnc_account_foreach_descendant( 00418 root, (AccountCb) hash_from_kvp_acc_cb, &data); 00419 00420 info->match_page_prepared = TRUE; 00421 } 00422 /* Update the graphical representation */ 00423 update_account_list(info); 00424 00425 /* Enable the Assistant Buttons */ 00426 gtk_assistant_set_page_complete (assistant, page, TRUE); 00427 } 00428 00429 void 00430 aai_on_finish (GtkAssistant *assistant, gpointer user_data) 00431 { 00432 ABInitialInfo *info = user_data; 00433 Account *root; 00434 00435 g_return_if_fail(info && info->gnc_hash); 00436 00437 /* Commit the changes */ 00438 root = gnc_book_get_root_account(gnc_get_current_book()); 00439 gnc_account_foreach_descendant(root, (AccountCb) clear_kvp_acc_cb, NULL); 00440 g_hash_table_foreach(info->gnc_hash, (GHFunc) save_kvp_acc_cb, NULL); 00441 00442 gtk_widget_destroy(info->window); 00443 } 00444 00445 static gboolean 00446 banking_has_accounts(AB_BANKING *banking) 00447 { 00448 AB_ACCOUNT_LIST2 *accl; 00449 gboolean result; 00450 00451 g_return_val_if_fail(banking, FALSE); 00452 00453 #ifdef AQBANKING_VERSION_4_EXACTLY 00454 AB_Banking_OnlineInit(banking, 0); 00455 #else 00456 AB_Banking_OnlineInit(banking); 00457 #endif 00458 00459 accl = AB_Banking_GetAccounts(banking); 00460 if (accl && (AB_Account_List2_GetSize(accl) > 0)) 00461 result = TRUE; 00462 else 00463 result = FALSE; 00464 00465 if (accl) 00466 AB_Account_List2_free(accl); 00467 00468 #ifdef AQBANKING_VERSION_4_EXACTLY 00469 AB_Banking_OnlineFini(banking, 0); 00470 #else 00471 AB_Banking_OnlineFini(banking); 00472 #endif 00473 00474 return result; 00475 } 00476 00477 static void 00478 hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data) 00479 { 00480 AccCbData *data = user_data; 00481 AB_ACCOUNT *ab_acc; 00482 00483 ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc); 00484 if (ab_acc) 00485 g_hash_table_insert(data->hash, ab_acc, gnc_acc); 00486 } 00487 00488 static void 00489 child_exit_cb(GPid pid, gint status, gpointer data) 00490 { 00491 DeferredInfo *deferred_info = data; 00492 ABInitialInfo *info = deferred_info->initial_info; 00493 gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(info->window)); 00494 GtkWidget *page = gtk_assistant_get_nth_page (GTK_ASSISTANT(info->window), num); 00495 00496 gint exit_status; 00497 00498 #ifdef G_OS_WIN32 00499 exit_status = status; 00500 #else 00501 exit_status = WEXITSTATUS(status); 00502 #endif 00503 00504 g_spawn_close_pid(pid); 00505 00506 if (!info) 00507 { 00508 g_message("Online Banking wizard exited, but the assistant has been " 00509 "destroyed already"); 00510 goto cleanup_child_exit_cb; 00511 } 00512 00513 if (exit_status == 0) 00514 { 00515 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, TRUE); 00516 } 00517 else 00518 { 00519 if (deferred_info->qt_probably_unavailable) 00520 { 00521 g_warning("on_aqhbci_button: Oops, aqhbci wizard return nonzero " 00522 "value: %d. The called program was \"%s\".\n", 00523 exit_status, deferred_info->wizard_path); 00524 gnc_error_dialog 00525 (info->window, "%s", 00526 _("The external program \"AqBanking Setup Wizard\" failed " 00527 "to run successfully because the " 00528 "additional software \"Qt\" was not found. " 00529 "Please install the \"Qt/Windows Open Source Edition\" " 00530 "from Trolltech by downloading it from www.trolltech.com" 00531 "\n\n" 00532 "If you have installed Qt already, you will have to adapt " 00533 "the PATH variable of your system appropriately. " 00534 "Contact the GnuCash developers if you need further " 00535 "assistance on how to install Qt correctly." 00536 "\n\n" 00537 "Online Banking cannot be setup without Qt. Press \"Close\" " 00538 "now, then \"Cancel\" to cancel the Online Banking setup.")); 00539 } 00540 else 00541 { 00542 g_warning("on_aqhbci_button: Oops, aqhbci wizard return nonzero " 00543 "value: %d. The called program was \"%s\".\n", 00544 exit_status, deferred_info->wizard_path); 00545 gnc_error_dialog 00546 (info->window, "%s", 00547 _("The external program \"AqBanking Setup Wizard\" failed " 00548 "to run successfully. Online Banking can only be setup " 00549 "if this wizard has run successfully. " 00550 "Please try running the \"AqBanking Setup Wizard\" again.")); 00551 } 00552 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, FALSE); 00553 } 00554 00555 cleanup_child_exit_cb: 00556 g_free(deferred_info->wizard_path); 00557 g_free(deferred_info); 00558 if (info) 00559 info->deferred_info = NULL; 00560 } 00561 00562 static gchar * 00563 ab_account_longname(const AB_ACCOUNT *ab_acc) 00564 { 00565 gchar *bankname; 00566 gchar *result; 00567 const char *ab_bankname, *bankcode; 00568 00569 g_return_val_if_fail(ab_acc, NULL); 00570 00571 ab_bankname = AB_Account_GetBankName(ab_acc); 00572 bankname = ab_bankname ? gnc_utf8_strip_invalid_strdup(ab_bankname) : NULL; 00573 bankcode = AB_Account_GetBankCode(ab_acc); 00574 00575 /* Translators: Strings are 1. Account code, 2. Bank name, 3. Bank code. */ 00576 if (bankname && *bankname) 00577 result = g_strdup_printf(_("%s at %s (code %s)"), 00578 AB_Account_GetAccountNumber(ab_acc), 00579 bankname, 00580 bankcode); 00581 else 00582 result = g_strdup_printf(_("%s at bank code %s"), 00583 AB_Account_GetAccountNumber(ab_acc), 00584 bankcode); 00585 g_free(bankname); 00586 00587 return result; 00588 00589 } 00590 00591 static AB_ACCOUNT * 00592 update_account_list_acc_cb(AB_ACCOUNT *ab_acc, gpointer user_data) 00593 { 00594 ABInitialInfo *info = user_data; 00595 gchar *gnc_name, *ab_name; 00596 Account *gnc_acc; 00597 GtkTreeIter iter; 00598 00599 g_return_val_if_fail(ab_acc && info, NULL); 00600 00601 ab_name = ab_account_longname(ab_acc); 00602 00603 /* Get corresponding gnucash account */ 00604 gnc_acc = g_hash_table_lookup(info->gnc_hash, ab_acc); 00605 00606 /* Build the text for the gnucash account. */ 00607 if (gnc_acc) 00608 gnc_name = gnc_account_get_full_name(gnc_acc); 00609 else 00610 gnc_name = g_strdup(""); 00611 00612 /* Add item to the list store */ 00613 gtk_list_store_append(info->account_store, &iter); 00614 gtk_list_store_set(info->account_store, &iter, 00615 ACCOUNT_LIST_COL_AB_NAME, ab_name, 00616 ACCOUNT_LIST_COL_AB_ACCT, ab_acc, 00617 ACCOUNT_LIST_COL_GNC_NAME, gnc_name, 00618 ACCOUNT_LIST_COL_CHECKED, FALSE, 00619 -1); 00620 g_free(gnc_name); 00621 g_free(ab_name); 00622 00623 return NULL; 00624 } 00625 00626 static void 00627 update_account_list(ABInitialInfo *info) 00628 { 00629 AB_ACCOUNT_LIST2 *acclist; 00630 00631 g_return_if_fail(info && info->api && info->gnc_hash); 00632 00633 /* Detach model from view while updating */ 00634 g_object_ref(info->account_store); 00635 gtk_tree_view_set_model(info->account_view, NULL); 00636 00637 /* Refill the list */ 00638 gtk_list_store_clear(info->account_store); 00639 acclist = AB_Banking_GetAccounts(info->api); 00640 if (acclist) 00641 AB_Account_List2_ForEach(acclist, update_account_list_acc_cb, info); 00642 else 00643 g_warning("update_account_list: Oops, account list from AB_Banking " 00644 "is NULL"); 00645 00646 /* Attach model to view again */ 00647 gtk_tree_view_set_model(info->account_view, 00648 GTK_TREE_MODEL(info->account_store)); 00649 00650 g_object_unref(info->account_store); 00651 } 00652 00653 static gboolean 00654 find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data) 00655 { 00656 RevLookupData *data = user_data; 00657 00658 g_return_val_if_fail(data, TRUE); 00659 00660 if (value == data->gnc_acc) 00661 { 00662 data->ab_acc = (AB_ACCOUNT*) key; 00663 return TRUE; 00664 } 00665 return FALSE; 00666 } 00667 00668 static gboolean 00669 clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, 00670 gpointer user_data) 00671 { 00672 RevLookupData *data = user_data; 00673 GtkListStore *store = GTK_LIST_STORE(model); 00674 gpointer ab_acc; 00675 00676 g_return_val_if_fail(data && store, FALSE); 00677 00678 gtk_tree_model_get(model, iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1); 00679 00680 if (ab_acc == data->ab_acc) 00681 { 00682 gtk_list_store_set(store, iter, ACCOUNT_LIST_COL_GNC_NAME, "", 00683 ACCOUNT_LIST_COL_CHECKED, TRUE, -1); 00684 return TRUE; 00685 } 00686 return FALSE; 00687 } 00688 00689 static void 00690 account_list_clicked_cb (GtkTreeView *view, GtkTreePath *path, 00691 GtkTreeViewColumn *col, gpointer user_data) 00692 { 00693 ABInitialInfo *info = user_data; 00694 GtkTreeSelection *selection; 00695 GtkTreeModel *model; 00696 GtkTreeIter iter; 00697 AB_ACCOUNT *ab_acc; 00698 gchar *longname, *gnc_name; 00699 Account *old_value, *gnc_acc; 00700 const gchar *currency; 00701 gnc_commodity *commodity = NULL; 00702 gboolean ok_pressed; 00703 00704 g_return_if_fail(info); 00705 00706 PINFO("Row has been double-clicked."); 00707 00708 model = gtk_tree_view_get_model(view); 00709 selection = gtk_tree_view_get_selection(info->account_view); 00710 00711 if (!gtk_tree_model_get_iter(model, &iter, path)) 00712 return; /* path describes a non-existing row - should not happen */ 00713 00714 gtk_tree_model_get(model, &iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1); 00715 00716 if (ab_acc) 00717 { 00718 old_value = g_hash_table_lookup(info->gnc_hash, ab_acc); 00719 00720 longname = ab_account_longname(ab_acc); 00721 currency = AB_Account_GetCurrency(ab_acc); 00722 if (currency && *currency) 00723 { 00724 commodity = gnc_commodity_table_lookup( 00725 gnc_commodity_table_get_table(gnc_get_current_book()), 00726 GNC_COMMODITY_NS_CURRENCY, 00727 currency); 00728 } 00729 00730 gnc_acc = gnc_import_select_account(info->window, NULL, TRUE, 00731 longname, commodity, ACCT_TYPE_BANK, 00732 old_value, &ok_pressed); 00733 g_free(longname); 00734 00735 if (ok_pressed && old_value != gnc_acc) 00736 { 00737 if (gnc_acc) 00738 { 00739 RevLookupData data; 00740 00741 /* Lookup and clear other mappings to gnc_acc */ 00742 data.gnc_acc = gnc_acc; 00743 data.ab_acc = NULL; 00744 g_hash_table_find(info->gnc_hash, (GHRFunc) find_gnc_acc_cb, 00745 &data); 00746 if (data.ab_acc) 00747 { 00748 g_hash_table_remove(info->gnc_hash, data.ab_acc); 00749 gtk_tree_model_foreach( 00750 GTK_TREE_MODEL(info->account_store), 00751 (GtkTreeModelForeachFunc) clear_line_cb, 00752 &data); 00753 } 00754 00755 /* Map ab_acc to gnc_acc */ 00756 g_hash_table_insert(info->gnc_hash, ab_acc, gnc_acc); 00757 gnc_name = gnc_account_get_full_name(gnc_acc); 00758 gtk_list_store_set(info->account_store, &iter, 00759 ACCOUNT_LIST_COL_GNC_NAME, gnc_name, 00760 ACCOUNT_LIST_COL_CHECKED, TRUE, 00761 -1); 00762 g_free(gnc_name); 00763 00764 } 00765 else 00766 { 00767 g_hash_table_remove(info->gnc_hash, ab_acc); 00768 gtk_list_store_set(info->account_store, &iter, 00769 ACCOUNT_LIST_COL_GNC_NAME, "", 00770 ACCOUNT_LIST_COL_CHECKED, TRUE, 00771 -1); 00772 } 00773 } 00774 } 00775 } 00776 00777 static void 00778 clear_kvp_acc_cb(Account *gnc_acc, gpointer user_data) 00779 { 00780 if (gnc_ab_get_account_uid(gnc_acc)) 00781 gnc_ab_set_account_uid(gnc_acc, 0); 00782 if (gnc_ab_get_account_accountid(gnc_acc)) 00783 gnc_ab_set_account_accountid(gnc_acc, ""); 00784 if (gnc_ab_get_account_bankcode(gnc_acc)) 00785 gnc_ab_set_account_bankcode(gnc_acc, ""); 00786 } 00787 00788 static void 00789 save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data) 00790 { 00791 AB_ACCOUNT *ab_acc = key; 00792 Account *gnc_acc = value; 00793 guint32 ab_account_uid; 00794 const gchar *ab_accountid, *gnc_accountid; 00795 const gchar *ab_bankcode, *gnc_bankcode; 00796 00797 g_return_if_fail(ab_acc && gnc_acc); 00798 00799 ab_account_uid = AB_Account_GetUniqueId(ab_acc); 00800 if (gnc_ab_get_account_uid(gnc_acc) != ab_account_uid) 00801 gnc_ab_set_account_uid(gnc_acc, ab_account_uid); 00802 00803 ab_accountid = AB_Account_GetAccountNumber(ab_acc); 00804 gnc_accountid = gnc_ab_get_account_accountid(gnc_acc); 00805 if (ab_accountid 00806 && (!gnc_accountid 00807 || (strcmp(ab_accountid, gnc_accountid) != 0))) 00808 gnc_ab_set_account_accountid(gnc_acc, ab_accountid); 00809 00810 ab_bankcode = AB_Account_GetBankCode(ab_acc); 00811 gnc_bankcode = gnc_ab_get_account_bankcode(gnc_acc); 00812 if (ab_bankcode 00813 && (!gnc_bankcode 00814 || (strcmp(gnc_bankcode, ab_bankcode) != 0))) 00815 gnc_ab_set_account_bankcode(gnc_acc, ab_bankcode); 00816 } 00817 00818 static void 00819 aai_close_handler(gpointer user_data) 00820 { 00821 ABInitialInfo *info = user_data; 00822 00823 gtk_widget_destroy(info->window); 00824 } 00825 00826 void aai_on_prepare (GtkAssistant *assistant, GtkWidget *page, 00827 gpointer user_data) 00828 { 00829 ABInitialInfo *info = user_data; 00830 gint currentpage = gtk_assistant_get_current_page(assistant); 00831 00832 switch (gtk_assistant_get_current_page(assistant)) 00833 { 00834 case 1: 00835 /* Current page is wizard button page */ 00836 aai_wizard_page_prepare (assistant , user_data ); 00837 break; 00838 case 2: 00839 /* Current page is match page */ 00840 aai_match_page_prepare (assistant , user_data ); 00841 break; 00842 } 00843 } 00844 00845 void 00846 gnc_ab_initial_assistant(void) 00847 { 00848 ABInitialInfo *info; 00849 GtkBuilder *builder; 00850 GtkTreeViewColumn *column; 00851 GtkTreeSelection *selection; 00852 gint component_id; 00853 00854 info = g_new0(ABInitialInfo, 1); 00855 builder = gtk_builder_new(); 00856 gnc_builder_add_from_file (builder, "assistant-ab-initial.glade", "AqBanking Init Assistant"); 00857 00858 info->window = GTK_WIDGET(gtk_builder_get_object (builder, "AqBanking Init Assistant")); 00859 00860 gnc_assistant_set_colors (GTK_ASSISTANT (info->assistant)); 00861 00862 info->api = gnc_AB_BANKING_new(); 00863 info->deferred_info = NULL; 00864 info->gnc_hash = NULL; 00865 00866 info->match_page_prepared = FALSE; 00867 info->account_view = 00868 GTK_TREE_VIEW(gtk_builder_get_object (builder, "account_page_view")); 00869 00870 info->account_store = gtk_list_store_new(NUM_ACCOUNT_LIST_COLS, 00871 G_TYPE_INT, G_TYPE_STRING, 00872 G_TYPE_POINTER, G_TYPE_STRING, 00873 G_TYPE_BOOLEAN); 00874 gtk_tree_view_set_model(info->account_view, 00875 GTK_TREE_MODEL(info->account_store)); 00876 g_object_unref(info->account_store); 00877 00878 column = gtk_tree_view_column_new_with_attributes( 00879 _("Online Banking Account Name"), gtk_cell_renderer_text_new(), 00880 "text", ACCOUNT_LIST_COL_AB_NAME, (gchar*) NULL); 00881 gtk_tree_view_append_column(info->account_view, column); 00882 00883 column = gtk_tree_view_column_new_with_attributes( 00884 _("GnuCash Account Name"), gtk_cell_renderer_text_new(), 00885 "text", ACCOUNT_LIST_COL_GNC_NAME, (gchar*) NULL); 00886 gtk_tree_view_column_set_expand(column, TRUE); 00887 gtk_tree_view_append_column(info->account_view, column); 00888 00889 column = gtk_tree_view_column_new_with_attributes( 00890 _("New?"), gtk_cell_renderer_toggle_new(), 00891 "active", ACCOUNT_LIST_COL_CHECKED, (gchar*) NULL); 00892 gtk_tree_view_append_column(info->account_view, column); 00893 00894 selection = gtk_tree_view_get_selection(info->account_view); 00895 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); 00896 00897 g_signal_connect(info->account_view, "row-activated", 00898 G_CALLBACK(account_list_clicked_cb), info); 00899 00900 g_signal_connect (G_OBJECT(info->window), "destroy", 00901 G_CALLBACK (aai_destroy_cb), info); 00902 00903 gtk_builder_connect_signals(builder, info); 00904 g_object_unref(G_OBJECT(builder)); 00905 00906 component_id = gnc_register_gui_component(ASSISTANT_AB_INITIAL_CM_CLASS, 00907 NULL, aai_close_handler, info); 00908 00909 gnc_gui_component_set_session(component_id, gnc_get_current_session()); 00910 00911 gtk_widget_show(info->window); 00912 }
1.7.4