GnuCash 2.4.99
import-match-picker.c
00001 /********************************************************************\
00002  * This program is free software; you can redistribute it and/or    *
00003  * modify it under the terms of the GNU General Public License as   *
00004  * published by the Free Software Foundation; either version 2 of   *
00005  * the License, or (at your option) any later version.              *
00006  *                                                                  *
00007  * This program is distributed in the hope that it will be useful,  *
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00010  * GNU General Public License for more details.                     *
00011  *                                                                  *
00012  * You should have received a copy of the GNU General Public License*
00013  * along with this program; if not, contact:                        *
00014  *                                                                  *
00015  * Free Software Foundation           Voice:  +1-617-542-5942       *
00016  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00017  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00018 \********************************************************************/
00029 #include "config.h"
00030 
00031 #include <gtk/gtk.h>
00032 #include <glib/gi18n.h>
00033 
00034 #include "import-backend.h"
00035 #include "import-match-picker.h"
00036 
00037 #include "qof.h"
00038 #include "gnc-ui-util.h"
00039 #include "dialog-utils.h"
00040 /********************************************************************\
00041  *   Constants   *
00042 \********************************************************************/
00043 
00044 #define GCONF_SECTION "dialogs/import/generic_matcher/match_picker"
00045 
00046 enum downloaded_cols
00047 {
00048     DOWNLOADED_COL_ACCOUNT = 0,
00049     DOWNLOADED_COL_DATE,
00050     DOWNLOADED_COL_AMOUNT,
00051     DOWNLOADED_COL_DESCRIPTION,
00052     DOWNLOADED_COL_MEMO,
00053     DOWNLOADED_COL_BALANCED,
00054     DOWNLOADED_COL_INFO_PTR,
00055     NUM_DOWNLOADED_COLS
00056 };
00057 
00058 enum matcher_cols
00059 {
00060     MATCHER_COL_CONFIDENCE = 0,
00061     MATCHER_COL_CONFIDENCE_PIXBUF,
00062     MATCHER_COL_DATE,
00063     MATCHER_COL_AMOUNT,
00064     MATCHER_COL_DESCRIPTION,
00065     MATCHER_COL_MEMO,
00066     MATCHER_COL_INFO_PTR,
00067     NUM_MATCHER_COLS
00068 };
00069 
00070 /* Needs to be commented in again if any DEBUG() macro is used here. */
00071 /*static short module = MOD_IMPORT;*/
00072 
00073 /********************************************************************\
00074  *   Constants, should idealy be defined a user preference dialog    *
00075 \********************************************************************/
00076 
00077 static const int SHOW_NUMERIC_SCORE = FALSE;
00078 
00079 /********************************************************************\
00080  *               Structures passed between the functions             *
00081 \********************************************************************/
00082 
00083 struct _transpickerdialog
00084 {
00085     GtkWidget * transaction_matcher;
00086     GtkTreeView * downloaded_view;
00087     GtkTreeView * match_view;
00088     GNCImportSettings * user_settings;
00089     struct _transactioninfo * selected_trans_info;
00090     GNCImportMatchInfo * selected_match_info;
00091 };
00092 
00093 
00094 
00095 static void
00096 downloaded_transaction_append(GNCImportMatchPicker * matcher,
00097                               GNCImportTransInfo * transaction_info)
00098 {
00099     GtkListStore *store;
00100     GtkTreeIter iter;
00101     GtkTreeSelection *selection;
00102     Transaction *trans;
00103     Split *split;
00104     gchar *text;
00105     const gchar *ro_text;
00106     gboolean found = FALSE;
00107     GNCImportTransInfo *local_info;
00108 
00109     g_assert(matcher);
00110     g_assert(transaction_info);
00111 
00112     /*DEBUG("Begin");*/
00113 
00114     /* Has the transaction already been added? */
00115     store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->downloaded_view));
00116     if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
00117     {
00118         do
00119         {
00120             gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
00121                                DOWNLOADED_COL_INFO_PTR, &local_info,
00122                                -1);
00123             if (local_info == transaction_info)
00124             {
00125                 found = TRUE;
00126                 break;
00127             }
00128         }
00129         while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
00130     }
00131     if (!found)
00132         gtk_list_store_append(store, &iter);
00133 
00134     split = gnc_import_TransInfo_get_fsplit(transaction_info);
00135     trans = gnc_import_TransInfo_get_trans(transaction_info);
00136 
00137     /*Account*/
00138     ro_text = xaccAccountGetName(xaccSplitGetAccount(split));
00139     gtk_list_store_set(store, &iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
00140 
00141     /*Date*/
00142     text = qof_print_date(xaccTransGetDate(trans));
00143     gtk_list_store_set(store, &iter, DOWNLOADED_COL_DATE, text, -1);
00144     g_free(text);
00145 
00146     /*Amount*/
00147     ro_text = xaccPrintAmount(xaccSplitGetAmount(split),
00148                               gnc_split_amount_print_info(split, TRUE));
00149     gtk_list_store_set(store, &iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
00150 
00151     /*Description*/
00152     ro_text = xaccTransGetDescription(trans);
00153     gtk_list_store_set(store, &iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1);
00154 
00155     /*Memo*/
00156     ro_text = xaccSplitGetMemo(split);
00157     gtk_list_store_set(store, &iter, DOWNLOADED_COL_MEMO, ro_text, -1);
00158 
00159     /*Imbalance*/
00160     /* Assume that the importer won't create a transaction that involves two or more
00161        currencies and no non-currency commodity.  In that case can use the simpler
00162        value imbalance check. */
00163     ro_text = xaccPrintAmount(xaccTransGetImbalanceValue(trans),
00164                               gnc_default_print_info(TRUE));
00165     gtk_list_store_set(store, &iter, DOWNLOADED_COL_BALANCED, ro_text, -1);
00166 
00167     gtk_list_store_set(store, &iter, DOWNLOADED_COL_INFO_PTR,
00168                        transaction_info, -1);
00169 
00170     selection = gtk_tree_view_get_selection(matcher->downloaded_view);
00171     gtk_tree_selection_select_iter(selection, &iter);
00172 }
00173 
00174 /********************************************************************\
00175  *                                                                   *
00176  *                       GUI callbacks                               *
00177  *                                                                   *
00178 \********************************************************************/
00179 
00180 static void
00181 downloaded_transaction_changed_cb (GtkTreeSelection *selection,
00182                                    GNCImportMatchPicker *matcher)
00183 {
00184     GNCImportMatchInfo * match_info;
00185     GtkTreeModel *dl_model;
00186     GtkListStore *match_store;
00187     GtkTreeIter iter;
00188     GList * list_element;
00189     gchar *text;
00190     const gchar *ro_text;
00191     /*DEBUG("row: %d%s%d",row,", column: ",column);*/
00192 
00193     /* Get the transaction info from the "downloaded" model.  */
00194     if (!gtk_tree_selection_get_selected(selection, &dl_model, &iter))
00195     {
00196         matcher->selected_trans_info = NULL;
00197         return;
00198     }
00199     gtk_tree_model_get(dl_model, &iter,
00200                        DOWNLOADED_COL_INFO_PTR, &matcher->selected_trans_info,
00201                        -1);
00202 
00203     /* Now rewrite the "match" model based on that trans. */
00204     match_store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->match_view));
00205     gtk_list_store_clear(match_store);
00206     list_element = g_list_first (gnc_import_TransInfo_get_match_list
00207                                  (matcher->selected_trans_info));
00208     while (list_element != NULL)
00209     {
00210         match_info = list_element->data;
00211 
00212         gtk_list_store_append(match_store, &iter);
00213 
00214         /* Print fields. */
00215 
00216         /* Probability */
00217         text = g_strdup_printf("%d", gnc_import_MatchInfo_get_probability (match_info));
00218         gtk_list_store_set(match_store, &iter, MATCHER_COL_CONFIDENCE, text, -1);
00219         g_free(text);
00220 
00221         /* Date */
00222         text =
00223             qof_print_date
00224             ( xaccTransGetDate
00225               ( xaccSplitGetParent
00226                 ( gnc_import_MatchInfo_get_split(match_info) ) ));
00227         gtk_list_store_set(match_store, &iter, MATCHER_COL_DATE, text, -1);
00228         g_free(text);
00229 
00230         /* Amount */
00231         ro_text =
00232             xaccPrintAmount( xaccSplitGetAmount ( gnc_import_MatchInfo_get_split(match_info)  ),
00233                              gnc_split_amount_print_info(gnc_import_MatchInfo_get_split(match_info), TRUE)
00234                            );
00235         gtk_list_store_set(match_store, &iter, MATCHER_COL_AMOUNT, ro_text, -1);
00236 
00237         /*Description*/
00238         ro_text = xaccTransGetDescription
00239                   ( xaccSplitGetParent( gnc_import_MatchInfo_get_split(match_info)) );
00240         gtk_list_store_set(match_store, &iter, MATCHER_COL_DESCRIPTION, ro_text, -1);
00241 
00242         /*Split memo*/
00243         ro_text = xaccSplitGetMemo(gnc_import_MatchInfo_get_split(match_info) );
00244         gtk_list_store_set(match_store, &iter, MATCHER_COL_MEMO, ro_text, -1);
00245 
00246         gtk_list_store_set(match_store, &iter, MATCHER_COL_INFO_PTR, match_info, -1);
00247         if (gnc_import_MatchInfo_get_probability(match_info) != 0)
00248         {
00249             if (SHOW_NUMERIC_SCORE == TRUE)
00250             {
00251                 gtk_list_store_set(match_store, &iter,
00252                                    MATCHER_COL_CONFIDENCE_PIXBUF,
00253                                    gen_probability_pixbuf(gnc_import_MatchInfo_get_probability(match_info),
00254                                            matcher->user_settings,
00255                                            GTK_WIDGET(matcher->match_view)),
00256                                    -1);
00257             }
00258             else
00259             {
00260                 gtk_list_store_set(match_store, &iter,
00261                                    MATCHER_COL_CONFIDENCE_PIXBUF,
00262                                    gen_probability_pixbuf(gnc_import_MatchInfo_get_probability(match_info),
00263                                            matcher->user_settings,
00264                                            GTK_WIDGET(matcher->match_view)),
00265                                    -1);
00266             }
00267         }
00268 
00269         if (match_info ==
00270                 gnc_import_TransInfo_get_selected_match (matcher->selected_trans_info))
00271         {
00272             GtkTreeSelection *selection;
00273 
00274             selection = gtk_tree_view_get_selection(matcher->match_view);
00275             gtk_tree_selection_select_iter(selection, &iter);
00276         }
00277 
00278         list_element = g_list_next(list_element);
00279     }
00280 }
00281 
00282 static void
00283 match_transaction_changed_cb (GtkTreeSelection *selection,
00284                               GNCImportMatchPicker *matcher)
00285 {
00286     GtkTreeModel *model;
00287     GtkTreeIter iter;
00288 
00289     if (!gtk_tree_selection_get_selected (selection, &model, &iter))
00290     {
00291         matcher->selected_match_info = NULL;
00292         return;
00293     }
00294 
00295     gtk_tree_model_get(model, &iter,
00296                        MATCHER_COL_INFO_PTR, &matcher->selected_match_info,
00297                        -1);
00298 }
00299 
00300 static void
00301 match_transaction_row_activated_cb (GtkTreeView *view, GtkTreePath *path,
00302                                     GtkTreeViewColumn *column,
00303                                     GNCImportMatchPicker *matcher)
00304 {
00305     g_return_if_fail (matcher && matcher->transaction_matcher);
00306 
00307     gtk_dialog_response (GTK_DIALOG (matcher->transaction_matcher),
00308                          GTK_RESPONSE_OK);
00309 }
00310 
00311 static void
00312 add_column(GtkTreeView *view, const gchar *title, int col_num)
00313 {
00314     GtkCellRenderer *renderer;
00315     GtkTreeViewColumn *column;
00316 
00317     renderer = gtk_cell_renderer_text_new();
00318     column = gtk_tree_view_column_new_with_attributes(title, renderer,
00319              "text", col_num,
00320              NULL);
00321     gtk_tree_view_append_column(view, column);
00322     g_object_set(G_OBJECT(column),
00323                  "reorderable", TRUE,
00324                  "resizable", TRUE,
00325                  NULL);
00326 }
00327 
00328 static void
00329 gnc_import_match_picker_init_downloaded_view (GNCImportMatchPicker * matcher)
00330 {
00331     GtkTreeView *view;
00332     GtkListStore *store;
00333     GtkTreeSelection *selection;
00334 
00335     view = matcher->downloaded_view;
00336     store = gtk_list_store_new(NUM_DOWNLOADED_COLS,
00337                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
00338                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
00339                                G_TYPE_POINTER);
00340     gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
00341     g_object_unref(store);
00342 
00343     add_column(view, _("Account"),     DOWNLOADED_COL_ACCOUNT);
00344     add_column(view, _("Date"),        DOWNLOADED_COL_DATE);
00345     add_column(view, _("Amount"),      DOWNLOADED_COL_AMOUNT);
00346     add_column(view, _("Description"), DOWNLOADED_COL_DESCRIPTION);
00347     add_column(view, _("Memo"),        DOWNLOADED_COL_MEMO);
00348     add_column(view, _("Balanced"),    DOWNLOADED_COL_BALANCED);
00349 
00350     selection = gtk_tree_view_get_selection(view);
00351     g_signal_connect(selection, "changed",
00352                      G_CALLBACK(downloaded_transaction_changed_cb), matcher);
00353 }
00354 
00355 static void
00356 gnc_import_match_picker_init_match_view (GNCImportMatchPicker * matcher)
00357 {
00358     GtkTreeView *view;
00359     GtkListStore *store;
00360     GtkCellRenderer *renderer;
00361     GtkTreeViewColumn *column;
00362     GtkTreeSelection *selection;
00363 
00364     view = matcher->match_view;
00365     store = gtk_list_store_new(NUM_MATCHER_COLS,
00366                                G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING,
00367                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
00368                                G_TYPE_POINTER);
00369     gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
00370     g_object_unref(store);
00371 
00372     renderer = gtk_cell_renderer_pixbuf_new();
00373     g_object_set(renderer, "xalign", 0.0, NULL);
00374     column = gtk_tree_view_column_new_with_attributes(_("Confidence"), renderer,
00375              "pixbuf", MATCHER_COL_CONFIDENCE_PIXBUF,
00376              NULL);
00377     renderer = gtk_cell_renderer_text_new();
00378     gtk_tree_view_column_pack_start(column, renderer, TRUE);
00379     gtk_tree_view_column_set_attributes(column, renderer,
00380                                         "text", MATCHER_COL_CONFIDENCE,
00381                                         NULL);
00382     gtk_tree_view_append_column(view, column);
00383 
00384     add_column(view, _("Date"),        MATCHER_COL_DATE);
00385     add_column(view, _("Amount"),      MATCHER_COL_AMOUNT);
00386     add_column(view, _("Description"), MATCHER_COL_DESCRIPTION);
00387     add_column(view, _("Memo"),        MATCHER_COL_MEMO);
00388 
00389     selection = gtk_tree_view_get_selection(view);
00390     g_signal_connect(selection, "changed",
00391                      G_CALLBACK(match_transaction_changed_cb), matcher);
00392     g_signal_connect(view, "row-activated",
00393                      G_CALLBACK(match_transaction_row_activated_cb), matcher);
00394 }
00395 
00396 /********************************************************************\
00397  * init_match_picker_gui()
00398  * -- GUI initialization for the Match_Picker Dialog
00399 \********************************************************************/
00400 static void
00401 init_match_picker_gui(GNCImportMatchPicker * matcher)
00402 {
00403     GtkBuilder *builder;
00404 
00405     /* DEBUG("Begin..."); */
00406 
00407     /* Initialize user Settings. */
00408     matcher->user_settings = gnc_import_Settings_new ();
00409 
00410     /* load the interface */
00411     builder = gtk_builder_new();
00412     gnc_builder_add_from_file (builder, "dialog-import.glade", "match_picker");
00413     g_return_if_fail (builder != NULL);
00414 
00415     matcher->transaction_matcher = GTK_WIDGET(gtk_builder_get_object (builder, "match_picker"));
00416     matcher->downloaded_view = (GtkTreeView *)GTK_WIDGET(gtk_builder_get_object (builder, "download_view"));
00417     matcher->match_view = (GtkTreeView *)GTK_WIDGET(gtk_builder_get_object (builder, "matched_view"));
00418 
00419     gnc_import_match_picker_init_downloaded_view(matcher);
00420     gnc_import_match_picker_init_match_view(matcher);
00421 
00422     /* DEBUG("User prefs:%s%d%s%d%s%d%s%d%s%d",
00423        " action_replace_enabled:",matcher->action_replace_enabled,
00424        ", action_skip_enabled:",matcher->action_skip_enabled,
00425        ", clear_threshold:",matcher->clear_threshold,
00426        ", add_threshold:",matcher->add_threshold,
00427        ", display_threshold:",matcher->display_threshold); */
00428 
00429     gnc_restore_window_size(GCONF_SECTION,
00430                             GTK_WINDOW (matcher->transaction_matcher));
00431     gtk_widget_show(matcher->transaction_matcher);
00432 
00433     g_object_unref(G_OBJECT(builder));
00434 
00435 }/* end init_match_picker_gui */
00436 
00442 void
00443 gnc_import_match_picker_run_and_close (GNCImportTransInfo *transaction_info)
00444 {
00445     GNCImportMatchPicker *matcher;
00446     gint response;
00447     GNCImportMatchInfo *old;
00448     g_assert (transaction_info);
00449 
00450     /* Create a new match_picker, even though it's stored in a
00451        transmatcher struct :-) */
00452     matcher = g_new0(GNCImportMatchPicker, 1);
00453     /* DEBUG("Init match_picker"); */
00454     init_match_picker_gui(matcher);
00455 
00456     /* Append this single transaction to the view and select it */
00457     downloaded_transaction_append(matcher, transaction_info);
00458 
00459     old = gnc_import_TransInfo_get_selected_match(transaction_info);
00460 
00461     /* Let this dialog run and close. */
00462     /*DEBUG("Right before run and close");*/
00463     gtk_window_set_modal(GTK_WINDOW(matcher->transaction_matcher), TRUE);
00464     response = gtk_dialog_run (GTK_DIALOG (matcher->transaction_matcher));
00465     gnc_save_window_size(GCONF_SECTION,
00466                          GTK_WINDOW (matcher->transaction_matcher));
00467     gtk_widget_destroy (matcher->transaction_matcher);
00468     /*DEBUG("Right after run and close");*/
00469     /* DEBUG("Response was %d.", response); */
00470     if (response == GTK_RESPONSE_OK && matcher->selected_match_info != old)
00471     {
00472         /* OK was pressed */
00473         gnc_import_TransInfo_set_selected_match (transaction_info,
00474                 matcher->selected_match_info,
00475                 TRUE);
00476     }
00477 }
00478 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines