diff --git a/common/debug/valgrind/valgrind-compiz.supp b/common/debug/valgrind/valgrind-compiz.supp new file mode 100644 index 0000000000..4e524e6ca5 --- /dev/null +++ b/common/debug/valgrind/valgrind-compiz.supp @@ -0,0 +1,919 @@ +# -*- tab-width: 3; indent-tabs-mode: nil -*- +# +# GNOME supressions base.supp: +# git://github.com/dtrebbien/GNOME.supp.git +# Copyright (C) 2012 Daniel Trebbien +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Python supressions valgrind-python.supp: +# http://hg.python.org/cpython +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Python Software Foundation; All Rights Reserved +# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +# -------------------------------------------- +# +# 1. This LICENSE AGREEMENT is between the Python Software Foundation +# ("PSF"), and the Individual or Organization ("Licensee") accessing and +# otherwise using this software ("Python") in source or binary form and +# its associated documentation. + +# 2. Subject to the terms and conditions of this License Agreement, PSF hereby +# grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +# analyze, test, perform and/or display publicly, prepare derivative works, +# distribute, and otherwise use Python alone or in any derivative version, +# provided, however, that PSF's License Agreement and PSF's notice of copyright, +# i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Python Software Foundation; All Rights Reserved" are retained in Python +# alone or in any derivative version prepared by Licensee. + +# 3. In the event Licensee prepares a derivative work that is based on +# or incorporates Python or any part thereof, and wants to make +# the derivative work available to others as provided herein, then +# Licensee hereby agrees to include in any such work a brief summary of +# the changes made to Python. + +# 4. PSF is making Python available to Licensee on an "AS IS" +# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +# INFRINGE ANY THIRD PARTY RIGHTS. +# +# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +# FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. +# +# 6. This License Agreement will automatically terminate upon a material +# breach of its terms and conditions. + +# 7. Nothing in this License Agreement shall be deemed to create any +# relationship of agency, partnership, or joint venture between PSF and +# Licensee. This License Agreement does not grant permission to use PSF +# trademarks or trade name in a trademark sense to endorse or promote +# products or services of Licensee, or any third party. +# +# 8. By copying, installing or otherwise using Python, Licensee +# agrees to be bound by the terms and conditions of this License +# Agreement. +# +# All other supressions: +# +# Copyright © 2012 Canonical Ltd. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without +# fee, provided that the above copyright notice appear in all copies +# and that both that copyright notice and this permission notice +# appear in supporting documentation, and that the name of +# Canonical Ltd. not be used in advertising or publicity pertaining to +# distribution of the software without specific, written prior permission. +# Canonical Ltd. makes no representations about the suitability of this +# software for any purpose. It is provided "as is" without express or +# implied warranty. +# +# CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Authored by: Sam Spilsbury +# / + +{ + xmlReadFile leaks a string + Memcheck:Leak + fun:malloc + fun:xmlStrndup + ... + fun:xmlReadFile +} + +{ + xmlReadFile leaks an xmlNewCharEncodingHandler + Memcheck:Leak + fun:malloc + fun:xmlNewCharEncodingHandler + ... + fun:xmlReadFile +} + +{ + xmInitCharEncodingHandlers leaks + Memcheck:Leak + fun:*alloc* + fun:xmlInitCharEncodingHandlers +} + +{ + xmlReadFile leaks an xmlNewRMutex + Memcheck:Leak + fun:malloc + fun:xmlNewRMutex + ... + fun:xmlReadFile +} + +{ + xmlParseDocument leaks an xmlNewMutex + Memcheck:Leak + fun:malloc + fun:xmlNewMutex + ... + fun:xmlParseDocument +} + +{ + dlopen leaks some tokens + Memcheck:Leak + fun:*alloc* + ... + fun:dlopen* +} + +{ + dlclose calls malloc and leaks + Memcheck:Leak + fun:*alloc* + ... + fun:dlclose* +} + +{ + import_submodule + Memcheck:Leak + fun:*alloc* + ... + fun:import_*module* +} + +{ + everything from PyInitialize_Ex + Memcheck:Leak + fun:*alloc* + ... + fun:Py_InitializeEx* +} + +{ + everything from PySys* + Memcheck:Leak + fun:*alloc* + ... + fun:PySys* +} + +{ + everything from PyList + Memcheck:Leak + fun:*alloc* + ... + fun:PyList_* +} + +{ + everything from PyThread + Memcheck:Leak + fun:*alloc* + ... + fun:PyThread* +} + +{ + everything from PyStructSequence + Memcheck:Leak + fun:*alloc* + ... + fun:PyStructSequence* +} + + + +{ + don't care about protobuf + Memcheck:Leak + ... + fun:_ZN6google8protobuf24SimpleDescriptorDatabase15DescriptorIndexISt4pairIPKviEE7AddFileERKNS0_19FileDescriptorProtoES6_ +} + +{ + google::protobuf::protobufAddDesc + Memcheck:Leak + ... + fun:*protobuf*AddDesc* +} + +{ + don't care about protobuf + Memcheck:Leak + ... + fun:_ZN6google8protobuf8internal10OnShutdownEPFvvE +} + +{ + g_types are never free'd + Memcheck:Leak + ... + fun:g_type* +} + +{ + g_settings_class_init intentionally leaks signals + Memcheck:Leak + fun:*alloc + ... + fun:g_signal_new + ... + fun:g_type_class_ref + ... + fun:g_object_new +} + +{ + g_list_append calls g_slice_alloc can call g_private_get which seems to leave reachable blocks + Memcheck:Leak + fun:malloc + ... + fun:g_private_get + fun:g_slice_alloc + fun:g_list_append +} + +{ + g_list_append calls g_mutex_lock which calls malloc + Memcheck:Leak + fun:malloc + ... + fun:g_mutex* + ... + fun:g_slice_alloc + fun:g_list_append +} + +# not entirely certain about this + +{ + g_list_append calls thread_memory_from_self, but we can't detect it + Memcheck:Leak + fun:calloc + ... + fun:g_slice_alloc + fun:g_list_append +} + +{ + g_variant_builder_end calls g_rec_mutex_lock + Memcheck:Leak + fun:malloc + ... + fun:g_slice_alloc + ... + fun:g_rec_mutex_lock + fun:g_variant_type_info_get + ... + fun:g_variant_builder_end +} + +{ + + Memcheck:Cond + fun:__GI___strcasecmp_l +} + +{ + + Memcheck:Value8 + fun:__GI___strcasecmp_l +} + +{ + + Memcheck:Addr8 + fun:__strspn_sse42 +} + +{ + + Memcheck:Cond + fun:__strspn_sse42 +} + +{ + + Memcheck:Addr4 + fun:FcConfigFileExists +} + + +{ + g_hash_table_insert_node() in ghash.c + Memcheck:Leak + ... + fun:g_memdup + fun:g_hash_table_insert_node +} + +{ + g_hash_table_resize() in ghash.c + Memcheck:Leak + ... + fun:g_hash_table_resize +} + + +{ + + Memcheck:Leak + ... + fun:g_get_application_name +} + +{ + + Memcheck:Leak + ... + fun:g_get_home_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_host_name +} + +{ + + Memcheck:Leak + ... + fun:g_get_prgname +} + +{ + + Memcheck:Leak + ... + fun:g_get_real_name +} + +{ + + Memcheck:Leak + ... + fun:g_get_system_config_dirs +} + +{ + + Memcheck:Leak + ... + fun:g_get_system_data_dirs +} + +{ + + Memcheck:Leak + ... + fun:g_get_tmp_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_cache_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_config_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_data_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_name +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_runtime_dir +} + +{ + + Memcheck:Leak + ... + fun:g_get_user_special_dir +} + +{ + + Memcheck:Leak + ... + fun:g_reload_user_special_dirs_cache +} + +{ + + Memcheck:Leak + ... + fun:g_set_application_name +} + +{ + + Memcheck:Leak + ... + fun:g_set_prgname +} + + +{ + + Memcheck:Leak + ... + fun:g_random_double +} + +{ + + Memcheck:Leak + ... + fun:g_random_double_range +} + +{ + + Memcheck:Leak + ... + fun:g_random_int +} + +{ + + Memcheck:Leak + ... + fun:g_random_int_range +} + +{ + + Memcheck:Leak + ... + fun:g_random_set_seed +} + + +{ + + Memcheck:Leak + ... + fun:g_bus_get + fun:g_bus_own_name +} + +{ + + Memcheck:Leak + ... + fun:g_hash_table_new + fun:g_bus_own_name +} + +{ + + Memcheck:Leak + ... + fun:g_main_context_ref_thread_default + fun:g_bus_own_name +} + +{ + + Memcheck:Leak + ... + fun:g_hash_table_new + fun:g_bus_own_name_on_connection +} + +{ + + Memcheck:Leak + ... + fun:g_variant_new + fun:g_bus_unown_name +} + +{ + _g_dbus_initialize() in gio/gdbusprivate.c + Memcheck:Leak + ... + fun:_g_dbus_initialize +} + +{ + + Memcheck:Leak + ... + fun:FcConfigSubstitute* + fun:pango_cairo_fc_font_map_fontset_key_substitute +} + +{ + _gtk_accessibility_init() in gail.c + Memcheck:Leak + ... + fun:atk_add_focus_tracker + fun:_gtk_accessibility_init +} + + +{ + + Memcheck:Leak + ... + fun:gdk_display_manager_get +} + +{ + + Memcheck:Leak + ... + fun:gdk_display_manager_get_default_display +} + + +{ + + Memcheck:Leak + ... + fun:gdk_display_get_default +} + + +{ + + Memcheck:Leak + ... + fun:gtk_clipboard_get_for_display +} + +{ + + Memcheck:Leak + ... + fun:gtk_clipboard_request_contents +} + +{ + gtk_im_module_initialize() in gtkimmodule.c + Memcheck:Leak + ... + fun:gtk_im_module_initialize +} + + +{ + + Memcheck:Leak + ... + fun:gtk_widget_get_style_context +} + +{ + g_main_context_default calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_main_context_new + fun:g_main_context_default +} + +{ + g_main_context_default calls g_mutex_lock + Memcheck:Leak + fun:*alloc* + ... + fun:g_mutex_lock + ... + fun:g_main_context_default +} + +{ + g_main_context_default calls g_cond_broadcast + Memcheck:Leak + fun:*alloc* + ... + fun:g_cond_broadcast + ... + fun:g_main_context_default +} + +{ + g_main_context_default calls g_slist_prepend + Memcheck:Leak + fun:*alloc* + ... + fun:g_slist_prepend + ... + fun:g_main_context_default +} + +{ + g_get_worker_context calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_main_context_new + fun:g_get_worker_context +} + +{ + g_get_worker_context calls g_thread_new + Memcheck:Leak + fun:*alloc* + ... + fun:g_thread_new + fun:g_get_worker_context +} + +{ + g_get_worker_context calls g_mutex_lock + Memcheck:Leak + fun:*alloc* + ... + fun:g_mutex_lock + ... + fun:g_get_worker_context +} + +{ + g_main_context_iterate calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_main_context_iterate* +} + +{ + g_main_loop_run calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_main_loop_run* +} + +{ + g_thread_proxy calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_thread_proxy +} + +{ + g_unix_signal_add_full calls g_mutex_lock which calls malloc + Memcheck:Leak + fun:*alloc* + ... + fun:g_mutex_lock + ... + fun:g_unix_signal_add_full +} + +{ + + Memcheck:Leak + ... + fun:gtk_source_style_scheme_manager_get_default +} + + +{ + + Memcheck:Leak + ... + fun:gtk_source_style_scheme_get_style +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64) + Memcheck:Value8 + fun:Py_ADDRESS_IN_RANGE +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:Py_ADDRESS_IN_RANGE +} + +{ + Suppress leaking the GIL. Happens once per process, see comment in ceval.c. + Memcheck:Leak + fun:malloc + fun:PyThread_allocate_lock + fun:PyEval_InitThreads +} + +{ + Suppress leaking the GIL after a fork. + Memcheck:Leak + fun:malloc + fun:PyThread_allocate_lock + fun:PyEval_ReInitThreads +} + +{ + Suppress leaking the autoTLSkey. This looks like it shouldn't leak though. + Memcheck:Leak + fun:malloc + fun:PyThread_create_key + fun:_PyGILState_Init + fun:Py_InitializeEx + fun:Py_Main +} + +{ + Hmmm, is this a real leak or like the GIL? + Memcheck:Leak + fun:malloc + fun:PyThread_ReInitTLS +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:realloc + fun:_PyObject_GC_Resize +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_New +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:*PyObject*Malloc* +} + +{ + Handle PyMalloc confusing valgrind (possibly leaked) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_NewVar +} + +{ + Dictresize confuses valgrind too + Memcheck:Leak + ... + fun:dictresize* +} + +{ + PyString can confuse it too + Memcheck:Leak + ... + fun:PyString* +} + +# +# Non-python specific leaks +# + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + Handle pthread issue (possibly leaked) + Memcheck:Leak + fun:memalign + fun:_dl_allocate_tls_storage + fun:_dl_allocate_tls +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Addr8 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Value8 + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:PyObject_Free +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Addr4 + fun:PyObject_Realloc* +} + +{ + ADDRESS_IN_RANGE/Invalid read of size 4 + Memcheck:Value4 + fun:PyObject_Realloc* +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Addr8 + fun:PyObject_Realloc* +} + +{ + ADDRESS_IN_RANGE/Use of uninitialised value of size 8 + Memcheck:Value8 + fun:PyObject_Realloc* +} + +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun:PyObject_Realloc* +} + +# Additional suppressions for the unified decimal tests: +{ + test_decimal + Memcheck:Addr4 + fun:PyUnicodeUCS2_FSConverter +} + +{ + test_decimal2 + Memcheck:Addr4 + fun:PyUnicode_FSConverter +} diff --git a/gnucash/gtkbuilder/dialog-import.glade b/gnucash/gtkbuilder/dialog-import.glade index 8a457f18cd..5843d186bc 100644 --- a/gnucash/gtkbuilder/dialog-import.glade +++ b/gnucash/gtkbuilder/dialog-import.glade @@ -1153,7 +1153,7 @@ True False - List of downloaded transactions (source split shown) + List of downloaded transactions (source split and matched information shown) center @@ -1190,18 +1190,46 @@ - - Show the Source Account column + True - True - False + False center - True + + + Show the _Account column + True + True + False + center + True + True + + + False + True + 0 + + + + + Show _matched information + True + True + False + True + True + + + False + True + 1 + + False True - 3 + 2 diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c index b42c497d79..dfb63ae648 100644 --- a/gnucash/import-export/import-main-matcher.c +++ b/gnucash/import-export/import-main-matcher.c @@ -66,6 +66,8 @@ struct _main_matcher_info gpointer user_data; GNCImportPendingMatches *pending_matches; GtkTreeViewColumn *account_column; + GtkWidget *show_account_column; + GtkWidget *show_matched_info; gboolean add_toggled; // flag to indicate that add has been toggled to stop selection }; @@ -85,6 +87,7 @@ enum downloaded_cols DOWNLOADED_COL_ACTION_PIXBUF, DOWNLOADED_COL_DATA, DOWNLOADED_COL_COLOR, + DOWNLOADED_COL_ENABLE, NUM_DOWNLOADED_COLS }; @@ -433,6 +436,11 @@ gnc_gen_trans_assign_transfer_account (GtkTreeView *treeview, DEBUG("path = %s", path_str); g_free (path_str); DEBUG("account passed in = %s", gnc_get_account_name_for_register (*new_acc)); + + // only allow response at the top level + if (gtk_tree_path_get_depth (path) != 1) + return; + model = gtk_tree_view_get_model (treeview); if (gtk_tree_model_get_iter (model, &iter, path)) { @@ -713,6 +721,8 @@ add_toggle_column (GtkTreeView *view, const gchar *title, int col_num, (title, renderer, "active", col_num, "cell-background", DOWNLOADED_COL_COLOR, + "activatable", DOWNLOADED_COL_ENABLE, + "visible", DOWNLOADED_COL_ENABLE, NULL); gtk_tree_view_column_set_sort_column_id (column, col_num); g_object_set (G_OBJECT(column), @@ -729,17 +739,18 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info, gboolean show_update) { GtkTreeView *view; - GtkListStore *store; + GtkTreeStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; view = info->view; - store = gtk_list_store_new (NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64, + store = gtk_tree_store_new (NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING, - GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING); + GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_STRING, + G_TYPE_BOOLEAN); gtk_tree_view_set_model (view, GTK_TREE_MODEL(store)); g_object_unref (store); @@ -831,6 +842,11 @@ view_selection_function (GtkTreeSelection *selection, GNCImportMainMatcher *info = data; ENTER("view_selection_function"); + + // only allow response at the top level + if (gtk_tree_path_get_depth (path) != 1) + return FALSE; + if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_tree_model_get (model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1); @@ -890,7 +906,24 @@ show_account_column_toggled_cb (GtkToggleButton *togglebutton, GNCImportMainMatcher *info) { gtk_tree_view_column_set_visible (info->account_column, - gtk_toggle_button_get_active (togglebutton)); + gtk_toggle_button_get_active (togglebutton)); +} + +static void +show_matched_info_toggled_cb (GtkToggleButton *togglebutton, + GNCImportMainMatcher *info) +{ + if (gtk_toggle_button_get_active (togglebutton)) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), TRUE); + gtk_tree_view_expand_all (info->view); + } + else + { + gtk_tree_view_column_set_visible (info->account_column, + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->show_account_column))); + gtk_tree_view_collapse_all (info->view); + } } GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent, @@ -905,7 +938,6 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent, gboolean show_update; GtkStyleContext *stylectxt; GdkRGBA color; - GtkWidget *button; info = g_new0 (GNCImportMainMatcher, 1); info->pending_matches = gnc_import_PendingMatches_new(); @@ -934,11 +966,15 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent, info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view")); g_assert (info->view != NULL); - button = GTK_WIDGET(gtk_builder_get_object (builder, "show_source_account_button")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), all_from_same_account); - g_signal_connect (G_OBJECT(button), "toggled", + info->show_account_column = GTK_WIDGET(gtk_builder_get_object (builder, "show_source_account_button")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), all_from_same_account); + g_signal_connect (G_OBJECT(info->show_account_column), "toggled", G_CALLBACK(show_account_column_toggled_cb), info); + info->show_matched_info = GTK_WIDGET(gtk_builder_get_object (builder, "show_matched_info_button")); + g_signal_connect (G_OBJECT(info->show_matched_info), "toggled", + G_CALLBACK(show_matched_info_toggled_cb), info); + show_update = gnc_import_Settings_get_action_update_enabled (info->user_settings); gnc_gen_trans_init_view (info, all_from_same_account, show_update); heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label")); @@ -978,7 +1014,6 @@ GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent, gboolean show_update; GtkStyleContext *stylectxt; GdkRGBA color; - GtkWidget *button; info = g_new0 (GNCImportMainMatcher, 1); info->pending_matches = gnc_import_PendingMatches_new(); @@ -1007,11 +1042,15 @@ GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent, info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view")); g_assert (info->view != NULL); - button = GTK_WIDGET(gtk_builder_get_object (builder, "show_source_account_button")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), all_from_same_account); - g_signal_connect (G_OBJECT(button), "toggled", + info->show_account_column = GTK_WIDGET(gtk_builder_get_object (builder, "show_source_account_button")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->show_account_column), all_from_same_account); + g_signal_connect (G_OBJECT(info->show_account_column), "toggled", G_CALLBACK(show_account_column_toggled_cb), info); + info->show_matched_info = GTK_WIDGET(gtk_builder_get_object (builder, "show_matched_info_button")); + g_signal_connect (G_OBJECT(info->show_matched_info), "toggled", + G_CALLBACK(show_matched_info_toggled_cb), info); + show_update = gnc_import_Settings_get_action_update_enabled (info->user_settings); gnc_gen_trans_init_view (info, all_from_same_account, show_update); heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label")); @@ -1072,13 +1111,61 @@ get_required_color (const gchar *class_name) return gdk_rgba_to_string (&color); } +static void +remove_child_row (GtkTreeModel *model, GtkTreeIter *iter) +{ + if (gtk_tree_model_iter_has_child (model, iter)) + { + GtkTreeIter child; + gtk_tree_model_iter_nth_child (model, &child, iter, 0); + gtk_tree_store_remove (GTK_TREE_STORE(model), &child); + } +} + +static void +update_child_row (GNCImportMatchInfo *sel_match, GtkTreeModel *model, GtkTreeIter *iter) +{ + GtkTreeStore *store; + GtkTreeIter child; + gchar *text = qof_print_date (xaccTransGetDate (sel_match->trans)); + const gchar *ro_text; + + const gchar *desc = xaccTransGetDescription (sel_match->trans); + const gchar *memo = xaccSplitGetMemo (sel_match->split); + + store = GTK_TREE_STORE(model); + + if (!gtk_tree_model_iter_has_child (model, iter)) + gtk_tree_store_append (GTK_TREE_STORE(model), &child, iter); + else + gtk_tree_model_iter_nth_child (model, &child, iter, 0); + + gtk_tree_store_set (store, &child, DOWNLOADED_COL_DATE_TXT, text, -1); + + if (xaccTransCountSplits(sel_match->trans) == 2) + gtk_tree_store_set (store, &child, DOWNLOADED_COL_ACCOUNT, xaccAccountGetName ( + xaccSplitGetAccount (xaccSplitGetOtherSplit (sel_match->split))), -1); + else + gtk_tree_store_set (store, &child, DOWNLOADED_COL_ACCOUNT, _("-- Split Transaction --"), -1); + + ro_text = xaccPrintAmount (xaccSplitGetAmount (sel_match->split), + gnc_split_amount_print_info (sel_match->split, TRUE)); + + gtk_tree_store_set (store, &child, DOWNLOADED_COL_AMOUNT, ro_text, -1); + gtk_tree_store_set (store, &child, DOWNLOADED_COL_MEMO, memo, -1); + gtk_tree_store_set (store, &child, DOWNLOADED_COL_DESCRIPTION, desc, -1); + + gtk_tree_store_set (store, &child, DOWNLOADED_COL_ENABLE, FALSE, -1); + g_free (text); +} + static void refresh_model_row (GNCImportMainMatcher *gui, GtkTreeModel *model, GtkTreeIter *iter, GNCImportTransInfo *info) { - GtkListStore *store; + GtkTreeStore *store; GtkTreeSelection *selection; gchar *tmp, *imbalance, *text, *color; const gchar *ro_text; @@ -1092,8 +1179,8 @@ refresh_model_row (GNCImportMainMatcher *gui, g_assert (info); /*DEBUG("Begin");*/ - store = GTK_LIST_STORE(model); - gtk_list_store_set (store, iter, DOWNLOADED_COL_DATA, info, -1); + store = GTK_TREE_STORE(model); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATA, info, -1); if (gui->dark_theme == TRUE) class_extension = "-dark"; @@ -1102,32 +1189,35 @@ refresh_model_row (GNCImportMainMatcher *gui, int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL); int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL); + /* This controls the visibility of the toggle cells */ + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ENABLE, TRUE, -1); + /*Account:*/ split = gnc_import_TransInfo_get_fsplit (info); g_assert (split); // Must not be NULL ro_text = xaccAccountGetName (xaccSplitGetAccount (split)); - gtk_list_store_set (store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1); /*Date*/ date = xaccTransGetDate (gnc_import_TransInfo_get_trans (info)); text = qof_print_date (date); - gtk_list_store_set (store, iter, DOWNLOADED_COL_DATE_TXT, text, -1); - gtk_list_store_set (store, iter, DOWNLOADED_COL_DATE_INT64, date, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_TXT, text, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_DATE_INT64, date, -1); g_free(text); /*Amount*/ amount = xaccSplitGetAmount (split); ro_text = xaccPrintAmount (amount, gnc_split_amount_print_info (split, TRUE)); - gtk_list_store_set (store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1); - gtk_list_store_set (store, iter, DOWNLOADED_COL_AMOUNT_DOUBLE, gnc_numeric_to_double (amount), -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_AMOUNT_DOUBLE, gnc_numeric_to_double (amount), -1); /*Description*/ ro_text = xaccTransGetDescription (gnc_import_TransInfo_get_trans (info) ); - gtk_list_store_set (store, iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1); /*Memo*/ ro_text = xaccSplitGetMemo (split); - gtk_list_store_set (store, iter, DOWNLOADED_COL_MEMO, ro_text, -1); + gtk_tree_store_set (store, iter, DOWNLOADED_COL_MEMO, ro_text, -1); /*Actions*/ @@ -1186,50 +1276,65 @@ refresh_model_row (GNCImportMainMatcher *gui, g_strdup_printf (_("New, UNBALANCED (need acct to transfer %s)!"), imbalance); } + remove_child_row (model, iter); + g_free (imbalance); } break; case GNCImport_CLEAR: - if (gnc_import_TransInfo_get_selected_match (info)) { - color = get_required_color (int_not_required_class); - if (gnc_import_TransInfo_get_match_selected_manually (info) == TRUE) + GNCImportMatchInfo *sel_match = gnc_import_TransInfo_get_selected_match (info); + + if (sel_match) { - ro_text = _("Reconcile (manual) match"); + color = get_required_color (int_not_required_class); + if (gnc_import_TransInfo_get_match_selected_manually (info)) + { + ro_text = _("Reconcile (manual) match"); + } + else + { + ro_text = _("Reconcile (auto) match"); + } + update_child_row (sel_match, model, iter); } else { - ro_text = _("Reconcile (auto) match"); + color = get_required_color (int_required_class); + ro_text = _("Match missing!"); + remove_child_row (model, iter); } } - else - { - color = get_required_color (int_required_class); - ro_text = _("Match missing!"); - } break; case GNCImport_UPDATE: - if (gnc_import_TransInfo_get_selected_match (info)) { - color = get_required_color (int_not_required_class); - if (gnc_import_TransInfo_get_match_selected_manually (info) == TRUE) + GNCImportMatchInfo *sel_match = gnc_import_TransInfo_get_selected_match (info); + + if (sel_match) { - ro_text = _("Update and reconcile (manual) match"); + color = get_required_color (int_not_required_class); + if (gnc_import_TransInfo_get_match_selected_manually (info)) + { + ro_text = _("Update and reconcile (manual) match"); + } + else + { + ro_text = _("Update and reconcile (auto) match"); + } + update_child_row (sel_match, model, iter); } else { - ro_text = _("Update and reconcile (auto) match"); + color = get_required_color (int_required_class); + ro_text = _("Match missing!"); + remove_child_row (model, iter); } } - else - { - color = get_required_color (int_required_class); - ro_text = _("Match missing!"); - } break; case GNCImport_SKIP: color = get_required_color (int_required_class); ro_text = _("Do not import (no action selected)"); + remove_child_row (model, iter); break; default: color = "white"; @@ -1237,7 +1342,7 @@ refresh_model_row (GNCImportMainMatcher *gui, break; } - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_COLOR, color, DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text, -1); @@ -1249,14 +1354,14 @@ refresh_model_row (GNCImportMainMatcher *gui, g_free (int_not_required_class); /* Set the pixmaps */ - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_ADD, gnc_import_TransInfo_get_action (info) == GNCImport_ADD, -1); if (gnc_import_TransInfo_get_action (info) == GNCImport_SKIP) { /*Show the best match's confidence pixmap in the info column*/ - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, gen_probability_pixbuf (gnc_import_MatchInfo_get_probability (gnc_import_TransInfo_get_selected_match (info)), @@ -1265,14 +1370,14 @@ refresh_model_row (GNCImportMainMatcher *gui, -1); } - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_CLEAR, gnc_import_TransInfo_get_action (info) == GNCImport_CLEAR, -1); if (gnc_import_TransInfo_get_action (info) == GNCImport_CLEAR) { /*Show the best match's confidence pixmap in the info column*/ - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, gen_probability_pixbuf (gnc_import_MatchInfo_get_probability (gnc_import_TransInfo_get_selected_match (info)), @@ -1281,14 +1386,14 @@ refresh_model_row (GNCImportMainMatcher *gui, -1); } - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_UPDATE, gnc_import_TransInfo_get_action (info) == GNCImport_UPDATE, -1); if (gnc_import_TransInfo_get_action (info) == GNCImport_UPDATE) { /*Show the best match's confidence pixmap in the info column*/ - gtk_list_store_set (store, iter, + gtk_tree_store_set (store, iter, DOWNLOADED_COL_ACTION_PIXBUF, gen_probability_pixbuf (gnc_import_MatchInfo_get_probability (gnc_import_TransInfo_get_selected_match (info)), @@ -1297,6 +1402,19 @@ refresh_model_row (GNCImportMainMatcher *gui, -1); } + // show child row if 'show matched info' is toggled + if (gtk_tree_model_iter_has_child (model, iter)) + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(gui->show_matched_info))) + { + GtkTreePath *path = gtk_tree_model_get_path (model, iter); + + gtk_tree_view_column_set_visible (gui->account_column, TRUE); + + gtk_tree_view_expand_row (GTK_TREE_VIEW(gui->view), path, TRUE); + gtk_tree_path_free (path); + } + } selection = gtk_tree_view_get_selection (gui->view); gtk_tree_selection_unselect_all (selection); } @@ -1339,7 +1457,7 @@ void gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transa match_selected_manually); model = gtk_tree_view_get_model (gui->view); - gtk_list_store_append (GTK_LIST_STORE(model), &iter); + gtk_tree_store_append (GTK_TREE_STORE(model), &iter, NULL); refresh_model_row (gui, model, &iter, transaction_info); } return;