diff options
| author | Paul Buetow <paul@buetow.org> | 2026-07-12 21:13:45 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-07-12 21:13:45 +0300 |
| commit | 89727590e718d3628a0847689182e896df646b8a (patch) | |
| tree | 3106397d1b041d95ecfc04762548261f9d660d62 /src/navigator.h | |
| parent | 198b0e8112905bc003f954fc9159cc3da2dfce09 (diff) | |
walkdir: navigator, shortcuts, window wiring, drop target, tests (ht0)
M2 (task ht0): walk the directory.
- src/navigator.{c,h}: GObject (no GtkWidget) holding the folder listing —
image-MIME filter + extension fallback, hide-RAW-sidecars (decision #33),
sort name/time/size, cursor + prev/next/wrap, path-based marks (survive
re-sort, pruned on rescan/monitor, cleared on remove), nearest-fallback,
GFileMonitor debounced 250ms (decision #28), 'changed' signal. 92% gcov.
- src/shortcuts.{c,h}: GtkShortcutController (MANAGED) binding h/l/Left/Right/
g/G/o/q to win.* actions; one table all milestones add to.
- src/window.{c,h}: open file->parent+current / folder->first; h/l/g/G actions
-> nav -> load -> viewer; single GCancellable last-write-wins (g_file_equal
guard for M3 async); header title 'filename · n/total'; GtkDropTarget
(GDK_TYPE_FILE_LIST, many->first, decision Z); GtkFileDialog open.
- data/gschema: add hide-raw-sidecars key.
- tests: unit test_navigator (12 subtests), integration test_walk_folder
(temp fixtures walk + ./sample-images skip-if-absent). 8/8 green; ASan clean
(GIO_USE_VFS=local in fixtures_env).
Fixed during this milestone: a UAF (borrowed c_name used after unref), a
cancellable double-ref leak, time::modified UINT64 vs INT64, and several
test-harness leaks. Sub-agent review issues addressed (mark pruning on
rescan/monitor, remove-before-cursor test, recursive temp-dir cleanup,
callback _cb naming, connect-before-mutate).
Diffstat (limited to 'src/navigator.h')
| -rw-r--r-- | src/navigator.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/navigator.h b/src/navigator.h new file mode 100644 index 0000000..b672480 --- /dev/null +++ b/src/navigator.h @@ -0,0 +1,99 @@ +#ifndef GGAZE_NAVIGATOR_H +#define GGAZE_NAVIGATOR_H + +/*:* + * ggaze — directory navigator + * + * Navigator is a GObject (no GtkWidget) that owns the current directory + * listing: it filters to image MIME types, sorts (name/time/size), keeps a + * cursor and a path-based mark set, watches the directory with GFileMonitor + * (debounced) and emits "changed" on structural changes so the views stay in + * sync. If the current file disappears (external delete, or trash/move) it + * falls back to the nearest. Owns no GTK state; unit-testable without a + * display. See docs/architecture.md "Responsibilities / navigator". + * + * Copyright (c) 2026 ggaze contributors + * SPDX-License-Identifier: GPL-3.0-or-later + *:*/ + +#include <gio/gio.h> +#include <glib-object.h> +#include <glib.h> + +G_BEGIN_DECLS + +#define GGAZE_TYPE_NAVIGATOR (navigator_get_type()) +G_DECLARE_FINAL_TYPE(Navigator, navigator, GGAZE, NAVIGATOR, GObject) + +typedef enum { + GGAZE_SORT_NAME = 0, + GGAZE_SORT_TIME, + GGAZE_SORT_SIZE +} GgazeSort; + +/* Construct a navigator over p_dir (file or folder; a file's parent is used by + * the caller). Refs p_dir. Lists immediately. e_sort is the initial sort; + * b_wrap controls prev/next wrap; b_hide_raw hides RAW sidecars when a JPEG + * with the same stem exists (decision #33). The current cursor is the first + * file. */ +Navigator *navigator_new(GFile *p_dir, GgazeSort e_sort, gboolean b_wrap, + gboolean b_hide_raw); + +/* g_object_unref wrapper for the _new/_delete convention. */ +void navigator_delete(Navigator *p_nav); + +/* --- listing ------------------------------------------------------------- */ +GFile *navigator_get_dir(Navigator *p_nav); /* (transfer none) */ +guint navigator_get_count(Navigator *p_nav); +GFile *navigator_get_file(Navigator *p_nav, + guint u_index); /* (transfer none) */ +gint navigator_get_current_index(Navigator *p_nav); /* -1 if empty */ +GFile *navigator_get_current(Navigator *p_nav); /* (transfer none) */ +guint +navigator_get_remaining(Navigator *p_nav); /* count; M7 excludes trashed */ +gboolean navigator_set_current(Navigator *p_nav, guint u_index); +gboolean navigator_set_current_file(Navigator *p_nav, + GFile *p_file); /* by path */ + +/* --- navigation (honour wrap) ------------------------------------------- */ +gboolean navigator_prev(Navigator *p_nav); +gboolean navigator_next(Navigator *p_nav); +gboolean navigator_first(Navigator *p_nav); +gboolean navigator_last(Navigator *p_nav); + +/* --- sort/filter --------------------------------------------------------- */ +GgazeSort navigator_get_sort(Navigator *p_nav); +void navigator_set_sort(Navigator *p_nav, GgazeSort e_sort); +gboolean navigator_get_wrap(Navigator *p_nav); +void navigator_set_wrap(Navigator *p_nav, gboolean b_wrap); +gboolean navigator_get_hide_raw(Navigator *p_nav); +void navigator_set_hide_raw(Navigator *p_nav, gboolean b_hide_raw); + +/* --- marks (path-based; survive re-sort; cleared on remove) ------------- */ +gboolean navigator_is_marked(Navigator *p_nav, GFile *p_file); +void navigator_toggle_mark(Navigator *p_nav, GFile *p_file); +void navigator_mark_range(Navigator *p_nav, GFile *p_from, GFile *p_to); +void navigator_mark_all(Navigator *p_nav); +void navigator_clear_marks(Navigator *p_nav); +guint navigator_get_mark_count(Navigator *p_nav); +GList *navigator_get_marks(Navigator *p_nav); /* (transfer full) GFile* refs */ + +/* --- mutations ---------------------------------------------------------- */ +/* Re-read the directory; if the current file is gone, fall back to nearest; + * emit "changed". */ +void navigator_rescan(Navigator *p_nav); +/* Remove p_file from the listing (used by trash/move); clear its mark; if it + * was current, fall back to nearest; emit "changed". Returns TRUE if removed. + */ +gboolean navigator_remove(Navigator *p_nav, GFile *p_file); + +/* GFileMonitor debounce in ms (default 250; decision #28). Tests may lower it. + */ +void navigator_set_debounce_ms(Navigator *p_nav, guint u_ms); + +/* "changed" signal: emitted on sort/filter/rescan/remove/monitor event. */ +void navigator_emit_changed(Navigator *p_nav); + +G_END_DECLS + +#endif /* GGAZE_NAVIGATOR_H */
\ No newline at end of file |
