Commit 36b09fa0 authored by guns's avatar guns
Browse files

Add prev_dir and next_dir navigation actions

Many image collections are organized by directory, so it is nice to have
jump-to-adjacent-directory navigation.

e.g. Given the following file hierarchy:

    .
    ├── A
    │   ├── 1.jpg
    │   ├── 2.jpg
    │   └── C
    │       ├── 1.jpg
    │       ├── 2.jpg
    │       └── 3.jpg
    └── B
        ├── 1.jpg
        ├── 2.jpg
        └── 3.jpg

`feh --recursive` creates the following filelist:

    A/1.jpg <---- current_file
    A/2.jpg
    A/C/1.jpg
    A/C/2.jpg
    A/C/3.jpg
    B/1.jpg
    B/2.jpg
    B/3.jpg

If we press [next_dir], we move the current_file pointer to:

    A/1.jpg
    A/2.jpg
    A/C/1.jpg <-- current_file
    A/C/2.jpg
    A/C/3.jpg
    B/1.jpg
    B/2.jpg
    B/3.jpg

Pressing [next_dir] again moves the pointer to:

    A/1.jpg
    A/2.jpg
    A/C/1.jpg
    A/C/2.jpg
    A/C/3.jpg
    B/1.jpg <---- current_file
    B/2.jpg
    B/3.jpg

[next_dir] now moves the pointer back to the top of the list:

    A/1.jpg <---- current_file
    A/2.jpg
    A/C/1.jpg
    A/C/2.jpg
    A/C/3.jpg
    B/1.jpg
    B/2.jpg
    B/3.jpg

Pressing [prev_dir] from here moves backwards to the first image of the
previous directory:

    A/1.jpg
    A/2.jpg
    A/C/1.jpg
    A/C/2.jpg
    A/C/3.jpg
    B/1.jpg <---- current_file
    B/2.jpg
    B/3.jpg

When starting from an position that is not the first image of a
directory, [prev_dir] moves the pointer to the first image of the
current directory.

These actions combine well with `--sort dirname` since all regular files
in a directory will be sorted before any subdirectories, avoiding a
filelist like the following:

    A/1.jpg
    A/SUBDIR/2.jpg
    A/SUBDIR/3.jpg
    A/4.jpg

With `--sort dirname` that filelist becomes:

    A/1.jpg
    A/4.jpg
    A/SUBDIR/2.jpg
    A/SUBDIR/3.jpg
parent 7db8895f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1284,6 +1284,12 @@ Close current window
.
Jump to a random position in the current filelist
.
.It \&[, \&] Bq prev_dir, next_dir
.
Jump to the first image of the previous or next sequence of images sharing
a directory name in the current filelist.  Use --sort dirname if you would
like to ensure that all images in a directory are grouped together.
.
.It < , > Bq orient_3 , orient_1
.
In place editing - rotate the images 90 degrees (counter)clockwise.
+3 −1
Original line number Diff line number Diff line
@@ -102,7 +102,9 @@ enum text_bg { TEXT_BG_CLEAR = 0, TEXT_BG_TINTED };

enum slide_change { SLIDE_NEXT, SLIDE_PREV, SLIDE_RAND, SLIDE_FIRST, SLIDE_LAST,
	SLIDE_JUMP_FWD,
	SLIDE_JUMP_BACK
	SLIDE_JUMP_BACK,
	SLIDE_JUMP_NEXT_DIR,
	SLIDE_JUMP_PREV_DIR
};

