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