summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTonCherAmi <kratos661@gmail.com>2021-06-27 10:28:21 +0300
committerGitHub <noreply@github.com>2021-06-27 09:28:21 +0200
commit0ff0866be738f1bd99862fa091daad34cd21fc19 (patch)
tree9579a3857a4951f8e12b889fb4a70a0b0b12539c
parent330402aa1351c6b5397dc896345fe8ae3756e261 (diff)
[FileBrowser] Add sorting-method. (#1340)
* [FileBrowser] Add sorting-method. * [FileBrowser] Convert -file-browser-directory to new config format.
-rw-r--r--config/config.c3
-rw-r--r--doc/rofi.120
-rw-r--r--doc/rofi.1.markdown19
-rw-r--r--include/settings.h3
-rw-r--r--source/dialogs/filebrowser.c163
-rw-r--r--source/xrmoptions.c3
6 files changed, 192 insertions, 19 deletions
diff --git a/config/config.c b/config/config.c
index 8d6039cd..2ec105a6 100644
--- a/config/config.c
+++ b/config/config.c
@@ -118,9 +118,6 @@ Settings config = {
/** Desktop Link launch command */
.drun_url_launcher = "xdg-open",
- /** Directory the file browser starts in */
- .file_browser_directory = NULL,
-
/** Window fields to match in window mode*/
.window_match_fields = "all",
/** Monitor */
diff --git a/doc/rofi.1 b/doc/rofi.1
index 8df9c1f4..e6e93fd7 100644
--- a/doc/rofi.1
+++ b/doc/rofi.1
@@ -1167,10 +1167,26 @@ Message can be multi\-line.
.SS File browser settings
.PP
-\fB\fC\-filebrowser\-directory\fR \fIdirectory\fP
+File browser behavior can be controlled via the following options:
.PP
-Directory the file browser starts in.
+.RS
+
+.nf
+configuration {
+ filebrowser {
+ /** Directory the file browser starts in. */
+ directory: "/some/directory";
+ /**
+ * Sorting method. Can be set to:
+ * - "name"
+ * - "mtime" (modification time)
+ * - "atime" (access time)
+ * - "ctime" (change time)
+ */
+ sorting-method: "name";
+ }
+}
.SS Other
.PP
diff --git a/doc/rofi.1.markdown b/doc/rofi.1.markdown
index 107ef85a..20a14677 100644
--- a/doc/rofi.1.markdown
+++ b/doc/rofi.1.markdown
@@ -698,9 +698,24 @@ Message can be multi-line.
### File browser settings
-`-filebrowser-directory` *directory*
+File browser behavior can be controlled via the following options:
-Directory the file browser starts in.
+```css
+configuration {
+ filebrowser {
+ /** Directory the file browser starts in. */
+ directory: "/some/directory";
+ /**
+ * Sorting method. Can be set to:
+ * - "name"
+ * - "mtime" (modification time)
+ * - "atime" (access time)
+ * - "ctime" (change time)
+ */
+ sorting-method: "name";
+ }
+}
+```
### Other
diff --git a/include/settings.h b/include/settings.h
index 6f1cd9ca..abc9eb14 100644
--- a/include/settings.h
+++ b/include/settings.h
@@ -116,9 +116,6 @@ typedef struct
/** Desktop Link launch command */
char * drun_url_launcher;
- /** Directory the file browser starts in */
- char * file_browser_directory;
-
/** Search case sensitivity */
unsigned int case_sensitive;
/** Cycle through in the element list */
diff --git a/source/dialogs/filebrowser.c b/source/dialogs/filebrowser.c
index 6ec2a7fb..750ea97b 100644
--- a/source/dialogs/filebrowser.c
+++ b/source/dialogs/filebrowser.c
@@ -36,11 +36,11 @@
#include <dirent.h>
#include "mode.h"
+#include "theme.h"
#include "helper.h"
#include "mode-private.h"
#include "dialogs/filebrowser.h"
#include "rofi.h"
-#include "settings.h"
#include "history.h"
#include <stdint.h>
@@ -59,6 +59,26 @@ enum FBFileType
RFILE,
NUM_FILE_TYPES,
};
+
+/**
+ * Possible sorting methods
+ */
+enum FBSortingMethod
+{
+ FB_SORT_NAME,
+ FB_SORT_TIME,
+};
+
+/**
+ * Type of time to sort by
+ */
+enum FBSortingTime
+{
+ FB_MTIME,
+ FB_ATIME,
+ FB_CTIME,
+};
+
/** Icons to use for the file type */
const char *icon_name[NUM_FILE_TYPES] =
{
@@ -73,6 +93,7 @@ typedef struct
enum FBFileType type;
uint32_t icon_fetch_uid;
gboolean link;
+ time_t time;
} FBFile;
typedef struct
@@ -82,6 +103,15 @@ typedef struct
unsigned int array_length;
} FileBrowserModePrivateData;
+struct
+{
+ enum FBSortingMethod sorting_method;
+ enum FBSortingTime sorting_time;
+} file_browser_config = {
+ .sorting_method = FB_SORT_NAME,
+ .sorting_time = FB_MTIME,
+};
+
static void free_list ( FileBrowserModePrivateData *pd )
{
for ( unsigned int i = 0; i < pd->array_length; i++ ) {
@@ -96,10 +126,11 @@ static void free_list ( FileBrowserModePrivateData *pd )
#include <sys/types.h>
#include <dirent.h>
-static gint compare ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
+static gint compare_name ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
{
FBFile *fa = (FBFile *) a;
FBFile *fb = (FBFile *) b;
+
if ( fa->type != fb->type ) {
return fa->type - fb->type;
}
@@ -107,7 +138,74 @@ static gint compare ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer d
return g_strcmp0 ( fa->name, fb->name );
}
-static void get_file_browser ( Mode *sw )
+static gint compare_time ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
+{
+ FBFile *fa = (FBFile *) a;
+ FBFile *fb = (FBFile *) b;
+
+ if ( fa->time < 0 ) {
+ return -1;
+ }
+
+ if ( fb->time < 0 ) {
+ return 1;
+ }
+
+ return fb->time - fa->time;
+}
+
+static gint compare ( gconstpointer a, gconstpointer b, gpointer data )
+{
+ GCompareDataFunc comparator = NULL;
+
+ switch ( file_browser_config.sorting_method )
+ {
+ case FB_SORT_NAME:
+ comparator = compare_name;
+ break;
+ case FB_SORT_TIME:
+ comparator = compare_time;
+ break;
+ default:
+ comparator = compare_name;
+ break;
+ }
+
+ return comparator ( a, b, data );
+}
+
+static time_t get_time ( const struct stat *statbuf )
+{
+ switch ( file_browser_config.sorting_time )
+ {
+ case FB_MTIME:
+ return statbuf->st_mtim.tv_sec;
+ case FB_ATIME:
+ return statbuf->st_atim.tv_sec;
+ case FB_CTIME:
+ return statbuf->st_ctim.tv_sec;
+ default:
+ return 0;
+ }
+}
+
+static void set_time ( FBFile *file )
+{
+ gchar* path = g_filename_from_utf8 ( file->path, -1, NULL, NULL, NULL );
+
+ struct stat statbuf;
+
+ if ( stat ( path, &statbuf ) == 0 ) {
+ file->time = get_time ( &statbuf );
+ }
+ else {
+ g_warning ( "Failed to stat file: %s, %s", path, strerror ( errno ) );
+ }
+
+ g_free ( path );
+}
+
+static void get_file_browser ( Mode *sw )
{
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
/**
@@ -127,6 +225,7 @@ static void get_file_browser ( Mode *sw )
pd->array[pd->array_length].type = UP;
pd->array[pd->array_length].icon_fetch_uid = 0;
pd->array[pd->array_length].link = FALSE;
+ pd->array[pd->array_length].time = -1;
pd->array_length++;
continue;
}
@@ -152,6 +251,11 @@ static void get_file_browser ( Mode *sw )
pd->array[pd->array_length].type = ( rd->d_type == DT_DIR ) ? DIRECTORY : RFILE;
pd->array[pd->array_length].icon_fetch_uid = 0;
pd->array[pd->array_length].link = FALSE;
+
+ if ( file_browser_config.sorting_method == FB_SORT_TIME ) {
+ set_time ( &pd->array[pd->array_length] );
+ }
+
pd->array_length++;
break;
case DT_LNK:
@@ -177,6 +281,10 @@ static void get_file_browser ( Mode *sw )
else if ( S_ISREG ( statbuf.st_mode ) ) {
pd->array[pd->array_length].type = RFILE;
}
+
+ if ( file_browser_config.sorting_method == FB_SORT_TIME ) {
+ pd->array[pd->array_length].time = get_time ( &statbuf );
+ }
}
else {
g_warning ( "Failed to stat file: %s, %s", file, strerror ( errno ) );
@@ -194,14 +302,56 @@ static void get_file_browser ( Mode *sw )
g_qsort_with_data ( pd->array, pd->array_length, sizeof ( FBFile ), compare, NULL );
}
+static void file_browser_mode_init_config ( Mode *sw )
+{
+ char *msg = NULL;
+ gboolean found_error = FALSE;
+
+ ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
+
+ Property *p = rofi_theme_find_property ( wid, P_STRING, "sorting-method", TRUE );
+ if ( p != NULL && p->type == P_STRING ) {
+ if ( g_strcmp0 ( p->value.s, "name" ) == 0 ) {
+ file_browser_config.sorting_method = FB_SORT_NAME;
+ }
+ else if ( g_strcmp0 ( p->value.s, "mtime" ) == 0 ) {
+ file_browser_config.sorting_method = FB_SORT_TIME;
+ file_browser_config.sorting_time = FB_MTIME;
+ }
+ else if ( g_strcmp0 ( p->value.s, "atime" ) == 0 ) {
+ file_browser_config.sorting_method = FB_SORT_TIME;
+ file_browser_config.sorting_time = FB_ATIME;
+ }
+ else if ( g_strcmp0 ( p->value.s, "ctime" ) == 0 ) {
+ file_browser_config.sorting_method = FB_SORT_TIME;
+ file_browser_config.sorting_time = FB_CTIME;
+ }
+ else {
+ found_error = TRUE;
+
+ msg = g_strdup_printf ( "\"%s\" is not a valid filebrowser sorting method", p->value.s );
+ }
+ }
+
+ if ( found_error ) {
+ rofi_view_error_dialog ( msg, FALSE );
+
+ g_free ( msg );
+ }
+}
+
static void file_browser_mode_init_current_dir ( Mode *sw ) {
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
- gboolean config_has_valid_dir = config.file_browser_directory != NULL
- && g_file_test ( config.file_browser_directory, G_FILE_TEST_IS_DIR );
+ ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
+
+ Property *p = rofi_theme_find_property ( wid, P_STRING, "directory", TRUE );
+
+ gboolean config_has_valid_dir = p != NULL && p->type == P_STRING
+ && g_file_test ( p->value.s, G_FILE_TEST_IS_DIR );
if ( config_has_valid_dir ) {
- pd->current_dir = g_file_new_for_path ( config.file_browser_directory );
+ pd->current_dir = g_file_new_for_path ( p->value.s );
} else {
char *current_dir = NULL;
char *cache_file = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, NULL );
@@ -233,6 +383,7 @@ static int file_browser_mode_init ( Mode *sw )
FileBrowserModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
mode_set_private_data ( sw, (void *) pd );
+ file_browser_mode_init_config ( sw );
file_browser_mode_init_current_dir ( sw );
// Load content.
diff --git a/source/xrmoptions.c b/source/xrmoptions.c
index c2bb0187..aba59ee4 100644
--- a/source/xrmoptions.c
+++ b/source/xrmoptions.c
@@ -132,9 +132,6 @@ static XrmOption xrmOptions[] = {
{ xrm_String, "drun-url-launcher", { .str = &config.drun_url_launcher }, NULL,
"Command to open a Desktop Entry that is a Link.", CONFIG_DEFAULT },
- { xrm_String, "filebrowser-directory", { .str = &config.file_browser_directory }, NULL,
- "Directory the file browser starts in", CONFIG_DEFAULT },
-
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL,
"Disable history in run/ssh", CONFIG_DEFAULT },
{ xrm_String, "ignored-prefixes", { .str = &config.ignored_prefixes }, NULL,