mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
[FileBrowser] Add sorting-method. (#1340)
* [FileBrowser] Add sorting-method. * [FileBrowser] Convert -file-browser-directory to new config format.
This commit is contained in:
parent
330402aa13
commit
0ff0866be7
6 changed files with 192 additions and 19 deletions
|
@ -118,9 +118,6 @@ Settings config = {
|
||||||
/** Desktop Link launch command */
|
/** Desktop Link launch command */
|
||||||
.drun_url_launcher = "xdg-open",
|
.drun_url_launcher = "xdg-open",
|
||||||
|
|
||||||
/** Directory the file browser starts in */
|
|
||||||
.file_browser_directory = NULL,
|
|
||||||
|
|
||||||
/** Window fields to match in window mode*/
|
/** Window fields to match in window mode*/
|
||||||
.window_match_fields = "all",
|
.window_match_fields = "all",
|
||||||
/** Monitor */
|
/** Monitor */
|
||||||
|
|
20
doc/rofi.1
20
doc/rofi.1
|
@ -1167,10 +1167,26 @@ Message can be multi\-line.
|
||||||
|
|
||||||
.SS File browser settings
|
.SS File browser settings
|
||||||
.PP
|
.PP
|
||||||
\fB\fC\-filebrowser\-directory\fR \fIdirectory\fP
|
File browser behavior can be controlled via the following options:
|
||||||
|
|
||||||
.PP
|
.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
|
.SS Other
|
||||||
.PP
|
.PP
|
||||||
|
|
|
@ -698,9 +698,24 @@ Message can be multi-line.
|
||||||
|
|
||||||
### File browser settings
|
### 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
|
### Other
|
||||||
|
|
||||||
|
|
|
@ -116,9 +116,6 @@ typedef struct
|
||||||
/** Desktop Link launch command */
|
/** Desktop Link launch command */
|
||||||
char * drun_url_launcher;
|
char * drun_url_launcher;
|
||||||
|
|
||||||
/** Directory the file browser starts in */
|
|
||||||
char * file_browser_directory;
|
|
||||||
|
|
||||||
/** Search case sensitivity */
|
/** Search case sensitivity */
|
||||||
unsigned int case_sensitive;
|
unsigned int case_sensitive;
|
||||||
/** Cycle through in the element list */
|
/** Cycle through in the element list */
|
||||||
|
|
|
@ -36,11 +36,11 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#include "mode.h"
|
#include "mode.h"
|
||||||
|
#include "theme.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
#include "mode-private.h"
|
#include "mode-private.h"
|
||||||
#include "dialogs/filebrowser.h"
|
#include "dialogs/filebrowser.h"
|
||||||
#include "rofi.h"
|
#include "rofi.h"
|
||||||
#include "settings.h"
|
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -59,6 +59,26 @@ enum FBFileType
|
||||||
RFILE,
|
RFILE,
|
||||||
NUM_FILE_TYPES,
|
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 */
|
/** Icons to use for the file type */
|
||||||
const char *icon_name[NUM_FILE_TYPES] =
|
const char *icon_name[NUM_FILE_TYPES] =
|
||||||
{
|
{
|
||||||
|
@ -73,6 +93,7 @@ typedef struct
|
||||||
enum FBFileType type;
|
enum FBFileType type;
|
||||||
uint32_t icon_fetch_uid;
|
uint32_t icon_fetch_uid;
|
||||||
gboolean link;
|
gboolean link;
|
||||||
|
time_t time;
|
||||||
} FBFile;
|
} FBFile;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -82,6 +103,15 @@ typedef struct
|
||||||
unsigned int array_length;
|
unsigned int array_length;
|
||||||
} FileBrowserModePrivateData;
|
} 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 )
|
static void free_list ( FileBrowserModePrivateData *pd )
|
||||||
{
|
{
|
||||||
for ( unsigned int i = 0; i < pd->array_length; i++ ) {
|
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 <sys/types.h>
|
||||||
#include <dirent.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 *fa = (FBFile *) a;
|
||||||
FBFile *fb = (FBFile *) b;
|
FBFile *fb = (FBFile *) b;
|
||||||
|
|
||||||
if ( fa->type != fb->type ) {
|
if ( fa->type != fb->type ) {
|
||||||
return 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 );
|
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 );
|
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].type = UP;
|
||||||
pd->array[pd->array_length].icon_fetch_uid = 0;
|
pd->array[pd->array_length].icon_fetch_uid = 0;
|
||||||
pd->array[pd->array_length].link = FALSE;
|
pd->array[pd->array_length].link = FALSE;
|
||||||
|
pd->array[pd->array_length].time = -1;
|
||||||
pd->array_length++;
|
pd->array_length++;
|
||||||
continue;
|
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].type = ( rd->d_type == DT_DIR ) ? DIRECTORY : RFILE;
|
||||||
pd->array[pd->array_length].icon_fetch_uid = 0;
|
pd->array[pd->array_length].icon_fetch_uid = 0;
|
||||||
pd->array[pd->array_length].link = FALSE;
|
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++;
|
pd->array_length++;
|
||||||
break;
|
break;
|
||||||
case DT_LNK:
|
case DT_LNK:
|
||||||
|
@ -177,6 +281,10 @@ static void get_file_browser ( Mode *sw )
|
||||||
else if ( S_ISREG ( statbuf.st_mode ) ) {
|
else if ( S_ISREG ( statbuf.st_mode ) ) {
|
||||||
pd->array[pd->array_length].type = RFILE;
|
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 {
|
else {
|
||||||
g_warning ( "Failed to stat file: %s, %s", file, strerror ( errno ) );
|
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 );
|
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 ) {
|
static void file_browser_mode_init_current_dir ( Mode *sw ) {
|
||||||
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
|
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
|
||||||
|
|
||||||
gboolean config_has_valid_dir = config.file_browser_directory != NULL
|
ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
|
||||||
&& g_file_test ( config.file_browser_directory, G_FILE_TEST_IS_DIR );
|
|
||||||
|
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 ) {
|
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 {
|
} else {
|
||||||
char *current_dir = NULL;
|
char *current_dir = NULL;
|
||||||
char *cache_file = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, 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 ) );
|
FileBrowserModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
|
||||||
mode_set_private_data ( sw, (void *) pd );
|
mode_set_private_data ( sw, (void *) pd );
|
||||||
|
|
||||||
|
file_browser_mode_init_config ( sw );
|
||||||
file_browser_mode_init_current_dir ( sw );
|
file_browser_mode_init_current_dir ( sw );
|
||||||
|
|
||||||
// Load content.
|
// Load content.
|
||||||
|
|
|
@ -132,9 +132,6 @@ static XrmOption xrmOptions[] = {
|
||||||
{ xrm_String, "drun-url-launcher", { .str = &config.drun_url_launcher }, NULL,
|
{ xrm_String, "drun-url-launcher", { .str = &config.drun_url_launcher }, NULL,
|
||||||
"Command to open a Desktop Entry that is a Link.", CONFIG_DEFAULT },
|
"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,
|
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL,
|
||||||
"Disable history in run/ssh", CONFIG_DEFAULT },
|
"Disable history in run/ssh", CONFIG_DEFAULT },
|
||||||
{ xrm_String, "ignored-prefixes", { .str = &config.ignored_prefixes }, NULL,
|
{ xrm_String, "ignored-prefixes", { .str = &config.ignored_prefixes }, NULL,
|
||||||
|
|
Loading…
Reference in a new issue