Skip to content

Commit

Permalink
Bug 753283 - Highlight missing when returning from schedule edit.
Browse files Browse the repository at this point in the history
When you return from editing a scheduled transaction the highlight is
missing in the tree view. This is partly due to the model being
recreated when ever a change is made to a scheduled transaction. To
overcome this, the selected schedules are added to a GList which is
used in a new call back signal that has been added to indicate when the
model is populated. When this happens, the model is scanned for the
schedules that are in the GList so they can be reselected.
  • Loading branch information
Bob-IT committed Apr 19, 2021
1 parent 33b8a19 commit c2a7b8e
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 11 deletions.
23 changes: 23 additions & 0 deletions gnucash/gnome-utils/gnc-sx-list-tree-model-adapter.c
Expand Up @@ -52,6 +52,16 @@ struct _GncSxListTreeModelAdapter
struct _GncSxListTreeModelAdapterClass
{
GObjectClass parent;

/* This signal is emitted when the model is populated */
void (*model_populated) (GncSxListTreeModelAdapter *model, gpointer user_data);
};

/* Signal codes */
enum
{
MODEL_POPULATED,
LAST_SIGNAL
};

static GObjectClass *parent_class = NULL;
Expand All @@ -63,6 +73,8 @@ static void gnc_sx_list_tree_model_adapter_init(GTypeInstance *instance, gpointe
static void gnc_sx_list_tree_model_adapter_dispose(GObject *obj);
static void gnc_sx_list_tree_model_adapter_finalize(GObject *obj);

static guint gnc_sx_list_tree_model_adapter_signals[LAST_SIGNAL] = {0};

static GncSxInstances* gsltma_get_sx_instances_from_orig_iter(GncSxListTreeModelAdapter *model, GtkTreeIter *orig_iter);

GType
Expand Down Expand Up @@ -119,6 +131,16 @@ gnc_sx_list_tree_model_adapter_class_init(GncSxListTreeModelAdapterClass *klass)
obj_class->dispose = gnc_sx_list_tree_model_adapter_dispose;
obj_class->finalize = gnc_sx_list_tree_model_adapter_finalize;

gnc_sx_list_tree_model_adapter_signals[MODEL_POPULATED] =
g_signal_new("model_populated",
G_TYPE_FROM_CLASS (obj_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GncSxListTreeModelAdapterClass, model_populated),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);

klass->model_populated = NULL;
}

static GtkTreeModelFlags
Expand Down Expand Up @@ -525,6 +547,7 @@ gsltma_populate_tree_store(GncSxListTreeModelAdapter *model)
-1);
g_free(frequency_str);
}
g_signal_emit_by_name (model, "model_populated");
}

static void
Expand Down
106 changes: 95 additions & 11 deletions gnucash/gnome/gnc-plugin-page-sx-list.c
Expand Up @@ -95,6 +95,7 @@ typedef struct GncPluginPageSxListPrivate

GncSxInstanceModel* instances;
GtkTreeView* tree_view;
GList *selected_list;

} GncPluginPageSxListPrivate;

Expand Down Expand Up @@ -351,6 +352,64 @@ gppsl_selection_changed_cb(GtkTreeSelection *selection, gpointer user_data)
}


static void
gppsl_update_selected_list (GncPluginPageSxList *page, gboolean reset, SchedXaction *sx)
{
GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);

if (reset && priv->selected_list)
{
g_list_free (priv->selected_list);
priv->selected_list = NULL;
}
if (sx)
priv->selected_list = g_list_prepend (priv->selected_list, sx);
}


static void
gppsl_model_populated_cb (GtkTreeModel *tree_model, GncPluginPageSxList *page)
{
GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree_view));
gboolean found = FALSE;

if (priv->selected_list)
{
// walk the list to see if we can reselect the sx
for (GList *list = priv->selected_list; list != NULL; list = list->next)
{
SchedXaction *sx = list->data;
GtkTreePath *path = gtk_tree_path_new_first ();

// loop through the model trying to find selected sx's
while (gnc_tree_view_path_is_valid (GNC_TREE_VIEW(priv->tree_view), path))
{
SchedXaction *sx_tmp = gnc_tree_view_sx_list_get_sx_from_path (
GNC_TREE_VIEW_SX_LIST(priv->tree_view), path);
if (sx_tmp == sx)
{
found = TRUE;
break;
}
gtk_tree_path_next (path);
}
if (found)
gtk_tree_selection_select_path (selection, path);

gtk_tree_path_free (path);
}
}
// this could be on load or if sx is deleted
if (!found)
{
GtkTreePath *path = gtk_tree_path_new_first ();
gtk_tree_selection_select_path (selection, path);
gtk_tree_path_free (path);
}
}


static GtkWidget *
gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)
{
Expand Down Expand Up @@ -420,6 +479,7 @@ gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)

{
GtkTreeSelection *selection;
GtkTreePath *path = gtk_tree_path_new_first ();

priv->tree_view = GTK_TREE_VIEW(gnc_tree_view_sx_list_new(priv->instances));
g_object_set(G_OBJECT(priv->tree_view),
Expand All @@ -430,8 +490,13 @@ gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)

selection = gtk_tree_view_get_selection(priv->tree_view);
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
gtk_tree_selection_select_path (selection, path);
gtk_tree_path_free (path);

g_signal_connect(G_OBJECT(selection), "changed", (GCallback)gppsl_selection_changed_cb, (gpointer)page);
g_signal_connect(G_OBJECT(priv->tree_view), "row-activated", (GCallback)gppsl_row_activated_cb, (gpointer)page);
g_signal_connect (G_OBJECT(gtk_tree_view_get_model (GTK_TREE_VIEW(priv->tree_view))),
"model-populated", (GCallback)gppsl_model_populated_cb, (gpointer)page);
}

