file-browser: Add 'Delete' to context menu

This commit is contained in:
K. Lange 2022-08-17 19:31:47 +09:00
parent 89325bb409
commit 74b6dcc8e3
2 changed files with 111 additions and 7 deletions

View File

@ -1445,6 +1445,44 @@ static void _menu_action_paste(struct MenuEntry * entry) {
yutani_special_request(yctx, NULL, YUTANI_SPECIAL_REQUEST_CLIPBOARD);
}
static void _menu_action_delete(struct MenuEntry * entry) {
size_t filesToDelete = 0;
for (int i = 0; i < file_pointers_len; ++i) {
if (file_pointers[i]->selected) filesToDelete++;
}
int base_is_root = !strcmp(current_directory, "/"); /* avoid redundant slash */
char ** args = malloc(sizeof(char*) * (filesToDelete + 3));
args[0] = "/bin/prompt_and_delete.krk";
args[1] = malloc(100);
snprintf(args[1],100,"%d",getpid());
size_t counter = 2;
for (int i = 0; i < file_pointers_len; ++i) {
if (file_pointers[i]->selected) {
const char * name = file_pointers[i]->type == 2 ? file_pointers[i]->filename : file_pointers[i]->name;
size_t len = strlen(current_directory) + !base_is_root + strlen(name) + 1;
args[counter] = malloc(len);
snprintf(args[counter], len, "%s%s%s", current_directory, base_is_root ? "" : "/", name);
counter++;
}
}
args[counter] = NULL;
pid_t child = fork();
if (!child) {
execv(args[0], args);
exit(1);
} else if (child < 0) {
fprintf(stderr, "Error forking.\n");
}
for (size_t i = 1; i < counter; ++i) {
free(args[i]);
}
free(args);
}
/* Help > About File Browser */
static void _menu_action_about(struct MenuEntry * entry) {
/* Show About dialog */
@ -1787,14 +1825,14 @@ static void _scroll_down(void) {
}
}
static int signalResponse = 0;
/**
* Desktop mode responsds to sig_usr2 by returning to
* the bottom of the Z-order stack.
*/
static void sig_usr2(int sig) {
yutani_set_stack(yctx, main_window, YUTANI_ZORDER_BOTTOM);
_menu_action_refresh(NULL);
signal(SIGUSR2, sig_usr2);
signalResponse |= 1;
}
/**
@ -1802,8 +1840,11 @@ static void sig_usr2(int sig) {
* to the current display size.
*/
static void sig_usr1(int sig) {
yutani_window_resize_offer(yctx, main_window, yctx->display_width, yctx->display_height);
signal(SIGUSR1, sig_usr1);
signalResponse |= 2;
}
static void sig_urg(int sig) {
signalResponse |= 4;
}
/**
@ -1893,6 +1934,14 @@ static void show_context_menu(struct yutani_msg_window_mouse_event * me) {
}
}
static void set_signal_handler(int signum, void (*handler)(int)) {
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0; /* do not restart syscalls, do not reset handler */
sigaction(signum, &action, NULL);
}
int main(int argc, char * argv[]) {
yctx = yutani_init();
@ -1907,8 +1956,8 @@ int main(int argc, char * argv[]) {
is_desktop_background = 1;
menu_bar_height = 0;
nav_bar_height = 0;
signal(SIGUSR1, sig_usr1);
signal(SIGUSR2, sig_usr2);
set_signal_handler(SIGUSR1, sig_usr1);
set_signal_handler(SIGUSR2, sig_usr2);
draw_background(yctx->display_width, yctx->display_height);
main_window = yutani_window_create_flags(yctx, yctx->display_width, yctx->display_height, YUTANI_WINDOW_FLAG_NO_STEAL_FOCUS);
yutani_window_move(yctx, main_window, 0, 0);
@ -1930,6 +1979,8 @@ int main(int argc, char * argv[]) {
set_view_mode(VIEW_MODE_TILES);
}
set_signal_handler(SIGURG, sig_urg);
if (arg_ind < argc) {
chdir(argv[arg_ind]);
}
@ -1990,7 +2041,9 @@ int main(int argc, char * argv[]) {
menu_insert(context_menu, menu_create_normal(NULL,NULL,"Copy",_menu_action_copy));
menu_insert(context_menu, menu_create_normal(NULL,NULL,"Paste",_menu_action_paste));
menu_insert(context_menu, menu_create_separator());
menu_insert(context_menu, menu_create_normal(NULL,NULL,"Delete",_menu_action_delete));
if (!is_desktop_background) {
menu_insert(context_menu, menu_create_separator());
menu_insert(context_menu, menu_create_normal("up",NULL,"Up",_menu_action_up));
}
menu_insert(context_menu, menu_create_normal("refresh",NULL,"Refresh",_menu_action_refresh));
@ -2024,6 +2077,19 @@ int main(int argc, char * argv[]) {
int fds[1] = {fileno(yctx->sock)};
int index = fswait2(1,fds,wallpaper_old ? 10 : 200);
if (index < 0 && signalResponse) {
if (signalResponse & 1) {
yutani_set_stack(yctx, main_window, YUTANI_ZORDER_BOTTOM);
_menu_action_refresh(NULL);
} else if (signalResponse & 2) {
yutani_window_resize_offer(yctx, main_window, yctx->display_width, yctx->display_height);
} else if (signalResponse & 4) {
_menu_action_refresh(NULL);
}
signalResponse = 0;
continue;
}
maybe_blink_cursor();
if (index == 1) {

38
apps/prompt_and_delete.krk Executable file
View File

@ -0,0 +1,38 @@
#!/bin/kuroko
import kuroko
import os
import _waitpid
let count = len(kuroko.argv)
if count < 3:
print("expected at least two arguments")
return 1
let callbackPid = int(kuroko.argv[1])
if callbackPid < 1:
print("suspicious callback pid:", callbackPid)
return 1
count -= 2
def show_dialog(msg,title="File Browser",icon="/usr/share/icons/48/folder.png"):
let pid = os.fork()
if pid == 0:
os.execvp('showdialog',['showdialog',title,icon,msg])
os.exit(1)
while True:
let result = _waitpid.waitpid(pid)
if result[0] != pid:
continue
return result[1] == 0
if show_dialog(f'This will permanently delete {count} file{"s" if count != 1 else ""}.'):
for file in kuroko.argv[2:]:
try:
os.remove(file)
except Exception as e:
if not show_dialog(f'An error occured while trying to delete "{file}":\n{e.arg}'):
break
os.kill(callbackPid, 21) # SIGURG
else:
return 1