GnuCash c935c2f+
Loading...
Searching...
No Matches
assistant-ab-initial.c
1/*
2 * assistant-ab-initial.c -- Initialise the AqBanking wizard
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, contact:
16 *
17 * Free Software Foundation Voice: +1-617-542-5942
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
19 * Boston, MA 02110-1301, USA gnu@gnu.org
20 */
21
33#include <config.h>
34
35#include <platform.h>
36#if PLATFORM(WINDOWS)
37#include <windows.h>
38#endif
39
40#include "gnc-ab-utils.h" /* For version macros */
41
42#include <aqbanking/banking.h>
43#include <aqbanking/types/account_spec.h>
44#include <gwenhywfar/gui.h>
45#include <glib.h>
46#include <glib/gi18n.h>
47#include <glib/gstdio.h>
48#include <gdk/gdkkeysyms.h>
49#ifdef HAVE_SYS_WAIT_H
50# include <sys/wait.h>
51#endif
52#include <fcntl.h>
53#include <unistd.h>
54#include <stdint.h>
55
56#include "dialog-utils.h"
58#include "gnc-ab-kvp.h"
59#include "gnc-ab-utils.h"
60#include "gnc-component-manager.h"
61#include "gnc-glib-utils.h"
62#include "gnc-ui.h"
63#include "gnc-ui-util.h"
64#include "gnc-session.h"
66/* This static indicates the debugging module that this .o belongs to. */
67static QofLogModule log_module = GNC_MOD_ASSISTANT;
68
69#define GNC_PREFS_GROUP "dialogs.ab-initial"
70#define ASSISTANT_AB_INITIAL_CM_CLASS "assistant-ab-initial"
71
72typedef struct _ABInitialInfo ABInitialInfo;
73typedef struct _DeferredInfo DeferredInfo;
74typedef struct _AccCbData AccCbData;
75typedef struct _RevLookupData RevLookupData;
76
77void aai_on_prepare (GtkAssistant *assistant, GtkWidget *page,
78 gpointer user_data);
79
80void aai_on_finish (GtkAssistant *gtkassistant, gpointer user_data);
81void aai_on_cancel (GtkAssistant *assistant, gpointer user_data);
82void aai_destroy_cb(GtkWidget *object, gpointer user_data);
83
84gboolean aai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
85
86void aai_page_prepare (GtkAssistant *assistant, gpointer user_data);
87void aai_button_clicked_cb(GtkButton *button, gpointer user_data);
88void aai_match_delete_button_clicked_cb(GtkButton *button, gpointer user_data);
89
90static guint aai_ab_account_hash(gconstpointer v);
91static gboolean aai_ab_account_equal(gconstpointer v1, gconstpointer v2);
92void aai_match_page_prepare (GtkAssistant *assistant, gpointer user_data);
93
94static gboolean banking_has_accounts(AB_BANKING *banking);
95static void hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data);
96static ABInitialInfo *single_info = NULL;
97static gchar *ab_account_longname(const GNC_AB_ACCOUNT_SPEC *ab_acc);
98static GNC_AB_ACCOUNT_SPEC *update_account_list_acc_cb(GNC_AB_ACCOUNT_SPEC *ab_acc, gpointer user_data);
99static void update_account_list(ABInitialInfo *info);
100static gboolean find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data);
101static gboolean clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data);
102static void account_list_clicked_cb (GtkTreeView *view, GtkTreePath *path,
103 GtkTreeViewColumn *col, gpointer user_data);
104static void delete_account_match(ABInitialInfo *info, RevLookupData *data);
105static void delete_selected_match_cb(gpointer data, gpointer user_data);
106static void insert_acc_into_revhash_cb(gpointer ab_acc, gpointer gnc_acc, gpointer revhash);
107static void remove_acc_from_revhash_cb(gpointer ab_acc, gpointer gnc_acc, gpointer revhash);
108static void clear_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data);
109static void save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data);
110static void aai_close_handler(gpointer user_data);
111
113{
114 GtkWidget *window;
115 GtkWidget *assistant;
116
117 /* account match page */
118 gboolean match_page_prepared;
119 GtkTreeView *account_view;
120 GtkListStore *account_store;
121
122 /* managed by child_exit_cb */
123 DeferredInfo *deferred_info;
124
125 /* AqBanking stuff */
126 AB_BANKING *api;
127 /* AB_ACCOUNT* -> Account* -- DO NOT DELETE THE KEYS! */
128 GHashTable *gnc_hash;
129 /* Reverse hash table for lookup of matched GnuCash accounts */
130 GHashTable *gnc_revhash;
131};
132
134{
135 ABInitialInfo *initial_info;
136 gchar *wizard_path;
137 gboolean qt_probably_unavailable;
138};
139
141{
142 AB_BANKING *api;
143 GHashTable *hash;
144};
145
147{
148 Account *gnc_acc;
149 GNC_AB_ACCOUNT_SPEC *ab_acc;
150};
151
152enum account_list_cols
153{
154 ACCOUNT_LIST_COL_INDEX = 0,
155 ACCOUNT_LIST_COL_AB_NAME,
156 ACCOUNT_LIST_COL_AB_ACCT,
157 ACCOUNT_LIST_COL_GNC_NAME,
158 ACCOUNT_LIST_COL_CHECKED,
159 NUM_ACCOUNT_LIST_COLS
160};
161
162gboolean
163aai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
164{
165 if (event->keyval == GDK_KEY_Escape)
166 {
167 gtk_widget_destroy(widget);
168 return TRUE;
169 }
170 else
171 {
172 return FALSE;
173 }
174}
175
176void
177aai_on_cancel (GtkAssistant *gtkassistant, gpointer user_data)
178{
179 ABInitialInfo *info = user_data;
180
181 gtk_widget_destroy(info->window);
182}
183
184void
185aai_destroy_cb(GtkWidget *object, gpointer user_data)
186{
187 ABInitialInfo *info = user_data;
188 g_return_if_fail (single_info && info == single_info);
189
190 gnc_unregister_gui_component_by_data(ASSISTANT_AB_INITIAL_CM_CLASS, info);
191
192 if (info->deferred_info)
193 {
194 PINFO("Online Banking assistant is being closed but the wizard is still "
195 "running. Inoring.");
196
197 /* Tell child_exit_cb() that there is no assistant anymore */
198 info->deferred_info->initial_info = NULL;
199 }
200
201 if (info->gnc_hash)
202 {
203 g_hash_table_destroy(info->gnc_hash);
204 info->gnc_hash = NULL;
205 }
206
207 if (info->gnc_revhash)
208 {
209 g_hash_table_destroy(info->gnc_revhash);
210 info->gnc_revhash = NULL;
211 }
212
213 if (info->api)
214 {
215 gnc_AB_BANKING_delete(info->api);
216 info->api = NULL;
217 }
218
219 gtk_widget_destroy(info->window);
220 info->window = NULL;
221
222 g_free(info);
223 single_info = NULL;
224}
225
226void
227aai_page_prepare (GtkAssistant *assistant, gpointer user_data)
228{
229 ABInitialInfo *info = user_data;
230 gint num = gtk_assistant_get_current_page (assistant);
231 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
232
233 g_return_if_fail(info->api);
234
235 /* Enable the Assistant Buttons if we accounts */
236 if (banking_has_accounts(info->api))
237 gtk_assistant_set_page_complete (assistant, page, TRUE);
238 else
239 gtk_assistant_set_page_complete (assistant, page, FALSE);
240}
241
242void
243aai_button_clicked_cb(GtkButton *button, gpointer user_data)
244{
245 ABInitialInfo *info = user_data;
246 gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(info->window));
247 GtkWidget *page = gtk_assistant_get_nth_page (GTK_ASSISTANT(info->window), num);
248
249 AB_BANKING *banking = info->api;
250 g_return_if_fail(banking);
251
252 ENTER("user_data: %p", user_data);
253
254 if (info->deferred_info)
255 {
256 LEAVE("Wizard is still running");
257 return;
258 }
259
260 {
261 GWEN_DIALOG *dlg = AB_Banking_CreateSetupDialog(banking);
262 if (!dlg)
263 {
264 PERR("Could not lookup Setup Dialog of aqbanking!");
265 }
266 else
267 {
268 int rv = GWEN_Gui_ExecDialog(dlg, 0);
269 if (rv <= 0)
270 {
271 /* Dialog was aborted/rejected */
272 PERR("Setup Dialog of aqbanking aborted/rejected, code %d", rv);
273 }
274 GWEN_Dialog_free(dlg);
275 }
276 }
277
278 /* Enable the Assistant Buttons if we accounts */
279 if (banking_has_accounts(info->api))
280 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, TRUE);
281 else
282 gtk_assistant_set_page_complete (GTK_ASSISTANT(info->window), page, FALSE);
283
284 LEAVE(" ");
285}
286
287static void delete_account_match(ABInitialInfo *info, RevLookupData *data)
288{
289 g_return_if_fail(info && info->gnc_hash &&
290 info->account_view && data && data->ab_acc);
291
292 g_hash_table_remove(info->gnc_hash, data->ab_acc);
293 gtk_tree_model_foreach(
294 GTK_TREE_MODEL(info->account_store),
295 (GtkTreeModelForeachFunc) clear_line_cb,
296 data);
297}
298
299static void
300delete_selected_match_cb(gpointer data, gpointer user_data)
301{
302 GtkTreeIter iter;
303 GtkTreeModel *model = NULL;
304 RevLookupData revLookupData = {NULL, NULL};
305
306 GtkTreePath *path = (GtkTreePath *) data;
307 ABInitialInfo *info = (ABInitialInfo *) user_data;
308 g_return_if_fail(path && info && info->account_view);
309
310 model = gtk_tree_view_get_model(info->account_view);
311 g_return_if_fail(model);
312
313 if (gtk_tree_model_get_iter(model, &iter, path))
314 {
315 gtk_tree_model_get(model, &iter, ACCOUNT_LIST_COL_AB_ACCT, &revLookupData.ab_acc, -1);
316 if (revLookupData.ab_acc)
317 delete_account_match(info, &revLookupData);
318 }
319}
320
321void
322aai_match_delete_button_clicked_cb(GtkButton *button, gpointer user_data)
323{
324 GList *selected_matches = NULL;
325 GtkTreeSelection *selection = NULL;
326 ABInitialInfo *info = (ABInitialInfo *) user_data;
327
328 g_return_if_fail(info && info->api && info->account_view && info->gnc_hash);
329
330 PINFO("Selected account matches are deleted");
331
332 selection = gtk_tree_view_get_selection (info->account_view);
333 if (selection)
334 {
335 selected_matches = gtk_tree_selection_get_selected_rows (selection, NULL);
336 if (selected_matches)
337 {
338 g_list_foreach (selected_matches, delete_selected_match_cb, info);
339 g_list_free_full (
340 selected_matches,
341 (GDestroyNotify) gtk_tree_path_free);
342 }
343 }
344}
345
346static guint
347aai_ab_account_hash (gconstpointer v)
348{
349 if (v == NULL)
350 return 0;
351 else
352 /* Use the account unique id as hash value */
353 return AB_AccountSpec_GetUniqueId((const GNC_AB_ACCOUNT_SPEC *) v);
354}
355
356static gboolean
357aai_ab_account_equal (gconstpointer v1, gconstpointer v2)
358{
359 if (v1 == NULL || v2 == NULL)
360 return v1 == v2;
361 else
362 {
363 /* Use the account unique id to check for equality */
364 uint32_t uid1 = AB_AccountSpec_GetUniqueId((const GNC_AB_ACCOUNT_SPEC *) v1);
365 uint32_t uid2 = AB_AccountSpec_GetUniqueId((const GNC_AB_ACCOUNT_SPEC *) v2);
366 return uid1 == uid2;
367 }
368}
369
370static void
371insert_acc_into_revhash_cb(gpointer ab_acc, gpointer gnc_acc, gpointer revhash)
372{
373 g_return_if_fail(revhash && gnc_acc && ab_acc);
374 g_hash_table_insert((GHashTable *) revhash, gnc_acc, ab_acc);
375}
376
377static void
378remove_acc_from_revhash_cb(gpointer ab_acc, gpointer gnc_acc, gpointer revhash)
379{
380 g_return_if_fail(revhash && gnc_acc);
381 g_hash_table_remove((GHashTable *) revhash, gnc_acc);
382}
383
384void
385aai_match_page_prepare (GtkAssistant *assistant, gpointer user_data)
386{
387 ABInitialInfo *info = user_data;
388 gint num = gtk_assistant_get_current_page (assistant);
389 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
390
391 Account *root;
392 AccCbData data;
393
394 g_return_if_fail(info && info->api);
395
396 /* Do not run this twice */
397 if (!info->match_page_prepared)
398 {
399 /* Determine current mapping */
400 root = gnc_book_get_root_account(gnc_get_current_book());
401 info->gnc_hash = g_hash_table_new(&aai_ab_account_hash, &aai_ab_account_equal);
402 data.api = info->api;
403 data.hash = info->gnc_hash;
404 gnc_account_foreach_descendant(root, (AccountCb) hash_from_kvp_acc_cb, &data);
405 /* Memorize initial matches in reverse hash table */
406 info->gnc_revhash = g_hash_table_new(NULL, NULL);
407 g_hash_table_foreach(data.hash, (GHFunc) insert_acc_into_revhash_cb, (gpointer) info->gnc_revhash);
408
409 info->match_page_prepared = TRUE;
410 }
411 /* Update the graphical representation */
412 update_account_list(info);
413
414 /* Enable the Assistant Buttons */
415 gtk_assistant_set_page_complete (assistant, page, TRUE);
416}
417
418void
419aai_on_finish (GtkAssistant *assistant, gpointer user_data)
420{
421 ABInitialInfo *info = user_data;
422
423 g_return_if_fail(info && info->gnc_hash && info->gnc_revhash);
424
425 /* Remove GnuCash accounts from reverse hash table which are still
426 * matched to an AqBanking account. For the remaining GnuCash accounts
427 * the KVPs must be cleared (i.e. deleted).
428 * Please note that the value (i.e. the GnuCash account) stored in info->gnc_hash
429 * is used as key for info->gnc_revhash */
430 g_hash_table_foreach(info->gnc_hash, (GHFunc) remove_acc_from_revhash_cb, info->gnc_revhash);
431 /* Commit the changes */
432 g_hash_table_foreach(info->gnc_revhash, (GHFunc) clear_kvp_acc_cb, NULL);
433 g_hash_table_foreach(info->gnc_hash, (GHFunc) save_kvp_acc_cb, NULL);
434
435 gtk_widget_destroy(info->window);
436}
437
438static gboolean
439banking_has_accounts(AB_BANKING *banking)
440{
441 GNC_AB_ACCOUNT_SPEC_LIST *accl = NULL;
442 gboolean result = FALSE;
443
444 g_return_val_if_fail(banking, FALSE);
445
446 if (AB_Banking_GetAccountSpecList (banking, &accl) >= 0 &&
447 accl && AB_AccountSpec_List_GetCount (accl))
448 result = TRUE;
449 if (accl)
450 AB_AccountSpec_List_free (accl);
451
452 return result;
453}
454
455static void
456hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data)
457{
458 AccCbData *data = user_data;
459 GNC_AB_ACCOUNT_SPEC *ab_acc;
460
461 ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc);
462 if (ab_acc)
463 g_hash_table_insert(data->hash, ab_acc, gnc_acc);
464}
465
466static gchar *
467ab_account_longname(const GNC_AB_ACCOUNT_SPEC *ab_acc)
468{
469 gchar *bankname = NULL;
470 gchar *result = NULL;
471 const char *bankcode, *subAccountId, *account_number;
472
473 g_return_val_if_fail(ab_acc, NULL);
474
475 bankcode = AB_AccountSpec_GetBankCode(ab_acc);
476 subAccountId = AB_AccountSpec_GetSubAccountNumber(ab_acc);
477 account_number = AB_AccountSpec_GetAccountNumber (ab_acc);
478 /* Translators: Strings are 1. Bank code, 2. Bank name,
479 3. Account Number, 4. Subaccount ID */
480 result = g_strdup_printf(_("Bank code %s (%s), Account %s (%s)"),
481 bankcode,
482 bankname ? bankname : "",
483 account_number,
484 subAccountId ? subAccountId : "");
485 g_free(bankname);
486
487 return result;
488
489}
490
491static GNC_AB_ACCOUNT_SPEC *
492update_account_list_acc_cb(GNC_AB_ACCOUNT_SPEC *ab_acc, gpointer user_data)
493{
494 ABInitialInfo *info = user_data;
495 gchar *gnc_name, *ab_name;
496 Account *gnc_acc;
497 GtkTreeIter iter;
498
499 g_return_val_if_fail(ab_acc && info, NULL);
500
501 ab_name = ab_account_longname(ab_acc);
502
503 /* Get corresponding gnucash account */
504 gnc_acc = g_hash_table_lookup(info->gnc_hash, ab_acc);
505
506 /* Build the text for the gnucash account. */
507 if (gnc_acc)
508 gnc_name = gnc_account_get_full_name(gnc_acc);
509 else
510 gnc_name = g_strdup("");
511
512 /* Add item to the list store */
513 gtk_list_store_append(info->account_store, &iter);
514 gtk_list_store_set(info->account_store, &iter,
515 ACCOUNT_LIST_COL_AB_NAME, ab_name,
516 ACCOUNT_LIST_COL_AB_ACCT, ab_acc,
517 ACCOUNT_LIST_COL_GNC_NAME, gnc_name,
518 ACCOUNT_LIST_COL_CHECKED, FALSE,
519 -1);
520 g_free(gnc_name);
521 g_free(ab_name);
522
523 return NULL;
524}
525
526static void
527update_account_list(ABInitialInfo *info)
528{
529 GNC_AB_ACCOUNT_SPEC_LIST *acclist = NULL;
530
531 g_return_if_fail(info && info->api && info->gnc_hash);
532
533 /* Detach model from view while updating */
534 g_object_ref(info->account_store);
535 gtk_tree_view_set_model(info->account_view, NULL);
536
537 /* Refill the list */
538 gtk_list_store_clear(info->account_store);
539 if (AB_Banking_GetAccountSpecList(info->api, &acclist) >= 0 && acclist)
540 AB_AccountSpec_List_ForEach(acclist, update_account_list_acc_cb, info);
541 else
542 g_warning("update_account_list: Oops, account list from AB_Banking "
543 "is NULL");
544
545 /* Attach model to view again */
546 gtk_tree_view_set_model(info->account_view,
547 GTK_TREE_MODEL(info->account_store));
548
549 g_object_unref(info->account_store);
550}
551
552static gboolean
553find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data)
554{
555 RevLookupData *data = user_data;
556
557 g_return_val_if_fail(data, TRUE);
558
559 if (value == data->gnc_acc)
560 {
561 data->ab_acc = (GNC_AB_ACCOUNT_SPEC*) key;
562 return TRUE;
563 }
564 return FALSE;
565}
566
567static gboolean
568clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
569 gpointer user_data)
570{
571 RevLookupData *data = user_data;
572 GtkListStore *store = GTK_LIST_STORE(model);
573 gpointer ab_acc;
574
575 g_return_val_if_fail(data && store, FALSE);
576
577 gtk_tree_model_get(model, iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1);
578
579 if (aai_ab_account_equal(ab_acc, data->ab_acc))
580 {
581 gtk_list_store_set(store, iter, ACCOUNT_LIST_COL_GNC_NAME, "",
582 ACCOUNT_LIST_COL_CHECKED, TRUE, -1);
583 return TRUE;
584 }
585 return FALSE;
586}
587
588static void
589account_list_clicked_cb (GtkTreeView *view, GtkTreePath *path,
590 GtkTreeViewColumn *col, gpointer user_data)
591{
592 ABInitialInfo *info = user_data;
593 GtkTreeModel *model;
594 GtkTreeIter iter;
595 GNC_AB_ACCOUNT_SPEC *ab_acc;
596 gchar *longname, *gnc_name;
597 Account *old_value, *gnc_acc;
598 const gchar *currency;
599 gnc_commodity *commodity = NULL;
600 gboolean ok_pressed;
601
602 g_return_if_fail(info);
603
604 PINFO("Row has been double-clicked.");
605
606 model = gtk_tree_view_get_model(view);
607
608 if (!gtk_tree_model_get_iter(model, &iter, path))
609 return; /* path describes a non-existing row - should not happen */
610
611 gtk_tree_model_get(model, &iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1);
612
613 if (ab_acc)
614 {
615 old_value = g_hash_table_lookup(info->gnc_hash, ab_acc);
616
617 longname = ab_account_longname(ab_acc);
618 currency = AB_AccountSpec_GetCurrency(ab_acc);
619 if (currency && *currency)
620 {
621 commodity = gnc_commodity_table_lookup(
622 gnc_commodity_table_get_table(gnc_get_current_book()),
623 GNC_COMMODITY_NS_CURRENCY,
624 currency);
625 }
626
627 gnc_acc = gnc_import_select_account(info->window, NULL, TRUE,
628 longname, commodity, ACCT_TYPE_BANK,
629 old_value, &ok_pressed);
630 g_free(longname);
631
632 if (ok_pressed && old_value != gnc_acc)
633 {
634 if (gnc_acc)
635 {
636 RevLookupData data;
637
638 /* Lookup and clear other mappings to gnc_acc */
639 data.gnc_acc = gnc_acc;
640 data.ab_acc = NULL;
641 g_hash_table_find(info->gnc_hash, (GHRFunc) find_gnc_acc_cb,
642 &data);
643 if (data.ab_acc)
644 delete_account_match(info, &data);
645
646 /* Map ab_acc to gnc_acc */
647 g_hash_table_insert(info->gnc_hash, ab_acc, gnc_acc);
648 gnc_name = gnc_account_get_full_name(gnc_acc);
649 gtk_list_store_set(info->account_store, &iter,
650 ACCOUNT_LIST_COL_GNC_NAME, gnc_name,
651 ACCOUNT_LIST_COL_CHECKED, TRUE,
652 -1);
653 g_free(gnc_name);
654
655 }
656 else
657 {
658 g_hash_table_remove(info->gnc_hash, ab_acc);
659 gtk_list_store_set(info->account_store, &iter,
660 ACCOUNT_LIST_COL_GNC_NAME, "",
661 ACCOUNT_LIST_COL_CHECKED, TRUE,
662 -1);
663 }
664 }
665 }
666}
667
668static void
669clear_kvp_acc_cb(gpointer gnc_acc, gpointer ab_acc, gpointer user_data)
670{
671 g_return_if_fail(gnc_acc);
672 /* Delete "online-id" and complete "hbci..." KVPs for GnuCash account */
673 gnc_account_delete_map_entry((Account *) gnc_acc, "online_id", NULL, NULL, FALSE);
674 gnc_account_delete_map_entry((Account *) gnc_acc, "hbci", NULL, NULL, FALSE);
675}
676
677static void
678save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data)
679{
680 GNC_AB_ACCOUNT_SPEC *ab_acc = key;
681 Account *gnc_acc = value;
682 guint32 ab_account_uid;
683 const gchar *ab_accountid, *gnc_accountid;
684 const gchar *ab_bankcode, *gnc_bankcode;
685 gchar *ab_online_id;
686 const gchar *gnc_online_id;
687
688 g_return_if_fail(ab_acc && gnc_acc);
689
690 ab_account_uid = AB_AccountSpec_GetUniqueId(ab_acc);
691 if (gnc_ab_get_account_uid(gnc_acc) != ab_account_uid)
692 gnc_ab_set_account_uid(gnc_acc, ab_account_uid);
693
694 ab_accountid = AB_AccountSpec_GetAccountNumber(ab_acc);
695 gnc_accountid = gnc_ab_get_account_accountid(gnc_acc);
696 if (ab_accountid
697 && (!gnc_accountid
698 || (strcmp(ab_accountid, gnc_accountid) != 0)))
699 gnc_ab_set_account_accountid(gnc_acc, ab_accountid);
700
701 ab_bankcode = AB_AccountSpec_GetBankCode(ab_acc);
702 gnc_bankcode = gnc_ab_get_account_bankcode(gnc_acc);
703 if (ab_bankcode
704 && (!gnc_bankcode
705 || (strcmp(gnc_bankcode, ab_bankcode) != 0)))
706 gnc_ab_set_account_bankcode(gnc_acc, ab_bankcode);
707
708 ab_online_id = gnc_ab_create_online_id(ab_bankcode, ab_accountid);
709 gnc_online_id = xaccAccountGetOnlineID(gnc_acc);
710 if (ab_online_id && (!gnc_online_id || (strcmp(ab_online_id, gnc_online_id) != 0)))
711 xaccAccountSetOnlineID(gnc_acc, ab_online_id);
712 g_free(ab_online_id);
713}
714
715static void
716aai_close_handler(gpointer user_data)
717{
718 ABInitialInfo *info = user_data;
719
720 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(info->window));
721 gtk_widget_destroy(info->window);
722}
723
724void aai_on_prepare (GtkAssistant *assistant, GtkWidget *page,
725 gpointer user_data)
726{
727 switch (gtk_assistant_get_current_page(assistant))
728 {
729 case 1:
730 /* Current page is wizard button page */
731 aai_page_prepare (assistant , user_data );
732 break;
733 case 2:
734 /* Current page is match page */
735 aai_match_page_prepare (assistant , user_data );
736 break;
737 }
738}
739
740static ABInitialInfo *
741gnc_ab_initial_assistant_new(void)
742{
743 GtkBuilder *builder;
744 GtkTreeViewColumn *column;
745 GtkTreeSelection *selection;
746 gint component_id;
747
748 ABInitialInfo *info = g_new0(ABInitialInfo, 1);
749 builder = gtk_builder_new();
750 gnc_builder_add_from_file (builder, "assistant-ab-initial.glade", "aqbanking_init_assistant");
751
752 info->window = GTK_WIDGET(gtk_builder_get_object (builder, "aqbanking_init_assistant"));
753
754 info->api = gnc_AB_BANKING_new();
755 info->deferred_info = NULL;
756 info->gnc_hash = NULL;
757
758 info->match_page_prepared = FALSE;
759 info->account_view =
760 GTK_TREE_VIEW(gtk_builder_get_object (builder, "account_page_view"));
761
762 info->account_store = gtk_list_store_new(NUM_ACCOUNT_LIST_COLS,
763 G_TYPE_INT, G_TYPE_STRING,
764 G_TYPE_POINTER, G_TYPE_STRING,
765 G_TYPE_BOOLEAN);
766 gtk_tree_view_set_model(info->account_view,
767 GTK_TREE_MODEL(info->account_store));
768 g_object_unref(info->account_store);
769
770 column = gtk_tree_view_column_new_with_attributes(
771 _("Online Banking Account Name"), gtk_cell_renderer_text_new(),
772 "text", ACCOUNT_LIST_COL_AB_NAME, (gchar*) NULL);
773 gtk_tree_view_append_column(info->account_view, column);
774
775 column = gtk_tree_view_column_new_with_attributes(
776 _("GnuCash Account Name"), gtk_cell_renderer_text_new(),
777 "text", ACCOUNT_LIST_COL_GNC_NAME, (gchar*) NULL);
778 gtk_tree_view_column_set_expand(column, TRUE);
779 gtk_tree_view_append_column(info->account_view, column);
780
781 column = gtk_tree_view_column_new_with_attributes(
782 _("New?"), gtk_cell_renderer_toggle_new(),
783 "active", ACCOUNT_LIST_COL_CHECKED, (gchar*) NULL);
784 gtk_tree_view_append_column(info->account_view, column);
785
786 selection = gtk_tree_view_get_selection(info->account_view);
787 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
788
789 gnc_restore_window_size (GNC_PREFS_GROUP,
790 GTK_WINDOW(info->window), gnc_ui_get_main_window(NULL));
791
792 g_signal_connect(info->account_view, "row-activated",
793 G_CALLBACK(account_list_clicked_cb), info);
794
795 g_signal_connect (G_OBJECT(info->window), "destroy",
796 G_CALLBACK (aai_destroy_cb), info);
797
798 gtk_builder_connect_signals(builder, info);
799 g_object_unref(G_OBJECT(builder));
800
801 component_id = gnc_register_gui_component(ASSISTANT_AB_INITIAL_CM_CLASS,
802 NULL, aai_close_handler, info);
803
804 gnc_gui_component_set_session(component_id, gnc_get_current_session());
805 return info;
806}
807
808void
810{
811 if (!single_info)
812 single_info = gnc_ab_initial_assistant_new();
813 gtk_widget_show(single_info->window);
814}
815
AqBanking setup functionality.
AqBanking KVP handling.
AqBanking utility functions.
GLib helper routines.
utility functions for the GnuCash UI
void xaccAccountSetOnlineID(Account *acc, const char *id)
Set the account's online_id, the identifier (e.g.
Definition Account.cpp:2661
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition Account.cpp:3305
const char * xaccAccountGetOnlineID(const Account *acc)
Get the account's online_id (see xaccAccountSetOnlineID).
Definition Account.cpp:3380
const gchar * gnc_ab_get_account_bankcode(const Account *a)
Return the bankcode string in the Account a.
Definition gnc-ab-kvp.c:59
GNC_AB_ACCOUNT_SPEC * gnc_ab_get_ab_account(const AB_BANKING *api, Account *gnc_acc)
Get the corresponding AqBanking account to the GnuCash account gnc_acc.
void gnc_ab_initial_assistant(void)
Create and show an assistant for the aqbanking setup.
gchar * gnc_ab_create_online_id(const gchar *bankcode, const gchar *accountnumber)
Creates an online ID from bank code and account number.
void gnc_ab_set_account_bankcode(Account *a, const gchar *code)
Set the bankcode string in the Account a to code.
Definition gnc-ab-kvp.c:69
void gnc_ab_set_account_accountid(Account *a, const gchar *id)
Set the accountid string in the Account a to id.
Definition gnc-ab-kvp.c:49
void gnc_ab_set_account_uid(Account *a, guint32 uid)
Set the unique id for the AB_BANKING account in the Account a to uid.
Definition gnc-ab-kvp.c:89
void gnc_AB_BANKING_delete(AB_BANKING *api)
Delete the AB_BANKING api.
const gchar * gnc_ab_get_account_accountid(const Account *a)
Return accountid string in the Account a.
Definition gnc-ab-kvp.c:39
guint32 gnc_ab_get_account_uid(const Account *a)
Return the unique id for the AB_BANKING account in the Account a.
Definition gnc-ab-kvp.c:79
AB_BANKING * gnc_AB_BANKING_new(void)
If there is a cached AB_BANKING object, return it initialized.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
void gnc_account_delete_map_entry(Account *acc, char *head, char *category, char *match_string, gboolean empty)
Delete the entry for Account pointed to by head,category and match_string, if empty is TRUE then use ...
Definition Account.cpp:5748
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
Account * gnc_import_select_account(GtkWidget *parent, const gchar *account_online_id_value, gboolean prompt_on_no_match, const gchar *account_human_description, const gnc_commodity *new_account_default_commodity, GNCAccountType new_account_default_type, Account *default_selection, gboolean *ok_pressed)
Must be called with a string containing a unique identifier for the account.
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
Generic and very flexible account matcher/picker.
STRUCTS.