From 23fead85491631ea99d9d1d20919d9cf7389d96d Mon Sep 17 00:00:00 2001 From: Jombo Date: Sun, 28 Dec 2025 04:35:13 +0000 Subject: [PATCH 1/5] Add support for sorting files by extension - Added NEMO_FILE_SORT_BY_EXTENSION to sort types. - Implemented compare_by_extension logic with case-insensitive grouping. - Added Extension column to List View for sorting. - Added Sort by Extension to Icon View context menu. - Added Extension sort option to Desktop View and Customization Overlay. --- gresources/nemo-desktop-overlay.glade | 5 ++ gresources/nemo-icon-view-ui.xml | 8 +-- libnemo-private/nemo-column-utilities.c | 7 +++ libnemo-private/nemo-file.c | 72 +++++++++++++++++++++++-- libnemo-private/nemo-file.h | 10 ++-- src/nemo-desktop-icon-grid-view.c | 11 +++- src/nemo-desktop-overlay.c | 3 ++ src/nemo-icon-view.c | 25 ++++++--- 8 files changed, 121 insertions(+), 20 deletions(-) diff --git a/gresources/nemo-desktop-overlay.glade b/gresources/nemo-desktop-overlay.glade index fbc4df232..93678fbb1 100644 --- a/gresources/nemo-desktop-overlay.glade +++ b/gresources/nemo-desktop-overlay.glade @@ -131,6 +131,11 @@ Date Desktop Sort by Date + + 10 + Extension + Desktop Sort by Extension + diff --git a/gresources/nemo-icon-view-ui.xml b/gresources/nemo-icon-view-ui.xml index bfe9baf60..322c27db4 100644 --- a/gresources/nemo-icon-view-ui.xml +++ b/gresources/nemo-icon-view-ui.xml @@ -10,8 +10,8 @@ - - + + @@ -32,8 +32,8 @@ - - + + diff --git a/libnemo-private/nemo-column-utilities.c b/libnemo-private/nemo-column-utilities.c index e7e97d8f3..1798ef30d 100644 --- a/libnemo-private/nemo-column-utilities.c +++ b/libnemo-private/nemo-column-utilities.c @@ -143,6 +143,13 @@ get_builtin_columns (void) "label", _("MIME Type"), "description", _("The mime type of the file."), NULL)); + columns = g_list_append (columns, + g_object_new (NEMO_TYPE_COLUMN, + "name", "extension", + "attribute", "extension", + "label", _("Extension"), + "description", _("The extension of the file."), + NULL)); #ifdef HAVE_SELINUX columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c index 01d23be22..64da2ef37 100644 --- a/libnemo-private/nemo-file.c +++ b/libnemo-private/nemo-file.c @@ -163,9 +163,9 @@ static GQuark attribute_name_q, attribute_where_q, attribute_link_target_q, attribute_volume_q, - attribute_free_space_q, - attribute_search_result_snippet_q, - attribute_search_result_count_q; + attribute_free_space_q, + attribute_extension_q, + attribute_search_result_snippet_q, attribute_search_result_count_q; static void nemo_file_info_iface_init (NemoFileInfoInterface *iface); @@ -3226,6 +3226,48 @@ compare_by_type (NemoFile *file_1, NemoFile *file_2, gboolean detailed) return result; } +static int +compare_by_extension (NemoFile *file_1, NemoFile *file_2) +{ + const char *name_1, *name_2; + char *ext_1, *ext_2; + char *ext_1_folded, *ext_2_folded; + int result; + + name_1 = nemo_file_peek_display_name (file_1); + name_2 = nemo_file_peek_display_name (file_2); + + ext_1 = eel_filename_get_extension_offset (name_1); + ext_2 = eel_filename_get_extension_offset (name_2); + + if (ext_1 == NULL && ext_2 == NULL) { + return 0; + } + + if (ext_1 == NULL) { + return -1; + } + + if (ext_2 == NULL) { + return 1; + } + + /* Skip the dot */ + ext_1++; + ext_2++; + + /* Case-insensitive comparison */ + ext_1_folded = g_utf8_casefold (ext_1, -1); + ext_2_folded = g_utf8_casefold (ext_2, -1); + + result = g_utf8_collate (ext_1_folded, ext_2_folded); + + g_free (ext_1_folded); + g_free (ext_2_folded); + + return result; +} + static int compare_by_time (NemoFile *file_1, NemoFile *file_2, NemoDateType type) { @@ -3410,6 +3452,12 @@ nemo_file_compare_for_sort (NemoFile *file_1, if (result == 0) { result = compare_by_full_path (file_1, file_2); } + break; + case NEMO_FILE_SORT_BY_EXTENSION: + result = compare_by_extension (file_1, file_2); + if (result == 0) { + result = compare_by_full_path (file_1, file_2); + } break; case NEMO_FILE_SORT_BY_MTIME: result = compare_by_time (file_1, file_2, NEMO_DATE_TYPE_MODIFIED); @@ -3500,6 +3548,13 @@ nemo_file_compare_for_sort_by_attribute_q (NemoFile *file_1, favorites_first, reversed, search_dir); + } else if (attribute == attribute_extension_q) { + return nemo_file_compare_for_sort (file_1, file_2, + NEMO_FILE_SORT_BY_EXTENSION, + directories_first, + favorites_first, + reversed, + search_dir); } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q || attribute == attribute_date_modified_with_time_q || @@ -6724,6 +6779,16 @@ nemo_file_get_string_attribute_q (NemoFile *file, GQuark attribute_q) if (attribute_q == attribute_name_q) { return nemo_file_get_display_name (file); } + if (attribute_q == attribute_extension_q) { + const char *name; + char *ext; + name = nemo_file_peek_display_name (file); + ext = eel_filename_get_extension_offset (name); + if (ext) { + return g_strdup (ext + 1); + } + return NULL; + } if (attribute_q == attribute_type_q) { return nemo_file_get_type_as_string (file); } @@ -8959,6 +9024,7 @@ nemo_file_class_init (NemoFileClass *class) attribute_link_target_q = g_quark_from_static_string ("link_target"); attribute_volume_q = g_quark_from_static_string ("volume"); attribute_free_space_q = g_quark_from_static_string ("free_space"); + attribute_extension_q = g_quark_from_static_string ("extension"); attribute_search_result_snippet_q = g_quark_from_string ("search_result_snippet"); attribute_search_result_count_q = g_quark_from_string ("search_result_count"); diff --git a/libnemo-private/nemo-file.h b/libnemo-private/nemo-file.h index 8b0f76975..f8583aae4 100644 --- a/libnemo-private/nemo-file.h +++ b/libnemo-private/nemo-file.h @@ -63,11 +63,11 @@ typedef enum { NEMO_FILE_SORT_BY_DETAILED_TYPE, NEMO_FILE_SORT_BY_MTIME, NEMO_FILE_SORT_BY_ATIME, - NEMO_FILE_SORT_BY_TRASHED_TIME, - NEMO_FILE_SORT_BY_BTIME, - NEMO_FILE_SORT_BY_SEARCH_RESULT_COUNT -} NemoFileSortType; - + NEMO_FILE_SORT_BY_TRASHED_TIME, + NEMO_FILE_SORT_BY_BTIME, + NEMO_FILE_SORT_BY_SEARCH_RESULT_COUNT, + NEMO_FILE_SORT_BY_EXTENSION + } NemoFileSortType; typedef enum { NEMO_REQUEST_NOT_STARTED, NEMO_REQUEST_IN_PROGRESS, diff --git a/src/nemo-desktop-icon-grid-view.c b/src/nemo-desktop-icon-grid-view.c index 4ef00601c..4a263e185 100644 --- a/src/nemo-desktop-icon-grid-view.c +++ b/src/nemo-desktop-icon-grid-view.c @@ -109,6 +109,11 @@ static const DesktopSortCriterion sort_criteria[] = { "Desktop Sort by Date", "modification date", NEMO_FILE_SORT_BY_MTIME + }, + { + "Desktop Sort by Extension", + "extension", + NEMO_FILE_SORT_BY_EXTENSION } }; @@ -1085,7 +1090,11 @@ static const GtkRadioActionEntry desktop_sort_radio_entries[] = { { "Desktop Sort by Date", NULL, N_("Date"), NULL, NULL, - NEMO_FILE_SORT_BY_MTIME } + NEMO_FILE_SORT_BY_MTIME }, + { "Desktop Sort by Extension", NULL, + N_("Extension"), NULL, + NULL, + NEMO_FILE_SORT_BY_EXTENSION } }; static const GtkActionEntry desktop_grid_entries[] = { diff --git a/src/nemo-desktop-overlay.c b/src/nemo-desktop-overlay.c index b40d507d5..ca04f1adc 100644 --- a/src/nemo-desktop-overlay.c +++ b/src/nemo-desktop-overlay.c @@ -207,6 +207,9 @@ sync_controls (NemoDesktopOverlay *overlay, case NEMO_FILE_SORT_BY_MTIME: combo_id = "Desktop Sort by Date"; break; + case NEMO_FILE_SORT_BY_EXTENSION: + combo_id = "Desktop Sort by Extension"; + break; case NEMO_FILE_SORT_BY_DISPLAY_NAME: default: combo_id = "Desktop Sort by Name"; diff --git a/src/nemo-icon-view.c b/src/nemo-icon-view.c index 5f1b1ce3f..cc5c90408 100644 --- a/src/nemo-icon-view.c +++ b/src/nemo-icon-view.c @@ -165,13 +165,20 @@ static const SortCriterion sort_criteria[] = { N_("by Modification _Date"), N_("Keep icons sorted by modification date in rows") }, - { - NEMO_FILE_SORT_BY_TRASHED_TIME, - "trashed", - "Sort by Trash Time", - N_("by T_rash Time"), - N_("Keep icons sorted by trash time in rows") - } + { + NEMO_FILE_SORT_BY_TRASHED_TIME, + "trashed", + "Sort by Trash Time", + N_("by T_rash Time"), + N_("Keep icons sorted by trash time in rows") + }, + { + NEMO_FILE_SORT_BY_EXTENSION, + "extension", + "Sort by Extension", + N_("by _Extension"), + N_("Keep icons sorted by extension in rows") + } }; static void nemo_icon_view_set_directory_sort_by (NemoIconView *icon_view, @@ -1448,6 +1455,10 @@ static const GtkRadioActionEntry arrange_radio_entries[] = { N_("By T_rash Time"), NULL, N_("Keep icons sorted by trash time in rows"), NEMO_FILE_SORT_BY_TRASHED_TIME }, + { "Sort by Extension", NULL, + N_("By _Extension"), NULL, + N_("Keep icons sorted by extension in rows"), + NEMO_FILE_SORT_BY_EXTENSION }, }; static void From 5bcbedc6cef57609d7f92ad9c2f8f1d365c2730a Mon Sep 17 00:00:00 2001 From: Jombo <44863559+Jombolio@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:52:45 +0000 Subject: [PATCH 2/5] Fix indentation for Sort by Extension menuitem --- gresources/nemo-icon-view-ui.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gresources/nemo-icon-view-ui.xml b/gresources/nemo-icon-view-ui.xml index 322c27db4..28c164e03 100644 --- a/gresources/nemo-icon-view-ui.xml +++ b/gresources/nemo-icon-view-ui.xml @@ -11,7 +11,8 @@ - + + @@ -33,7 +34,8 @@ - + + From 9d0f3d57fe844d3167ab1b823e021fb9e2157a79 Mon Sep 17 00:00:00 2001 From: Jombo <44863559+Jombolio@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:56:30 +0000 Subject: [PATCH 3/5] Formatting is hAAAAAAAAAAAAAAAAAAAARD --- libnemo-private/nemo-file.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c index 64da2ef37..861f20183 100644 --- a/libnemo-private/nemo-file.c +++ b/libnemo-private/nemo-file.c @@ -163,9 +163,10 @@ static GQuark attribute_name_q, attribute_where_q, attribute_link_target_q, attribute_volume_q, - attribute_free_space_q, - attribute_extension_q, - attribute_search_result_snippet_q, attribute_search_result_count_q; + attribute_free_space_q, + attribute_extension_q, + attribute_search_result_snippet_q, + attribute_search_result_count_q; static void nemo_file_info_iface_init (NemoFileInfoInterface *iface); From a5aed2f131353fb69d3b74428096b2593e11c738 Mon Sep 17 00:00:00 2001 From: Jombo <44863559+Jombolio@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:59:36 +0000 Subject: [PATCH 4/5] Reorder NemoFileSortType enum values --- libnemo-private/nemo-file.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libnemo-private/nemo-file.h b/libnemo-private/nemo-file.h index f8583aae4..ae2598048 100644 --- a/libnemo-private/nemo-file.h +++ b/libnemo-private/nemo-file.h @@ -63,11 +63,11 @@ typedef enum { NEMO_FILE_SORT_BY_DETAILED_TYPE, NEMO_FILE_SORT_BY_MTIME, NEMO_FILE_SORT_BY_ATIME, - NEMO_FILE_SORT_BY_TRASHED_TIME, - NEMO_FILE_SORT_BY_BTIME, - NEMO_FILE_SORT_BY_SEARCH_RESULT_COUNT, - NEMO_FILE_SORT_BY_EXTENSION - } NemoFileSortType; + NEMO_FILE_SORT_BY_TRASHED_TIME, + NEMO_FILE_SORT_BY_BTIME, + NEMO_FILE_SORT_BY_SEARCH_RESULT_COUNT, + NEMO_FILE_SORT_BY_EXTENSION +} NemoFileSortType; typedef enum { NEMO_REQUEST_NOT_STARTED, NEMO_REQUEST_IN_PROGRESS, From 78f94d928e3639af172a0bb5353d50e875b8f976 Mon Sep 17 00:00:00 2001 From: Jombo <44863559+Jombolio@users.noreply.github.com> Date: Sun, 28 Dec 2025 05:01:25 +0000 Subject: [PATCH 5/5] Fix formatting for sorting options in nemo-icon-view --- src/nemo-icon-view.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/nemo-icon-view.c b/src/nemo-icon-view.c index cc5c90408..8ee362d24 100644 --- a/src/nemo-icon-view.c +++ b/src/nemo-icon-view.c @@ -166,18 +166,18 @@ static const SortCriterion sort_criteria[] = { N_("Keep icons sorted by modification date in rows") }, { - NEMO_FILE_SORT_BY_TRASHED_TIME, - "trashed", - "Sort by Trash Time", - N_("by T_rash Time"), - N_("Keep icons sorted by trash time in rows") + NEMO_FILE_SORT_BY_TRASHED_TIME, + "trashed", + "Sort by Trash Time", + N_("by T_rash Time"), + N_("Keep icons sorted by trash time in rows") }, { - NEMO_FILE_SORT_BY_EXTENSION, - "extension", - "Sort by Extension", - N_("by _Extension"), - N_("Keep icons sorted by extension in rows") + NEMO_FILE_SORT_BY_EXTENSION, + "extension", + "Sort by Extension", + N_("by _Extension"), + N_("Keep icons sorted by extension in rows") } };