From d8735cedb5f5f7a893cce31acac2f110b459831e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 13 Feb 2023 12:15:22 +0000 Subject: [PATCH 1/4] Put items with submenus at the top of the menu --- src/ui_utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui_utils.c b/src/ui_utils.c index 8ba90ef481..4e5b4c9982 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -2875,11 +2875,11 @@ static gint compare_menu_item_labels(gconstpointer a, gconstpointer b) gchar *sa, *sb; gint result; - /* put entries with submenus at the end of the menu */ + /* put entries with submenus at the start of the menu */ if (gtk_menu_item_get_submenu(item_a) && !gtk_menu_item_get_submenu(item_b)) - return 1; - else if (!gtk_menu_item_get_submenu(item_a) && gtk_menu_item_get_submenu(item_b)) return -1; + else if (!gtk_menu_item_get_submenu(item_a) && gtk_menu_item_get_submenu(item_b)) + return 1; sa = ui_menu_item_get_text(item_a); sb = ui_menu_item_get_text(item_b); From 39215550e4d5ddfbf6828b9e4ca62bbced661b60 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 13 Feb 2023 12:23:34 +0000 Subject: [PATCH 2/4] Add filetype submenus for new file template menus Add submenus when there's more than one template per filetype. --- src/templates.c | 40 +++++++++++++++++++++++++++++++++++++++- src/ui_utils.c | 3 +-- src/ui_utils.h | 2 ++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/templates.c b/src/templates.c index ebf4c89e0c..345b2a9bbc 100644 --- a/src/templates.c +++ b/src/templates.c @@ -255,19 +255,57 @@ static void add_file_item(const gchar *fname, GtkWidget *menu) } +typedef struct +{ + gint count; + GtkWidget *menu; +} +FTMenu; + static void populate_file_template_menu(GtkWidget *menu) { GSList *list = utils_get_config_files(GEANY_TEMPLATES_SUBDIR G_DIR_SEPARATOR_S "files"); GSList *node; + FTMenu *ft_groups; + gint nbytes = sizeof(FTMenu) * filetypes_array->len; + + ft_groups = g_alloca(nbytes); + memset(ft_groups, 0, nbytes); + + foreach_slist(node, list) + { + gchar *fname = node->data; + GeanyFiletype *ft = filetypes_detect_from_extension(fname); + if (ft) + ft_groups[ft->id].count++; + } foreach_slist(node, list) { gchar *fname = node->data; + GeanyFiletype *ft = filetypes_detect_from_extension(fname); + FTMenu *group = NULL; - add_file_item(fname, menu); + if (ft) + group = &ft_groups[ft->id]; + if (group->count == 1) + add_file_item(fname, menu); + else + { + if (!group->menu) + { + GtkWidget *item = gtk_menu_item_new_with_label(ft->name); + gtk_widget_show(item); + gtk_container_add(GTK_CONTAINER(menu), item); + group->menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group->menu); + } + add_file_item(fname, group->menu); + } g_free(fname); } g_slist_free(list); + ui_menu_sort_by_label(GTK_MENU(menu)); } diff --git a/src/ui_utils.c b/src/ui_utils.c index 4e5b4c9982..3d58df254c 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -118,7 +118,6 @@ static void recent_file_loaded(const gchar *utf8_filename, GeanyRecentFiles *grf static void recent_file_activate_cb(GtkMenuItem *menuitem, gpointer user_data); static void recent_project_activate_cb(GtkMenuItem *menuitem, gpointer user_data); static GtkWidget *progress_bar_create(void); -static void ui_menu_sort_by_label(GtkMenu *menu); /* simple wrapper for gtk_widget_set_sensitive() to allow widget being NULL */ @@ -2891,7 +2890,7 @@ static gint compare_menu_item_labels(gconstpointer a, gconstpointer b) /* Currently @a menu should contain only GtkMenuItems with labels. */ -static void ui_menu_sort_by_label(GtkMenu *menu) +void ui_menu_sort_by_label(GtkMenu *menu) { GList *list = gtk_container_get_children(GTK_CONTAINER(menu)); GList *node; diff --git a/src/ui_utils.h b/src/ui_utils.h index 6ac5534deb..c99e2d8143 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -369,6 +369,8 @@ gboolean ui_encodings_combo_box_set_active_encoding(GtkComboBox *combo, gint enc gchar *ui_get_project_directory(const gchar *path); +void ui_menu_sort_by_label(GtkMenu *menu); + void ui_menu_popup(GtkMenu* menu, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time); #endif /* GEANY_PRIVATE */ From db3c3814b0b04185bfd3bdd0230951c0e79621d0 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 15 Feb 2023 11:12:17 +0000 Subject: [PATCH 3/4] Remove redundant checks for null ft --- src/filetypes.c | 3 ++- src/templates.c | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/filetypes.c b/src/filetypes.c index c247de2d35..de21e902de 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -513,7 +513,8 @@ static GeanyFiletype *detect_filetype_conf_file(const gchar *utf8_filename) /* Detect filetype only based on the filename extension. - * utf8_filename can include the full path. */ + * utf8_filename can include the full path. + * Returns: non-NULL */ GeanyFiletype *filetypes_detect_from_extension(const gchar *utf8_filename) { gchar *base_filename; diff --git a/src/templates.c b/src/templates.c index 345b2a9bbc..5181ab97d0 100644 --- a/src/templates.c +++ b/src/templates.c @@ -277,17 +277,14 @@ static void populate_file_template_menu(GtkWidget *menu) gchar *fname = node->data; GeanyFiletype *ft = filetypes_detect_from_extension(fname); - if (ft) - ft_groups[ft->id].count++; + ft_groups[ft->id].count++; } foreach_slist(node, list) { gchar *fname = node->data; GeanyFiletype *ft = filetypes_detect_from_extension(fname); - FTMenu *group = NULL; + FTMenu *group = &ft_groups[ft->id]; - if (ft) - group = &ft_groups[ft->id]; if (group->count == 1) add_file_item(fname, menu); else From 6e611ae02e7105d516b4ff63fff29cbe47dd27d2 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 1 Mar 2023 11:56:55 +0000 Subject: [PATCH 4/4] Update docs --- doc/geany.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/geany.txt b/doc/geany.txt index 5612b9558a..7f1e8e0619 100644 --- a/doc/geany.txt +++ b/doc/geany.txt @@ -4930,7 +4930,8 @@ File templates File templates are templates used as the basis of a new file. To use them, choose the *New (with Template)* menu item from the *File* -menu. +menu. If there is more than one template for a filetype then they +will be grouped in a submenu. By default, file templates are installed for some filetypes. Custom file templates can be added by creating the appropriate template file. You can