GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
import-match-picker.c
1 /********************************************************************\
2  * This program is free software; you can redistribute it and/or *
3  * modify it under the terms of the GNU General Public License as *
4  * published by the Free Software Foundation; either version 2 of *
5  * the License, or (at your option) any later version. *
6  * *
7  * This program is distributed in the hope that it will be useful, *
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
10  * GNU General Public License for more details. *
11  * *
12  * You should have received a copy of the GNU General Public License*
13  * along with this program; if not, contact: *
14  * *
15  * Free Software Foundation Voice: +1-617-542-5942 *
16  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
17  * Boston, MA 02110-1301, USA [email protected] *
18 \********************************************************************/
29 #include "config.h"
30 
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33 
34 #include "import-backend.h"
35 #include "import-match-picker.h"
36 
37 #include "qof.h"
38 #include "gnc-ui-util.h"
39 #include "dialog-utils.h"
40 /********************************************************************\
41  * Constants *
42 \********************************************************************/
43 
44 #define GNC_PREFS_GROUP "dialogs.import.generic.match-picker"
45 
46 enum downloaded_cols
47 {
48  DOWNLOADED_COL_ACCOUNT = 0,
49  DOWNLOADED_COL_DATE,
50  DOWNLOADED_COL_AMOUNT,
51  DOWNLOADED_COL_DESCRIPTION,
52  DOWNLOADED_COL_MEMO,
53  DOWNLOADED_COL_BALANCED,
54  DOWNLOADED_COL_INFO_PTR,
55  NUM_DOWNLOADED_COLS
56 };
57 
58 enum matcher_cols
59 {
60  MATCHER_COL_CONFIDENCE = 0,
61  MATCHER_COL_CONFIDENCE_PIXBUF,
62  MATCHER_COL_DATE,
63  MATCHER_COL_AMOUNT,
64  MATCHER_COL_DESCRIPTION,
65  MATCHER_COL_MEMO,
66  MATCHER_COL_INFO_PTR,
67  NUM_MATCHER_COLS
68 };
69 
70 /* Needs to be commented in again if any DEBUG() macro is used here. */
71 /*static short module = MOD_IMPORT;*/
72 
73 /********************************************************************\
74  * Constants, should idealy be defined a user preference dialog *
75 \********************************************************************/
76 
77 static const int SHOW_NUMERIC_SCORE = FALSE;
78 
79 /********************************************************************\
80  * Structures passed between the functions *
81 \********************************************************************/
82 
84 {
85  GtkWidget * transaction_matcher;
86  GtkTreeView * downloaded_view;
87  GtkTreeView * match_view;
88  GNCImportSettings * user_settings;
89  struct _transactioninfo * selected_trans_info;
90  GNCImportMatchInfo * selected_match_info;
91 };
92 
93 
94 
95 static void
96 downloaded_transaction_append(GNCImportMatchPicker * matcher,
97  GNCImportTransInfo * transaction_info)
98 {
99  GtkListStore *store;
100  GtkTreeIter iter;
101  GtkTreeSelection *selection;
102  Transaction *trans;
103  Split *split;
104  gchar *text;
105  const gchar *ro_text;
106  gboolean found = FALSE;
107  GNCImportTransInfo *local_info;
108 
109  g_assert(matcher);
110  g_assert(transaction_info);
111 
112  /*DEBUG("Begin");*/
113 
114  /* Has the transaction already been added? */
115  store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->downloaded_view));
116  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
117  {
118  do
119  {
120  gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
121  DOWNLOADED_COL_INFO_PTR, &local_info,
122  -1);
123  if (local_info == transaction_info)
124  {
125  found = TRUE;
126  break;
127  }
128  }
129  while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
130  }
131  if (!found)
132  gtk_list_store_append(store, &iter);
133 
134  split = gnc_import_TransInfo_get_fsplit(transaction_info);
135  trans = gnc_import_TransInfo_get_trans(transaction_info);
136 
137  /*Account*/
138  ro_text = xaccAccountGetName(xaccSplitGetAccount(split));
139  gtk_list_store_set(store, &iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
140 
141  /*Date*/
142  text = qof_print_date(xaccTransGetDate(trans));
143  gtk_list_store_set(store, &iter, DOWNLOADED_COL_DATE, text, -1);
144  g_free(text);
145 
146  /*Amount*/
147  ro_text = xaccPrintAmount(xaccSplitGetAmount(split),
148  gnc_split_amount_print_info(split, TRUE));
149  gtk_list_store_set(store, &iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
150 
151  /*Description*/
152  ro_text = xaccTransGetDescription(trans);
153  gtk_list_store_set(store, &iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1);
154 
155  /*Memo*/
156  ro_text = xaccSplitGetMemo(split);
157  gtk_list_store_set(store, &iter, DOWNLOADED_COL_MEMO, ro_text, -1);
158 
159  /*Imbalance*/
160  /* Assume that the importer won't create a transaction that involves two or more
161  currencies and no non-currency commodity. In that case can use the simpler
162  value imbalance check. */
163  ro_text = xaccPrintAmount(xaccTransGetImbalanceValue(trans),
164  gnc_default_print_info(TRUE));
165  gtk_list_store_set(store, &iter, DOWNLOADED_COL_BALANCED, ro_text, -1);
166 
167  gtk_list_store_set(store, &iter, DOWNLOADED_COL_INFO_PTR,
168  transaction_info, -1);
169 
170  selection = gtk_tree_view_get_selection(matcher->downloaded_view);
171  gtk_tree_selection_select_iter(selection, &iter);
172 }
173 
174 /********************************************************************\
175  * *
176  * GUI callbacks *
177  * *
178 \********************************************************************/
179 
180 static void
181 downloaded_transaction_changed_cb (GtkTreeSelection *selection,
182  GNCImportMatchPicker *matcher)
183 {
184  GNCImportMatchInfo * match_info;
185  GtkTreeModel *dl_model;
186  GtkListStore *match_store;
187  GtkTreeIter iter;
188  GList * list_element;
189  gchar *text;
190  const gchar *ro_text;
191  /*DEBUG("row: %d%s%d",row,", column: ",column);*/
192 
193  /* Get the transaction info from the "downloaded" model. */
194  if (!gtk_tree_selection_get_selected(selection, &dl_model, &iter))
195  {
196  matcher->selected_trans_info = NULL;
197  return;
198  }
199  gtk_tree_model_get(dl_model, &iter,
200  DOWNLOADED_COL_INFO_PTR, &matcher->selected_trans_info,
201  -1);
202 
203  /* Now rewrite the "match" model based on that trans. */
204  match_store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->match_view));
205  gtk_list_store_clear(match_store);
206  list_element = g_list_first (gnc_import_TransInfo_get_match_list
207  (matcher->selected_trans_info));
208  while (list_element != NULL)
209  {
210  match_info = list_element->data;
211 
212  gtk_list_store_append(match_store, &iter);
213 
214  /* Print fields. */
215 
216  /* Probability */
217  text = g_strdup_printf("%d", gnc_import_MatchInfo_get_probability (match_info));
218  gtk_list_store_set(match_store, &iter, MATCHER_COL_CONFIDENCE, text, -1);
219  g_free(text);
220 
221  /* Date */
222  text =
226  ( gnc_import_MatchInfo_get_split(match_info) ) ));
227  gtk_list_store_set(match_store, &iter, MATCHER_COL_DATE, text, -1);
228  g_free(text);
229 
230  /* Amount */
231  ro_text =
232  xaccPrintAmount( xaccSplitGetAmount ( gnc_import_MatchInfo_get_split(match_info) ),
233  gnc_split_amount_print_info(gnc_import_MatchInfo_get_split(match_info), TRUE)
234  );
235  gtk_list_store_set(match_store, &iter, MATCHER_COL_AMOUNT, ro_text, -1);
236 
237  /*Description*/
238  ro_text = xaccTransGetDescription
240  gtk_list_store_set(match_store, &iter, MATCHER_COL_DESCRIPTION, ro_text, -1);
241 
242  /*Split memo*/
243  ro_text = xaccSplitGetMemo(gnc_import_MatchInfo_get_split(match_info) );
244  gtk_list_store_set(match_store, &iter, MATCHER_COL_MEMO, ro_text, -1);
245 
246  gtk_list_store_set(match_store, &iter, MATCHER_COL_INFO_PTR, match_info, -1);
247  if (gnc_import_MatchInfo_get_probability(match_info) != 0)
248  {
249  if (SHOW_NUMERIC_SCORE == TRUE)
250  {
251  gtk_list_store_set(match_store, &iter,
252  MATCHER_COL_CONFIDENCE_PIXBUF,
254  matcher->user_settings,
255  GTK_WIDGET(matcher->match_view)),
256  -1);
257  }
258  else
259  {
260  gtk_list_store_set(match_store, &iter,
261  MATCHER_COL_CONFIDENCE_PIXBUF,
263  matcher->user_settings,
264  GTK_WIDGET(matcher->match_view)),
265  -1);
266  }
267  }
268 
269  if (match_info ==
270  gnc_import_TransInfo_get_selected_match (matcher->selected_trans_info))
271  {
272  GtkTreeSelection *selection;
273 
274  selection = gtk_tree_view_get_selection(matcher->match_view);
275  gtk_tree_selection_select_iter(selection, &iter);
276  }
277 
278  list_element = g_list_next(list_element);
279  }
280 }
281 
282 static void
283 match_transaction_changed_cb (GtkTreeSelection *selection,
284  GNCImportMatchPicker *matcher)
285 {
286  GtkTreeModel *model;
287  GtkTreeIter iter;
288 
289  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
290  {
291  matcher->selected_match_info = NULL;
292  return;
293  }
294 
295  gtk_tree_model_get(model, &iter,
296  MATCHER_COL_INFO_PTR, &matcher->selected_match_info,
297  -1);
298 }
299 
300 static void
301 match_transaction_row_activated_cb (GtkTreeView *view, GtkTreePath *path,
302  GtkTreeViewColumn *column,
303  GNCImportMatchPicker *matcher)
304 {
305  g_return_if_fail (matcher && matcher->transaction_matcher);
306 
307  gtk_dialog_response (GTK_DIALOG (matcher->transaction_matcher),
308  GTK_RESPONSE_OK);
309 }
310 
311 static void
312 add_column(GtkTreeView *view, const gchar *title, int col_num)
313 {
314  GtkCellRenderer *renderer;
315  GtkTreeViewColumn *column;
316 
317  renderer = gtk_cell_renderer_text_new();
318  column = gtk_tree_view_column_new_with_attributes(title, renderer,
319  "text", col_num,
320  NULL);
321  gtk_tree_view_append_column(view, column);
322  g_object_set(G_OBJECT(column),
323  "reorderable", TRUE,
324  "resizable", TRUE,
325  NULL);
326 }
327 
328 static void
329 gnc_import_match_picker_init_downloaded_view (GNCImportMatchPicker * matcher)
330 {
331  GtkTreeView *view;
332  GtkListStore *store;
333  GtkTreeSelection *selection;
334 
335  view = matcher->downloaded_view;
336  store = gtk_list_store_new(NUM_DOWNLOADED_COLS,
337  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
338  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
339  G_TYPE_POINTER);
340  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
341  g_object_unref(store);
342 
343  add_column(view, _("Account"), DOWNLOADED_COL_ACCOUNT);
344  add_column(view, _("Date"), DOWNLOADED_COL_DATE);
345  add_column(view, _("Amount"), DOWNLOADED_COL_AMOUNT);
346  add_column(view, _("Description"), DOWNLOADED_COL_DESCRIPTION);
347  add_column(view, _("Memo"), DOWNLOADED_COL_MEMO);
348  add_column(view, _("Balanced"), DOWNLOADED_COL_BALANCED);
349 
350  selection = gtk_tree_view_get_selection(view);
351  g_signal_connect(selection, "changed",
352  G_CALLBACK(downloaded_transaction_changed_cb), matcher);
353 }
354 
355 static void
356 gnc_import_match_picker_init_match_view (GNCImportMatchPicker * matcher)
357 {
358  GtkTreeView *view;
359  GtkListStore *store;
360  GtkCellRenderer *renderer;
361  GtkTreeViewColumn *column;
362  GtkTreeSelection *selection;
363 
364  view = matcher->match_view;
365  store = gtk_list_store_new(NUM_MATCHER_COLS,
366  G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING,
367  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
368  G_TYPE_POINTER);
369  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
370  g_object_unref(store);
371 
372  renderer = gtk_cell_renderer_pixbuf_new();
373  g_object_set(renderer, "xalign", 0.0, NULL);
374  column = gtk_tree_view_column_new_with_attributes(_("Confidence"), renderer,
375  "pixbuf", MATCHER_COL_CONFIDENCE_PIXBUF,
376  NULL);
377  renderer = gtk_cell_renderer_text_new();
378  gtk_tree_view_column_pack_start(column, renderer, TRUE);
379  gtk_tree_view_column_set_attributes(column, renderer,
380  "text", MATCHER_COL_CONFIDENCE,
381  NULL);
382  gtk_tree_view_append_column(view, column);
383 
384  add_column(view, _("Date"), MATCHER_COL_DATE);
385  add_column(view, _("Amount"), MATCHER_COL_AMOUNT);
386  add_column(view, _("Description"), MATCHER_COL_DESCRIPTION);
387  add_column(view, _("Memo"), MATCHER_COL_MEMO);
388 
389  selection = gtk_tree_view_get_selection(view);
390  g_signal_connect(selection, "changed",
391  G_CALLBACK(match_transaction_changed_cb), matcher);
392  g_signal_connect(view, "row-activated",
393  G_CALLBACK(match_transaction_row_activated_cb), matcher);
394 }
395 
396 /********************************************************************\
397  * init_match_picker_gui()
398  * -- GUI initialization for the Match_Picker Dialog
399 \********************************************************************/
400 static void
401 init_match_picker_gui(GNCImportMatchPicker * matcher)
402 {
403  GtkBuilder *builder;
404 
405  /* DEBUG("Begin..."); */
406 
407  /* Initialize user Settings. */
408  matcher->user_settings = gnc_import_Settings_new ();
409 
410  /* load the interface */
411  builder = gtk_builder_new();
412  gnc_builder_add_from_file (builder, "dialog-import.glade", "match_picker");
413  g_return_if_fail (builder != NULL);
414 
415  matcher->transaction_matcher = GTK_WIDGET(gtk_builder_get_object (builder, "match_picker"));
416  matcher->downloaded_view = (GtkTreeView *)GTK_WIDGET(gtk_builder_get_object (builder, "download_view"));
417  matcher->match_view = (GtkTreeView *)GTK_WIDGET(gtk_builder_get_object (builder, "matched_view"));
418 
419  gnc_import_match_picker_init_downloaded_view(matcher);
420  gnc_import_match_picker_init_match_view(matcher);
421 
422  /* DEBUG("User prefs:%s%d%s%d%s%d%s%d%s%d",
423  " action_replace_enabled:",matcher->action_replace_enabled,
424  ", action_skip_enabled:",matcher->action_skip_enabled,
425  ", clear_threshold:",matcher->clear_threshold,
426  ", add_threshold:",matcher->add_threshold,
427  ", display_threshold:",matcher->display_threshold); */
428 
429  gnc_restore_window_size(GNC_PREFS_GROUP,
430  GTK_WINDOW (matcher->transaction_matcher));
431  gtk_widget_show(matcher->transaction_matcher);
432 
433  g_object_unref(G_OBJECT(builder));
434 
435 }/* end init_match_picker_gui */
436 
442 void
444 {
445  GNCImportMatchPicker *matcher;
446  gint response;
447  GNCImportMatchInfo *old;
448  g_assert (transaction_info);
449 
450  /* Create a new match_picker, even though it's stored in a
451  transmatcher struct :-) */
452  matcher = g_new0(GNCImportMatchPicker, 1);
453  /* DEBUG("Init match_picker"); */
454  init_match_picker_gui(matcher);
455 
456  /* Append this single transaction to the view and select it */
457  downloaded_transaction_append(matcher, transaction_info);
458 
459  old = gnc_import_TransInfo_get_selected_match(transaction_info);
460 
461  /* Let this dialog run and close. */
462  /*DEBUG("Right before run and close");*/
463  gtk_window_set_modal(GTK_WINDOW(matcher->transaction_matcher), TRUE);
464  response = gtk_dialog_run (GTK_DIALOG (matcher->transaction_matcher));
465  gnc_save_window_size(GNC_PREFS_GROUP,
466  GTK_WINDOW (matcher->transaction_matcher));
467  gtk_widget_destroy (matcher->transaction_matcher);
468  /*DEBUG("Right after run and close");*/
469  /* DEBUG("Response was %d.", response); */
470  if (response == GTK_RESPONSE_OK && matcher->selected_match_info != old)
471  {
472  /* OK was pressed */
473  gnc_import_TransInfo_set_selected_match (transaction_info,
474  matcher->selected_match_info,
475  TRUE);
476  }
477 }
478 
void gnc_import_match_picker_run_and_close(GNCImportTransInfo *transaction_info)
time64 xaccTransGetDate(const Transaction *trans)
Definition: Transaction.c:2215
utility functions for the GnuCash UI
GNCImportSettings * gnc_import_Settings_new(void)
Generic importer backend interface.
void gnc_import_TransInfo_set_selected_match(GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
GdkPixbuf * gen_probability_pixbuf(gint score_original, GNCImportSettings *settings, GtkWidget *widget)
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
char * qof_print_date(time64 secs)
Split * gnc_import_MatchInfo_get_split(const GNCImportMatchInfo *info)
gint gnc_import_MatchInfo_get_probability(const GNCImportMatchInfo *info)
The transaction match picker dialog interface.
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
Definition: Transaction.c:1036
const char * xaccTransGetDescription(const Transaction *trans)
Definition: Transaction.c:2184
Definition: SplitP.h:71
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:968
const char * xaccSplitGetMemo(const Split *split)
Definition: Split.c:1968
GList * gnc_import_TransInfo_get_match_list(const GNCImportTransInfo *info)
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:3031
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1987