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 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( static void wintc_sh_tree_view_behaviour_update_view(
WinTCShTreeViewBehaviour* behaviour, WinTCShTreeViewBehaviour* behaviour,
WinTCShBrowser* browser WinTCShBrowser* browser
@@ -315,6 +320,98 @@ WinTCShTreeViewBehaviour* wintc_sh_tree_view_behaviour_new(
// //
// PRIVATE FUNCTIONS // 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( static void wintc_sh_tree_view_behaviour_update_view(
WinTCShTreeViewBehaviour* behaviour, WinTCShTreeViewBehaviour* behaviour,
WinTCShBrowser* browser WinTCShBrowser* browser
@@ -607,7 +704,18 @@ static void wintc_sh_tree_view_behaviour_update_view(
G_CONNECT_DEFAULT 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 // Delete the view if needed
@@ -666,7 +774,7 @@ static void on_browser_load_changed(
WinTCShTreeViewBehaviour* behaviour = WinTCShTreeViewBehaviour* behaviour =
WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data); WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data);
if (load_event != WINTC_SH_BROWSER_LOAD_STARTED) if (load_event != WINTC_SH_BROWSER_LOAD_FINISHED)
{ {
return; return;
} }
@@ -683,9 +791,6 @@ static void on_view_items_added(
WinTCShTreeViewBehaviour* behaviour = WinTCShTreeViewBehaviour* behaviour =
WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data); WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data);
GtkTreeIter parent;
GtkTreeIter child;
WINTC_LOG_DEBUG( WINTC_LOG_DEBUG(
"shell: tree - items added to %p", "shell: tree - items added to %p",
GUINT_TO_POINTER(wintc_ishext_view_get_unique_hash(view)) GUINT_TO_POINTER(wintc_ishext_view_get_unique_hash(view))
@@ -693,6 +798,7 @@ static void on_view_items_added(
// Locate the parent node // Locate the parent node
// //
GtkTreeIter parent;
GtkTreeRowReference* row_ref; GtkTreeRowReference* row_ref;
GtkTreePath* tree_path; GtkTreePath* tree_path;
@@ -718,82 +824,13 @@ static void on_view_items_added(
gtk_tree_path_free(tree_path); 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; wintc_sh_tree_view_behaviour_node_add_items(
behaviour,
for (GList* iter = update->data; iter; iter = iter->next) &parent,
{ update->data
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);
}
} }
static void on_view_items_removed( 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( static const gchar* wintc_sh_view_cpl_get_icon_name(
WinTCIShextView* view WinTCIShextView* view
); );
static GList* wintc_sh_view_cpl_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_cpl_get_operations_for_item( static GMenuModel* wintc_sh_view_cpl_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash 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->compare_items = wintc_sh_view_cpl_compare_items;
iface->get_display_name = wintc_sh_view_cpl_get_display_name; iface->get_display_name = wintc_sh_view_cpl_get_display_name;
iface->get_icon_name = wintc_sh_view_cpl_get_icon_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_item = wintc_sh_view_cpl_get_operations_for_item;
iface->get_operations_for_view = wintc_sh_view_cpl_get_operations_for_view; iface->get_operations_for_view = wintc_sh_view_cpl_get_operations_for_view;
iface->get_parent_path = wintc_sh_view_cpl_get_parent_path; 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"; 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( static GMenuModel* wintc_sh_view_cpl_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash) 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( static const gchar* wintc_sh_view_desktop_get_icon_name(
WinTCIShextView* view WinTCIShextView* view
); );
static GList* wintc_sh_view_desktop_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_desktop_get_operations_for_item( static GMenuModel* wintc_sh_view_desktop_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash 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->compare_items = wintc_sh_view_desktop_compare_items;
iface->get_display_name = wintc_sh_view_desktop_get_display_name; iface->get_display_name = wintc_sh_view_desktop_get_display_name;
iface->get_icon_name = wintc_sh_view_desktop_get_icon_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 = iface->get_operations_for_item =
wintc_sh_view_desktop_get_operations_for_item; wintc_sh_view_desktop_get_operations_for_item;
iface->get_operations_for_view = iface->get_operations_for_view =
@@ -303,6 +307,13 @@ static const gchar* wintc_sh_view_desktop_get_icon_name(
return "user-desktop"; 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( static GMenuModel* wintc_sh_view_desktop_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash) 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( static const gchar* wintc_sh_view_drives_get_icon_name(
WinTCIShextView* view WinTCIShextView* view
); );
static GList* wintc_sh_view_drives_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_drives_get_operations_for_item( static GMenuModel* wintc_sh_view_drives_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash 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->compare_items = wintc_sh_view_drives_compare_items;
iface->get_display_name = wintc_sh_view_drives_get_display_name; iface->get_display_name = wintc_sh_view_drives_get_display_name;
iface->get_icon_name = wintc_sh_view_drives_get_icon_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 = iface->get_operations_for_item =
wintc_sh_view_drives_get_operations_for_item; wintc_sh_view_drives_get_operations_for_item;
iface->get_operations_for_view = iface->get_operations_for_view =
@@ -274,6 +278,13 @@ static const gchar* wintc_sh_view_drives_get_icon_name(
return "computer"; 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( static GMenuModel* wintc_sh_view_drives_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash) 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( static const gchar* wintc_sh_view_fs_get_icon_name(
WinTCIShextView* view WinTCIShextView* view
); );
static GList* wintc_sh_view_fs_get_items(
WinTCIShextView* view
);
static GMenuModel* wintc_sh_view_fs_get_operations_for_item( static GMenuModel* wintc_sh_view_fs_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash guint item_hash
@@ -195,8 +198,9 @@ struct _WinTCShViewFS
// FS state // FS state
// //
gchar* parent_path; gboolean is_new; // Track if this view has ever been refreshed before
gchar* path; gchar* parent_path;
gchar* path;
GFileMonitor* fs_monitor; GFileMonitor* fs_monitor;
GHashTable* fs_map_entries; GHashTable* fs_map_entries;
@@ -266,6 +270,7 @@ static void wintc_sh_view_fs_init(
WinTCShViewFS* self WinTCShViewFS* self
) )
{ {
self->is_new = TRUE;
self->fs_clipboard = wintc_sh_fs_clipboard_new(); 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->compare_items = wintc_sh_view_fs_compare_items;
iface->get_display_name = wintc_sh_view_fs_get_display_name; iface->get_display_name = wintc_sh_view_fs_get_display_name;
iface->get_icon_name = wintc_sh_view_fs_get_icon_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_item = wintc_sh_view_fs_get_operations_for_item;
iface->get_operations_for_view = wintc_sh_view_fs_get_operations_for_view; iface->get_operations_for_view = wintc_sh_view_fs_get_operations_for_view;
iface->get_parent_path = wintc_sh_view_fs_get_parent_path; 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( 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"; 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( static GMenuModel* wintc_sh_view_fs_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash guint item_hash
@@ -665,6 +693,8 @@ static void wintc_sh_view_fs_refresh_items(
WINTC_LOG_DEBUG("%s", "shell: refresh fs view"); WINTC_LOG_DEBUG("%s", "shell: refresh fs view");
view_fs->is_new = FALSE;
_wintc_ishext_view_refreshing(view); _wintc_ishext_view_refreshing(view);
if (view_fs->fs_map_entries) if (view_fs->fs_map_entries)

View File

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

View File

@@ -139,6 +139,16 @@ const gchar* wintc_ishext_view_get_icon_name(
return iface->get_icon_name(view); 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( GMenuModel* wintc_ishext_view_get_operations_for_item(
WinTCIShextView* view, WinTCIShextView* view,
guint item_hash guint item_hash