Bug 797612 - Add a dialog to the imap_dialog to show invalid maps

When imap_dialog is opened, check the tot_invalid_maps value to see if
there were any invalid maps and present a dialog to allow the user to
remove them now, if not add a button to imap_dialog so it can be done
later.
This commit is contained in:
Robert Fewell 2020-03-01 11:59:04 +00:00
parent 3556182ab5
commit 9fed4b464f
2 changed files with 227 additions and 9 deletions

View File

@ -31,6 +31,7 @@
#include "gnc-component-manager.h" #include "gnc-component-manager.h"
#include "gnc-session.h" #include "gnc-session.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h" #include "gnc-ui-util.h"
#include "Account.h" #include "Account.h"
@ -72,9 +73,13 @@ typedef struct
GtkWidget *filter_label; GtkWidget *filter_label;
gboolean apply_selection_filter; gboolean apply_selection_filter;
GtkWidget *total_entries_label;
gint tot_entries;
gint tot_invalid_maps;
GtkWidget *expand_button; GtkWidget *expand_button;
GtkWidget *collapse_button; GtkWidget *collapse_button;
GtkWidget *remove_button;
}ImapDialog; }ImapDialog;
@ -146,6 +151,12 @@ delete_selected_row (ImapDialog *imap_dialog, GtkTreeIter *iter)
gchar *head; gchar *head;
gchar *category; gchar *category;
gchar *match_string; 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, gtk_tree_model_get (imap_dialog->model, iter, SOURCE_ACCOUNT, &source_account,
SOURCE_FULL_ACC, &full_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) if (imap_dialog->type == NBAYES)
delete_info_nbayes (source_account, head, category, match_string, depth); 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) if (head)
g_free (head); g_free (head);
if (category) if (category)
@ -185,6 +204,30 @@ delete_selected_row (ImapDialog *imap_dialog, GtkTreeIter *iter)
g_free (full_source_account); 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 static void
gnc_imap_dialog_delete (ImapDialog *imap_dialog) gnc_imap_dialog_delete (ImapDialog *imap_dialog)
{ {
@ -203,6 +246,9 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog)
if (g_list_length (list) == 0) if (g_list_length (list) == 0)
return; return;
// reset the invalid map total
imap_dialog->tot_invalid_maps = 0;
// reverse list // reverse list
list = g_list_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_foreach (list, (GFunc) gtk_tree_path_free, NULL);
g_list_free (list); 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 // Enable GUI refresh again
gnc_resume_gui_refresh(); 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 void
@ -238,6 +389,10 @@ gnc_imap_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_
gnc_imap_dialog_delete (imap_dialog); gnc_imap_dialog_delete (imap_dialog);
return; return;
case GTK_RESPONSE_REJECT:
gnc_imap_invalid_maps_dialog (imap_dialog);
return;
case GTK_RESPONSE_CLOSE: case GTK_RESPONSE_CLOSE:
default: default:
gnc_close_gui_component_by_data (DIALOG_IMAP_CM_CLASS, imap_dialog); 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; imap_dialog->type = type;
get_account_info (imap_dialog); 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 // Do we have a valid map account
if (imapInfo->map_account == NULL) if (imapInfo->map_account == NULL)
{
// count the total invalid maps
imap_dialog->tot_invalid_maps ++;
map_fullname = g_strdup (_("Map Account NOT found")); map_fullname = g_strdup (_("Map Account NOT found"));
}
else else
map_fullname = gnc_account_get_full_name (imapInfo->map_account); 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", 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); fullname, imapInfo->head, imapInfo->category, imapInfo->match_string, map_fullname, imapInfo->count);
@ -581,11 +745,15 @@ get_account_info (ImapDialog *imap_dialog)
Account *root; Account *root;
GList *accts; GList *accts;
GtkTreeModel *fmodel; GtkTreeModel *fmodel;
gchar *total;
/* Get list of Accounts */ /* Get list of Accounts */
root = gnc_book_get_root_account (gnc_get_current_book()); root = gnc_book_get_root_account (gnc_get_current_book());
accts = gnc_account_get_descendants_sorted (root); 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)); 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)); 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 // if there are any entries, show first row
show_first_row (imap_dialog); 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); 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")); dialog = GTK_WIDGET(gtk_builder_get_object (builder, "import_map_dialog"));
imap_dialog->dialog = dialog; imap_dialog->dialog = dialog;
// Set the style context for this dialog so it can be easily manipulated with css // Set the name for this dialog so it can be easily manipulated with css
gnc_widget_set_style_context (GTK_WIDGET(dialog), "GncImapDialog"); gtk_widget_set_name (GTK_WIDGET(dialog), "gnc-id-import-map");
imap_dialog->session = gnc_get_current_session(); imap_dialog->session = gnc_get_current_session();
imap_dialog->type = BAYES; 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_signal_connect (imap_dialog->radio_nbayes, "toggled",
G_CALLBACK(list_type_selected_cb), (gpointer)imap_dialog); 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_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_label = GTK_WIDGET(gtk_builder_get_object (builder, "filter-label"));
imap_dialog->filter_button = GTK_WIDGET(gtk_builder_get_object (builder, "filter-button")); 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->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 // Set filter column
filter = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view)); 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); 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); gnc_gui_component_set_session (component_id, imap_dialog->session);
gtk_widget_show (imap_dialog->dialog); gtk_widget_show (imap_dialog->dialog);
gtk_widget_hide (imap_dialog->remove_button);
gnc_imap_invalid_maps_dialog (imap_dialog);
LEAVE(" "); LEAVE(" ");
} }

View File

@ -50,6 +50,20 @@
<object class="GtkButtonBox" id="dialog-action_area1"> <object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="layout_style">end</property> <property name="layout_style">end</property>
<child>
<object class="GtkButton" id="remove_button">
<property name="label" translatable="yes">_Remove Invalid Mappings</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child> <child>
<object class="GtkButton" id="delete_button"> <object class="GtkButton" id="delete_button">
<property name="label" translatable="yes">_Delete</property> <property name="label" translatable="yes">_Delete</property>
@ -61,7 +75,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">0</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -77,7 +91,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
</object> </object>
@ -85,7 +99,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="pack_type">end</property> <property name="pack_type">end</property>
<property name="position">0</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -98,7 +112,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">1</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -161,7 +175,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">2</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -251,6 +265,22 @@
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="total_entries_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">3</property>
<property name="margin_bottom">3</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
@ -261,6 +291,9 @@
<property name="margin_top">5</property> <property name="margin_top">5</property>
<property name="margin_bottom">5</property> <property name="margin_bottom">5</property>
<property name="label" translatable="yes">Filter will be applied to 'Match String' and 'Mapped to Account Name' fields, case sensitive.</property> <property name="label" translatable="yes">Filter will be applied to 'Match String' and 'Mapped to Account Name' fields, case sensitive.</property>
<style>
<class name="gnc-class-highlight"/>
</style>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -327,7 +360,7 @@
</child> </child>
<child> <child>
<object class="GtkButton" id="collapse-button"> <object class="GtkButton" id="collapse-button">
<property name="label" translatable="yes">_Collapse All</property> <property name="label" translatable="yes">Collapse _All</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
@ -374,6 +407,7 @@
</object> </object>
</child> </child>
<action-widgets> <action-widgets>
<action-widget response="-2">remove_button</action-widget>
<action-widget response="-10">delete_button</action-widget> <action-widget response="-10">delete_button</action-widget>
<action-widget response="-6">close_button</action-widget> <action-widget response="-6">close_button</action-widget>
</action-widgets> </action-widgets>