GnuCash c935c2f+
Loading...
Searching...
No Matches
dialog-ab-trans.c
1/*
2 * dialog-ab-trans.c --
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
32#include <config.h>
33
34#include <glib/gi18n.h>
35#include "gnc-ab-utils.h"
36#if (AQBANKING_VERSION_INT >= 60400)
37#include <aqbanking/types/transaction.h>
38
39#include <gnc-aqbanking-templates.h>
40#endif
41#include "dialog-ab-trans.h"
42#include "dialog-transfer.h"
43#include "dialog-utils.h"
44#include "gnc-amount-edit.h"
45#include "gnc-ui.h"
46
47/* This static indicates the debugging module that this .o belongs to. */
48static QofLogModule log_module = G_LOG_DOMAIN;
49
50#if (AQBANKING_VERSION_INT >= 60400)
51/* Template handling */
52static void gnc_ab_trans_dialog_fill_templ_helper(gpointer data, gpointer user_data);
53static gboolean gnc_ab_trans_dialog_clear_templ_helper(GtkTreeModel *model,
54 GtkTreePath *path,
55 GtkTreeIter *iter,
56 gpointer user_data);
57static gboolean gnc_ab_trans_dialog_get_templ_helper(GtkTreeModel *model,
58 GtkTreePath *path,
59 GtkTreeIter *iter,
60 gpointer data);
61#endif
62static AB_TRANSACTION *gnc_ab_trans_dialog_fill_values(GncABTransDialog *td);
63static GNC_AB_JOB *gnc_ab_trans_dialog_get_available_empty_job(GNC_AB_ACCOUNT_SPEC *ab_acc,
64 GncABTransType trans_type);
65
66static void gnc_ab_trans_dialog_check_iban(const GncABTransDialog *td,
67 const AB_TRANSACTION *trans);
68
69/* Callbacks - connected with GtkBuilder - so should not be static */
70void gnc_ab_trans_dialog_add_templ_cb(GtkButton *button, gpointer user_data);
71void gnc_ab_trans_dialog_moveup_templ_cb(GtkButton *button, gpointer user_data);
72void gnc_ab_trans_dialog_movedown_templ_cb(GtkButton *button, gpointer user_data);
73void gnc_ab_trans_dialog_sort_templ_cb(GtkButton *button, gpointer user_data);
74void gnc_ab_trans_dialog_del_templ_cb(GtkButton *button, gpointer user_data);
75void gnc_ab_trans_dialog_ibanentry_filter_cb (GtkEditable *editable,
76 const gchar *text,
77 gint length,
78 gint *position,
79 gpointer user_data);
80void gnc_ab_trans_dialog_bicentry_filter_cb (GtkEditable *editable,
81 const gchar *text,
82 gint length,
83 gint *position,
84 gpointer user_data);
85void gnc_ab_trans_dialog_templ_list_row_activated_cb(GtkTreeView *view,
86 GtkTreePath *path,
87 GtkTreeViewColumn *column,
88 gpointer user_data);
89
90static void gnc_ab_trans_dialog_verify_values(GncABTransDialog *td);
91
92
93enum
94{
95 TEMPLATE_NAME,
96 TEMPLATE_POINTER,
97 TEMPLATE_NUM_COLUMNS
98};
99
101{
102 /* The dialog itself */
103 GtkWidget *dialog;
104 GtkWidget *parent;
105 GNC_AB_ACCOUNT_SPEC *ab_acc;
106
107 /* Whether this is a transfer or a direct debit */
108 GncABTransType trans_type;
109
110 /* Recipient */
111 GtkWidget *recp_name_entry;
112 GtkWidget *recp_account_entry;
113 GtkWidget *recp_bankcode_entry;
114
115 /* Amount */
116 GtkWidget *amount_edit;
117
118 /* Purpose, description */
119 GtkWidget *purpose_entry;
120 GtkWidget *purpose_cont_entry;
121 GtkWidget *purpose_cont2_entry;
122 GtkWidget *purpose_cont3_entry;
123
124 /* Recipient's bank name (may be filled in automatically sometime later) */
125 GtkWidget *recp_bankname_label;
126
127 /* Originator's name (might have to be edited by the user) */
128 GtkWidget *orig_name_entry;
129
130 /* The template choosing GtkTreeView/GtkListStore */
131 GtkTreeView *template_gtktreeview;
132 GtkListStore *template_list_store;
133
134 /* Exec button */
135 GtkWidget *exec_button;
136
137 /* Flag, if template list has been changed */
138 gboolean templ_changed;
139
140 /* The aqbanking transaction that got created here */
141 AB_TRANSACTION *ab_trans;
142
143 /* The gnucash transaction that got created here */
144 Transaction *gnc_trans;
145};
146
147gboolean gnc_ab_trans_isSEPA(GncABTransType t)
148{
149 switch (t)
150 {
151 case SEPA_TRANSFER:
152#if (AQBANKING_VERSION_INT >= 60400)
153 case SEPA_INTERNAL_TRANSFER:
154#endif
155 case SEPA_DEBITNOTE:
156 return TRUE;
157 default:
158 return FALSE;
159 }
160}
161
162#if (AQBANKING_VERSION_INT >= 60400)
163static void
164gnc_ab_trans_dialog_fill_templ_helper(gpointer data, gpointer user_data)
165{
166 GncABTransTempl *templ = data;
167 GtkListStore *store = user_data;
168 GtkTreeIter iter;
169
170 g_return_if_fail(templ && store);
171 gtk_list_store_append(store, &iter);
172 gtk_list_store_set(store, &iter,
173 TEMPLATE_NAME, gnc_ab_trans_templ_get_name(templ),
174 TEMPLATE_POINTER, templ,
175 -1);
176}
177#endif
182static AB_TRANSACTION *
183gnc_ab_trans_dialog_fill_values(GncABTransDialog *td)
184{
185 /* Fill in the user-entered values */
186 AB_TRANSACTION *trans = AB_Transaction_new();
187 AB_VALUE *value;
188
189 AB_Banking_FillTransactionFromAccountSpec(trans, td->ab_acc);
190
191 if (gnc_ab_trans_isSEPA(td->trans_type))
192 {
193 AB_Transaction_SetRemoteBic(
194 trans, gtk_entry_get_text(GTK_ENTRY(td->recp_bankcode_entry)));
195 AB_Transaction_SetRemoteIban(
196 trans, gtk_entry_get_text(GTK_ENTRY(td->recp_account_entry)));
197 AB_Transaction_SetLocalName(
198 trans, gtk_entry_get_text(GTK_ENTRY(td->orig_name_entry)));
199 }
200 else
201 {
202 AB_Transaction_SetRemoteBankCode(
203 trans, gtk_entry_get_text(GTK_ENTRY(td->recp_bankcode_entry)));
204 AB_Transaction_SetRemoteAccountNumber(
205 trans, gtk_entry_get_text(GTK_ENTRY(td->recp_account_entry)));
206 }
207 AB_Transaction_SetRemoteCountry(trans, "DE");
208 AB_Transaction_SetRemoteName(
209 trans, gtk_entry_get_text(GTK_ENTRY(td->recp_name_entry)));
210
211 AB_Transaction_AddPurposeLine(
212 trans, gtk_entry_get_text(GTK_ENTRY(td->purpose_entry)));
213 AB_Transaction_AddPurposeLine(
214 trans, gtk_entry_get_text(GTK_ENTRY(td->purpose_cont_entry)));
215 AB_Transaction_AddPurposeLine(
216 trans, gtk_entry_get_text(GTK_ENTRY(td->purpose_cont2_entry)));
217 value = AB_Value_fromDouble(gnc_amount_edit_get_damount(
218 GNC_AMOUNT_EDIT(td->amount_edit)));
219 /* FIXME: Replace "EUR" by account-dependent string here. */
220 AB_Value_SetCurrency(value, "EUR");
221 AB_Transaction_SetValue(trans, value);
222 AB_Value_free(value);
223
224 /* If this is a direct debit, a textkey/ "Textschluessel"/transactionCode
225 * different from the default has to be set. */
226 switch (td->trans_type)
227 {
228 case SINGLE_DEBITNOTE:
229 /* AB_Transaction_SetTransactionCode (trans, 05); */
230 AB_Transaction_SetTextKey(trans, 05);
231 break;
232 default:
233 /* AB_Transaction_SetTransactionCode (trans, 51); */
234 AB_Transaction_SetTextKey (trans, 51);
235 break;
236 }
237
238 return trans;
239}
240
241GncABTransDialog *
242gnc_ab_trans_dialog_new(GtkWidget *parent, GNC_AB_ACCOUNT_SPEC *ab_acc,
243 gint commodity_scu, GncABTransType trans_type,
244 GList *templates)
245{
246 GncABTransDialog *td;
247 GtkBuilder *builder;
248 const gchar *ab_ownername;
249 const gchar *ab_accountnumber;
250 const gchar *ab_bankname;
251 const gchar *ab_bankcode;
252 G_GNUC_UNUSED GtkWidget *trans_vbox;
253 GtkWidget *heading_label;
254 GtkWidget *recp_name_heading;
255 GtkWidget *recp_account_heading;
256 GtkWidget *recp_bankcode_heading;
257 GtkWidget *amount_hbox, *amount_label;
258 GtkWidget *orig_name_heading;
259 GtkWidget *orig_account_heading;
260 GtkWidget *orig_account_label;
261 G_GNUC_UNUSED GtkWidget *orig_bankname_heading;
262 GtkWidget *orig_bankname_label;
263 GtkWidget *orig_bankcode_heading;
264 GtkWidget *orig_bankcode_label;
265 GtkCellRenderer *renderer;
266 GtkTreeViewColumn *column;
267#if (AQBANKING_VERSION_INT >= 60400)
268 GtkExpander *template_expander;
269 GtkWidget *template_label;
270 GtkWidget *add_templ_button;
271 GtkWidget *del_templ_button;
272#endif
273
274 g_return_val_if_fail(ab_acc, NULL);
275
276 ab_ownername = AB_AccountSpec_GetOwnerName(ab_acc);
277 if (!ab_ownername)
278 ab_ownername = "";
279 ab_accountnumber = AB_AccountSpec_GetAccountNumber(ab_acc);
280 ab_bankcode = AB_AccountSpec_GetBankCode(ab_acc);
281 ab_bankname = _("(unknown)");
282
283 td = g_new0(GncABTransDialog, 1);
284 td->parent = parent;
285 td->ab_acc = ab_acc;
286 td->trans_type = trans_type;
287
288 builder = gtk_builder_new();
289 gnc_builder_add_from_file (builder, "dialog-ab.glade", "aqbanking_transaction_dialog");
290 td->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "aqbanking_transaction_dialog"));
291
292 if (parent)
293 gtk_window_set_transient_for(GTK_WINDOW(td->dialog), GTK_WINDOW(parent));
294
295 /* Extract widgets */
296 trans_vbox = GTK_WIDGET(gtk_builder_get_object (builder, "trans_vbox"));
297 heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
298 recp_name_heading = GTK_WIDGET(gtk_builder_get_object (builder, "recp_name_heading"));
299 td->recp_name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "recp_name_entry"));
300 recp_account_heading = GTK_WIDGET(gtk_builder_get_object (builder, "recp_account_heading"));
301 td->recp_account_entry = GTK_WIDGET(gtk_builder_get_object (builder, "recp_account_entry"));
302 recp_bankcode_heading = GTK_WIDGET(gtk_builder_get_object (builder, "recp_bankcode_heading"));
303 td->recp_bankcode_entry = GTK_WIDGET(gtk_builder_get_object (builder, "recp_bankcode_entry"));
304 td->recp_bankname_label = GTK_WIDGET(gtk_builder_get_object (builder, "recp_bankname_label"));
305 amount_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "amount_hbox"));
306 amount_label = GTK_WIDGET(gtk_builder_get_object (builder, "amount_label"));
307 td->purpose_entry = GTK_WIDGET(gtk_builder_get_object (builder, "purpose_entry"));
308 td->purpose_cont_entry = GTK_WIDGET(gtk_builder_get_object (builder, "purpose_cont_entry"));
309 td->purpose_cont2_entry = GTK_WIDGET(gtk_builder_get_object (builder, "purpose_cont2_entry"));
310 td->purpose_cont3_entry = GTK_WIDGET(gtk_builder_get_object (builder, "purpose_cont3_entry"));
311 td->exec_button = GTK_WIDGET(gtk_builder_get_object(builder, "exec_now_button"));
312 orig_name_heading = GTK_WIDGET(gtk_builder_get_object (builder, "orig_name_heading"));
313 td->orig_name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "orig_name_label"));
314 orig_account_heading = GTK_WIDGET(gtk_builder_get_object (builder, "orig_account_heading"));
315 orig_account_label = GTK_WIDGET(gtk_builder_get_object (builder, "orig_account_label"));
316 orig_bankname_heading = GTK_WIDGET(gtk_builder_get_object (builder, "orig_bankname_heading"));
317 orig_bankname_label = GTK_WIDGET(gtk_builder_get_object (builder, "orig_bankname_label"));
318 orig_bankcode_heading = GTK_WIDGET(gtk_builder_get_object (builder, "orig_bankcode_heading"));
319 orig_bankcode_label = GTK_WIDGET(gtk_builder_get_object (builder, "orig_bankcode_label"));
320 td->template_gtktreeview =
321 GTK_TREE_VIEW(gtk_builder_get_object (builder, "template_list"));
322#if (AQBANKING_VERSION_INT >= 60400)
323 template_expander = GTK_EXPANDER(gtk_builder_get_object (builder, "expander1"));
324 template_label = GTK_WIDGET(gtk_builder_get_object (builder, "label1"));
325 add_templ_button= GTK_WIDGET(gtk_builder_get_object(builder, "add_templ_button"));
326 del_templ_button= GTK_WIDGET(gtk_builder_get_object(builder, "del_templ_button"));
327#endif
328
329 /* Amount edit */
330 td->amount_edit = gnc_amount_edit_new();
331 gtk_box_pack_start(GTK_BOX(amount_hbox), td->amount_edit, TRUE, TRUE, 0);
332 gnc_amount_edit_make_mnemonic_target(GNC_AMOUNT_EDIT(td->amount_edit), amount_label);
333 gnc_amount_edit_set_evaluate_on_enter(GNC_AMOUNT_EDIT(td->amount_edit),
334 TRUE);
335 gnc_amount_edit_set_fraction(GNC_AMOUNT_EDIT(td->amount_edit),
336 commodity_scu);
337
338 /* Use "focus-out" signal because "amount-changed" is only sent when ENTER is pressed */
339 g_signal_connect_swapped (gnc_amount_edit_gtk_entry(GNC_AMOUNT_EDIT(td->amount_edit)), "focus-out-event",
340 G_CALLBACK(gnc_ab_trans_dialog_verify_values), td);
341
342 /* Check for what kind of transaction this should be, and change the
343 * labels accordingly */
344 switch (trans_type)
345 {
346 case SINGLE_TRANSFER:
347 case SINGLE_INTERNAL_TRANSFER:
348 /* all labels are already set */
349 break;
350 case SEPA_TRANSFER:
351 gtk_label_set_text(GTK_LABEL (heading_label),
352 /* Translators: Strings from this file are
353 needed only in countries that have one of
354 aqbanking's Online Banking techniques
355 available. This is 'OFX DirectConnect'
356 (U.S. and others), 'HBCI' (Germany),
357 or 'YellowNet' (Switzerland). If none of
358 these techniques are available in your
359 country, you may safely ignore strings
360 from the import-export/hbci
361 subdirectory. */
362 _("Enter a SEPA Online Transfer"));
363 gtk_label_set_text(GTK_LABEL(recp_account_heading),
364 _("Recipient IBAN (International Account Number)"));
365 gtk_label_set_text(GTK_LABEL(recp_bankcode_heading),
366 _("Recipient BIC (Bank Code)"));
367
368 gtk_label_set_text(GTK_LABEL(orig_account_heading),
369 _("Originator IBAN (International Account Number)"));
370 gtk_label_set_text(GTK_LABEL(orig_bankcode_heading),
371 _("Originator BIC (Bank Code)"));
372 break;
373
374#if (AQBANKING_VERSION_INT >= 60400)
375 case SEPA_INTERNAL_TRANSFER:
376 gtk_label_set_text(GTK_LABEL (heading_label),
377 _("Enter a SEPA Internal Transfer"));
378 gtk_label_set_text(GTK_LABEL(recp_account_heading),
379 _("Recipient IBAN (International Account Number)"));
380 gtk_label_set_text(GTK_LABEL(recp_bankcode_heading),
381 _("Recipient BIC (Bank Code)"));
382
383 gtk_label_set_text(GTK_LABEL(orig_account_heading),
384 _("Originator IBAN (International Account Number)"));
385 gtk_label_set_text(GTK_LABEL(orig_bankcode_heading),
386 _("Originator BIC (Bank Code)"));
387 /* Disable target account entry for SEPA internal transfers, but only let choose from templates */
388 gtk_widget_set_sensitive(td->recp_name_entry, FALSE);
389 gtk_widget_set_sensitive(td->recp_account_entry, FALSE);
390 gtk_widget_set_sensitive(td->recp_bankcode_entry, FALSE);
391 gtk_widget_set_sensitive(add_templ_button, FALSE);
392 gtk_widget_set_visible(add_templ_button, FALSE);
393 gtk_widget_set_can_focus(add_templ_button, FALSE);
394 gtk_widget_set_sensitive(del_templ_button, FALSE);
395 gtk_widget_set_visible(del_templ_button, FALSE);
396 gtk_widget_set_can_focus(del_templ_button, FALSE);
397 gtk_label_set_text(GTK_LABEL(template_label),
398 _("Target Accounts"));
399 gtk_expander_set_expanded(template_expander, TRUE);
400 break;
401#endif
402
403 case SINGLE_DEBITNOTE:
404 /* this case is no longer in use; don't introduce extra strings */
405 break;
406
407 case SEPA_DEBITNOTE:
408 gtk_label_set_text(GTK_LABEL (heading_label),
409 _("Enter a SEPA Online Direct Debit Note"));
410
411 gtk_label_set_text(GTK_LABEL(recp_name_heading),
412 _("Debited Account Owner"));
413 gtk_label_set_text(GTK_LABEL(recp_account_heading),
414 _("Debited IBAN (International Account Number)"));
415 gtk_label_set_text(GTK_LABEL(recp_bankcode_heading),
416 _("Debited BIC (Bank Code)"));
417
418 gtk_label_set_text(GTK_LABEL(orig_name_heading),
419 _("Credited Account Owner"));
420 gtk_label_set_text(GTK_LABEL(orig_account_heading),
421 _("Credited IBAN (International Account Number)"));
422 gtk_label_set_text(GTK_LABEL(orig_bankcode_heading),
423 _("Credited BIC (Bank Code)"));
424 break;
425
426 default:
427 g_critical("gnc_ab_trans_dialog_new: Oops, unknown GncABTransType %d",
428 trans_type);
429 break;
430 }
431
432 /* Additionally change the labels for the European (SEPA) transactions */
433 if (gnc_ab_trans_isSEPA(trans_type))
434 {
435 // Also, SEPA might have much longer IBAN (up to 34 chars) and BIC (11)
436 gtk_entry_set_max_length(GTK_ENTRY(td->recp_bankcode_entry), 11);
437 gtk_entry_set_max_length(GTK_ENTRY(td->recp_account_entry), 34);
438 }
439
440 gtk_entry_set_text(GTK_ENTRY(td->orig_name_entry), ab_ownername);
441 gtk_label_set_text(GTK_LABEL(orig_bankname_label), ab_bankname);
442 if (gnc_ab_trans_isSEPA(trans_type))
443 {
444 gtk_widget_set_sensitive(GTK_WIDGET(td->orig_name_entry), TRUE);
445 ab_accountnumber = AB_AccountSpec_GetIban(ab_acc);
446 ab_bankcode = AB_AccountSpec_GetBic(ab_acc);
447 gtk_label_set_text(GTK_LABEL(orig_account_label), ab_accountnumber);
448 gtk_label_set_text (GTK_LABEL (orig_bankcode_label), ab_bankcode);
449 }
450 else
451 {
452 gtk_widget_set_sensitive(GTK_WIDGET(td->orig_name_entry), FALSE);
453 gtk_label_set_text(GTK_LABEL(orig_account_label), ab_accountnumber);
454 gtk_label_set_text (GTK_LABEL (orig_bankcode_label), ab_bankcode);
455 }
456
457#if (AQBANKING_VERSION_INT >= 60400)
458 /* Fill list for choosing a transaction template */
459 td->template_list_store = gtk_list_store_new(TEMPLATE_NUM_COLUMNS,
460 G_TYPE_STRING, G_TYPE_POINTER);
461 g_list_foreach(templates, gnc_ab_trans_dialog_fill_templ_helper, td->template_list_store);
462 gtk_tree_view_set_model(td->template_gtktreeview,
463 GTK_TREE_MODEL(td->template_list_store));
464 td->templ_changed = FALSE;
465 /* Keep a reference to the store */
466#endif
467 /* Show this list */
468 renderer = gtk_cell_renderer_text_new();
469 column = gtk_tree_view_column_new_with_attributes(
470 "Template Name", renderer, "text", TEMPLATE_NAME, NULL);
471 gtk_tree_view_append_column(td->template_gtktreeview, column);
472
473 /* Connect the Signals */
474 gtk_builder_connect_signals_full(builder, gnc_builder_connect_full_func, td);
475
476 g_object_unref(G_OBJECT(builder));
477
478 /* Disabled OK button until suitable values are filled */
479 gnc_ab_trans_dialog_verify_values(td);
480
481 return td;
482}
483
484static void
485gnc_ab_trans_dialog_entry_set (GtkWidget* entry,
486 const gchar* message,
487 const gchar* icon_name)
488{
489 g_object_set (entry,
490 "secondary-icon-name", icon_name,
491 "secondary-icon-tooltip-text", message,
492 NULL);
493}
494
495static void
496gnc_ab_trans_dialog_check_iban(const GncABTransDialog *td,
497 const AB_TRANSACTION *trans)
498{
499 if (gnc_ab_trans_isSEPA(td->trans_type))
500 {
501 /* Verify the correct IBAN bank code */
502 int rv = AB_Banking_CheckIban(AB_Transaction_GetRemoteIban(trans));
503 if (rv != 0) {
504 gchar *message = g_strdup_printf(_("The internal check of the destination IBAN '%s' "
505 "failed. This means "
506 "the account number might contain an error."),
507 AB_Transaction_GetRemoteIban(trans));
508 gnc_ab_trans_dialog_entry_set (td->recp_account_entry, message,
509 "dialog-warning");
510 }
511 else
512 {
513 gnc_ab_trans_dialog_entry_set (td->recp_account_entry, "",
514 NULL);
515 gnc_ab_trans_dialog_entry_set (td->recp_bankcode_entry, "",
516 NULL);
517 }
518 }
519 else
520 {
521 /* this case is no longer in use */
522 return;
523 }
524}
525
526static void
527gnc_ab_trans_dialog_clear_transaction(GncABTransDialog *td)
528{
529 AB_Transaction_free(td->ab_trans);
530 td->ab_trans = NULL;
531}
532
533void
534gnc_ab_trans_dialog_verify_values(GncABTransDialog *td)
535{
536 gchar* purpose;
537 gchar* othername;
538 const gchar* account;
539 const gchar* bankcode;
540
541 gboolean values_ok = TRUE;
542
543 GtkWidget *amount_entry = gnc_amount_edit_gtk_entry(GNC_AMOUNT_EDIT(td->amount_edit));
544
545 /* Fill in the values from the entry fields into a new
546 * AB_TRANSACTION */
547 td->ab_trans = gnc_ab_trans_dialog_fill_values(td);
548
549 // Verify that we have a local IBAN and BIC
550 if (gnc_ab_trans_isSEPA(td->trans_type))
551 {
552 const char* localIBAN = AB_Transaction_GetLocalIban(td->ab_trans);
553 if (!localIBAN || (strlen(localIBAN) == 0))
554 {
555 const char* localBankCode = AB_Transaction_GetLocalBankCode(td->ab_trans);
556 const char* localAccountCode = AB_Transaction_GetLocalAccountNumber(td->ab_trans);
557 values_ok = FALSE;
558 gnc_error_dialog(GTK_WINDOW (td->dialog),
559 _("Your local bank account does not yet have the SEPA account information stored."
560 " We are sorry, but in this development version one additional step is necessary "
561 "which has not yet been implemented directly in gnucash. "
562 "Please execute the command line program \"aqhbci-tool\" for your account, as follows: "
563 "aqhbci-tool4 getaccsepa -b %s -a %s"),
564 (localBankCode ? localBankCode : ""),
565 (localAccountCode ? localAccountCode : ""));
566 }
567 }
568
569 /* Check recipient / remote name */
570 othername = gnc_ab_get_remote_name(td->ab_trans);
571 if (!othername || !strlen(othername))
572 {
573 gnc_ab_trans_dialog_entry_set (td->recp_name_entry,
574 _("You did not enter a recipient name. A recipient name is "
575 "required for an online transfer.\n"),
576 "process-stop");
577
578 g_free (othername);
579 values_ok = FALSE;
580 }
581 else
582 {
583 gnc_ab_trans_dialog_entry_set (td->recp_name_entry, "", NULL);
584 g_free(othername);
585 }
586
587 /* Check account */
588 account = gnc_ab_trans_isSEPA(td->trans_type)
589 ? AB_Transaction_GetRemoteIban(td->ab_trans)
590 : AB_Transaction_GetRemoteAccountNumber(td->ab_trans);
591 if (!account || !strlen(account))
592 {
593 gnc_ab_trans_dialog_entry_set (td->recp_account_entry,
594 _("You did not enter a recipient account. A recipient account is "
595 "required for an online transfer.\n"),
596 "process-stop");
597 values_ok = FALSE;
598 }
599 else
600 {
601 gnc_ab_trans_dialog_entry_set (td->recp_account_entry, "", NULL);
602 }
603 /* Check bank */
604 bankcode = gnc_ab_trans_isSEPA(td->trans_type)
605 ? AB_Transaction_GetRemoteBic(td->ab_trans)
606 : AB_Transaction_GetRemoteBankCode(td->ab_trans);
607 if (!gnc_ab_trans_isSEPA(td->trans_type) && (!bankcode || !strlen(bankcode)))
608 {
609 gnc_ab_trans_dialog_entry_set (td->recp_bankcode_entry,
610 _("You did not enter a recipient bank. A recipient bank is "
611 "required for an online transfer.\n"),
612 "process-stop");
613 values_ok = FALSE;
614 }
615 else
616 {
617 gnc_ab_trans_dialog_entry_set (td->recp_bankcode_entry, "", NULL);
618 }
619 /* Check if account details are correct - gives warning only */
620 if (values_ok)
621 gnc_ab_trans_dialog_check_iban(td, td->ab_trans);
622
623 /* Check transaction value */
624 if (AB_Value_GetValueAsDouble(AB_Transaction_GetValue(td->ab_trans))
625 == 0.0)
626 {
627 gnc_ab_trans_dialog_entry_set (amount_entry,
628 _("The amount is zero or the amount field could not be "
629 "interpreted correctly. You might have mixed up decimal "
630 "point and comma, compared to your locale settings. "
631 "This does not result in a valid online transfer job."),
632 "process-stop");
633 values_ok = FALSE;
634 }
635 else
636 {
637 gnc_ab_trans_dialog_entry_set (amount_entry, "", NULL);
638 }
639
640 /* Check transaction purpose. OFX doesn't do transfers. */
641 purpose = gnc_ab_get_purpose(td->ab_trans, FALSE);
642 if (!purpose || !strlen(purpose))
643 {
644 gnc_ab_trans_dialog_entry_set (td->purpose_entry,
645 _("You did not enter any transaction purpose. A purpose is "
646 "required for an online transfer.\n"),
647 "process-stop");
648 g_free (purpose);
649 values_ok = FALSE;
650 }
651 else
652 {
653 gnc_ab_trans_dialog_entry_set (td->purpose_entry, "", NULL);
654 g_free(purpose);
655 }
656
657 gtk_widget_set_sensitive(td->exec_button, values_ok);
658 gnc_ab_trans_dialog_clear_transaction(td);
659}
660
661gint
663{
664 gint result;
665 GNC_AB_JOB *job;
666 const AB_TRANSACTION_LIMITS *joblimits;
667 guint8 max_purpose_lines;
668
669 /* Check whether the account supports this job */
670 job = gnc_ab_trans_dialog_get_available_empty_job(td->ab_acc, td->trans_type);
671 if (!job)
672 {
673 g_warning("gnc_ab_trans_dialog_run_until_ok: Oops, job not available");
674 return GTK_RESPONSE_CANCEL;
675 }
676
677 /* Activate as many purpose entries as available for the job */
678 joblimits = AB_AccountSpec_GetTransactionLimitsForCommand(td->ab_acc, AB_Transaction_GetCommand(job));
679 max_purpose_lines = joblimits ?
680 AB_TransactionLimits_GetMaxLinesPurpose(joblimits) : 2;
681 gtk_widget_set_sensitive(td->purpose_cont_entry, max_purpose_lines > 1);
682 gtk_widget_set_sensitive(td->purpose_cont2_entry, max_purpose_lines > 2);
683 gtk_widget_set_sensitive(td->purpose_cont3_entry, max_purpose_lines > 3);
684 if (joblimits)
685 {
686 gtk_entry_set_max_length(GTK_ENTRY(td->purpose_entry),
687 AB_TransactionLimits_GetMaxLenPurpose(joblimits));
688 gtk_entry_set_max_length(GTK_ENTRY(td->purpose_cont_entry),
689 AB_TransactionLimits_GetMaxLenPurpose(joblimits));
690 gtk_entry_set_max_length(GTK_ENTRY(td->purpose_cont2_entry),
691 AB_TransactionLimits_GetMaxLenPurpose(joblimits));
692 gtk_entry_set_max_length(GTK_ENTRY(td->purpose_cont3_entry),
693 AB_TransactionLimits_GetMaxLenPurpose(joblimits));
694 gtk_entry_set_max_length(GTK_ENTRY(td->recp_name_entry),
695 AB_TransactionLimits_GetMaxLenRemoteName(joblimits));
696 }
697
698 /* Show the dialog */
699 gtk_widget_show(td->dialog);
700
701 /* Now run the dialog until it gets closed by a button press */
702 result = gtk_dialog_run (GTK_DIALOG (td->dialog));
703
704 /* Was cancel pressed or dialog closed?
705 * GNC_RESPONSE_NOW == execute now
706 * GNC_RESPONSE_LATER == scheduled for later execution (unimplemented)
707 * GTK_RESPONSE_CANCEL == cancel
708 * GTK_RESPONSE_DELETE_EVENT == window destroyed */
709 if (result != GNC_RESPONSE_NOW && result != GNC_RESPONSE_LATER)
710 {
711 gtk_widget_destroy(td->dialog);
712 td->dialog = NULL;
713 return result;
714 }
715
716 /* Get the transaction details - have been checked beforehand */
717 td->ab_trans = gnc_ab_trans_dialog_fill_values(td);
718
719 /* FIXME: If this is a direct debit, set the textkey/ "Textschluessel"/
720 * transactionCode according to some GUI selection here!! */
721 /*if (td->trans_type == SINGLE_DEBITNOTE)
722 AB_TRANSACTION_setTextKey (td->hbci_trans, 05); */
723
724
725 /* Hide the dialog */
726 if (td->dialog)
727 gtk_widget_hide(td->dialog);
728
729 return result;
730}
731
732#if (AQBANKING_VERSION_INT >= 60400)
733static gboolean
734gnc_ab_trans_dialog_clear_templ_helper(GtkTreeModel *model,
735 GtkTreePath *path,
736 GtkTreeIter *iter,
737 gpointer user_data)
738{
739 GncABTransTempl *templ;
740
741 g_return_val_if_fail(model && iter, TRUE);
742
743 gtk_tree_model_get(model, iter, TEMPLATE_POINTER, &templ, -1);
745 return FALSE;
746}
747#endif
748void
749gnc_ab_trans_dialog_free(GncABTransDialog *td)
750{
751 if (!td) return;
752 if (td->ab_trans)
753 AB_Transaction_free(td->ab_trans);
754 if (td->dialog)
755 gtk_widget_destroy(td->dialog);
756
757#if (AQBANKING_VERSION_INT >= 60400)
758 if (td->template_list_store)
759 {
760 gtk_tree_model_foreach(GTK_TREE_MODEL(td->template_list_store),
761 gnc_ab_trans_dialog_clear_templ_helper, NULL);
762 g_object_unref(td->template_list_store);
763 }
764#endif
765 g_free(td);
766}
767
768#if (AQBANKING_VERSION_INT >= 60400)
769static gboolean
770gnc_ab_trans_dialog_get_templ_helper(GtkTreeModel *model,
771 GtkTreePath *path,
772 GtkTreeIter *iter,
773 gpointer data)
774{
775 GList **list = data;
776 GncABTransTempl *templ;
777
778 g_return_val_if_fail(model && iter, TRUE);
779
780 gtk_tree_model_get(model, iter, TEMPLATE_POINTER, &templ, -1);
781 *list = g_list_prepend(*list, templ);
782 return FALSE;
783}
784
785GList *
786gnc_ab_trans_dialog_get_templ(const GncABTransDialog *td, gboolean *changed)
787{
788 GList *list = NULL;
789
790 g_return_val_if_fail(td, NULL);
791
792 if (changed)
793 {
794 *changed = td->templ_changed;
795 if (!*changed)
796 return NULL;
797 }
798
799 gtk_tree_model_foreach(GTK_TREE_MODEL(td->template_list_store),
800 gnc_ab_trans_dialog_get_templ_helper, &list);
801 list = g_list_reverse(list);
802 return list;
803}
804#endif
805
806GtkWidget *
807gnc_ab_trans_dialog_get_parent(const GncABTransDialog *td)
808{
809 g_return_val_if_fail(td, NULL);
810 return td->parent;
811}
812
813const AB_TRANSACTION *
814gnc_ab_trans_dialog_get_ab_trans(const GncABTransDialog *td)
815{
816 g_return_val_if_fail(td, NULL);
817 return td->ab_trans;
818}
819
820static GNC_AB_JOB *
821gnc_ab_trans_dialog_get_available_empty_job(GNC_AB_ACCOUNT_SPEC *ab_acc, GncABTransType trans_type)
822{
823 GNC_AB_JOB *job;
824 AB_TRANSACTION_COMMAND cmd = AB_Transaction_CommandUnknown;
825
826 switch (trans_type)
827 {
828 case SINGLE_DEBITNOTE: /* no longer in use */
829 cmd=AB_Transaction_CommandDebitNote;
830 break;
831 case SINGLE_INTERNAL_TRANSFER:
832 cmd=AB_Transaction_CommandInternalTransfer;
833 break;
834 case SEPA_TRANSFER:
835 cmd=AB_Transaction_CommandSepaTransfer;
836 break;
837#if (AQBANKING_VERSION_INT >= 60400)
838 case SEPA_INTERNAL_TRANSFER:
839 cmd=AB_Transaction_CommandSepaInternalTransfer;
840 break;
841#endif
842 case SEPA_DEBITNOTE:
843 cmd=AB_Transaction_CommandSepaDebitNote;
844 break;
845 default:
846 cmd=AB_Transaction_CommandTransfer; /* no longer in use */
847 break;
848 };
849 if (!AB_AccountSpec_GetTransactionLimitsForCommand(ab_acc, cmd))
850 return NULL;
851
852 job = AB_Transaction_new();
853 AB_Transaction_SetCommand(job, cmd);
854 AB_Transaction_SetUniqueAccountId(job, AB_AccountSpec_GetUniqueId(ab_acc));
855 return job;
856}
857
858GNC_AB_JOB *
859gnc_ab_trans_dialog_get_job(const GncABTransDialog *td)
860{
861 g_return_val_if_fail(td, NULL);
862 return gnc_ab_get_trans_job(td->ab_acc, td->ab_trans, td->trans_type);
863}
864
865GNC_AB_JOB *
866gnc_ab_get_trans_job(GNC_AB_ACCOUNT_SPEC *ab_acc,
867 const AB_TRANSACTION *ab_trans,
868 GncABTransType trans_type)
869{
870 GNC_AB_JOB *job;
871
872 g_return_val_if_fail(ab_acc && ab_trans, NULL);
873
874 job = gnc_ab_trans_dialog_get_available_empty_job(ab_acc, trans_type);
875 if (job)
876 {
877 AB_TRANSACTION *new_job;
878
879 /* merge transactions */
880 new_job=AB_Transaction_dup(ab_trans);
881 AB_Transaction_SetCommand(new_job, AB_Transaction_GetCommand(job));
882 AB_Transaction_SetUniqueAccountId(new_job,
883 AB_Transaction_GetUniqueAccountId(job));
884
885 AB_Transaction_free(job);
886 return new_job;
887 }
888 return NULL;
889
890}
891
892#if (AQBANKING_VERSION_INT >= 60400)
893void
894gnc_ab_trans_dialog_templ_list_row_activated_cb(GtkTreeView *view,
895 GtkTreePath *path,
896 GtkTreeViewColumn *column,
897 gpointer user_data)
898{
899 GncABTransDialog *td = user_data;
900 GtkTreeIter iter;
901 GncABTransTempl *templ;
902 const gchar *new_name;
903 const gchar *new_account;
904 const gchar *new_bankcode;
905 const gchar *new_purpose;
906 const gchar *new_purpose_cont;
907 gnc_numeric new_amount;
908
909 g_return_if_fail(td);
910
911 ENTER("td=%p", td);
912 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(td->template_list_store), &iter,
913 path))
914 {
915 LEAVE("Could not get iter");
916 return;
917 }
918 gtk_tree_model_get(GTK_TREE_MODEL(td->template_list_store), &iter,
919 TEMPLATE_POINTER, &templ, -1);
920
921 /* Get new values */
922 new_name = gnc_ab_trans_templ_get_recp_name(templ);
923 new_account = gnc_ab_trans_templ_get_recp_account(templ);
924 new_bankcode = gnc_ab_trans_templ_get_recp_bankcode(templ);
925 new_purpose = gnc_ab_trans_templ_get_purpose(templ);
926 new_purpose_cont = gnc_ab_trans_templ_get_purpose_cont(templ);
927 new_amount = gnc_ab_trans_templ_get_amount(templ);
928 if (!new_name) new_name = "";
929 if (!new_account) new_account = "";
930 if (!new_bankcode) new_bankcode = "";
931 if (!new_purpose) new_purpose = "";
932 if (!new_purpose_cont) new_purpose_cont = "";
933
934 /* Fill in */
935 gtk_entry_set_text(GTK_ENTRY(td->recp_name_entry), new_name);
936 gtk_entry_set_text(GTK_ENTRY(td->recp_account_entry), new_account);
937 gtk_entry_set_text(GTK_ENTRY(td->recp_bankcode_entry), new_bankcode);
938 gtk_entry_set_text(GTK_ENTRY(td->purpose_entry), new_purpose);
939 gtk_entry_set_text(GTK_ENTRY(td->purpose_cont_entry), new_purpose_cont);
940 gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(td->amount_edit), new_amount);
941 LEAVE(" ");
942}
943
944
945struct _FindTemplData
946{
947 const gchar *name;
948 const GncABTransTempl *pointer;
949};
950
951static gboolean
952find_templ_helper(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
953 gpointer user_data)
954{
955 struct _FindTemplData *data = user_data;
956 gchar *name;
957 GncABTransTempl *templ;
958 gboolean match;
959
960 g_return_val_if_fail(model && data, TRUE);
961 gtk_tree_model_get(model, iter,
962 TEMPLATE_NAME, &name,
963 TEMPLATE_POINTER, &templ,
964 -1);
965 if (data->name)
966 {
967 /* Search for the template by name */
968 g_return_val_if_fail(!data->pointer, TRUE);
969 match = strcmp(name, data->name) == 0;
970 if (match) data->pointer = templ;
971 }
972 else
973 {
974 /* Search for the template by template pointer */
975 g_return_val_if_fail(!data->name, TRUE);
976 match = templ == data->pointer;
977 if (match) data->name = g_strdup(name);
978 }
979 g_free(name);
980 return match;
981}
982
983void
984gnc_ab_trans_dialog_add_templ_cb(GtkButton *button, gpointer user_data)
985{
986 GncABTransDialog *td = user_data;
987 GtkBuilder *builder;
988 GtkWidget *dialog;
989 GtkWidget *entry;
990 gint retval;
991 const gchar *name;
992 GncABTransTempl *templ;
993 struct _FindTemplData data;
994 GtkTreeSelection *selection;
995 GtkTreeIter cur_iter;
996 GtkTreeIter new_iter;
997
998 g_return_if_fail(td);
999
1000 ENTER("td=%p", td);
1001 builder = gtk_builder_new();
1002 gnc_builder_add_from_file (builder, "dialog-ab.glade", "aqbanking_template_name_dialog");
1003 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "aqbanking_template_name_dialog"));
1004
1005 entry = GTK_WIDGET(gtk_builder_get_object (builder, "template_name"));
1006
1007 /* Suggest recipient name as name of the template */
1008 gtk_entry_set_text(GTK_ENTRY(entry),
1009 gtk_entry_get_text(GTK_ENTRY(td->recp_name_entry)));
1010
1011 do
1012 {
1013 retval = gtk_dialog_run(GTK_DIALOG(dialog));
1014 if (retval != GTK_RESPONSE_OK)
1015 break;
1016
1017 name = gtk_entry_get_text(GTK_ENTRY(entry));
1018 if (!*name)
1019 break;
1020
1021 data.name = name;
1022 data.pointer = NULL;
1023 gtk_tree_model_foreach(GTK_TREE_MODEL(td->template_list_store),
1024 find_templ_helper, &data);
1025 if (data.pointer)
1026 {
1027 gnc_error_dialog(GTK_WINDOW (dialog), "%s",
1028 _("A template with the given name already exists. "
1029 "Please enter another name."));
1030 continue;
1031 }
1032
1033 /* Create a new template */
1035 name,
1036 gtk_entry_get_text(GTK_ENTRY(td->recp_name_entry)),
1037 gtk_entry_get_text(GTK_ENTRY(td->recp_account_entry)),
1038 gtk_entry_get_text(GTK_ENTRY(td->recp_bankcode_entry)),
1039 gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(td->amount_edit)),
1040 gtk_entry_get_text(GTK_ENTRY(td->purpose_entry)),
1041 gtk_entry_get_text (GTK_ENTRY(td->purpose_cont_entry)));
1042
1043 /* Insert it, either after the selected one or at the end */
1044 selection = gtk_tree_view_get_selection(td->template_gtktreeview);
1045 if (gtk_tree_selection_get_selected(selection, NULL, &cur_iter))
1046 {
1047 gtk_list_store_insert_after(td->template_list_store,
1048 &new_iter, &cur_iter);
1049 }
1050 else
1051 {
1052 gtk_list_store_append(td->template_list_store, &new_iter);
1053 }
1054 gtk_list_store_set(td->template_list_store, &new_iter,
1055 TEMPLATE_NAME, name,
1056 TEMPLATE_POINTER, templ,
1057 -1);
1058 td->templ_changed = TRUE;
1059 DEBUG("Added template with name %s", name);
1060 break;
1061 }
1062 while (TRUE);
1063
1064 g_object_unref(G_OBJECT(builder));
1065
1066 gtk_widget_destroy(dialog);
1067
1068 LEAVE(" ");
1069}
1070#endif
1071
1072void
1073gnc_ab_trans_dialog_moveup_templ_cb(GtkButton *button, gpointer user_data)
1074{
1075 GncABTransDialog *td = user_data;
1076 GtkTreeSelection *selection;
1077 GtkTreeModel *model;
1078 GtkTreeIter iter;
1079 GtkTreePath *prev_path;
1080 GtkTreeIter prev_iter;
1081
1082 g_return_if_fail(td);
1083
1084 selection = gtk_tree_view_get_selection(td->template_gtktreeview);
1085 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1086 return;
1087
1088 prev_path = gtk_tree_model_get_path(model, &iter);
1089 if (gtk_tree_path_prev(prev_path))
1090 {
1091 if (gtk_tree_model_get_iter(model, &prev_iter, prev_path))
1092 {
1093 gtk_list_store_move_before(GTK_LIST_STORE(model), &iter, &prev_iter);
1094 td->templ_changed = TRUE;
1095 }
1096 }
1097 gtk_tree_path_free(prev_path);
1098}
1099
1100void
1101gnc_ab_trans_dialog_movedown_templ_cb(GtkButton *button, gpointer user_data)
1102{
1103 GncABTransDialog *td = user_data;
1104 GtkTreeSelection *selection;
1105 GtkTreeModel *model;
1106 GtkTreeIter iter;
1107 GtkTreeIter next_iter;
1108
1109 g_return_if_fail(td);
1110
1111 selection = gtk_tree_view_get_selection(td->template_gtktreeview);
1112 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
1113 return;
1114
1115 next_iter = iter;
1116 if (gtk_tree_model_iter_next(model, &next_iter))
1117 {
1118 gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, &next_iter);
1119 td->templ_changed = TRUE;
1120 }
1121}
1122
1123void
1124gnc_ab_trans_dialog_sort_templ_cb(GtkButton *button, gpointer user_data)
1125{
1126 GncABTransDialog *td = user_data;
1127
1128 g_return_if_fail(td);
1129
1130 ENTER("td=%p", td);
1131 gtk_tree_sortable_set_sort_column_id(
1132 GTK_TREE_SORTABLE(td->template_list_store),
1133 TEMPLATE_NAME, GTK_SORT_ASCENDING);
1134 gtk_tree_sortable_set_sort_column_id(
1135 GTK_TREE_SORTABLE(td->template_list_store),
1136 GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
1137 GTK_SORT_ASCENDING);
1138 td->templ_changed = TRUE;
1139 LEAVE(" ");
1140}
1141
1142void
1143gnc_ab_trans_dialog_del_templ_cb(GtkButton *button, gpointer user_data)
1144{
1145 GncABTransDialog *td = user_data;
1146 GtkTreeSelection *selection;
1147 GtkTreeModel *model;
1148 GtkTreeIter iter;
1149 gchar *name;
1150
1151 g_return_if_fail(td);
1152
1153 ENTER("td=%p", td);
1154 selection = gtk_tree_view_get_selection(td->template_gtktreeview);
1155 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
1156 {
1157 LEAVE("None selected");
1158 return;
1159 }
1160
1161 gtk_tree_model_get(model, &iter, TEMPLATE_NAME, &name, -1);
1162 if (gnc_verify_dialog (
1163 GTK_WINDOW (td->parent), FALSE,
1164 _("Do you really want to delete the template with the name \"%s\"?"),
1165 name))
1166 {
1167 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1168 td->templ_changed = TRUE;
1169 DEBUG("Deleted template with name %s", name);
1170 }
1171 g_free(name);
1172 LEAVE(" ");
1173}
1174
1175void
1176gnc_ab_trans_dialog_ibanentry_filter_cb (GtkEditable *editable,
1177 const gchar *text,
1178 gint length,
1179 gint *position,
1180 gpointer data)
1181{
1182 GString* result = g_string_new(NULL);
1183 gint i;
1184 GncABTransDialog *td = data;
1185
1186 if (length == -1)
1187 length = strlen(text);
1188 g_assert(position);
1189
1190 /* Filter digits / non digits as needed */
1191 for (i = 0; i < length; i++)
1192 {
1193 gchar c = text[i];
1194
1195 if (gnc_ab_trans_isSEPA(td->trans_type))
1196 {
1197 enum {
1198 ALPHA
1199 , ALNUM
1200 , NUMERIC
1201 } allowed_characterclass;
1202
1203 // SEPA: Only alphas in the first two places (at index 0, 1)
1204 if (*position + i < 2)
1205 {
1206 allowed_characterclass = ALPHA;
1207 }
1208 // SEPA: Next two places are digits only (index 2, 3)
1209 else if (*position + i < 4)
1210 {
1211 allowed_characterclass = NUMERIC;
1212 }
1213 // SEPA: The rest depends on the country code: Either Alpha-numeric or numeric only
1214 else
1215 {
1216 const gchar* acct_text = gtk_entry_get_text(GTK_ENTRY(td->recp_account_entry));
1217 // Special case for German ("DE") IBAN: Numeric only. Otherwise allow alpha-numeric
1218 if (acct_text[0] == 'D' && acct_text[1] == 'E')
1219 {
1220 allowed_characterclass = NUMERIC;
1221 }
1222 else
1223 {
1224 allowed_characterclass = ALNUM;
1225 }
1226 }
1227
1228 // Do the actual character class check. Alphas are only allowed in
1229 // uppercase, though.
1230 switch (allowed_characterclass)
1231 {
1232 case ALPHA:
1233 if (g_ascii_isalpha(c))
1234 g_string_append_c(result, g_ascii_toupper(c));
1235 break;
1236 case ALNUM:
1237 if (g_ascii_isalnum(c))
1238 g_string_append_c(result, g_ascii_toupper(c));
1239 break;
1240 case NUMERIC:
1241 if (g_ascii_isdigit(c))
1242 g_string_append_c(result, c);
1243 break;
1244 }
1245 }
1246 else
1247 {
1248 // Non-SEPA: Only accept digits.
1249 if (g_ascii_isdigit(c))
1250 {
1251 g_string_append_c(result, c);
1252 }
1253 }
1254 }
1255
1256 g_signal_handlers_block_by_func (editable,
1257 (gpointer) gnc_ab_trans_dialog_ibanentry_filter_cb, data);
1258 gtk_editable_insert_text (editable, result->str, result->len, position);
1259 g_signal_handlers_unblock_by_func (editable,
1260 (gpointer) gnc_ab_trans_dialog_ibanentry_filter_cb, data);
1261 g_signal_stop_emission_by_name (editable, "insert_text");
1262 g_string_free (result, TRUE);
1263}
1264
1265void
1266gnc_ab_trans_dialog_bicentry_filter_cb (GtkEditable *editable,
1267 const gchar *text,
1268 gint length,
1269 gint *position,
1270 gpointer data)
1271{
1272 GString* result = g_string_new(NULL);
1273 gint i;
1274 GncABTransDialog *td = data;
1275
1276 if (length == -1)
1277 length = strlen(text);
1278 g_assert(position);
1279
1280 /* Filter non digits */
1281 for (i = 0; i < length; i++)
1282 {
1283 gchar c = text[i];
1284
1285 if (gnc_ab_trans_isSEPA(td->trans_type))
1286 {
1287 // SEPA: Only alphas in the first 6 places (only upper case, though), then both upper-case alphas and digits
1288 if (*position + i < 6)
1289 {
1290 if (g_ascii_isalpha(c))
1291 g_string_append_c(result, g_ascii_toupper(c));
1292 }
1293 else
1294 {
1295 if (g_ascii_isalnum(c))
1296 g_string_append_c(result, g_ascii_toupper(c));
1297 }
1298 }
1299 else
1300 {
1301 // Non-SEPA: Only digits accepted.
1302 if (g_ascii_isdigit(c))
1303 {
1304 g_string_append_c(result, c);
1305 }
1306 }
1307 }
1308
1309 g_signal_handlers_block_by_func (editable,
1310 (gpointer) gnc_ab_trans_dialog_bicentry_filter_cb, data);
1311 gtk_editable_insert_text (editable, result->str, result->len, position);
1312 g_signal_handlers_unblock_by_func (editable,
1313 (gpointer) gnc_ab_trans_dialog_bicentry_filter_cb, data);
1314 g_signal_stop_emission_by_name (editable, "insert_text");
1315 g_string_free (result, TRUE);
1316}
Dialog for AqBanking transaction data.
AqBanking utility functions.
const gchar * gnc_ab_trans_templ_get_name(const GncABTransTempl *t)
GtkWidget * gnc_ab_trans_dialog_get_parent(const GncABTransDialog *td)
Retrieve the widget used as parent.
gnc_numeric gnc_ab_trans_templ_get_amount(const GncABTransTempl *t)
GncABTransDialog * gnc_ab_trans_dialog_new(GtkWidget *parent, GNC_AB_ACCOUNT_SPEC *ab_acc, gint commodity_scu, GncABTransType trans_type, GList *templates)
Create a new AqBanking transfer dialog.
GNC_AB_JOB * gnc_ab_trans_dialog_get_job(const GncABTransDialog *td)
Receive the Aqbanking job filled by the dialog.
const gchar * gnc_ab_trans_templ_get_recp_bankcode(const GncABTransTempl *t)
GncABTransTempl * gnc_ab_trans_templ_new_full(const gchar *name, const gchar *recp_name, const gchar *recp_account, const gchar *recp_bankcode, gnc_numeric amount, const gchar *purpose, const gchar *purpose_cont)
Create a template with given contents.
const gchar * gnc_ab_trans_templ_get_purpose(const GncABTransTempl *t)
void gnc_ab_trans_templ_free(GncABTransTempl *t)
Free the memory used by a template.
const gchar * gnc_ab_trans_templ_get_recp_account(const GncABTransTempl *t)
gint gnc_ab_trans_dialog_run_until_ok(GncABTransDialog *td)
Run the Aqbanking transfer dialog until correct values where entered or the user cancelled the dialog...
gchar * gnc_ab_get_purpose(const AB_TRANSACTION *ab_trans, gboolean is_ofx)
Retrieve the merged purpose fields from a transaction.
const AB_TRANSACTION * gnc_ab_trans_dialog_get_ab_trans(const GncABTransDialog *td)
Receive the Aqbanking Transaction filled by the dialog.
gchar * gnc_ab_get_remote_name(const AB_TRANSACTION *ab_trans)
Retrieve the merged "remote name" fields from a transaction.
const gchar * gnc_ab_trans_templ_get_recp_name(const GncABTransTempl *t)
void gnc_ab_trans_dialog_free(GncABTransDialog *td)
Free a Aqbanking transfer dialog.
const gchar * gnc_ab_trans_templ_get_purpose_cont(const GncABTransTempl *t)
gboolean gnc_ab_trans_isSEPA(GncABTransType t)
Returns true if the given GncABTransType is an European (SEPA) transaction (transfer or debit note),...
GNC_AB_JOB * gnc_ab_get_trans_job(GNC_AB_ACCOUNT_SPEC *ab_acc, const AB_TRANSACTION *ab_trans, GncABTransType trans_type)
Return the AqBanking job associated with the transaction.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272