diff --git a/gnucash/gnome/dialog-imap-editor.c b/gnucash/gnome/dialog-imap-editor.c index d88b31886b..76a7f351ab 100644 --- a/gnucash/gnome/dialog-imap-editor.c +++ b/gnucash/gnome/dialog-imap-editor.c @@ -31,6 +31,7 @@ #include "gnc-component-manager.h" #include "gnc-session.h" +#include "gnc-ui.h" #include "gnc-ui-util.h" #include "Account.h" @@ -72,9 +73,13 @@ typedef struct GtkWidget *filter_label; gboolean apply_selection_filter; + GtkWidget *total_entries_label; + gint tot_entries; + gint tot_invalid_maps; GtkWidget *expand_button; GtkWidget *collapse_button; + GtkWidget *remove_button; }ImapDialog; @@ -146,6 +151,12 @@ delete_selected_row (ImapDialog *imap_dialog, GtkTreeIter *iter) gchar *head; gchar *category; gchar *match_string; + gint num = 0; + GtkTreeIter parent; + + // get the parent iter and see how many children it has, if 1 we will remove + if (gtk_tree_model_iter_parent (imap_dialog->model, &parent, iter)) + num = gtk_tree_model_iter_n_children (imap_dialog->model, &parent); gtk_tree_model_get (imap_dialog->model, iter, SOURCE_ACCOUNT, &source_account, SOURCE_FULL_ACC, &full_source_account, @@ -174,7 +185,15 @@ delete_selected_row (ImapDialog *imap_dialog, GtkTreeIter *iter) if (imap_dialog->type == NBAYES) delete_info_nbayes (source_account, head, category, match_string, depth); + + gtk_tree_store_remove (GTK_TREE_STORE(imap_dialog->model), iter); + + if (num == 1 && (imap_dialog->type != ONLINE)) + gtk_tree_store_remove (GTK_TREE_STORE(imap_dialog->model), &parent); } + // Clear the total + gtk_label_set_text (GTK_LABEL(imap_dialog->total_entries_label), " "); + if (head) g_free (head); if (category) @@ -185,6 +204,30 @@ delete_selected_row (ImapDialog *imap_dialog, GtkTreeIter *iter) g_free (full_source_account); } +static gboolean +find_invalid_mappings_total (GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, ImapDialog *imap_dialog) +{ + Account *source_account = NULL; + Account *map_account = NULL; + gchar *head; + gint depth; + + gtk_tree_model_get (model, iter, SOURCE_ACCOUNT, &source_account, + MAP_ACCOUNT, &map_account, + HEAD, &head, -1); + + depth = gtk_tree_path_get_depth (path); + + if ((source_account != NULL) && (map_account == NULL)) + { + if (((g_strcmp0 (head, "online_id") == 0) && (depth == 1)) || (depth == 2)) + imap_dialog->tot_invalid_maps ++; + } + g_free (head); + return FALSE; +} + static void gnc_imap_dialog_delete (ImapDialog *imap_dialog) { @@ -203,6 +246,9 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog) if (g_list_length (list) == 0) return; + // reset the invalid map total + imap_dialog->tot_invalid_maps = 0; + // reverse list list = g_list_reverse (list); @@ -221,10 +267,115 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog) g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); g_list_free (list); - get_account_info (imap_dialog); + // Enable GUI refresh again + gnc_resume_gui_refresh(); + + // recount the number of invalid maps + gtk_tree_model_foreach (imap_dialog->model, + (GtkTreeModelForeachFunc)find_invalid_mappings_total, + imap_dialog); + + if (imap_dialog->tot_invalid_maps == 0) + gtk_widget_hide (imap_dialog->remove_button); + +} + +static gboolean +find_invalid_mappings (GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, GList **rowref_list) +{ + Account *source_account = NULL; + Account *map_account = NULL; + gchar *head; + gint depth; + + gtk_tree_model_get (model, iter, SOURCE_ACCOUNT, &source_account, + MAP_ACCOUNT, &map_account, + HEAD, &head, -1); + + depth = gtk_tree_path_get_depth (path); + + if ((source_account != NULL) && (map_account == NULL)) + { + if (((g_strcmp0 (head, "online_id") == 0) && (depth == 1)) || (depth == 2)) + { + GtkTreeRowReference *rowref = gtk_tree_row_reference_new (model, path); + *rowref_list = g_list_append (*rowref_list, rowref); + } + } + g_free (head); + return FALSE; +} + +static void +gnc_imap_remove_invalid_maps (ImapDialog *imap_dialog) +{ + GList *rr_list = NULL; + GList *node; + + gtk_tree_model_foreach (imap_dialog->model, + (GtkTreeModelForeachFunc)find_invalid_mappings, + &rr_list); + + // reverse the reference list + rr_list = g_list_reverse (rr_list); + + // Suspend GUI refreshing + gnc_suspend_gui_refresh(); + + // Walk the list + for (node = rr_list; node != NULL; node = node->next) + { + GtkTreePath *path = gtk_tree_row_reference_get_path ((GtkTreeRowReference*)node->data); + + if (path) + { + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL(imap_dialog->model), &iter, path)) + delete_selected_row (imap_dialog, &iter); + + gtk_tree_path_free (path); + } + } // Enable GUI refresh again gnc_resume_gui_refresh(); + + g_list_foreach (rr_list, (GFunc)gtk_tree_row_reference_free, NULL); + g_list_free (rr_list); +} + +static void +gnc_imap_invalid_maps_dialog (ImapDialog *imap_dialog) +{ + gtk_widget_hide (imap_dialog->remove_button); + + if (imap_dialog->tot_invalid_maps > 0) + { + /* Translators: This is a ngettext(3) message, %d is the number of maps missing */ + gchar *message = g_strdup_printf (ngettext ("There is %d invalid mapping,\n\nWould you like to remove it now?", + "There are %d invalid mappings,\n\nWould you like to remove them now?", + imap_dialog->tot_invalid_maps), + imap_dialog->tot_invalid_maps); + + gchar *message2 = g_strdup_printf (gettext ("To see the invalid mappings, use a filter of '%s'"), _("Map Account NOT found")); + + gchar *text = g_strdup_printf ("%s\n\n%s\n\n%s", message, message2, _("(Note, if there is a large number, it may take a while)")); + + if (gnc_verify_dialog (GTK_WINDOW (imap_dialog->dialog), FALSE, "%s", text)) + { + gnc_imap_remove_invalid_maps (imap_dialog); + gtk_widget_hide (imap_dialog->remove_button); + } + else + { + gtk_widget_show (imap_dialog->remove_button); + } + g_free (message); + g_free (message2); + g_free (text); + } } void @@ -238,6 +389,10 @@ gnc_imap_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_ gnc_imap_dialog_delete (imap_dialog); return; + case GTK_RESPONSE_REJECT: + gnc_imap_invalid_maps_dialog (imap_dialog); + return; + case GTK_RESPONSE_CLOSE: default: gnc_close_gui_component_by_data (DIALOG_IMAP_CM_CLASS, imap_dialog); @@ -366,6 +521,7 @@ list_type_selected_cb (GtkToggleButton* button, ImapDialog *imap_dialog) { imap_dialog->type = type; get_account_info (imap_dialog); + gnc_imap_invalid_maps_dialog (imap_dialog); } } @@ -395,10 +551,18 @@ add_to_store (ImapDialog *imap_dialog, GtkTreeIter *iter, const gchar *text, Gnc // Do we have a valid map account if (imapInfo->map_account == NULL) + { + // count the total invalid maps + imap_dialog->tot_invalid_maps ++; + map_fullname = g_strdup (_("Map Account NOT found")); + } else map_fullname = gnc_account_get_full_name (imapInfo->map_account); + // count the total entries + imap_dialog->tot_entries ++; + PINFO("Add to Store: Source Acc '%s', Head is '%s', Category is '%s', Match '%s', Map Acc '%s', Count is %s", fullname, imapInfo->head, imapInfo->category, imapInfo->match_string, map_fullname, imapInfo->count); @@ -581,11 +745,15 @@ get_account_info (ImapDialog *imap_dialog) Account *root; GList *accts; GtkTreeModel *fmodel; + gchar *total; /* Get list of Accounts */ root = gnc_book_get_root_account (gnc_get_current_book()); accts = gnc_account_get_descendants_sorted (root); + imap_dialog->tot_entries = 0; + imap_dialog->tot_invalid_maps = 0; + fmodel = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view)); imap_dialog->model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(fmodel)); @@ -633,6 +801,17 @@ get_account_info (ImapDialog *imap_dialog) // if there are any entries, show first row show_first_row (imap_dialog); + // add the totals + total = g_strdup_printf ("%s %d", _("Total Entries"), imap_dialog->tot_entries); + gtk_label_set_text (GTK_LABEL(imap_dialog->total_entries_label), total); + gtk_widget_show (imap_dialog->total_entries_label); + g_free (total); + + if (imap_dialog->tot_invalid_maps > 0) + gtk_widget_show (imap_dialog->remove_button); + else + gtk_widget_hide (imap_dialog->remove_button); + g_list_free (accts); } @@ -681,8 +860,8 @@ gnc_imap_dialog_create (GtkWidget *parent, ImapDialog *imap_dialog) dialog = GTK_WIDGET(gtk_builder_get_object (builder, "import_map_dialog")); imap_dialog->dialog = dialog; - // Set the style context for this dialog so it can be easily manipulated with css - gnc_widget_set_style_context (GTK_WIDGET(dialog), "GncImapDialog"); + // Set the name for this dialog so it can be easily manipulated with css + gtk_widget_set_name (GTK_WIDGET(dialog), "gnc-id-import-map"); imap_dialog->session = gnc_get_current_session(); imap_dialog->type = BAYES; @@ -700,6 +879,7 @@ gnc_imap_dialog_create (GtkWidget *parent, ImapDialog *imap_dialog) g_signal_connect (imap_dialog->radio_nbayes, "toggled", G_CALLBACK(list_type_selected_cb), (gpointer)imap_dialog); + imap_dialog->total_entries_label = GTK_WIDGET(gtk_builder_get_object (builder, "total_entries_label")); imap_dialog->filter_text_entry = GTK_WIDGET(gtk_builder_get_object (builder, "filter-text-entry")); imap_dialog->filter_label = GTK_WIDGET(gtk_builder_get_object (builder, "filter-label")); imap_dialog->filter_button = GTK_WIDGET(gtk_builder_get_object (builder, "filter-button")); @@ -716,6 +896,8 @@ gnc_imap_dialog_create (GtkWidget *parent, ImapDialog *imap_dialog) imap_dialog->view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview")); + imap_dialog->remove_button = GTK_WIDGET(gtk_builder_get_object (builder, "remove_button")); + // Set filter column filter = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view)); gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER(filter), FILTER); @@ -810,5 +992,7 @@ gnc_imap_dialog (GtkWidget *parent) gnc_gui_component_set_session (component_id, imap_dialog->session); gtk_widget_show (imap_dialog->dialog); + gtk_widget_hide (imap_dialog->remove_button); + gnc_imap_invalid_maps_dialog (imap_dialog); LEAVE(" "); } diff --git a/gnucash/gtkbuilder/dialog-imap-editor.glade b/gnucash/gtkbuilder/dialog-imap-editor.glade index e4fd3dba93..c1e61c8cc7 100644 --- a/gnucash/gtkbuilder/dialog-imap-editor.glade +++ b/gnucash/gtkbuilder/dialog-imap-editor.glade @@ -50,6 +50,20 @@ False end + + + _Remove Invalid Mappings + True + True + True + True + + + True + True + 0 + + _Delete @@ -61,7 +75,7 @@ False False - 0 + 1 @@ -77,7 +91,7 @@ False False - 1 + 2 @@ -85,7 +99,7 @@ False False end - 0 + 3 @@ -98,7 +112,7 @@ False False - 1 + 0 @@ -161,7 +175,7 @@ False False - 2 + 1 @@ -251,6 +265,22 @@ True True + 2 + + + + + True + False + start + 6 + 6 + 3 + 3 + + + False + True 3 @@ -261,6 +291,9 @@ 5 5 Filter will be applied to 'Match String' and 'Mapped to Account Name' fields, case sensitive. + False @@ -327,7 +360,7 @@ - _Collapse All + Collapse _All True True True @@ -374,6 +407,7 @@ + remove_button delete_button close_button