Add Filter option to tree store

This commit is contained in:
Robert Fewell 2016-01-06 13:15:29 +00:00 committed by John Ralls
parent f17f047a68
commit a90b10b15e
2 changed files with 340 additions and 69 deletions

View File

@ -46,7 +46,7 @@
/** Enumeration for the tree-store */ /** Enumeration for the tree-store */
enum GncImapColumn {SOURCE_FULL_ACC, SOURCE_ACCOUNT, BASED_ON, MATCH_STRING, enum GncImapColumn {SOURCE_FULL_ACC, SOURCE_ACCOUNT, BASED_ON, MATCH_STRING,
MAP_FULL_ACC, MAP_ACCOUNT, FULL_CATEGORY, COUNT}; MAP_FULL_ACC, MAP_ACCOUNT, FULL_CATEGORY, COUNT, FILTER};
typedef enum typedef enum
{ {
@ -59,7 +59,6 @@ typedef struct
{ {
GtkWidget *dialog; GtkWidget *dialog;
QofSession *session; QofSession *session;
GtkWidget *store;
GtkWidget *view; GtkWidget *view;
GncListType type; GncListType type;
@ -67,6 +66,12 @@ typedef struct
GtkWidget *radio_nbayes; GtkWidget *radio_nbayes;
GtkWidget *radio_online; GtkWidget *radio_online;
GtkWidget *filter_button;
GtkWidget *filter_text_entry;
GtkWidget *filter_label;
GtkWidget *expand_button;
GtkWidget *collapse_button;
}ImapDialog; }ImapDialog;
@ -162,11 +167,11 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog)
if (gtk_tree_model_get_iter (model, &iter, row->data)) if (gtk_tree_model_get_iter (model, &iter, row->data))
{ {
GtkTreePath *tree_path; GtkTreePath *tree_path;
Account *source_account = NULL; Account *source_account = NULL;
gchar *full_source_account; gchar *full_source_account;
gchar *full_category; gchar *full_category;
gchar *match_string; gchar *match_string;
gint depth; gint depth;
gtk_tree_model_get (model, &iter, SOURCE_ACCOUNT, &source_account, SOURCE_FULL_ACC, &full_source_account, gtk_tree_model_get (model, &iter, SOURCE_ACCOUNT, &source_account, SOURCE_FULL_ACC, &full_source_account,
FULL_CATEGORY, &full_category, MATCH_STRING, &match_string, -1); FULL_CATEGORY, &full_category, MATCH_STRING, &match_string, -1);
@ -188,7 +193,7 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog)
gnc_account_delete_map_entry (source_account, full_category, TRUE); gnc_account_delete_map_entry (source_account, full_category, TRUE);
full_category = g_strdup_printf (IMAP_FRAME_BAYES); full_category = g_strdup_printf (IMAP_FRAME_BAYES);
if (depth == 1) // top level if (depth == 1) // top level, delete all below
gnc_account_delete_map_entry (source_account, full_category, FALSE); gnc_account_delete_map_entry (source_account, full_category, FALSE);
else else
gnc_account_delete_map_entry (source_account, full_category, TRUE); gnc_account_delete_map_entry (source_account, full_category, TRUE);
@ -206,7 +211,7 @@ gnc_imap_dialog_delete (ImapDialog *imap_dialog)
gnc_account_delete_map_entry (source_account, full_category, TRUE); gnc_account_delete_map_entry (source_account, full_category, TRUE);
full_category = g_strdup_printf (IMAP_FRAME); full_category = g_strdup_printf (IMAP_FRAME);
if (depth == 1) // top level if (depth == 1) // top level, delete all below
gnc_account_delete_map_entry (source_account, full_category, FALSE); gnc_account_delete_map_entry (source_account, full_category, FALSE);
else else
gnc_account_delete_map_entry (source_account, full_category, TRUE); gnc_account_delete_map_entry (source_account, full_category, TRUE);
@ -241,7 +246,95 @@ gnc_imap_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_
} }
static void static void
list_type_selected (GtkToggleButton* button, ImapDialog *imap_dialog) filter_button_cb (GtkButton *button, ImapDialog *imap_dialog)
{
GtkTreeModel *model, *filter;
GtkTreeIter iter;
const gchar *filter_text;
gboolean valid;
filter = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view));
model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(filter));
filter_text = gtk_entry_get_text (GTK_ENTRY(imap_dialog->filter_text_entry));
// Collapse all nodes
gtk_tree_view_collapse_all (GTK_TREE_VIEW(imap_dialog->view));
valid = gtk_tree_model_get_iter_first (model, &iter);
while (valid)
{
GtkTreePath *tree_path;
gint depth;
const gchar *match_string;
const gchar *map_full_acc;
// Walk through the list, reading each row
gtk_tree_model_get (model, &iter, MATCH_STRING, &match_string, MAP_FULL_ACC, &map_full_acc, -1);
// Get the level we are at in the tree-model
tree_path = gtk_tree_model_get_path (model, &iter);
depth = gtk_tree_path_get_depth (tree_path);
// Reset filter to TRUE
gtk_tree_store_set (GTK_TREE_STORE(model), &iter, FILTER, TRUE, -1);
// Check for a filter_text entry
if (g_strcmp0 (filter_text, "") != 0)
{
if (match_string != NULL) // Check for match_string is not NULL, valid line
{
if ((g_strrstr (match_string, filter_text) == NULL) &&
(g_strrstr (map_full_acc, filter_text) == NULL ))
gtk_tree_store_set (GTK_TREE_STORE(model), &iter, FILTER, FALSE, -1);
else
gtk_tree_view_expand_to_path (GTK_TREE_VIEW(imap_dialog->view), tree_path);
}
}
// Select next entry based on path
if (depth == 1)
gtk_tree_path_down (tree_path);
else
{
gtk_tree_path_next (tree_path);
if (!gtk_tree_model_get_iter (model, &iter, tree_path))
{
gtk_tree_path_prev (tree_path);
gtk_tree_path_up (tree_path);
gtk_tree_path_next (tree_path);
}
}
valid = gtk_tree_model_get_iter (model, &iter, tree_path);
gtk_tree_path_free (tree_path);
}
}
static void
expand_button_cb (GtkButton *button, ImapDialog *imap_dialog)
{
// Clear the filter
gtk_entry_set_text (GTK_ENTRY(imap_dialog->filter_text_entry), "");
filter_button_cb (button, imap_dialog);
gtk_tree_view_expand_all (GTK_TREE_VIEW(imap_dialog->view));
}
static void
collapse_button_cb (GtkButton *button, ImapDialog *imap_dialog)
{
// Clear the filter
gtk_entry_set_text (GTK_ENTRY(imap_dialog->filter_text_entry), "");
filter_button_cb (button, imap_dialog);
gtk_tree_view_collapse_all (GTK_TREE_VIEW(imap_dialog->view));
}
static void
list_type_selected_cb (GtkToggleButton* button, ImapDialog *imap_dialog)
{ {
GncListType type; GncListType type;
@ -277,7 +370,7 @@ show_count_column (ImapDialog *imap_dialog, gboolean show)
} }
static void static void
add_to_store (GtkTreeModel *store, GtkTreeIter *iter, const gchar *text, gpointer user_data) add_to_store (GtkTreeModel *model, GtkTreeIter *iter, const gchar *text, gpointer user_data)
{ {
gchar *fullname = NULL; gchar *fullname = NULL;
gchar *map_fullname = NULL; gchar *map_fullname = NULL;
@ -286,23 +379,28 @@ add_to_store (GtkTreeModel *store, GtkTreeIter *iter, const gchar *text, gpointe
fullname = gnc_account_get_full_name (imapInfo->source_account); fullname = gnc_account_get_full_name (imapInfo->source_account);
map_fullname = gnc_account_get_full_name (imapInfo->map_account); // Do we have a valid map account
if (imapInfo->map_account == NULL)
map_fullname = g_strdup (_("Map Account NOT found"));
else
map_fullname = gnc_account_get_full_name (imapInfo->map_account);
PINFO("Add to Store: Source Acc '%s', Match '%s', Map Acc '%s'", fullname, imapInfo->match_string, map_fullname); PINFO("Add to Store: Source Acc '%s', Match '%s', Map Acc '%s'", fullname, imapInfo->match_string, map_fullname);
gtk_tree_store_set (GTK_TREE_STORE(store), iter, gtk_tree_store_set (GTK_TREE_STORE(model), iter,
SOURCE_FULL_ACC, fullname, SOURCE_ACCOUNT, imapInfo->source_account, SOURCE_FULL_ACC, fullname, SOURCE_ACCOUNT, imapInfo->source_account,
BASED_ON, text, BASED_ON, text,
MATCH_STRING, imapInfo->match_string, MATCH_STRING, imapInfo->match_string,
MAP_FULL_ACC, map_fullname, MAP_ACCOUNT, imapInfo->map_account, MAP_FULL_ACC, map_fullname, MAP_ACCOUNT, imapInfo->map_account,
FULL_CATEGORY, imapInfo->full_category, COUNT, imapInfo->count, -1); FULL_CATEGORY, imapInfo->full_category, COUNT, imapInfo->count,
FILTER, TRUE, -1);
g_free (fullname); g_free (fullname);
g_free (map_fullname); g_free (map_fullname);
} }
static void static void
get_imap_info (Account *acc, const gchar *category, GtkTreeModel *store, const gchar *text) get_imap_info (Account *acc, const gchar *category, GtkTreeModel *model, const gchar *text)
{ {
GtkTreeIter toplevel, child; GtkTreeIter toplevel, child;
GList *imap_list, *node; GList *imap_list, *node;
@ -320,9 +418,10 @@ get_imap_info (Account *acc, const gchar *category, GtkTreeModel *store, const g
{ {
PINFO("List length is %d", g_list_length (imap_list)); PINFO("List length is %d", g_list_length (imap_list));
gtk_tree_store_append (GTK_TREE_STORE(store), &toplevel, NULL); // Add top level entry of Source full Account and Based on.
gtk_tree_store_set (GTK_TREE_STORE(store), &toplevel, gtk_tree_store_append (GTK_TREE_STORE(model), &toplevel, NULL);
SOURCE_ACCOUNT, acc, SOURCE_FULL_ACC, acc_name, BASED_ON, text, -1); gtk_tree_store_set (GTK_TREE_STORE(model), &toplevel,
SOURCE_ACCOUNT, acc, SOURCE_FULL_ACC, acc_name, BASED_ON, text, FILTER, TRUE, -1);
for (node = imap_list; node; node = g_list_next (node)) for (node = imap_list; node; node = g_list_next (node))
{ {
@ -330,10 +429,9 @@ get_imap_info (Account *acc, const gchar *category, GtkTreeModel *store, const g
imapInfo = node->data; imapInfo = node->data;
gtk_tree_store_append (GTK_TREE_STORE(store), &child, &toplevel); // First add a child entry and pass iter to add_to_store
gtk_tree_store_append (GTK_TREE_STORE(model), &child, &toplevel);
// Add to store add_to_store (model, &child, text, imapInfo);
add_to_store (store, &child, text, imapInfo);
// Free the members and structure // Free the members and structure
g_free (imapInfo->category_head); g_free (imapInfo->category_head);
@ -350,13 +448,14 @@ get_imap_info (Account *acc, const gchar *category, GtkTreeModel *store, const g
static void static void
show_first_row (ImapDialog *imap_dialog) show_first_row (ImapDialog *imap_dialog)
{ {
GtkTreeIter iter; GtkTreeModel *model, *filter;
GtkTreeModel *store; GtkTreeIter iter;
store = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view)); filter = gtk_tree_view_get_model (GTK_TREE_VIEW(imap_dialog->view));
model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(filter));
// See if there are any entries // See if there are any entries
if (gtk_tree_model_get_iter_first (store, &iter)) if (gtk_tree_model_get_iter_first (model, &iter))
{ {
GtkTreePath *path; GtkTreePath *path;
path = gtk_tree_path_new_first (); // Set Path to first entry path = gtk_tree_path_new_first (); // Set Path to first entry
@ -366,7 +465,7 @@ show_first_row (ImapDialog *imap_dialog)
} }
static void static void
get_account_info_bayes (GList *accts, GtkTreeModel *store) get_account_info_bayes (GList *accts, GtkTreeModel *model)
{ {
GList *ptr; GList *ptr;
@ -380,12 +479,12 @@ get_account_info_bayes (GList *accts, GtkTreeModel *store)
// Save source account // Save source account
imapInfo.source_account = acc; imapInfo.source_account = acc;
get_imap_info (acc, NULL, store, _("Bayesian")); get_imap_info (acc, NULL, model, _("Bayesian"));
} }
} }
static void static void
get_account_info_nbayes (GList *accts, GtkTreeModel *store) get_account_info_nbayes (GList *accts, GtkTreeModel *model)
{ {
GList *ptr; GList *ptr;
@ -400,18 +499,18 @@ get_account_info_nbayes (GList *accts, GtkTreeModel *store)
imapInfo.source_account = acc; imapInfo.source_account = acc;
// Description // Description
get_imap_info (acc, IMAP_FRAME_DESC, store, _("Description Field")); get_imap_info (acc, IMAP_FRAME_DESC, model, _("Description Field"));
// Memo // Memo
get_imap_info (acc, IMAP_FRAME_MEMO, store, _("Memo Field")); get_imap_info (acc, IMAP_FRAME_MEMO, model, _("Memo Field"));
// CSV Account Map // CSV Account Map
get_imap_info (acc, IMAP_FRAME_CSV, store, _("CSV Account Map")); get_imap_info (acc, IMAP_FRAME_CSV, model, _("CSV Account Map"));
} }
} }
static void static void
get_account_info_online (GList *accts, GtkTreeModel *store) get_account_info_online (GList *accts, GtkTreeModel *model)
{ {
GList *ptr; GList *ptr;
GtkTreeIter toplevel; GtkTreeIter toplevel;
@ -441,45 +540,78 @@ get_account_info_online (GList *accts, GtkTreeModel *store)
imapInfo.match_string = text; imapInfo.match_string = text;
imapInfo.count = " "; imapInfo.count = " ";
gtk_tree_store_append (GTK_TREE_STORE(store), &toplevel, NULL); // Add top level entry and pass iter to add_to_store
gtk_tree_store_append (GTK_TREE_STORE(model), &toplevel, NULL);
// Add imap data to store add_to_store (model, &toplevel, _("Online Id"), &imapInfo);
add_to_store (store, &toplevel, _("Online Id"), &imapInfo);
} }
g_free (text); g_free (text);
} }
} }
static void
show_filter_option (ImapDialog *imap_dialog, gboolean show)
{
if (show)
{
gtk_widget_show (imap_dialog->filter_text_entry);
gtk_widget_show (imap_dialog->filter_button);
gtk_widget_show (imap_dialog->filter_label);
gtk_widget_show (imap_dialog->expand_button);
gtk_widget_show (imap_dialog->collapse_button);
}
else
{
gtk_widget_hide (imap_dialog->filter_text_entry);
gtk_widget_hide (imap_dialog->filter_button);
gtk_widget_hide (imap_dialog->filter_label);
gtk_widget_hide (imap_dialog->expand_button);
gtk_widget_hide (imap_dialog->collapse_button);
}
}
static void static void
get_account_info (ImapDialog *imap_dialog) get_account_info (ImapDialog *imap_dialog)
{ {
Account *root; Account *root;
GList *accts; GList *accts;
GtkTreeIter iter; GtkTreeModel *model, *filter;
GtkTreeModel *store; GtkTreeIter iter;
/* 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);
store = 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_store_clear (GTK_TREE_STORE(store));
model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(filter));
// Clear the tree store
gtk_tree_store_clear (GTK_TREE_STORE(model));
// Clear the filter
gtk_entry_set_text (GTK_ENTRY(imap_dialog->filter_text_entry), "");
// Hide Count Column // Hide Count Column
show_count_column (imap_dialog, FALSE); show_count_column (imap_dialog, FALSE);
// Show Filter Option
show_filter_option (imap_dialog, TRUE);
if (imap_dialog->type == BAYES) if (imap_dialog->type == BAYES)
{ {
get_account_info_bayes (accts, store); get_account_info_bayes (accts, model);
// Show Count Column // Show Count Column
show_count_column (imap_dialog, TRUE); show_count_column (imap_dialog, TRUE);
} }
else if (imap_dialog->type == NBAYES) else if (imap_dialog->type == NBAYES)
get_account_info_nbayes (accts, store); get_account_info_nbayes (accts, model);
else if (imap_dialog->type == ONLINE) else if (imap_dialog->type == ONLINE)
get_account_info_online (accts, store); {
// Hide Filter Option
show_filter_option (imap_dialog, FALSE);
get_account_info_online (accts, model);
}
// 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);
@ -491,11 +623,13 @@ gnc_imap_dialog_create (GtkWidget *parent, ImapDialog *imap_dialog)
{ {
GtkWidget *dialog; GtkWidget *dialog;
GtkBuilder *builder; GtkBuilder *builder;
GtkTreeModel *filter;
GtkTreeSelection *selection; GtkTreeSelection *selection;
ENTER(" "); ENTER(" ");
builder = gtk_builder_new(); builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-imap-editor.glade", "tree-store"); gnc_builder_add_from_file (builder, "dialog-imap-editor.glade", "tree-store");
gnc_builder_add_from_file (builder, "dialog-imap-editor.glade", "treemodelfilter");
gnc_builder_add_from_file (builder, "dialog-imap-editor.glade", "Import Map Dialog"); gnc_builder_add_from_file (builder, "dialog-imap-editor.glade", "Import Map Dialog");
dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Import Map Dialog")); dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Import Map Dialog"));
@ -513,12 +647,30 @@ gnc_imap_dialog_create (GtkWidget *parent, ImapDialog *imap_dialog)
imap_dialog->radio_nbayes = GTK_WIDGET(gtk_builder_get_object (builder, "radio-nbayes")); imap_dialog->radio_nbayes = GTK_WIDGET(gtk_builder_get_object (builder, "radio-nbayes"));
imap_dialog->radio_online = GTK_WIDGET(gtk_builder_get_object (builder, "radio-online")); imap_dialog->radio_online = GTK_WIDGET(gtk_builder_get_object (builder, "radio-online"));
g_signal_connect (imap_dialog->radio_bayes, "toggled", g_signal_connect (imap_dialog->radio_bayes, "toggled",
G_CALLBACK(list_type_selected), (gpointer)imap_dialog); G_CALLBACK(list_type_selected_cb), (gpointer)imap_dialog);
g_signal_connect (imap_dialog->radio_nbayes, "toggled", g_signal_connect (imap_dialog->radio_nbayes, "toggled",
G_CALLBACK(list_type_selected), (gpointer)imap_dialog); G_CALLBACK(list_type_selected_cb), (gpointer)imap_dialog);
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"));
g_signal_connect (imap_dialog->filter_button, "clicked",
G_CALLBACK(filter_button_cb), (gpointer)imap_dialog);
imap_dialog->expand_button = GTK_WIDGET(gtk_builder_get_object (builder, "expand-button"));
g_signal_connect (imap_dialog->expand_button, "clicked",
G_CALLBACK(expand_button_cb), (gpointer)imap_dialog);
imap_dialog->collapse_button = GTK_WIDGET(gtk_builder_get_object (builder, "collapse-button"));
g_signal_connect (imap_dialog->collapse_button, "clicked",
G_CALLBACK(collapse_button_cb), (gpointer)imap_dialog);
imap_dialog->view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview")); imap_dialog->view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
// 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);
/* Enable alternative line colors */ /* Enable alternative line colors */
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(imap_dialog->view), TRUE); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(imap_dialog->view), TRUE);

View File

@ -16,12 +16,17 @@
<column type="gchararray"/> <column type="gchararray"/>
<!-- column-name map_account --> <!-- column-name map_account -->
<column type="gpointer"/> <column type="gpointer"/>
<!-- column-name path --> <!-- column-name full_category -->
<column type="gchararray"/> <column type="gchararray"/>
<!-- column-name count --> <!-- column-name count -->
<column type="gchararray"/> <column type="gchararray"/>
<!-- column-name filter -->
<column type="gboolean"/>
</columns> </columns>
</object> </object>
<object class="GtkTreeModelFilter" id="treemodelfilter">
<property name="child_model">tree-store</property>
</object>
<object class="GtkDialog" id="Import Map Dialog"> <object class="GtkDialog" id="Import Map Dialog">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="border_width">6</property> <property name="border_width">6</property>
@ -35,18 +40,6 @@
<child internal-child="vbox"> <child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox2"> <object class="GtkVBox" id="dialog-vbox2">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">What type of information to display?</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="action_area"> <child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1"> <object class="GtkHButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property> <property name="can_focus">False</property>
@ -89,6 +82,18 @@
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">What type of information to display?</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child> <child>
<object class="GtkHBox" id="hbox1"> <object class="GtkHBox" id="hbox1">
<property name="visible">True</property> <property name="visible">True</property>
@ -158,7 +163,7 @@
<object class="GtkTreeView" id="treeview"> <object class="GtkTreeView" id="treeview">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="model">tree-store</property> <property name="model">treemodelfilter</property>
<child> <child>
<object class="GtkTreeViewColumn" id="source_account_name"> <object class="GtkTreeViewColumn" id="source_account_name">
<property name="resizable">True</property> <property name="resizable">True</property>
@ -176,7 +181,9 @@
<property name="resizable">True</property> <property name="resizable">True</property>
<property name="title" translatable="yes">Based On</property> <property name="title" translatable="yes">Based On</property>
<child> <child>
<object class="GtkCellRendererText" id="cellrenderertext4"/> <object class="GtkCellRendererText" id="cellrenderertext4">
<property name="xpad">10</property>
</object>
<attributes> <attributes>
<attribute name="text">2</attribute> <attribute name="text">2</attribute>
</attributes> </attributes>
@ -188,7 +195,9 @@
<property name="resizable">True</property> <property name="resizable">True</property>
<property name="title" translatable="yes">Match String</property> <property name="title" translatable="yes">Match String</property>
<child> <child>
<object class="GtkCellRendererText" id="cellrenderertext1"/> <object class="GtkCellRendererText" id="cellrenderertext1">
<property name="xpad">10</property>
</object>
<attributes> <attributes>
<attribute name="text">3</attribute> <attribute name="text">3</attribute>
</attributes> </attributes>
@ -200,7 +209,9 @@
<property name="resizable">True</property> <property name="resizable">True</property>
<property name="title" translatable="yes">Mapped to Account Name</property> <property name="title" translatable="yes">Mapped to Account Name</property>
<child> <child>
<object class="GtkCellRendererText" id="cellrenderertext2"/> <object class="GtkCellRendererText" id="cellrenderertext2">
<property name="xpad">10</property>
</object>
<attributes> <attributes>
<attribute name="text">4</attribute> <attribute name="text">4</attribute>
</attributes> </attributes>
@ -212,7 +223,10 @@
<property name="resizable">True</property> <property name="resizable">True</property>
<property name="title" translatable="yes">Count of Match String Usage</property> <property name="title" translatable="yes">Count of Match String Usage</property>
<child> <child>
<object class="GtkCellRendererText" id="cellrenderertext5"/> <object class="GtkCellRendererText" id="cellrenderertext5">
<property name="xpad">10</property>
<property name="alignment">center</property>
</object>
<attributes> <attributes>
<attribute name="text">7</attribute> <attribute name="text">7</attribute>
</attributes> </attributes>
@ -229,11 +243,11 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label2"> <object class="GtkLabel" id="filter-label">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="ypad">5</property> <property name="ypad">5</property>
<property name="label" translatable="yes">You may select multiple rows and then press the delete button...</property> <property name="label" translatable="yes">Case sensative filtering is available on 'Match String' and 'Mapped to Account Name'.</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -241,6 +255,111 @@
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="filter-text-entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="filter-button">
<property name="label" translatable="yes">_Filter</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="expand-button">
<property name="label" translatable="yes">_Expand All</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="collapse-button">
<property name="label" translatable="yes">_Collapse All</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ypad">5</property>
<property name="label" translatable="yes">Multiple rows can be selected and then deleted by pressing the delete button...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">6</property>
</packing>
</child>
</object> </object>
</child> </child>
<action-widgets> <action-widgets>