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 gnc_gui_refresh_all ();
259 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
261 return !gtk_tree_model_get_iter_first (model, &iter) && !info->temp_trans_list;
265 gnc_gen_trans_list_show_accounts_column (GNCImportMainMatcher *info)
269 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
270 if (gtk_tree_model_iter_n_children (model, NULL) > 1)
272 bool multiple_accounts =
false;
276 bool valid = gtk_tree_model_get_iter_first (model, &iter);
280 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &account_name, -1);
282 valid = gtk_tree_model_iter_next (model, &iter);
286 gchar *test_account_name;
287 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_ACCOUNT, &test_account_name, -1);
288 if (g_strcmp0 (account_name, test_account_name) != 0)
290 multiple_accounts =
true;
291 g_free (test_account_name);
294 valid = gtk_tree_model_iter_next (model, &iter);
295 g_free (test_account_name);
297 g_free (account_name);
300 if (multiple_accounts)
302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
303 gtk_tree_view_expand_all (info->view);
307 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
false);
308 gtk_tree_view_collapse_all (info->view);
315 get_top_trans_match_id (GList* match_list)
317 if (!match_list || !match_list->data)
return NULL;
319 Transaction *trans = match_info->trans;
325 get_top_trans_match_score (GList* match_list)
327 if (!match_list || !match_list->data)
return 0;
329 return match_info->probability;
333 get_trans_match_list (GtkTreeModel* model, GtkTreeIter* iter)
335 GNCImportTransInfo *transaction_info;
336 gtk_tree_model_get (model, iter,
337 DOWNLOADED_COL_DATA, &transaction_info,
342 static GNCImportTransInfo*
343 get_trans_info (GtkTreeModel* model, GtkTreeIter* iter)
345 GNCImportTransInfo *transaction_info;
346 gtk_tree_model_get (model, iter,
347 DOWNLOADED_COL_DATA, &transaction_info,
349 return transaction_info;
357 get_conflict_list (GtkTreeModel* model, GtkTreeIter import_iter,
GncGUID*
id, gint best_match)
359 GtkTreeIter iter = import_iter;
360 GNCImportTransInfo* best_import = get_trans_info (model, &import_iter);
361 GList* conflicts = g_list_prepend (NULL, best_import);
363 while (gtk_tree_model_iter_next (model, &iter))
365 gint match_score = 0;
366 GNCImportTransInfo* trans_info;
369 GList* register_iter = get_trans_match_list (model, &iter);
370 if (!register_iter || !register_iter->data)
373 id2 = *get_top_trans_match_id (register_iter);
378 match_score = get_top_trans_match_score (register_iter);
379 trans_info = get_trans_info (model, &iter);
380 conflicts = g_list_prepend (conflicts, trans_info);
382 if (match_score > best_match)
385 best_match = match_score;
386 best_import = trans_info;
391 conflicts = g_list_remove (conflicts, best_import);
396 remove_top_matches (GList* conflicts)
398 for (GList* iter = conflicts; iter && iter->data; iter=iter->next)
403 resolve_conflicts (GNCImportMainMatcher *info)
405 GtkTreeModel* model = gtk_tree_view_get_model (info->view);
406 GtkTreeIter import_iter;
412 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
415 GList *match_list = get_trans_match_list (model, &import_iter);
416 if (!match_list || !match_list->data)
418 valid = gtk_tree_model_iter_next (model, &import_iter);
423 GncGUID id = *get_top_trans_match_id (match_list);
424 best_match = get_top_trans_match_score (match_list);
427 GList *conflicts = get_conflict_list (model, import_iter, &
id, best_match);
431 remove_top_matches (conflicts);
434 valid = gtk_tree_model_get_iter_first (model, &import_iter);
437 valid = gtk_tree_model_iter_next (model, &import_iter);
441 g_list_free (conflicts);
445 valid = gtk_tree_model_get_iter_first (model, &import_iter);
448 refresh_model_row (info, model, &import_iter, get_trans_info (model, &import_iter));
449 valid = gtk_tree_model_iter_next (model, &import_iter);
455 load_hash_tables (GNCImportMainMatcher *info)
457 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
458 GtkTreeIter import_iter;
459 GList *accounts_list = NULL;
460 bool valid = gtk_tree_model_get_iter_first (model, &import_iter);
463 GNCImportTransInfo *trans_info = get_trans_info (model, &import_iter);
466 if (!g_list_find (accounts_list, acc))
467 accounts_list = g_list_prepend (accounts_list, acc);
468 valid = gtk_tree_model_iter_next (model, &import_iter);
470 for (GList *m = accounts_list; m; m = m->next)
472 for (
auto s : xaccAccountGetSplits (static_cast<Account*>(m->data)))
478 g_hash_table_insert (info->desc_hash, (gpointer)key, one);
482 g_hash_table_insert (info->notes_hash, (gpointer)key, one);
486 g_hash_table_insert (info->memo_hash, (gpointer)key, one);
489 g_list_free (accounts_list);
499 GSList *temp_trans_list = info->temp_trans_list;
500 if (!temp_trans_list)
502 gnc_info_dialog (GTK_WINDOW (info->main_widget),
"%s", _(
"No new transactions were found in this import."));
505 auto trans_info =
static_cast<GNCImportTransInfo *
>(temp_trans_list->data);
508 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (info->append_text),
511 gnc_gen_trans_list_create_matches (info);
512 load_hash_tables (info);
513 resolve_conflicts (info);
514 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
515 gnc_gen_trans_list_show_accounts_column (info);
518 static void acc_begin_edit (GList **accounts_modified,
Account *acc)
520 if (!acc || !accounts_modified || g_list_find (*accounts_modified, acc))
525 *accounts_modified = g_list_prepend (*accounts_modified, acc);
528 on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
534 GtkTreeModel *model = gtk_tree_view_get_model (info->view);
536 if (!gtk_tree_model_get_iter_first (model, &iter))
545 gnc_suspend_gui_refresh ();
546 bool first_tran =
true;
547 bool append_text = gtk_toggle_button_get_active ((GtkToggleButton*) info->append_text);
548 GList *accounts_modified = NULL;
551 GNCImportTransInfo *trans_info;
552 gtk_tree_model_get (model, &iter,
553 DOWNLOADED_COL_DATA, &trans_info,
577 acc_begin_edit (&accounts_modified, dest_acc);
581 if (info->transaction_processed_cb)
583 info->transaction_processed_cb (trans_info,
true,
588 while (gtk_tree_model_iter_next (model, &iter));
593 gnc_resume_gui_refresh ();
600 on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
602 auto info =
static_cast<GNCImportMainMatcher *
>(user_data);
607 on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
609 auto info =
static_cast<GNCImportMainMatcher *
>(data);
615 on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
617 auto help_dialog =
static_cast<GtkWidget *
>(user_data);
619 gtk_widget_destroy (help_dialog);
625 auto info =
static_cast<GNCImportMainMatcher*
>(user_data);
627 GtkBuilder *builder = gtk_builder_new ();
628 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer2");
629 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer3");
630 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer4");
631 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer5");
632 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"textbuffer1");
633 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"matcher_help_dialog");
635 const gchar *class_extension = NULL;
636 if (info->dark_theme ==
true)
637 class_extension =
"-dark";
639 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
640 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
641 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
643 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_required_box"));
644 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_required_class);
646 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_probably_required_box"));
647 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_prob_required_class);
649 box = GTK_WIDGET(gtk_builder_get_object (builder,
"intervention_not_required_box"));
650 gnc_widget_style_context_add_class (GTK_WIDGET(box), int_not_required_class);
652 GtkWidget *help_dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"matcher_help_dialog"));
653 gtk_window_set_transient_for (GTK_WINDOW(help_dialog), GTK_WINDOW(info->main_widget));
656 gtk_widget_set_name (GTK_WIDGET(help_dialog),
"gnc-id-import-matcher-help");
657 gnc_widget_style_context_add_class (GTK_WIDGET(help_dialog),
"gnc-class-imports");
660 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
662 g_object_unref (G_OBJECT(builder));
664 g_free (int_required_class);
665 g_free (int_prob_required_class);
666 g_free (int_not_required_class);
668 gtk_widget_show (help_dialog);
672 run_match_dialog (GNCImportMainMatcher *info,
673 GNCImportTransInfo *trans_info)
676 trans_info, info->pending_matches);
680 set_treeview_selection_from_path (GtkTreeView* view,
const char* path)
682 auto selection = gtk_tree_view_get_selection (view);
683 auto tree_path = gtk_tree_path_new_from_string (path);
684 gtk_tree_selection_select_path (selection, tree_path);
685 gtk_tree_path_free (tree_path);
689 gen_trans_common_toggled_cb (GtkCellRendererToggle *cell_renderer, gchar *path,
690 GNCImportMainMatcher *gui, GNCImportAction action)
692 auto model = gtk_tree_view_get_model (gui->view);
693 GtkTreeIter tree_iter;
694 g_return_if_fail (gtk_tree_model_get_iter_from_string (model, &tree_iter, path));
696 GNCImportTransInfo *transaction_info;
697 gtk_tree_model_get (model, &tree_iter, DOWNLOADED_COL_DATA, &transaction_info, -1);
703 refresh_model_row (gui, model, &tree_iter, transaction_info);
705 set_treeview_selection_from_path (GTK_TREE_VIEW(gui->view), path);
709 gnc_gen_trans_add_toggled_cb (GtkCellRendererToggle *cell_renderer,
711 GNCImportMainMatcher *gui)
713 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_ADD);
717 gnc_gen_trans_clear_toggled_cb (GtkCellRendererToggle *cell_renderer,
719 GNCImportMainMatcher *gui)
721 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_CLEAR);
725 gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
727 GNCImportMainMatcher *gui)
729 gen_trans_common_toggled_cb (cell_renderer, path, gui, GNCImport_UPDATE);
733 gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview,
738 GNCImportMainMatcher *info)
740 gchar *path_str = gtk_tree_path_to_string (path);
744 DEBUG(
"first = %s", *first ?
"true" :
"false");
745 DEBUG(
"is_selection = %s", is_selection ?
"true" :
"false");
746 DEBUG(
"path = %s", path_str);
748 DEBUG(
"account passed in = %s", acct_str);
752 if (gtk_tree_path_get_depth (path) != 1)
755 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
757 if (gtk_tree_model_get_iter (model, &iter, path))
759 GNCImportTransInfo *trans_info;
760 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
770 gchar *acc_full_name;
774 _(
"Destination account for the auto-balance split."),
782 DEBUG(
"account selected = %s", acc_full_name);
783 g_free (acc_full_name);
788 defer_bal_computation (info, *new_acc);
792 case GNCImport_CLEAR:
793 case GNCImport_UPDATE:
794 if (*first && !is_selection)
795 run_match_dialog (info, trans_info);
800 PERR(
"InvalidGNCImportValue");
803 refresh_model_row (info, model, &iter, trans_info);
811 void operator()(GtkTreeRowReference* ptr)
const { gtk_tree_row_reference_free (ptr); }
814 using TreeRowReferencePtr = std::unique_ptr<GtkTreeRowReference, TreeRowRefDestructor>;
818 static std::vector<TreeRowReferencePtr>
819 get_treeview_selection_refs (GtkTreeView *treeview, GtkTreeModel *model)
821 std::vector<TreeRowReferencePtr> rv;
823 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview) && GTK_IS_TREE_MODEL (model), rv);
825 auto selection = gtk_tree_view_get_selection (treeview);
826 auto selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
828 for (
auto n = selected_rows; n; n = g_list_next (n))
829 rv.emplace_back (gtk_tree_row_reference_new (model, static_cast<GtkTreePath*>(n->data)));
831 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
836 gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
837 GNCImportMainMatcher *info)
841 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
842 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
843 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
844 auto selected_refs = get_treeview_selection_refs (treeview, model);
845 Account *assigned_account = NULL;
847 bool is_selection =
true;
850 DEBUG(
"Rows in selection = %zu", selected_refs.size());
852 for (
const auto& ref : selected_refs)
854 auto path = gtk_tree_row_reference_get_path (ref.get());
855 if (debugging_enabled)
857 auto path_str = gtk_tree_path_to_string (path);
858 DEBUG(
"passing first = %s", first ?
"true" :
"false");
859 DEBUG(
"passing is_selection = %s", is_selection ?
"true" :
"false");
860 DEBUG(
"passing path = %s", path_str);
863 gnc_gen_trans_assign_transfer_account (treeview,
864 &first, is_selection, path,
865 &assigned_account, info);
866 if (debugging_enabled)
869 DEBUG(
"returned value of account = %s", fullname);
870 DEBUG(
"returned value of first = %s", first ?
"true" :
"false");
874 gtk_tree_path_free (path);
875 if (!assigned_account)
880 for (
const auto& ref : selected_refs)
882 GtkTreePath *path = gtk_tree_row_reference_get_path (ref.get());
883 gtk_tree_selection_select_path (selection, path);
884 gtk_tree_path_free (path);
893 RowInfo (GtkTreePath *path, GNCImportMainMatcher *info)
895 init_from_path (path, info);
897 RowInfo (
const TreeRowReferencePtr &ref, GNCImportMainMatcher *info)
899 auto path = gtk_tree_row_reference_get_path (ref.get());
900 init_from_path (path, info);
901 gtk_tree_path_free (path);
905 g_free (m_orig_desc);
906 g_free (m_orig_notes);
907 g_free (m_orig_memo);
909 GNCImportTransInfo* get_trans_info () {
return m_trans_info; };
910 GtkTreeIter* get_iter () {
return &m_iter; };
911 const char* get_orig_desc () {
return m_orig_desc; };
912 const char* get_orig_notes () {
return m_orig_notes; };
913 const char* get_orig_memo () {
return m_orig_memo; };
915 void init_from_path (GtkTreePath *path, GNCImportMainMatcher *info)
917 auto model = gtk_tree_view_get_model (info->view);
918 gtk_tree_model_get_iter (model, &m_iter, path);
919 gtk_tree_model_get (model, &m_iter,
920 DOWNLOADED_COL_DATA, &m_trans_info,
921 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &m_orig_desc,
922 DOWNLOADED_COL_NOTES_ORIGINAL, &m_orig_notes,
923 DOWNLOADED_COL_MEMO_ORIGINAL, &m_orig_memo,
926 GNCImportTransInfo *m_trans_info;
928 char *m_orig_desc, *m_orig_notes, *m_orig_memo;
933 COMPLETION_LIST_ORIGINAL,
934 COMPLETION_LIST_NORMALIZED_FOLDED,
938 static void populate_list (gpointer key, gpointer value, GtkListStore *list)
941 auto original =
static_cast<const char*
>(key);
942 char *normalized = g_utf8_normalize (original, -1, G_NORMALIZE_NFC);
943 char *normalized_folded = normalized ? g_utf8_casefold (normalized, -1) : NULL;
944 gtk_list_store_append (list, &iter);
945 gtk_list_store_set (list, &iter,
946 COMPLETION_LIST_ORIGINAL, original,
947 COMPLETION_LIST_NORMALIZED_FOLDED, normalized_folded,
949 g_free (normalized_folded);
954 match_func (GtkEntryCompletion *completion,
const char *entry_str,
955 GtkTreeIter *iter, gpointer user_data)
957 auto model =
static_cast<GtkTreeModel*
>(user_data);
958 gchar *existing_str = NULL;
960 gtk_tree_model_get (model, iter,
961 COMPLETION_LIST_NORMALIZED_FOLDED, &existing_str,
963 if (existing_str && *existing_str && strstr (existing_str, entry_str))
965 g_free (existing_str);
972 GObject *override_widget;
978 static void override_widget_clicked (GtkWidget *widget,
EntryInfo *entryinfo)
980 gtk_widget_set_visible (GTK_WIDGET (entryinfo->override_widget),
false);
981 gtk_widget_set_sensitive (entryinfo->entry,
true);
982 gtk_entry_set_text (GTK_ENTRY (entryinfo->entry),
"");
983 gtk_widget_grab_focus (entryinfo->entry);
984 entryinfo->can_edit =
true;
990 auto sensitive = entryinfo.can_edit;
991 auto entry = entryinfo.entry;
992 auto override_widget = GTK_WIDGET (entryinfo.override_widget);
993 auto hash = entryinfo.hash;
994 auto initial = entryinfo.initial;
996 gtk_widget_set_sensitive (entry, sensitive);
997 gtk_widget_set_visible (override_widget, !sensitive);
999 if (sensitive && initial && *initial)
1000 gtk_entry_set_text (GTK_ENTRY (entry), initial);
1001 else if (!sensitive)
1003 gtk_entry_set_text (GTK_ENTRY (entry), _(
"Click Edit to modify"));
1004 g_signal_connect (override_widget,
"clicked", G_CALLBACK (override_widget_clicked),
1008 GtkListStore *list = gtk_list_store_new (NUM_COMPLETION_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1009 g_hash_table_foreach (hash, (GHFunc)populate_list, list);
1010 if (initial && *initial && !g_hash_table_lookup (hash, (gpointer)initial))
1011 populate_list ((gpointer)initial, NULL, list);
1012 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list),
1013 COMPLETION_LIST_ORIGINAL,
1014 GTK_SORT_ASCENDING);
1016 GtkEntryCompletion *completion = gtk_entry_completion_new ();
1017 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL(list));
1018 gtk_entry_completion_set_text_column (completion, COMPLETION_LIST_ORIGINAL);
1019 gtk_entry_completion_set_match_func (completion,
1020 (GtkEntryCompletionMatchFunc)match_func,
1021 GTK_TREE_MODEL(list), NULL);
1022 gtk_entry_set_completion (GTK_ENTRY (entry), completion);
1026 input_new_fields (GNCImportMainMatcher *info,
RowInfo& rowinfo,
1027 char **new_desc,
char **new_notes,
char **new_memo)
1029 GtkBuilder *builder = gtk_builder_new ();
1030 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_edit_dialog");
1032 GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_edit_dialog"));
1035 gtk_widget_set_name (GTK_WIDGET(dialog),
"gnc-id-import-matcher-edits");
1036 gnc_widget_style_context_add_class (GTK_WIDGET(dialog),
"gnc-class-imports");
1038 GtkWidget *desc_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"desc_entry"));
1039 GtkWidget *memo_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"memo_entry"));
1040 GtkWidget *notes_entry = GTK_WIDGET(gtk_builder_get_object (builder,
"notes_entry"));
1045 std::vector<EntryInfo> entries = {
1046 { desc_entry, gtk_builder_get_object (builder,
"desc_override"), info->can_edit_desc, info->desc_hash,
xaccTransGetDescription (trans) },
1047 { notes_entry, gtk_builder_get_object (builder,
"notes_override"), info->can_edit_notes, info->notes_hash,
xaccTransGetNotes (trans) },
1048 { memo_entry, gtk_builder_get_object (builder,
"memo_override"), info->can_edit_memo, info->memo_hash,
xaccSplitGetMemo (split) },
1051 std::for_each (entries.begin(), entries.end(), setup_entry);
1055 auto it = std::find_if (entries.begin(), entries.end(), [](
auto info){
return info.can_edit; });
1056 if (it != entries.end())
1057 gtk_widget_grab_focus (it->entry);
1059 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (info->main_widget));
1062 gtk_widget_show (dialog);
1064 bool retval =
false;
1065 switch (gtk_dialog_run (GTK_DIALOG(dialog)))
1067 case GTK_RESPONSE_OK:
1068 *new_desc = g_strdup (gtk_entry_get_text (GTK_ENTRY (desc_entry)));
1069 *new_notes = g_strdup (gtk_entry_get_text (GTK_ENTRY (notes_entry)));
1070 *new_memo = g_strdup (gtk_entry_get_text (GTK_ENTRY (memo_entry)));
1077 gtk_widget_destroy (dialog);
1078 g_object_unref (G_OBJECT(builder));
1083 maybe_add_string (GNCImportMainMatcher *info, GHashTable *hash,
const char *str)
1085 if (!str || !str[0] || g_hash_table_lookup (hash, str))
1087 char *new_string = g_strdup (str);
1088 info->new_strings = g_list_prepend (info->new_strings, new_string);
1089 g_hash_table_insert (hash, new_string, one);
1093 gnc_gen_trans_set_price_to_selection_cb (GtkMenuItem *menuitem,
1094 GNCImportMainMatcher *info)
1097 g_return_if_fail (info);
1099 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1100 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1101 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1102 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1106 LEAVE (
"No selected rows");
1110 for (GList *n = selected_rows; n; n = g_list_next (n))
1112 RowInfo row{
static_cast<GtkTreePath*
>(n->data), info};
1120 XferDialog *xfer = gnc_xfer_dialog(GTK_WIDGET (info->main_widget), src_acc);
1121 gnc_xfer_dialog_select_to_account(xfer, dest_acc);
1122 gnc_xfer_dialog_set_amount(xfer, dest_value);
1123 gnc_xfer_dialog_set_date (xfer, post_date);
1127 gnc_xfer_dialog_set_from_show_button_active(xfer,
false);
1128 gnc_xfer_dialog_set_to_show_button_active(xfer,
false);
1129 gnc_xfer_dialog_hide_from_account_tree(xfer);
1130 gnc_xfer_dialog_hide_to_account_tree(xfer);
1132 gnc_xfer_dialog_is_exchange_dialog(xfer, &exch);
1134 if (!gnc_xfer_dialog_run_until_done(xfer))
1146 refresh_model_row (info, model, row.get_iter(), row.get_trans_info());
1149 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1154 gnc_gen_trans_edit_fields (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1158 g_return_if_fail (info);
1160 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1161 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1162 GtkTreeStore *store = GTK_TREE_STORE (model);
1163 auto selected_refs = get_treeview_selection_refs (treeview, model);
1165 if (selected_refs.empty())
1167 LEAVE (
"No selected rows");
1171 char *new_desc = NULL, *new_notes = NULL, *new_memo = NULL;
1172 RowInfo first_row{selected_refs[0], info};
1173 if (input_new_fields (info, first_row, &new_desc, &new_notes, &new_memo))
1175 for (
const auto& ref : selected_refs)
1180 if (info->can_edit_desc)
1182 gint style = g_strcmp0 (new_desc, row.get_orig_desc()) ?
1183 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1184 gtk_tree_store_set (store, row.get_iter(),
1185 DOWNLOADED_COL_DESCRIPTION, new_desc,
1186 DOWNLOADED_COL_DESCRIPTION_STYLE, style,
1189 maybe_add_string (info, info->desc_hash, new_desc);
1192 if (info->can_edit_notes)
1195 maybe_add_string (info, info->notes_hash, new_notes);
1198 if (info->can_edit_memo)
1200 gint style = g_strcmp0 (new_memo, row.get_orig_memo()) ?
1201 PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1202 gtk_tree_store_set (store, row.get_iter(),
1203 DOWNLOADED_COL_MEMO, new_memo,
1204 DOWNLOADED_COL_MEMO_STYLE, style,
1207 maybe_add_string (info, info->memo_hash, new_memo);
1218 gnc_gen_trans_reset_edits_cb (GtkMenuItem *menuitem, GNCImportMainMatcher *info)
1220 g_return_if_fail (info);
1221 ENTER(
"gnc_gen_trans_reset_edits_cb");
1223 GtkTreeView *treeview = GTK_TREE_VIEW(info->view);
1224 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1225 GtkTreeStore *store = GTK_TREE_STORE (model);
1226 auto selected_refs = get_treeview_selection_refs (treeview, model);
1228 if (selected_refs.empty())
1230 LEAVE (
"No selected rows");
1234 for (
const auto& ref : selected_refs)
1242 gtk_tree_store_set (store, rowinfo.get_iter(),
1243 DOWNLOADED_COL_DESCRIPTION, rowinfo.get_orig_desc(),
1244 DOWNLOADED_COL_MEMO, rowinfo.get_orig_memo(),
1245 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1246 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1253 gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
1255 GtkTreeViewColumn *column,
1256 GNCImportMainMatcher *info)
1261 bool is_selection =
false;
1262 Account *assigned_account = NULL;
1263 gnc_gen_trans_assign_transfer_account (treeview,
1264 &first, is_selection, path,
1265 &assigned_account, info);
1267 gtk_tree_selection_select_path (gtk_tree_view_get_selection (treeview), path);
1270 DEBUG(
"account returned = %s", namestr);
1275 static GNCImportAction
1276 get_action_for_path (GtkTreePath* path, GtkTreeModel *model)
1278 GNCImportTransInfo *trans_info;
1280 gtk_tree_model_get_iter (model, &iter, path);
1281 gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
1285 return GNCImport_INVALID_ACTION;
1290 gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
1291 GNCImportMainMatcher *info)
1293 GtkTreeModel *model;
1297 if (gtk_tree_selection_count_selected_rows (selection) >= 2)
1300 GList* list = gtk_tree_selection_get_selected_rows (selection, &model);
1301 for (GList *n = list; n; n = n->next)
1303 auto path =
static_cast<GtkTreePath*
>(n->data);
1304 if (get_action_for_path (path, model) != GNCImport_ADD)
1305 gtk_tree_selection_unselect_path (selection, path);
1307 g_list_free_full (list, (GDestroyNotify)gtk_tree_path_free);
1310 GtkSelectionMode mode = gtk_tree_selection_get_mode (selection);
1313 case GTK_SELECTION_MULTIPLE:
1314 DEBUG(
"mode = GTK_SELECTION_MULTIPLE, no action");
1316 case GTK_SELECTION_NONE:
1317 DEBUG(
"mode = GTK_SELECTION_NONE, no action");
1319 case GTK_SELECTION_BROWSE:
1320 DEBUG(
"mode = GTK_SELECTION_BROWSE->default");
1321 case GTK_SELECTION_SINGLE:
1322 DEBUG(
"mode = GTK_SELECTION_SINGLE->default");
1324 DEBUG(
"mode = default unselect selected row");
1325 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1327 gtk_tree_selection_unselect_iter (selection, &iter);
1334 gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
1336 GNCImportMainMatcher *info)
1340 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1341 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1342 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
1344 const char *desc = NULL, *memo = NULL, *notes = NULL;
1347 RowInfo first_rowinfo{
static_cast<GtkTreePath*
>(selected_rows->data), info};
1356 info->can_edit_desc =
true;
1357 info->can_edit_notes =
true;
1358 info->can_edit_memo =
true;
1359 bool can_undo_edits =
false;
1360 bool can_update_prices =
true;
1361 bool can_assign_acct =
true;
1362 for (GList *n = selected_rows; n; n = g_list_next(n))
1364 RowInfo rowinfo{
static_cast<GtkTreePath*
>(n->data), info};
1367 if (can_assign_acct)
1374 if (can_update_prices)
1380 can_update_prices =
false;
1386 if (info->can_edit_desc)
1388 if (info->can_edit_notes)
1390 if (info->can_edit_memo)
1395 if (!can_undo_edits)
1396 can_undo_edits = (g_strcmp0 (
xaccSplitGetMemo (split), rowinfo.get_orig_memo()) ||
1401 if (!can_assign_acct && !can_update_prices &&
1402 !info->can_edit_desc && !info->can_edit_notes && !info->can_edit_memo &&
1407 GtkWidget *menu = gtk_menu_new();
1409 auto add_menu_item = [&menu, &info](
const char* name,
bool sensitive, GCallback callback)
1411 auto menuitem = gtk_menu_item_new_with_mnemonic (_(name));
1412 gtk_widget_set_sensitive (menuitem, sensitive);
1413 g_signal_connect (menuitem,
"activate", callback, info);
1414 gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
1418 add_menu_item (N_(
"_Assign transfer account"),
1420 G_CALLBACK(gnc_gen_trans_assign_transfer_account_to_selection_cb));
1423 add_menu_item (N_(
"Assign e_xchange rate"),
1425 G_CALLBACK (gnc_gen_trans_set_price_to_selection_cb));
1428 add_menu_item (N_(
"_Edit description, notes, or memo"),
1429 info->can_edit_desc || info->can_edit_notes || info->can_edit_memo,
1430 G_CALLBACK (gnc_gen_trans_edit_fields));
1433 add_menu_item (N_(
"_Reset all edits"),
1435 G_CALLBACK (gnc_gen_trans_reset_edits_cb));
1437 gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (treeview), NULL);
1439 gtk_widget_show_all (menu);
1441 gtk_menu_popup_at_pointer (GTK_MENU(menu), (GdkEvent*)event);
1443 g_list_free_full (selected_rows, (GDestroyNotify)gtk_tree_path_free);
1448 gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
1450 GNCImportMainMatcher *info)
1453 g_return_val_if_fail (treeview != NULL,
false);
1454 g_return_val_if_fail (event != NULL,
false);
1456 if (event->type == GDK_BUTTON_PRESS)
1458 GdkEventButton *event_button = (GdkEventButton *) event;
1459 if (event_button->button == GDK_BUTTON_SECONDARY)
1461 DEBUG(
"Right mouseClick detected - popup the menu.");
1463 auto selection = gtk_tree_view_get_selection (treeview);
1464 auto selected_rows = gtk_tree_selection_count_selected_rows (selection);
1469 GtkTreePath* path =
nullptr;
1470 if (gtk_tree_view_get_path_at_pos (treeview, event_button->x,
1471 event_button->y, &path,
nullptr,
nullptr,
nullptr))
1473 gtk_tree_selection_select_path (selection, path);
1475 gtk_tree_path_free (path);
1478 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1480 GtkTreeModel *model;
1481 auto selected = gtk_tree_selection_get_selected_rows (selection, &model);
1482 if (get_action_for_path (static_cast<GtkTreePath*>(selected->data), model) == GNCImport_ADD)
1483 gnc_gen_trans_view_popup_menu (treeview, event, info);
1484 g_list_free_full (selected, (GDestroyNotify)gtk_tree_path_free);
1486 LEAVE(
"return true");
1490 LEAVE(
"return false");
1495 gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
1496 GNCImportMainMatcher *info)
1498 ENTER(
"onPopupMenu_cb");
1500 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1501 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1503 gnc_gen_trans_view_popup_menu (treeview, NULL, info);
1511 static GtkTreeViewColumn *
1512 add_text_column (GtkTreeView *view,
const gchar *title,
int col_num,
bool ellipsize)
1514 GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1515 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title,
1518 "background", DOWNLOADED_COL_COLOR,
1522 g_object_set (renderer,
"ellipsize", PANGO_ELLIPSIZE_END, NULL);
1525 if (col_num == DOWNLOADED_COL_DATE_TXT)
1526 gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_DATE_INT64);
1527 else if (col_num == DOWNLOADED_COL_AMOUNT)
1529 gtk_cell_renderer_set_alignment (renderer, 1.0, 0.5);
1530 gtk_cell_renderer_set_padding (renderer, 5, 0);
1531 gtk_tree_view_column_set_sort_column_id (column, DOWNLOADED_COL_AMOUNT_DOUBLE);
1534 gtk_tree_view_column_set_sort_column_id (column, col_num);
1536 if (col_num == DOWNLOADED_COL_DESCRIPTION)
1537 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_DESCRIPTION_STYLE);
1539 if (col_num == DOWNLOADED_COL_MEMO)
1540 gtk_tree_view_column_add_attribute (column, renderer,
"style", DOWNLOADED_COL_MEMO_STYLE);
1542 g_object_set (G_OBJECT(column),
1543 "reorderable",
true,
1546 gtk_tree_view_append_column (view, column);
1550 static GtkTreeViewColumn *
1551 add_toggle_column (GtkTreeView *view,
const gchar *title,
int col_num,
1552 GCallback cb_fn, gpointer cb_arg)
1554 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
1555 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title, renderer,
1557 "cell-background", DOWNLOADED_COL_COLOR,
1558 "activatable", DOWNLOADED_COL_ENABLE,
1559 "visible", DOWNLOADED_COL_ENABLE,
1561 gtk_tree_view_column_set_sort_column_id (column, col_num);
1562 g_object_set (G_OBJECT(column),
"reorderable",
true, NULL);
1563 g_signal_connect (renderer,
"toggled", cb_fn, cb_arg);
1564 gtk_tree_view_append_column (view, column);
1569 gnc_gen_trans_init_view (GNCImportMainMatcher *info,
1573 GtkTreeView *view = info->view;
1574 GtkTreeStore *store = gtk_tree_store_new (NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64,
1575 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE,
1576 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1577 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
1578 G_TYPE_STRING, G_TYPE_BOOLEAN,
1579 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
1580 GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING,
1582 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
1583 g_object_unref (store);
1586 gtk_tree_view_set_reorderable (view,
false);
1589 add_text_column (view, _(
"Date"), DOWNLOADED_COL_DATE_TXT,
false);
1590 info->account_column = add_text_column (view, _(
"Account"), DOWNLOADED_COL_ACCOUNT,
false);
1591 gtk_tree_view_column_set_visible (info->account_column, show_account);
1592 add_text_column (view, _(
"Amount"), DOWNLOADED_COL_AMOUNT,
false);
1593 add_text_column (view, _(
"Description"), DOWNLOADED_COL_DESCRIPTION,
false);
1594 info->memo_column = add_text_column (view, _(
"Memo"), DOWNLOADED_COL_MEMO,
true);
1595 add_toggle_column (view, C_(
"Column header for 'Adding transaction'",
"A"),
1596 DOWNLOADED_COL_ACTION_ADD,
1597 G_CALLBACK(gnc_gen_trans_add_toggled_cb), info);
1598 GtkTreeViewColumn *column = add_toggle_column (view,
1599 C_(
"Column header for 'Updating plus Clearing transaction'",
"U+C"),
1600 DOWNLOADED_COL_ACTION_UPDATE,
1601 G_CALLBACK(gnc_gen_trans_update_toggled_cb), info);
1602 gtk_tree_view_column_set_visible (column, show_update);
1603 add_toggle_column (view, C_(
"Column header for 'Clearing transaction'",
"C"),
1604 DOWNLOADED_COL_ACTION_CLEAR,
1605 G_CALLBACK(gnc_gen_trans_clear_toggled_cb), info);
1608 GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
1609 g_object_set (renderer,
"xalign", 0.0, NULL);
1610 column = gtk_tree_view_column_new_with_attributes (_(
"Info"), renderer,
1611 "pixbuf", DOWNLOADED_COL_ACTION_PIXBUF,
1612 "cell-background", DOWNLOADED_COL_COLOR,
1615 gtk_tree_view_append_column (info->view, column);
1617 column = add_text_column (view, _(
"Additional Comments"), DOWNLOADED_COL_ACTION_INFO,
false);
1618 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1621 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
1622 DOWNLOADED_COL_DATE_INT64,
1623 GTK_SORT_ASCENDING);
1624 GtkTreeSelection *selection = gtk_tree_view_get_selection (info->view);
1626 g_object_set (info->view,
"has-tooltip",
true, NULL);
1628 g_signal_connect (G_OBJECT(info->view),
"query-tooltip",
1629 G_CALLBACK(query_tooltip_tree_view_cb), info);
1630 g_signal_connect (info->view,
"row-activated",
1631 G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
1632 g_signal_connect (selection,
"changed",
1633 G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
1634 g_signal_connect (view,
"button-press-event",
1635 G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
1636 g_signal_connect (view,
"popup-menu",
1637 G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
1641 show_account_column_toggled_cb (GtkToggleButton *togglebutton,
1642 GNCImportMainMatcher *info)
1644 gtk_tree_view_column_set_visible (info->account_column,
1645 gtk_toggle_button_get_active (togglebutton));
1649 show_memo_column_toggled_cb (GtkToggleButton *togglebutton,
1650 GNCImportMainMatcher *info)
1652 gtk_tree_view_column_set_visible (info->memo_column,
1653 gtk_toggle_button_get_active (togglebutton));
1657 show_matched_info_toggled_cb (GtkToggleButton *togglebutton,
1658 GNCImportMainMatcher *info)
1660 if (gtk_toggle_button_get_active (togglebutton))
1662 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column),
true);
1663 gtk_tree_view_expand_all (info->view);
1667 gtk_tree_view_column_set_visible (info->account_column,
1668 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->show_account_column)));
1669 gtk_tree_view_collapse_all (info->view);
1674 gnc_gen_trans_common_setup (GNCImportMainMatcher *info,
1676 GtkBuilder *builder,
1677 const gchar* heading,
1678 bool all_from_same_account,
1679 gint match_date_hardlimit)
1681 info->pending_matches = gnc_import_PendingMatches_new ();
1687 GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(parent));
1689 gtk_style_context_get_color (stylectxt, GTK_STATE_FLAG_NORMAL, &color);
1693 info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder,
"downloaded_view"));
1694 g_assert (info->view != NULL);
1696 info->show_account_column = GTK_WIDGET(gtk_builder_get_object (builder,
"show_source_account_button"));
1697 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), all_from_same_account);
1698 g_signal_connect (G_OBJECT(info->show_account_column),
"toggled",
1699 G_CALLBACK(show_account_column_toggled_cb), info);
1701 GtkWidget *button = GTK_WIDGET(gtk_builder_get_object (builder,
"show_memo_column_button"));
1702 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
true);
1703 g_signal_connect (G_OBJECT(button),
"toggled",
1704 G_CALLBACK(show_memo_column_toggled_cb), info);
1706 info->show_matched_info = GTK_WIDGET(gtk_builder_get_object (builder,
"show_matched_info_button"));
1707 g_signal_connect (G_OBJECT(info->show_matched_info),
"toggled",
1708 G_CALLBACK(show_matched_info_toggled_cb), info);
1710 info->append_text = GTK_WIDGET(gtk_builder_get_object (builder,
"append_desc_notes_button"));
1713 info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder,
"reconcile_after_close_button"));
1716 GtkWidget *heading_label = GTK_WIDGET(gtk_builder_get_object (builder,
"heading_label"));
1718 gtk_label_set_text (GTK_LABEL(heading_label), heading);
1721 gnc_gen_trans_init_view (info, all_from_same_account, show_update);
1723 info->acct_id_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1724 (GDestroyNotify)g_hash_table_destroy);
1725 info->desc_hash = g_hash_table_new (g_str_hash, g_str_equal);
1726 info->notes_hash = g_hash_table_new (g_str_hash, g_str_equal);
1727 info->memo_hash = g_hash_table_new (g_str_hash, g_str_equal);
1728 info->new_strings = NULL;
1729 info->transaction_processed_cb = NULL;
1732 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
1734 g_object_unref (G_OBJECT(builder));
1738 GNCImportMainMatcher *
1740 const gchar* heading,
1741 bool all_from_same_account,
1742 gint match_date_hardlimit,
1745 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1748 GtkBuilder *builder = gtk_builder_new ();
1749 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_dialog");
1750 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1752 info->main_widget = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_dialog"));
1753 g_assert (info->main_widget != NULL);
1756 GtkWidget *pbox = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_vbox"));
1757 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1758 gtk_box_pack_start (GTK_BOX(pbox), box,
true,
true, 0);
1761 gtk_widget_set_name (GTK_WIDGET(info->main_widget),
"gnc-id-import-matcher-transactions");
1762 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1763 gnc_widget_style_context_add_class (GTK_WIDGET(info->main_widget),
"gnc-class-imports");
1766 gnc_gen_trans_common_setup (info, parent, builder, heading,
1767 all_from_same_account, match_date_hardlimit);
1770 gtk_window_set_transient_for (GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1772 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1775 gtk_widget_show_all (GTK_WIDGET(info->main_widget));
1778 info->id = gnc_register_gui_component (IMPORT_MAIN_MATCHER_CM_CLASS,
1783 gnc_gui_component_set_session (info->id, gnc_get_current_session());
1792 GNCImportMainMatcher *
1794 GtkWidget *assistant_page,
1795 const gchar* heading,
1796 bool all_from_same_account,
1797 gint match_date_hardlimit)
1799 GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1800 info->main_widget = GTK_WIDGET(parent);
1803 GtkBuilder *builder = gtk_builder_new ();
1804 gnc_builder_add_from_file (builder,
"dialog-import.glade",
"transaction_matcher_content");
1807 GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
"transaction_matcher_content"));
1808 g_assert (box != NULL);
1809 gtk_box_pack_start (GTK_BOX(assistant_page), box,
true,
true, 6);
1812 gtk_widget_set_name (GTK_WIDGET(box),
"gnc-id-import-transaction-content");
1815 gnc_gen_trans_common_setup (info, parent, builder, heading,
1816 all_from_same_account, match_date_hardlimit);
1824 on_matcher_ok_clicked (NULL, info);
1833 GNCTransactionProcessedCB trans_processed_cb,
1836 info->user_data = user_data;
1837 info->transaction_processed_cb = trans_processed_cb;
1844 bool result = gtk_dialog_run (GTK_DIALOG (info->main_widget));
1854 get_required_color (
const gchar *class_name)
1857 GtkWidget *label = gtk_label_new (
"Color");
1858 GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET(label));
1859 gtk_style_context_add_class (context, class_name);
1861 static gchar *strbuf = NULL;
1864 strbuf = gdk_rgba_to_string (&color);
1869 remove_child_row (GtkTreeModel *model, GtkTreeIter *iter)
1871 if (gtk_tree_model_iter_has_child (model, iter))
1874 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1875 gtk_tree_store_remove (GTK_TREE_STORE(model), &child);
1880 update_child_row (
GNCImportMatchInfo *sel_match, GtkTreeModel *model, GtkTreeIter *iter)
1882 GtkTreeStore *store = GTK_TREE_STORE(model);
1884 if (!gtk_tree_model_iter_has_child (model, iter))
1885 gtk_tree_store_append (GTK_TREE_STORE(model), &child, iter);
1887 gtk_tree_model_iter_nth_child (model, &child, iter, 0);
1891 : _(
"-- Split Transaction --");
1895 gtk_tree_store_set (store, &child,
1896 DOWNLOADED_COL_ACCOUNT, account_str,
1897 DOWNLOADED_COL_DATE_TXT, date,
1898 DOWNLOADED_COL_AMOUNT, amount_str,
1900 DOWNLOADED_COL_MEMO_STYLE, PANGO_STYLE_NORMAL,
1902 DOWNLOADED_COL_DESCRIPTION_STYLE, PANGO_STYLE_NORMAL,
1903 DOWNLOADED_COL_ENABLE,
false,
1909 get_peer_acct_names (Split *split)
1911 GList *names = NULL, *accounts_seen = NULL;
1915 if ((n->data == split) ||
1917 (g_list_find (accounts_seen, account)))
1920 names = g_list_prepend (names, name);
1921 accounts_seen = g_list_prepend (accounts_seen, account);
1923 names = g_list_sort (names, (GCompareFunc)g_utf8_collate);
1925 g_list_free_full (names, g_free);
1926 g_list_free (accounts_seen);
1931 refresh_model_row (GNCImportMainMatcher *gui,
1932 GtkTreeModel *model,
1934 GNCImportTransInfo *info)
1941 GtkTreeStore *store = GTK_TREE_STORE(model);
1942 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATA, info, -1);
1944 const gchar *class_extension = NULL;
1945 if (gui->dark_theme)
1946 class_extension =
"-dark";
1948 gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
1949 gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
1950 gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
1953 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ENABLE,
true, -1);
1959 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);
1964 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_TXT, text, -1);
1965 gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_INT64, date, -1);
1970 ro_text =
xaccPrintAmount (amount, gnc_split_amount_print_info (split,
true));
1971 gtk_tree_store_set (store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);
1976 gtk_tree_store_set (store, iter, DOWNLOADED_COL_NOTES_ORIGINAL, ro_text, -1);
1980 gtk_tree_store_set (store, iter,
1981 DOWNLOADED_COL_DESCRIPTION, ro_text,
1982 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, ro_text,
1986 gtk_tree_store_set (store, iter,
1987 DOWNLOADED_COL_MEMO, ro_text,
1988 DOWNLOADED_COL_MEMO_ORIGINAL, ro_text,
1994 ro_text = text = NULL;
1995 const gchar *color = NULL;
1996 bool show_pixbuf =
true;
2002 ro_text = _(
"New, already balanced");
2003 color = get_required_color (int_not_required_class);
2008 char *imbalance = NULL;
2018 color = get_required_color (int_not_required_class);
2024 g_strdup_printf (_(
"New, transfer %s to (manual) \"%s\""),
2025 imbalance, acct_full_name);
2032 g_strdup_printf (_(
"New, transfer %s to (auto) \"%s\""),
2033 imbalance, acct_full_name);
2042 color = get_required_color (int_required_class);
2045 g_strdup_printf (_(
"New, UNBALANCED (need price to transfer %s to acct %s)!"),
2046 imbalance, acct_full_name);
2050 g_free (acct_full_name);
2058 color = get_required_color (int_prob_required_class);
2061 g_strdup_printf (_(
"New, UNBALANCED (need acct to transfer %s)!"),
2064 remove_child_row (model, iter);
2069 case GNCImport_CLEAR:
2075 gchar *full_names = get_peer_acct_names (sel_match->split);
2076 color = get_required_color (int_not_required_class);
2079 text = g_strdup_printf (_(
"Reconcile (manual) match to %s"),
2084 text = g_strdup_printf (_(
"Reconcile (auto) match to %s"),
2087 g_free (full_names);
2088 update_child_row (sel_match, model, iter);
2092 color = get_required_color (int_required_class);
2093 ro_text = _(
"Match missing!");
2094 show_pixbuf =
false;
2095 remove_child_row (model, iter);
2099 case GNCImport_UPDATE:
2104 gchar *full_names = get_peer_acct_names (sel_match->split);
2105 color = get_required_color (int_not_required_class);
2108 text = g_strdup_printf (_(
"Update and reconcile (manual) match to %s"),
2113 text = g_strdup_printf (_(
"Update and reconcile (auto) match to %s"),
2116 g_free (full_names);
2117 update_child_row (sel_match, model, iter);
2121 color = get_required_color (int_required_class);
2122 ro_text = _(
"Match missing!");
2123 show_pixbuf =
false;
2124 remove_child_row (model, iter);
2128 case GNCImport_SKIP:
2129 color = get_required_color (int_required_class);
2130 ro_text = _(
"Do not import (no action selected)");
2131 show_pixbuf =
false;
2132 remove_child_row (model, iter);
2136 ro_text =
"WRITEME, this is an unknown action";
2137 show_pixbuf =
false;
2141 gtk_tree_store_set (store, iter,
2142 DOWNLOADED_COL_COLOR, color,
2143 DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text,
2148 g_free (int_required_class);
2149 g_free (int_prob_required_class);
2150 g_free (int_not_required_class);
2153 gtk_tree_store_set (store, iter,
2154 DOWNLOADED_COL_ACTION_ADD,
2160 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2163 gtk_tree_store_set (store, iter,
2164 DOWNLOADED_COL_ACTION_CLEAR,
2171 gtk_tree_store_set (store, iter,
2172 DOWNLOADED_COL_ACTION_PIXBUF,
2176 GTK_WIDGET(gui->view)),
2179 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2182 gtk_tree_store_set (store, iter,
2183 DOWNLOADED_COL_ACTION_UPDATE,
2190 gtk_tree_store_set (store, iter,
2191 DOWNLOADED_COL_ACTION_PIXBUF,
2195 GTK_WIDGET(gui->view)),
2198 gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, NULL, -1);
2202 if (gtk_tree_model_iter_has_child (model, iter))
2204 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui->show_matched_info)))
2206 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
2208 gtk_tree_view_column_set_visible (gui->account_column,
true);
2209 gtk_tree_view_column_set_visible (gui->memo_column,
true);
2211 gtk_tree_view_expand_row (GTK_TREE_VIEW(gui->view), path,
true);
2212 gtk_tree_path_free (path);
2215 GtkTreeSelection *selection = gtk_tree_view_get_selection (gui->view);
2216 gtk_tree_selection_unselect_all (selection);
2221 bool reconcile_after_close,
2224 gtk_widget_set_visible (info->reconcile_after_close, reconcile_after_close);
2225 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->reconcile_after_close), active);
2231 return info->reconcile_after_close;
2236 gnc_gen_trans_list_add_trans_internal (GNCImportMainMatcher *gui, Transaction *trans,
2244 defer_bal_computation (gui, acc);
2250 DEBUG(
"%s",
"Transaction with same online ID exists, destroying current transaction");
2261 gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info);
2267 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, NULL);
2273 gnc_gen_trans_list_add_trans_internal (gui, trans, ref_id, NULL);
2280 gnc_gen_trans_list_add_trans_internal (gui, trans, 0, lsplit);
2289 filter_existing_splits_on_account_and_date (GNCImportMainMatcher *gui)
2291 static const int secs_per_day = 86400;
2292 gint match_date_limit =
2294 time64 min_time=G_MAXINT64, max_time=0;
2295 time64 match_timelimit = match_date_limit * secs_per_day;
2296 GList *all_accounts = NULL;
2301 for (GSList* txn = gui->temp_trans_list; txn != NULL;
2302 txn = g_slist_next (txn))
2304 auto txn_info =
static_cast<GNCImportTransInfo*
>(txn->data);
2309 all_accounts = g_list_prepend (all_accounts, txn_account);
2310 min_time = MIN(min_time, txn_time);
2311 max_time = MAX(max_time, txn_time);
2315 Query *query = qof_query_create_for (GNC_ID_SPLIT);
2317 xaccQueryAddAccountMatch (query, all_accounts,
2319 xaccQueryAddDateMatchTT (query,
2320 true, min_time - match_timelimit,
2321 true, max_time + match_timelimit,
2324 g_list_free (all_accounts);
2325 GList *retval = g_list_copy (query_results);
2335 create_hash_of_potential_matches (GList *candidate_splits,
2336 GHashTable *account_hash)
2338 for (GList* candidate = candidate_splits; candidate != NULL;
2339 candidate = g_list_next (candidate))
2341 auto split =
static_cast<Split*
>(candidate->data);
2342 if (gnc_import_split_has_online_id (split))
2352 auto split_list =
static_cast<GSList*
>(g_hash_table_lookup (account_hash, split_account));
2353 g_hash_table_steal (account_hash, split_account);
2354 split_list = g_slist_prepend (split_list, split);
2355 g_hash_table_insert (account_hash, split_account, split_list);
2357 return account_hash;
2360 typedef struct _match_struct
2362 GNCImportTransInfo* transaction_info;
2363 gint display_threshold;
2364 gint date_threshold;
2365 gint date_not_threshold;
2366 double fuzzy_amount;
2373 s->display_threshold,
2375 s->date_not_threshold,
2385 perform_matching (GNCImportMainMatcher *gui, GHashTable *account_hash)
2387 GtkTreeModel* model = gtk_tree_view_get_model (gui->view);
2388 gint display_threshold =
2390 gint date_threshold =
2391 gnc_import_Settings_get_date_threshold (gui->user_settings);
2392 gint date_not_threshold =
2393 gnc_import_Settings_get_date_not_threshold (gui->user_settings);
2394 double fuzzy_amount =
2397 for (GSList *imported_txn = gui->temp_trans_list; imported_txn !=NULL;
2398 imported_txn = g_slist_next (imported_txn))
2400 auto txn_info =
static_cast<GNCImportTransInfo*
>(imported_txn->data);
2402 match_struct s = {txn_info, display_threshold, date_threshold, date_not_threshold, fuzzy_amount};
2404 g_slist_foreach (static_cast<GSList*>(g_hash_table_lookup (account_hash, importaccount)),
2405 (GFunc) match_helper, &s);
2411 bool match_selected_manually =
2415 gnc_import_PendingMatches_add_match (gui->pending_matches,
2417 match_selected_manually);
2420 gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
2421 refresh_model_row (gui, model, &iter, txn_info);
2426 gnc_gen_trans_list_create_matches (GNCImportMainMatcher *gui)
2428 GHashTable* account_hash =
2429 g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
2430 (GDestroyNotify)g_slist_free);
2432 GList *candidate_splits = filter_existing_splits_on_account_and_date (gui);
2434 create_hash_of_potential_matches (candidate_splits, account_hash);
2435 perform_matching (gui, account_hash);
2437 g_list_free (candidate_splits);
2438 g_hash_table_destroy (account_hash);
2446 return info->main_widget;
2453 return info->append_text;
2457 query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
2459 GtkTooltip *tooltip,
2462 GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
2463 GtkTreePath *path = NULL;
2464 GtkTreeViewColumn *column = NULL;
2465 gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &x, &y);
2466 if (keyboard_tip || !gtk_tree_view_get_path_at_pos (tree_view, x, y, &path,
2467 &column, NULL, NULL))
2469 gtk_tree_path_free (path);
2474 bool show_tooltip =
false;
2475 GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2477 if (gtk_tree_model_get_iter(model, &iter, path) && column)
2479 gchar *tooltip_text = NULL;
2482 gint num_col = gtk_tree_view_column_get_sort_column_id (column);
2485 case DOWNLOADED_COL_DESCRIPTION:
2486 gtk_tree_model_get (model, &iter,
2487 DOWNLOADED_COL_DESCRIPTION_ORIGINAL, &tooltip_text,
2490 case DOWNLOADED_COL_MEMO:
2491 gtk_tree_model_get (model, &iter,
2492 DOWNLOADED_COL_MEMO_ORIGINAL, &tooltip_text,
2500 if (tooltip_text && *tooltip_text)
2502 show_tooltip =
true;
2503 gtk_tooltip_set_text (tooltip, tooltip_text);
2504 gtk_tree_view_set_tooltip_cell (tree_view, tooltip, path, column, NULL);
2506 g_free (tooltip_text);
2509 gtk_tree_path_free (path);
2510 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.
double gnc_numeric_to_double(gnc_numeric in)
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...