38 #include <glib/gi18n.h> 44 #include <unordered_map> 50 #include "dialog-transfer.h" 51 #include "dialog-utils.h" 61 #include "gnc-component-manager.h" 63 #include "gnc-session.h" 66 #define GNC_PREFS_GROUP "dialogs.import.generic.transaction-list" 67 #define IMPORT_MAIN_MATCHER_CM_CLASS "transaction-matcher-dialog" 69 using StrStrMap = std::unordered_map<std::string,std::string>;
73 GtkWidget *main_widget;
75 GNCImportSettings *user_settings;
78 GNCTransactionProcessedCB transaction_processed_cb;
80 GNCImportPendingMatches *pending_matches;
81 GtkTreeViewColumn *account_column;
82 GtkTreeViewColumn *memo_column;
83 GtkWidget *show_account_column;
84 GtkWidget *show_matched_info;
85 GtkWidget *append_text;
86 GtkWidget *reconcile_after_close;
89 GSList* temp_trans_list;
90 GHashTable* acct_id_hash;
91 GSList* edited_accounts;
98 GHashTable *desc_hash;
99 GHashTable *notes_hash;
100 GHashTable *memo_hash;
108 DOWNLOADED_COL_DATE_TXT = 0,
109 DOWNLOADED_COL_DATE_INT64,
110 DOWNLOADED_COL_ACCOUNT,
111 DOWNLOADED_COL_AMOUNT,
112 DOWNLOADED_COL_AMOUNT_DOUBLE,
113 DOWNLOADED_COL_DESCRIPTION,
114 DOWNLOADED_COL_DESCRIPTION_ORIGINAL,
115 DOWNLOADED_COL_DESCRIPTION_STYLE,
117 DOWNLOADED_COL_MEMO_ORIGINAL,
118 DOWNLOADED_COL_MEMO_STYLE,
119 DOWNLOADED_COL_NOTES_ORIGINAL,
120 DOWNLOADED_COL_ACTION_ADD,
121 DOWNLOADED_COL_ACTION_CLEAR,
122 DOWNLOADED_COL_ACTION_UPDATE,
123 DOWNLOADED_COL_ACTION_INFO,
124 DOWNLOADED_COL_ACTION_PIXBUF,
126 DOWNLOADED_COL_COLOR,
127 DOWNLOADED_COL_ENABLE,
131 #define CSS_INT_REQUIRED_CLASS "gnc-class-intervention-required" 132 #define CSS_INT_PROB_REQUIRED_CLASS "gnc-class-intervention-probably-required" 133 #define CSS_INT_NOT_REQUIRED_CLASS "gnc-class-intervention-not-required" 136 #define G_MOD_IMPORT_MATCHER "gnc.import.main-matcher" 138 static QofLogModule log_module = G_MOD_IMPORT_MATCHER;
140 static const gpointer one = GINT_TO_POINTER (1);
143 void on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info);
144 void on_matcher_cancel_clicked (GtkButton *button, gpointer user_data);
145 bool on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data);
147 void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data);
150 static void gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui);
153 static void gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview,
158 GNCImportMainMatcher *info);
159 static void gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
160 GNCImportMainMatcher *info);
161 static void gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
163 GNCImportMainMatcher *info);
164 static bool gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
166 GNCImportMainMatcher *info);
167 static bool gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
168 GNCImportMainMatcher *info);
169 static void refresh_model_row (GNCImportMainMatcher *gui,
172 GNCImportTransInfo *info);
173 static bool query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
180 update_all_balances (GNCImportMainMatcher *info)
182 for (GSList* iter = info->edited_accounts; iter; iter=iter->next)
184 auto acct =
static_cast<Account*
>(iter->data);
188 g_slist_free (info->edited_accounts);
189 info->edited_accounts = NULL;
193 defer_bal_computation (GNCImportMainMatcher *info,
Account* acc)
198 info->edited_accounts = g_slist_prepend (info->edited_accounts, acc);
209 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
211 if (gtk_tree_model_get_iter_first (model, &iter))
215 GNCImportTransInfo *trans_info;
216 gtk_tree_model_get (model, &iter,
217 DOWNLOADED_COL_DATA, &trans_info,
220 if (info->transaction_processed_cb)
222 info->transaction_processed_cb (trans_info,
false,
226 while (gtk_tree_model_iter_next (model, &iter));
229 if (GTK_IS_DIALOG(info->main_widget))
231 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget));
233 gnc_unregister_gui_component (info->id);
234 gtk_widget_destroy (GTK_WIDGET(info->main_widget));
240 info->temp_trans_list = NULL;
243 update_all_balances (info);
245 gnc_import_PendingMatches_delete (info->pending_matches);
246 g_hash_table_destroy (info->acct_id_hash);
247 g_hash_table_destroy (info->desc_hash);
248 g_hash_table_destroy (info->notes_hash);
249 g_hash_table_destroy (info->memo_hash);
250 info->colormap.~StrStrMap();
252 g_list_free_full (info->new_strings, (GDestroyNotify)g_free);
256 if (!gnc_gui_refresh_suspended ())
257 gnc_gui_refresh_all ();
266 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
268 return !gtk_tree_model_get_iter_first (model, &iter) && !info->temp_trans_list;
272 gnc_gen_trans_list_show_accounts_column (GNCImportMainMatcher *info)
276 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
277 if (gtk_tree_model_iter_n_children (model, NULL) > 1)
279 bool multiple_accounts =
false;
283 bool valid = gtk_tree_model_get_iter_first (model, &iter);
287 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &account_name, -1);
289 valid = gtk_tree_model_iter_next (model, &iter);
293 gchar *test_account_name;
294 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &test_account_name, -1);
295 if (g_strcmp0 (account_name, test_account_name) != 0)
297 multiple_accounts =
true;
298 g_free (test_account_name);
301 valid = gtk_tree_model_iter_next (model, &iter);
302 g_free (test_account_name);
304 g_free (account_name);
307 if (multiple_accounts)
309 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
310 gtk_tree_view_expand_all (info->view);
314 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
false);
315 gtk_tree_view_collapse_all (info->view);
322 get_top_trans_match_id (GList* match_list)
324 if (!match_list || !match_list->data)
return NULL;
326 Transaction *trans = match_info->trans;
332 get_top_trans_match_score (GList* match_list)
334 if (!match_list || !match_list->data)
return 0;
336 return match_info->probability;
340 get_trans_match_list (GtkTreeModel* model, GtkTreeIter* iter)
342 GNCImportTransInfo *transaction_info;
343 gtk_tree_model_get (model, iter,
344 DOWNLOADED_COL_DATA, &transaction_info,
349 static GNCImportTransInfo*
350 get_trans_info (GtkTreeModel* model, GtkTreeIter* iter)
352 GNCImportTransInfo *transaction_info;
353 gtk_tree_model_get (model, iter,
354 DOWNLOADED_COL_DATA, &transaction_info,
356 return transaction_info;
364 get_conflict_list (GtkTreeModel* model, GtkTreeIter import_iter,
GncGUID*
id, gint best_match)
366 GtkTreeIter iter = import_iter;
367 GNCImportTransInfo* best_import = get_trans_info (model, &import_iter);
368 GList* conflicts = g_list_prepend (NULL, best_import);
370 while (gtk_tree_model_iter_next (model, &iter))
372 gint match_score = 0;
373 GNCImportTransInfo* trans_info;
376 GList* register_iter = get_trans_match_list (model, &iter);
377 if (!register_iter || !register_iter->data)
380 id2 = *get_top_trans_match_id (register_iter);
385 match_score = get_top_trans_match_score (register_iter);
386 trans_info = get_trans_info (model, &iter);
387 conflicts = g_list_prepend (conflicts, trans_info);
389 if (match_score > best_match)
392 best_match = match_score;
393 best_import = trans_info;
398 conflicts = g_list_remove (conflicts, best_import);
403 remove_top_matches (GList* conflicts)
405 for (GList* iter = conflicts; iter && iter->data; iter=iter->next)
410 resolve_conflicts (GNCImportMainMatcher *info)
412 GtkTreeModel* model = gtk_tree_view_get_model (info->view);
413 GtkTreeIter import_iter;
419 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
422 GList *match_list = get_trans_match_list (model, &import_iter);
423 if (!match_list || !match_list->data)
425 valid = gtk_tree_model_iter_next (model, &import_iter);
430 GncGUID id = *get_top_trans_match_id (match_list);
431 best_match = get_top_trans_match_score (match_list);
434 GList *conflicts = get_conflict_list (model, import_iter, &
id, best_match);
438 remove_top_matches (conflicts);
441 valid = gtk_tree_model_get_iter_first (model, &import_iter);
444 valid = gtk_tree_model_iter_next (model, &import_iter);
448 g_list_free (conflicts);
452 valid = gtk_tree_model_get_iter_first (model, &import_iter);
455 refresh_model_row (info, model, &import_iter, get_trans_info (model, &import_iter));
456 valid = gtk_tree_model_iter_next (model, &import_iter);
462 load_hash_tables (GNCImportMainMatcher *info)
464 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
465 GtkTreeIter import_iter;
466 GList *accounts_list = NULL;
467 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
470 GNCImportTransInfo *trans_info = get_trans_info (model, &import_iter);
473 if (!g_list_find (accounts_list, acc))
474 accounts_list = g_list_prepend (accounts_list, acc);
475 valid = gtk_tree_model_iter_next (model, &import_iter);
477 for (GList *m = accounts_list; m; m = m->next)
479 for (
auto s : xaccAccountGetSplits (static_cast<Account*>(m->data)))
485 g_hash_table_insert (info->desc_hash, (gpointer)key, one);
489 g_hash_table_insert (info->notes_hash, (gpointer)key, one);
493 g_hash_table_insert (info->memo_hash, (gpointer)key, one);
496 g_list_free (accounts_list);
506 GSList *temp_trans_list = info->temp_trans_list;
507 if (!temp_trans_list)
509 gnc_info_dialog (GTK_WINDOW (info->main_widget),
"%s", _(
"No new transactions were found in this import."));
512 auto trans_info =
static_cast<GNCImportTransInfo *
>(temp_trans_list->data);
515 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (info->append_text),
518 gnc_gen_trans_list_create_matches (info);
519 load_hash_tables (info);
520 resolve_conflicts (info);
521 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
522 gnc_gen_trans_list_show_accounts_column (info);
525 static void acc_begin_edit (GList **accounts_modified,
Account *acc)
527 if (!acc || !accounts_modified || g_list_find (*accounts_modified, acc))
532 *accounts_modified = g_list_prepend (*accounts_modified, acc);
535 on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
541 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
543 if (!gtk_tree_model_get_iter_first (model, &iter))
552 gnc_suspend_gui_refresh ();
553 bool first_tran =
true;
554 bool append_text = gtk_toggle_button_get_active ((GtkToggleButton*) info->append_text);
555 GList *accounts_modified = NULL;
558 GNCImportTransInfo *trans_info;
559 gtk_tree_model_get (model, &iter,
560 DOWNLOADED_COL_DATA, &trans_info,
584 acc_begin_edit (&accounts_modified, dest_acc);
588 if (info->transaction_processed_cb)
590 info->transaction_processed_cb (trans_info,
true,
595 while (gtk_tree_model_iter_next (model, &iter));
603 gnc_resume_gui_refresh ();
607 on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
609 auto info =
static_cast<GNCImportMainMatcher *
>(user_data);
614 on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
616 auto info =
static_cast<GNCImportMainMatcher *
>(data);
622 on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
624 auto help_dialog =
static_cast<GtkWidget *
>(user_data);
626 gtk_widget_destroy (help_dialog);
632 auto info =
static_cast<GNCImportMainMatcher*
>(user_data);
634 GtkBuilder *builder = gtk_builder_new ();
635 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer2");
636 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer3");
637 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer4");
638 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer5");
639 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer1");
640 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"matcher_help_dialog");
642 const gchar *class_extension = NULL;
643 if (info->dark_theme ==
true)
644 class_extension =
"-dark";
646 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
647 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
648 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
650 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_required_box"));
651 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_required_class);
653 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_probably_required_box"));
654 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_prob_required_class);
656 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_not_required_box"));
657 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_not_required_class);
659 GtkWidget *help_dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"matcher_help_dialog"));
660 gtk_window_set_transient_for (GTK_WINDOW(help_dialog), GTK_WINDOW(info->main_widget));
663 gtk_widget_set_name (GTK_WIDGET(help_dialog),
"gnc-id-import-matcher-help");
664 gnc_widget_style_context_add_class (GTK_WIDGET(help_dialog),
"gnc-class-imports");
667 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
669 g_object_unref (G_OBJECT(builder));
671 g_free (int_required_class);
672 g_free (int_prob_required_class);
673 g_free (int_not_required_class);
675 gtk_widget_show (help_dialog);
679 run_match_dialog (GNCImportMainMatcher *info,
680 GNCImportTransInfo *trans_info)
683 trans_info, info->pending_matches);
687 set_treeview_selection_from_path (GtkTreeView* view,
const char* path)
689 auto selection = gtk_tree_view_get_selection (view);
690 auto tree_path = gtk_tree_path_new_from_string (path);
691 gtk_tree_selection_select_path (selection, tree_path);
692 gtk_tree_path_free (tree_path);
696 gen_trans_common_toggled_cb (GtkCellRendererToggle *cell_renderer, gchar *path,
697 GNCImportMainMatcher *gui, GNCImportAction action)
699 auto model = gtk_tree_view_get_model (gui->view);
700 GtkTreeIter tree_iter;
701 g_return_if_fail (gtk_tree_model_get_iter_from_string (model, &tree_iter, path));
703 GNCImportTransInfo *transaction_info;
704 gtk_tree_model_get (model, &tree_iter, DOWNLOADED_COL_DATA, &transaction_info, -1);
710 refresh_model_row (gui, model, &tree_iter, transaction_info);
712 set_treeview_selection_from_path (GTK_TREE_VIEW(gui->view), path);
716 gnc_gen_trans_add_toggled_cb (GtkCellRendererToggle *cell_renderer,
718 GNCImportMainMatcher *gui)
720 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_ADD);
724 gnc_gen_trans_clear_toggled_cb (GtkCellRendererToggle *cell_renderer,
726 GNCImportMainMatcher *gui)
728 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_CLEAR);
732 gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
734 GNCImportMainMatcher *gui)
736 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_UPDATE);
740 gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview,
745 GNCImportMainMatcher *info)
747 gchar *path_str = gtk_tree_path_to_string (path);
751 DEBUG(
"first = %s", *first ?
"true" :
"false");
752 DEBUG(
"is_selection = %s", is_selection ?
"true" :
"false");
753 DEBUG(
"path = %s", path_str);
755 DEBUG(
"account passed in = %s", acct_str);
759 if (gtk_tree_path_get_depth (path) != 1)
762 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
764 if (gtk_tree_model_get_iter (model, &iter, path))
766 GNCImportTransInfo *trans_info;
767 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
777 gchar *acc_full_name;
781 _(
"Destination account for the auto-balance split."),
789 DEBUG(
"account selected = %s", acc_full_name);
790 g_free (acc_full_name);
795 defer_bal_computation (info, *new_acc);
799 case GNCImport_CLEAR:
800 case GNCImport_UPDATE:
801 if (*first && !is_selection)
802 run_match_dialog (info, trans_info);
807 PERR(
"InvalidGNCImportValue");
810 refresh_model_row (info, model, &iter, trans_info);
818 void operator()(GtkTreeRowReference* ptr)
const { gtk_tree_row_reference_free (ptr); }
821 using TreeRowReferencePtr = std::unique_ptr<GtkTreeRowReference, TreeRowRefDestructor>;
825 static std::vector<TreeRowReferencePtr>
826 get_treeview_selection_refs (GtkTreeView *treeview, GtkTreeModel *model)
828 std::vector<TreeRowReferencePtr> rv;
830 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview) && GTK_IS_TREE_MODEL (model), rv);
832 auto selection = gtk_tree_view_get_selection (treeview);
833 auto selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
835 for (
auto n = selected_rows; n; n = g_list_next (n))
836 rv.emplace_back (gtk_tree_row_reference_new (model, static_cast<GtkTreePath*>(n->data)));
838 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
843 gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
844 GNCImportMainMatcher *info)
848 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
849 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
850 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
851 auto selected_refs = get_treeview_selection_refs (treeview, model);
852 Account *assigned_account = NULL;
854 bool is_selection =
true;
857 DEBUG(
"Rows in selection = %zu", selected_refs.size());
859 for (
const auto& ref : selected_refs)
861 auto path = gtk_tree_row_reference_get_path (ref.get());
862 if (debugging_enabled)
864 auto path_str = gtk_tree_path_to_string (path);
865 DEBUG(
"passing first = %s", first ?
"true" :
"false");
866 DEBUG(
"passing is_selection = %s", is_selection ?
"true" :
"false");
867 DEBUG(
"passing path = %s", path_str);
870 gnc_gen_trans_assign_transfer_account (treeview,
871 &first, is_selection, path,
872 &assigned_account, info);
873 if (debugging_enabled)
876 DEBUG(
"returned value of account = %s", fullname);
877 DEBUG(
"returned value of first = %s", first ?
"true" :
"false");
881 gtk_tree_path_free (path);
882 if (!assigned_account)
887 for (
const auto& ref : selected_refs)
889 GtkTreePath *path = gtk_tree_row_reference_get_path (ref.get());
890 gtk_tree_selection_select_path (selection, path);
891 gtk_tree_path_free (path);
900 RowInfo (GtkTreePath *path, GNCImportMainMatcher *info)
902 init_from_path (path, info);
904 RowInfo (
const TreeRowReferencePtr &ref, GNCImportMainMatcher *info)
906 auto path = gtk_tree_row_reference_get_path (ref.get());
907 init_from_path (path, info);
908 gtk_tree_path_free (path);
912 g_free (m_orig_desc);
913 g_free (m_orig_notes);
914 g_free (m_orig_memo);
916 GNCImportTransInfo* get_trans_info () {
return m_trans_info; };
917 GtkTreeIter* get_iter () {
return &m_iter; };
918 const char* get_orig_desc () {
return m_orig_desc; };
919 const char* get_orig_notes () {
return m_orig_notes; };
920 const char* get_orig_memo () {
return m_orig_memo; };
922 void init_from_path (GtkTreePath *path, GNCImportMainMatcher *info)
924 auto model = gtk_tree_view_get_model (info->view);
925 gtk_tree_model_get_iter (model, &m_iter, path);
926 gtk_tree_model_get (model, &m_iter,
927 DOWNLOADED_COL_DATA, &m_trans_info,
928 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &m_orig_desc,
929 DOWNLOADED_COL_NOTES_ORIGINAL, &m_orig_notes,
930 DOWNLOADED_COL_MEMO_ORIGINAL, &m_orig_memo,
933 GNCImportTransInfo *m_trans_info;
935 char *m_orig_desc, *m_orig_notes, *m_orig_memo;
940 COMPLETION_LIST_ORIGINAL,
941 COMPLETION_LIST_NORMALIZED_FOLDED,
945 static void populate_list (gpointer key, gpointer value, GtkListStore *list)
948 auto original =
static_cast<const char*
>(key);
949 char *normalized = g_utf8_normalize (original, -1, G_NORMALIZE_NFC);
950 char *normalized_folded = normalized ? g_utf8_casefold (normalized, -1) : NULL;
951 gtk_list_store_append (list, &iter);
952 gtk_list_store_set (list, &iter,
953 COMPLETION_LIST_ORIGINAL, original,
954 COMPLETION_LIST_NORMALIZED_FOLDED, normalized_folded,
956 g_free (normalized_folded);
961 match_func (GtkEntryCompletion *completion,
const char *entry_str,
962 GtkTreeIter *iter, gpointer user_data)
964 auto model =
static_cast<GtkTreeModel*
>(user_data);
965 gchar *existing_str = NULL;
967 gtk_tree_model_get (model, iter,
968 COMPLETION_LIST_NORMALIZED_FOLDED, &existing_str,
970 if (existing_str && *existing_str && strstr (existing_str, entry_str))
972 g_free (existing_str);
979 GObject *override_widget;
985 static void override_widget_clicked (GtkWidget *widget,
EntryInfo *entryinfo)
987 gtk_widget_set_visible (GTK_WIDGET (entryinfo->override_widget),
false);
988 gtk_widget_set_sensitive (entryinfo->entry,
true);
989 gtk_entry_set_text (GTK_ENTRY (entryinfo->entry),
"");
990 gtk_widget_grab_focus (entryinfo->entry);
991 entryinfo->can_edit =
true;
997 auto sensitive = entryinfo.can_edit;
998 auto entry = entryinfo.entry;
999 auto override_widget = GTK_WIDGET (entryinfo.override_widget);
1000 auto hash = entryinfo.hash;
1001 auto initial = entryinfo.initial;
1003 gtk_widget_set_sensitive (entry, sensitive);
1004 gtk_widget_set_visible (override_widget, !sensitive);
1006 if (sensitive && initial && *initial)
1007 gtk_entry_set_text (GTK_ENTRY (entry), initial);
1008 else if (!sensitive)
1010 gtk_entry_set_text (GTK_ENTRY (entry), _(
"Click Edit to modify"));
1011 g_signal_connect (override_widget,
"clicked", G_CALLBACK (override_widget_clicked),
1015 GtkListStore *list = gtk_list_store_new (NUM_COMPLETION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1016 g_hash_table_foreach (hash, (GHFunc)populate_list, list);
1017 if (initial && *initial && !g_hash_table_lookup (hash, (gpointer)initial))
1018 populate_list ((gpointer)initial, NULL, list);
1019 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list),
1020 COMPLETION_LIST_ORIGINAL,
1021 GTK_SORT_ASCENDING);
1023 GtkEntryCompletion *completion = gtk_entry_completion_new ();
1024 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL(list));
1025 gtk_entry_completion_set_text_column (completion, COMPLETION_LIST_ORIGINAL);
1026 gtk_entry_completion_set_match_func (completion,
1027 (GtkEntryCompletionMatchFunc)match_func,
1028 GTK_TREE_MODEL(list), NULL);
1029 gtk_entry_set_completion (GTK_ENTRY (entry), completion);
1033 input_new_fields (GNCImportMainMatcher *info,
RowInfo& rowinfo,
1034 char **new_desc,
char **new_notes,
char **new_memo)
1036 GtkBuilder *builder = gtk_builder_new ();
1037 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_edit_dialog");
1039 GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_edit_dialog"));
1042 gtk_widget_set_name (GTK_WIDGET(dialog),
"gnc-id-import-matcher-edits");
1043 gnc_widget_style_context_add_class (GTK_WIDGET(dialog),
"gnc-class-imports");
1045 GtkWidget *desc_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"desc_entry"));
1046 GtkWidget *memo_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"memo_entry"));
1047 GtkWidget *notes_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"notes_entry"));
1052 std::vector<EntryInfo> entries = {
1053 { desc_entry, gtk_builder_get_object (builder,
"desc_override"), info->can_edit_desc, info->desc_hash,
xaccTransGetDescription (trans) },
1054 { notes_entry, gtk_builder_get_object (builder,
"notes_override"), info->can_edit_notes, info->notes_hash,
xaccTransGetNotes (trans) },
1055 { memo_entry, gtk_builder_get_object (builder,
"memo_override"), info->can_edit_memo, info->memo_hash,
xaccSplitGetMemo (split) },
1058 std::for_each (entries.begin(), entries.end(), setup_entry);
1062 auto it = std::find_if (entries.begin(), entries.end(), [](
auto info){
return info.can_edit; });
1063 if (it != entries.end())
1064 gtk_widget_grab_focus (it->entry);
1066 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (info->main_widget));
1069 gtk_widget_show (dialog);
1071 bool retval =
false;
1072 switch (gtk_dialog_run (GTK_DIALOG(dialog)))
1074 case GTK_RESPONSE_OK:
1075 *new_desc = g_strdup (gtk_entry_get_text (GTK_ENTRY (desc_entry)));
1076 *new_notes = g_strdup (gtk_entry_get_text (GTK_ENTRY (notes_entry)));
1077 *new_memo = g_strdup (gtk_entry_get_text (GTK_ENTRY (memo_entry)));
1084 gtk_widget_destroy (dialog);
1085 g_object_unref (G_OBJECT(builder));
1090 maybe_add_string (GNCImportMainMatcher *info, GHashTable *hash,
const char *str)
1092 if (!str || !str[0] || g_hash_table_lookup (hash, str))
1094 char *new_string = g_strdup (str);
1095 info->new_strings = g_list_prepend (info->new_strings, new_string);
1096 g_hash_table_insert (hash, new_string, one);
1100 gnc_gen_trans_set_price_to_selection_cb (GtkMenuItem *menuitem,
1101 GNCImportMainMatcher *info)
1104 g_return_if_fail (info);
1106 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1107 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1108 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1109 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1113 LEAVE (
"No selected rows");
1117 for (GList *n = selected_rows; n; n = g_list_next (n))
1119 RowInfo row{
static_cast<GtkTreePath*
>(n->data), info};
1127 XferDialog *xfer = gnc_xfer_dialog(GTK_WIDGET (info->main_widget), src_acc);
1128 gnc_xfer_dialog_select_to_account(xfer, dest_acc);
1129 gnc_xfer_dialog_set_amount(xfer, dest_value);
1130 gnc_xfer_dialog_set_date (xfer, post_date);
1134 gnc_xfer_dialog_set_from_show_button_active(xfer,
false);
1135 gnc_xfer_dialog_set_to_show_button_active(xfer,
false);
1136 gnc_xfer_dialog_hide_from_account_tree(xfer);
1137 gnc_xfer_dialog_hide_to_account_tree(xfer);
1139 gnc_xfer_dialog_is_exchange_dialog(xfer, &exch);
1141 if (!gnc_xfer_dialog_run_until_done(xfer))
1153 refresh_model_row (info, model, row.get_iter(), row.get_trans_info());
1156 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1161 gnc_gen_trans_edit_fields (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1165 g_return_if_fail (info);
1167 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1168 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1169 GtkTreeStore *store = GTK_TREE_STORE (model);
1170 auto selected_refs = get_treeview_selection_refs (treeview, model);
1172 if (selected_refs.empty())
1174 LEAVE (
"No selected rows");
1178 char *new_desc = NULL, *new_notes = NULL, *new_memo = NULL;
1179 RowInfo first_row{selected_refs[0], info};
1180 if (input_new_fields (info, first_row, &new_desc, &new_notes, &new_memo))
1182 for (
const auto& ref : selected_refs)
1187 if (info->can_edit_desc)
1189 gint style = g_strcmp0 (new_desc, row.get_orig_desc()) ?
1190 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1191 gtk_tree_store_set (store, row.get_iter(),
1192 DOWNLOADED_COL_DESCRIPTION, new_desc,
1193 DOWNLOADED_COL_DESCRIPTION_STYLE, style,
1196 maybe_add_string (info, info->desc_hash, new_desc);
1199 if (info->can_edit_notes)
1202 maybe_add_string (info, info->notes_hash, new_notes);
1205 if (info->can_edit_memo)
1207 gint style = g_strcmp0 (new_memo, row.get_orig_memo()) ?
1208 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1209 gtk_tree_store_set (store, row.get_iter(),
1210 DOWNLOADED_COL_MEMO, new_memo,
1211 DOWNLOADED_COL_MEMO_STYLE, style,
1214 maybe_add_string (info, info->memo_hash, new_memo);
1225 gnc_gen_trans_reset_edits_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1227 g_return_if_fail (info);
1228 ENTER(
"gnc_gen_trans_reset_edits_cb");
1230 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1231 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1232 GtkTreeStore *store = GTK_TREE_STORE (model);
1233 auto selected_refs = get_treeview_selection_refs (treeview, model);
1235 if (selected_refs.empty())
1237 LEAVE (
"No selected rows");
1241 for (
const auto& ref : selected_refs)
1249 gtk_tree_store_set (store, rowinfo.get_iter(),
1250 DOWNLOADED_COL_DESCRIPTION, rowinfo.get_orig_desc(),
1251 DOWNLOADED_COL_MEMO, rowinfo.get_orig_memo(),
1252 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1253 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1260 gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
1262 GtkTreeViewColumn *column,
1263 GNCImportMainMatcher *info)
1268 bool is_selection =
false;
1269 Account *assigned_account = NULL;
1270 gnc_gen_trans_assign_transfer_account (treeview,
1271 &first, is_selection, path,
1272 &assigned_account, info);
1274 gtk_tree_selection_select_path (gtk_tree_view_get_selection (treeview), path);
1277 DEBUG(
"account returned = %s", namestr);
1282 static GNCImportAction
1283 get_action_for_path (GtkTreePath* path, GtkTreeModel *model)
1285 GNCImportTransInfo *trans_info;
1287 gtk_tree_model_get_iter (model, &iter, path);
1288 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
1292 return GNCImport_INVALID_ACTION;
1297 gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
1298 GNCImportMainMatcher *info)
1300 GtkTreeModel *model;
1304 if (gtk_tree_selection_count_selected_rows (selection) >= 2)
1307 GList* list = gtk_tree_selection_get_selected_rows (selection, &model);
1308 for (GList *n = list; n; n = n->next)
1310 auto path =
static_cast<GtkTreePath*
>(n->data);
1311 if (get_action_for_path (path, model) != GNCImport_ADD)
1312 gtk_tree_selection_unselect_path (selection, path);
1314 g_list_free_full (list, (GDestroyNotify)gtk_tree_path_free);
1317 GtkSelectionMode mode = gtk_tree_selection_get_mode (selection);
1320 case GTK_SELECTION_MULTIPLE:
1321 DEBUG(
"mode = GTK_SELECTION_MULTIPLE, no action");
1323 case GTK_SELECTION_NONE:
1324 DEBUG(
"mode = GTK_SELECTION_NONE, no action");
1326 case GTK_SELECTION_BROWSE:
1327 DEBUG(
"mode = GTK_SELECTION_BROWSE->default");
1328 case GTK_SELECTION_SINGLE:
1329 DEBUG(
"mode = GTK_SELECTION_SINGLE->default");
1331 DEBUG(
"mode = default unselect selected row");
1332 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1334 gtk_tree_selection_unselect_iter (selection, &iter);
1341 gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
1343 GNCImportMainMatcher *info)
1347 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1348 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1349 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1351 const char *desc = NULL, *memo = NULL, *notes = NULL;
1354 RowInfo first_rowinfo{
static_cast<GtkTreePath*
>(selected_rows->data), info};
1363 info->can_edit_desc =
true;
1364 info->can_edit_notes =
true;
1365 info->can_edit_memo =
true;
1366 bool can_undo_edits =
false;
1367 bool can_update_prices =
true;
1368 bool can_assign_acct =
true;
1369 for (GList *n = selected_rows; n; n = g_list_next(n))
1371 RowInfo rowinfo{
static_cast<GtkTreePath*
>(n->data), info};
1374 if (can_assign_acct)
1381 if (can_update_prices)
1387 can_update_prices =
false;
1393 if (info->can_edit_desc)
1395 if (info->can_edit_notes)
1397 if (info->can_edit_memo)
1402 if (!can_undo_edits)
1403 can_undo_edits = (g_strcmp0 (
xaccSplitGetMemo (split), rowinfo.get_orig_memo()) ||
1408 if (!can_assign_acct && !can_update_prices &&
1409 !info->can_edit_desc && !info->can_edit_notes && !info->can_edit_memo &&
1414 GtkWidget *menu = gtk_menu_new();
1416 auto add_menu_item = [&menu, &info](
const char* name,
bool sensitive, GCallback callback)
1418 auto menuitem = gtk_menu_item_new_with_mnemonic (_(name));
1419 gtk_widget_set_sensitive (menuitem, sensitive);
1420 g_signal_connect (menuitem,
"activate", callback, info);
1421 gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
1425 add_menu_item (N_(
"_Assign transfer account"),
1427 G_CALLBACK(gnc_gen_trans_assign_transfer_account_to_selection_cb));
1430 add_menu_item (N_(
"Assign e_xchange rate"),
1432 G_CALLBACK (gnc_gen_trans_set_price_to_selection_cb));
1435 add_menu_item (N_(
"_Edit description, notes, or memo"),
1436 info->can_edit_desc || info->can_edit_notes || info->can_edit_memo,
1437 G_CALLBACK (gnc_gen_trans_edit_fields));
1440 add_menu_item (N_(
"_Reset all edits"),
1442 G_CALLBACK (gnc_gen_trans_reset_edits_cb));
1444 gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (treeview), NULL);
1446 gtk_widget_show_all (menu);
1448 gtk_menu_popup_at_pointer (GTK_MENU(menu), (GdkEvent*)event);
1450 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1455 gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
1457 GNCImportMainMatcher *info)
1460 g_return_val_if_fail (treeview != NULL,
false);
1461 g_return_val_if_fail (event != NULL,
false);
1463 if (event->type == GDK_BUTTON_PRESS)
1465 GdkEventButton *event_button = (GdkEventButton *) event;
1466 if (event_button->button == GDK_BUTTON_SECONDARY)
1468 DEBUG(
"Right mouseClick detected - popup the menu.");
1470 auto selection = gtk_tree_view_get_selection (treeview);
1471 GtkTreePath* path =
nullptr;
1474 if (gtk_tree_view_get_path_at_pos (treeview, event_button->x,
1475 event_button->y, &path,
1476 nullptr,
nullptr,
nullptr))
1478 if (!gtk_tree_selection_path_is_selected (selection, path))
1480 gtk_tree_selection_unselect_all (selection);
1481 gtk_tree_selection_select_path (selection, path);
1483 gtk_tree_path_free (path);
1486 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1488 GtkTreeModel *model;
1489 auto selected = gtk_tree_selection_get_selected_rows (selection, &model);
1490 if (get_action_for_path (static_cast<GtkTreePath*>(selected->data), model) == GNCImport_ADD)
1491 gnc_gen_trans_view_popup_menu (treeview, event, info);
1492 g_list_free_full (selected, (GDestroyNotify)gtk_tree_path_free);
1494 LEAVE(
"return true");
1498 LEAVE(
"return false");
1503 gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
1504 GNCImportMainMatcher *info)
1506 ENTER(
"onPopupMenu_cb");
1508 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1509 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1511 gnc_gen_trans_view_popup_menu (treeview, NULL, info);
1519 static GtkTreeViewColumn *
1520 add_text_column (GtkTreeView *view,
const gchar *title,
int col_num,
bool ellipsize)
1522 GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1523 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title,
1526 "background", DOWNLOADED_COL_COLOR,
1530 g_object_set (renderer,
"ellipsize", PANGO_ELLIPSIZE_END, NULL);
1533 if (col_num == DOWNLOADED_COL_DATE_TXT)
1534 gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_DATE_INT64);
1535 else if (col_num == DOWNLOADED_COL_AMOUNT)
1537 gtk_cell_renderer_set_alignment (renderer, 1.0, 0.5);
1538 gtk_cell_renderer_set_padding (renderer, 5, 0);
1539 gtk_tree_view_column_set_sort_column_id (column, DOWNLOADED_COL_AMOUNT_DOUBLE);
1542 gtk_tree_view_column_set_sort_column_id (column, col_num);
1544 if (col_num == DOWNLOADED_COL_DESCRIPTION)
1545 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_DESCRIPTION_STYLE);
1547 if (col_num == DOWNLOADED_COL_MEMO)
1548 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_MEMO_STYLE);
1550 g_object_set (G_OBJECT(column),
1551 "reorderable",
true,
1554 gtk_tree_view_append_column (view, column);
1558 static GtkTreeViewColumn *
1559 add_toggle_column (GtkTreeView *view,
const gchar *title,
int col_num,
1560 GCallback cb_fn, gpointer cb_arg,
const gchar *tooltip_text)
1562 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
1563 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title, renderer,
1565 "cell-background", DOWNLOADED_COL_COLOR,
1566 "activatable", DOWNLOADED_COL_ENABLE,
1567 "visible", DOWNLOADED_COL_ENABLE,
1569 gtk_tree_view_column_set_sort_column_id (column, col_num);
1570 g_object_set (G_OBJECT(column),
"reorderable",
true, NULL);
1571 g_signal_connect (renderer,
"toggled", cb_fn, cb_arg);
1572 gtk_tree_view_append_column (view, column);
1576 gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (column), tooltip_text);
1582 gnc_gen_trans_init_view (GNCImportMainMatcher *info,
1586 GtkTreeView *view = info->view;
1587 GtkTreeStore *store = gtk_tree_store_new (NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64,
1588 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE,
1589 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1590 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1591 G_TYPE_STRING, G_TYPE_BOOLEAN,
1592 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
1593 GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING,
1595 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
1596 g_object_unref (store);
1599 gtk_tree_view_set_reorderable (view,
false);
1602 add_text_column (view, _(
"Date"), DOWNLOADED_COL_DATE_TXT,
false);
1603 info->account_column = add_text_column (view, _(
"Account"), DOWNLOADED_COL_ACCOUNT,
false);
1604 gtk_tree_view_column_set_visible (info->account_column, show_account);
1605 add_text_column (view, _(
"Amount"), DOWNLOADED_COL_AMOUNT,
false);
1606 add_text_column (view, _(
"Description"), DOWNLOADED_COL_DESCRIPTION,
false);
1607 info->memo_column = add_text_column (view, _(
"Memo"), DOWNLOADED_COL_MEMO,
true);
1608 add_toggle_column (view, C_(
"Column header for 'Adding transaction'",
"A"),
1609 DOWNLOADED_COL_ACTION_ADD,
1610 G_CALLBACK(gnc_gen_trans_add_toggled_cb), info,
1611 _(
"Add as a new transaction"));
1612 GtkTreeViewColumn *column = add_toggle_column (view,
1613 C_(
"Column header for 'Updating plus Clearing transaction'",
"U+C"),
1614 DOWNLOADED_COL_ACTION_UPDATE,
1615 G_CALLBACK(gnc_gen_trans_update_toggled_cb), info,
1616 _(
"Update + Clear Transaction\nUpdate existing transaction with the imported data and mark it as cleared"));
1617 gtk_tree_view_column_set_visible (column, show_update);
1618 add_toggle_column (view, C_(
"Column header for 'Clearing transaction'",
"C"),
1619 DOWNLOADED_COL_ACTION_CLEAR,
1620 G_CALLBACK(gnc_gen_trans_clear_toggled_cb), info,
1621 _(
"Clear Transaction\nMark existing transaction as cleared without changing its details"));
1624 GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
1625 g_object_set (renderer,
"xalign", 0.0, NULL);
1626 column = gtk_tree_view_column_new_with_attributes (_(
"Info"), renderer,
1627 "pixbuf", DOWNLOADED_COL_ACTION_PIXBUF,
1628 "cell-background", DOWNLOADED_COL_COLOR,
1631 gtk_tree_view_append_column (info->view, column);
1633 column = add_text_column (view, _(
"Additional Comments"), DOWNLOADED_COL_ACTION_INFO,
false);
1634 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1637 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
1638 DOWNLOADED_COL_DATE_INT64,
1639 GTK_SORT_ASCENDING);
1640 GtkTreeSelection *selection = gtk_tree_view_get_selection (info->view);
1642 g_object_set (info->view,
"has-tooltip",
true, NULL);
1644 g_signal_connect (G_OBJECT(info->view),
"query-tooltip",
1645 G_CALLBACK(query_tooltip_tree_view_cb), info);
1646 g_signal_connect (info->view,
"row-activated",
1647 G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
1648 g_signal_connect (selection,
"changed",
1649 G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
1650 g_signal_connect (view,
"button-press-event",
1651 G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
1652 g_signal_connect (view,
"popup-menu",
1653 G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
1657 show_account_column_toggled_cb (GtkToggleButton *togglebutton,
1658 GNCImportMainMatcher *info)
1660 gtk_tree_view_column_set_visible (info->account_column,
1661 gtk_toggle_button_get_active (togglebutton));
1665 show_memo_column_toggled_cb (GtkToggleButton *togglebutton,
1666 GNCImportMainMatcher *info)
1668 gtk_tree_view_column_set_visible (info->memo_column,
1669 gtk_toggle_button_get_active (togglebutton));
1673 show_matched_info_toggled_cb (GtkToggleButton *togglebutton,
1674 GNCImportMainMatcher *info)
1676 if (gtk_toggle_button_get_active (togglebutton))
1678 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
1679 gtk_tree_view_expand_all (info->view);
1683 gtk_tree_view_column_set_visible (info->account_column,
1684 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->show_account_column)));
1685 gtk_tree_view_collapse_all (info->view);
1690 gnc_gen_trans_common_setup (GNCImportMainMatcher *info,
1692 GtkBuilder *builder,
1693 const gchar* heading,
1694 bool all_from_same_account,
1695 gint match_date_hardlimit)
1697 info->pending_matches = gnc_import_PendingMatches_new ();
1703 GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(parent));
1705 gtk_style_context_get_color (stylectxt, GTK_STATE_FLAG_NORMAL, &color);
1709 info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder,
"downloaded_view"));
1710 g_assert (info->view != NULL);
1712 info->show_account_column = GTK_WIDGET(gtk_builder_get_object (builder,
"show_source_account_button"));
1713 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), all_from_same_account);
1714 g_signal_connect (G_OBJECT(info->show_account_column),
"toggled",
1715 G_CALLBACK(show_account_column_toggled_cb), info);
1717 GtkWidget *button = GTK_WIDGET(gtk_builder_get_object (builder,
"show_memo_column_button"));
1718 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
true);
1719 g_signal_connect (G_OBJECT(button),
"toggled",
1720 G_CALLBACK(show_memo_column_toggled_cb), info);
1722 info->show_matched_info = GTK_WIDGET(gtk_builder_get_object (builder,
"show_matched_info_button"));
1723 g_signal_connect (G_OBJECT(info->show_matched_info),
"toggled",
1724 G_CALLBACK(show_matched_info_toggled_cb), info);
1726 info->append_text = GTK_WIDGET(gtk_builder_get_object (builder,
"append_desc_notes_button"));
1729 info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder,
"reconcile_after_close_button"));
1732 GtkWidget *heading_label = GTK_WIDGET(gtk_builder_get_object (builder,
"heading_label"));
1734 gtk_label_set_text (GTK_LABEL(heading_label), heading);
1737 gnc_gen_trans_init_view (info, all_from_same_account, show_update);
1739 info->acct_id_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1740 (GDestroyNotify)g_hash_table_destroy);
1741 info->desc_hash = g_hash_table_new (g_str_hash, g_str_equal);
1742 info->notes_hash = g_hash_table_new (g_str_hash, g_str_equal);
1743 info->memo_hash = g_hash_table_new (g_str_hash, g_str_equal);
1744 info->new_strings = NULL;
1745 info->transaction_processed_cb = NULL;
1746 new (&info->colormap) StrStrMap();
1749 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
1751 g_object_unref (G_OBJECT(builder));
1755 GNCImportMainMatcher *
1757 const gchar* heading,
1758 bool all_from_same_account,
1759 gint match_date_hardlimit,
1762 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1765 GtkBuilder *builder = gtk_builder_new ();
1766 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_dialog");
1767 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1769 info->main_widget = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_dialog"));
1770 g_assert (info->main_widget != NULL);
1773 GtkWidget *pbox = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_vbox"));
1774 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1775 gtk_box_pack_start (GTK_BOX(pbox), box,
true,
true, 0);
1778 gtk_widget_set_name (GTK_WIDGET(info->main_widget),
"gnc-id-import-matcher-transactions");
1779 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1780 gnc_widget_style_context_add_class (GTK_WIDGET(info->main_widget),
"gnc-class-imports");
1783 gnc_gen_trans_common_setup (info, parent, builder, heading,
1784 all_from_same_account, match_date_hardlimit);
1787 gtk_window_set_transient_for (GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1789 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1792 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
1795 info->id = gnc_register_gui_component (IMPORT_MAIN_MATCHER_CM_CLASS,
1800 gnc_gui_component_set_session (info->id, gnc_get_current_session());
1809 GNCImportMainMatcher *
1811 GtkWidget *assistant_page,
1812 const gchar* heading,
1813 bool all_from_same_account,
1814 gint match_date_hardlimit)
1816 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1817 info->main_widget = GTK_WIDGET(parent);
1820 GtkBuilder *builder = gtk_builder_new ();
1821 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1824 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1825 g_assert (box != NULL);
1826 gtk_box_pack_start (GTK_BOX(assistant_page), box,
true,
true, 6);
1829 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1832 gnc_gen_trans_common_setup (info, parent, builder, heading,
1833 all_from_same_account, match_date_hardlimit);
1841 on_matcher_ok_clicked (NULL, info);
1850 GNCTransactionProcessedCB trans_processed_cb,
1853 info->user_data = user_data;
1854 info->transaction_processed_cb = trans_processed_cb;
1861 bool result = gtk_dialog_run (GTK_DIALOG (info->main_widget));
1871 get_required_color (StrStrMap& cache,
const gchar *class_name)
1873 auto& rv = cache[class_name];
1877 GtkWidget *label = gtk_label_new (
"Color");
1878 GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET(label));
1879 gtk_style_context_add_class (context, class_name);
1881 gchar* col_str = gdk_rgba_to_string (&color);
1884 gtk_widget_destroy (label);
1890 remove_child_row (GtkTreeModel *model, GtkTreeIter *iter)
1892 if (gtk_tree_model_iter_has_child (model, iter))
1895 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1896 gtk_tree_store_remove (GTK_TREE_STORE(model), &child);
1901 update_child_row (
GNCImportMatchInfo *sel_match, GtkTreeModel *model, GtkTreeIter *iter)
1903 GtkTreeStore *store = GTK_TREE_STORE(model);
1905 if (!gtk_tree_model_iter_has_child (model, iter))
1906 gtk_tree_store_append (GTK_TREE_STORE(model), &child, iter);
1908 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1912 : _(
"-- Split Transaction --");
1916 gtk_tree_store_set (store, &child,
1917 DOWNLOADED_COL_ACCOUNT, account_str,
1918 DOWNLOADED_COL_DATE_TXT, date,
1919 DOWNLOADED_COL_AMOUNT, amount_str,
1921 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1923 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1924 DOWNLOADED_COL_ENABLE,
false,
1930 get_peer_acct_names (Split *split)
1932 GList *names = NULL, *accounts_seen = NULL;
1936 if ((n->data == split) ||
1938 (g_list_find (accounts_seen, account)))
1941 names = g_list_prepend (names, name);
1942 accounts_seen = g_list_prepend (accounts_seen, account);
1944 names = g_list_sort (names, (GCompareFunc)g_utf8_collate);
1946 g_list_free_full (names, g_free);
1947 g_list_free (accounts_seen);
1952 refresh_model_row (GNCImportMainMatcher *gui,
1953 GtkTreeModel *model,
1955 GNCImportTransInfo *info)
1962 GtkTreeStore *store = GTK_TREE_STORE(model);
1963 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATA, info, -1);
1965 const gchar *class_extension = NULL;
1966 if (gui->dark_theme)
1967 class_extension =
"-dark";
1969 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
1970 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
1971 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
1974 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ENABLE,
true, -1);
1980 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
1985 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_TXT, text, -1);
1986 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_INT64, date, -1);
1991 ro_text =
xaccPrintAmount (amount, gnc_split_amount_print_info (split,
true));
1992 gtk_tree_store_set (store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
1997 gtk_tree_store_set (store, iter, DOWNLOADED_COL_NOTES_ORIGINAL, ro_text, -1);
2001 gtk_tree_store_set (store, iter,
2002 DOWNLOADED_COL_DESCRIPTION, ro_text,
2003 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, ro_text,
2007 gtk_tree_store_set (store, iter,
2008 DOWNLOADED_COL_MEMO, ro_text,
2009 DOWNLOADED_COL_MEMO_ORIGINAL, ro_text,
2015 ro_text = text = NULL;
2016 const gchar *color = NULL;
2017 bool show_pixbuf =
true;
2023 ro_text = _(
"New, already balanced");
2024 color = get_required_color (gui->colormap, int_not_required_class);
2029 char *imbalance = NULL;
2039 color = get_required_color (gui->colormap, int_not_required_class);
2045 g_strdup_printf (_(
"New, transfer %s to (manual) \"%s\""),
2046 imbalance, acct_full_name);
2053 g_strdup_printf (_(
"New, transfer %s to (auto) \"%s\""),
2054 imbalance, acct_full_name);
2063 color = get_required_color (gui->colormap, int_required_class);
2066 g_strdup_printf (_(
"New, UNBALANCED (need price to transfer %s to acct %s)!"),
2067 imbalance, acct_full_name);
2071 g_free (acct_full_name);
2079 color = get_required_color (gui->colormap, int_prob_required_class);
2082 g_strdup_printf (_(
"New, UNBALANCED (need acct to transfer %s)!"),
2085 remove_child_row (model, iter);
2090 case GNCImport_CLEAR:
2096 gchar *full_names = get_peer_acct_names (sel_match->split);
2097 color = get_required_color (gui->colormap, int_not_required_class);
2100 text = g_strdup_printf (_(
"Reconcile (manual) match to %s"),
2105 text = g_strdup_printf (_(
"Reconcile (auto) match to %s"),
2108 g_free (full_names);
2109 update_child_row (sel_match, model, iter);
2113 color = get_required_color (gui->colormap, int_required_class);
2114 ro_text = _(
"Match missing!");
2115 show_pixbuf =
false;
2116 remove_child_row (model, iter);
2120 case GNCImport_UPDATE:
2125 gchar *full_names = get_peer_acct_names (sel_match->split);
2126 color = get_required_color (gui->colormap, int_not_required_class);
2129 text = g_strdup_printf (_(
"Update and reconcile (manual) match to %s"),
2134 text = g_strdup_printf (_(
"Update and reconcile (auto) match to %s"),
2137 g_free (full_names);
2138 update_child_row (sel_match, model, iter);
2142 color = get_required_color (gui->colormap, int_required_class);
2143 ro_text = _(
"Match missing!");
2144 show_pixbuf =
false;
2145 remove_child_row (model, iter);
2149 case GNCImport_SKIP:
2150 color = get_required_color (gui->colormap, int_required_class);
2151 ro_text = _(
"Do not import (no action selected)");
2152 show_pixbuf =
false;
2153 remove_child_row (model, iter);
2157 ro_text =
"WRITEME, this is an unknown action";
2158 show_pixbuf =
false;
2162 gtk_tree_store_set (store, iter,
2163 DOWNLOADED_COL_COLOR, color,
2164 DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text,
2169 g_free (int_required_class);
2170 g_free (int_prob_required_class);
2171 g_free (int_not_required_class);
2174 gtk_tree_store_set (store, iter,
2175 DOWNLOADED_COL_ACTION_ADD,
2181 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2184 gtk_tree_store_set (store, iter,
2185 DOWNLOADED_COL_ACTION_CLEAR,
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);
2203 gtk_tree_store_set (store, iter,
2204 DOWNLOADED_COL_ACTION_UPDATE,
2211 gtk_tree_store_set (store, iter,
2212 DOWNLOADED_COL_ACTION_PIXBUF,
2216 GTK_WIDGET(gui->view)),
2219 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2223 if (gtk_tree_model_iter_has_child (model, iter))
2225 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui->show_matched_info)))
2227 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
2229 gtk_tree_view_column_set_visible (gui->account_column,
true);
2230 gtk_tree_view_column_set_visible (gui->memo_column,
true);
2232 gtk_tree_view_expand_row (GTK_TREE_VIEW(gui->view), path,
true);
2233 gtk_tree_path_free (path);
2236 GtkTreeSelection *selection = gtk_tree_view_get_selection (gui->view);
2237 gtk_tree_selection_unselect_all (selection);
2242 bool reconcile_after_close,
2245 gtk_widget_set_visible (info->reconcile_after_close, reconcile_after_close);
2246 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->reconcile_after_close), active);
2252 return info->reconcile_after_close;
2257 gnc_gen_trans_list_add_trans_internal (GNCImportMainMatcher *gui, Transaction *trans,
2265 defer_bal_computation (gui, acc);
2271 DEBUG(
"%s",
"Transaction with same online ID exists, destroying current transaction");
2282 gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info);
2288 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, NULL);
2294 gnc_gen_trans_list_add_trans_internal (gui, trans, ref_id, NULL);
2301 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, lsplit);
2310 filter_existing_splits_on_account_and_date (GNCImportMainMatcher *gui)
2312 static const int secs_per_day = 86400;
2313 gint match_date_limit =
2315 time64 min_time=G_MAXINT64, max_time=0;
2316 time64 match_timelimit = match_date_limit * secs_per_day;
2317 GList *all_accounts = NULL;
2322 for (GSList* txn = gui->temp_trans_list; txn != NULL;
2323 txn = g_slist_next (txn))
2325 auto txn_info =
static_cast<GNCImportTransInfo*
>(txn->data);
2330 all_accounts = g_list_prepend (all_accounts, txn_account);
2331 min_time = MIN(min_time, txn_time);
2332 max_time = MAX(max_time, txn_time);
2336 Query *query = qof_query_create_for (GNC_ID_SPLIT);
2338 xaccQueryAddAccountMatch (query, all_accounts,
2340 xaccQueryAddDateMatchTT (query,
2341 true, min_time - match_timelimit,
2342 true, max_time + match_timelimit,
2345 g_list_free (all_accounts);
2346 GList *retval = g_list_copy (query_results);
2356 create_hash_of_potential_matches (GList *candidate_splits,
2357 GHashTable *account_hash)
2359 for (GList* candidate = candidate_splits; candidate != NULL;
2360 candidate = g_list_next (candidate))
2362 auto split =
static_cast<Split*
>(candidate->data);
2363 if (gnc_import_split_has_online_id (split))
2373 auto split_list =
static_cast<GSList*
>(g_hash_table_lookup (account_hash, split_account));
2374 g_hash_table_steal (account_hash, split_account);
2375 split_list = g_slist_prepend (split_list, split);
2376 g_hash_table_insert (account_hash, split_account, split_list);
2378 return account_hash;
2381 typedef struct _match_struct
2383 GNCImportTransInfo* transaction_info;
2384 gint display_threshold;
2385 gint date_threshold;
2386 gint date_not_threshold;
2387 double fuzzy_amount;
2394 s->display_threshold,
2396 s->date_not_threshold,
2406 perform_matching (GNCImportMainMatcher *gui, GHashTable *account_hash)
2408 GtkTreeModel* model = gtk_tree_view_get_model (gui->view);
2409 gint display_threshold =
2411 gint date_threshold =
2412 gnc_import_Settings_get_date_threshold (gui->user_settings);
2413 gint date_not_threshold =
2414 gnc_import_Settings_get_date_not_threshold (gui->user_settings);
2415 double fuzzy_amount =
2418 for (GSList *imported_txn = gui->temp_trans_list; imported_txn !=NULL;
2419 imported_txn = g_slist_next (imported_txn))
2421 auto txn_info =
static_cast<GNCImportTransInfo*
>(imported_txn->data);
2423 match_struct s = {txn_info, display_threshold, date_threshold, date_not_threshold, fuzzy_amount};
2425 g_slist_foreach (static_cast<GSList*>(g_hash_table_lookup (account_hash, importaccount)),
2426 (GFunc) match_helper, &s);
2432 bool match_selected_manually =
2436 gnc_import_PendingMatches_add_match (gui->pending_matches,
2438 match_selected_manually);
2441 gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
2442 refresh_model_row (gui, model, &iter, txn_info);
2447 gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui)
2449 GHashTable* account_hash =
2450 g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
2451 (GDestroyNotify)g_slist_free);
2453 GList *candidate_splits = filter_existing_splits_on_account_and_date (gui);
2455 create_hash_of_potential_matches (candidate_splits, account_hash);
2456 perform_matching (gui, account_hash);
2458 g_list_free (candidate_splits);
2459 g_hash_table_destroy (account_hash);
2467 return info->main_widget;
2474 return info->append_text;
2478 query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
2480 GtkTooltip *tooltip,
2483 GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
2484 GtkTreePath *path = NULL;
2485 GtkTreeViewColumn *column = NULL;
2486 gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &x, &y);
2487 if (keyboard_tip || !gtk_tree_view_get_path_at_pos (tree_view, x, y, &path,
2488 &column, NULL, NULL))
2490 gtk_tree_path_free (path);
2495 bool show_tooltip =
false;
2496 GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2498 if (gtk_tree_model_get_iter(model, &iter, path) && column)
2500 gchar *tooltip_text = NULL;
2503 gint num_col = gtk_tree_view_column_get_sort_column_id (column);
2506 case DOWNLOADED_COL_DESCRIPTION:
2507 gtk_tree_model_get (model, &iter,
2508 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &tooltip_text,
2511 case DOWNLOADED_COL_MEMO:
2512 gtk_tree_model_get (model, &iter,
2513 DOWNLOADED_COL_MEMO_ORIGINAL, &tooltip_text,
2521 if (tooltip_text && *tooltip_text)
2523 show_tooltip =
true;
2524 gtk_tooltip_set_text (tooltip, tooltip_text);
2525 gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, column, NULL);
2527 g_free (tooltip_text);
2530 gtk_tree_path_free (path);
2531 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...