Enhancement: Fixes #380, shell - file system watcher for FS view

This commit is contained in:
Rory Fewell
2024-11-29 22:01:10 +00:00
parent 329cc5224b
commit 4e0711a9f7
17 changed files with 632 additions and 275 deletions

View File

@@ -4,7 +4,7 @@
// //
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
GSList* wintc_sh_fs_get_names_as_list( GList* wintc_sh_fs_get_names_as_list(
const gchar* path, const gchar* path,
gboolean full_names, gboolean full_names,
GFileTest test, GFileTest test,

View File

@@ -6,7 +6,7 @@
// //
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
GSList* wintc_sh_fs_get_names_as_list( GList* wintc_sh_fs_get_names_as_list(
const gchar* path, const gchar* path,
gboolean full_names, gboolean full_names,
GFileTest test, GFileTest test,
@@ -17,7 +17,7 @@ GSList* wintc_sh_fs_get_names_as_list(
GDir* dir; GDir* dir;
const gchar* dir_entry = NULL; const gchar* dir_entry = NULL;
GSList* dirs_to_enum = NULL; GSList* dirs_to_enum = NULL;
GSList* entries = NULL; GList* entries = NULL;
GSList* iter = NULL; GSList* iter = NULL;
WINTC_SAFE_REF_CLEAR(error); WINTC_SAFE_REF_CLEAR(error);
@@ -42,7 +42,7 @@ GSList* wintc_sh_fs_get_names_as_list(
if (!dir) if (!dir)
{ {
g_slist_free_full(dirs_to_enum, g_free); g_slist_free_full(dirs_to_enum, g_free);
g_slist_free_full(entries, g_free); g_list_free_full(entries, g_free);
return NULL; return NULL;
} }
@@ -71,7 +71,7 @@ GSList* wintc_sh_fs_get_names_as_list(
if (!test || g_file_test(full_path, test)) if (!test || g_file_test(full_path, test))
{ {
entries = entries =
g_slist_append( g_list_append(
entries, entries,
g_strdup(full_names ? full_path : dir_entry) g_strdup(full_names ? full_path : dir_entry)
); );

View File

@@ -44,7 +44,7 @@ WinTCShBrowser* wintc_sh_browser_new(
gboolean wintc_sh_browser_activate_item( gboolean wintc_sh_browser_activate_item(
WinTCShBrowser* browser, WinTCShBrowser* browser,
WinTCShextViewItem* item, guint item_hash,
GError** error GError** error
); );

View File

@@ -17,7 +17,7 @@ typedef struct _WinTCShCplApplet
// //
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
GSList* wintc_sh_cpl_applet_get_all(void); GList* wintc_sh_cpl_applet_get_all(void);
gboolean wintc_sh_cpl_applet_is_executable( gboolean wintc_sh_cpl_applet_is_executable(
WinTCShCplApplet* applet WinTCShCplApplet* applet

View File

@@ -22,9 +22,9 @@ enum
enum enum
{ {
COLUMN_VIEWITEM = 0, COLUMN_ICON = 0,
COLUMN_ICON, COLUMN_ENTRY_NAME,
COLUMN_DISPLAY_NAME, COLUMN_VIEW_HASH,
N_COLUMNS N_COLUMNS
}; };
@@ -53,14 +53,14 @@ static void wintc_sh_browser_set_property(
); );
static void on_current_view_items_added( static void on_current_view_items_added(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItemsAddedData* event_data, WinTCShextViewItemsUpdate* update,
gpointer user_data gpointer user_data
); );
static void on_current_view_items_removed( static void on_current_view_items_removed(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem** items, WinTCShextViewItemsUpdate* update,
gpointer user_data gpointer user_data
); );
static void on_current_view_refreshing( static void on_current_view_refreshing(
WinTCIShextView* view, WinTCIShextView* view,
@@ -85,6 +85,10 @@ struct _WinTCShBrowser
// //
WinTCIShextView* current_view; WinTCIShextView* current_view;
GtkListStore* view_model; GtkListStore* view_model;
gulong sigid_items_added;
gulong sigid_items_removed;
gulong sigid_refreshing;
}; };
// //
@@ -142,9 +146,9 @@ static void wintc_sh_browser_init(
self->view_model = self->view_model =
gtk_list_store_new( gtk_list_store_new(
3, 3,
G_TYPE_POINTER,
GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF,
G_TYPE_STRING G_TYPE_STRING,
G_TYPE_UINT
); );
} }
@@ -218,7 +222,7 @@ WinTCShBrowser* wintc_sh_browser_new(
gboolean wintc_sh_browser_activate_item( gboolean wintc_sh_browser_activate_item(
WinTCShBrowser* browser, WinTCShBrowser* browser,
WinTCShextViewItem* item, guint item_hash,
GError** error GError** error
) )
{ {
@@ -238,7 +242,7 @@ gboolean wintc_sh_browser_activate_item(
if ( if (
!wintc_ishext_view_activate_item( !wintc_ishext_view_activate_item(
browser->current_view, browser->current_view,
item, item_hash,
&path_info, &path_info,
&local_error &local_error
) )
@@ -388,29 +392,54 @@ gboolean wintc_sh_browser_set_location(
return FALSE; return FALSE;
} }
// Disconnect from old view
//
if (browser->current_view)
{
g_signal_handler_disconnect(
browser->current_view,
browser->sigid_items_added
);
g_signal_handler_disconnect(
browser->current_view,
browser->sigid_items_removed
);
g_signal_handler_disconnect(
browser->current_view,
browser->sigid_refreshing
);
g_clear_object(&(browser->current_view));
}
// Update the view // Update the view
// //
g_clear_object(&(browser->current_view));
browser->current_view = new_view; browser->current_view = new_view;
g_signal_connect( browser->sigid_items_added =
browser->current_view, g_signal_connect_object(
"items-added", browser->current_view,
G_CALLBACK(on_current_view_items_added), "items-added",
browser G_CALLBACK(on_current_view_items_added),
); browser,
g_signal_connect( G_CONNECT_DEFAULT
browser->current_view, );
"items-removed", browser->sigid_items_removed =
G_CALLBACK(on_current_view_items_removed), g_signal_connect_object(
browser browser->current_view,
); "items-removed",
g_signal_connect( G_CALLBACK(on_current_view_items_removed),
browser->current_view, browser,
"refreshing", G_CONNECT_DEFAULT
G_CALLBACK(on_current_view_refreshing), );
browser browser->sigid_refreshing =
); g_signal_connect_object(
browser->current_view,
"refreshing",
G_CALLBACK(on_current_view_refreshing),
browser,
G_CONNECT_DEFAULT
);
// Notify that we're loading... // Notify that we're loading...
// //
@@ -433,15 +462,15 @@ gboolean wintc_sh_browser_set_location(
// //
static void on_current_view_items_added( static void on_current_view_items_added(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItemsAddedData* event_data, WinTCShextViewItemsUpdate* update,
gpointer user_data gpointer user_data
) )
{ {
WinTCShBrowser* browser = WINTC_SH_BROWSER(user_data); WinTCShBrowser* browser = WINTC_SH_BROWSER(user_data);
for (int i = 0; i < event_data->num_items; i++) for (GList* iter = update->data; iter; iter = iter->next)
{ {
WinTCShextViewItem* item = &(event_data->items[i]); WinTCShextViewItem* item = iter->data;
// Load icon // Load icon
// //
@@ -462,16 +491,16 @@ static void on_current_view_items_added(
gtk_list_store_set( gtk_list_store_set(
browser->view_model, browser->view_model,
&iter, &iter,
COLUMN_VIEWITEM, item, COLUMN_ICON, icon,
COLUMN_ICON, icon, COLUMN_ENTRY_NAME, item->display_name,
COLUMN_DISPLAY_NAME, item->display_name, COLUMN_VIEW_HASH, item->hash,
-1 -1
); );
} }
// Check if done // Check if done
// //
if (event_data->done) if (update->done)
{ {
WINTC_LOG_DEBUG("%s", "shell: current view finished refreshing"); WINTC_LOG_DEBUG("%s", "shell: current view finished refreshing");
@@ -486,18 +515,55 @@ static void on_current_view_items_added(
static void on_current_view_items_removed( static void on_current_view_items_removed(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem** items, WinTCShextViewItemsUpdate* update,
WINTC_UNUSED(gpointer user_data) gpointer user_data
) )
{ {
WinTCShextViewItem* p_item = items[0]; WinTCShBrowser* browser = WINTC_SH_BROWSER(user_data);
// FIXME: Proper implementation later, just print the names for now // FIXME: Inefficient linear search - improve later
// //
while (p_item) GtkTreeIter iter;
gboolean searching;
for (GList* upd_iter = update->data; upd_iter; upd_iter = upd_iter->next)
{ {
g_message("Item removed: %s", p_item->display_name); guint item_hash = GPOINTER_TO_UINT(upd_iter->data);
p_item++;
searching =
gtk_tree_model_iter_children(
GTK_TREE_MODEL(browser->view_model),
&iter,
NULL
);
while (searching)
{
guint hash;
gtk_tree_model_get(
GTK_TREE_MODEL(browser->view_model),
&iter,
COLUMN_VIEW_HASH, &hash,
-1
);
if (item_hash == hash)
{
gtk_list_store_remove(
browser->view_model,
&iter
);
break;
}
searching =
gtk_tree_model_iter_next(
GTK_TREE_MODEL(browser->view_model),
&iter
);
}
} }
} }

View File

@@ -18,9 +18,9 @@ static const gchar* S_CPL_KEY_ICON_NAME = "Icon";
// //
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
GSList* wintc_sh_cpl_applet_get_all(void) GList* wintc_sh_cpl_applet_get_all(void)
{ {
GSList* entries = GList* entries =
wintc_sh_fs_get_names_as_list( wintc_sh_fs_get_names_as_list(
S_CPL_ENTRIES_DIR, S_CPL_ENTRIES_DIR,
TRUE, TRUE,
@@ -35,12 +35,12 @@ GSList* wintc_sh_cpl_applet_get_all(void)
} }
WinTCShCplApplet* applet; WinTCShCplApplet* applet;
GSList* cpls = NULL; GList* cpls = NULL;
GError* error = NULL; GError* error = NULL;
GKeyFile* key_file = g_key_file_new(); GKeyFile* key_file = g_key_file_new();
gboolean success = TRUE; gboolean success = TRUE;
for (GSList* iter = entries; iter; iter = iter->next) for (GList* iter = entries; iter; iter = iter->next)
{ {
WINTC_LOG_DEBUG("shell: cpl parse %s", (gchar*) iter->data); WINTC_LOG_DEBUG("shell: cpl parse %s", (gchar*) iter->data);
@@ -107,7 +107,7 @@ GSList* wintc_sh_cpl_applet_get_all(void)
if (success) if (success)
{ {
cpls = g_slist_append(cpls, applet); cpls = g_list_append(cpls, applet);
} }
else else
{ {
@@ -119,7 +119,7 @@ GSList* wintc_sh_cpl_applet_get_all(void)
success = TRUE; success = TRUE;
} }
g_slist_free_full(entries, g_free); g_list_free_full(entries, g_free);
g_key_file_free(key_file); g_key_file_free(key_file);
return cpls; return cpls;

View File

@@ -123,11 +123,11 @@ static void wintc_sh_icon_view_behaviour_constructed(
); );
gtk_icon_view_set_pixbuf_column( gtk_icon_view_set_pixbuf_column(
GTK_ICON_VIEW(behaviour->icon_view), GTK_ICON_VIEW(behaviour->icon_view),
1 0
); );
gtk_icon_view_set_text_column( gtk_icon_view_set_text_column(
GTK_ICON_VIEW(behaviour->icon_view), GTK_ICON_VIEW(behaviour->icon_view),
2 1
); );
// Attach signals // Attach signals
@@ -218,19 +218,19 @@ static void on_icon_view_item_activated(
if (gtk_tree_model_get_iter(model, &iter, path)) if (gtk_tree_model_get_iter(model, &iter, path))
{ {
GError* error = NULL; GError* error = NULL;
WinTCShextViewItem* item = NULL; guint hash;
gtk_tree_model_get( gtk_tree_model_get(
model, model,
&iter, &iter,
0, &item, // FIXME: Guess we should make the columns public 2, &hash, // FIXME: Guess we should make the columns public
-1 -1
); );
wintc_sh_browser_activate_item( wintc_sh_browser_activate_item(
behaviour->browser, behaviour->browser,
item, hash,
&error &error
); );

View File

@@ -16,10 +16,10 @@ enum
enum enum
{ {
COL_ICON_NAME = 0, COLUMN_ICON_NAME = 0,
COL_ENTRY_NAME, COLUMN_ENTRY_NAME,
COL_VIEW_HASH, COLUMN_VIEW_HASH,
NUM_COLS N_COLUMNS
}; };
// //
@@ -54,9 +54,14 @@ static void on_browser_load_changed(
); );
static void on_view_items_added( static void on_view_items_added(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItemsAddedData* items_data, WinTCShextViewItemsUpdate* update,
gpointer user_data gpointer user_data
);
static void on_view_items_removed(
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
gpointer user_data
); );
// //
@@ -216,7 +221,7 @@ static void wintc_sh_tree_view_behaviour_constructed(
new_column, new_column,
new_cell, new_cell,
"icon-name", "icon-name",
COL_ICON_NAME COLUMN_ICON_NAME
); );
new_cell = gtk_cell_renderer_text_new(); new_cell = gtk_cell_renderer_text_new();
@@ -226,7 +231,7 @@ static void wintc_sh_tree_view_behaviour_constructed(
new_column, new_column,
new_cell, new_cell,
"text", "text",
COL_ENTRY_NAME COLUMN_ENTRY_NAME
); );
gtk_tree_view_append_column( gtk_tree_view_append_column(
@@ -493,9 +498,9 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set( gtk_tree_store_set(
behaviour->tree_model, behaviour->tree_model,
&next, &next,
COL_ICON_NAME, wintc_ishext_view_get_icon_name(view), COLUMN_ICON_NAME, wintc_ishext_view_get_icon_name(view),
COL_ENTRY_NAME, wintc_ishext_view_get_display_name(view), COLUMN_ENTRY_NAME, wintc_ishext_view_get_display_name(view),
COL_VIEW_HASH, hash, COLUMN_VIEW_HASH, hash,
-1 -1
); );
@@ -549,9 +554,9 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set( gtk_tree_store_set(
behaviour->tree_model, behaviour->tree_model,
&next, &next,
COL_ICON_NAME, wintc_ishext_view_get_icon_name(next_view), COLUMN_ICON_NAME, wintc_ishext_view_get_icon_name(next_view),
COL_ENTRY_NAME, wintc_ishext_view_get_display_name(next_view), COLUMN_ENTRY_NAME, wintc_ishext_view_get_display_name(next_view),
COL_VIEW_HASH, hash, COLUMN_VIEW_HASH, hash,
-1 -1
); );
@@ -584,6 +589,13 @@ static void wintc_sh_tree_view_behaviour_update_view(
behaviour, behaviour,
G_CONNECT_DEFAULT G_CONNECT_DEFAULT
); );
g_signal_connect_object(
view,
"items-removed",
G_CALLBACK(on_view_items_removed),
behaviour,
G_CONNECT_DEFAULT
);
wintc_ishext_view_refresh_items(view); wintc_ishext_view_refresh_items(view);
} }
@@ -634,9 +646,9 @@ static void on_browser_load_changed(
} }
static void on_view_items_added( static void on_view_items_added(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItemsAddedData* items_data, WinTCShextViewItemsUpdate* update,
gpointer user_data gpointer user_data
) )
{ {
WinTCShTreeViewBehaviour* behaviour = WinTCShTreeViewBehaviour* behaviour =
@@ -674,9 +686,9 @@ static void on_view_items_added(
// //
WinTCShextViewItem* view_item; WinTCShextViewItem* view_item;
for (gint i = 0; i < items_data->num_items; i++) for (GList* iter = update->data; iter; iter = iter->next)
{ {
view_item = &(items_data->items[i]); view_item = iter->data;
// Skip leaf nodes and nodes that already exist // Skip leaf nodes and nodes that already exist
// //
@@ -704,9 +716,9 @@ static void on_view_items_added(
gtk_tree_store_set( gtk_tree_store_set(
behaviour->tree_model, behaviour->tree_model,
&child, &child,
COL_ICON_NAME, view_item->icon_name, COLUMN_ICON_NAME, view_item->icon_name,
COL_ENTRY_NAME, view_item->display_name, COLUMN_ENTRY_NAME, view_item->display_name,
COL_VIEW_HASH, view_item->hash, COLUMN_VIEW_HASH, view_item->hash,
-1 -1
); );
@@ -720,3 +732,53 @@ static void on_view_items_added(
); );
} }
} }
static void on_view_items_removed(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItemsUpdate* update,
gpointer user_data
)
{
WinTCShTreeViewBehaviour* behaviour =
WINTC_SH_TREE_VIEW_BEHAVIOUR(user_data);
// Track down and bin via the maps
//
GtkTreeIter iter;
for (GList* upd_iter = update->data; upd_iter; upd_iter = upd_iter->next)
{
guint item_hash = GPOINTER_TO_UINT(upd_iter->data);
const gchar* iter_path =
g_hash_table_lookup(
behaviour->map_hash_to_iter,
GUINT_TO_POINTER(item_hash)
);
if (!iter_path)
{
continue;
}
gtk_tree_model_get_iter_from_string(
GTK_TREE_MODEL(behaviour->tree_model),
&iter,
iter_path
);
gtk_tree_store_remove(
behaviour->tree_model,
&iter
);
g_hash_table_remove(
behaviour->map_iter_to_view,
iter_path
);
g_hash_table_remove(
behaviour->map_hash_to_iter,
GUINT_TO_POINTER(item_hash)
);
}
}

View File

@@ -34,7 +34,7 @@ static void wintc_sh_view_cpl_get_property(
static gboolean wintc_sh_view_cpl_activate_item( static gboolean wintc_sh_view_cpl_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -83,8 +83,8 @@ struct _WinTCShViewCpl
// State // State
// //
GSList* list_cpls; GList* cpls;
GArray* view_items; GHashTable* map_items;
}; };
// //
@@ -117,11 +117,8 @@ static void wintc_sh_view_cpl_class_init(
} }
static void wintc_sh_view_cpl_init( static void wintc_sh_view_cpl_init(
WinTCShViewCpl* self WINTC_UNUSED(WinTCShViewCpl* self)
) ) {}
{
self->view_items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
}
static void wintc_sh_view_cpl_ishext_view_interface_init( static void wintc_sh_view_cpl_ishext_view_interface_init(
WinTCIShextViewInterface* iface WinTCIShextViewInterface* iface
@@ -148,11 +145,17 @@ static void wintc_sh_view_cpl_finalize(
{ {
WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(object); WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(object);
g_clear_slist( g_clear_list(
&(view_cpl->list_cpls), &(view_cpl->cpls),
(GDestroyNotify) wintc_sh_cpl_applet_free (GDestroyNotify) wintc_sh_cpl_applet_free
); );
g_array_free(view_cpl->view_items, TRUE);
if (view_cpl->map_items)
{
g_hash_table_destroy(
g_steal_pointer(&(view_cpl->map_items))
);
}
(G_OBJECT_CLASS(wintc_sh_view_cpl_parent_class))->finalize(object); (G_OBJECT_CLASS(wintc_sh_view_cpl_parent_class))->finalize(object);
} }
@@ -185,13 +188,23 @@ static void wintc_sh_view_cpl_get_property(
// INTERFACE METHODS (WinTCIShextView) // INTERFACE METHODS (WinTCIShextView)
// //
static gboolean wintc_sh_view_cpl_activate_item( static gboolean wintc_sh_view_cpl_activate_item(
WINTC_UNUSED(WinTCIShextView* view), WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
{ {
WinTCShCplApplet* applet = (WinTCShCplApplet*) item->priv; WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(view);
WinTCShCplApplet* applet;
WinTCShextViewItem* item;
item = (WinTCShextViewItem*)
g_hash_table_lookup(
view_cpl->map_items,
GUINT_TO_POINTER(item_hash)
);
applet = (WinTCShCplApplet*) item->priv;
if (wintc_sh_cpl_applet_is_executable(applet)) if (wintc_sh_cpl_applet_is_executable(applet))
{ {
@@ -211,37 +224,32 @@ static void wintc_sh_view_cpl_refresh_items(
_wintc_ishext_view_refreshing(view); _wintc_ishext_view_refreshing(view);
// Refresh list g_clear_list(
// &(view_cpl->cpls),
g_clear_slist(
&(view_cpl->list_cpls),
(GDestroyNotify) wintc_sh_cpl_applet_free (GDestroyNotify) wintc_sh_cpl_applet_free
); );
view_cpl->list_cpls = wintc_sh_cpl_applet_get_all(); if (view_cpl->map_items)
{
g_array_remove_range( g_hash_table_destroy(
view_cpl->view_items, g_steal_pointer(&(view_cpl->map_items))
0, );
view_cpl->view_items->len }
);
g_array_set_size(
view_cpl->view_items,
g_slist_length(view_cpl->list_cpls)
);
// Create view items // Create view items
// //
gint i = 0; view_cpl->cpls = wintc_sh_cpl_applet_get_all();
view_cpl->map_items = g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) g_free
);
for (GSList* iter = view_cpl->list_cpls; iter; iter = iter->next) for (GList* iter = view_cpl->cpls; iter; iter = iter->next)
{ {
WinTCShCplApplet* applet = (WinTCShCplApplet*) iter->data; WinTCShCplApplet* applet = (WinTCShCplApplet*) iter->data;
WinTCShextViewItem* view_item = &g_array_index( WinTCShextViewItem* view_item = g_new(WinTCShextViewItem, 1);
view_cpl->view_items,
WinTCShextViewItem,
i
);
view_item->display_name = applet->display_name; view_item->display_name = applet->display_name;
view_item->icon_name = applet->icon_name ? view_item->icon_name = applet->icon_name ?
@@ -251,22 +259,25 @@ static void wintc_sh_view_cpl_refresh_items(
view_item->hash = g_str_hash(applet->exec); view_item->hash = g_str_hash(applet->exec);
view_item->priv = applet; view_item->priv = applet;
i++; g_hash_table_insert(
view_cpl->map_items,
GUINT_TO_POINTER(view_item->hash),
view_item
);
} }
// Provide update // Provide update
// //
WinTCShextViewItemsAddedData update = { 0 }; WinTCShextViewItemsUpdate update = { 0 };
update.items = &g_array_index( GList* items = g_hash_table_get_values(view_cpl->map_items);
view_cpl->view_items,
WinTCShextViewItem, update.data = items;
0 update.done = TRUE;
);
update.num_items = view_cpl->view_items->len;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update); _wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_sh_view_cpl_get_actions_for_item( static void wintc_sh_view_cpl_get_actions_for_item(

View File

@@ -17,6 +17,10 @@ enum
// STATIC DATA // STATIC DATA
// //
// FIXME: Temp
//
static GHashTable* s_desktop_map = NULL;
// FIXME: LAZY AGAIN! Use shlang!!!!!! Temporary as well cos the user can // FIXME: LAZY AGAIN! Use shlang!!!!!! Temporary as well cos the user can
// toggle which items are present // toggle which items are present
// //
@@ -67,7 +71,7 @@ static void wintc_sh_view_desktop_get_property(
static gboolean wintc_sh_view_desktop_activate_item( static gboolean wintc_sh_view_desktop_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -132,6 +136,8 @@ static void wintc_sh_view_desktop_class_init(
WinTCShViewDesktopClass* klass WinTCShViewDesktopClass* klass
) )
{ {
s_desktop_map = g_hash_table_new(g_direct_hash, g_direct_equal);
// Assign GUID paths to built-in desktop items - kind of rubbish but // Assign GUID paths to built-in desktop items - kind of rubbish but
// whatever // whatever
// //
@@ -155,6 +161,12 @@ static void wintc_sh_view_desktop_class_init(
g_free(temp); g_free(temp);
} }
g_hash_table_insert(
s_desktop_map,
GUINT_TO_POINTER(s_desktop_items[i].hash),
&(s_desktop_items[i])
);
} }
// GObject initialization // GObject initialization
@@ -222,22 +234,27 @@ static void wintc_sh_view_desktop_get_property(
// //
static gboolean wintc_sh_view_desktop_activate_item( static gboolean wintc_sh_view_desktop_activate_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
{ {
WINTC_SAFE_REF_CLEAR(error); WINTC_SAFE_REF_CLEAR(error);
gchar* target = (gchar*) item->priv; WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
s_desktop_map,
GUINT_TO_POINTER(item_hash)
);
if (!target) if (!(item->priv))
{ {
g_critical("%s", "shell: desk view can't activate item, no target"); g_critical("%s", "shell: desk view can't activate item, no target");
return FALSE; return FALSE;
} }
path_info->base_path = g_strdup(target); path_info->base_path = g_strdup(item->priv);
return TRUE; return TRUE;
} }
@@ -253,13 +270,16 @@ static void wintc_sh_view_desktop_refresh_items(
// Just emit the default items for now // Just emit the default items for now
// TODO: Should aggregate with user desktop files // TODO: Should aggregate with user desktop files
// //
WinTCShextViewItemsAddedData items = { WinTCShextViewItemsUpdate update = { 0 };
&(s_desktop_items[0]),
G_N_ELEMENTS(s_desktop_items),
TRUE
};
_wintc_ishext_view_items_added(view, &items); GList* items = g_hash_table_get_values(s_desktop_map);
update.data = items;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_sh_view_desktop_get_actions_for_item( static void wintc_sh_view_desktop_get_actions_for_item(

View File

@@ -17,6 +17,10 @@ enum
// STATIC DATA // STATIC DATA
// //
// FIXME: Temp
//
static GHashTable* s_drives_map = NULL;
// FIXME: Temporary - only item is the drive root atm // FIXME: Temporary - only item is the drive root atm
// //
static WinTCShextViewItem s_temp_items[] = { static WinTCShextViewItem s_temp_items[] = {
@@ -40,7 +44,7 @@ static void wintc_sh_view_drives_get_property(
static gboolean wintc_sh_view_drives_activate_item( static gboolean wintc_sh_view_drives_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_data,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -105,6 +109,8 @@ static void wintc_sh_view_drives_class_init(
WinTCShViewDrivesClass* klass WinTCShViewDrivesClass* klass
) )
{ {
s_drives_map = g_hash_table_new(g_direct_hash, g_direct_equal);
// TEMP: Assign CPL view path // TEMP: Assign CPL view path
// //
s_temp_items[1].priv = wintc_sh_path_for_guid(WINTC_SH_GUID_CPL); s_temp_items[1].priv = wintc_sh_path_for_guid(WINTC_SH_GUID_CPL);
@@ -114,6 +120,19 @@ static void wintc_sh_view_drives_class_init(
s_temp_items[0].hash = g_str_hash("/"); s_temp_items[0].hash = g_str_hash("/");
s_temp_items[1].hash = g_str_hash(s_temp_items[1].priv); s_temp_items[1].hash = g_str_hash(s_temp_items[1].priv);
// TEMP: Prepend items
//
g_hash_table_insert(
s_drives_map,
GUINT_TO_POINTER(s_temp_items[0].hash),
&(s_temp_items[0])
);
g_hash_table_insert(
s_drives_map,
GUINT_TO_POINTER(s_temp_items[1].hash),
&(s_temp_items[1])
);
// GObject initialisation // GObject initialisation
// //
GObjectClass* object_class = G_OBJECT_CLASS(klass); GObjectClass* object_class = G_OBJECT_CLASS(klass);
@@ -179,13 +198,20 @@ static void wintc_sh_view_drives_get_property(
// //
static gboolean wintc_sh_view_drives_activate_item( static gboolean wintc_sh_view_drives_activate_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
{ {
WINTC_SAFE_REF_CLEAR(error); WINTC_SAFE_REF_CLEAR(error);
WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
s_drives_map,
GUINT_TO_POINTER(item_hash)
);
// TODO: Handle properly, we're using temp items for now // TODO: Handle properly, we're using temp items for now
// //
path_info->base_path = g_strdup(item->priv); path_info->base_path = g_strdup(item->priv);
@@ -204,13 +230,16 @@ static void wintc_sh_view_drives_refresh_items(
// Emit only the root '/' for now // Emit only the root '/' for now
// TODO: Basically everything in My Computer! // TODO: Basically everything in My Computer!
// //
WinTCShextViewItemsAddedData items = { WinTCShextViewItemsUpdate update = { 0 };
&(s_temp_items[0]),
G_N_ELEMENTS(s_temp_items),
TRUE
};
_wintc_ishext_view_items_added(view, &items); GList* items = g_hash_table_get_values(s_drives_map);
update.data = items;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_sh_view_drives_get_actions_for_item( static void wintc_sh_view_drives_get_actions_for_item(

View File

@@ -1,3 +1,4 @@
#include <gio/gio.h>
#include <glib.h> #include <glib.h>
#include <wintc/comgtk.h> #include <wintc/comgtk.h>
#include <wintc/exec.h> #include <wintc/exec.h>
@@ -44,7 +45,7 @@ static void wintc_sh_view_fs_set_property(
static gboolean wintc_sh_view_fs_activate_item( static gboolean wintc_sh_view_fs_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -83,6 +84,14 @@ static void clear_view_item(
WinTCShextViewItem* item WinTCShextViewItem* item
); );
static void on_file_monitor_changed(
GFileMonitor* self,
GFile* file,
GFile* other_file,
GFileMonitorEvent event_type,
gpointer user_data
);
// //
// GLIB OOP/CLASS INSTANCE DEFINITIONS // GLIB OOP/CLASS INSTANCE DEFINITIONS
// //
@@ -97,10 +106,12 @@ struct _WinTCShViewFS
// FS state // FS state
// //
GArray* items;
gchar* parent_path; gchar* parent_path;
gchar* path; gchar* path;
GFileMonitor* fs_monitor;
GHashTable* fs_map_entries;
WinTCShextHost* shext_host; WinTCShextHost* shext_host;
}; };
@@ -159,16 +170,8 @@ static void wintc_sh_view_fs_class_init(
} }
static void wintc_sh_view_fs_init( static void wintc_sh_view_fs_init(
WinTCShViewFS* self WINTC_UNUSED(WinTCShViewFS* self)
) ) {}
{
self->items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
g_array_set_clear_func(
self->items,
(GDestroyNotify) clear_view_item
);
}
static void wintc_sh_view_fs_ishext_view_interface_init( static void wintc_sh_view_fs_ishext_view_interface_init(
WinTCIShextViewInterface* iface WinTCIShextViewInterface* iface
@@ -193,9 +196,10 @@ static void wintc_sh_view_fs_dispose(
GObject* object GObject* object
) )
{ {
WinTCShViewFS* view = WINTC_SH_VIEW_FS(object); WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(object);
g_clear_object(&(view->shext_host)); g_clear_object(&(view_fs->fs_monitor));
g_clear_object(&(view_fs->shext_host));
(G_OBJECT_CLASS(wintc_sh_view_fs_parent_class))->dispose(object); (G_OBJECT_CLASS(wintc_sh_view_fs_parent_class))->dispose(object);
} }
@@ -204,11 +208,17 @@ static void wintc_sh_view_fs_finalize(
GObject* object GObject* object
) )
{ {
WinTCShViewFS* view = WINTC_SH_VIEW_FS(object); WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(object);
g_array_free(view->items, TRUE); g_free(view_fs->parent_path);
g_free(view->parent_path); g_free(view_fs->path);
g_free(view->path);
if (view_fs->fs_map_entries)
{
g_hash_table_destroy(
g_steal_pointer(&(view_fs->fs_map_entries))
);
}
(G_OBJECT_CLASS(wintc_sh_view_fs_parent_class))->finalize(object); (G_OBJECT_CLASS(wintc_sh_view_fs_parent_class))->finalize(object);
} }
@@ -280,7 +290,7 @@ static void wintc_sh_view_fs_set_property(
// //
static gboolean wintc_sh_view_fs_activate_item( static gboolean wintc_sh_view_fs_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
@@ -290,6 +300,24 @@ static gboolean wintc_sh_view_fs_activate_item(
WINTC_SAFE_REF_CLEAR(error); WINTC_SAFE_REF_CLEAR(error);
// Retrieve the item itself
//
WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item_hash)
);
if (!item)
{
g_critical(
"%s",
"shell: fs - attempt to activate non-existent item"
);
return FALSE;
}
// Retrieve MIME for the item // Retrieve MIME for the item
// //
gchar* next_path = g_build_path( gchar* next_path = g_build_path(
@@ -348,9 +376,16 @@ static void wintc_sh_view_fs_refresh_items(
_wintc_ishext_view_refreshing(view); _wintc_ishext_view_refreshing(view);
if (view_fs->fs_map_entries)
{
g_hash_table_destroy(
g_steal_pointer(&(view_fs->fs_map_entries))
);
}
// FIXME: Error handling (no way of passing to caller) // FIXME: Error handling (no way of passing to caller)
// //
GSList* entries = GList* entries =
wintc_sh_fs_get_names_as_list( wintc_sh_fs_get_names_as_list(
view_fs->path, view_fs->path,
FALSE, FALSE,
@@ -359,31 +394,49 @@ static void wintc_sh_view_fs_refresh_items(
NULL NULL
); );
// Create actual array // Spawn file monitor if needed
// FIXME: list->array should probs be in comgtk //
if (!view_fs->fs_monitor)
{
GFile* this_dir = g_file_new_for_path(view_fs->path);
view_fs->fs_monitor =
g_file_monitor_directory(
this_dir,
0,
NULL,
NULL
);
if (view_fs->fs_monitor)
{
g_signal_connect(
view_fs->fs_monitor,
"changed",
G_CALLBACK(on_file_monitor_changed),
view_fs
);
}
g_object_unref(this_dir);
}
// Enumerate the entries now
// //
gchar* entry_path; gchar* entry_path;
gint i = 0;
g_array_remove_range( view_fs->fs_map_entries =
view_fs->items, g_hash_table_new_full(
0, g_direct_hash,
view_fs->items->len g_direct_equal,
); NULL,
g_array_set_size( (GDestroyNotify) clear_view_item
view_fs->items, );
g_slist_length(entries)
);
for (GSList* iter = entries; iter; iter = iter->next) for (GList* iter = entries; iter; iter = iter->next)
{ {
gboolean is_dir; gboolean is_dir;
WinTCShextViewItem* item = WinTCShextViewItem* item = g_new(WinTCShextViewItem, 1);
&g_array_index(
view_fs->items,
WinTCShextViewItem,
i
);
entry_path = entry_path =
g_build_path( g_build_path(
@@ -402,24 +455,27 @@ static void wintc_sh_view_fs_refresh_items(
g_free(entry_path); g_free(entry_path);
i++; g_hash_table_insert(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item->hash),
item
);
} }
g_slist_free(entries); g_list_free(entries);
// Provide update // Provide update
// //
WinTCShextViewItemsAddedData update = { 0 }; WinTCShextViewItemsUpdate update = { 0 };
update.items = &g_array_index( GList* items = g_hash_table_get_values(view_fs->fs_map_entries);
view_fs->items,
WinTCShextViewItem, update.data = items;
0 update.done = TRUE;
);
update.num_items = view_fs->items->len;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update); _wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_sh_view_fs_get_actions_for_item( static void wintc_sh_view_fs_get_actions_for_item(
@@ -536,5 +592,87 @@ static void clear_view_item(
WinTCShextViewItem* item WinTCShextViewItem* item
) )
{ {
g_clear_pointer(&(item->display_name), g_free); g_free(item->display_name);
g_free(item);
}
static void on_file_monitor_changed(
WINTC_UNUSED(GFileMonitor* self),
GFile* file,
WINTC_UNUSED(GFile* other_file),
GFileMonitorEvent event_type,
gpointer user_data
)
{
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(user_data);
GList* data = NULL;
gchar* file_path = NULL;
gboolean is_dir;
WinTCShextViewItem* item;
WinTCShextViewItemsUpdate update = { 0 };
switch (event_type)
{
case G_FILE_MONITOR_EVENT_CREATED:
file_path = g_file_get_path(file);
is_dir =
g_file_query_file_type(file, 0, NULL) == G_FILE_TYPE_DIRECTORY;
WINTC_LOG_DEBUG("shell: fs monitor - %s created", file_path);
item = g_new(WinTCShextViewItem, 1);
item->display_name = g_file_get_basename(file);
item->icon_name = is_dir ? "inode-directory" : "empty";
item->is_leaf = !is_dir;
item->hash = g_str_hash(file_path);
g_hash_table_insert(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item->hash),
item
);
// Issue update
//
data = g_list_prepend(data, item);
update.data = data;
update.done = TRUE;
_wintc_ishext_view_items_added(
WINTC_ISHEXT_VIEW(view_fs),
&update
);
break;
case G_FILE_MONITOR_EVENT_DELETED:
file_path = g_file_get_path(file);
WINTC_LOG_DEBUG("shell: fs monitor - %s deleted", file_path);
// Issue update
data =
g_list_prepend(
data,
GUINT_TO_POINTER(g_str_hash(file_path))
);
update.data = data;
update.done = TRUE;
_wintc_ishext_view_items_removed(
WINTC_ISHEXT_VIEW(view_fs),
&update
);
break;
default: break;
}
g_list_free(data);
g_free(file_path);
} }

View File

@@ -36,7 +36,7 @@ struct _WinTCIShextViewInterface
gboolean (*activate_item) ( gboolean (*activate_item) (
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -80,7 +80,7 @@ struct _WinTCIShextViewInterface
// //
gboolean wintc_ishext_view_activate_item( gboolean wintc_ishext_view_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -122,12 +122,12 @@ gboolean wintc_ishext_view_has_parent(
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
void _wintc_ishext_view_items_added( void _wintc_ishext_view_items_added(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItemsAddedData* items WinTCShextViewItemsUpdate* update
); );
void _wintc_ishext_view_items_removed( void _wintc_ishext_view_items_removed(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem** items WinTCShextViewItemsUpdate* update
); );
void _wintc_ishext_view_refreshing( void _wintc_ishext_view_refreshing(
WinTCIShextView* view WinTCIShextView* view

View File

@@ -17,11 +17,10 @@ typedef struct _WinTCShextViewItem
gpointer priv; gpointer priv;
} WinTCShextViewItem; } WinTCShextViewItem;
typedef struct _WinTCShextViewItemsAddedData typedef struct _WinTCShextViewItemsUpdate
{ {
WinTCShextViewItem* items; GList* data;
gint num_items; gboolean done;
gboolean done; } WinTCShextViewItemsUpdate;
} WinTCShextViewItemsAddedData;
#endif #endif

View File

@@ -91,7 +91,7 @@ static void wintc_ishext_view_default_init(
// //
gboolean wintc_ishext_view_activate_item( gboolean wintc_ishext_view_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
@@ -101,7 +101,7 @@ gboolean wintc_ishext_view_activate_item(
return iface->activate_item( return iface->activate_item(
view, view,
item, item_hash,
path_info, path_info,
error error
); );
@@ -204,28 +204,28 @@ void wintc_ishext_view_refresh_items(
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
void _wintc_ishext_view_items_added( void _wintc_ishext_view_items_added(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItemsAddedData* items WinTCShextViewItemsUpdate* update
) )
{ {
g_signal_emit( g_signal_emit(
view, view,
wintc_ishext_view_signals[SIGNAL_ITEMS_ADDED], wintc_ishext_view_signals[SIGNAL_ITEMS_ADDED],
0, 0,
items update
); );
} }
void _wintc_ishext_view_items_removed( void _wintc_ishext_view_items_removed(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem** items WinTCShextViewItemsUpdate* update
) )
{ {
g_signal_emit( g_signal_emit(
view, view,
wintc_ishext_view_signals[SIGNAL_ITEMS_REMOVED], wintc_ishext_view_signals[SIGNAL_ITEMS_REMOVED],
0, 0,
items update
); );
} }

View File

@@ -18,6 +18,10 @@ enum
// STATIC DATA // STATIC DATA
// //
// FIXME: Temp
//
static GHashTable* s_printers_map = NULL;
// FIXME: Temporary, until we display printers // FIXME: Temporary, until we display printers
// //
static WinTCShextViewItem s_temp_items[] = { static WinTCShextViewItem s_temp_items[] = {
@@ -40,7 +44,7 @@ static void wintc_cpl_view_printers_get_property(
static gboolean wintc_cpl_view_printers_activate_item( static gboolean wintc_cpl_view_printers_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -111,6 +115,15 @@ static void wintc_cpl_view_printers_class_init(
g_free(temp); g_free(temp);
s_printers_map =
g_hash_table_new(g_direct_hash, g_direct_equal);
g_hash_table_insert(
s_printers_map,
GUINT_TO_POINTER(s_temp_items[0].hash),
&(s_temp_items[0])
);
// GObject initialisation // GObject initialisation
// //
GObjectClass* object_class = G_OBJECT_CLASS(klass); GObjectClass* object_class = G_OBJECT_CLASS(klass);
@@ -176,7 +189,7 @@ static void wintc_cpl_view_printers_get_property(
// //
static gboolean wintc_cpl_view_printers_activate_item( static gboolean wintc_cpl_view_printers_activate_item(
WINTC_UNUSED(WinTCIShextView* view), WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(WinTCShextViewItem* item), WINTC_UNUSED(guint item_hash),
WINTC_UNUSED(WinTCShextPathInfo* path_info), WINTC_UNUSED(WinTCShextPathInfo* path_info),
GError** error GError** error
) )
@@ -197,13 +210,16 @@ static void wintc_cpl_view_printers_refresh_items(
// Emit the FPO printer for now // Emit the FPO printer for now
// TODO: Implement this! // TODO: Implement this!
// //
WinTCShextViewItemsAddedData items = { WinTCShextViewItemsUpdate update = { 0 };
&(s_temp_items[0]),
G_N_ELEMENTS(s_temp_items),
TRUE
};
_wintc_ishext_view_items_added(view, &items); GList* items = g_hash_table_get_values(s_printers_map);
update.data = items;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_cpl_view_printers_get_actions_for_item( static void wintc_cpl_view_printers_get_actions_for_item(

View File

@@ -41,7 +41,7 @@ static void wintc_view_zip_set_property(
static gboolean wintc_view_zip_activate_item( static gboolean wintc_view_zip_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
); );
@@ -104,10 +104,11 @@ struct _WinTCViewZip
// ZIP state // ZIP state
// //
GArray* items;
gchar* parent_path; gchar* parent_path;
gchar* rel_path; gchar* rel_path;
gchar* zip_uri; gchar* zip_uri;
GHashTable* map_items;
}; };
// //
@@ -164,16 +165,8 @@ static void wintc_view_zip_class_init(
} }
static void wintc_view_zip_init( static void wintc_view_zip_init(
WinTCViewZip* self WINTC_UNUSED(WinTCViewZip* self)
) ) {}
{
self->items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
g_array_set_clear_func(
self->items,
(GDestroyNotify) clear_view_item
);
}
static void wintc_view_zip_ishext_view_interface_init( static void wintc_view_zip_ishext_view_interface_init(
WinTCIShextViewInterface* iface WinTCIShextViewInterface* iface
@@ -200,11 +193,17 @@ static void wintc_view_zip_finalize(
{ {
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(object); WinTCViewZip* view_zip = WINTC_VIEW_ZIP(object);
g_array_free(view_zip->items, TRUE);
g_free(view_zip->parent_path); g_free(view_zip->parent_path);
g_free(view_zip->rel_path); g_free(view_zip->rel_path);
g_free(view_zip->zip_uri); g_free(view_zip->zip_uri);
if (view_zip->map_items)
{
g_hash_table_destroy(
g_steal_pointer(&(view_zip->map_items))
);
}
(G_OBJECT_CLASS(wintc_view_zip_parent_class))->finalize(object); (G_OBJECT_CLASS(wintc_view_zip_parent_class))->finalize(object);
} }
@@ -263,7 +262,7 @@ static void wintc_view_zip_set_property(
// //
static gboolean wintc_view_zip_activate_item( static gboolean wintc_view_zip_activate_item(
WinTCIShextView* view, WinTCIShextView* view,
WinTCShextViewItem* item, guint item_hash,
WinTCShextPathInfo* path_info, WinTCShextPathInfo* path_info,
GError** error GError** error
) )
@@ -272,6 +271,24 @@ static gboolean wintc_view_zip_activate_item(
WINTC_SAFE_REF_CLEAR(error); WINTC_SAFE_REF_CLEAR(error);
WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
view_zip->map_items,
GUINT_TO_POINTER(item_hash)
);
if (!item)
{
g_critical(
"%s",
"shell: zip - attempt to activate non-existent item"
);
return FALSE;
}
// Handle opening directories
//
gboolean is_dir = g_str_has_suffix(item->priv, G_DIR_SEPARATOR_S); gboolean is_dir = g_str_has_suffix(item->priv, G_DIR_SEPARATOR_S);
if (is_dir) if (is_dir)
@@ -305,6 +322,21 @@ static void wintc_view_zip_refresh_items(
_wintc_ishext_view_refreshing(view); _wintc_ishext_view_refreshing(view);
if (view_zip->map_items)
{
g_hash_table_destroy(
g_steal_pointer(&(view_zip->map_items))
);
}
view_zip->map_items =
g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) clear_view_item
);
// Open the archive // Open the archive
// //
const gchar* path = view_zip->zip_uri + strlen("file://"); const gchar* path = view_zip->zip_uri + strlen("file://");
@@ -334,18 +366,7 @@ static void wintc_view_zip_refresh_items(
// FIXME: Probably want to cap max num of entries? Check zip bombs to see // FIXME: Probably want to cap max num of entries? Check zip bombs to see
// what happens - don't want to get nuked by a crazy zip archive // what happens - don't want to get nuked by a crazy zip archive
// //
gint64 n_entries = zip_get_num_entries(zip_file, 0); gint64 n_entries = zip_get_num_entries(zip_file, 0);
gint64 n_local_entries = 0;
g_array_remove_range(
view_zip->items,
0,
view_zip->items->len
);
g_array_set_size(
view_zip->items,
n_entries
);
for (gint64 i = 0; i < n_entries; i++) for (gint64 i = 0; i < n_entries; i++)
{ {
@@ -361,11 +382,7 @@ static void wintc_view_zip_refresh_items(
} }
gchar* entry_copy = g_strdup(entry_name); gchar* entry_copy = g_strdup(entry_name);
WinTCShextViewItem* item = &g_array_index( WinTCShextViewItem* item = g_new(WinTCShextViewItem, 1);
view_zip->items,
WinTCShextViewItem,
n_local_entries
);
item->display_name = entry_copy + name_offset; item->display_name = entry_copy + name_offset;
item->is_leaf = !g_str_has_suffix(entry_name, G_DIR_SEPARATOR_S); item->is_leaf = !g_str_has_suffix(entry_name, G_DIR_SEPARATOR_S);
@@ -373,29 +390,27 @@ static void wintc_view_zip_refresh_items(
item->hash = zip_entry_hash(path, entry_name); item->hash = zip_entry_hash(path, entry_name);
item->priv = entry_copy; item->priv = entry_copy;
n_local_entries++; g_hash_table_insert(
view_zip->map_items,
GUINT_TO_POINTER(item->hash),
item
);
} }
zip_close(zip_file); zip_close(zip_file);
// Emit the entries // Emit the entries
// //
WinTCShextViewItemsAddedData update = { 0 }; WinTCShextViewItemsUpdate update = { 0 };
g_array_set_size( GList* items = g_hash_table_get_values(view_zip->map_items);
view_zip->items,
n_local_entries
);
update.items = &g_array_index( update.data = items;
view_zip->items, update.done = TRUE;
WinTCShextViewItem,
0
);
update.num_items = n_local_entries;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update); _wintc_ishext_view_items_added(view, &update);
g_list_free(items);
} }
static void wintc_view_zip_get_actions_for_item( static void wintc_view_zip_get_actions_for_item(
@@ -643,5 +658,6 @@ static void clear_view_item(
// Don't need to bin display_name as it's an offset into priv which // Don't need to bin display_name as it's an offset into priv which
// contains the full path in the zip // contains the full path in the zip
// //
g_clear_pointer(&(item->priv), g_free); g_free(item->priv);
g_free(item);
} }