/* Add vbox and label */
Expand Down Expand Up @@ -503,6 +568,9 @@ gnc_plugin_page_sx_list_destroy_widget (GncPluginPage *plugin_page)
priv->widget = NULL;
}

if (priv->selected_list)
g_list_free (priv->selected_list);

if (priv->gnc_component_id)
{
gnc_unregister_gui_component(priv->gnc_component_id);
Expand Down Expand Up @@ -611,6 +679,7 @@ gnc_plugin_page_sx_list_cmd_new(GtkAction *action, GncPluginPageSxList *page)
gnc_sx_set_schedule(new_sx, schedule);
}
gnc_ui_scheduled_xaction_editor_dialog_create(window, new_sx, new_sx_flag);
gppsl_update_selected_list (page, TRUE, new_sx);
}

#ifdef REGISTER2_ENABLED
Expand Down Expand Up @@ -696,6 +765,14 @@ gnc_plugin_page_sx_list_cmd_edit(GtkAction *action, GncPluginPageSxList *page)
to_edit = gnc_g_list_map(selected_paths,
(GncGMapFunc)_argument_reorder_fn,
priv->tree_view);

gppsl_update_selected_list (page, TRUE, NULL);
for (GList *list = to_edit; list != NULL; list = list->next)
{
g_debug("to-edit [%s]\n", xaccSchedXactionGetName ((SchedXaction*)list->data));
gppsl_update_selected_list (page, FALSE, list->data);
}

g_list_foreach(to_edit, (GFunc)_edit_sx, window);
g_list_free(to_edit);
g_list_foreach(selected_paths, (GFunc)gtk_tree_path_free, NULL);
Expand Down Expand Up @@ -744,6 +821,7 @@ gppsl_row_activated_cb(GtkTreeView *tree_view,

SchedXaction *sx = gnc_tree_view_sx_list_get_sx_from_path(GNC_TREE_VIEW_SX_LIST(priv->tree_view), path);
gnc_ui_scheduled_xaction_editor_dialog_create(window, sx, FALSE);
gppsl_update_selected_list (page, TRUE, sx);
}


Expand All @@ -769,6 +847,8 @@ gnc_plugin_page_sx_list_cmd_delete(GtkAction *action, GncPluginPageSxList *page)
GList *selected_paths, *to_delete = NULL;
GtkTreeModel *model;
GtkWindow *window;
gchar *message = NULL;
gint length;

selection = gtk_tree_view_get_selection(priv->tree_view);
selected_paths = gtk_tree_selection_get_selected_rows(selection, &model);
Expand All @@ -781,24 +861,28 @@ gnc_plugin_page_sx_list_cmd_delete(GtkAction *action, GncPluginPageSxList *page)
to_delete = gnc_g_list_map(selected_paths,
(GncGMapFunc)_argument_reorder_fn,
priv->tree_view);

window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));

length = g_list_length (to_delete);

/* Translators: This is a ngettext(3) message, %d is the number of scheduled transactions deleted */

This comment has been minimized.

Copy link
@fellen

fellen Apr 21, 2021

Member

@Bob-IT No need for This is a ngettext(3) message Just explain the parameter(s).

This comment has been minimized.

Copy link
@Bob-IT

Bob-IT Apr 21, 2021

Author Contributor

Are you suggesting change line above to...
/* Translators: %d is the number of scheduled transactions deleted */

This comment has been minimized.

Copy link
@fellen

fellen Apr 21, 2021

Member

Yes for similar cases in the future.

Looking again at this message i think the meaning is obvious by the string. IMHO no comment is required here.

This comment has been minimized.

Copy link
@Bob-IT

Bob-IT Apr 21, 2021

Author Contributor

OK, noted.

message = g_strdup_printf (ngettext ("Do you really want to delete this scheduled transaction?",
"Do you really want to delete %d scheduled transactions?",
length), length);

if (gnc_verify_dialog (window, FALSE, "%s", message))
{
GList *list;
for (list = to_delete; list != NULL; list = list->next)
gppsl_update_selected_list (page, TRUE, NULL);
for (GList *list = to_delete; list != NULL; list = list->next)
{
g_debug("to-delete [%s]\n", xaccSchedXactionGetName((SchedXaction*)list->data));
gppsl_update_selected_list (page, FALSE, list->data);
}
}

window = GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page)));
/* FIXME: Does this always refer to only one transaction? Or could
multiple SXs be deleted as well? Ideally, the number of
to-be-deleted SXs should be mentioned here; see
dialog-sx-since-last-run.c:807 */
if (gnc_verify_dialog (window, FALSE, "%s", _("Do you really want to delete this scheduled transaction?")))
{
g_list_foreach(to_delete, (GFunc)_destroy_sx, NULL);
}

g_free (message);
g_list_free(to_delete);
g_list_foreach(selected_paths, (GFunc)gtk_tree_path_free, NULL);
g_list_free(selected_paths);
Expand Down

0 comments on commit c2a7b8e

Please sign in to comment.