Enhancement: Fixes #541, shell / shellext - API for sorting view items

This commit is contained in:
Rory Fewell
2025-11-03 23:51:36 +00:00
parent a6ee559734
commit 6dbaadeeea
17 changed files with 622 additions and 123 deletions

View File

@@ -78,6 +78,8 @@ add_library(
public/strings.h
src/styles.c
public/styles.h
src/treemodel.c
public/treemodel.h
src/version.c
public/version.h
src/window.c

View File

@@ -25,6 +25,7 @@
#include "@LIB_HEADER_DIR@/signals.h"
#include "@LIB_HEADER_DIR@/strings.h"
#include "@LIB_HEADER_DIR@/styles.h"
#include "@LIB_HEADER_DIR@/treemodel.h"
#include "@LIB_HEADER_DIR@/version.h"
#include "@LIB_HEADER_DIR@/window.h"

View File

@@ -0,0 +1,19 @@
#ifndef __COMGTK_TREEMODEL_H__
#define __COMGTK_TREEMODEL_H__
#include <glib.h>
#include <gtk/gtk.h>
//
// PUBLIC FUNCTIONS
//
gint wintc_tree_model_get_insertion_sort_pos(
GtkTreeModel* tree_model,
GtkTreeIter* node,
gint column,
gint data_type,
GCompareFunc compare_func,
gconstpointer item
);
#endif

View File

@@ -0,0 +1,137 @@
#include <glib.h>
#include <gtk/gtk.h>
#include "../public/treemodel.h"
//
// PUBLIC FUNCTIONS
//
gint wintc_tree_model_get_insertion_sort_pos(
GtkTreeModel* tree_model,
GtkTreeIter* node,
gint column,
gint data_type,
GCompareFunc compare_func,
gconstpointer item
)
{
gint n_children = gtk_tree_model_iter_n_children(tree_model, node);
if (!n_children)
{
return 0;
}
// Set ourselves up, if we're sorting top level children or children of a
// node
//
GtkTreeIter child;
gint start = 0;
gint middle = n_children / 2;
gint end = n_children;
gint diff = end - start;
while (TRUE)
{
gtk_tree_model_iter_nth_child(
tree_model,
&child,
node,
middle
);
// Compare item at this node
//
gpointer item_ptr;
gint item_int;
guint item_uint;
gint result;
switch (data_type)
{
case G_TYPE_INT:
gtk_tree_model_get(
tree_model,
&child,
column, &item_int,
-1
);
result =
compare_func(
item,
GINT_TO_POINTER(item_int)
);
break;
case G_TYPE_UINT:
gtk_tree_model_get(
tree_model,
&child,
column, &item_uint,
-1
);
result =
compare_func(
item,
GUINT_TO_POINTER(item_uint)
);
break;
default:
gtk_tree_model_get(
tree_model,
&child,
column, &item_ptr,
-1
);
result =
compare_func(
item,
item_ptr
);
break;
}
// If this is the last iteration, deal with it
//
if (diff == 1)
{
if (result > 0)
{
return middle + 1;
}
else
{
return middle;
}
}
// Otherwise, iterate
//
if (result < 0)
{
end = middle;
}
else if (result > 0)
{
start = middle;
}
else
{
start = middle;
end = middle;
}
diff = end - start;
middle = start + (diff / 2);
}
}

View File

@@ -814,7 +814,7 @@ static void on_browser_load_changed(
}
static void on_current_view_items_added(
WINTC_UNUSED(WinTCIShextView* view),
WinTCIShextView* view,
WinTCShextViewItemsUpdate* update,
gpointer user_data
)
@@ -838,11 +838,29 @@ static void on_current_view_items_added(
NULL // FIXME: Error handling
);
// 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->list_model),
NULL,
COLUMN_VIEW_HASH,
G_TYPE_UINT,
sort_func,
GUINT_TO_POINTER(item->hash)
);
// Push to model
//
GtkTreeIter iter;
gtk_list_store_append(behaviour->list_model, &iter);
gtk_list_store_insert(
behaviour->list_model,
&iter,
item_pos
);
gtk_list_store_set(
behaviour->list_model,
&iter,

View File

@@ -19,6 +19,7 @@ enum
COLUMN_ICON_NAME = 0,
COLUMN_ENTRY_NAME,
COLUMN_VIEW_HASH,
COLUMN_MAPPED_VIEW,
N_COLUMNS
};
@@ -43,8 +44,8 @@ static void wintc_sh_tree_view_behaviour_update_view(
WinTCShBrowser* browser
);
static void clear_object_safe(
GObject* object
static void clear_tree_row_reference(
GtkTreeRowReference* row_ref
);
static void on_browser_load_changed(
@@ -80,8 +81,7 @@ struct _WinTCShTreeViewBehaviour
WinTCShextHost* shext_host;
GtkTreeStore* tree_model;
GHashTable* map_iter_to_view;
GHashTable* map_hash_to_iter;
GHashTable* map_hash_to_row;
GtkWidget* tree_view;
};
@@ -133,7 +133,7 @@ static void wintc_sh_tree_view_behaviour_init(
WinTCShTreeViewBehaviour* self
)
{
// Set up maps hash->iter->view
// Set up map for hash->row
//
// The intention of this is to be able to map view/viewitems to a node in
// the tree, and then those nodes to a concrete view object
@@ -142,18 +142,13 @@ static void wintc_sh_tree_view_behaviour_init(
// that are enumerated from a view are akin to placeholders, and a view is
// created only when those nodes are expanded/enumerated themselves
//
self->map_iter_to_view = g_hash_table_new_full(
g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) clear_object_safe
);
self->map_hash_to_iter = g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
g_free
);
self->map_hash_to_row =
g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) clear_tree_row_reference
);
}
//
@@ -198,10 +193,11 @@ static void wintc_sh_tree_view_behaviour_constructed(
behaviour->tree_model =
gtk_tree_store_new(
3,
4,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_UINT
G_TYPE_UINT,
G_TYPE_OBJECT
);
gtk_tree_view_set_headers_visible(
@@ -266,8 +262,7 @@ static void wintc_sh_tree_view_behaviour_dispose(
g_clear_object(&(behaviour->shext_host));
g_clear_object(&(behaviour->tree_view));
g_hash_table_unref(g_steal_pointer(&(behaviour->map_iter_to_view)));
g_hash_table_unref(g_steal_pointer(&(behaviour->map_hash_to_iter)));
g_hash_table_unref(g_steal_pointer(&(behaviour->map_hash_to_row)));
(G_OBJECT_CLASS(wintc_sh_tree_view_behaviour_parent_class))
->dispose(object);
@@ -336,11 +331,11 @@ static void wintc_sh_tree_view_behaviour_update_view(
// Collect up the views back up the tree, until we hit a view we already
// have
//
GError* error = NULL;
const gchar* iter_path = NULL;
GSList* list_views = NULL;
WinTCShextPathInfo path_info = { 0 };
WinTCIShextView* view = current_view;
GError* error = NULL;
GSList* list_views = NULL;
WinTCShextPathInfo path_info = { 0 };
GtkTreeRowReference* row_ref = NULL;
WinTCIShextView* view = current_view;
while (view)
{
@@ -350,13 +345,13 @@ static void wintc_sh_tree_view_behaviour_update_view(
// If there is a node in the tree for the view hash, stop here
//
iter_path =
row_ref =
g_hash_table_lookup(
behaviour->map_hash_to_iter,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(wintc_ishext_view_get_unique_hash(view))
);
if (iter_path)
if (row_ref)
{
break;
}
@@ -431,20 +426,30 @@ static void wintc_sh_tree_view_behaviour_update_view(
//
if (iter == list_views)
{
if (iter_path)
if (row_ref)
{
gtk_tree_model_get_iter_from_string(
WinTCIShextView* node_view = NULL;
GtkTreePath* tree_path;
tree_path =
gtk_tree_row_reference_get_path(row_ref);
gtk_tree_model_get_iter(
GTK_TREE_MODEL(behaviour->tree_model),
&next,
iter_path
tree_path
);
if (
g_hash_table_contains(
behaviour->map_iter_to_view,
iter_path
)
)
gtk_tree_model_get(
GTK_TREE_MODEL(behaviour->tree_model),
&next,
COLUMN_MAPPED_VIEW, &node_view,
-1
);
gtk_tree_path_free(tree_path);
if (node_view)
{
WINTC_LOG_DEBUG(
"shell: tree - first iter is a mapped view."
@@ -475,10 +480,11 @@ static void wintc_sh_tree_view_behaviour_update_view(
g_object_ref(view);
}
g_hash_table_insert(
behaviour->map_iter_to_view,
g_strdup(iter_path),
view
gtk_tree_store_set(
behaviour->tree_model,
&next,
COLUMN_MAPPED_VIEW, view,
-1
);
}
}
@@ -498,35 +504,36 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set(
behaviour->tree_model,
&next,
COLUMN_ICON_NAME, wintc_ishext_view_get_icon_name(view),
COLUMN_ENTRY_NAME, wintc_ishext_view_get_display_name(view),
COLUMN_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,
COLUMN_MAPPED_VIEW, view,
-1
);
// Map the hash<->iter
// Map the hash->row
//
GtkTreePath* tree_path =
gtk_tree_model_get_path(
GTK_TREE_MODEL(behaviour->tree_model),
&next
);
if (view == current_view)
{
g_object_ref(view);
}
g_hash_table_insert(
behaviour->map_hash_to_iter,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(hash),
gtk_tree_model_get_string_from_iter(
gtk_tree_row_reference_new(
GTK_TREE_MODEL(behaviour->tree_model),
&next
tree_path
)
);
g_hash_table_insert(
behaviour->map_iter_to_view,
gtk_tree_model_get_string_from_iter(
GTK_TREE_MODEL(behaviour->tree_model),
&next
),
view
);
gtk_tree_path_free(tree_path);
}
last = next; // Copy node iter over
@@ -554,28 +561,31 @@ static void wintc_sh_tree_view_behaviour_update_view(
gtk_tree_store_set(
behaviour->tree_model,
&next,
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,
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,
COLUMN_MAPPED_VIEW, next_view,
-1
);
g_hash_table_insert(
behaviour->map_hash_to_iter,
GUINT_TO_POINTER(hash),
gtk_tree_model_get_string_from_iter(
// Map the hash->row
//
GtkTreePath* tree_path =
gtk_tree_model_get_path(
GTK_TREE_MODEL(behaviour->tree_model),
&next
);
g_hash_table_insert(
behaviour->map_hash_to_row,
GUINT_TO_POINTER(hash),
gtk_tree_row_reference_new(
GTK_TREE_MODEL(behaviour->tree_model),
tree_path
)
);
g_hash_table_insert(
behaviour->map_iter_to_view,
gtk_tree_model_get_string_from_iter(
GTK_TREE_MODEL(behaviour->tree_model),
&next
),
next_view
);
gtk_tree_path_free(tree_path);
}
// Watch for items and refresh if this is a new view
@@ -618,14 +628,33 @@ static void wintc_sh_tree_view_behaviour_update_view(
//
// CALLBACKS
//
static void clear_object_safe(
GObject* object
static void clear_tree_row_reference(
GtkTreeRowReference* row_ref
)
{
if (object)
{
g_object_unref(object);
}
WinTCIShextView* view = NULL;
GtkTreeModel* tree_model = gtk_tree_row_reference_get_model(row_ref);
GtkTreePath* tree_path = gtk_tree_row_reference_get_path(row_ref);
GtkTreeIter row;
gtk_tree_model_get_iter(
tree_model,
&row,
tree_path
);
gtk_tree_model_get(
tree_model,
&row,
COLUMN_MAPPED_VIEW, &view,
-1
);
g_clear_object(&view);
gtk_tree_path_free(tree_path);
gtk_tree_row_reference_free(row_ref);
}
static void on_browser_load_changed(
@@ -664,17 +693,22 @@ static void on_view_items_added(
// Locate the parent node
//
const gchar* iter_path =
GtkTreeRowReference* row_ref;
GtkTreePath* tree_path;
row_ref =
g_hash_table_lookup(
behaviour->map_hash_to_iter,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(wintc_ishext_view_get_unique_hash(view))
);
tree_path = gtk_tree_row_reference_get_path(row_ref);
if (
!gtk_tree_model_get_iter_from_string(
!gtk_tree_model_get_iter(
GTK_TREE_MODEL(behaviour->tree_model),
&parent,
iter_path
tree_path
)
)
{
@@ -682,6 +716,8 @@ static void on_view_items_added(
return;
}
gtk_tree_path_free(tree_path);
// Iterate over the items to append to the tree
//
WinTCShextViewItem* view_item;
@@ -695,7 +731,7 @@ static void on_view_items_added(
if (
view_item->is_leaf ||
g_hash_table_contains(
behaviour->map_hash_to_iter,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(view_item->hash)
)
)
@@ -708,10 +744,27 @@ static void on_view_items_added(
GUINT_TO_POINTER(view_item->hash)
);
gtk_tree_store_append(
// 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
&parent,
item_pos
);
gtk_tree_store_set(
behaviour->tree_model,
@@ -722,14 +775,24 @@ static void on_view_items_added(
-1
);
g_hash_table_insert(
behaviour->map_hash_to_iter,
GUINT_TO_POINTER(view_item->hash),
gtk_tree_model_get_string_from_iter(
// 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);
}
}
@@ -750,34 +813,43 @@ static void on_view_items_removed(
{
guint item_hash = GPOINTER_TO_UINT(upd_iter->data);
const gchar* iter_path =
// Nav to iter
//
GtkTreeRowReference* row_ref;
GtkTreePath* tree_path;
row_ref =
g_hash_table_lookup(
behaviour->map_hash_to_iter,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(item_hash)
);
if (!iter_path)
if (!row_ref)
{
continue;
}
gtk_tree_model_get_iter_from_string(
tree_path =
gtk_tree_row_reference_get_path(row_ref);
gtk_tree_model_get_iter(
GTK_TREE_MODEL(behaviour->tree_model),
&iter,
iter_path
tree_path
);
gtk_tree_path_free(tree_path);
// Delete node and mapping (row ref and view collected up via
// clear_tree_row_reference())
//
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,
behaviour->map_hash_to_row,
GUINT_TO_POINTER(item_hash)
);
}

View File

@@ -38,6 +38,11 @@ static gboolean wintc_sh_view_cpl_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static gint wintc_sh_view_cpl_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static const gchar* wintc_sh_view_cpl_get_display_name(
WinTCIShextView* view
);
@@ -75,6 +80,11 @@ static WinTCShextOperation* wintc_sh_view_cpl_spawn_operation(
GError** error
);
static WinTCShextViewItem* wintc_sh_view_cpl_get_view_item(
WinTCShViewCpl* view_cpl,
guint item_hash
);
//
// GLIB OOP/CLASS INSTANCE DEFINITIONS
//
@@ -131,6 +141,7 @@ static void wintc_sh_view_cpl_ishext_view_interface_init(
)
{
iface->activate_item = wintc_sh_view_cpl_activate_item;
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_operations_for_item = wintc_sh_view_cpl_get_operations_for_item;
@@ -206,11 +217,7 @@ static gboolean wintc_sh_view_cpl_activate_item(
WinTCShCplApplet* applet;
WinTCShextViewItem* item;
item = (WinTCShextViewItem*)
g_hash_table_lookup(
view_cpl->map_items,
GUINT_TO_POINTER(item_hash)
);
item = wintc_sh_view_cpl_get_view_item(view_cpl, item_hash);
applet = (WinTCShCplApplet*) item->priv;
if (wintc_sh_cpl_applet_is_executable(applet))
@@ -223,6 +230,22 @@ static gboolean wintc_sh_view_cpl_activate_item(
return TRUE;
}
static gint wintc_sh_view_cpl_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
)
{
WinTCShViewCpl* view_cpl = WINTC_SH_VIEW_CPL(view);
WinTCShextViewItem* item1 =
wintc_sh_view_cpl_get_view_item(view_cpl, item_hash1);
WinTCShextViewItem* item2 =
wintc_sh_view_cpl_get_view_item(view_cpl, item_hash2);
return wintc_shext_view_item_compare_by_name(item1, item2);
}
static const gchar* wintc_sh_view_cpl_get_display_name(
WINTC_UNUSED(WinTCIShextView* view)
)
@@ -379,3 +402,19 @@ WinTCIShextView* wintc_sh_view_cpl_new(void)
)
);
}
//
// PRIVATE FUNCTIONS
//
static WinTCShextViewItem* wintc_sh_view_cpl_get_view_item(
WinTCShViewCpl* view_cpl,
guint item_hash
)
{
return
(WinTCShextViewItem*)
g_hash_table_lookup(
view_cpl->map_items,
GUINT_TO_POINTER(item_hash)
);
}

View File

@@ -79,6 +79,11 @@ static gboolean wintc_sh_view_desktop_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static gint wintc_sh_view_desktop_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static const gchar* wintc_sh_view_desktop_get_display_name(
WinTCIShextView* view
);
@@ -201,6 +206,7 @@ static void wintc_sh_view_desktop_ishext_view_interface_init(
)
{
iface->activate_item = wintc_sh_view_desktop_activate_item;
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_operations_for_item =
@@ -272,6 +278,16 @@ static gboolean wintc_sh_view_desktop_activate_item(
return TRUE;
}
static gint wintc_sh_view_desktop_compare_items(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash1),
WINTC_UNUSED(guint item_hash2)
)
{
// FIXME: Proper implementation
return -1;
}
static const gchar* wintc_sh_view_desktop_get_display_name(
WINTC_UNUSED(WinTCIShextView* view)
)

View File

@@ -62,6 +62,11 @@ static gboolean wintc_sh_view_drives_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static gint wintc_sh_view_drives_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static const gchar* wintc_sh_view_drives_get_display_name(
WinTCIShextView* view
);
@@ -175,6 +180,7 @@ static void wintc_sh_view_drives_ishext_view_interface_init(
)
{
iface->activate_item = wintc_sh_view_drives_activate_item;
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_operations_for_item =
@@ -242,6 +248,16 @@ static gboolean wintc_sh_view_drives_activate_item(
return TRUE;
}
static gint wintc_sh_view_drives_compare_items(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash1),
WINTC_UNUSED(guint item_hash2)
)
{
// FIXME: Proper implementation
return -1;
}
static const gchar* wintc_sh_view_drives_get_display_name(
WINTC_UNUSED(WinTCIShextView* view)
)

View File

@@ -68,8 +68,10 @@ static gboolean wintc_sh_view_fs_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static guint wintc_sh_view_fs_get_unique_hash(
WinTCIShextView* view
static gint wintc_sh_view_fs_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static const gchar* wintc_sh_view_fs_get_display_name(
WinTCIShextView* view
@@ -92,6 +94,9 @@ static void wintc_sh_view_fs_get_path(
WinTCIShextView* view,
WinTCShextPathInfo* path_info
);
static guint wintc_sh_view_fs_get_unique_hash(
WinTCIShextView* view
);
static gboolean wintc_sh_view_fs_has_parent(
WinTCIShextView* view
);
@@ -122,6 +127,10 @@ static gboolean real_activate_item(
GError** error
);
static WinTCShextViewItem* wintc_sh_view_fs_get_view_item(
WinTCShViewFS* view_fs,
guint item_hash
);
static void wintc_sh_view_fs_update_new_templates(
WinTCShViewFS* view_fs
);
@@ -246,6 +255,7 @@ static void wintc_sh_view_fs_ishext_view_interface_init(
)
{
iface->activate_item = wintc_sh_view_fs_activate_item;
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_operations_for_item = wintc_sh_view_fs_get_operations_for_item;
@@ -396,11 +406,7 @@ static gboolean wintc_sh_view_fs_activate_item(
// Retrieve the item itself
//
WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item_hash)
);
wintc_sh_view_fs_get_view_item(view_fs, item_hash);
if (!item)
{
@@ -419,6 +425,20 @@ static gboolean wintc_sh_view_fs_activate_item(
);
}
static gint wintc_sh_view_fs_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
)
{
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
return wintc_shext_view_item_compare_by_fs_order(
wintc_sh_view_fs_get_view_item(view_fs, item_hash1),
wintc_sh_view_fs_get_view_item(view_fs, item_hash2)
);
}
static const gchar* wintc_sh_view_fs_get_display_name(
WinTCIShextView* view
)
@@ -453,11 +473,7 @@ static GMenuModel* wintc_sh_view_fs_get_operations_for_item(
WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view);
WinTCShextViewItem* view_item =
(WinTCShextViewItem*)
g_hash_table_lookup(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item_hash)
);
wintc_sh_view_fs_get_view_item(view_fs, item_hash);
if (!view_item)
{
@@ -953,6 +969,19 @@ static gboolean real_activate_item(
return success;
}
static WinTCShextViewItem* wintc_sh_view_fs_get_view_item(
WinTCShViewFS* view_fs,
guint item_hash
)
{
return
(WinTCShextViewItem*)
g_hash_table_lookup(
view_fs->fs_map_entries,
GUINT_TO_POINTER(item_hash)
);
}
static void wintc_sh_view_fs_update_new_templates(
WinTCShViewFS* view_fs
)

View File

@@ -44,6 +44,7 @@ add_library(
public/if_view.h
src/uictl.c
public/uictl.h
src/viewitem.c
public/viewitem.h
public/viewops.h
)

View File

@@ -42,6 +42,11 @@ struct _WinTCIShextViewInterface
GError** error
);
gint (*compare_items) (
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
const gchar* (*get_display_name) (
WinTCIShextView* view
);
@@ -92,6 +97,11 @@ gboolean wintc_ishext_view_activate_item(
GError** error
);
gint wintc_ishext_view_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
void wintc_ishext_view_refresh_items(
WinTCIShextView* view
);
@@ -145,6 +155,10 @@ void _wintc_ishext_view_refreshing(
WinTCIShextView* view
);
GCompareFunc wintc_ishext_view_get_sort_func(
WinTCIShextView* view
);
// WinTCShextPathInfo methods
//
void wintc_shext_path_info_demangle_uri(

View File

@@ -33,4 +33,16 @@ typedef struct _WinTCShextViewItemsUpdate
gboolean done;
} WinTCShextViewItemsUpdate;
//
// PUBLIC FUNCTIONS
//
gint wintc_shext_view_item_compare_by_name(
const WinTCShextViewItem* item1,
const WinTCShextViewItem* item2
);
gint wintc_shext_view_item_compare_by_fs_order(
const WinTCShextViewItem* item1,
const WinTCShextViewItem* item2
);
#endif

View File

@@ -107,6 +107,18 @@ gboolean wintc_ishext_view_activate_item(
);
}
gint wintc_ishext_view_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
)
{
WinTCIShextViewInterface* iface =
WINTC_ISHEXT_VIEW_GET_IFACE(view);
return iface->compare_items(view, item_hash1, item_hash2);
}
const gchar* wintc_ishext_view_get_display_name(
WinTCIShextView* view
)
@@ -258,6 +270,40 @@ void _wintc_ishext_view_refreshing(
);
}
// HACKY SORT FUNC
static WinTCIShextView* S_CUR_VIEW_FOR_SORTING = NULL;
gint _wintc_ishext_view_sort_func(
gconstpointer item_hash1,
gconstpointer item_hash2
)
{
if (!S_CUR_VIEW_FOR_SORTING)
{
g_critical("%s", "shellext: attempting to sort with no view!");
return 0;
}
return wintc_ishext_view_compare_items(
S_CUR_VIEW_FOR_SORTING,
GPOINTER_TO_UINT(item_hash1),
GPOINTER_TO_UINT(item_hash2)
);
}
GCompareFunc wintc_ishext_view_get_sort_func(
WinTCIShextView* view
)
{
//
// FIXME: This is NOT thread-safe!!
//
S_CUR_VIEW_FOR_SORTING = view;
return ((GCompareFunc) _wintc_ishext_view_sort_func);
}
// END HACKY SORT FUNC
void wintc_shext_path_info_demangle_uri(
WinTCShextPathInfo* path_info,
const gchar* uri

View File

@@ -0,0 +1,27 @@
#include <glib.h>
#include "../public/viewitem.h"
//
// PUBLIC FUNCTIONS
//
gint wintc_shext_view_item_compare_by_name(
const WinTCShextViewItem* item1,
const WinTCShextViewItem* item2
)
{
return g_strcmp0(item1->display_name, item2->display_name);
}
gint wintc_shext_view_item_compare_by_fs_order(
const WinTCShextViewItem* item1,
const WinTCShextViewItem* item2
)
{
if (item1->is_leaf == item2->is_leaf)
{
return wintc_shext_view_item_compare_by_name(item1, item2);
}
return item1->is_leaf ? 1 : -1;
}

View File

@@ -55,6 +55,11 @@ static gboolean wintc_cpl_view_printers_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static gint wintc_cpl_view_printers_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static const gchar* wintc_cpl_view_printers_get_display_name(
WinTCIShextView* view
);
@@ -153,6 +158,7 @@ static void wintc_cpl_view_printers_ishext_view_interface_init(
)
{
iface->activate_item = wintc_cpl_view_printers_activate_item;
iface->compare_items = wintc_cpl_view_printers_compare_items;
iface->get_display_name = wintc_cpl_view_printers_get_display_name;
iface->get_icon_name = wintc_cpl_view_printers_get_icon_name;
iface->get_operations_for_item =
@@ -208,6 +214,16 @@ static gboolean wintc_cpl_view_printers_activate_item(
return FALSE;
}
static gint wintc_cpl_view_printers_compare_items(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash1),
WINTC_UNUSED(guint item_hash2)
)
{
// FIXME: Proper implementation
return -1;
}
static GMenuModel* wintc_cpl_view_printers_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash)

View File

@@ -45,6 +45,11 @@ static gboolean wintc_view_zip_activate_item(
WinTCShextPathInfo* path_info,
GError** error
);
static gint wintc_view_zip_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
);
static GMenuModel* wintc_view_zip_get_operations_for_item(
WinTCIShextView* view,
guint item_hash
@@ -76,6 +81,11 @@ static void wintc_view_zip_refresh_items(
WinTCIShextView* view
);
static WinTCShextViewItem* wintc_view_zip_get_view_item(
WinTCViewZip* view_zip,
guint item_hash
);
static guint zip_entry_hash(
const gchar* zip_file_path,
const gchar* rel_entry_path
@@ -173,6 +183,7 @@ static void wintc_view_zip_ishext_view_interface_init(
)
{
iface->activate_item = wintc_view_zip_activate_item;
iface->compare_items = wintc_view_zip_compare_items;
iface->get_operations_for_item = wintc_view_zip_get_operations_for_item;
iface->get_operations_for_view = wintc_view_zip_get_operations_for_view;
iface->get_display_name = wintc_view_zip_get_display_name;
@@ -272,11 +283,7 @@ static gboolean wintc_view_zip_activate_item(
WINTC_SAFE_REF_CLEAR(error);
WinTCShextViewItem* item =
(WinTCShextViewItem*)
g_hash_table_lookup(
view_zip->map_items,
GUINT_TO_POINTER(item_hash)
);
wintc_view_zip_get_view_item(view_zip, item_hash);
if (!item)
{
@@ -312,6 +319,20 @@ static gboolean wintc_view_zip_activate_item(
return FALSE;
}
static gint wintc_view_zip_compare_items(
WinTCIShextView* view,
guint item_hash1,
guint item_hash2
)
{
WinTCViewZip* view_zip = WINTC_VIEW_ZIP(view);
return wintc_shext_view_item_compare_by_fs_order(
wintc_view_zip_get_view_item(view_zip, item_hash1),
wintc_view_zip_get_view_item(view_zip, item_hash2)
);
}
static GMenuModel* wintc_view_zip_get_operations_for_item(
WINTC_UNUSED(WinTCIShextView* view),
WINTC_UNUSED(guint item_hash)
@@ -585,6 +606,19 @@ WinTCIShextView* wintc_view_zip_new(
//
// PRIVATE FUNCTIONS
//
static WinTCShextViewItem* wintc_view_zip_get_view_item(
WinTCViewZip* view_zip,
guint item_hash
)
{
return
(WinTCShextViewItem*)
g_hash_table_lookup(
view_zip->map_items,
GUINT_TO_POINTER(item_hash)
);
}
static guint zip_entry_hash(
const gchar* zip_file_path,
const gchar* rel_entry_path