Enhancement: Fixes #556, shell - avoid double refresh caused by tree view

This commit is contained in:
Rory Fewell
2025-12-18 22:00:22 +00:00
parent 7df520ee0d
commit a675dcfabc
7 changed files with 201 additions and 83 deletions

View File

@@ -39,6 +39,11 @@ static void wintc_sh_tree_view_behaviour_set_property(
GParamSpec* pspec
);
static void wintc_sh_tree_view_behaviour_node_add_items(
WinTCShTreeViewBehaviour* behaviour,
GtkTreeIter* node,
GList* items
);
static void wintc_sh_tree_view_behaviour_update_view(
WinTCShTreeViewBehaviour* behaviour,
WinTCShBrowser* browser
@@ -315,6 +320,98 @@ WinTCShTreeViewBehaviour* wintc_sh_tree_view_behaviour_new(
//
// PRIVATE FUNCTIONS
//
static void wintc_sh_tree_view_behaviour_node_add_items(
WinTCShTreeViewBehaviour* behaviour,
GtkTreeIter* node,
GList* items
)
{
GtkTreeIter child;
WinTCShextViewItem* view_item;
WinTCIShextView* view = NULL;
gtk_tree_model_get(
GTK_TREE_MODEL(behaviour->tree_model),
node,
COLUMN_MAPPED_VIEW, &view,
-1
);
for (GList* iter = items; iter; iter = iter->next)
{
view_item = iter->data;
// Skip leaf nodes and nodes that already exist
//
if (
view_item->is_leaf ||
g_hash_table_contains(
behaviour->map_hash_to_row,
GUINT_TO_POINTER(view_item->hash)
)
)
{
continue;
}
WINTC_LOG_DEBUG(
"shell: tree adding item %p",
GUINT_TO_POINTER(view_item->hash)
);
// Sort into model
//
GCompareFunc sort_func = wintc_ishext_view_get_sort_func(view);
gint item_pos =
wintc_tree_model_get_insertion_sort_pos(
GTK_TREE_MODEL(behaviour->tree_model),
node,
COLUMN_VIEW_HASH,
G_TYPE_UINT,
sort_func,
GUINT_TO_POINTER(view_item->hash)
);
// Push to model
//
gtk_tree_store_insert(
behaviour->tree_model,
&child,
node,
item_pos
);
gtk_tree_store_set(
behaviour->tree_model,
&child,
COLUMN_ICON_NAME, view_item->icon_name,
COLUMN_ENTRY_NAME, view_item->display_name,
COLUMN_VIEW_HASH, view_item->hash,
-1
);
// Map hash-->row
//
GtkTreePath* tree_path =
gtk_tree_model_get_path(
GTK_TREE_MODEL(behaviour->tree_model),
&child
);
g_hash_table_insert(
behaviour->map_hash_to_row,
GUINT_TO_POINTER(view_item->hash),
gtk_tree_row_reference_new(
GTK_TREE_MODEL(behaviour->tree_model),
tree_path
)
);
gtk_tree_path_free(tree_path);
}
}
static void wintc_sh_tree_view_behaviour_update_view(
WinTCShTreeViewBehaviour* behaviour,
WinTCShBrowser* browser
@@ -607,7 +704,18 @@ static void wintc_sh_tree_view_behaviour_update_view(
G_CONNECT_DEFAULT
);
wintc_ishext_view_refresh_items(view);
// Add the items now - if this is a totally new view this'll just
// trigger a refresh and the signals will deal with it
//
GList* items = wintc_ishext_view_get_items(view);
wintc_sh_tree_view_behaviour_node_add_items(
behaviour,
&last,
items
);
g_list_free(items);
}
// Delete the view if needed
@@ -666,7 +774,7 @@ static void on_browser_load_changed(
WinTCShTreeViewBehaviour* behaviour =
WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data);
if (load_event != WINTC_SH_BROWSER_LOAD_STARTED)
if (load_event != WINTC_SH_BROWSER_LOAD_FINISHED)
{
return;
}
@@ -683,9 +791,6 @@ static void on_view_items_added(
WinTCShTreeViewBehaviour* behaviour =
WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data);
GtkTreeIter parent;
GtkTreeIter child;
WINTC_LOG_DEBUG(
"shell: tree - items added to %p",
GUINT_TO_POINTER(wintc_ishext_view_get_unique_hash(view))
@@ -693,6 +798,7 @@ static void on_view_items_added(
// Locate the parent node
//
GtkTreeIter parent;
GtkTreeRowReference* row_ref;
GtkTreePath* tree_path;
@@ -718,82 +824,13 @@ static void on_view_items_added(
gtk_tree_path_free(tree_path);
// Iterate over the items to append to the tree
// Append the items to the node now
//
WinTCShextViewItem* view_item;
for (GList* iter = update->data; iter; iter = iter->next)
{
view_item = iter->data;
// Skip leaf nodes and nodes that already exist
//
if (
view_item->is_leaf ||
g_hash_table_contains(
behaviour->map_hash_to_row,
GUINT_TO_POINTER(view_item->hash)
)
)
{
continue;
}
WINTC_LOG_DEBUG(
"shell: tree adding item %p",
GUINT_TO_POINTER(view_item->hash)
);
// Sort into model
//
GCompareFunc sort_func = wintc_ishext_view_get_sort_func(view);
gint item_pos =
wintc_tree_model_get_insertion_sort_pos(
GTK_TREE_MODEL(behaviour->tree_model),
&parent,
COLUMN_VIEW_HASH,
G_TYPE_UINT,
sort_func,
GUINT_TO_POINTER(view_item->hash)
);
// Push to model
//
gtk_tree_store_insert(
behaviour->tree_model,
&child,
&parent,
item_pos
);
gtk_tree_store_set(
behaviour->tree_model,
&child,
COLUMN_ICON_NAME, view_item->icon_name,
COLUMN_ENTRY_NAME, view_item->display_name,
COLUMN_VIEW_HASH, view_item->hash,
-1
);
// Map hash-->row
//
GtkTreePath* tree_path =
gtk_tree_model_get_path(
GTK_TREE_MODEL(behaviour->tree_model),
&child
);
g_hash_table_insert(
behaviour->map_hash_to_row,
GUINT_TO_POINTER(view_item->hash),
gtk_tree_row_reference_new(
GTK_TREE_MODEL(behaviour->tree_model),
tree_path
)
);
gtk_tree_path_free(tree_path);
}
wintc_sh_tree_view_behaviour_node_add_items(
behaviour,
&parent,
update->data
);
}
static void on_view_items_removed(

View File

@@ -49,6 +49,9 @@ static const gchar* wintc_sh_view_cpl_get_display_name(
static const gchar* wintc_sh_view_cpl_get_icon_name(
WinTCIShextView* view
);
static GList* wintc_sh_view_cpl_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_cpl_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -144,6 +147,7 @@ static void wintc_sh_view_cpl_ishext_view_interface_init(
iface->compare_items = wintc_sh_view_cpl_compare_items;
iface->get_display_name = wintc_sh_view_cpl_get_display_name;
iface->get_icon_name = wintc_sh_view_cpl_get_icon_name;
iface->get_items = wintc_sh_view_cpl_get_items;
iface->get_operations_for_item = wintc_sh_view_cpl_get_operations_for_item;
iface->get_operations_for_view = wintc_sh_view_cpl_get_operations_for_view;
iface->get_parent_path = wintc_sh_view_cpl_get_parent_path;
@@ -262,6 +266,15 @@ static const gchar* wintc_sh_view_cpl_get_icon_name(
return "preferences-other";
}
static GList* wintc_sh_view_cpl_get_items(
WinTCIShextView* view
)
{
WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(view);
return g_hash_table_get_values(view_cpl->map_items);
}
static GMenuModel* wintc_sh_view_cpl_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash)

View File

@@ -90,6 +90,9 @@ static const gchar* wintc_sh_view_desktop_get_display_name(
static const gchar* wintc_sh_view_desktop_get_icon_name(
WinTCIShextView* view
);
static GList* wintc_sh_view_desktop_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_desktop_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -209,6 +212,7 @@ static void wintc_sh_view_desktop_ishext_view_interface_init(
iface->compare_items = wintc_sh_view_desktop_compare_items;
iface->get_display_name = wintc_sh_view_desktop_get_display_name;
iface->get_icon_name = wintc_sh_view_desktop_get_icon_name;
iface->get_items = wintc_sh_view_desktop_get_items;
iface->get_operations_for_item =
wintc_sh_view_desktop_get_operations_for_item;
iface->get_operations_for_view =
@@ -303,6 +307,13 @@ static const gchar* wintc_sh_view_desktop_get_icon_name(
return "user-desktop";
}
static GList* wintc_sh_view_desktop_get_items(
WINTC_UNUSED(WinTCIShextView* view)
)
{
return g_hash_table_get_values(s_desktop_map);
}
static GMenuModel* wintc_sh_view_desktop_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash)

View File

@@ -73,6 +73,9 @@ static const gchar* wintc_sh_view_drives_get_display_name(
static const gchar* wintc_sh_view_drives_get_icon_name(
WinTCIShextView* view
);
static GList* wintc_sh_view_drives_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_drives_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -183,6 +186,7 @@ static void wintc_sh_view_drives_ishext_view_interface_init(
iface->compare_items = wintc_sh_view_drives_compare_items;
iface->get_display_name = wintc_sh_view_drives_get_display_name;
iface->get_icon_name = wintc_sh_view_drives_get_icon_name;
iface->get_items = wintc_sh_view_drives_get_items;
iface->get_operations_for_item =
wintc_sh_view_drives_get_operations_for_item;
iface->get_operations_for_view =
@@ -274,6 +278,13 @@ static const gchar* wintc_sh_view_drives_get_icon_name(
return "computer";
}
static GList* wintc_sh_view_drives_get_items(
WINTC_UNUSED(WinTCIShextView* view)
)
{
return g_hash_table_get_values(s_drives_map);
}
static GMenuModel* wintc_sh_view_drives_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash)

View File

@@ -80,6 +80,9 @@ static const gchar* wintc_sh_view_fs_get_display_name(
static const gchar* wintc_sh_view_fs_get_icon_name(
WinTCIShextView* view
);
static GList* wintc_sh_view_fs_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_fs_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -195,8 +198,9 @@ struct _WinTCShViewFS
// FS state
//
gchar* parent_path;
gchar* path;
gboolean is_new; // Track if this view has ever been refreshed before
gchar* parent_path;
gchar* path;
GFileMonitor* fs_monitor;
GHashTable* fs_map_entries;
@@ -266,6 +270,7 @@ static void wintc_sh_view_fs_init(
WinTCShViewFS* self
)
{
self->is_new = TRUE;
self->fs_clipboard = wintc_sh_fs_clipboard_new();
}
@@ -277,6 +282,7 @@ static void wintc_sh_view_fs_ishext_view_interface_init(
iface->compare_items = wintc_sh_view_fs_compare_items;
iface->get_display_name = wintc_sh_view_fs_get_display_name;
iface->get_icon_name = wintc_sh_view_fs_get_icon_name;
iface->get_items = wintc_sh_view_fs_get_items;
iface->get_operations_for_item = wintc_sh_view_fs_get_operations_for_item;
iface->get_operations_for_view = wintc_sh_view_fs_get_operations_for_view;
iface->get_parent_path = wintc_sh_view_fs_get_parent_path;
@@ -476,12 +482,34 @@ static const gchar* wintc_sh_view_fs_get_display_name(
}
static const gchar* wintc_sh_view_fs_get_icon_name(
WINTC_UNUSED(WinTCIShextView* view)
WinTCIShextView* view
)
{
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
if (g_strcmp0(view_fs->path, "/") == 0)
{
return "drive-harddisk";
}
return "inode-directory";
}
static GList* wintc_sh_view_fs_get_items(
WinTCIShextView* view
)
{
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
if (view_fs->is_new)
{
wintc_sh_view_fs_refresh_items(view);
return NULL;
}
return g_hash_table_get_values(view_fs->fs_map_entries);
}
static GMenuModel* wintc_sh_view_fs_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -665,6 +693,8 @@ static void wintc_sh_view_fs_refresh_items(
WINTC_LOG_DEBUG("%s", "shell: refresh fs view");
view_fs->is_new = FALSE;
_wintc_ishext_view_refreshing(view);
if (view_fs->fs_map_entries)

View File

@@ -53,6 +53,9 @@ struct _WinTCIShextViewInterface
const gchar* (*get_icon_name) (
WinTCIShextView* view
);
GList* (*get_items) (
WinTCIShextView* view
);
GMenuModel* (*get_operations_for_item) (
WinTCIShextView* view,
guint item_hash
@@ -112,6 +115,9 @@ const gchar* wintc_ishext_view_get_display_name(
const gchar* wintc_ishext_view_get_icon_name(
WinTCIShextView* view
);
GList* wintc_ishext_view_get_items(
WinTCIShextView* view
);
GMenuModel* wintc_ishext_view_get_operations_for_item(
WinTCIShextView* view,
guint item_hash

View File

@@ -139,6 +139,16 @@ const gchar* wintc_ishext_view_get_icon_name(
return iface->get_icon_name(view);
}
GList* wintc_ishext_view_get_items(
WinTCIShextView* view
)
{
WinTCIShextViewInterface* iface =
WINTC_ISHEXT_VIEW_GET_IFACE(view);
return iface->get_items(view);
}
GMenuModel* wintc_ishext_view_get_operations_for_item(
WinTCIShextView* view,
guint item_hash