hbci-interaction.c

00001 /* hbci-interaction.c
00002    Copyright 2002 by Christian Stimming <stimming@tuhh.de> */
00003 
00004 /***************************************************************************
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the Free Software   *
00018  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,            *
00019  *   MA  02110-1301  USA                                                   *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #include "config.h"
00024 
00025 #include <gtk/gtk.h>
00026 #include <glib/gi18n.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <locale.h>
00030 #include <iconv.h>
00031 #include <aqbanking/banking.h>
00032 #include <gwenhywfar/bio_buffer.h>
00033 #include <gwenhywfar/xml.h>
00034 
00035 #include "hbci-interaction.h"
00036 #include "hbci-interactionP.h"
00037 
00038 #include "dialog-utils.h"
00039 #include "druid-utils.h"
00040 #include "gnc-ui-util.h"
00041 #include "gnc-ui.h"
00042 #include "gnc-gconf-utils.h"
00043 #include "gnc-component-manager.h"
00044 #include "gnc-session.h"
00045 
00046 #include "dialog-pass.h"
00047 #include "gnc-hbci-utils.h"
00048 
00049 #include <aqbanking/version.h>
00050 #if AQBANKING_VERSION_MAJOR > 2
00051 # include <gwenhywfar/gui.h>
00052 # define AB_Banking_SetMessageBoxFn GWEN_Gui_SetMessageBoxFn
00053 # define AB_Banking_SetInputBoxFn GWEN_Gui_SetInputBoxFn
00054 # define AB_Banking_SetShowBoxFn GWEN_Gui_SetShowBoxFn
00055 # define AB_Banking_SetHideBoxFn GWEN_Gui_SetHideBoxFn
00056 # define AB_Banking_SetProgressStartFn GWEN_Gui_SetProgressStartFn
00057 # define AB_Banking_SetProgressAdvanceFn GWEN_Gui_SetProgressAdvanceFn
00058 # define AB_Banking_SetProgressLogFn GWEN_Gui_SetProgressLogFn
00059 # define AB_Banking_SetProgressEndFn GWEN_Gui_SetProgressEndFn
00060 # define AB_Banking_SetGetTanFn GWEN_Gui_SetGetTanFn
00061 # define AB_BANKING_MSG_FLAGS_TYPE_ERROR GWEN_GUI_MSG_FLAGS_TYPE_ERROR
00062 # define AB_BANKING_INPUT_FLAGS_CONFIRM GWEN_GUI_INPUT_FLAGS_CONFIRM
00063 # define AB_BANKING_INPUT_FLAGS_SHOW GWEN_GUI_INPUT_FLAGS_SHOW
00064 # define AB_BANKING_PROGRESS_NONE GWEN_GUI_PROGRESS_NONE
00065 # define AB_Banking_GetUserData(arg) GWEN_INHERIT_GETDATA(GWEN_GUI, GNCInteractor, arg)
00066 # define AB_Banking_SetUserData(arg1, arg2)
00067 /* Note about other changes: Replace callback object AB_BANKING by
00068    GWEN_GUI, to be created by GWEN_GUI_new; replace GetTan
00069    callback by watching for INPUT_FLAGS_TAN in InputBox(). */
00070 #endif
00071 
00072 GWEN_INHERIT(AB_BANKING, GNCInteractor)
00073 
00074 #define GCONF_SECTION_CONNECTION GCONF_SECTION "/connection_dialog"
00075 #define DIALOG_HBCILOG_CM_CLASS "dialog-hbcilog"
00076 
00077 gchar *gnc__extractText(const char *text);
00078 static void cm_close_handler(gpointer user_data);
00079 
00081 GNCInteractor *gnc_AB_BANKING_interactors (AB_BANKING *api, GtkWidget *parent)
00082 {
00083   GNCInteractor *data;
00084   gint component_id;
00085   
00086   data = g_new0 (GNCInteractor, 1);
00087   data->parent = parent;
00088   /* FIXME: The internal target encoding is hard-coded so far. This
00089      needs to be fixed for the gnome2 version; the target encoding is
00090      then probably utf-8 as well. iconv is also used in
00091      gnc_hbci_descr_tognc() in gnc-hbci-utils.c. */
00092   data->gnc_iconv_handler = 
00093     g_iconv_open(gnc_hbci_book_encoding(), gnc_hbci_AQBANKING_encoding());
00094   g_assert(data->gnc_iconv_handler != (GIConv)(-1));
00095   data->keepAlive = TRUE;
00096   data->cache_pin = 
00097     gnc_gconf_get_bool(GCONF_SECTION, KEY_REMEMBER_PIN, NULL);
00098   data->showbox_id = 1;
00099   data->showbox_hash = g_hash_table_new(NULL, NULL); 
00100   data->min_loglevel = AB_Banking_LogLevelVerbous;
00101 
00102   component_id = gnc_register_gui_component(DIALOG_HBCILOG_CM_CLASS,
00103                                             NULL, cm_close_handler,
00104                                             data);
00105   gnc_gui_component_set_session(component_id, gnc_get_current_session());
00106 
00107   /* set HBCI_Interactor */
00108   gnc_hbci_add_callbacks(api, data);
00109   return data;
00110 }
00111 
00112 void GNCInteractor_delete(GNCInteractor *data)
00113 {
00114   if (data == NULL)
00115     return;
00116   if (data->dialog != NULL) {
00117     gnc_gconf_set_bool(GCONF_SECTION, KEY_CLOSE_ON_FINISH,
00118                        gtk_toggle_button_get_active 
00119                        (GTK_TOGGLE_BUTTON (data->close_checkbutton)),
00120                        NULL);
00121     gnc_save_window_size(GCONF_SECTION_CONNECTION, GTK_WINDOW (data->dialog));
00122     g_object_unref (G_OBJECT (data->dialog));
00123     gtk_widget_destroy (data->dialog);
00124   }
00125   
00126   gnc_unregister_gui_component_by_data(DIALOG_HBCILOG_CM_CLASS, data);
00127 
00128   data->dialog = NULL;
00129 
00130   g_hash_table_destroy(data->showbox_hash);
00131   g_iconv_close(data->gnc_iconv_handler);
00132 
00133   g_free (data);
00134 }
00135 
00136 
00137 
00138 /* ************************************************************
00139  */
00140 
00141 
00142 GtkWidget *GNCInteractor_parent(const GNCInteractor *i)
00143 {
00144   g_assert(i);
00145   return i->parent;
00146 }
00147 
00148 GtkWidget *GNCInteractor_dialog(const GNCInteractor *i)
00149 {
00150   g_assert(i);
00151   return i->dialog;
00152 }
00153 
00154 static void GNCInteractor_setRunning (GNCInteractor *data)
00155 {
00156   g_assert(data);
00157   data->state = RUNNING;
00158   gtk_widget_set_sensitive (GTK_WIDGET (data->abort_button), TRUE);
00159   gtk_widget_set_sensitive (GTK_WIDGET (data->close_button), FALSE);
00160   data->keepAlive = TRUE;
00161 }
00162 static void GNCInteractor_setFinished (GNCInteractor *data)
00163 {
00164   g_assert(data);
00165   data->state = FINISHED;
00166   gtk_widget_set_sensitive (GTK_WIDGET (data->abort_button), FALSE);
00167   gtk_widget_set_sensitive (GTK_WIDGET (data->close_button), TRUE);
00168   if (gtk_toggle_button_get_active
00169       (GTK_TOGGLE_BUTTON (data->close_checkbutton)))
00170     GNCInteractor_hide (data);
00171 }
00172 static void GNCInteractor_setAborted (GNCInteractor *data)
00173 {
00174   g_assert(data);
00175   data->state = ABORTED;
00176   gtk_widget_set_sensitive (GTK_WIDGET (data->abort_button), FALSE);
00177   gtk_widget_set_sensitive (GTK_WIDGET (data->close_button), TRUE);
00178   data->keepAlive = FALSE;
00179 }
00180 
00181 
00182 gboolean GNCInteractor_aborted(const GNCInteractor *i)
00183 {
00184   g_assert(i);
00185   return !(i->keepAlive);
00186 }
00187 
00188 void GNCInteractor_show_nodelete(GNCInteractor *i)
00189 {
00190   gboolean cache_pin = 
00191     gnc_gconf_get_bool(GCONF_SECTION, KEY_REMEMBER_PIN, NULL);
00192   g_assert(i);
00193   /* Show widgets */
00194   gtk_widget_show_all (i->dialog);
00195 
00196   /* Make sure the cache_pin option is up to date. */
00197   if (cache_pin != i->cache_pin) {
00198     /* AB_Banking_SetEnablePinCaching (ab, cache_pin); */
00199     i->cache_pin = cache_pin;
00200     if (cache_pin == FALSE)
00201       GNCInteractor_erasePIN (i);
00202   }
00203 }
00204 void GNCInteractor_show(GNCInteractor *i)
00205 {
00206   g_assert(i);
00207   GNCInteractor_show_nodelete(i);
00208   /* Clear log window. */
00209   gtk_text_buffer_set_text
00210     (gtk_text_view_get_buffer (GTK_TEXT_VIEW (i->log_text) ),
00211      "", 0);
00212 }
00213 
00214 
00215 void GNCInteractor_hide(GNCInteractor *i)
00216 {
00217   g_assert(i);
00218   if (gtk_toggle_button_get_active 
00219       (GTK_TOGGLE_BUTTON (i->close_checkbutton)))
00220     gtk_widget_hide_all (i->dialog);
00221   gnc_gconf_set_bool(GCONF_SECTION, KEY_CLOSE_ON_FINISH,
00222                      gtk_toggle_button_get_active 
00223                      (GTK_TOGGLE_BUTTON (i->close_checkbutton)),
00224                      NULL);
00225   gnc_save_window_size(GCONF_SECTION_CONNECTION, GTK_WINDOW (i->dialog));
00226 }
00227 
00228 gboolean GNCInteractor_get_cache_valid(const GNCInteractor *i)
00229 {
00230   g_assert(i);
00231   return i->cache_pin;
00232 }
00233 void GNCInteractor_set_cache_valid(GNCInteractor *i, gboolean value)
00234 {
00235   g_assert(i);
00236   /* Nothing to be done right now. */
00237 }
00238 
00239 void GNCInteractor_erasePIN(GNCInteractor *i)
00240 {
00241   g_assert(i);
00242   /* Nothing to be done right now. */
00243 }
00244 void GNCInteractor_reparent (GNCInteractor *i, GtkWidget *new_parent)
00245 {
00246   g_assert (i);
00247   if (new_parent != i->parent)
00248     {
00249       i->parent = new_parent;
00250       /*if (GTK_WIDGET (i->dialog) -> parent != NULL)
00251         gtk_widget_reparent (GTK_WIDGET (i->dialog), new_parent);
00252         else
00253         gtk_widget_set_parent (GTK_WIDGET (i->dialog), new_parent);*/
00254       gtk_window_set_transient_for (GTK_WINDOW (i->dialog), 
00255                                GTK_WINDOW (new_parent));
00256     }
00257 }
00258 
00259 gboolean GNCInteractor_hadErrors (const GNCInteractor *i)
00260 {
00261   g_assert (i);
00262   return (i->msgBoxError != 0);
00263 }
00264 
00265 gboolean GNCInteractor_errorsLogged (const GNCInteractor *i)
00266 {
00267   g_assert (i);
00268   /* Note: Unfortunately this does not mean at all that there actually
00269      has been any error. Old aqbanking versions had some debugging
00270      messages set at "error" level, and there can also be errors when
00271      closing connection that don't affect the job result at all. */
00272   return (i->min_loglevel < AB_Banking_LogLevelNotice);
00273 }
00274 
00275 /* ************************************************************ 
00276  */
00277 
00278 /* This function extracts the normal text part out of the
00279    combi-strings that are passed from aqbanking. */
00280 gchar *gnc__extractText(const char *text) 
00281 {
00282   gchar *res;
00283   GWEN_BUFFEREDIO *bio;
00284   GWEN_XMLNODE *xmlNode;
00285   GWEN_BUFFER *buf;
00286   int rv;
00287 
00288   if (!text)
00289     text = "";
00290 
00291   buf=GWEN_Buffer_new(0, 256, 0, 1);
00292   GWEN_Buffer_AppendString(buf, text);
00293   GWEN_Buffer_Rewind(buf);
00294 
00295   /* check whether there is a html tag */
00296   bio=GWEN_BufferedIO_Buffer2_new(buf, 1);
00297   GWEN_BufferedIO_SetReadBuffer(bio, 0, 256);
00298   xmlNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "html");
00299   rv=GWEN_XML_Parse(xmlNode, bio,
00300                     GWEN_XML_FLAGS_DEFAULT |
00301                     GWEN_XML_FLAGS_HANDLE_OPEN_HTMLTAGS |
00302                     GWEN_XML_FLAGS_NO_CONDENSE |
00303                     GWEN_XML_FLAGS_KEEP_CNTRL);
00304   GWEN_BufferedIO_Close(bio);
00305   GWEN_BufferedIO_free(bio);
00306 
00307   if (rv) {
00308     res = g_strdup(text);
00309   }
00310   else {
00311     GWEN_XMLNODE *nn;
00312 
00313     nn=GWEN_XMLNode_GetFirstData(xmlNode);
00314     if (nn) {
00315       res = g_strdup(GWEN_XMLNode_GetData(nn));
00316     }
00317     else {
00318       res = g_strdup(text);
00319     }
00320   }
00321   GWEN_XMLNode_free(xmlNode);
00322   return res;
00323 }
00324 
00325 
00326 char *gnc_hbci_utf8ToLatin1(GNCInteractor *data, const char *utf)
00327 {
00328   char *utf8extracted, *latin1;
00329 
00330   g_assert(data);
00331   if (!utf) return g_strdup("");
00332 
00333   /* Get rid of the aaaarg html-combi-text part */
00334   utf8extracted = gnc__extractText(utf);
00335 /*   printf("Extracted \"%s\" into \"%s\"\n", utf, utf8extracted); */
00336 
00337   latin1 = gnc_call_iconv(data->gnc_iconv_handler, utf8extracted);
00338 
00339 /*   printf("Converted \"%s\" into \"%s\"\n", utf8extracted, latin1); */
00340   g_free(utf8extracted);
00341   return latin1;
00342 }
00343 
00344 /********************************************************
00345  * Now all the callback functions 
00346  */
00347 
00348 static int inputBoxCB(AB_BANKING *ab,
00349                       GWEN_TYPE_UINT32 flags,
00350                       const char *utf8title,
00351                       const char *utf8text,
00352                       char *resultbuffer,
00353                       int minsize,
00354                       int maxLen)
00355 {
00356   GNCInteractor *data;
00357   char *passwd = NULL;
00358   int retval = 0;
00359   int newPin;
00360   int hideInput;
00361   gchar *title, *text;
00362 
00363   g_assert(ab);
00364   data = AB_Banking_GetUserData(ab);
00365   g_assert(data);
00366   g_assert(maxLen > minsize);
00367   data->msgBoxError = flags & AB_BANKING_MSG_FLAGS_TYPE_ERROR;
00368 
00369   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00370   title = gnc_hbci_utf8ToLatin1(data, utf8title);
00371 
00372   newPin = (flags | AB_BANKING_INPUT_FLAGS_CONFIRM) == 0;
00373   hideInput = (flags | AB_BANKING_INPUT_FLAGS_SHOW) != 0;
00374 
00375   while (TRUE) {
00376 
00377     if (newPin) {
00378       if (!hideInput)
00379         g_warning("inputBoxCB: Oops, hideInput==false and newPin==true, i.e. the input is supposed to be readable -- not implemented (since I thought this does not make sense when entering a new PIN).\n");
00380       retval = gnc_hbci_get_initial_password (data->parent,
00381                                               title,
00382                                               text,
00383                                               &passwd);
00384     }
00385     else {
00386       retval = gnc_hbci_get_password (data->parent,
00387                                       title,
00388                                       text,
00389                                       NULL,
00390                                       &passwd,
00391                                       hideInput);
00392     } /* newPin */
00393     
00394     if (!retval)
00395       break;
00396     
00397     g_assert(passwd);
00398     if (strlen(passwd) < (unsigned int)minsize) {
00399       gboolean retval;
00400       char *msg = 
00401         g_strdup_printf (  _("The PIN needs to be at least %d characters "
00402                              "long. Do you want to try again?"),
00403                            minsize);
00404       retval = gnc_verify_dialog (GTK_WIDGET (data->parent), 
00405                                            TRUE,
00406                                            "%s", msg);
00407       g_free (msg);
00408       if (!retval)
00409         break;
00410     }
00411     else if (strlen(passwd) >= (unsigned int)maxLen) {
00412       gboolean retval;
00413       char *msg = 
00414         g_strdup_printf (  _("You entered %ld characters, but the PIN must "
00415                              "be no longer than %d characters. "
00416                              "Do you want to try again?"),
00417                            (long)strlen(passwd), maxLen);
00418       retval = gnc_verify_dialog (GTK_WIDGET (data->parent), 
00419                                            TRUE,
00420                                            "%s", msg);
00421       g_free (msg);
00422       if (!retval)
00423         break;
00424     }
00425     else {
00426       g_assert (maxLen > strlen(passwd)); /* assertion was queried above */
00427       strcpy(resultbuffer, passwd);
00428       g_free (memset (passwd, 0, strlen (passwd)));
00429       g_free(title);
00430       g_free(text);
00431       return 0;
00432     }
00433   }
00434   
00435   /* User wanted to abort. */
00436   g_free(title);
00437   g_free(text);
00438   return 1;
00439 }
00440 
00441 /* **************************************** 
00442  */
00443 
00444 
00445 static int getTanCB(AB_BANKING *ab,
00446                     const char *token,
00447                     const char *utf8title,
00448                     const char *utf8text,
00449                     char *resultbuffer,
00450                     int minsize,
00451                     int maxLen)
00452 {
00453   GNCInteractor *data;
00454   char *passwd = NULL;
00455   int retval = 0;
00456   gchar *title, *text;
00457 
00458   g_assert(ab);
00459   data = AB_Banking_GetUserData(ab);
00460   g_assert(data);
00461   g_assert(maxLen > minsize);
00462   data->msgBoxError = 0;
00463 
00464   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00465   title = gnc_hbci_utf8ToLatin1(data, utf8title);
00466 
00467   while (TRUE) {
00468 
00469     retval = gnc_hbci_get_password (data->parent,
00470                                     title,
00471                                     text,
00472                                     NULL,
00473                                     &passwd,
00474                                     FALSE);
00475 
00476     if (!retval)
00477       break;
00478     
00479     if (strlen(passwd) < (unsigned int)minsize) {
00480       gboolean retval;
00481       char *msg = 
00482         g_strdup_printf (  _("This TAN needs to be at least %d characters "
00483                              "long. Do you want to try again?"),
00484                            minsize);
00485       retval = gnc_verify_dialog (GTK_WIDGET (data->parent), 
00486                                            TRUE,
00487                                            "%s", msg);
00488       g_free (msg);
00489       if (!retval)
00490         break;
00491     }
00492     else if (strlen(passwd) >= (unsigned int)maxLen) {
00493       gboolean retval;
00494       char *msg = 
00495         g_strdup_printf (  _("You entered %ld characters, but the TAN must "
00496                              "be no longer than %d characters. "
00497                              "Do you want to try again?"),
00498                            (long)strlen(passwd), maxLen);
00499       retval = gnc_verify_dialog (GTK_WIDGET (data->parent), 
00500                                            TRUE,
00501                                            "%s", msg);
00502       g_free (msg);
00503       if (!retval)
00504         break;
00505     }
00506     else {
00507       g_assert (maxLen > strlen(passwd)); /* assertion was queried above */
00508       strcpy(resultbuffer, passwd);
00509 
00510       g_free (memset (passwd, 0, strlen (passwd)));
00511       g_free(title);
00512       g_free(text);
00513       return 0;
00514     }
00515   }
00516   
00517   /* User wanted to abort. */
00518   g_free(title);
00519   g_free(text);
00520   return 1;
00521 }
00522 
00523 
00524 /* ************************************************************ 
00525  */
00526 
00527 static int keepAlive(void *user_data)
00528 {
00529   GNCInteractor *data = user_data;
00530   GMainContext *context;
00531 
00532   g_assert(data);
00533   /*fprintf(stdout, "my-keepAlive: returning 1\n");*/
00534 
00535   /* Let the widgets be redrawn */
00536   context = g_main_context_default();
00537   while (g_main_context_iteration(context, FALSE));
00538 
00539   return data->keepAlive;
00540 }
00541 
00542 
00543 #ifndef GWENHYWFAR_CB
00544 /* Has been introduced in gwenhywfar>=2.4.1 for callback function
00545    decoration on win32, but is empty everywhere else. */
00546 # define GWENHYWFAR_CB
00547 #endif
00548 static void GWENHYWFAR_CB destr(void *bp, void *user_data)
00549 {
00550   GNCInteractor *data = user_data;
00551   if (data == NULL)
00552     return;
00553 
00554   GNCInteractor_delete (data);
00555 }
00556 
00557 
00558 /* ************************************************************ 
00559  */
00560 
00561 static void 
00562 hideBoxCB(AB_BANKING *ab, GWEN_TYPE_UINT32 id)
00563 {
00564   GNCInteractor *data;
00565   GtkWidget *dialog;
00566   g_assert(ab);
00567   data = AB_Banking_GetUserData(ab);
00568   g_assert(data);
00569 
00570   if (id > 0) {
00571     dialog = g_hash_table_lookup(data->showbox_hash, GUINT_TO_POINTER(id));
00572   } else {
00573     dialog = data->showbox_last;
00574   }
00575   if (dialog) {
00576     gtk_widget_hide (dialog);
00577     gtk_widget_destroy (dialog);
00578     g_hash_table_remove(data->showbox_hash, GUINT_TO_POINTER(id));
00579   }
00580 }
00581 
00582 static GWEN_TYPE_UINT32
00583 showBoxCB(AB_BANKING *ab, GWEN_TYPE_UINT32 flags,
00584           const char *utf8title, const char *utf8text)
00585 {
00586   GtkWidget *dialog;
00587   GNCInteractor *data;
00588   GWEN_TYPE_UINT32 result;
00589   gchar *title, *text;
00590 
00591   g_assert(ab);
00592   data = AB_Banking_GetUserData(ab);
00593   g_assert(data);
00594   data->msgBoxError = flags & AB_BANKING_MSG_FLAGS_TYPE_ERROR;
00595   
00596   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00597   title = gnc_hbci_utf8ToLatin1(data, utf8title);
00598 
00599   /* Create new dialog */
00600   dialog = gtk_message_dialog_new(GTK_WINDOW(data->parent),
00601                                   0,
00602                                   GTK_MESSAGE_INFO,
00603                                   GTK_BUTTONS_OK,
00604                                   "%s", text);
00605 
00606   if (title && (strlen(title) > 0))
00607     gtk_window_set_title (GTK_WINDOW (dialog), title);
00608 
00609   g_signal_connect(G_OBJECT(dialog), "response",
00610                    (GCallback)gtk_widget_hide, NULL);
00611   gtk_widget_show_all (dialog);
00612 
00613   result = data->showbox_id;
00614   g_hash_table_insert(data->showbox_hash, GUINT_TO_POINTER(result), dialog);
00615   data->showbox_id++;
00616   data->showbox_last = dialog;
00617 
00618   g_free(title);
00619   g_free(text);
00620   return result;
00621 }
00622 
00623 /* ************************************************************ 
00624  */
00625 
00626 static int messageBoxCB(AB_BANKING *ab, GWEN_TYPE_UINT32 flags, 
00627                         const char *utf8title, const char *utf8text, 
00628                         const char *b1, const char *b2, const char *b3)
00629 {
00630   GNCInteractor *data;
00631   GtkWidget *dialog, *label;
00632   int result;
00633   gchar *text, *title, *b1text, *b2text, *b3text;
00634 
00635   g_assert(ab);
00636   data = AB_Banking_GetUserData(ab);
00637   g_assert(data);
00638   data->msgBoxError = flags & AB_BANKING_MSG_FLAGS_TYPE_ERROR;
00639 
00640   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00641   title = gnc_hbci_utf8ToLatin1(data, utf8title);
00642   b1text = gnc_hbci_utf8ToLatin1(data, b1);
00643   b2text = gnc_hbci_utf8ToLatin1(data, b2);
00644   b3text = gnc_hbci_utf8ToLatin1(data, b3);
00645 
00646   dialog = gtk_dialog_new_with_buttons (title, 
00647                                         GTK_WINDOW (data->parent),
00648                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
00649                                         b1 ? b1text : NULL,
00650                                         1,
00651                                         b2 ? b2text : NULL,
00652                                         2,
00653                                         b3 ? b3text : NULL,
00654                                         3,
00655                                         NULL);
00656   /* Add the label, and show everything we've added to the dialog. */
00657   label = gtk_label_new (text);
00658   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
00659   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
00660                      label);
00661   gtk_widget_show_all (dialog);
00662 
00663   result = gtk_dialog_run (GTK_DIALOG (dialog));
00664   gtk_widget_destroy (dialog);
00665   if (result<1 || result>3) {
00666     g_warning("messageBoxCB: Bad result %d", result);
00667     result = 0;
00668   }
00669   g_free(title);
00670   g_free(text);
00671   g_free(b1text);
00672   g_free(b2text);
00673   g_free(b3text);
00674   return result;
00675 }
00676 
00677 
00678 /* ************************************************************ 
00679  */
00680 
00681 #define progress_id 4711
00682 
00683 static GWEN_TYPE_UINT32 progressStartCB(AB_BANKING *ab, const char *utf8title, 
00684                                         const char *utf8text, GWEN_TYPE_UINT32 total)
00685 {
00686   GNCInteractor *data;
00687   gchar *title, *text;
00688 
00689   g_assert(ab);
00690   data = AB_Banking_GetUserData(ab);
00691   g_assert(data);
00692   
00693   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00694   title = gnc_hbci_utf8ToLatin1(data, utf8title);
00695 
00696   /* Now set the text etc */
00697   gtk_entry_set_text (GTK_ENTRY (data->job_entry), title);
00698   gtk_entry_set_text (GTK_ENTRY (data->action_entry), text);
00699 
00700   /*   printf("progressLogCB: Logging msg: %s\n", text); */
00701   /*   GNCInteractor_add_log_text (data, text); */
00702 
00703   /* Set progress bar */
00704   gtk_widget_set_sensitive (data->action_progress, TRUE);
00705   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(data->action_progress), 0.0);
00706   data->action_max = total;
00707   GNCInteractor_setRunning(data);
00708   /* printf("progressStartCB: Action \"%s\" started, total %d.\n",
00709      text, total); */
00710 
00711   /* Show the dialog */
00712   GNCInteractor_show(data);
00713 
00714   /* Initialize loglevel caching */
00715   data->min_loglevel = AB_Banking_LogLevelVerbous;
00716 
00717   g_free(title);
00718   g_free(text);
00719   return progress_id;
00720 }
00721 
00722 static int progressAdvanceCB(AB_BANKING *ab, GWEN_TYPE_UINT32 id, 
00723                              GWEN_TYPE_UINT32 progress)
00724 {
00725   GNCInteractor *data;
00726 
00727   g_assert(ab);
00728   data = AB_Banking_GetUserData(ab);
00729   g_assert(data);
00730 
00731   if ((id != 0) && (id != progress_id)) {
00732 /*     printf("progressLogCB: Oops, wrong progress id %d -- ignored.\n", id); */
00733   }
00734 
00735   if (progress != AB_BANKING_PROGRESS_NONE) {
00736     /* printf("progressLogCB: Progress set to %d out of %f.\n", 
00737        progress, data->action_max); */
00738     if (progress <= data->action_max) 
00739       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (data->action_progress),
00740                                      progress/data->action_max);
00741   }
00742 
00743   return !keepAlive(data);
00744 }
00745 
00746 
00747 static int progressLogCB(AB_BANKING *ab, GWEN_TYPE_UINT32 id, 
00748                          AB_BANKING_LOGLEVEL level, const char *utf8text)
00749 {
00750   GNCInteractor *data;
00751   gchar *text;
00752 
00753   g_assert(ab);
00754   data = AB_Banking_GetUserData(ab);
00755   g_assert(data);
00756 
00757   text = gnc_hbci_utf8ToLatin1(data, utf8text);
00758 
00759   if ((id != 0) && (id != progress_id)) {
00760 /*     printf("progressLogCB: Oops, wrong progress id %d -- ignored.\n", id); */
00761   }
00762 
00763   /* printf("progressLogCB: Logging msg: %s\n", text); */
00764   GNCInteractor_add_log_text (data, text);
00765 
00766   /* Cache loglevel */
00767   if (level < data->min_loglevel)
00768     data->min_loglevel = level;
00769 
00770   g_free(text);
00771   return !keepAlive(data);
00772 }
00773 
00774 static int progressEndCB(AB_BANKING *ab, GWEN_TYPE_UINT32 id)
00775 {
00776   GNCInteractor *data;
00777   g_assert(ab);
00778   data = AB_Banking_GetUserData(ab);
00779   g_assert(data);
00780 
00781   if ((id != 0) && (id != progress_id)) {
00782 /*     printf("progressLogCB: Oops, wrong progress id %d -- ignored.\n", id); */
00783   }
00784 
00785   GNCInteractor_setFinished(data);
00786 
00787   keepAlive(data);
00788   return 0;
00789 }
00790 
00791 
00792 
00793 /* ************************************************************ 
00794  */
00795 
00796 int debug_pmonitor = FALSE;
00797 void GNCInteractor_add_log_text (GNCInteractor *data, const char *msg)
00798 {
00799   GtkTextBuffer *tb;
00800   GtkTextView *tv;
00801   g_assert(data);
00802 
00803   tv = GTK_TEXT_VIEW (data->log_text);
00804   tb = gtk_text_view_get_buffer (tv);
00805   gtk_text_buffer_insert_at_cursor (tb, msg, -1);
00806   gtk_text_buffer_insert_at_cursor (tb, "\n", -1);
00807   /* and scroll to the end of the buffer */
00808   gtk_text_view_scroll_to_mark (tv, gtk_text_buffer_get_insert (tb),
00809                                 0.0, FALSE, 0.0, 0.0);
00810 }
00811 
00812 static void
00813 on_button_clicked (GtkButton *button,
00814                    gpointer user_data)
00815 {
00816   GNCInteractor *data = user_data;
00817   GMainContext *context;
00818   const char *name;
00819   g_assert(data);
00820   
00821   name = gtk_widget_get_name (GTK_WIDGET (button));
00822   if (strcmp (name, "abort_button") == 0) {
00823     GNCInteractor_setAborted(data);
00824   } else if (strcmp (name, "close_button") == 0) {
00825     if (data->state != RUNNING) {
00826       gtk_widget_hide_all (data->dialog); 
00827       /*data->dont_hide = FALSE;*/
00828       /*GNCInteractor_hide (data);*/
00829     }
00830   } else {
00831     g_critical("on_button_clicked: Oops, unknown button: %s\n",
00832            name);
00833   }
00834   /* Let the widgets be redrawn */
00835   context = g_main_context_default();
00836   while (g_main_context_iteration(context, FALSE));
00837 }
00838 
00839 static void
00840 cm_close_handler(gpointer user_data)
00841 {
00842   GNCInteractor *data = user_data;
00843 
00844   GNCInteractor_setAborted(data);
00845   /* Notes about correctly handling this ComponentManager close event:
00846      We can't actually close the dialog here because AqBanking might
00847      still be running and expecting the GNCInteractor object to exist
00848      (and it doesn't offer any handlers for aborting from here). This
00849      is not per se a problem with gnucash objects because as soon as
00850      AqBanking received the SetAborted signal, it will abort and not
00851      deliver any actual results, which means the gnc-hbci module will
00852      not continue any operation. 
00853 
00854      However, the dialog and the AB_BANKING object will still be
00855      around. It is unclear whether this is 1. correct or 2. wrong:
00856      1. It might be correct because a user might still want to see the
00857      log messages in the window until he manually closes the
00858      GNCInteractor. 2. It might be wrong because once we've received
00859      the close event, nobody wants to see the GNCInteractor log
00860      messages anyway. To implement the behaviour #2, we should add a
00861      new flag in GNCInteractor that is being queried in
00862      gnc_AB_BANKING_execute() right after AB_Banking_ExecuteQueue()
00863      has finished, and if it is activated from the cm_close_handler,
00864      gnc_AB_BANKING_execute should immediately delete the AB_BANKING
00865      object (which will also delete the GNCInteractor object) and
00866      abort.
00867   */
00868 }
00869 
00870 
00871 /********************************************************
00872  * Constructor 
00873  */
00874 void
00875 gnc_hbci_add_callbacks(AB_BANKING *ab, GNCInteractor *data)
00876 {
00877   GtkWidget *dialog;
00878   GladeXML *xml;
00879 
00880   /* Create the progress dialog window */
00881   xml = gnc_glade_xml_new ("hbci.glade", "HBCI_connection_dialog");
00882 
00883   g_assert ((dialog = glade_xml_get_widget (xml, "HBCI_connection_dialog")) != NULL);
00884   data->dialog = dialog;
00885   g_assert ((data->job_entry = glade_xml_get_widget (xml, "job_entry")) != NULL);
00886   g_assert ((data->action_entry = glade_xml_get_widget (xml, "action_entry")) != NULL);
00887   g_assert ((data->action_progress = 
00888              glade_xml_get_widget (xml, "action_progress")) != NULL);
00889   g_assert ((data->log_text = glade_xml_get_widget (xml, "log_text")) != NULL);
00890   g_assert ((data->abort_button = glade_xml_get_widget (xml, "abort_button")) != NULL);
00891   gtk_widget_set_sensitive (GTK_WIDGET (data->abort_button), FALSE);
00892   g_assert ((data->close_button = glade_xml_get_widget (xml, "close_button")) != NULL);
00893   g_assert ((data->close_checkbutton = 
00894              glade_xml_get_widget (xml, "close_checkbutton")) != NULL);
00895 
00896   /* grey out the progress bar -- its unused at the moment */
00897   gtk_widget_set_sensitive (data->action_progress, FALSE);
00898   gtk_toggle_button_set_active 
00899     (GTK_TOGGLE_BUTTON (data->close_checkbutton), 
00900      gnc_gconf_get_bool(GCONF_SECTION, KEY_CLOSE_ON_FINISH, NULL));
00901 
00902   g_signal_connect (data->abort_button, "clicked", 
00903                     G_CALLBACK (on_button_clicked), data);
00904   g_signal_connect (data->close_button, "clicked", 
00905                     G_CALLBACK (on_button_clicked), data);
00906 
00907   if (data->parent)
00908     gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->parent));
00909   gnc_restore_window_size(GCONF_SECTION_CONNECTION, GTK_WINDOW (dialog));
00910 
00911   g_object_ref (G_OBJECT (dialog));
00912   gtk_widget_hide_all (dialog);
00913 
00914   GWEN_INHERIT_SETDATA(AB_BANKING, GNCInteractor,
00915                        ab, data,
00916                        &destr);
00917 
00918   AB_Banking_SetMessageBoxFn(ab, messageBoxCB);
00919   AB_Banking_SetInputBoxFn(ab, inputBoxCB);
00920   AB_Banking_SetShowBoxFn(ab, showBoxCB);
00921   AB_Banking_SetHideBoxFn(ab, hideBoxCB);
00922   AB_Banking_SetProgressStartFn(ab, progressStartCB);
00923   AB_Banking_SetProgressAdvanceFn(ab, progressAdvanceCB);
00924   AB_Banking_SetProgressLogFn(ab, progressLogCB);
00925   AB_Banking_SetProgressEndFn(ab, progressEndCB);
00926 
00927   /* AB_Banking_SetGetPinFn(ab,); */
00928   AB_Banking_SetGetTanFn(ab, getTanCB);
00929 
00930   AB_Banking_SetUserData(ab, data);
00931 
00932 }

Generated on Tue Oct 14 05:04:54 2008 for GnuCash by  doxygen 1.5.2