GnuCash 2.4.99
import-main-matcher.c
00001 /********************************************************************\
00002  * import-main-matcher.c - Transaction matcher main window          *
00003  *                                                                  *
00004  * Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca>        *
00005  * Copyright (C) 2002 Christian Stimming                            *
00006  * Copyright (c) 2006 David Hampton <hampton@employees.org>         *
00007  * Copyright (C) 2012 Robert Fewell                                 *
00008  *                                                                  *
00009  * This program is free software; you can redistribute it and/or    *
00010  * modify it under the terms of the GNU General Public License as   *
00011  * published by the Free Software Foundation; either version 2 of   *
00012  * the License, or (at your option) any later version.              *
00013  *                                                                  *
00014  * This program is distributed in the hope that it will be useful,  *
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00017  * GNU General Public License for more details.                     *
00018  *                                                                  *
00019  * You should have received a copy of the GNU General Public License*
00020  * along with this program; if not, contact:                        *
00021  *                                                                  *
00022  * Free Software Foundation           Voice:  +1-617-542-5942       *
00023  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00024  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00025 \********************************************************************/
00035 #include "config.h"
00036 
00037 #include <gtk/gtk.h>
00038 #include <glib/gi18n.h>
00039 
00040 #include "import-main-matcher.h"
00041 
00042 #include "dialog-utils.h"
00043 #include "gnc-ui.h"
00044 #include "gnc-ui-util.h"
00045 #include "gnc-engine.h"
00046 #include "import-settings.h"
00047 #include "import-match-map.h"
00048 #include "import-match-picker.h"
00049 #include "import-backend.h"
00050 #include "import-account-matcher.h"
00051 
00052 #define GCONF_SECTION "dialogs/import/generic_matcher/transaction_list"
00053 
00054 struct _main_matcher_info
00055 {
00056     GtkWidget *dialog;
00057     GtkWidget *assistant;
00058     GtkTreeView *view;
00059     GNCImportSettings *user_settings;
00060     GdkColor color_back_red;
00061     GdkColor color_back_green;
00062     GdkColor color_back_yellow;
00063     int selected_row;
00064     GNCTransactionProcessedCB transaction_processed_cb;
00065     gpointer user_data;
00066 };
00067 
00068 enum downloaded_cols
00069 {
00070     DOWNLOADED_COL_DATE = 0,
00071     DOWNLOADED_COL_ACCOUNT,
00072     DOWNLOADED_COL_AMOUNT,
00073     DOWNLOADED_COL_DESCRIPTION,
00074     DOWNLOADED_COL_MEMO,
00075     DOWNLOADED_COL_ACTION_ADD,
00076     DOWNLOADED_COL_ACTION_CLEAR,
00077     DOWNLOADED_COL_ACTION_UPDATE,
00078     DOWNLOADED_COL_ACTION_INFO,
00079     DOWNLOADED_COL_ACTION_PIXBUF,
00080     DOWNLOADED_COL_DATA,
00081     DOWNLOADED_COL_COLOR,
00082     NUM_DOWNLOADED_COLS
00083 };
00084 
00085 #define COLOR_RED    "brown1"
00086 #define COLOR_YELLOW "gold"
00087 #define COLOR_GREEN  "DarkSeaGreen1"
00088 
00089 static QofLogModule log_module = GNC_MOD_IMPORT;
00090 
00091 void on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info);
00092 void on_matcher_cancel_clicked (GtkButton *button, gpointer user_data);
00093 void on_matcher_help_clicked (GtkButton *button, gpointer user_data);
00094 void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data);
00095 
00096 /* Local prototypes */
00097 static void
00098 automatch_store_transactions(GNCImportMainMatcher *info,
00099                              GtkTreeModel *model,
00100                              GtkTreeIter *iter,
00101                              GNCImportTransInfo *trans_info);
00102 static void
00103 refresh_model_row(GNCImportMainMatcher *gui, GtkTreeModel *model,
00104                   GtkTreeIter *iter, GNCImportTransInfo *info);
00105 
00106 void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
00107 {
00108     GtkTreeModel *model;
00109     GtkTreeIter iter;
00110     GNCImportTransInfo *trans_info;
00111 
00112     if (info == NULL)
00113         return;
00114 
00115     model = gtk_tree_view_get_model(info->view);
00116     if (gtk_tree_model_get_iter_first(model, &iter))
00117     {
00118         do
00119         {
00120             gtk_tree_model_get(model, &iter,
00121                                DOWNLOADED_COL_DATA, &trans_info,
00122                                -1);
00123 
00124             if (info->transaction_processed_cb)
00125             {
00126                 info->transaction_processed_cb(trans_info,
00127                                                FALSE,
00128                                                info->user_data);
00129             }
00130 
00131             gnc_import_TransInfo_delete(trans_info);
00132         }
00133         while (gtk_tree_model_iter_next (model, &iter));
00134     }
00135 
00136 
00137     if (!(info->dialog == NULL))
00138     {
00139         gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
00140         gnc_import_Settings_delete (info->user_settings);
00141         gtk_widget_destroy (GTK_WIDGET (info->dialog));
00142     }
00143     else
00144         gnc_import_Settings_delete (info->user_settings);
00145     g_free (info);
00146 }
00147 
00148 void
00149 on_matcher_ok_clicked (GtkButton *button,
00150                        GNCImportMainMatcher *info)
00151 {
00152     GtkTreeModel *model;
00153     GtkTreePath *path;
00154     GtkTreeRowReference *ref;
00155     GtkTreeIter iter;
00156     GNCImportTransInfo *trans_info;
00157     GSList *refs_list = NULL, *item;
00158 
00159     g_assert (info);
00160 
00161     /*   DEBUG ("Begin") */
00162 
00163     model = gtk_tree_view_get_model(info->view);
00164     if (!gtk_tree_model_get_iter_first(model, &iter))
00165         return;
00166 
00167     do
00168     {
00169         gtk_tree_model_get(model, &iter,
00170                            DOWNLOADED_COL_DATA, &trans_info,
00171                            -1);
00172 
00173         if (gnc_import_process_trans_item(NULL, trans_info))
00174         {
00175             path = gtk_tree_model_get_path(model, &iter);
00176             ref = gtk_tree_row_reference_new(model, path);
00177             refs_list = g_slist_append(refs_list, ref);
00178             gtk_tree_path_free(path);
00179 
00180             if (info->transaction_processed_cb)
00181             {
00182                 info->transaction_processed_cb(trans_info,
00183                                                TRUE,
00184                                                info->user_data);
00185             }
00186         }
00187         else
00188         {
00189             /* transaction skipped -> destroy
00190              * Otherwise temporary transactions remains visible if account is open
00191              * (see gnc_import_process_trans_item() case GNCImport_CLEAR) */
00192 /*FIXME            xaccTransDestroy(gnc_import_TransInfo_get_trans(trans_info));
00193             xaccTransCommitEdit(gnc_import_TransInfo_get_trans(trans_info)); */
00194         }
00195 
00196     }
00197     while (gtk_tree_model_iter_next (model, &iter));
00198 
00199     /* DEBUG ("Deleting") */
00200     /* DRH: Is this necessary. Isn't the call to trans_list_delete at
00201        the end of this routine going to destroy the entire list store
00202        anyway? */
00203 /*FIXME    for (item = refs_list; item; item = g_slist_next(item))
00204     {
00205         ref = item->data;
00206         path =  gtk_tree_row_reference_get_path(ref);
00207         if (gtk_tree_model_get_iter(model, &iter, path))
00208             gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
00209         gtk_tree_path_free(path);
00210         gtk_tree_row_reference_free(ref);
00211     }
00212     g_slist_free(refs_list); */
00213 
00214     gnc_gen_trans_list_delete (info);
00215     /* DEBUG ("End") */
00216 }
00217 
00218 void
00219 on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
00220 {
00221     GNCImportMainMatcher *info = user_data;
00222     gnc_gen_trans_list_delete (info);
00223 }
00224 
00225 void
00226 on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
00227 {
00228     GtkWidget *help_dialog = user_data;
00229 
00230     gtk_widget_destroy(help_dialog);
00231 }
00232 
00233 void
00234 on_matcher_help_clicked (GtkButton *button, gpointer user_data)
00235 {
00236     GNCImportMainMatcher *info = user_data;
00237     GtkBuilder *builder;
00238     GtkWidget *help_dialog, *box, *closebutton;
00239 
00240     builder = gtk_builder_new();
00241     gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer2");
00242     gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer3");
00243     gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer4");
00244     gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer5");
00245     gnc_builder_add_from_file (builder, "dialog-import.glade", "matcher_help");
00246 
00247     box = GTK_WIDGET(gtk_builder_get_object (builder, "red"));
00248     gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_red);
00249     box = GTK_WIDGET(gtk_builder_get_object (builder, "yellow"));
00250     gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_yellow);
00251     box = GTK_WIDGET(gtk_builder_get_object (builder, "green"));
00252     gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_green);
00253 
00254     help_dialog = GTK_WIDGET(gtk_builder_get_object (builder, "matcher_help"));
00255     gtk_window_set_transient_for(GTK_WINDOW(help_dialog),
00256                                  GTK_WINDOW(info->dialog));
00257 
00258     /* Connect the signals */
00259     gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
00260 
00261     g_object_unref(G_OBJECT(builder));
00262 
00263     gtk_widget_show(help_dialog);
00264 }
00265 
00266 static void
00267 run_account_picker_dialog (GNCImportMainMatcher *info,
00268                            GtkTreeModel *model,
00269                            GtkTreeIter *iter,
00270                            GNCImportTransInfo *trans_info)
00271 {
00272     Account *old_acc, *new_acc;
00273     gboolean ok_pressed;
00274     g_assert (trans_info);
00275     old_acc = gnc_import_TransInfo_get_destacc (trans_info);
00276     new_acc = gnc_import_select_account(info->dialog,
00277                                         NULL,
00278                                         TRUE,
00279                                         _("Destination account for the auto-balance split."),
00280                                         xaccTransGetCurrency(gnc_import_TransInfo_get_trans(trans_info)),
00281                                         ACCT_TYPE_NONE,
00282                                         old_acc,
00283                                         &ok_pressed);
00284     if (ok_pressed)
00285     {
00286         gnc_import_TransInfo_set_destacc (trans_info,
00287                                           new_acc,
00288                                           TRUE);
00289 
00290         /* Iterate through the transactions in a given clist to auto match them */
00291         automatch_store_transactions(info, model, iter, trans_info);
00292     }
00293 }
00294 
00295 static void
00296 run_match_dialog (GNCImportMainMatcher *info,
00297                   GNCImportTransInfo *trans_info)
00298 {
00299     gnc_import_match_picker_run_and_close (trans_info);
00300 }
00301 
00302 static void
00303 gnc_gen_trans_add_toggled_cb (GtkCellRendererToggle *cell_renderer,
00304                               gchar                 *path,
00305                               GNCImportMainMatcher  *gui)
00306 {
00307     GtkTreeModel *model;
00308     GtkTreeIter iter;
00309     GNCImportTransInfo *trans_info;
00310 
00311     model = gtk_tree_view_get_model(gui->view);
00312     if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
00313         return;
00314     gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
00315 
00316     if ( gnc_import_TransInfo_get_action(trans_info) == GNCImport_ADD
00317             && gnc_import_Settings_get_action_skip_enabled (gui->user_settings) == TRUE)
00318     {
00319         gnc_import_TransInfo_set_action(trans_info, GNCImport_SKIP);
00320     }
00321     else
00322     {
00323         gnc_import_TransInfo_set_action(trans_info, GNCImport_ADD);
00324     }
00325     refresh_model_row(gui, model, &iter, trans_info);
00326 }
00327 
00328 static void
00329 gnc_gen_trans_clear_toggled_cb (GtkCellRendererToggle *cell_renderer,
00330                                 gchar                 *path,
00331                                 GNCImportMainMatcher  *gui)
00332 {
00333     GtkTreeModel *model;
00334     GtkTreeIter iter;
00335     GNCImportTransInfo *trans_info;
00336 
00337     model = gtk_tree_view_get_model(gui->view);
00338     if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
00339         return;
00340     gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
00341 
00342     if ( gnc_import_TransInfo_get_action(trans_info) == GNCImport_CLEAR
00343             && gnc_import_Settings_get_action_skip_enabled (gui->user_settings) == TRUE)
00344     {
00345         gnc_import_TransInfo_set_action(trans_info, GNCImport_SKIP);
00346     }
00347     else
00348     {
00349         gnc_import_TransInfo_set_action(trans_info, GNCImport_CLEAR);
00350     }
00351     refresh_model_row(gui, model, &iter, trans_info);
00352 }
00353 
00354 static void
00355 gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
00356                                  gchar                 *path,
00357                                  GNCImportMainMatcher  *gui)
00358 {
00359     GtkTreeModel *model;
00360     GtkTreeIter iter;
00361     GNCImportTransInfo *trans_info;
00362 
00363     model = gtk_tree_view_get_model(gui->view);
00364     if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
00365         return;
00366     gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
00367 
00368     if ( gnc_import_TransInfo_get_action(trans_info) == GNCImport_UPDATE
00369             && gnc_import_Settings_get_action_skip_enabled (gui->user_settings) == TRUE)
00370     {
00371         gnc_import_TransInfo_set_action(trans_info, GNCImport_SKIP);
00372     }
00373     else
00374     {
00375         gnc_import_TransInfo_set_action(trans_info, GNCImport_UPDATE);
00376     }
00377     refresh_model_row(gui, model, &iter, trans_info);
00378 }
00379 
00380 static void
00381 gnc_gen_trans_row_activated_cb (GtkTreeView           *view,
00382                                 GtkTreePath           *path,
00383                                 GtkTreeViewColumn     *column,
00384                                 GNCImportMainMatcher  *gui)
00385 {
00386     GtkTreeModel *model;
00387     GtkTreeIter iter;
00388     GNCImportTransInfo *trans_info;
00389 
00390     model = gtk_tree_view_get_model(gui->view);
00391     if (!gtk_tree_model_get_iter(model, &iter, path))
00392         return;
00393     gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
00394 
00395     switch (gnc_import_TransInfo_get_action (trans_info))
00396     {
00397     case GNCImport_ADD:
00398         if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE)
00399         {
00400             run_account_picker_dialog (gui, model, &iter, trans_info);
00401         }
00402         break;
00403     case GNCImport_CLEAR:
00404     case GNCImport_UPDATE:
00405         run_match_dialog (gui, trans_info);
00406         break;
00407     case GNCImport_SKIP:
00408         /*The information displayed is only informative, until you select an action*/
00409         break;
00410     default:
00411         PERR("I don't know what to do! (Yet...)");
00412     }
00413     refresh_model_row(gui, model, &iter, trans_info);
00414 }
00415 
00416 static void
00417 gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
00418                               GNCImportMainMatcher *gui)
00419 {
00420     GtkTreeModel *model;
00421     GtkTreeIter iter;
00422 
00423     if (!gtk_tree_selection_get_selected(selection, &model, &iter))
00424         return;
00425     gtk_tree_selection_unselect_iter(selection, &iter);
00426 }
00427 
00428 static GtkTreeViewColumn *
00429 add_text_column(GtkTreeView *view, const gchar *title, int col_num)
00430 {
00431     GtkCellRenderer *renderer;
00432     GtkTreeViewColumn *column;
00433 
00434     renderer = gtk_cell_renderer_text_new();
00435     g_object_set(G_OBJECT(renderer),
00436                  "foreground", "black",
00437                  "foreground-set", TRUE,
00438                  NULL);
00439     column = gtk_tree_view_column_new_with_attributes
00440              (title, renderer,
00441               "text", col_num,
00442               "background", DOWNLOADED_COL_COLOR,
00443               NULL);
00444     gtk_tree_view_column_set_sort_column_id(column, col_num);
00445     g_object_set(G_OBJECT(column),
00446                  "reorderable", TRUE,
00447                  "resizable", TRUE,
00448                  NULL);
00449     gtk_tree_view_append_column(view, column);
00450     return column;
00451 }
00452 
00453 static GtkTreeViewColumn *
00454 add_toggle_column(GtkTreeView *view, const gchar *title, int col_num,
00455                   GCallback cb_fn, gpointer cb_arg)
00456 {
00457     GtkCellRenderer *renderer;
00458     GtkTreeViewColumn *column;
00459 
00460     renderer = gtk_cell_renderer_toggle_new();
00461     column = gtk_tree_view_column_new_with_attributes
00462              (title, renderer,
00463               "active", col_num,
00464               "cell-background", DOWNLOADED_COL_COLOR,
00465               NULL);
00466     gtk_tree_view_column_set_sort_column_id(column, col_num);
00467     g_object_set(G_OBJECT(column),
00468                  "reorderable", TRUE,
00469                  NULL);
00470     g_signal_connect(renderer, "toggled", cb_fn, cb_arg);
00471     gtk_tree_view_append_column(view, column);
00472     return column;
00473 }
00474 
00475 static void
00476 gnc_gen_trans_init_view (GNCImportMainMatcher *info,
00477                          gboolean show_account,
00478                          gboolean show_update)
00479 {
00480     GtkTreeView *view;
00481     GtkListStore *store;
00482     GtkCellRenderer *renderer;
00483     GtkTreeViewColumn *column;
00484     GtkTreeSelection *selection;
00485 
00486     view = info->view;
00487     store = gtk_list_store_new(NUM_DOWNLOADED_COLS,
00488                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
00489                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN,
00490                                G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
00491                                GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING);
00492     gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
00493     g_object_unref(store);
00494 
00495     /* Add the columns */
00496     add_text_column(view, _("Date"), DOWNLOADED_COL_DATE);
00497     column = add_text_column(view, _("Account"), DOWNLOADED_COL_ACCOUNT);
00498     gtk_tree_view_column_set_visible(column, show_account);
00499     add_text_column(view, _("Amount"), DOWNLOADED_COL_AMOUNT);
00500     add_text_column(view, _("Description"), DOWNLOADED_COL_DESCRIPTION);
00501     add_text_column(view, _("Memo"), DOWNLOADED_COL_MEMO);
00502     add_toggle_column(view, _("A"), DOWNLOADED_COL_ACTION_ADD,
00503                       G_CALLBACK(gnc_gen_trans_add_toggled_cb), info);
00504     column = add_toggle_column(view, _("U+R"), DOWNLOADED_COL_ACTION_UPDATE,
00505                                G_CALLBACK(gnc_gen_trans_update_toggled_cb), info);
00506     gtk_tree_view_column_set_visible(column, show_update);
00507     add_toggle_column(view, _("R"), DOWNLOADED_COL_ACTION_CLEAR,
00508                       G_CALLBACK(gnc_gen_trans_clear_toggled_cb), info);
00509 
00510     /* The last column has multiple renderers */
00511     renderer = gtk_cell_renderer_pixbuf_new();
00512     g_object_set(renderer, "xalign", 0.0, NULL);
00513     column = gtk_tree_view_column_new_with_attributes(_("Info"), renderer,
00514              "pixbuf", DOWNLOADED_COL_ACTION_PIXBUF,
00515              "cell-background", DOWNLOADED_COL_COLOR,
00516              NULL);
00517     renderer = gtk_cell_renderer_text_new();
00518     g_object_set(G_OBJECT(renderer),
00519                  "foreground", "black",
00520                  "foreground-set", TRUE,
00521                  NULL);
00522     gtk_tree_view_column_pack_start(column, renderer, TRUE);
00523     gtk_tree_view_column_set_attributes(column, renderer,
00524                                         "text", DOWNLOADED_COL_ACTION_INFO,
00525                                         "background", DOWNLOADED_COL_COLOR,
00526                                         NULL);
00527     gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_ACTION_INFO);
00528     g_object_set(G_OBJECT(column),
00529                  "reorderable", TRUE,
00530                  "resizable", TRUE,
00531                  NULL);
00532     gtk_tree_view_append_column(info->view, column);
00533 
00534 
00535     selection = gtk_tree_view_get_selection(info->view);
00536     g_signal_connect(info->view, "row-activated",
00537                      G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
00538     g_signal_connect(selection, "changed",
00539                      G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
00540 }
00541 
00542 GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
00543         const gchar* heading,
00544         gboolean all_from_same_account,
00545         gint match_date_hardlimit)
00546 {
00547     GNCImportMainMatcher *info;
00548     GtkBuilder *builder;
00549     GtkWidget *heading_label;
00550     GtkWidget *button, *box, *pbox;
00551     gboolean show_update;
00552 
00553     info = g_new0 (GNCImportMainMatcher, 1);
00554 
00555     /* Initialize user Settings. */
00556     info->user_settings = gnc_import_Settings_new ();
00557     gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
00558 
00559     /* Initialize the GtkDialog. */
00560     builder = gtk_builder_new();
00561     gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher");
00562     gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
00563     info->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher"));
00564     g_assert (info->dialog != NULL);
00565 
00566     /* Pack the content into the dialog vbox */
00567     pbox = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_vbox"));
00568     box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
00569     gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE, 0);
00570 
00571     /* Get the view */
00572     info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
00573     g_assert (info->view != NULL);
00574 
00575     show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
00576     gnc_gen_trans_init_view(info, all_from_same_account, show_update);
00577     heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
00578     g_assert (heading_label != NULL);
00579 
00580     /* if (parent)
00581       gtk_window_set_transient_for (GTK_WINDOW (info->dialog),
00582                           GTK_WINDOW (parent));*/
00583 
00584     /*Initialise the colors */
00585     gdk_color_parse(COLOR_RED,    &info->color_back_red);
00586     gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
00587     gdk_color_parse(COLOR_GREEN,  &info->color_back_green);
00588 
00589     if (heading)
00590         gtk_label_set_text (GTK_LABEL (heading_label), heading);
00591 
00592     gnc_restore_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
00593     gtk_widget_show_all (GTK_WIDGET (info->dialog));
00594 
00595     info->transaction_processed_cb = NULL;
00596 
00597     /* Connect the signals */
00598     gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
00599 
00600     g_object_unref(G_OBJECT(builder));
00601 
00602     return info;
00603 }
00604 
00605 /*****************************************************************
00606  *                 Assistant routines Start                      *
00607  *****************************************************************/
00608 
00609 GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
00610         const gchar* heading,
00611         gboolean all_from_same_account,
00612         gint match_date_hardlimit)
00613 {
00614     GNCImportMainMatcher *info;
00615     GtkBuilder *builder;
00616     GtkWidget *heading_label;
00617     GtkWidget *button, *box, *pbox;
00618     gboolean show_update;
00619 
00620     info = g_new0 (GNCImportMainMatcher, 1);
00621 
00622     /* Initialize user Settings. */
00623     info->user_settings = gnc_import_Settings_new ();
00624     gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
00625 
00626     /* load the interface */
00627     builder = gtk_builder_new();
00628     gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
00629     if (builder == NULL)
00630     {
00631         PERR("Error opening the glade builder interface");
00632     }
00633     /* Pack content into Assistant page widget */
00634     box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
00635     gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
00636 
00637     /* Get the view */
00638     info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
00639     g_assert (info->view != NULL);
00640 
00641     show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
00642     gnc_gen_trans_init_view(info, all_from_same_account, show_update);
00643     heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
00644     g_assert (heading_label != NULL);
00645 
00646     /*Initialise the colors */
00647     gdk_color_parse(COLOR_RED,    &info->color_back_red);
00648     gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
00649     gdk_color_parse(COLOR_GREEN,  &info->color_back_green);
00650 
00651     if (heading)
00652         gtk_label_set_text (GTK_LABEL (heading_label), heading);
00653 
00654     info->transaction_processed_cb = NULL;
00655 
00656     /* Connect the signals */
00657     gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
00658 
00659     g_object_unref(G_OBJECT(builder));
00660 
00661     return info;
00662 }
00663 
00664 void gnc_gen_trans_assist_start (GNCImportMainMatcher *info)
00665 {
00666     on_matcher_ok_clicked (NULL, info);
00667 }
00668 
00669 /*****************************************************************
00670  *                   Assistant routines End                      *
00671  *****************************************************************/
00672 
00673 void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info,
00674                                   GNCTransactionProcessedCB trans_processed_cb,
00675                                   gpointer user_data)
00676 {
00677     info->user_data = user_data;
00678     info->transaction_processed_cb = trans_processed_cb;
00679 }
00680 
00681 gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info)
00682 {
00683     gboolean result;
00684 
00685     /* DEBUG("Begin"); */
00686     result = gtk_dialog_run (GTK_DIALOG (info->dialog));
00687     /* DEBUG("Result was %d", result); */
00688 
00689     /* No destroying here since the dialog was already destroyed through
00690        the ok_clicked handlers. */
00691 
00692     return result;
00693 }
00694 
00695 static void
00696 refresh_model_row (GNCImportMainMatcher *gui,
00697                    GtkTreeModel *model,
00698                    GtkTreeIter *iter,
00699                    GNCImportTransInfo *info)
00700 {
00701     GtkListStore *store;
00702     GtkTreeSelection *selection;
00703     gchar *tmp, *imbalance, *text, *color;
00704     const gchar *ro_text;
00705     Split *split;
00706     g_assert (gui);
00707     g_assert (model);
00708     g_assert (info);
00709     /*DEBUG("Begin");*/
00710 
00711     store = GTK_LIST_STORE(model);
00712     gtk_list_store_set(store, iter, DOWNLOADED_COL_DATA, info, -1);
00713 
00714     /*Account:*/
00715     split = gnc_import_TransInfo_get_fsplit (info);
00716     g_assert(split); // Must not be NULL
00717     ro_text = xaccAccountGetName(xaccSplitGetAccount(split));
00718     gtk_list_store_set(store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
00719 
00720     /*Date*/
00721     text = qof_print_date ( xaccTransGetDate( gnc_import_TransInfo_get_trans(info) ) );
00722     gtk_list_store_set(store, iter, DOWNLOADED_COL_DATE, text, -1);
00723     g_free(text);
00724 
00725     /*Amount*/
00726     ro_text = xaccPrintAmount
00727               (xaccSplitGetAmount (split),
00728                gnc_split_amount_print_info(split, TRUE)
00729               );
00730     gtk_list_store_set(store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
00731 
00732     /*Description*/
00733     ro_text = xaccTransGetDescription(gnc_import_TransInfo_get_trans(info) );
00734     gtk_list_store_set(store, iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1);
00735 
00736     /*Memo*/
00737     ro_text = xaccSplitGetMemo(split);
00738     gtk_list_store_set(store, iter, DOWNLOADED_COL_MEMO, ro_text, -1);
00739 
00740     /*Actions*/
00741 
00742     /* Action informations */
00743     ro_text = text = color = NULL;
00744     switch (gnc_import_TransInfo_get_action(info))
00745     {
00746     case GNCImport_ADD:
00747         if (gnc_import_TransInfo_is_balanced(info) == TRUE)
00748         {
00749             ro_text = _("New, already balanced");
00750             color = COLOR_GREEN;
00751         }
00752         else
00753         {
00754             /* Assume that importers won't create transactions in two or more
00755                currencies so we can use xaccTransGetImbalanceValue */
00756             imbalance =
00757                 g_strdup
00758                 (xaccPrintAmount
00759                  (gnc_numeric_neg(xaccTransGetImbalanceValue
00760                                   (gnc_import_TransInfo_get_trans(info) )),
00761                   gnc_commodity_print_info
00762                   (xaccTransGetCurrency(gnc_import_TransInfo_get_trans (info)),
00763                    TRUE) ));
00764             if (gnc_import_TransInfo_get_destacc (info) != NULL)
00765             {
00766                 color = COLOR_GREEN;
00767                 tmp = gnc_account_get_full_name
00768                       (gnc_import_TransInfo_get_destacc (info));
00769                 if (gnc_import_TransInfo_get_destacc_selected_manually(info)
00770                         == TRUE)
00771                 {
00772                     text =
00773                         /* Translators: %1$s is the amount to be
00774                            transferred. %2$s is the destination account. */
00775                         g_strdup_printf(_("New, transfer %s to (manual) \"%s\""),
00776                                         imbalance, tmp);
00777                 }
00778                 else
00779                 {
00780                     text =
00781                         /* Translators: %1$s is the amount to be
00782                            transferred. %2$s is the destination account. */
00783                         g_strdup_printf(_("New, transfer %s to (auto) \"%s\""),
00784                                         imbalance, tmp);
00785                 }
00786                 g_free (tmp);
00787 
00788             }
00789             else
00790             {
00791                 color = COLOR_YELLOW;
00792                 text =
00793                     /* Translators: %s is the amount to be transferred. */
00794                     g_strdup_printf(_("New, UNBALANCED (need acct to transfer %s)!"),
00795                                     imbalance);
00796             }
00797             g_free (imbalance);
00798         }
00799         break;
00800     case GNCImport_CLEAR:
00801         if (gnc_import_TransInfo_get_selected_match(info))
00802         {
00803             color = COLOR_GREEN;
00804             if (gnc_import_TransInfo_get_match_selected_manually(info) == TRUE)
00805             {
00806                 ro_text = _("Reconcile (manual) match");
00807             }
00808             else
00809             {
00810                 ro_text = _("Reconcile (auto) match");
00811             }
00812         }
00813         else
00814         {
00815             color = COLOR_RED;
00816             ro_text = _("Match missing!");
00817         }
00818         break;
00819     case GNCImport_UPDATE:
00820         if (gnc_import_TransInfo_get_selected_match(info))
00821         {
00822             color = COLOR_GREEN;
00823             if (gnc_import_TransInfo_get_match_selected_manually(info) == TRUE)
00824             {
00825                 ro_text = _("Update and reconcile (manual) match");
00826             }
00827             else
00828             {
00829                 ro_text = _("Update and reconcile (auto) match");
00830             }
00831         }
00832         else
00833         {
00834             color = COLOR_RED;
00835             ro_text = _("Match missing!");
00836         }
00837         break;
00838     case GNCImport_SKIP:
00839         color = COLOR_RED;
00840         ro_text = _("Do not import (no action selected)");
00841         break;
00842     default:
00843         color = "white";
00844         ro_text = "WRITEME, this is an unknown action";
00845     }
00846 
00847     gtk_list_store_set(store, iter,
00848                        DOWNLOADED_COL_COLOR, color,
00849                        DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text,
00850                        -1);
00851     if (text)
00852         g_free(text);
00853 
00854     /* Set the pixmaps */
00855     gtk_list_store_set(store, iter,
00856                        DOWNLOADED_COL_ACTION_ADD,
00857                        gnc_import_TransInfo_get_action(info) == GNCImport_ADD,
00858                        -1);
00859     if (gnc_import_TransInfo_get_action(info) == GNCImport_SKIP)
00860     {
00861         /*Show the best match's confidence pixmap in the info column*/
00862         gtk_list_store_set(store, iter,
00863                            DOWNLOADED_COL_ACTION_PIXBUF,
00864                            gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
00865                                    ( gnc_import_TransInfo_get_selected_match (info)),
00866                                    gui->user_settings,
00867                                    GTK_WIDGET(gui->view)),
00868                            -1);
00869     }
00870 
00871     gtk_list_store_set(store, iter,
00872                        DOWNLOADED_COL_ACTION_CLEAR,
00873                        gnc_import_TransInfo_get_action(info) == GNCImport_CLEAR,
00874                        -1);
00875     if (gnc_import_TransInfo_get_action(info) == GNCImport_CLEAR)
00876     {
00877         /*Show the best match's confidence pixmap in the info column*/
00878         gtk_list_store_set(store, iter,
00879                            DOWNLOADED_COL_ACTION_PIXBUF,
00880                            gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
00881                                    ( gnc_import_TransInfo_get_selected_match (info)),
00882                                    gui->user_settings,
00883                                    GTK_WIDGET(gui->view)),
00884                            -1);
00885     }
00886 
00887     gtk_list_store_set(store, iter,
00888                        DOWNLOADED_COL_ACTION_UPDATE,
00889                        gnc_import_TransInfo_get_action(info) == GNCImport_UPDATE,
00890                        -1);
00891     if (gnc_import_TransInfo_get_action(info) == GNCImport_UPDATE)
00892     {
00893         /*Show the best match's confidence pixmap in the info column*/
00894         gtk_list_store_set(store, iter,
00895                            DOWNLOADED_COL_ACTION_PIXBUF,
00896                            gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
00897                                    ( gnc_import_TransInfo_get_selected_match (info)),
00898                                    gui->user_settings,
00899                                    GTK_WIDGET(gui->view)),
00900                            -1);
00901     }
00902 
00903     selection = gtk_tree_view_get_selection(gui->view);
00904     gtk_tree_selection_unselect_all(selection);
00905 }
00906 
00907 void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
00908 {
00909     gnc_gen_trans_list_add_trans_with_ref_id(gui, trans, 0);
00910     return;
00911 }/* end gnc_import_add_trans() */
00912 
00913 void gnc_gen_trans_list_add_trans_with_ref_id(GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)
00914 {
00915     GNCImportTransInfo * transaction_info = NULL;
00916     GtkTreeModel *model;
00917     GtkTreeIter iter;
00918     g_assert (gui);
00919     g_assert (trans);
00920 
00921 
00922     if (gnc_import_exists_online_id (trans))
00923         return;
00924     else
00925     {
00926         transaction_info = gnc_import_TransInfo_new(trans, NULL);
00927         gnc_import_TransInfo_set_ref_id(transaction_info, ref_id);
00928 
00929         gnc_import_TransInfo_init_matches(transaction_info,
00930                                           gui->user_settings);
00931 
00932         model = gtk_tree_view_get_model(gui->view);
00933         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
00934         refresh_model_row (gui, model, &iter, transaction_info);
00935     }
00936     return;
00937 }/* end gnc_import_add_trans_with_ref_id() */
00938 
00939 /* Iterate through the rows of the clist and try to automatch each of them */
00940 static void
00941 automatch_store_transactions (GNCImportMainMatcher *info,
00942                               GtkTreeModel *model,
00943                               GtkTreeIter *iter,
00944                               GNCImportTransInfo *trans_info)
00945 {
00946     /* returns TRUE if we changed this row, so update it */
00947     if (gnc_import_TransInfo_refresh_destacc(trans_info, NULL))
00948     {
00949         refresh_model_row(info, model, iter, trans_info);
00950     }
00951 }
00952 
00953 GtkWidget *gnc_gen_trans_list_widget (GNCImportMainMatcher *info)
00954 {
00955     g_assert(info);
00956     return info->dialog;
00957 }
00958 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines