ImportMatcherMultiSelect

Mods to import-main-matcher.c and dialog-import.glade to implement multi-selection of transactions to import and assignment of a single transfer account to the selection

Silence Deprecation Warning

Added conditional replacement of gtk_menu_popup in import-main-matcher.c and reapplied changes to treeview to current version of dialog-import.glade from maint branch.

ImportMatcherMultiSelect #497  Fixes

fixed GTK deprecation selection to use GTK_CHECK_VERSION, deleted g-list-free(l..., , added check for  a selection before popping
ImportMatcherMultiSelect #497 GTKFix

Fix to mixup of deprecated and replacement GTK function for popup menu
 Open ImportMatcherMultiSelect #497 Delet g_list_free..
This commit is contained in:
David Cousens 2019-05-28 13:38:42 +10:00 committed by Geert Janssens
parent cc12fcf322
commit 5f51fc5406
3 changed files with 273 additions and 87 deletions

View File

@ -1143,8 +1143,11 @@
<property name="reorderable">True</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="rubber_banding">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection3"/>
<object class="GtkTreeSelection" id="treeview-selection3">
<property name="mode">multiple</property>
</object>
</child>
</object>
</child>

View File

@ -64,16 +64,13 @@ struct _main_matcher_info
GNCTransactionProcessedCB transaction_processed_cb;
gpointer user_data;
GNCImportPendingMatches *pending_matches;
GtkTreeViewColumn *account_column;
};
enum downloaded_cols
{
DOWNLOADED_COL_DATE_TXT = 0,
DOWNLOADED_COL_DATE_INT64,
DOWNLOADED_COL_DATE = 0,
DOWNLOADED_COL_ACCOUNT,
DOWNLOADED_COL_AMOUNT,
DOWNLOADED_COL_AMOUNT_DOUBLE,
DOWNLOADED_COL_DESCRIPTION,
DOWNLOADED_COL_MEMO,
DOWNLOADED_COL_ACTION_ADD,
@ -98,9 +95,28 @@ void on_matcher_help_clicked (GtkButton *button, gpointer user_data);
void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data);
/* Local prototypes */
static void
refresh_model_row(GNCImportMainMatcher *gui, GtkTreeModel *model,
static void gnc_gen_trans_assign_transfer_account(
GtkTreeView *treeview,
gboolean *first,
gboolean *is_selection,
GtkTreePath *path,
Account **new_acc,
GNCImportMainMatcher *info);
static void gnc_gen_trans_assign_transfer_account_to_selection_cb (
GtkMenuItem *menuitem,
GNCImportMainMatcher *info);
static void gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info);
static gboolean gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info);
static gboolean gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info);
static void refresh_model_row(GNCImportMainMatcher *gui, GtkTreeModel *model,
GtkTreeIter *iter, GNCImportTransInfo *info);
/* end local prototypes */
void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
{
@ -361,54 +377,254 @@ gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
}
static void
gnc_gen_trans_row_activated_cb (GtkTreeView *view,
GtkTreePath *path,
GtkTreeViewColumn *column,
GNCImportMainMatcher *gui)
gnc_gen_trans_assign_transfer_account(GtkTreeView *treeview,
gboolean *first,
gboolean *is_selection,
GtkTreePath *path,
Account **new_acc,
GNCImportMainMatcher *info)
{
GtkTreeModel *model;
GtkTreeIter iter;
GNCImportTransInfo *trans_info;
Account *old_acc;
gboolean ok_pressed;
model = gtk_tree_view_get_model(gui->view);
if (!gtk_tree_model_get_iter(model, &iter, path))
return;
gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
switch (gnc_import_TransInfo_get_action (trans_info))
ENTER("");
DEBUG("first = %s",*first?"true":"false");
DEBUG("is_selection = %s",*is_selection?"true":"false");
DEBUG("path = %s", gtk_tree_path_to_string(path));
DEBUG("account passed in = %s", gnc_get_account_name_for_register(*new_acc));
model = gtk_tree_view_get_model(treeview);
if (gtk_tree_model_get_iter(model, &iter, path))
{
case GNCImport_ADD:
if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE)
gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
switch (gnc_import_TransInfo_get_action (trans_info))
{
run_account_picker_dialog (gui, model, &iter, trans_info);
case GNCImport_ADD:
if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE)
{
ok_pressed = TRUE;
old_acc = gnc_import_TransInfo_get_destacc (trans_info);
if (*first)
{
ok_pressed = FALSE;
*new_acc = gnc_import_select_account(info->main_widget,
NULL,
TRUE,
_("Destination account for the auto-balance split."),
xaccTransGetCurrency(
gnc_import_TransInfo_get_trans(trans_info)),
ACCT_TYPE_NONE,
old_acc,
&ok_pressed);
*first = FALSE;
DEBUG("account selected = %s",
gnc_account_get_full_name(*new_acc));
}
if (ok_pressed)
gnc_import_TransInfo_set_destacc (trans_info,
*new_acc, TRUE);
}
break;
case GNCImport_CLEAR:
case GNCImport_UPDATE:
if (first && !is_selection) run_match_dialog (info, trans_info);
break;
case GNCImport_SKIP:
break;
default:
PERR("InvalidGNCImportValue");
break;
}
break;
case GNCImport_CLEAR:
case GNCImport_UPDATE:
run_match_dialog (gui, trans_info);
break;
case GNCImport_SKIP:
/*The information displayed is only informative, until you select an action*/
break;
default:
PERR("I don't know what to do! (Yet...)");
break;
refresh_model_row(info, model, &iter, trans_info);
}
refresh_model_row(gui, model, &iter, trans_info);
LEAVE("");
}
static void
gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
GNCImportMainMatcher *info)
{
GtkTreeView *treeview;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
GNCImportTransInfo *trans_info;
Account *assigned_account;
GList *selected_rows, *l;
gboolean first, is_selection;
ENTER("");
treeview = GTK_TREE_VIEW(info->view);
model = gtk_tree_view_get_model(treeview);
selection = gtk_tree_view_get_selection(treeview);
selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
assigned_account = NULL;
first = TRUE;
is_selection = TRUE;
DEBUG("Rows in selection = %i",
gtk_tree_selection_count_selected_rows(selection));
DEBUG("Entering loop over selection");
if (gtk_tree_selection_count_selected_rows(selection) > 0)
{
for (l = selected_rows; l != NULL; l = l->next)
{
DEBUG("passing first = %s",
first?"true":"false");
DEBUG("passing is_selection = %s",
is_selection?"true":"false");
DEBUG("passing path = %s",
gtk_tree_path_to_string(l->data));
DEBUG("passing account value = %s",
gnc_account_get_full_name(assigned_account));
gnc_gen_trans_assign_transfer_account(treeview,
&first, &is_selection, l->data, &assigned_account, info);
DEBUG("returned value of account = %s",
gnc_account_get_full_name(assigned_account));
DEBUG("returned value of first = %s",first?"true":"false");
if (assigned_account == NULL) break;
gtk_tree_selection_unselect_path(selection, l->data);
}
}
g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
LEAVE("");
}
static void
gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *column,
GNCImportMainMatcher *info)
{
Account *assigned_account;
gboolean first, is_selection;
ENTER("");
assigned_account = NULL;
first = TRUE;
is_selection = FALSE;
gnc_gen_trans_assign_transfer_account(treeview,
&first, &is_selection, path,
&assigned_account, info);
DEBUG("account returned = %s", gnc_account_get_full_name(assigned_account));
LEAVE("");
}
static void
gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
GNCImportMainMatcher *gui)
GNCImportMainMatcher *info)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkSelectionMode mode;
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
return;
gtk_tree_selection_unselect_iter(selection, &iter);
ENTER("");
mode = gtk_tree_selection_get_mode(selection);
switch (mode)
{
case GTK_SELECTION_MULTIPLE:
DEBUG("mode = GTK_SELECTION_MULTIPLE, no action");
break;
case GTK_SELECTION_NONE:
DEBUG("mode = GTK_SELECTION_NONE, no action");
break;
case GTK_SELECTION_BROWSE:
DEBUG("mode = GTK_SELECTION_BROWSE->default");
case GTK_SELECTION_SINGLE:
DEBUG("mode = GTK_SELECTION_SINGLE->default");
default:
DEBUG("mode = default unselect selected row");
if (gtk_tree_selection_get_selected(selection, &model, &iter))
{
gtk_tree_selection_unselect_iter(selection, &iter);
}
}
LEAVE("");
}
static void
gnc_gen_trans_view_popup_menu (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info)
{
GtkWidget *menu, *menuitem;
GdkEventButton *event_button;
ENTER ("");
menu = gtk_menu_new();
menuitem = gtk_menu_item_new_with_label(_("Assign a transfer account."));
g_signal_connect(menuitem, "activate",
G_CALLBACK(
gnc_gen_trans_assign_transfer_account_to_selection_cb),
info);
DEBUG("Callback to assign destination account to selection connected");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
gtk_widget_show_all(menu);
event_button = (GdkEventButton *) event;
/* Note: event can be NULL here when called from view_onPopupMenu;
* gdk_event_get_time() accepts a NULL argument */
/* replace deprecated function for GTK versions >=3.22 */
#if GTK_CHECK_VERSION(3,22,0)
gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent*)event);
#else
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
(event_button != NULL) ? event_button->button : 0,
gdk_event_get_time((GdkEvent*)event));
#endif
LEAVE ("");
}
static gboolean
gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info)
{
GdkEventButton *event_button;
GtkTreeSelection *selection;
ENTER("");
g_return_val_if_fail (treeview != NULL, FALSE);
g_return_val_if_fail (event != NULL, FALSE);
/* handle single click with the right mouse button? */
if (event->type == GDK_BUTTON_PRESS)
{
event_button = (GdkEventButton *) event;
if (event_button->button == GDK_BUTTON_SECONDARY)
{
DEBUG("Right mouseClick detected- popup the menu.");
selection = gtk_tree_view_get_selection(treeview);
if (gtk_tree_selection_count_selected_rows(selection) > 0)
{
gnc_gen_trans_view_popup_menu(treeview, event, info);
}
LEAVE("return TRUE");
return TRUE;
}
}
LEAVE("return FALSE");
return FALSE;
}
static gboolean
gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
GdkEvent *event,
GNCImportMainMatcher *info)
{
GtkTreeSelection *selection;
ENTER("");
/* respond to Shift-F10 popup menu hotkey */
selection = gtk_tree_view_get_selection(treeview);
if (gtk_tree_selection_count_selected_rows(selection) > 0)
{
gnc_gen_trans_view_popup_menu(treeview, NULL, info);
}
LEAVE ("");
return TRUE;
}
static GtkTreeViewColumn *
add_text_column(GtkTreeView *view, const gchar *title, int col_num)
{
@ -421,19 +637,7 @@ add_text_column(GtkTreeView *view, const gchar *title, int col_num)
"text", col_num,
"background", DOWNLOADED_COL_COLOR,
NULL);
// If date column, use the time64 value for the sorting.
if (col_num == DOWNLOADED_COL_DATE_TXT)
gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_DATE_INT64);
else if (col_num == DOWNLOADED_COL_AMOUNT) // If amount column, use double value
{
gtk_cell_renderer_set_alignment (renderer, 1.0, 0.5); // right align amount column
gtk_cell_renderer_set_padding (renderer, 5, 0); // add padding so its not close to description
gtk_tree_view_column_set_sort_column_id(column, DOWNLOADED_COL_AMOUNT_DOUBLE);
}
else
gtk_tree_view_column_set_sort_column_id(column, col_num);
gtk_tree_view_column_set_sort_column_id(column, col_num);
g_object_set(G_OBJECT(column),
"reorderable", TRUE,
"resizable", TRUE,
@ -476,23 +680,20 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info,
GtkTreeSelection *selection;
view = info->view;
store = gtk_list_store_new(NUM_DOWNLOADED_COLS, G_TYPE_STRING, G_TYPE_INT64,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE,
store = gtk_list_store_new(NUM_DOWNLOADED_COLS,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
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);
gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
g_object_unref(store);
/* prevent the rows being dragged to a different order */
gtk_tree_view_set_reorderable (view, FALSE);
/* Add the columns *
* (keep the line break below to avoid a translator comment) */
add_text_column(view,
_("Date"), DOWNLOADED_COL_DATE_TXT);
info->account_column = add_text_column(view, _("Account"), DOWNLOADED_COL_ACCOUNT);
gtk_tree_view_column_set_visible(info->account_column, show_account);
_("Date"), DOWNLOADED_COL_DATE);
column = add_text_column(view, _("Account"), DOWNLOADED_COL_ACCOUNT);
gtk_tree_view_column_set_visible(column, show_account);
add_text_column(view, _("Amount"), DOWNLOADED_COL_AMOUNT);
add_text_column(view, _("Description"), DOWNLOADED_COL_DESCRIPTION);
add_text_column(view, _("Memo"), DOWNLOADED_COL_MEMO);
@ -536,15 +737,14 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info,
G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
g_signal_connect(selection, "changed",
G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
g_signal_connect(view, "button-press-event",
G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
g_signal_connect(view, "popup-menu",
G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
}
static void
show_account_column_toggled_cb (GtkToggleButton *togglebutton,
GNCImportMainMatcher *info)
{
gtk_tree_view_column_set_visible (info->account_column,
gtk_toggle_button_get_active (togglebutton));
}
GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
const gchar* heading,
@ -558,7 +758,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();
@ -587,11 +786,6 @@ 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",
G_CALLBACK(show_account_column_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"));
@ -631,7 +825,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();
@ -660,11 +853,6 @@ 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",
G_CALLBACK(show_account_column_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"));
@ -738,8 +926,6 @@ refresh_model_row (GNCImportMainMatcher *gui,
gchar *int_required_class, *int_prob_required_class, *int_not_required_class;
gchar *class_extension = NULL;
Split *split;
time64 date;
gnc_numeric amount;
g_assert (gui);
g_assert (model);
g_assert (info);
@ -762,17 +948,16 @@ refresh_model_row (GNCImportMainMatcher *gui,
gtk_list_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);
text = qof_print_date ( xaccTransGetDate( gnc_import_TransInfo_get_trans(info) ) );
gtk_list_store_set(store, iter, DOWNLOADED_COL_DATE, text, -1);
g_free(text);
/*Amount*/
amount = xaccSplitGetAmount (split);
ro_text = xaccPrintAmount (amount, gnc_split_amount_print_info(split, TRUE));
ro_text = xaccPrintAmount
(xaccSplitGetAmount (split),
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);
/*Description*/
ro_text = xaccTransGetDescription(gnc_import_TransInfo_get_trans(info) );

View File

@ -1,6 +1,5 @@
# This is a list of files which contain translatable strings.
# This file was autogenerated by cmake.
bindings/python/gnucash_core.c
borrowed/goffice/go-charmap-sel.c
borrowed/goffice/go-glib-extras.c
borrowed/goffice/go-optionmenu.c
@ -194,7 +193,6 @@ gnucash/gnome-utils/search-param.c
gnucash/gnome-utils/tree-view-utils.c
gnucash/gnome-utils/window-main-summarybar.c
gnucash/gnucash-bin.c
gnucash/gnucash-gresources.c
gnucash/gschemas/org.gnucash.dialogs.business.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.checkprinting.gschema.xml.in
gnucash/gschemas/org.gnucash.dialogs.commodities.gschema.xml.in