mirror of
https://github.com/rozniak/xfce-winxp-tc.git
synced 2026-05-01 11:41:30 +00:00
Enhancement: Fixes #436, taskband - Start menu - All Programs items should be sorted by display name
This commit is contained in:
@@ -31,6 +31,7 @@ wintc_resolve_library(gdk-pixbuf-2.0 GDK_PIXBUF)
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(upower-glib UPOWER_GLIB)
|
||||
wintc_resolve_library(wintc-comctl WINTC_COMCTL)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-exec WINTC_EXEC)
|
||||
wintc_resolve_library(wintc-shcommon WINTC_SHCOMMON)
|
||||
@@ -117,6 +118,7 @@ target_include_directories(
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${UPOWER_GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_EXEC_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_INCLUDE_DIRS}
|
||||
@@ -135,6 +137,7 @@ target_link_directories(
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${UPOWER_GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_EXEC_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARY_DIRS}
|
||||
@@ -153,6 +156,7 @@ target_link_libraries(
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${UPOWER_GLIB_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_EXEC_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARIES}
|
||||
|
||||
@@ -7,6 +7,7 @@ bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:networkmanager
|
||||
bt,rt:upower-glib
|
||||
bt,rt:wintc-comctl
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-exec
|
||||
bt,rt:wintc-shcommon
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <wintc/comctl.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/exec.h>
|
||||
#include <wintc/shelldpa.h>
|
||||
@@ -264,7 +265,9 @@ void create_personal_menu(
|
||||
//
|
||||
gtk_menu_item_set_submenu(
|
||||
GTK_MENU_ITEM(toolbar_start->personal.menuitem_all_programs),
|
||||
wintc_toolbar_start_progmenu_new_gtk_menu()
|
||||
wintc_toolbar_start_progmenu_new_gtk_menu(
|
||||
&(toolbar_start->personal.all_programs_binding)
|
||||
)
|
||||
);
|
||||
|
||||
// Transfer to popup
|
||||
@@ -395,6 +398,12 @@ void destroy_personal_menu(
|
||||
g_steal_pointer(&(toolbar_start->personal.separator_all_programs))
|
||||
);
|
||||
|
||||
// Clear all programs menu model binding object
|
||||
//
|
||||
g_clear_object(
|
||||
&(toolbar_start->personal.all_programs_binding)
|
||||
);
|
||||
|
||||
// Clear signal tuple data
|
||||
//
|
||||
g_array_unref(
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wintc/comctl.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/exec.h>
|
||||
#include <wintc/shcommon.h>
|
||||
@@ -48,6 +49,10 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
GList* files,
|
||||
GHashTable** map_dir_to_menu
|
||||
);
|
||||
static void wintc_toolbar_start_progmenu_menu_insert_sorted(
|
||||
GMenu* menu,
|
||||
GMenuItem* menu_item
|
||||
);
|
||||
|
||||
static gboolean create_symlink(
|
||||
const gchar* rel_path,
|
||||
@@ -186,8 +191,6 @@ gboolean wintc_toolbar_start_progmenu_init(
|
||||
);
|
||||
}
|
||||
|
||||
files = g_list_sort(files, (GCompareFunc) g_ascii_strcasecmp);
|
||||
|
||||
// Construct the menu
|
||||
//
|
||||
S_MENU_PROGRAMS =
|
||||
@@ -203,7 +206,9 @@ gboolean wintc_toolbar_start_progmenu_init(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget* wintc_toolbar_start_progmenu_new_gtk_menu()
|
||||
GtkWidget* wintc_toolbar_start_progmenu_new_gtk_menu(
|
||||
WinTCCtlMenuBinding** menu_binding
|
||||
)
|
||||
{
|
||||
if (!S_INIT_DONE)
|
||||
{
|
||||
@@ -233,7 +238,15 @@ GtkWidget* wintc_toolbar_start_progmenu_new_gtk_menu()
|
||||
|
||||
// Create the menu
|
||||
//
|
||||
GtkWidget* menu = gtk_menu_new_from_model(G_MENU_MODEL(S_MENU_PROGRAMS));
|
||||
GtkWidget* menu = gtk_menu_new();
|
||||
|
||||
gtk_menu_set_reserve_toggle_size(GTK_MENU(menu), FALSE);
|
||||
|
||||
*menu_binding =
|
||||
wintc_ctl_menu_binding_new(
|
||||
GTK_MENU_SHELL(menu),
|
||||
G_MENU_MODEL(S_MENU_PROGRAMS)
|
||||
);
|
||||
|
||||
gtk_widget_insert_action_group(
|
||||
menu,
|
||||
@@ -447,7 +460,7 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
|
||||
// Construct the menus from this file list
|
||||
//
|
||||
gint len_root = strlen(S_DIR_START_MENU);
|
||||
gint len_root = g_utf8_strlen(S_DIR_START_MENU, -1);
|
||||
|
||||
for (GList* iter = files; iter; iter = iter->next)
|
||||
{
|
||||
@@ -460,7 +473,11 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
// Pull the directory components out of the path to check the submenu
|
||||
// that should own this item
|
||||
//
|
||||
const gchar* dir_end = strrchr(entry_path, G_DIR_SEPARATOR);
|
||||
const gchar* dir_end = g_utf8_strrchr(
|
||||
entry_path,
|
||||
-1,
|
||||
G_DIR_SEPARATOR
|
||||
);
|
||||
const gchar* dir_start = entry_path + len_root;
|
||||
|
||||
gchar* rel_dir = g_malloc0((dir_end - dir_start) + 1);
|
||||
@@ -513,7 +530,10 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
g_app_info_get_name(G_APP_INFO(entry))
|
||||
);
|
||||
|
||||
g_menu_append_item(menu_owner, new_item);
|
||||
wintc_toolbar_start_progmenu_menu_insert_sorted(
|
||||
menu_owner,
|
||||
new_item
|
||||
);
|
||||
|
||||
g_free(cmd);
|
||||
g_object_unref(new_item);
|
||||
@@ -553,7 +573,7 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
{
|
||||
// Retrieve the parent path
|
||||
//
|
||||
const gchar* dir_end = strrchr(iter, G_DIR_SEPARATOR);
|
||||
const gchar* dir_end = g_utf8_strrchr(iter, -1, G_DIR_SEPARATOR);
|
||||
|
||||
gchar* parent = g_malloc0(dir_end - iter + 1);
|
||||
|
||||
@@ -576,7 +596,7 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
|
||||
g_menu_item_set_icon(
|
||||
submenu_item,
|
||||
g_themed_icon_new("add")
|
||||
s_icon_programs
|
||||
);
|
||||
g_menu_item_set_label(
|
||||
submenu_item,
|
||||
@@ -597,7 +617,7 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
|
||||
if (parent_menu)
|
||||
{
|
||||
g_menu_prepend_item(
|
||||
wintc_toolbar_start_progmenu_menu_insert_sorted(
|
||||
parent_menu,
|
||||
submenu_item
|
||||
);
|
||||
@@ -642,6 +662,183 @@ static GMenu* wintc_toolbar_start_progmenu_menu_from_filelist(
|
||||
return menu;
|
||||
}
|
||||
|
||||
static void wintc_toolbar_start_progmenu_menu_insert_sorted(
|
||||
GMenu* menu,
|
||||
GMenuItem* menu_item
|
||||
)
|
||||
{
|
||||
gint idx_start = 0;
|
||||
gint idx_end = 0;
|
||||
gint n_items = g_menu_model_get_n_items(G_MENU_MODEL(menu));
|
||||
|
||||
// Easy case - no items? Prepend
|
||||
//
|
||||
if (!n_items)
|
||||
{
|
||||
g_menu_prepend_item(menu, menu_item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the end of submenu items
|
||||
//
|
||||
gint n_submenu_items = 0;
|
||||
|
||||
for (; n_submenu_items < n_items; n_submenu_items++)
|
||||
{
|
||||
// Hit a normal item? We've already hit the end then
|
||||
//
|
||||
if (
|
||||
!g_menu_model_get_item_link(
|
||||
G_MENU_MODEL(menu),
|
||||
n_submenu_items,
|
||||
G_MENU_LINK_SUBMENU
|
||||
)
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the start/end depending on whether we need to insert a normal item
|
||||
// or submenu item
|
||||
//
|
||||
if (g_menu_item_get_link(menu_item, G_MENU_LINK_SUBMENU))
|
||||
{
|
||||
if (n_submenu_items)
|
||||
{
|
||||
idx_end = n_submenu_items - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n_submenu_items)
|
||||
{
|
||||
idx_start = n_submenu_items;
|
||||
}
|
||||
|
||||
idx_end = n_items - 1;
|
||||
}
|
||||
|
||||
// Binary search and insert
|
||||
//
|
||||
gint idx_mid;
|
||||
gchar* cmp_name = NULL;
|
||||
gchar* our_name = NULL;
|
||||
gint res;
|
||||
|
||||
g_menu_item_get_attribute(
|
||||
menu_item,
|
||||
G_MENU_ATTRIBUTE_LABEL,
|
||||
"s",
|
||||
&our_name
|
||||
);
|
||||
|
||||
WINTC_UTF8_TRANSFORM(our_name, g_utf8_casefold);
|
||||
|
||||
while (idx_end - idx_start > 1)
|
||||
{
|
||||
idx_mid = idx_start + ((idx_end - idx_start) / 2);
|
||||
|
||||
g_menu_model_get_item_attribute(
|
||||
G_MENU_MODEL(menu),
|
||||
idx_mid,
|
||||
G_MENU_ATTRIBUTE_LABEL,
|
||||
"s",
|
||||
&cmp_name
|
||||
);
|
||||
|
||||
WINTC_UTF8_TRANSFORM(cmp_name, g_utf8_casefold);
|
||||
|
||||
res = g_utf8_collate(our_name, cmp_name);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
idx_end = idx_mid;
|
||||
}
|
||||
else if (res > 0)
|
||||
{
|
||||
idx_start = idx_mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx_start = idx_mid;
|
||||
idx_end = idx_mid;
|
||||
}
|
||||
|
||||
g_free(cmp_name);
|
||||
}
|
||||
|
||||
// If we found an exact location, insert there
|
||||
//
|
||||
if (idx_start == idx_end)
|
||||
{
|
||||
g_menu_insert_item(
|
||||
menu,
|
||||
idx_start,
|
||||
menu_item
|
||||
);
|
||||
|
||||
g_free(our_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise determine between start and end
|
||||
//
|
||||
g_menu_model_get_item_attribute(
|
||||
G_MENU_MODEL(menu),
|
||||
idx_start,
|
||||
G_MENU_ATTRIBUTE_LABEL,
|
||||
"s",
|
||||
&cmp_name
|
||||
);
|
||||
|
||||
WINTC_UTF8_TRANSFORM(cmp_name, g_utf8_casefold);
|
||||
|
||||
if (g_utf8_collate(our_name, cmp_name) < 0)
|
||||
{
|
||||
g_menu_insert_item(
|
||||
menu,
|
||||
idx_start,
|
||||
menu_item
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(cmp_name);
|
||||
|
||||
g_menu_model_get_item_attribute(
|
||||
G_MENU_MODEL(menu),
|
||||
idx_end,
|
||||
G_MENU_ATTRIBUTE_LABEL,
|
||||
"s",
|
||||
&cmp_name
|
||||
);
|
||||
|
||||
WINTC_UTF8_TRANSFORM(cmp_name, g_utf8_casefold);
|
||||
|
||||
if (g_utf8_collate(our_name, cmp_name) < 0)
|
||||
{
|
||||
g_menu_insert_item(
|
||||
menu,
|
||||
idx_end,
|
||||
menu_item
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_menu_insert_item(
|
||||
menu,
|
||||
idx_end + 1,
|
||||
menu_item
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(cmp_name);
|
||||
g_free(our_name);
|
||||
}
|
||||
|
||||
static gboolean create_symlink(
|
||||
const gchar* rel_path,
|
||||
const gchar* entry_name,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comctl.h>
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
@@ -11,6 +12,8 @@ gboolean wintc_toolbar_start_progmenu_init(
|
||||
GError** error
|
||||
);
|
||||
|
||||
GtkWidget* wintc_toolbar_start_progmenu_new_gtk_menu(void);
|
||||
GtkWidget* wintc_toolbar_start_progmenu_new_gtk_menu(
|
||||
WinTCCtlMenuBinding** menu_binding
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef __SHARED_START_H__
|
||||
#define __SHARED_START_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comctl.h>
|
||||
|
||||
//
|
||||
// INTERNAL STRUCTS
|
||||
//
|
||||
@@ -18,6 +22,8 @@ typedef struct _PersonalStartMenuData
|
||||
GtkWidget* menuitem_all_programs;
|
||||
GtkWidget* separator_all_programs;
|
||||
|
||||
WinTCCtlMenuBinding* all_programs_binding;
|
||||
|
||||
// UI state
|
||||
//
|
||||
gboolean sync_menu_refresh;
|
||||
|
||||
Reference in New Issue
Block a user