enum image_bg { IMAGE_BG_CHECKS = 1, IMAGE_BG_BLACK, IMAGE_BG_WHITE };
+14 −0
Original line number Diff line number Diff line
@@ -110,6 +110,8 @@ void init_keyevents(void) {
	feh_set_kb(&keys.next_img  , 0, XK_Right     , 0, XK_n         , 0, XK_space);
	feh_set_kb(&keys.jump_back , 0, XK_Page_Up   , 0, XK_KP_Page_Up, 0, 0);
	feh_set_kb(&keys.jump_fwd  , 0, XK_Page_Down , 0, XK_KP_Page_Down,0,0);
	feh_set_kb(&keys.prev_dir  , 0, XK_bracketleft, 0, 0           , 0, 0);
	feh_set_kb(&keys.next_dir  , 0, XK_bracketright, 0, 0          , 0, 0);
	feh_set_kb(&keys.jump_random,0, XK_z         , 0, 0            , 0, 0);
	feh_set_kb(&keys.quit      , 0, XK_Escape    , 0, XK_q         , 0, 0);
	feh_set_kb(&keys.close     , 0, XK_x         , 0, 0            , 0, 0);
@@ -222,6 +224,10 @@ void init_keyevents(void) {
			cur_kb = &keys.jump_back;
		else if (!strcmp(action, "jump_fwd"))
			cur_kb = &keys.jump_fwd;
		else if (!strcmp(action, "prev_dir"))
			cur_kb = &keys.prev_dir;
		else if (!strcmp(action, "next_dir"))
			cur_kb = &keys.next_dir;
		else if (!strcmp(action, "jump_random"))
			cur_kb = &keys.jump_random;
		else if (!strcmp(action, "quit"))
@@ -532,6 +538,14 @@ void feh_event_handle_keypress(XEvent * ev)
		else if (winwid->type == WIN_TYPE_THUMBNAIL)
			feh_thumbnail_select_next(winwid, 10);
	}
	else if (feh_is_kp(&keys.next_dir, keysym, state)) {
		if (opt.slideshow)
			slideshow_change_image(winwid, SLIDE_JUMP_NEXT_DIR, 1);
	}
	else if (feh_is_kp(&keys.prev_dir, keysym, state)) {
		if (opt.slideshow)
			slideshow_change_image(winwid, SLIDE_JUMP_PREV_DIR, 1);
	}
	else if (feh_is_kp(&keys.quit, keysym, state)) {
		winwidget_destroy_all();
	}
+2 −0
Original line number Diff line number Diff line
@@ -153,6 +153,8 @@ struct __fehkb {
	struct __fehkey jump_back;
	struct __fehkey quit;
	struct __fehkey jump_fwd;
	struct __fehkey prev_dir;
	struct __fehkey next_dir;
	struct __fehkey remove;
	struct __fehkey delete;
	struct __fehkey jump_first;
+38 −0
Original line number Diff line number Diff line
@@ -322,6 +322,44 @@ void slideshow_change_image(winwidget winwid, int change, int render)
			   try the previous file, not another jmp */
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_NEXT_DIR:
			{
				char old_dir[FEH_MAX_DIRNAME_LEN], new_dir[FEH_MAX_DIRNAME_LEN];
				int j;

				feh_file_dirname(old_dir, FEH_FILE(current_file->data), FEH_MAX_DIRNAME_LEN);

				for (j = 0; j < our_filelist_len; j++) {
					current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
					feh_file_dirname(new_dir, FEH_FILE(current_file->data), FEH_MAX_DIRNAME_LEN);
					if (strcmp(old_dir, new_dir) != 0)
						break;
				}
			}
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_PREV_DIR:
			{
				char old_dir[FEH_MAX_DIRNAME_LEN], new_dir[FEH_MAX_DIRNAME_LEN];
				int j;

				/* Start the search from the previous file in case we are on
				   the first file of a directory */
				current_file = feh_list_jump(filelist, current_file, BACK, 1);
				feh_file_dirname(old_dir, FEH_FILE(current_file->data), FEH_MAX_DIRNAME_LEN);

				for (j = 0; j < our_filelist_len; j++) {
					current_file = feh_list_jump(filelist, current_file, BACK, 1);
					feh_file_dirname(new_dir, FEH_FILE(current_file->data), FEH_MAX_DIRNAME_LEN);
					if (strcmp(old_dir, new_dir) != 0)
						break;
				}

				/* Next file is the first entry of prev_dir */
				current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
			}
			change = SLIDE_NEXT;
			break;
		default:
			eprintf("BUG!\n");
			break;