38 #include <glib/gi18n.h> 48 #include "dialog-transfer.h" 49 #include "dialog-utils.h" 59 #include "gnc-component-manager.h" 61 #include "gnc-session.h" 64 #define GNC_PREFS_GROUP "dialogs.import.generic.transaction-list" 65 #define IMPORT_MAIN_MATCHER_CM_CLASS "transaction-matcher-dialog" 69 GtkWidget *main_widget;
71 GNCImportSettings *user_settings;
74 GNCTransactionProcessedCB transaction_processed_cb;
76 GNCImportPendingMatches *pending_matches;
77 GtkTreeViewColumn *account_column;
78 GtkTreeViewColumn *memo_column;
79 GtkWidget *show_account_column;
80 GtkWidget *show_matched_info;
81 GtkWidget *append_text;
82 GtkWidget *reconcile_after_close;
85 GSList* temp_trans_list;
86 GHashTable* acct_id_hash;
87 GSList* edited_accounts;
94 GHashTable *desc_hash;
95 GHashTable *notes_hash;
96 GHashTable *memo_hash;
103 DOWNLOADED_COL_DATE_TXT = 0,
104 DOWNLOADED_COL_DATE_INT64,
105 DOWNLOADED_COL_ACCOUNT,
106 DOWNLOADED_COL_AMOUNT,
107 DOWNLOADED_COL_AMOUNT_DOUBLE,
108 DOWNLOADED_COL_DESCRIPTION,
109 DOWNLOADED_COL_DESCRIPTION_ORIGINAL,
110 DOWNLOADED_COL_DESCRIPTION_STYLE,
112 DOWNLOADED_COL_MEMO_ORIGINAL,
113 DOWNLOADED_COL_MEMO_STYLE,
114 DOWNLOADED_COL_NOTES_ORIGINAL,
115 DOWNLOADED_COL_ACTION_ADD,
116 DOWNLOADED_COL_ACTION_CLEAR,
117 DOWNLOADED_COL_ACTION_UPDATE,
118 DOWNLOADED_COL_ACTION_INFO,
119 DOWNLOADED_COL_ACTION_PIXBUF,
121 DOWNLOADED_COL_COLOR,
122 DOWNLOADED_COL_ENABLE,
126 #define CSS_INT_REQUIRED_CLASS "gnc-class-intervention-required" 127 #define CSS_INT_PROB_REQUIRED_CLASS "gnc-class-intervention-probably-required" 128 #define CSS_INT_NOT_REQUIRED_CLASS "gnc-class-intervention-not-required" 131 #define G_MOD_IMPORT_MATCHER "gnc.import.main-matcher" 133 static QofLogModule log_module = G_MOD_IMPORT_MATCHER;
135 static const gpointer one = GINT_TO_POINTER (1);
138 void on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info);
139 void on_matcher_cancel_clicked (GtkButton *button, gpointer user_data);
140 bool on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data);
142 void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data);
145 static void gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui);
148 static void gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview,
153 GNCImportMainMatcher *info);
154 static void gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
155 GNCImportMainMatcher *info);
156 static void gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
158 GNCImportMainMatcher *info);
159 static bool gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
161 GNCImportMainMatcher *info);
162 static bool gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
163 GNCImportMainMatcher *info);
164 static void refresh_model_row (GNCImportMainMatcher *gui,
167 GNCImportTransInfo *info);
168 static bool query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
175 update_all_balances (GNCImportMainMatcher *info)
177 for (GSList* iter = info->edited_accounts; iter; iter=iter->next)
179 auto acct =
static_cast<Account*
>(iter->data);
183 g_slist_free (info->edited_accounts);
184 info->edited_accounts = NULL;
188 defer_bal_computation (GNCImportMainMatcher *info,
Account* acc)
193 info->edited_accounts = g_slist_prepend (info->edited_accounts, acc);
204 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
206 if (gtk_tree_model_get_iter_first (model, &iter))
210 GNCImportTransInfo *trans_info;
211 gtk_tree_model_get (model, &iter,
212 DOWNLOADED_COL_DATA, &trans_info,
215 if (info->transaction_processed_cb)
217 info->transaction_processed_cb (trans_info,
false,
221 while (gtk_tree_model_iter_next (model, &iter));
224 if (GTK_IS_DIALOG(info->main_widget))
226 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget));
228 gnc_unregister_gui_component (info->id);
229 gtk_widget_destroy (GTK_WIDGET(info->main_widget));
235 info->temp_trans_list = NULL;
238 update_all_balances (info);
240 gnc_import_PendingMatches_delete (info->pending_matches);
241 g_hash_table_destroy (info->acct_id_hash);
242 g_hash_table_destroy (info->desc_hash);
243 g_hash_table_destroy (info->notes_hash);
244 g_hash_table_destroy (info->memo_hash);
246 g_list_free_full (info->new_strings, (GDestroyNotify)g_free);
250 if (!gnc_gui_refresh_suspended ())
251 gnc_gui_refresh_all ();
260 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
262 return !gtk_tree_model_get_iter_first (model, &iter) && !info->temp_trans_list;
266 gnc_gen_trans_list_show_accounts_column (GNCImportMainMatcher *info)
270 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
271 if (gtk_tree_model_iter_n_children (model, NULL) > 1)
273 bool multiple_accounts =
false;
277 bool valid = gtk_tree_model_get_iter_first (model, &iter);
281 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &account_name, -1);
283 valid = gtk_tree_model_iter_next (model, &iter);
287 gchar *test_account_name;
288 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &test_account_name, -1);
289 if (g_strcmp0 (account_name, test_account_name) != 0)
291 multiple_accounts =
true;
292 g_free (test_account_name);
295 valid = gtk_tree_model_iter_next (model, &iter);
296 g_free (test_account_name);
298 g_free (account_name);
301 if (multiple_accounts)
303 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
304 gtk_tree_view_expand_all (info->view);
308 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
false);
309 gtk_tree_view_collapse_all (info->view);
316 get_top_trans_match_id (GList* match_list)
318 if (!match_list || !match_list->data)
return NULL;
320 Transaction *trans = match_info->trans;
326 get_top_trans_match_score (GList* match_list)
328 if (!match_list || !match_list->data)
return 0;
330 return match_info->probability;
334 get_trans_match_list (GtkTreeModel* model, GtkTreeIter* iter)
336 GNCImportTransInfo *transaction_info;
337 gtk_tree_model_get (model, iter,
338 DOWNLOADED_COL_DATA, &transaction_info,
343 static GNCImportTransInfo*
344 get_trans_info (GtkTreeModel* model, GtkTreeIter* iter)
346 GNCImportTransInfo *transaction_info;
347 gtk_tree_model_get (model, iter,
348 DOWNLOADED_COL_DATA, &transaction_info,
350 return transaction_info;
358 get_conflict_list (GtkTreeModel* model, GtkTreeIter import_iter,
GncGUID*
id, gint best_match)
360 GtkTreeIter iter = import_iter;
361 GNCImportTransInfo* best_import = get_trans_info (model, &import_iter);
362 GList* conflicts = g_list_prepend (NULL, best_import);
364 while (gtk_tree_model_iter_next (model, &iter))
366 gint match_score = 0;
367 GNCImportTransInfo* trans_info;
370 GList* register_iter = get_trans_match_list (model, &iter);
371 if (!register_iter || !register_iter->data)
374 id2 = *get_top_trans_match_id (register_iter);
379 match_score = get_top_trans_match_score (register_iter);
380 trans_info = get_trans_info (model, &iter);
381 conflicts = g_list_prepend (conflicts, trans_info);
383 if (match_score > best_match)
386 best_match = match_score;
387 best_import = trans_info;
392 conflicts = g_list_remove (conflicts, best_import);
397 remove_top_matches (GList* conflicts)
399 for (GList* iter = conflicts; iter && iter->data; iter=iter->next)
404 resolve_conflicts (GNCImportMainMatcher *info)
406 GtkTreeModel* model = gtk_tree_view_get_model (info->view);
407 GtkTreeIter import_iter;
413 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
416 GList *match_list = get_trans_match_list (model, &import_iter);
417 if (!match_list || !match_list->data)
419 valid = gtk_tree_model_iter_next (model, &import_iter);
424 GncGUID id = *get_top_trans_match_id (match_list);
425 best_match = get_top_trans_match_score (match_list);
428 GList *conflicts = get_conflict_list (model, import_iter, &
id, best_match);
432 remove_top_matches (conflicts);
435 valid = gtk_tree_model_get_iter_first (model, &import_iter);
438 valid = gtk_tree_model_iter_next (model, &import_iter);
442 g_list_free (conflicts);
446 valid = gtk_tree_model_get_iter_first (model, &import_iter);
449 refresh_model_row (info, model, &import_iter, get_trans_info (model, &import_iter));
450 valid = gtk_tree_model_iter_next (model, &import_iter);
456 load_hash_tables (GNCImportMainMatcher *info)
458 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
459 GtkTreeIter import_iter;
460 GList *accounts_list = NULL;
461 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
464 GNCImportTransInfo *trans_info = get_trans_info (model, &import_iter);
467 if (!g_list_find (accounts_list, acc))
468 accounts_list = g_list_prepend (accounts_list, acc);
469 valid = gtk_tree_model_iter_next (model, &import_iter);
471 for (GList *m = accounts_list; m; m = m->next)
473 for (
auto s : xaccAccountGetSplits (static_cast<Account*>(m->data)))
479 g_hash_table_insert (info->desc_hash, (gpointer)key, one);
483 g_hash_table_insert (info->notes_hash, (gpointer)key, one);
487 g_hash_table_insert (info->memo_hash, (gpointer)key, one);
490 g_list_free (accounts_list);
500 GSList *temp_trans_list = info->temp_trans_list;
501 if (!temp_trans_list)
503 gnc_info_dialog (GTK_WINDOW (info->main_widget),
"%s", _(
"No new transactions were found in this import."));
506 auto trans_info =
static_cast<GNCImportTransInfo *
>(temp_trans_list->data);
509 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (info->append_text),
512 gnc_gen_trans_list_create_matches (info);
513 load_hash_tables (info);
514 resolve_conflicts (info);
515 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
516 gnc_gen_trans_list_show_accounts_column (info);
519 static void acc_begin_edit (GList **accounts_modified,
Account *acc)
521 if (!acc || !accounts_modified || g_list_find (*accounts_modified, acc))
526 *accounts_modified = g_list_prepend (*accounts_modified, acc);
529 on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
535 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
537 if (!gtk_tree_model_get_iter_first (model, &iter))
546 gnc_suspend_gui_refresh ();
547 bool first_tran =
true;
548 bool append_text = gtk_toggle_button_get_active ((GtkToggleButton*) info->append_text);
549 GList *accounts_modified = NULL;
552 GNCImportTransInfo *trans_info;
553 gtk_tree_model_get (model, &iter,
554 DOWNLOADED_COL_DATA, &trans_info,
578 acc_begin_edit (&accounts_modified, dest_acc);
582 if (info->transaction_processed_cb)
584 info->transaction_processed_cb (trans_info,
true,
589 while (gtk_tree_model_iter_next (model, &iter));
594 gnc_resume_gui_refresh ();
601 on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
603 auto info =
static_cast<GNCImportMainMatcher *
>(user_data);
608 on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
610 auto info =
static_cast<GNCImportMainMatcher *
>(data);
616 on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
618 auto help_dialog =
static_cast<GtkWidget *
>(user_data);
620 gtk_widget_destroy (help_dialog);
626 auto info =
static_cast<GNCImportMainMatcher*
>(user_data);
628 GtkBuilder *builder = gtk_builder_new ();
629 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer2");
630 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer3");
631 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer4");
632 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer5");
633 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer1");
634 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"matcher_help_dialog");
636 const gchar *class_extension = NULL;
637 if (info->dark_theme ==
true)
638 class_extension =
"-dark";
640 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
641 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
642 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
644 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_required_box"));
645 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_required_class);
647 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_probably_required_box"));
648 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_prob_required_class);
650 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_not_required_box"));
651 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_not_required_class);
653 GtkWidget *help_dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"matcher_help_dialog"));
654 gtk_window_set_transient_for (GTK_WINDOW(help_dialog), GTK_WINDOW(info->main_widget));
657 gtk_widget_set_name (GTK_WIDGET(help_dialog),
"gnc-id-import-matcher-help");
658 gnc_widget_style_context_add_class (GTK_WIDGET(help_dialog),
"gnc-class-imports");
661 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
663 g_object_unref (G_OBJECT(builder));
665 g_free (int_required_class);
666 g_free (int_prob_required_class);
667 g_free (int_not_required_class);
669 gtk_widget_show (help_dialog);
673 run_match_dialog (GNCImportMainMatcher *info,
674 GNCImportTransInfo *trans_info)
677 trans_info, info->pending_matches);
681 set_treeview_selection_from_path (GtkTreeView* view,
const char* path)
683 auto selection = gtk_tree_view_get_selection (view);
684 auto tree_path = gtk_tree_path_new_from_string (path);
685 gtk_tree_selection_select_path (selection, tree_path);
686 gtk_tree_path_free (tree_path);
690 gen_trans_common_toggled_cb (GtkCellRendererToggle *cell_renderer, gchar *path,
691 GNCImportMainMatcher *gui, GNCImportAction action)
693 auto model = gtk_tree_view_get_model (gui->view);
694 GtkTreeIter tree_iter;
695 g_return_if_fail (gtk_tree_model_get_iter_from_string (model, &tree_iter, path));
697 GNCImportTransInfo *transaction_info;
698 gtk_tree_model_get (model, &tree_iter, DOWNLOADED_COL_DATA, &transaction_info, -1);
704 refresh_model_row (gui, model, &tree_iter, transaction_info);
706 set_treeview_selection_from_path (GTK_TREE_VIEW(gui->view), path);
710 gnc_gen_trans_add_toggled_cb (GtkCellRendererToggle *cell_renderer,
712 GNCImportMainMatcher *gui)
714 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_ADD);
718 gnc_gen_trans_clear_toggled_cb (GtkCellRendererToggle *cell_renderer,
720 GNCImportMainMatcher *gui)
722 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_CLEAR);
726 gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
728 GNCImportMainMatcher *gui)
730 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_UPDATE);
734 gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview,
739 GNCImportMainMatcher *info)
741 gchar *path_str = gtk_tree_path_to_string (path);
745 DEBUG(
"first = %s", *first ?
"true" :
"false");
746 DEBUG(
"is_selection = %s", is_selection ?
"true" :
"false");
747 DEBUG(
"path = %s", path_str);
749 DEBUG(
"account passed in = %s", acct_str);
753 if (gtk_tree_path_get_depth (path) != 1)
756 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
758 if (gtk_tree_model_get_iter (model, &iter, path))
760 GNCImportTransInfo *trans_info;
761 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
771 gchar *acc_full_name;
775 _(
"Destination account for the auto-balance split."),
783 DEBUG(
"account selected = %s", acc_full_name);
784 g_free (acc_full_name);
789 defer_bal_computation (info, *new_acc);
793 case GNCImport_CLEAR:
794 case GNCImport_UPDATE:
795 if (*first && !is_selection)
796 run_match_dialog (info, trans_info);
801 PERR(
"InvalidGNCImportValue");
804 refresh_model_row (info, model, &iter, trans_info);
812 void operator()(GtkTreeRowReference* ptr)
const { gtk_tree_row_reference_free (ptr); }
815 using TreeRowReferencePtr = std::unique_ptr<GtkTreeRowReference, TreeRowRefDestructor>;
819 static std::vector<TreeRowReferencePtr>
820 get_treeview_selection_refs (GtkTreeView *treeview, GtkTreeModel *model)
822 std::vector<TreeRowReferencePtr> rv;
824 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview) && GTK_IS_TREE_MODEL (model), rv);
826 auto selection = gtk_tree_view_get_selection (treeview);
827 auto selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
829 for (
auto n = selected_rows; n; n = g_list_next (n))
830 rv.emplace_back (gtk_tree_row_reference_new (model, static_cast<GtkTreePath*>(n->data)));
832 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
837 gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
838 GNCImportMainMatcher *info)
842 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
843 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
844 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
845 auto selected_refs = get_treeview_selection_refs (treeview, model);
846 Account *assigned_account = NULL;
848 bool is_selection =
true;
851 DEBUG(
"Rows in selection = %zu", selected_refs.size());
853 for (
const auto& ref : selected_refs)
855 auto path = gtk_tree_row_reference_get_path (ref.get());
856 if (debugging_enabled)
858 auto path_str = gtk_tree_path_to_string (path);
859 DEBUG(
"passing first = %s", first ?
"true" :
"false");
860 DEBUG(
"passing is_selection = %s", is_selection ?
"true" :
"false");
861 DEBUG(
"passing path = %s", path_str);
864 gnc_gen_trans_assign_transfer_account (treeview,
865 &first, is_selection, path,
866 &assigned_account, info);
867 if (debugging_enabled)
870 DEBUG(
"returned value of account = %s", fullname);
871 DEBUG(
"returned value of first = %s", first ?
"true" :
"false");
875 gtk_tree_path_free (path);
876 if (!assigned_account)
881 for (
const auto& ref : selected_refs)
883 GtkTreePath *path = gtk_tree_row_reference_get_path (ref.get());
884 gtk_tree_selection_select_path (selection, path);
885 gtk_tree_path_free (path);
894 RowInfo (GtkTreePath *path, GNCImportMainMatcher *info)
896 init_from_path (path, info);
898 RowInfo (
const TreeRowReferencePtr &ref, GNCImportMainMatcher *info)
900 auto path = gtk_tree_row_reference_get_path (ref.get());
901 init_from_path (path, info);
902 gtk_tree_path_free (path);
906 g_free (m_orig_desc);
907 g_free (m_orig_notes);
908 g_free (m_orig_memo);
910 GNCImportTransInfo* get_trans_info () {
return m_trans_info; };
911 GtkTreeIter* get_iter () {
return &m_iter; };
912 const char* get_orig_desc () {
return m_orig_desc; };
913 const char* get_orig_notes () {
return m_orig_notes; };
914 const char* get_orig_memo () {
return m_orig_memo; };
916 void init_from_path (GtkTreePath *path, GNCImportMainMatcher *info)
918 auto model = gtk_tree_view_get_model (info->view);
919 gtk_tree_model_get_iter (model, &m_iter, path);
920 gtk_tree_model_get (model, &m_iter,
921 DOWNLOADED_COL_DATA, &m_trans_info,
922 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &m_orig_desc,
923 DOWNLOADED_COL_NOTES_ORIGINAL, &m_orig_notes,
924 DOWNLOADED_COL_MEMO_ORIGINAL, &m_orig_memo,
927 GNCImportTransInfo *m_trans_info;
929 char *m_orig_desc, *m_orig_notes, *m_orig_memo;
934 COMPLETION_LIST_ORIGINAL,
935 COMPLETION_LIST_NORMALIZED_FOLDED,
939 static void populate_list (gpointer key, gpointer value, GtkListStore *list)
942 auto original =
static_cast<const char*
>(key);
943 char *normalized = g_utf8_normalize (original, -1, G_NORMALIZE_NFC);
944 char *normalized_folded = normalized ? g_utf8_casefold (normalized, -1) : NULL;
945 gtk_list_store_append (list, &iter);
946 gtk_list_store_set (list, &iter,
947 COMPLETION_LIST_ORIGINAL, original,
948 COMPLETION_LIST_NORMALIZED_FOLDED, normalized_folded,
950 g_free (normalized_folded);
955 match_func (GtkEntryCompletion *completion,
const char *entry_str,
956 GtkTreeIter *iter, gpointer user_data)
958 auto model =
static_cast<GtkTreeModel*
>(user_data);
959 gchar *existing_str = NULL;
961 gtk_tree_model_get (model, iter,
962 COMPLETION_LIST_NORMALIZED_FOLDED, &existing_str,
964 if (existing_str && *existing_str && strstr (existing_str, entry_str))
966 g_free (existing_str);
973 GObject *override_widget;
979 static void override_widget_clicked (GtkWidget *widget,
EntryInfo *entryinfo)
981 gtk_widget_set_visible (GTK_WIDGET (entryinfo->override_widget),
false);
982 gtk_widget_set_sensitive (entryinfo->entry,
true);
983 gtk_entry_set_text (GTK_ENTRY (entryinfo->entry),
"");
984 gtk_widget_grab_focus (entryinfo->entry);
985 entryinfo->can_edit =
true;
991 auto sensitive = entryinfo.can_edit;
992 auto entry = entryinfo.entry;
993 auto override_widget = GTK_WIDGET (entryinfo.override_widget);
994 auto hash = entryinfo.hash;
995 auto initial = entryinfo.initial;
997 gtk_widget_set_sensitive (entry, sensitive);
998 gtk_widget_set_visible (override_widget, !sensitive);
1000 if (sensitive && initial && *initial)
1001 gtk_entry_set_text (GTK_ENTRY (entry), initial);
1002 else if (!sensitive)
1004 gtk_entry_set_text (GTK_ENTRY (entry), _(
"Click Edit to modify"));
1005 g_signal_connect (override_widget,
"clicked", G_CALLBACK (override_widget_clicked),
1009 GtkListStore *list = gtk_list_store_new (NUM_COMPLETION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1010 g_hash_table_foreach (hash, (GHFunc)populate_list, list);
1011 if (initial && *initial && !g_hash_table_lookup (hash, (gpointer)initial))
1012 populate_list ((gpointer)initial, NULL, list);
1013 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list),
1014 COMPLETION_LIST_ORIGINAL,
1015 GTK_SORT_ASCENDING);
1017 GtkEntryCompletion *completion = gtk_entry_completion_new ();
1018 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL(list));
1019 gtk_entry_completion_set_text_column (completion, COMPLETION_LIST_ORIGINAL);
1020 gtk_entry_completion_set_match_func (completion,
1021 (GtkEntryCompletionMatchFunc)match_func,
1022 GTK_TREE_MODEL(list), NULL);
1023 gtk_entry_set_completion (GTK_ENTRY (entry), completion);
1027 input_new_fields (GNCImportMainMatcher *info,
RowInfo& rowinfo,
1028 char **new_desc,
char **new_notes,
char **new_memo)
1030 GtkBuilder *builder = gtk_builder_new ();
1031 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_edit_dialog");
1033 GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_edit_dialog"));
1036 gtk_widget_set_name (GTK_WIDGET(dialog),
"gnc-id-import-matcher-edits");
1037 gnc_widget_style_context_add_class (GTK_WIDGET(dialog),
"gnc-class-imports");
1039 GtkWidget *desc_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"desc_entry"));
1040 GtkWidget *memo_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"memo_entry"));
1041 GtkWidget *notes_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"notes_entry"));
1046 std::vector<EntryInfo> entries = {
1047 { desc_entry, gtk_builder_get_object (builder,
"desc_override"), info->can_edit_desc, info->desc_hash,
xaccTransGetDescription (trans) },
1048 { notes_entry, gtk_builder_get_object (builder,
"notes_override"), info->can_edit_notes, info->notes_hash,
xaccTransGetNotes (trans) },
1049 { memo_entry, gtk_builder_get_object (builder,
"memo_override"), info->can_edit_memo, info->memo_hash,
xaccSplitGetMemo (split) },
1052 std::for_each (entries.begin(), entries.end(), setup_entry);
1056 auto it = std::find_if (entries.begin(), entries.end(), [](
auto info){
return info.can_edit; });
1057 if (it != entries.end())
1058 gtk_widget_grab_focus (it->entry);
1060 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (info->main_widget));
1063 gtk_widget_show (dialog);
1065 bool retval =
false;
1066 switch (gtk_dialog_run (GTK_DIALOG(dialog)))
1068 case GTK_RESPONSE_OK:
1069 *new_desc = g_strdup (gtk_entry_get_text (GTK_ENTRY (desc_entry)));
1070 *new_notes = g_strdup (gtk_entry_get_text (GTK_ENTRY (notes_entry)));
1071 *new_memo = g_strdup (gtk_entry_get_text (GTK_ENTRY (memo_entry)));
1078 gtk_widget_destroy (dialog);
1079 g_object_unref (G_OBJECT(builder));
1084 maybe_add_string (GNCImportMainMatcher *info, GHashTable *hash,
const char *str)
1086 if (!str || !str[0] || g_hash_table_lookup (hash, str))
1088 char *new_string = g_strdup (str);
1089 info->new_strings = g_list_prepend (info->new_strings, new_string);
1090 g_hash_table_insert (hash, new_string, one);
1094 gnc_gen_trans_set_price_to_selection_cb (GtkMenuItem *menuitem,
1095 GNCImportMainMatcher *info)
1098 g_return_if_fail (info);
1100 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1101 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1102 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1103 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1107 LEAVE (
"No selected rows");
1111 for (GList *n = selected_rows; n; n = g_list_next (n))
1113 RowInfo row{
static_cast<GtkTreePath*
>(n->data), info};
1121 XferDialog *xfer = gnc_xfer_dialog(GTK_WIDGET (info->main_widget), src_acc);
1122 gnc_xfer_dialog_select_to_account(xfer, dest_acc);
1123 gnc_xfer_dialog_set_amount(xfer, dest_value);
1124 gnc_xfer_dialog_set_date (xfer, post_date);
1128 gnc_xfer_dialog_set_from_show_button_active(xfer,
false);
1129 gnc_xfer_dialog_set_to_show_button_active(xfer,
false);
1130 gnc_xfer_dialog_hide_from_account_tree(xfer);
1131 gnc_xfer_dialog_hide_to_account_tree(xfer);
1133 gnc_xfer_dialog_is_exchange_dialog(xfer, &exch);
1135 if (!gnc_xfer_dialog_run_until_done(xfer))
1147 refresh_model_row (info, model, row.get_iter(), row.get_trans_info());
1150 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1155 gnc_gen_trans_edit_fields (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1159 g_return_if_fail (info);
1161 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1162 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1163 GtkTreeStore *store = GTK_TREE_STORE (model);
1164 auto selected_refs = get_treeview_selection_refs (treeview, model);
1166 if (selected_refs.empty())
1168 LEAVE (
"No selected rows");
1172 char *new_desc = NULL, *new_notes = NULL, *new_memo = NULL;
1173 RowInfo first_row{selected_refs[0], info};
1174 if (input_new_fields (info, first_row, &new_desc, &new_notes, &new_memo))
1176 for (
const auto& ref : selected_refs)
1181 if (info->can_edit_desc)
1183 gint style = g_strcmp0 (new_desc, row.get_orig_desc()) ?
1184 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1185 gtk_tree_store_set (store, row.get_iter(),
1186 DOWNLOADED_COL_DESCRIPTION, new_desc,
1187 DOWNLOADED_COL_DESCRIPTION_STYLE, style,
1190 maybe_add_string (info, info->desc_hash, new_desc);
1193 if (info->can_edit_notes)
1196 maybe_add_string (info, info->notes_hash, new_notes);
1199 if (info->can_edit_memo)
1201 gint style = g_strcmp0 (new_memo, row.get_orig_memo()) ?
1202 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1203 gtk_tree_store_set (store, row.get_iter(),
1204 DOWNLOADED_COL_MEMO, new_memo,
1205 DOWNLOADED_COL_MEMO_STYLE, style,
1208 maybe_add_string (info, info->memo_hash, new_memo);
1219 gnc_gen_trans_reset_edits_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1221 g_return_if_fail (info);
1222 ENTER(
"gnc_gen_trans_reset_edits_cb");
1224 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1225 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1226 GtkTreeStore *store = GTK_TREE_STORE (model);
1227 auto selected_refs = get_treeview_selection_refs (treeview, model);
1229 if (selected_refs.empty())
1231 LEAVE (
"No selected rows");
1235 for (
const auto& ref : selected_refs)
1243 gtk_tree_store_set (store, rowinfo.get_iter(),
1244 DOWNLOADED_COL_DESCRIPTION, rowinfo.get_orig_desc(),
1245 DOWNLOADED_COL_MEMO, rowinfo.get_orig_memo(),
1246 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1247 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1254 gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
1256 GtkTreeViewColumn *column,
1257 GNCImportMainMatcher *info)
1262 bool is_selection =
false;
1263 Account *assigned_account = NULL;
1264 gnc_gen_trans_assign_transfer_account (treeview,
1265 &first, is_selection, path,
1266 &assigned_account, info);
1268 gtk_tree_selection_select_path (gtk_tree_view_get_selection (treeview), path);
1271 DEBUG(
"account returned = %s", namestr);
1276 static GNCImportAction
1277 get_action_for_path (GtkTreePath* path, GtkTreeModel *model)
1279 GNCImportTransInfo *trans_info;
1281 gtk_tree_model_get_iter (model, &iter, path);
1282 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
1286 return GNCImport_INVALID_ACTION;
1291 gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
1292 GNCImportMainMatcher *info)
1294 GtkTreeModel *model;
1298 if (gtk_tree_selection_count_selected_rows (selection) >= 2)
1301 GList* list = gtk_tree_selection_get_selected_rows (selection, &model);
1302 for (GList *n = list; n; n = n->next)
1304 auto path =
static_cast<GtkTreePath*
>(n->data);
1305 if (get_action_for_path (path, model) != GNCImport_ADD)
1306 gtk_tree_selection_unselect_path (selection, path);
1308 g_list_free_full (list, (GDestroyNotify)gtk_tree_path_free);
1311 GtkSelectionMode mode = gtk_tree_selection_get_mode (selection);
1314 case GTK_SELECTION_MULTIPLE:
1315 DEBUG(
"mode = GTK_SELECTION_MULTIPLE, no action");
1317 case GTK_SELECTION_NONE:
1318 DEBUG(
"mode = GTK_SELECTION_NONE, no action");
1320 case GTK_SELECTION_BROWSE:
1321 DEBUG(
"mode = GTK_SELECTION_BROWSE->default");
1322 case GTK_SELECTION_SINGLE:
1323 DEBUG(
"mode = GTK_SELECTION_SINGLE->default");
1325 DEBUG(
"mode = default unselect selected row");
1326 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1328 gtk_tree_selection_unselect_iter (selection, &iter);
1335 gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
1337 GNCImportMainMatcher *info)
1341 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1342 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1343 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1345 const char *desc = NULL, *memo = NULL, *notes = NULL;
1348 RowInfo first_rowinfo{
static_cast<GtkTreePath*
>(selected_rows->data), info};
1357 info->can_edit_desc =
true;
1358 info->can_edit_notes =
true;
1359 info->can_edit_memo =
true;
1360 bool can_undo_edits =
false;
1361 bool can_update_prices =
true;
1362 bool can_assign_acct =
true;
1363 for (GList *n = selected_rows; n; n = g_list_next(n))
1365 RowInfo rowinfo{
static_cast<GtkTreePath*
>(n->data), info};
1368 if (can_assign_acct)
1375 if (can_update_prices)
1381 can_update_prices =
false;
1387 if (info->can_edit_desc)
1389 if (info->can_edit_notes)
1391 if (info->can_edit_memo)
1396 if (!can_undo_edits)
1397 can_undo_edits = (g_strcmp0 (
xaccSplitGetMemo (split), rowinfo.get_orig_memo()) ||
1402 if (!can_assign_acct && !can_update_prices &&
1403 !info->can_edit_desc && !info->can_edit_notes && !info->can_edit_memo &&
1408 GtkWidget *menu = gtk_menu_new();
1410 auto add_menu_item = [&menu, &info](
const char* name,
bool sensitive, GCallback callback)
1412 auto menuitem = gtk_menu_item_new_with_mnemonic (_(name));
1413 gtk_widget_set_sensitive (menuitem, sensitive);
1414 g_signal_connect (menuitem,
"activate", callback, info);
1415 gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
1419 add_menu_item (N_(
"_Assign transfer account"),
1421 G_CALLBACK(gnc_gen_trans_assign_transfer_account_to_selection_cb));
1424 add_menu_item (N_(
"Assign e_xchange rate"),
1426 G_CALLBACK (gnc_gen_trans_set_price_to_selection_cb));
1429 add_menu_item (N_(
"_Edit description, notes, or memo"),
1430 info->can_edit_desc || info->can_edit_notes || info->can_edit_memo,
1431 G_CALLBACK (gnc_gen_trans_edit_fields));
1434 add_menu_item (N_(
"_Reset all edits"),
1436 G_CALLBACK (gnc_gen_trans_reset_edits_cb));
1438 gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (treeview), NULL);
1440 gtk_widget_show_all (menu);
1442 gtk_menu_popup_at_pointer (GTK_MENU(menu), (GdkEvent*)event);
1444 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1449 gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
1451 GNCImportMainMatcher *info)
1454 g_return_val_if_fail (treeview != NULL,
false);
1455 g_return_val_if_fail (event != NULL,
false);
1457 if (event->type == GDK_BUTTON_PRESS)
1459 GdkEventButton *event_button = (GdkEventButton *) event;
1460 if (event_button->button == GDK_BUTTON_SECONDARY)
1462 DEBUG(
"Right mouseClick detected - popup the menu.");
1464 auto selection = gtk_tree_view_get_selection (treeview);
1465 GtkTreePath* path =
nullptr;
1468 if (gtk_tree_view_get_path_at_pos (treeview, event_button->x,
1469 event_button->y, &path,
1470 nullptr,
nullptr,
nullptr))
1472 if (!gtk_tree_selection_path_is_selected (selection, path))
1474 gtk_tree_selection_unselect_all (selection);
1475 gtk_tree_selection_select_path (selection, path);
1477 gtk_tree_path_free (path);
1480 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1482 GtkTreeModel *model;
1483 auto selected = gtk_tree_selection_get_selected_rows (selection, &model);
1484 if (get_action_for_path (static_cast<GtkTreePath*>(selected->data), model) == GNCImport_ADD)
1485 gnc_gen_trans_view_popup_menu (treeview, event, info);
1486 g_list_free_full (selected, (GDestroyNotify)gtk_tree_path_free);
1488 LEAVE(
"return true");
1492 LEAVE(
"return false");
1497 gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
1498 GNCImportMainMatcher *info)
1500 ENTER(
"onPopupMenu_cb");
1502 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1503 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1505 gnc_gen_trans_view_popup_menu (treeview, NULL, info);
1513 static GtkTreeViewColumn *
1514 add_text_column (GtkTreeView *view,
const gchar *title,
int col_num,
bool ellipsize)
1516 GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1517 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title,
1520 "background", DOWNLOADED_COL_COLOR,
1524 g_object_set (renderer,
"ellipsize", PANGO_ELLIPSIZE_END, NULL);
1527 if (col_num == DOWNLOADED_COL_DATE_TXT)
1528 gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_DATE_INT64);
1529 else if (col_num == DOWNLOADED_COL_AMOUNT)
1531 gtk_cell_renderer_set_alignment (renderer, 1.0, 0.5);
1532 gtk_cell_renderer_set_padding (renderer, 5, 0);
1533 gtk_tree_view_column_set_sort_column_id (column, DOWNLOADED_COL_AMOUNT_DOUBLE);
1536 gtk_tree_view_column_set_sort_column_id (column, col_num);
1538 if (col_num == DOWNLOADED_COL_DESCRIPTION)
1539 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_DESCRIPTION_STYLE);
1541 if (col_num == DOWNLOADED_COL_MEMO)
1542 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_MEMO_STYLE);
1544 g_object_set (G_OBJECT(column),
1545 "reorderable",
true,
1548 gtk_tree_view_append_column (view, column);
1552 static GtkTreeViewColumn *
1553 add_toggle_column (GtkTreeView *view,
const gchar *title,
int col_num,
1554 GCallback cb_fn, gpointer cb_arg)
1556 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
1557 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title, renderer,
1559 "cell-background", DOWNLOADED_COL_COLOR,
1560 "activatable", DOWNLOADED_COL_ENABLE,
1561 "visible", DOWNLOADED_COL_ENABLE,
1563 gtk_tree_view_column_set_sort_column_id (column, col_num);
1564 g_object_set (G_OBJECT(column),
"reorderable",
true, NULL);
1565 g_signal_connect (renderer,
"toggled", cb_fn, cb_arg);
1566 gtk_tree_view_append_column (view, column);
1571 gnc_gen_trans_init_view (GNCImportMainMatcher *info,
1575 GtkTreeView *view = info->view;
1576 GtkTreeStore *store = gtk_tree_store_new (NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64,
1577 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE,
1578 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1579 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1580 G_TYPE_STRING, G_TYPE_BOOLEAN,
1581 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
1582 GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING,
1584 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
1585 g_object_unref (store);
1588 gtk_tree_view_set_reorderable (view,
false);
1591 add_text_column (view, _(
"Date"), DOWNLOADED_COL_DATE_TXT,
false);
1592 info->account_column = add_text_column (view, _(
"Account"), DOWNLOADED_COL_ACCOUNT,
false);
1593 gtk_tree_view_column_set_visible (info->account_column, show_account);
1594 add_text_column (view, _(
"Amount"), DOWNLOADED_COL_AMOUNT,
false);
1595 add_text_column (view, _(
"Description"), DOWNLOADED_COL_DESCRIPTION,
false);
1596 info->memo_column = add_text_column (view, _(
"Memo"), DOWNLOADED_COL_MEMO,
true);
1597 add_toggle_column (view, C_(
"Column header for 'Adding transaction'",
"A"),
1598 DOWNLOADED_COL_ACTION_ADD,
1599 G_CALLBACK(gnc_gen_trans_add_toggled_cb), info);
1600 GtkTreeViewColumn *column = add_toggle_column (view,
1601 C_(
"Column header for 'Updating plus Clearing transaction'",
"U+C"),
1602 DOWNLOADED_COL_ACTION_UPDATE,
1603 G_CALLBACK(gnc_gen_trans_update_toggled_cb), info);
1604 gtk_tree_view_column_set_visible (column, show_update);
1605 add_toggle_column (view, C_(
"Column header for 'Clearing transaction'",
"C"),
1606 DOWNLOADED_COL_ACTION_CLEAR,
1607 G_CALLBACK(gnc_gen_trans_clear_toggled_cb), info);
1610 GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
1611 g_object_set (renderer,
"xalign", 0.0, NULL);
1612 column = gtk_tree_view_column_new_with_attributes (_(
"Info"), renderer,
1613 "pixbuf", DOWNLOADED_COL_ACTION_PIXBUF,
1614 "cell-background", DOWNLOADED_COL_COLOR,
1617 gtk_tree_view_append_column (info->view, column);
1619 column = add_text_column (view, _(
"Additional Comments"), DOWNLOADED_COL_ACTION_INFO,
false);
1620 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1623 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
1624 DOWNLOADED_COL_DATE_INT64,
1625 GTK_SORT_ASCENDING);
1626 GtkTreeSelection *selection = gtk_tree_view_get_selection (info->view);
1628 g_object_set (info->view,
"has-tooltip",
true, NULL);
1630 g_signal_connect (G_OBJECT(info->view),
"query-tooltip",
1631 G_CALLBACK(query_tooltip_tree_view_cb), info);
1632 g_signal_connect (info->view,
"row-activated",
1633 G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
1634 g_signal_connect (selection,
"changed",
1635 G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
1636 g_signal_connect (view,
"button-press-event",
1637 G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
1638 g_signal_connect (view,
"popup-menu",
1639 G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
1643 show_account_column_toggled_cb (GtkToggleButton *togglebutton,
1644 GNCImportMainMatcher *info)
1646 gtk_tree_view_column_set_visible (info->account_column,
1647 gtk_toggle_button_get_active (togglebutton));
1651 show_memo_column_toggled_cb (GtkToggleButton *togglebutton,
1652 GNCImportMainMatcher *info)
1654 gtk_tree_view_column_set_visible (info->memo_column,
1655 gtk_toggle_button_get_active (togglebutton));
1659 show_matched_info_toggled_cb (GtkToggleButton *togglebutton,
1660 GNCImportMainMatcher *info)
1662 if (gtk_toggle_button_get_active (togglebutton))
1664 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
1665 gtk_tree_view_expand_all (info->view);
1669 gtk_tree_view_column_set_visible (info->account_column,
1670 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->show_account_column)));
1671 gtk_tree_view_collapse_all (info->view);
1676 gnc_gen_trans_common_setup (GNCImportMainMatcher *info,
1678 GtkBuilder *builder,
1679 const gchar* heading,
1680 bool all_from_same_account,
1681 gint match_date_hardlimit)
1683 info->pending_matches = gnc_import_PendingMatches_new ();
1689 GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(parent));
1691 gtk_style_context_get_color (stylectxt, GTK_STATE_FLAG_NORMAL, &color);
1695 info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder,
"downloaded_view"));
1696 g_assert (info->view != NULL);
1698 info->show_account_column = GTK_WIDGET(gtk_builder_get_object (builder,
"show_source_account_button"));
1699 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), all_from_same_account);
1700 g_signal_connect (G_OBJECT(info->show_account_column),
"toggled",
1701 G_CALLBACK(show_account_column_toggled_cb), info);
1703 GtkWidget *button = GTK_WIDGET(gtk_builder_get_object (builder,
"show_memo_column_button"));
1704 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
true);
1705 g_signal_connect (G_OBJECT(button),
"toggled",
1706 G_CALLBACK(show_memo_column_toggled_cb), info);
1708 info->show_matched_info = GTK_WIDGET(gtk_builder_get_object (builder,
"show_matched_info_button"));
1709 g_signal_connect (G_OBJECT(info->show_matched_info),
"toggled",
1710 G_CALLBACK(show_matched_info_toggled_cb), info);
1712 info->append_text = GTK_WIDGET(gtk_builder_get_object (builder,
"append_desc_notes_button"));
1715 info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder,
"reconcile_after_close_button"));
1718 GtkWidget *heading_label = GTK_WIDGET(gtk_builder_get_object (builder,
"heading_label"));
1720 gtk_label_set_text (GTK_LABEL(heading_label), heading);
1723 gnc_gen_trans_init_view (info, all_from_same_account, show_update);
1725 info->acct_id_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1726 (GDestroyNotify)g_hash_table_destroy);
1727 info->desc_hash = g_hash_table_new (g_str_hash, g_str_equal);
1728 info->notes_hash = g_hash_table_new (g_str_hash, g_str_equal);
1729 info->memo_hash = g_hash_table_new (g_str_hash, g_str_equal);
1730 info->new_strings = NULL;
1731 info->transaction_processed_cb = NULL;
1734 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
1736 g_object_unref (G_OBJECT(builder));
1740 GNCImportMainMatcher *
1742 const gchar* heading,
1743 bool all_from_same_account,
1744 gint match_date_hardlimit,
1747 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1750 GtkBuilder *builder = gtk_builder_new ();
1751 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_dialog");
1752 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1754 info->main_widget = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_dialog"));
1755 g_assert (info->main_widget != NULL);
1758 GtkWidget *pbox = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_vbox"));
1759 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1760 gtk_box_pack_start (GTK_BOX(pbox), box,
true,
true, 0);
1763 gtk_widget_set_name (GTK_WIDGET(info->main_widget),
"gnc-id-import-matcher-transactions");
1764 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1765 gnc_widget_style_context_add_class (GTK_WIDGET(info->main_widget),
"gnc-class-imports");
1768 gnc_gen_trans_common_setup (info, parent, builder, heading,
1769 all_from_same_account, match_date_hardlimit);
1772 gtk_window_set_transient_for (GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1774 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1777 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
1780 info->id = gnc_register_gui_component (IMPORT_MAIN_MATCHER_CM_CLASS,
1785 gnc_gui_component_set_session (info->id, gnc_get_current_session());
1794 GNCImportMainMatcher *
1796 GtkWidget *assistant_page,
1797 const gchar* heading,
1798 bool all_from_same_account,
1799 gint match_date_hardlimit)
1801 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1802 info->main_widget = GTK_WIDGET(parent);
1805 GtkBuilder *builder = gtk_builder_new ();
1806 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1809 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1810 g_assert (box != NULL);
1811 gtk_box_pack_start (GTK_BOX(assistant_page), box,
true,
true, 6);
1814 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1817 gnc_gen_trans_common_setup (info, parent, builder, heading,
1818 all_from_same_account, match_date_hardlimit);
1826 on_matcher_ok_clicked (NULL, info);
1835 GNCTransactionProcessedCB trans_processed_cb,
1838 info->user_data = user_data;
1839 info->transaction_processed_cb = trans_processed_cb;
1846 bool result = gtk_dialog_run (GTK_DIALOG (info->main_widget));
1856 get_required_color (
const gchar *class_name)
1859 GtkWidget *label = gtk_label_new (
"Color");
1860 GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET(label));
1861 gtk_style_context_add_class (context, class_name);
1863 static gchar *strbuf = NULL;
1866 strbuf = gdk_rgba_to_string (&color);
1871 remove_child_row (GtkTreeModel *model, GtkTreeIter *iter)
1873 if (gtk_tree_model_iter_has_child (model, iter))
1876 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1877 gtk_tree_store_remove (GTK_TREE_STORE(model), &child);
1882 update_child_row (
GNCImportMatchInfo *sel_match, GtkTreeModel *model, GtkTreeIter *iter)
1884 GtkTreeStore *store = GTK_TREE_STORE(model);
1886 if (!gtk_tree_model_iter_has_child (model, iter))
1887 gtk_tree_store_append (GTK_TREE_STORE(model), &child, iter);
1889 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1893 : _(
"-- Split Transaction --");
1897 gtk_tree_store_set (store, &child,
1898 DOWNLOADED_COL_ACCOUNT, account_str,
1899 DOWNLOADED_COL_DATE_TXT, date,
1900 DOWNLOADED_COL_AMOUNT, amount_str,
1902 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1904 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1905 DOWNLOADED_COL_ENABLE,
false,
1911 get_peer_acct_names (Split *split)
1913 GList *names = NULL, *accounts_seen = NULL;
1917 if ((n->data == split) ||
1919 (g_list_find (accounts_seen, account)))
1922 names = g_list_prepend (names, name);
1923 accounts_seen = g_list_prepend (accounts_seen, account);
1925 names = g_list_sort (names, (GCompareFunc)g_utf8_collate);
1927 g_list_free_full (names, g_free);
1928 g_list_free (accounts_seen);
1933 refresh_model_row (GNCImportMainMatcher *gui,
1934 GtkTreeModel *model,
1936 GNCImportTransInfo *info)
1943 GtkTreeStore *store = GTK_TREE_STORE(model);
1944 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATA, info, -1);
1946 const gchar *class_extension = NULL;
1947 if (gui->dark_theme)
1948 class_extension =
"-dark";
1950 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
1951 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
1952 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
1955 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ENABLE,
true, -1);
1961 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
1966 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_TXT, text, -1);
1967 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_INT64, date, -1);
1972 ro_text =
xaccPrintAmount (amount, gnc_split_amount_print_info (split,
true));
1973 gtk_tree_store_set (store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
1978 gtk_tree_store_set (store, iter, DOWNLOADED_COL_NOTES_ORIGINAL, ro_text, -1);
1982 gtk_tree_store_set (store, iter,
1983 DOWNLOADED_COL_DESCRIPTION, ro_text,
1984 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, ro_text,
1988 gtk_tree_store_set (store, iter,
1989 DOWNLOADED_COL_MEMO, ro_text,
1990 DOWNLOADED_COL_MEMO_ORIGINAL, ro_text,
1996 ro_text = text = NULL;
1997 const gchar *color = NULL;
1998 bool show_pixbuf =
true;
2004 ro_text = _(
"New, already balanced");
2005 color = get_required_color (int_not_required_class);
2010 char *imbalance = NULL;
2020 color = get_required_color (int_not_required_class);
2026 g_strdup_printf (_(
"New, transfer %s to (manual) \"%s\""),
2027 imbalance, acct_full_name);
2034 g_strdup_printf (_(
"New, transfer %s to (auto) \"%s\""),
2035 imbalance, acct_full_name);
2044 color = get_required_color (int_required_class);
2047 g_strdup_printf (_(
"New, UNBALANCED (need price to transfer %s to acct %s)!"),
2048 imbalance, acct_full_name);
2052 g_free (acct_full_name);
2060 color = get_required_color (int_prob_required_class);
2063 g_strdup_printf (_(
"New, UNBALANCED (need acct to transfer %s)!"),
2066 remove_child_row (model, iter);
2071 case GNCImport_CLEAR:
2077 gchar *full_names = get_peer_acct_names (sel_match->split);
2078 color = get_required_color (int_not_required_class);
2081 text = g_strdup_printf (_(
"Reconcile (manual) match to %s"),
2086 text = g_strdup_printf (_(
"Reconcile (auto) match to %s"),
2089 g_free (full_names);
2090 update_child_row (sel_match, model, iter);
2094 color = get_required_color (int_required_class);
2095 ro_text = _(
"Match missing!");
2096 show_pixbuf =
false;
2097 remove_child_row (model, iter);
2101 case GNCImport_UPDATE:
2106 gchar *full_names = get_peer_acct_names (sel_match->split);
2107 color = get_required_color (int_not_required_class);
2110 text = g_strdup_printf (_(
"Update and reconcile (manual) match to %s"),
2115 text = g_strdup_printf (_(
"Update and reconcile (auto) match to %s"),
2118 g_free (full_names);
2119 update_child_row (sel_match, model, iter);
2123 color = get_required_color (int_required_class);
2124 ro_text = _(
"Match missing!");
2125 show_pixbuf =
false;
2126 remove_child_row (model, iter);
2130 case GNCImport_SKIP:
2131 color = get_required_color (int_required_class);
2132 ro_text = _(
"Do not import (no action selected)");
2133 show_pixbuf =
false;
2134 remove_child_row (model, iter);
2138 ro_text =
"WRITEME, this is an unknown action";
2139 show_pixbuf =
false;
2143 gtk_tree_store_set (store, iter,
2144 DOWNLOADED_COL_COLOR, color,
2145 DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text,
2150 g_free (int_required_class);
2151 g_free (int_prob_required_class);
2152 g_free (int_not_required_class);
2155 gtk_tree_store_set (store, iter,
2156 DOWNLOADED_COL_ACTION_ADD,
2162 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2165 gtk_tree_store_set (store, iter,
2166 DOWNLOADED_COL_ACTION_CLEAR,
2173 gtk_tree_store_set (store, iter,
2174 DOWNLOADED_COL_ACTION_PIXBUF,
2178 GTK_WIDGET(gui->view)),
2181 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2184 gtk_tree_store_set (store, iter,
2185 DOWNLOADED_COL_ACTION_UPDATE,
2192 gtk_tree_store_set (store, iter,
2193 DOWNLOADED_COL_ACTION_PIXBUF,
2197 GTK_WIDGET(gui->view)),
2200 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2204 if (gtk_tree_model_iter_has_child (model, iter))
2206 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui->show_matched_info)))
2208 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
2210 gtk_tree_view_column_set_visible (gui->account_column,
true);
2211 gtk_tree_view_column_set_visible (gui->memo_column,
true);
2213 gtk_tree_view_expand_row (GTK_TREE_VIEW(gui->view), path,
true);
2214 gtk_tree_path_free (path);
2217 GtkTreeSelection *selection = gtk_tree_view_get_selection (gui->view);
2218 gtk_tree_selection_unselect_all (selection);
2223 bool reconcile_after_close,
2226 gtk_widget_set_visible (info->reconcile_after_close, reconcile_after_close);
2227 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->reconcile_after_close), active);
2233 return info->reconcile_after_close;
2238 gnc_gen_trans_list_add_trans_internal (GNCImportMainMatcher *gui, Transaction *trans,
2246 defer_bal_computation (gui, acc);
2252 DEBUG(
"%s",
"Transaction with same online ID exists, destroying current transaction");
2263 gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info);
2269 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, NULL);
2275 gnc_gen_trans_list_add_trans_internal (gui, trans, ref_id, NULL);
2282 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, lsplit);
2291 filter_existing_splits_on_account_and_date (GNCImportMainMatcher *gui)
2293 static const int secs_per_day = 86400;
2294 gint match_date_limit =
2296 time64 min_time=G_MAXINT64, max_time=0;
2297 time64 match_timelimit = match_date_limit * secs_per_day;
2298 GList *all_accounts = NULL;
2303 for (GSList* txn = gui->temp_trans_list; txn != NULL;
2304 txn = g_slist_next (txn))
2306 auto txn_info =
static_cast<GNCImportTransInfo*
>(txn->data);
2311 all_accounts = g_list_prepend (all_accounts, txn_account);
2312 min_time = MIN(min_time, txn_time);
2313 max_time = MAX(max_time, txn_time);
2317 Query *query = qof_query_create_for (GNC_ID_SPLIT);
2319 xaccQueryAddAccountMatch (query, all_accounts,
2321 xaccQueryAddDateMatchTT (query,
2322 true, min_time - match_timelimit,
2323 true, max_time + match_timelimit,
2326 g_list_free (all_accounts);
2327 GList *retval = g_list_copy (query_results);
2337 create_hash_of_potential_matches (GList *candidate_splits,
2338 GHashTable *account_hash)
2340 for (GList* candidate = candidate_splits; candidate != NULL;
2341 candidate = g_list_next (candidate))
2343 auto split =
static_cast<Split*
>(candidate->data);
2344 if (gnc_import_split_has_online_id (split))
2354 auto split_list =
static_cast<GSList*
>(g_hash_table_lookup (account_hash, split_account));
2355 g_hash_table_steal (account_hash, split_account);
2356 split_list = g_slist_prepend (split_list, split);
2357 g_hash_table_insert (account_hash, split_account, split_list);
2359 return account_hash;
2362 typedef struct _match_struct
2364 GNCImportTransInfo* transaction_info;
2365 gint display_threshold;
2366 gint date_threshold;
2367 gint date_not_threshold;
2368 double fuzzy_amount;
2375 s->display_threshold,
2377 s->date_not_threshold,
2387 perform_matching (GNCImportMainMatcher *gui, GHashTable *account_hash)
2389 GtkTreeModel* model = gtk_tree_view_get_model (gui->view);
2390 gint display_threshold =
2392 gint date_threshold =
2393 gnc_import_Settings_get_date_threshold (gui->user_settings);
2394 gint date_not_threshold =
2395 gnc_import_Settings_get_date_not_threshold (gui->user_settings);
2396 double fuzzy_amount =
2399 for (GSList *imported_txn = gui->temp_trans_list; imported_txn !=NULL;
2400 imported_txn = g_slist_next (imported_txn))
2402 auto txn_info =
static_cast<GNCImportTransInfo*
>(imported_txn->data);
2404 match_struct s = {txn_info, display_threshold, date_threshold, date_not_threshold, fuzzy_amount};
2406 g_slist_foreach (static_cast<GSList*>(g_hash_table_lookup (account_hash, importaccount)),
2407 (GFunc) match_helper, &s);
2413 bool match_selected_manually =
2417 gnc_import_PendingMatches_add_match (gui->pending_matches,
2419 match_selected_manually);
2422 gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
2423 refresh_model_row (gui, model, &iter, txn_info);
2428 gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui)
2430 GHashTable* account_hash =
2431 g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
2432 (GDestroyNotify)g_slist_free);
2434 GList *candidate_splits = filter_existing_splits_on_account_and_date (gui);
2436 create_hash_of_potential_matches (candidate_splits, account_hash);
2437 perform_matching (gui, account_hash);
2439 g_list_free (candidate_splits);
2440 g_hash_table_destroy (account_hash);
2448 return info->main_widget;
2455 return info->append_text;
2459 query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
2461 GtkTooltip *tooltip,
2464 GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
2465 GtkTreePath *path = NULL;
2466 GtkTreeViewColumn *column = NULL;
2467 gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &x, &y);
2468 if (keyboard_tip || !gtk_tree_view_get_path_at_pos (tree_view, x, y, &path,
2469 &column, NULL, NULL))
2471 gtk_tree_path_free (path);
2476 bool show_tooltip =
false;
2477 GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2479 if (gtk_tree_model_get_iter(model, &iter, path) && column)
2481 gchar *tooltip_text = NULL;
2484 gint num_col = gtk_tree_view_column_get_sort_column_id (column);
2487 case DOWNLOADED_COL_DESCRIPTION:
2488 gtk_tree_model_get (model, &iter,
2489 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &tooltip_text,
2492 case DOWNLOADED_COL_MEMO:
2493 gtk_tree_model_get (model, &iter,
2494 DOWNLOADED_COL_MEMO_ORIGINAL, &tooltip_text,
2502 if (tooltip_text && *tooltip_text)
2504 show_tooltip =
true;
2505 gtk_tooltip_set_text (tooltip, tooltip_text);
2506 gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, column, NULL);
2508 g_free (tooltip_text);
2511 gtk_tree_path_free (path);
2512 return show_tooltip;
void gnc_gen_trans_list_show_reconcile_after_close_button(GNCImportMainMatcher *info, bool reconcile_after_close, bool active)
Show and set the reconcile after close check button.
gnc_numeric gnc_import_TransInfo_get_dest_value(const GNCImportTransInfo *info)
Returns the destination split value for this TransInfo.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
void split_find_match(GNCImportTransInfo *trans_info, Split *split, gint display_threshold, gint date_threshold, gint date_not_threshold, double fuzzy_amount_difference)
The transaction matching heuristics are here.
void gnc_gen_trans_list_show_all(GNCImportMainMatcher *info)
Shows widgets.
gboolean xaccTransIsOpen(const Transaction *trans)
The xaccTransIsOpen() method returns TRUE if the transaction is open for editing. ...
utility functions for the GnuCash UI
GNCImportSettings * gnc_import_Settings_new(void)
Allocates a new GNCImportSettings object, and initialize it with the appropriate user prefs...
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
GdkPixbuf * gen_probability_pixbuf(gint score_original, GNCImportSettings *settings, GtkWidget *widget)
This function generates a new pixmap representing a match score.
void gnc_import_TransInfo_delete(GNCImportTransInfo *info)
Destructor.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
void xaccTransSetNotes(Transaction *trans, const char *notes)
Sets the transaction Notes.
gint gnc_import_Settings_get_display_threshold(GNCImportSettings *settings)
Return the selected threshold.
gboolean xaccAccountGetAppendText(const Account *acc)
Get the "import-append-text" flag for an account.
void gnc_import_TransInfo_set_ref_id(GNCImportTransInfo *info, guint32 ref_id)
Set the reference id for this TransInfo.
Tracking container for pending match status.
void gnc_import_Settings_delete(GNCImportSettings *settings)
Destructor.
#define DEBUG(format, args...)
Print a debugging message.
Generic importer backend interface.
GNCImportTransInfo * gnc_import_TransInfo_new(Transaction *trans, Account *base_acc)
Create a new object of GNCImportTransInfo here.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
globally unique ID User API
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
Returns the first split of the transaction of this TransInfo.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
void on_matcher_help_clicked(GtkButton *button, gpointer user_data)
This allows for the transaction help dialog to be started from the assistant button callback...
Transaction matcher main window.
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
Returns the transaction of this TransInfo.
gboolean gnc_is_dark_theme(GdkRGBA *fg_color)
Return whether the current gtk theme is a dark one.
gint gnc_import_Settings_get_match_date_hardlimit(const GNCImportSettings *s)
Returns the hard-limiting number of days that a matching split may differ.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
Account * gnc_import_select_account(GtkWidget *parent, const gchar *account_online_id_value, gboolean prompt_on_no_match, const gchar *account_human_description, const gnc_commodity *new_account_default_commodity, GNCAccountType new_account_default_type, Account *default_selection, gboolean *ok_pressed)
Must be called with a string containing a unique identifier for the account.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info, GNCTransactionProcessedCB trans_processed_cb, gpointer user_data)
Add transaction processed callback to the transaction importer.
Generic and very flexible account matcher/picker.
GtkWidget * gnc_gen_trans_list_append_text_widget(GNCImportMainMatcher *info)
Returns the append_text widget of this dialog.
void gnc_import_TransInfo_set_destacc(GNCImportTransInfo *info, Account *acc, gboolean selected_manually)
Set the 'other account' of this transaction (used for auto-balance if needed).
Import preference handling.
GNCImportMainMatcher * gnc_gen_trans_assist_new(GtkWidget *parent, GtkWidget *assistant_page, const gchar *heading, bool all_from_same_account, gint match_date_hardlimit)
Add the Transaction matcher to an existing page of an assistant.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
void gnc_style_context_get_background_color(GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
Wrapper to get the background color of a widget for a given state.
void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
Add a newly imported Transaction to the Transaction Importer.
void gnc_import_TransInfo_init_matches(GNCImportTransInfo *trans_info, GNCImportSettings *settings)
Iterates through all splits of trans_info's originating account match list.
GNCImportAction gnc_import_TransInfo_get_action(const GNCImportTransInfo *info)
Returns the currently selected action for this TransInfo.
Account used to record multiple commodity transactions.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
bool gnc_gen_trans_list_empty(GNCImportMainMatcher *info)
Checks whether there are no transactions to match.
gboolean qof_log_check(QofLogModule domain, QofLogLevel level)
Check to see if the given log_module is configured to log at the given log_level. ...
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
char * gnc_get_account_name_for_register(const Account *account)
Get either the full name of the account or the simple name, depending on the configuration parameter ...
int xaccTransCountSplits(const Transaction *trans)
Returns the number of splits in this transaction.
gboolean gnc_import_process_trans_item(Account *base_acc, GNCImportTransInfo *trans_info)
/brief – Processes one match according to its selected action.
void gnc_gen_trans_list_add_trans_with_split_data(GNCImportMainMatcher *gui, Transaction *trans, GNCImportLastSplitInfo *lsplit)
Add a newly imported Transaction to the Transaction Importer.
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
gnc_numeric gnc_numeric_invert(gnc_numeric num)
Invert a gnc_numeric.
gint gnc_import_MatchInfo_get_probability(const GNCImportMatchInfo *info)
Get the probability (confidence level) of this MatchInfo.
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
GtkWidget * gnc_gen_trans_list_get_reconcile_after_close_button(GNCImportMainMatcher *info)
Returns the reconcile after close check button.
GtkWidget * gnc_gen_trans_list_widget(GNCImportMainMatcher *info)
Returns the widget of this dialog.
Account public routines (C++ api)
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
void gnc_gen_trans_assist_start(GNCImportMainMatcher *info)
This starts the import process for transaction from an assistant.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
GNCImportMainMatcher * gnc_gen_trans_list_new(GtkWidget *parent, const gchar *heading, bool all_from_same_account, gint match_date_hardlimit, bool show_all)
Create a new generic transaction dialog window and return it.
gchar * gnc_list_formatter(GList *strings)
This function takes a GList of char*, and uses locale-sensitive list formatter.
void gnc_import_TransInfo_set_action(GNCImportTransInfo *info, GNCImportAction action)
Set the action for this TransInfo.
void gnc_import_Settings_set_match_date_hardlimit(GNCImportSettings *s, gint m)
void xaccAccountRecomputeBalance(Account *acc)
The following recompute the partial balances (stored with the transaction) and the total balance...
gboolean gnc_import_exists_online_id(Transaction *trans, GHashTable *acct_id_hash)
Checks whether the given transaction's online_id already exists in its parent account.
double gnc_import_Settings_get_fuzzy_amount(GNCImportSettings *settings)
Return the allowed amount range for fuzzy amount matching.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
gboolean gnc_account_get_defer_bal_computation(Account *acc)
Get the account's flag for deferred balance computation.
gnc_numeric gnc_import_TransInfo_get_dest_amount(const GNCImportTransInfo *info)
Returns the destination split amount for this TransInfo.
void gnc_import_TransInfo_set_append_text(GNCImportTransInfo *info, gboolean append_text)
Set the append_text for this TransInfo.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
All type declarations for the whole Gnucash engine.
void xaccAccountSetAppendText(Account *acc, gboolean val)
Set the "import-append-text" flag for an account.
#define xaccTransGetGUID(X)
void gnc_import_TransInfo_set_price(GNCImportTransInfo *info, gnc_numeric lprice)
Set the exchange rate for this TransInfo.
void gnc_gen_trans_list_add_trans_with_ref_id(GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)
Add a newly imported Transaction to the Transaction Importer and provide an external reference id for...
gboolean gnc_import_Settings_get_action_update_enabled(GNCImportSettings *settings)
Return the selected action is enable state.
gboolean gnc_import_TransInfo_get_match_selected_manually(const GNCImportTransInfo *info)
Returns if the currently selected match was selected by the user.
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
void gnc_import_match_picker_run_and_close(GtkWidget *parent, GNCImportTransInfo *transaction_info, GNCImportPendingMatches *pending_matches)
Run a match_picker dialog so that the selected-MatchInfo in the given trans_info is updated according...
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
void gnc_gen_trans_list_delete(GNCImportMainMatcher *info)
Deletes the given object.
bool gnc_gen_trans_list_run(GNCImportMainMatcher *info)
Run this dialog and return only after the user pressed Ok, Cancel, or closed the window.
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
#define LEAVE(format, args...)
Print a function exit debugging message.
Account * gnc_import_TransInfo_get_destacc(const GNCImportTransInfo *info)
Returns the 'other account' of this transaction.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
gnc_numeric gnc_import_TransInfo_get_price(const GNCImportTransInfo *info)
Returns the exchange rate for this TransInfo.
GList * gnc_import_TransInfo_get_match_list(const GNCImportTransInfo *info)
Returns the stored list of possible matches.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)
Returns the currently selected match in this TransInfo.
void gnc_account_set_defer_bal_computation(Account *acc, gboolean defer)
Set the defer balance flag.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
void gnc_import_TransInfo_remove_top_match(GNCImportTransInfo *info)
Remove the first match in the list of possible matches.
The type used to store guids in C.
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gboolean gnc_import_Settings_get_action_skip_enabled(GNCImportSettings *settings)
Return the selected action is enable state.
gboolean gnc_import_TransInfo_is_balanced(const GNCImportTransInfo *info)
Returns if the transaction stored in the TransInfo is currently balanced.
void gnc_import_TransInfo_set_last_split_info(GNCImportTransInfo *info, GNCImportLastSplitInfo *lsplit)
Sets additional parameters to be used to generate the closing split.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
gboolean gnc_import_TransInfo_get_destacc_selected_manually(const GNCImportTransInfo *info)
Returns if the currently selected destination account for auto-matching was selected by the user...