diff --git a/gnucash/import-export/import-main-matcher.cpp b/gnucash/import-export/import-main-matcher.cpp index 3a6fd94da27..4c6b502d57b 100644 --- a/gnucash/import-export/import-main-matcher.cpp +++ b/gnucash/import-export/import-main-matcher.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include "import-main-matcher.h" @@ -193,33 +195,75 @@ defer_bal_computation (GNCImportMainMatcher *info, Account* acc) } } -struct TreeViewIter + +// Custom iterator class +class GtkTreeModelIterator { public: - TreeViewIter (GtkTreeView *view) - : m_model{gtk_tree_view_get_model (view)} - , m_value{(bool)gtk_tree_model_get_iter_first (m_model, &m_iter)} - {}; - gpointer get (gint col) + using iterator_category = std::forward_iterator_tag; + using difference_type = ptrdiff_t; + GtkTreeModelIterator(GtkTreeModel* model, std::optional iter) + : m_model(model), m_iter(iter) {} + GtkTreeModelIterator& operator++() { + if (m_iter.has_value() && !gtk_tree_model_iter_next(m_model, &*m_iter)) + m_iter = std::nullopt; + return *this; + } + template + T get (int column) { + g_return_val_if_fail (m_iter.has_value(), T()); gpointer rv; - gtk_tree_model_get (m_model, &m_iter, col, &rv, -1); - return rv; + gtk_tree_model_get(m_model, &*m_iter, column, &rv, -1); + return static_cast(rv); } - GNCImportTransInfo* get_trans_info () { return static_cast(get(DOWNLOADED_COL_DATA)); }; + GNCImportTransInfo* get_trans_info () + { + g_return_if_fail (m_iter.has_value(), nullptr); + return get(DOWNLOADED_COL_DATA); + }; std::string get_account_name () { - auto str = static_cast(get(DOWNLOADED_COL_ACCOUNT)); + g_return_if_fail (m_iter.has_value(), ""); + auto str = get(DOWNLOADED_COL_ACCOUNT); std::string rv{str}; g_free (str); return rv; } - bool has_value () { return m_value; }; - bool next () { return (m_value = gtk_tree_model_iter_next (m_model, &m_iter)); }; + GtkTreeModelIterator operator*() const { return *this; } + bool operator==(const GtkTreeModelIterator& other) const + { + if (!m_iter.has_value() && !other.m_iter.has_value()) + return true; + if (!m_iter.has_value() || !other.m_iter.has_value()) + return false; + return (m_model == other.m_model) && + (m_iter->stamp == other.m_iter->stamp) && + (m_iter->user_data == other.m_iter->user_data) && + (m_iter->user_data2 == other.m_iter->user_data2) && + (m_iter->user_data3 == other.m_iter->user_data3); + } + bool operator!=(const GtkTreeModelIterator& other) const { return !(*this == other); } +private: + GtkTreeModel* m_model; + std::optional m_iter; +}; + +// Custom container class +class GtkTreeModelContainer +{ +public: + using iterator = GtkTreeModelIterator; + GtkTreeModelContainer(GtkTreeModel* model) : m_model(model) {} + iterator begin() + { + GtkTreeIter iter; + gtk_tree_model_get_iter_first(m_model, &iter); + return iterator(m_model, iter); + } + iterator end() { return iterator(m_model, std::nullopt); } private: GtkTreeModel* m_model; - bool m_value; - GtkTreeIter m_iter; }; void @@ -230,7 +274,7 @@ gnc_gen_trans_list_delete (GNCImportMainMatcher *info) return; if (info->transaction_processed_cb) - for (auto iter = TreeViewIter(info->view); iter.has_value(); iter.next()) + for (auto iter : GtkTreeModelContainer(gtk_tree_view_get_model (info->view))) info->transaction_processed_cb (iter.get_trans_info(), false, info->user_data); if (GTK_IS_DIALOG(info->main_widget)) @@ -281,7 +325,7 @@ gnc_gen_trans_list_show_accounts_column (GNCImportMainMatcher *info) std::string first_acct_name; bool multiple_accounts = false; - for (auto iter = TreeViewIter (info->view); iter.has_value(); iter.next()) + for (auto iter : GtkTreeModelContainer(gtk_tree_view_get_model (info->view))) { auto acct_name = iter.get_account_name (); if (acct_name.empty()) @@ -434,7 +478,6 @@ resolve_conflicts (GNCImportMainMatcher *info) g_list_free (conflicts); } - for (auto iter = TreeViewIter(info->view); iter.has_value(); iter.next()) // Refresh all valid = gtk_tree_model_get_iter_first (model, &import_iter); while (valid) @@ -449,7 +492,7 @@ static void load_hash_tables (GNCImportMainMatcher *info) { GList *accounts_list = NULL; - for (auto iter = TreeViewIter(info->view); iter.has_value(); iter.next()) + for (auto iter : GtkTreeModelContainer(gtk_tree_view_get_model (info->view))) { auto trans_info = iter.get_trans_info (); Split *s = gnc_import_TransInfo_get_fsplit (trans_info); @@ -522,8 +565,8 @@ on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info) /* DEBUG ("Begin") */ - TreeViewIter iter{info->view}; - if (!iter.has_value()) + GtkTreeModelContainer container(gtk_tree_view_get_model (info->view)); + if (container.begin() == container.end()) { // No transaction, we can just close the dialog. gnc_gen_trans_list_delete (info); @@ -536,7 +579,7 @@ on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info) bool first_tran = true; bool append_text = gtk_toggle_button_get_active ((GtkToggleButton*) info->append_text); GList *accounts_modified = NULL; - for (; iter.has_value(); iter.next()) + for (auto iter : container) { auto trans_info{iter.get_trans_info()}; Split* first_split = gnc_import_TransInfo_get_fsplit (trans_info);