summaryrefslogtreecommitdiff
path: root/docs/open-questions.md
blob: e6962f6913ccd624e140f9bbc7ccc712286a73e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# Open Questions

Decisions to make before/while coding. None block M0.

Most items are now **decided** — see PLAN.md decisions #29–#38. Each item's
**Decision:** line records the chosen value; the milestone-level Leans are
locked in decision #37.

## A. libadwaita or plain GTK4?
- libadwaita → GNOME-native styling, follows release style, but opinionated
  (header bar patterns, no theming overrides).
- plain GTK4 → full control, works under any GTK theme, less "GNOME-native".
- **Decision:** libadwaita (decision #29).

## B. App ID / GApplication name
- Placeholder `org.buetow.ggaze`. Confirm domain + naming.
- **Decision:** `org.buetow.ggaze` (decision #30).

## C. Image decode strategy
- Rely on GdkPixbuf loaders for the common case, or link libjpeg-turbo /
  libpng directly from the start for the progressive low-res preview feature?
- **Lean:** GdkPixbuf first; add direct libs in M5/M6.

## D. Thumbnail grid view — in scope (decided)
- Two views per window: a thumbnail grid (overview) and a large single-image
  view. `Enter`/`Esc` switch between them; cursor stays in sync.
- Trashed/deleted items stay listed but dimmed (with a hide toggle).
- **Lean:** grid view is a core feature, M7. Not "a different app" after all.

## E. Single instance?
- `GApplication` single-instance means a second `ggaze img.jpg` reuses the
  window and loads the new image. Convenient; small risk of state confusion.
- **Decision:** single instance, replace on new `open` (decision #32).

## F. Recursive directory walking
- `ggaze folder/` → recurse into subdirs, or just flat siblings?
- **Lean:** flat by default; add `--recursive` later.

## G. Color management
- Ignore sRGB-only for now; plan a later milestone for lcms2 + ICC.
- Confirm target displays are sRGB-ish (most are).
- **Update:** if GEGL is enabled (M9), color-managed decode/export comes via
  babl + LCMS (`gegl:icc-file-loader`, `gegl:lcms-from-profile`,
  `gegl:convert-color-space`) — no separate lcms2 wiring. Without GEGL, stay
  sRGB-only.

## H. Scroll behavior default
- Scroll = zoom (feh-style `--scale-zoom`) vs scroll = next/prev.
- **Lean:** zoom; expose in settings since it divides users.

## I. Trash vs delete (decided)
- `d` moves the file to a local `<folder>/.Trash/` directory (created lazily,
  collision-suffixed), undoable with `u`. This is **not** the system trash.
- `D` permanently deletes (unlink), no undo.
- **Lean:** confirmed; `./Trash` lives with the shoot for easy inspection/emptying.

## J. Packaging targets
- RPM first (Fedora native). Flatpak too? Copr repo?
- **Lean:** RPM + AppStream; Flatpak later.

## K. Camera-dump specifics
- **RAW + JPEG pairs.** Many cameras shoot both. Show only the JPEG and hide
  the matching `.RAF/.CR3/.NEF`? Or show RAW via embedded preview? Hide-pairs
  is the culling-friendly choice.
- **Burst grouping.** Auto-detect burst sequences (EXIF burst ID or
  sub-second capture time clustering) and collapse them into a group, letting
  `j`/`k` step group-by-group with an expand for within-burst? Big UX win for
  the stated use case, but scope creep — decide whether it's M-something or
  "later".
- **Default sort.** Capture time (EXIF `DateTimeOriginal`) vs filename. Camera
  dumps are usually already named in shot order, so filename sort ≈ capture
  order; but capture-time sort is more robust after a burst of edits.
- **Import folder.** Any integration with the camera-download location, or just
  "whatever path you point it at"? Lean: just a path.
- **Decision:** burst grouping deferred to "later"; hide RAW sidecars by
  default (toggle to reveal); default sort = filename (capture-time as a menu
  option); import folder = just a path (decision #33).

## L. Custom viewer widget vs GtkPicture
- `GtkPicture` is simplest but limited zoom/pan. A custom `GtkWidget` gives
  cursor-centered zoom, pan clamping, animated transitions.
- **Decision:** custom viewer widget (decision #31).

## M. Destination configuration storage
- GSettings `a(ss)` (ordered name→path) is simplest and integrates with
  `gsettings`/dconf. Alternative: a small TOML/ini under
  `~/.config/ggaze/destinations.conf` for hand editing.
- **Lean:** GSettings `a(ss)` via the Preferences dialog; revisit if users want
  to hand-edit.

## N. Move vs copy, and collision policy
- `g_file_move` (rename / copy+delete) by default; a copy mode ("send a copy
  without removing") could be a modifier (`M` for copy?).
- Collision: suffix `-1`, `-2`, … (never overwrite).
- **Lean:** move + suffix; copy as a later option.

## O. Auto-hotkey scheme past 10 destinations
- `1`-`9`, `0`, then `a`-`z` gives 36 slots — plenty. Beyond that, a scrollable
  list navigable by arrows + `Enter` (no single-key shortcut).
- **Lean:** digits then letters; cap at a sane number.

## P. Undo depth
- One level (`u` undoes the last `d` or `m`) is enough to start; a small stack
  (10) is a cheap upgrade later.
- **Lean:** one level now, stack later.

## Q. Marks vs re-sort / view switch / trash
- Marks are path-based and held by the navigator: a re-sort reflows but keeps
  marks; a view switch preserves them; trashing a marked item clears its mark.
- **Lean:** confirm during implementation.

## R. External programs — command format & launch
- Store `name → command` pairs; command uses freedesktop `Exec` placeholders
  (`%f` single file, `%F` multiple). Start with `%f` only; `%F` (marked set)
  later.
- Launch via `GSubprocess` detached (non-blocking), or `g_app_info`?
  GSubprocess is simpler for raw commands; `g_app_info` is better if reusing
  `.desktop` entries.
- **Lean:** raw command + `%f` + GSubprocess; revisit `.desktop` reuse later.
- Should `e` apply to marks (`%F`)? **Lean:** current image first; marks later.

## S. Shell scripts — execution model
- Run via `/bin/sh -c "<cmd>"` (POSIX sh) or `bash -c`? Use the user's
  `$SHELL`? **Lean:** `/bin/sh -c` for portability; revisit for bash-isms.
- Async, non-blocking; toast while running and on completion. On exit,
  rescan the directory (scripts may add/remove/move files). A destructive
  script could rename the current file away — rescan handles it (cursor falls
  back to nearest).
- Placeholders: `%f` (current image), `%d` (current folder); `%F` (marked
  set) later. **Shell injection:** single-quote substituted paths (filenames
  can contain spaces, `$`, backticks) — or pass paths via env/argv instead of
  `sh -c`.
- **Lean:** `/bin/sh -c`, single-quote paths, rescan on exit, `%f`/`%d` now.

## T. Thumbnail size — range, step, and cache
- freedesktop TMS defines only 128 (normal) and 256 (large) cached sizes.
  For larger grid thumbnails, decode a custom size on demand (downscale the
  full image or the `large` cache entry), cached in a separate bucket. Range
  ~64–512px, step ~32px. Confirm.
- Persist `thumbnail-size` (int) in GSettings; restore on launch.
- **Lean:** 64–512px, ±32px step, custom cache bucket for non-TMS sizes.

## U. GEGL integration
- **Hard or optional dep?** Lean: optional meson `feature`; core viewer works
  without it. Confirm RPM splits a `ggaze-gegl` subpackage or keeps it in.
- **Preset format:** store `gegl-graph` text (parsed via `gegl:gegl` /
  `gegl_node_new_from_xml`) or build programmatically per known preset? Lean:
  built-in presets built programmatically; user presets as graph text.
- **Apply timing:** only when paused on an image (not during `h`/`l` scrub);
  disable the preset during rapid navigation, reapply on settle. Confirm.
- **Viewer path:** import decoded pixels → GeglBuffer (GdkPixbuf-source op or
  babl), process, render output buffer → GdkTexture. Measure overhead; maybe
  show a subtle "enhanced" badge in the header.
- **Export naming:** `<stem>-enhanced.<ext>`; collision → suffix `-1`. Same dir
  as original by default; configurable later.
- **gegl-gtk?** No — keep the custom viewer, render to GdkTexture.
- **Save flow:** `s` = save enhanced copy; no auto-save; navigate-away (or
  quit, or `d`/`D`/`m`) with a dirty preview prompts Save/Discard/Cancel.
  Slideshow moved to `S` to free `s` for save. Confirm the prompt also fires
  on `d`/`D`/`m` of a dirty image (Lean: yes).
- **Decision:** optional meson feature; built-in presets programmatic, user
  presets as `gegl-graph` text; apply only when settled (not during scrub);
  "enhanced" badge; export `<stem>-enhanced.<ext>` same dir, collision suffix
  `-1`; dirty-prompt fires on `d`/`D`/`m`; no gegl-gtk (decision #34).

## V. Clipboard — pixels vs URIs
- Single image → `image/png` pixels (paste as image into chat apps); marks →
  `text/uri-list` (+ `text/plain` paths). Verify Katogram paste accepts image
  pixels (some apps want URIs even for one file).
- Offer both at once via `gdk_content_provider_new_union` (PNG + uri-list) when
  one file, so the target picks. Lean: yes.
- Decode-for-PNG-copy runs in a `GTask` thread; cap size (downscale very
  large images?) — Lean: copy full-res, note the memory cost.
- `Ctrl+Shift+c` to force copy-as-path (text) — later.

## W. Crop, straighten & rotate tools
- **Crop rect UI:** overlay rectangle with handles; keyboard move
  (`h`/`l`/`j`/`k`) + resize (`H`/`L`/`J`/`K`); aspect presets `1`-`4` + `0`
  free. Tool mode grabs keys until `Enter`/`Esc` so they don't clash with
  pan/zoom.
- **Straighten:** drag-a-horizon-line vs angle nudge; ±0.5° step; grid overlay.
  Auto-crop rotated corners? Lean: offer as a toggle, default on.
- **Rotate 90°:** one-shot `[`/`]`; repeat to 180°/270°; non-destructive. No
  overlay.
- All are GEGL ops in the same preview graph as enhance; `s` exports. If GEGL
  off, toast. Confirm compose order (crop after rotate, or user order).
- **Compare:** hold `Space` (momentary key-release event) vs a toggle; GUI uses
  a menu *Show original* toggle. Confirm momentary doesn't fight the
  navigate-away dirty prompt.
- **Decision:** compose order load→enhance(color)→rotate→straighten→crop→
  export; straighten auto-crop default on (decision #35).

## X. Enhance — fixed presets vs tunable parameters
- Ship one-shot presets with sensible fixed strengths (brightness/contrast/
  saturation/etc.). Strength is editable in the `enhance-presets` gegl-graph
  text (Preferences / `gsettings`) — no slider UI, keeps KISS.
- Later: a "fine adjust" mode that nudges the active preset's main parameter
  with keys (which keys? `+`/`-` clash with zoom; maybe `H`/`L` or a sub-mode).
  Lean: presets first; nudging only if asked.
- **Curves:** GEGL has `gegl:contrast-curve` and `gegl:curve`; confirm the
  exact op name and how to embed a curve shape in the graph text. Interactive
  curve editing is out of scope (GIMP hand-off via `e`).
- **Decision:** one active color preset (replace); crop/straighten/rotate
  stack; reset preview clears all; combine color presets via one `gegl-graph`
  entry; curves via `gegl:contrast-curve`; no fine-adjust nudging in v1
  (decision #36).

## Y. EXIF orientation
- Source: GdkPixbuf's `gdk_pixbuf_apply_embedded_orientation` covers JPEG/TIFF
  via GdkPixbuf; for direct-lib backends (libjpeg-turbo, libjxl, libavif,
  libheif) read the orientation tag (libexif or the format's own metadata) and
  rotate/flip. Confirm a single code path (normalize to identity orientation
  before producing the `GdkTexture`).
- Manual `[`/`]` and straighten compose **on top** of the EXIF-corrected image.
- On `s` export, the pixels are already upright → write the EXIF Orientation
  tag as 1 (normal) to avoid double-rotation in other apps. Confirm.

## Z. Opening files, folders & drag-drop
- **Folder arg vs file arg:** `ggaze dir/` → grid of dir; `ggaze file.jpg` →
  parent dir as navigator, file current (large view). Confirm.
- **Drop semantics:** drop folder → grid; drop one file → open it; drop many
  files → open the first file's folder in grid with the first selected (or
  treat the dropped set as the navigator's universe?). Lean: first-file's
  folder, first selected.
- **`o` dialog:** use `GtkFileDialog` (GTK4) with folder selection allowed as
  well as files.
- **Single-instance:** a new `open` (arg or drop) replaces the current
  folder/image (per open-question E).

## AA. Folder monitoring
- `GFileMonitor` on the current directory; debounce bursts (usbimport writes
  many files quickly) — e.g. 250 ms coalesce before emitting `changed`.
- Removed current file → fall back to nearest neighbor (or stay on a
  placeholder)? Lean: nearest.
- Recurse into subdirs? No (flat; matches open-question F). Watch only the
  current dir.
- Pause monitoring during rapid `h`/`l` scrubbing? Probably unnecessary;
  debounce handles it.