feat: add Files app selection marquee, Properties dialog for multiple files
This commit is contained in:
@@ -21,57 +21,65 @@ static bool path_is_same_or_descendant(const char* path, const char* root) {
|
||||
return path[root_len] == '\0' || path[root_len] == '/';
|
||||
}
|
||||
|
||||
void filemanager_do_copy(FileManagerState* fm) {
|
||||
if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
|
||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
|
||||
fm->entry_types[fm->selected] == FM_ENTRY_DRIVE) return;
|
||||
static void filemanager_load_clipboard(FileManagerState* fm, bool is_cut) {
|
||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
|
||||
|
||||
filemanager_build_fullpath(fm->clipboard_path, 256,
|
||||
fm->current_path, fm->entry_names[fm->selected]);
|
||||
fm->clipboard_has_data = true;
|
||||
fm->clipboard_is_cut = false;
|
||||
int sel[64];
|
||||
int n = filemanager_collect_selection(fm, sel, 64);
|
||||
if (n <= 0) return;
|
||||
|
||||
int out = 0;
|
||||
for (int i = 0; i < n && out < 64; i++) {
|
||||
int idx = sel[i];
|
||||
if (fm->entry_types[idx] == FM_ENTRY_DRIVE) continue;
|
||||
filemanager_build_fullpath(fm->clipboard_paths[out], 256,
|
||||
fm->current_path, fm->entry_names[idx]);
|
||||
out++;
|
||||
}
|
||||
if (out == 0) return;
|
||||
|
||||
fm->clipboard_count = out;
|
||||
fm->clipboard_is_cut = is_cut;
|
||||
}
|
||||
|
||||
void filemanager_do_copy(FileManagerState* fm) {
|
||||
filemanager_load_clipboard(fm, false);
|
||||
}
|
||||
|
||||
void filemanager_do_cut(FileManagerState* fm) {
|
||||
if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
|
||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
|
||||
fm->entry_types[fm->selected] == FM_ENTRY_DRIVE) return;
|
||||
|
||||
filemanager_build_fullpath(fm->clipboard_path, 256,
|
||||
fm->current_path, fm->entry_names[fm->selected]);
|
||||
fm->clipboard_has_data = true;
|
||||
fm->clipboard_is_cut = true;
|
||||
filemanager_load_clipboard(fm, true);
|
||||
}
|
||||
|
||||
void filemanager_do_paste(FileManagerState* fm) {
|
||||
if (!fm->clipboard_has_data || filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
|
||||
if (fm->clipboard_count <= 0 ||
|
||||
filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
|
||||
|
||||
const char* basename = path_basename(fm->clipboard_path);
|
||||
char dst[512];
|
||||
filemanager_build_fullpath(dst, 512, fm->current_path, basename);
|
||||
if (montauk::streq(dst, fm->clipboard_path)) return;
|
||||
bool any_ok = false;
|
||||
bool clear_clipboard = fm->clipboard_is_cut;
|
||||
for (int i = 0; i < fm->clipboard_count; i++) {
|
||||
const char* src = fm->clipboard_paths[i];
|
||||
const char* basename = path_basename(src);
|
||||
char dst[512];
|
||||
filemanager_build_fullpath(dst, 512, fm->current_path, basename);
|
||||
if (montauk::streq(dst, src)) continue;
|
||||
|
||||
// Check if source is a directory by trying to readdir it
|
||||
const char* probe[1];
|
||||
int probe_count = montauk::readdir(fm->clipboard_path, probe, 1);
|
||||
bool src_is_dir = (probe_count >= 0);
|
||||
if (src_is_dir && path_is_same_or_descendant(dst, fm->clipboard_path)) return;
|
||||
const char* probe[1];
|
||||
int probe_count = montauk::readdir(src, probe, 1);
|
||||
bool src_is_dir = (probe_count >= 0);
|
||||
if (src_is_dir && path_is_same_or_descendant(dst, src)) continue;
|
||||
|
||||
bool ok;
|
||||
if (src_is_dir)
|
||||
ok = filemanager_copy_dir_recursive(fm->clipboard_path, dst);
|
||||
else
|
||||
ok = filemanager_copy_file(fm->clipboard_path, dst);
|
||||
bool ok = src_is_dir ? filemanager_copy_dir_recursive(src, dst)
|
||||
: filemanager_copy_file(src, dst);
|
||||
any_ok = any_ok || ok;
|
||||
|
||||
if (ok && fm->clipboard_is_cut) {
|
||||
if (src_is_dir)
|
||||
filemanager_delete_recursive(fm->clipboard_path);
|
||||
else
|
||||
montauk::fdelete(fm->clipboard_path);
|
||||
fm->clipboard_has_data = false;
|
||||
if (ok && fm->clipboard_is_cut) {
|
||||
if (src_is_dir) filemanager_delete_recursive(src);
|
||||
else montauk::fdelete(src);
|
||||
}
|
||||
}
|
||||
|
||||
filemanager_read_dir(fm);
|
||||
if (clear_clipboard) fm->clipboard_count = 0;
|
||||
if (any_ok) filemanager_read_dir(fm);
|
||||
}
|
||||
|
||||
void filemanager_start_rename(FileManagerState* fm) {
|
||||
@@ -147,19 +155,40 @@ void filemanager_new_folder(FileManagerState* fm) {
|
||||
}
|
||||
|
||||
void filemanager_delete_selected(FileManagerState* fm) {
|
||||
if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
|
||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
|
||||
fm->entry_types[fm->selected] == FM_ENTRY_DRIVE) return;
|
||||
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
|
||||
|
||||
int sel[64];
|
||||
int n = filemanager_collect_selection(fm, sel, 64);
|
||||
if (n <= 0) return;
|
||||
|
||||
// Filter out drives.
|
||||
int filtered[64];
|
||||
int fn = 0;
|
||||
bool any_dir = false;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int idx = sel[i];
|
||||
if (fm->entry_types[idx] == FM_ENTRY_DRIVE) continue;
|
||||
filtered[fn++] = idx;
|
||||
if (fm->is_dir[idx]) any_dir = true;
|
||||
}
|
||||
if (fn == 0) return;
|
||||
|
||||
// Anything with a directory or multi-item selection: confirm first.
|
||||
if (any_dir || fn > 1) {
|
||||
if (fn == 1 && any_dir) {
|
||||
filemanager_show_directory_delete_confirmation(fm, filtered[0]);
|
||||
} else {
|
||||
filemanager_show_bulk_delete_confirmation(fm, filtered, fn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Single plain file: delete immediately.
|
||||
char fullpath[512];
|
||||
filemanager_build_fullpath(fullpath, 512,
|
||||
fm->current_path, fm->entry_names[fm->selected]);
|
||||
if (fm->is_dir[fm->selected]) {
|
||||
filemanager_show_directory_delete_confirmation(fm, fm->selected);
|
||||
return;
|
||||
} else {
|
||||
montauk::fdelete(fullpath);
|
||||
}
|
||||
fm->current_path, fm->entry_names[filtered[0]]);
|
||||
montauk::fdelete(fullpath);
|
||||
filemanager_clear_multi_selection(fm);
|
||||
filemanager_read_dir(fm);
|
||||
}
|
||||
|
||||
@@ -197,7 +226,7 @@ void filemanager_open_ctx_menu(FileManagerState* fm, int local_x, int local_y, i
|
||||
if (filemanager_is_computer_view(fm)) {
|
||||
fm->ctx_items[fm->ctx_item_count++] = CTX_REFRESH;
|
||||
} else {
|
||||
if (fm->clipboard_has_data)
|
||||
if (fm->clipboard_count > 0)
|
||||
fm->ctx_items[fm->ctx_item_count++] = CTX_PASTE;
|
||||
fm->ctx_items[fm->ctx_item_count++] = CTX_NEW_FOLDER;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user