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
//
GSList* wintc_sh_fs_get_names_as_list(
GList* wintc_sh_fs_get_names_as_list(
const gchar* path,
gboolean full_names,
GFileTest test,

View File

@@ -6,7 +6,7 @@
//
// PUBLIC FUNCTIONS
//
GSList* wintc_sh_fs_get_names_as_list(
GList* wintc_sh_fs_get_names_as_list(
const gchar* path,
gboolean full_names,
GFileTest test,
@@ -17,7 +17,7 @@ GSList* wintc_sh_fs_get_names_as_list(
GDir* dir;
const gchar* dir_entry = NULL;
GSList* dirs_to_enum = NULL;
GSList* entries = NULL;
GList* entries = NULL;
GSList* iter = NULL;
WINTC_SAFE_REF_CLEAR(error);
@@ -42,7 +42,7 @@ GSList* wintc_sh_fs_get_names_as_list(
if (!dir)
{
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;
}
@@ -71,7 +71,7 @@ GSList* wintc_sh_fs_get_names_as_list(
if (!test || g_file_test(full_path, test))
{
entries =
g_slist_append(
g_list_append(
entries,
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(
WinTCShBrowser* browser,
WinTCShextViewItem* item,
guint item_hash,
GError** error
);

View File

@@ -17,7 +17,7 @@ typedef struct _WinTCShCplApplet
//
// 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(
WinTCShCplApplet* applet

View File

@@ -22,9 +22,9 @@ enum
enum
{
COLUMN_VIEWITEM = 0,
COLUMN_ICON,
COLUMN_DISPLAY_NAME,
COLUMN_ICON = 0,
COLUMN_ENTRY_NAME,
COLUMN_VIEW_HASH,
N_COLUMNS
};
@@ -53,14 +53,14 @@ static void wintc_sh_browser_set_property(
);
static void on_current_view_items_added(
WinTCIShextView* view,
WinTCShextViewItemsAddedData* event_data,
gpointer user_data
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
gpointer user_data
);
static void on_current_view_items_removed(
WinTCIShextView* view,
WinTCShextViewItem** items,
gpointer user_data
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
gpointer user_data
);
static void on_current_view_refreshing(
WinTCIShextView* view,
@@ -85,6 +85,10 @@ struct _WinTCShBrowser
//
WinTCIShextView* current_view;
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 =
gtk_list_store_new(
3,
G_TYPE_POINTER,
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(
WinTCShBrowser* browser,
WinTCShextViewItem* item,
guint item_hash,
GError** error
)
{
@@ -238,7 +242,7 @@ gboolean wintc_sh_browser_activate_item(
if (
!wintc_ishext_view_activate_item(
browser->current_view,
item,
item_hash,
&path_info,
&local_error
)
@@ -388,29 +392,54 @@ gboolean wintc_sh_browser_set_location(
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
//
g_clear_object(&(browser->current_view));
browser->current_view = new_view;
g_signal_connect(
browser->current_view,
"items-added",
G_CALLBACK(on_current_view_items_added),
browser
);
g_signal_connect(
browser->current_view,
"items-removed",
G_CALLBACK(on_current_view_items_removed),
browser
);
g_signal_connect(
browser->current_view,
"refreshing",
G_CALLBACK(on_current_view_refreshing),
browser
);
browser->sigid_items_added =
g_signal_connect_object(
browser->current_view,
"items-added",
G_CALLBACK(on_current_view_items_added),
browser,
G_CONNECT_DEFAULT
);
browser->sigid_items_removed =
g_signal_connect_object(
browser->current_view,
"items-removed",
G_CALLBACK(on_current_view_items_removed),
browser,
G_CONNECT_DEFAULT
);
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...
//
@@ -433,15 +462,15 @@ gboolean wintc_sh_browser_set_location(
//
static void on_current_view_items_added(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItemsAddedData* event_data,
gpointer user_data
WinTCShextViewItemsUpdate* update,
gpointer 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
//
@@ -462,16 +491,16 @@ static void on_current_view_items_added(
gtk_list_store_set(
browser->view_model,
&iter,
COLUMN_VIEWITEM, item,
COLUMN_ICON, icon,
COLUMN_DISPLAY_NAME, item->display_name,
COLUMN_ICON, icon,
COLUMN_ENTRY_NAME, item->display_name,
COLUMN_VIEW_HASH, item->hash,
-1
);
}
// Check if done
//
if (event_data->done)
if (update->done)
{
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(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem** items,
WINTC_UNUSED(gpointer user_data)
WinTCShextViewItemsUpdate* update,
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);
p_item++;
guint item_hash = GPOINTER_TO_UINT(upd_iter->data);
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
//
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(
S_CPL_ENTRIES_DIR,
TRUE,
@@ -35,12 +35,12 @@ GSList* wintc_sh_cpl_applet_get_all(void)
}
WinTCShCplApplet* applet;
GSList* cpls = NULL;
GList* cpls = NULL;
GError* error = NULL;
GKeyFile* key_file = g_key_file_new();
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);
@@ -107,7 +107,7 @@ GSList* wintc_sh_cpl_applet_get_all(void)
if (success)
{
cpls = g_slist_append(cpls, applet);
cpls = g_list_append(cpls, applet);
}
else
{
@@ -119,7 +119,7 @@ GSList* wintc_sh_cpl_applet_get_all(void)
success = TRUE;
}
g_slist_free_full(entries, g_free);
g_list_free_full(entries, g_free);
g_key_file_free(key_file);
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(behaviour->icon_view),
1
0
);
gtk_icon_view_set_text_column(
GTK_ICON_VIEW(behaviour->icon_view),
2
1
);
// Attach signals
@@ -218,19 +218,19 @@ static void on_icon_view_item_activated(
if (gtk_tree_model_get_iter(model, &iter, path))
{
GError* error = NULL;
WinTCShextViewItem* item = NULL;
GError* error = NULL;
guint hash;
gtk_tree_model_get(
model,
&iter,
0, &item, // FIXME: Guess we should make the columns public
2, &hash, // FIXME: Guess we should make the columns public
-1
);
wintc_sh_browser_activate_item(
behaviour->browser,
item,
hash,
&error
);

View File

@@ -16,10 +16,10 @@ enum
enum
{
COL_ICON_NAME = 0,
COL_ENTRY_NAME,
COL_VIEW_HASH,
NUM_COLS
COLUMN_ICON_NAME = 0,
COLUMN_ENTRY_NAME,
COLUMN_VIEW_HASH,
N_COLUMNS
};
//
@@ -54,9 +54,14 @@ static void on_browser_load_changed(
);
static void on_view_items_added(
WinTCIShextView* view,
WinTCShextViewItemsAddedData* items_data,
gpointer user_data
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
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_cell,
"icon-name",
COL_ICON_NAME
COLUMN_ICON_NAME
);
new_cell = gtk_cell_renderer_text_new();
@@ -226,7 +231,7 @@ static void wintc_sh_tree_view_behaviour_constructed(
new_column,
new_cell,
"text",
COL_ENTRY_NAME
COLUMN_ENTRY_NAME
);
gtk_tree_view_append_column(
@@ -493,9 +498,9 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set(
behaviour->tree_model,
&next,
COL_ICON_NAME, wintc_ishext_view_get_icon_name(view),
COL_ENTRY_NAME, wintc_ishext_view_get_display_name(view),
COL_VIEW_HASH, hash,
COLUMN_ICON_NAME, wintc_ishext_view_get_icon_name(view),
COLUMN_ENTRY_NAME, wintc_ishext_view_get_display_name(view),
COLUMN_VIEW_HASH, hash,
-1
);
@@ -549,9 +554,9 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set(
behaviour->tree_model,
&next,
COL_ICON_NAME, wintc_ishext_view_get_icon_name(next_view),
COL_ENTRY_NAME, wintc_ishext_view_get_display_name(next_view),
COL_VIEW_HASH, hash,
COLUMN_ICON_NAME, wintc_ishext_view_get_icon_name(next_view),
COLUMN_ENTRY_NAME, wintc_ishext_view_get_display_name(next_view),
COLUMN_VIEW_HASH, hash,
-1
);
@@ -584,6 +589,13 @@ static void wintc_sh_tree_view_behaviour_update_view(
behaviour,
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);
}
@@ -634,9 +646,9 @@ static void on_browser_load_changed(
}
static void on_view_items_added(
WinTCIShextView* view,
WinTCShextViewItemsAddedData* items_data,
gpointer user_data
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
gpointer user_data
)
{
WinTCShTreeViewBehaviour* behaviour =
@@ -674,9 +686,9 @@ static void on_view_items_added(
//
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
//
@@ -704,9 +716,9 @@ static void on_view_items_added(
gtk_tree_store_set(
behaviour->tree_model,
&child,
COL_ICON_NAME, view_item->icon_name,
COL_ENTRY_NAME, view_item->display_name,
COL_VIEW_HASH, view_item->hash,
COLUMN_ICON_NAME, view_item->icon_name,
COLUMN_ENTRY_NAME, view_item->display_name,
COLUMN_VIEW_HASH, view_item->hash,
-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(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -83,8 +83,8 @@ struct _WinTCShViewCpl
// State
//
GSList* list_cpls;
GArray* view_items;
GList* cpls;
GHashTable* map_items;
};
//
@@ -117,11 +117,8 @@ static void wintc_sh_view_cpl_class_init(
}
static void wintc_sh_view_cpl_init(
WinTCShViewCpl* self
)
{
self->view_items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
}
WINTC_UNUSED(WinTCShViewCpl* self)
) {}
static void wintc_sh_view_cpl_ishext_view_interface_init(
WinTCIShextViewInterface* iface
@@ -148,11 +145,17 @@ static void wintc_sh_view_cpl_finalize(
{
WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(object);
g_clear_slist(
&(view_cpl->list_cpls),
g_clear_list(
&(view_cpl->cpls),
(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);
}
@@ -185,13 +188,23 @@ static void wintc_sh_view_cpl_get_property(
// INTERFACE METHODS (WinTCIShextView)
//
static gboolean wintc_sh_view_cpl_activate_item(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem* item,
WinTCIShextView* view,
guint item_hash,
WinTCShextPathInfo* path_info,
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))
{
@@ -211,37 +224,32 @@ static void wintc_sh_view_cpl_refresh_items(
_wintc_ishext_view_refreshing(view);
// Refresh list
//
g_clear_slist(
&(view_cpl->list_cpls),
g_clear_list(
&(view_cpl->cpls),
(GDestroyNotify) wintc_sh_cpl_applet_free
);
view_cpl->list_cpls = wintc_sh_cpl_applet_get_all();
g_array_remove_range(
view_cpl->view_items,
0,
view_cpl->view_items->len
);
g_array_set_size(
view_cpl->view_items,
g_slist_length(view_cpl->list_cpls)
);
if (view_cpl->map_items)
{
g_hash_table_destroy(
g_steal_pointer(&(view_cpl->map_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;
WinTCShextViewItem* view_item = &g_array_index(
view_cpl->view_items,
WinTCShextViewItem,
i
);
WinTCShextViewItem* view_item = g_new(WinTCShextViewItem, 1);
view_item->display_name = applet->display_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->priv = applet;
i++;
g_hash_table_insert(
view_cpl->map_items,
GUINT_TO_POINTER(view_item->hash),
view_item
);
}
// Provide update
//
WinTCShextViewItemsAddedData update = { 0 };
WinTCShextViewItemsUpdate update = { 0 };
update.items = &g_array_index(
view_cpl->view_items,
WinTCShextViewItem,
0
);
update.num_items = view_cpl->view_items->len;
update.done = TRUE;
GList* items = g_hash_table_get_values(view_cpl->map_items);
update.data = items;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update);
g_list_free(items);
}
static void wintc_sh_view_cpl_get_actions_for_item(

View File

@@ -17,6 +17,10 @@ enum
// STATIC DATA
//
// FIXME: Temp
//
static GHashTable* s_desktop_map = NULL;
// FIXME: LAZY AGAIN! Use shlang!!!!!! Temporary as well cos the user can
// 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(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -132,6 +136,8 @@ static void wintc_sh_view_desktop_class_init(
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
// whatever
//
@@ -155,6 +161,12 @@ static void wintc_sh_view_desktop_class_init(
g_free(temp);
}
g_hash_table_insert(
s_desktop_map,
GUINT_TO_POINTER(s_desktop_items[i].hash),
&(s_desktop_items[i])
);
}
// GObject initialization
@@ -222,22 +234,27 @@ static void wintc_sh_view_desktop_get_property(
//
static gboolean wintc_sh_view_desktop_activate_item(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** 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");
return FALSE;
}
path_info->base_path = g_strdup(target);
path_info->base_path = g_strdup(item->priv);
return TRUE;
}
@@ -253,13 +270,16 @@ static void wintc_sh_view_desktop_refresh_items(
// Just emit the default items for now
// TODO: Should aggregate with user desktop files
//
WinTCShextViewItemsAddedData items = {
&(s_desktop_items[0]),
G_N_ELEMENTS(s_desktop_items),
TRUE
};
WinTCShextViewItemsUpdate update = { 0 };
_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(

View File

@@ -17,6 +17,10 @@ enum
// STATIC DATA
//
// FIXME: Temp
//
static GHashTable* s_drives_map = NULL;
// FIXME: Temporary - only item is the drive root atm
//
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(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_data,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -105,6 +109,8 @@ static void wintc_sh_view_drives_class_init(
WinTCShViewDrivesClass* klass
)
{
s_drives_map = g_hash_table_new(g_direct_hash, g_direct_equal);
// TEMP: Assign CPL view path
//
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[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
//
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(
WINTC_UNUSED(WinTCIShextView* view),
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** 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
//
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
// TODO: Basically everything in My Computer!
//
WinTCShextViewItemsAddedData items = {
&(s_temp_items[0]),
G_N_ELEMENTS(s_temp_items),
TRUE
};
WinTCShextViewItemsUpdate update = { 0 };
_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(

View File

@@ -1,3 +1,4 @@
#include <gio/gio.h>
#include <glib.h>
#include <wintc/comgtk.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(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -83,6 +84,14 @@ static void clear_view_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
//
@@ -97,10 +106,12 @@ struct _WinTCShViewFS
// FS state
//
GArray* items;
gchar* parent_path;
gchar* path;
GFileMonitor* fs_monitor;
GHashTable* fs_map_entries;
WinTCShextHost* shext_host;
};
@@ -159,16 +170,8 @@ static void wintc_sh_view_fs_class_init(
}
static void wintc_sh_view_fs_init(
WinTCShViewFS* self
)
{
self->items = g_array_new(FALSE, TRUE, sizeof (WinTCShextViewItem));
g_array_set_clear_func(
self->items,
(GDestroyNotify) clear_view_item
);
}
WINTC_UNUSED(WinTCShViewFS* self)
) {}
static void wintc_sh_view_fs_ishext_view_interface_init(
WinTCIShextViewInterface* iface
@@ -193,9 +196,10 @@ static void wintc_sh_view_fs_dispose(
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);
}
@@ -204,11 +208,17 @@ static void wintc_sh_view_fs_finalize(
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->parent_path);
g_free(view->path);
g_free(view_fs->parent_path);
g_free(view_fs->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);
}
@@ -280,7 +290,7 @@ static void wintc_sh_view_fs_set_property(
//
static gboolean wintc_sh_view_fs_activate_item(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
)
@@ -290,6 +300,24 @@ static gboolean wintc_sh_view_fs_activate_item(
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
//
gchar* next_path = g_build_path(
@@ -348,9 +376,16 @@ static void wintc_sh_view_fs_refresh_items(
_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)
//
GSList* entries =
GList* entries =
wintc_sh_fs_get_names_as_list(
view_fs->path,
FALSE,
@@ -359,31 +394,49 @@ static void wintc_sh_view_fs_refresh_items(
NULL
);
// Create actual array
// FIXME: list->array should probs be in comgtk
// Spawn file monitor if needed
//
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;
gint i = 0;
g_array_remove_range(
view_fs->items,
0,
view_fs->items->len
);
g_array_set_size(
view_fs->items,
g_slist_length(entries)
);
view_fs->fs_map_entries =
g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) clear_view_item
);
for (GSList* iter = entries; iter; iter = iter->next)
for (GList* iter = entries; iter; iter = iter->next)
{
gboolean is_dir;
WinTCShextViewItem* item =
&g_array_index(
view_fs->items,
WinTCShextViewItem,
i
);
WinTCShextViewItem* item = g_new(WinTCShextViewItem, 1);
entry_path =
g_build_path(
@@ -402,24 +455,27 @@ static void wintc_sh_view_fs_refresh_items(
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
//
WinTCShextViewItemsAddedData update = { 0 };
WinTCShextViewItemsUpdate update = { 0 };
update.items = &g_array_index(
view_fs->items,
WinTCShextViewItem,
0
);
update.num_items = view_fs->items->len;
update.done = TRUE;
GList* items = g_hash_table_get_values(view_fs->fs_map_entries);
update.data = items;
update.done = TRUE;
_wintc_ishext_view_items_added(view, &update);
g_list_free(items);
}
static void wintc_sh_view_fs_get_actions_for_item(
@@ -536,5 +592,87 @@ static void clear_view_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) (
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -80,7 +80,7 @@ struct _WinTCIShextViewInterface
//
gboolean wintc_ishext_view_activate_item(
WinTCIShextView* view,
WinTCShextViewItem* item,
guint item_hash,
WinTCShextPathInfo* path_info,
GError** error
);
@@ -122,12 +122,12 @@ gboolean wintc_ishext_view_has_parent(
// PUBLIC FUNCTIONS
//
void _wintc_ishext_view_items_added(
WinTCIShextView* view,
WinTCShextViewItemsAddedData* items
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update
);
void _wintc_ishext_view_items_removed(
WinTCIShextView* view,
WinTCShextViewItem** items
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update
);
void _wintc_ishext_view_refreshing(
WinTCIShextView* view

View File

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

View File

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