Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
filemanager.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
25#include "common/darktable.h"
26#include "common/collection.h"
27#include "common/selection.h"
28#include "control/control.h"
29#include "dtgtk/thumbtable.h"
31#include "dtgtk/thumbnail.h"
32#include "gui/accelerators.h"
33#include "gui/gtk.h"
34
35#include <math.h>
36
37
38// --- Content widget ---------------------------------------------------------------------------
39
41{
42 // GtkFixed: the grid pins its width to the viewport (horizontal policy NEVER) and only ever
43 // scrolls vertically, so the implicit GtkViewport it gets inside the GtkScrolledWindow is fine.
44 return gtk_fixed_new();
45}
46
47
48// --- Geometry ---------------------------------------------------------------------------------
49
50static void _grid_configure_dims(dt_thumbtable_t *table, int *new_width, int *new_height,
51 int *per_row, int *thumb_width, int *thumb_height)
52{
53 // GtkScrolledWindow reserves a "scrollbar-spacing" gutter between the content and the scrollbar.
54 // It is a legacy GtkWidget *style property* (default 3px), not a CSS box property - invisible in the
55 // GTK Inspector's CSS pane. We zero it via CSS (#thumbtable-scroll, see ansel.css) but still read its
56 // real value here so the maths stays exact whatever the theme/DPI yields.
57 gint sb_spacing = 0;
58 gtk_widget_style_get(table->scroll_window, "scrollbar-spacing", &sb_spacing, NULL);
59
60 // Use actual widget allocations for sizing: GtkAdjustment page sizes are not reliably updated
61 // during shrinking, which can prevent thumbnails from downscaling until another resize happens.
62 int width = gtk_widget_get_allocated_width(table->parent_overlay);
63 int height = gtk_widget_get_allocated_height(table->parent_overlay);
64
65 GtkWidget *v_scroll = gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(table->scroll_window));
66 const int v_scroll_w = v_scroll ? gtk_widget_get_allocated_width(v_scroll) : 0;
67 if(v_scroll_w > 0) width -= v_scroll_w + sb_spacing;
68
69 const int cols = dt_conf_get_int("plugins/lighttable/images_in_row");
70
71 // Reserve the per-cell decoration surplus on the cross axis so the whole grid (cols*thumb_width plus
72 // the last cell's protruding border) stays within the viewport. Under the NEVER scroll policy a
73 // GtkFixed wider than the viewport would drag the scrolled window (and scrollbar) past the parent.
74 const int deco = dt_thumbtable_thumb_cell_decoration();
75
76 *new_width = width;
77 *new_height = height;
78 *per_row = cols;
79 *thumb_width = (int)floorf((float)(width - deco) / (float)MAX(cols, 1));
80 *thumb_height = (cols == 1) ? height : *thumb_width;
81}
82
83static void _grid_rowid_to_position(dt_thumbtable_t *table, int rowid, int *x, int *y)
84{
85 int row = rowid / table->thumbs_per_row; // euclidean division
86 int col = rowid % table->thumbs_per_row;
87 *x = col * table->thumb_width;
88 *y = row * table->thumb_height;
89}
90
91static int _grid_position_to_rowid(dt_thumbtable_t *table, const double x, const double y)
92{
93 // Attempt to get the image rowid sitting in the center of the middle row
94 return (y + table->view_height / 2) / table->thumb_height * table->thumbs_per_row
95 + table->thumbs_per_row / 2 - 1;
96}
97
98static void _grid_get_row_ids(dt_thumbtable_t *table, int *rowid_min, int *rowid_max)
99{
100 // Pixel coordinates of the viewport:
101 float page_size = gtk_adjustment_get_page_size(table->v_scrollbar);
102 float position = gtk_adjustment_get_value(table->v_scrollbar);
103
104 // what is currently visible lies between position and position + page_size.
105 // don't preload next/previous rows because, when in 1 thumb/column,
106 // that can be quite slow
107 int row_min = floorf(position / (float)table->thumb_height);
108 int row_max = ceilf((position + page_size) / (float)table->thumb_height);
109
110 // rowid is the positional ID of the image in the SQLite collection, indexed from 0.
111 // SQLite indexes from 1 but then be use our own array to cache results.
112 *rowid_min = row_min * table->thumbs_per_row;
113 *rowid_max = row_max * table->thumbs_per_row;
114}
115
116static gboolean _grid_is_rowid_visible(dt_thumbtable_t *table, int rowid)
117{
118 // Pixel coordinates of the viewport:
119 int page_size = gtk_adjustment_get_page_size(table->v_scrollbar);
120 int position = gtk_adjustment_get_value(table->v_scrollbar);
121 int page_bottom = page_size + position;
122
123 int img_top = (rowid / table->thumbs_per_row) * table->thumb_height;
124 int img_bottom = img_top + table->thumb_height;
125 return img_top >= position && img_bottom <= page_bottom;
126}
127
129{
130 int current_w = 0, current_h = 0;
131 gtk_widget_get_size_request(table->grid, &current_w, &current_h);
132
133 const int height = (int)ceilf((float)table->collection_count / (float)table->thumbs_per_row) * table->thumb_height;
134 // Pin the cross-axis (width) to the viewport so the grid reaches the scrollbar instead of stopping
135 // at the floor-rounded column total. Safe under NEVER: the grid content already fits view_width
136 // (decoration budgeted in configure), so this lands on a stable fixpoint (grid = view_width,
137 // scrolled window = parent) without perturbing the cross-axis adjustment.
138 if(current_h != height || current_w != table->view_width)
139 {
140 gtk_widget_set_size_request(table->grid, table->view_width, height);
141 dt_print(DT_DEBUG_LIGHTTABLE, "Configuring grid size main dimension: %.f\n", (double)height);
142 }
143}
144
145
146// --- Group borders ----------------------------------------------------------------------------
147
149{
150 const int32_t rowid = thumb->rowid;
151 const int32_t groupid = thumb->info.group_id;
152
153 if(table->lut[CLAMP_ROW(rowid - table->thumbs_per_row)].groupid != groupid
154 || IS_COLLECTION_EDGE(rowid - table->thumbs_per_row))
155 *borders |= DT_THUMBNAIL_BORDER_TOP;
156
157 if(table->lut[CLAMP_ROW(rowid + table->thumbs_per_row)].groupid != groupid
158 || IS_COLLECTION_EDGE(rowid + table->thumbs_per_row))
159 *borders |= DT_THUMBNAIL_BORDER_BOTTOM;
160
161 if(table->lut[CLAMP_ROW(rowid - 1)].groupid != groupid
162 || IS_COLLECTION_EDGE(rowid - 1))
163 *borders |= DT_THUMBNAIL_BORDER_LEFT;
164
165 if(table->lut[CLAMP_ROW(rowid + 1)].groupid != groupid
166 || IS_COLLECTION_EDGE(rowid + 1))
167 *borders |= DT_THUMBNAIL_BORDER_RIGHT;
168
169 // If the group spans over more than a full row,
170 // close the row ends. Otherwise, we leave orphans opened at the row ends.
171 if(table->lut[rowid].thumb->info.group_members > table->thumbs_per_row)
172 {
173 if(rowid % table->thumbs_per_row == 0)
174 *borders |= DT_THUMBNAIL_BORDER_LEFT;
175 if(rowid % table->thumbs_per_row == table->thumbs_per_row - 1)
176 *borders |= DT_THUMBNAIL_BORDER_RIGHT;
177 }
178}
179
180
181// --- Child placement --------------------------------------------------------------------------
182
184{
185 gtk_fixed_put(GTK_FIXED(table->grid), thumb->widget, thumb->x, thumb->y);
186}
187
189{
190 gtk_fixed_move(GTK_FIXED(table->grid), thumb->widget, thumb->x, thumb->y);
191}
192
193
194// --- Scrollbars -------------------------------------------------------------------------------
195
196static gboolean _grid_wants_scroll_value(dt_thumbtable_t *table, GtkAdjustment *adjustment)
197{
198 return adjustment == table->v_scrollbar;
199}
200
201static gboolean _grid_wants_page_size_notify(dt_thumbtable_t *table, GObject *object)
202{
203 // Page size is only used to size the filemanager/grid. Only react to the scroll-axis (vertical)
204 // adjustment. The cross-axis adjustment's page size is driven by the grid width we set during
205 // configure; reacting to it would re-enter configure and can spin in a resize/redraw loop.
206 return object == (GObject *)table->v_scrollbar;
207}
208
209static gboolean _grid_relevant_scrollbar_changed(dt_thumbtable_t *table, GtkWidget *widget, GtkAllocation *allocation)
210{
211 // Filemanager fallback sizing subtracts the vertical scrollbar width.
212 GtkWidget *v_scroll = gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(table->scroll_window));
213 if(widget != v_scroll) return FALSE;
214 if(allocation->width == table->last_v_scrollbar_width) return FALSE;
215 table->last_v_scrollbar_width = allocation->width;
216 return TRUE;
217}
218
219
220// --- Per-thumbnail state ----------------------------------------------------------------------
221
222// The grid highlights the lighttable selection.
223static gboolean _grid_is_thumb_highlighted(dt_thumbtable_t *table, int32_t imgid)
224{
226}
227
233
234static void _grid_on_drag_begin(dt_thumbtable_t *table, int32_t imgid)
235{
236 // Ensure the image that collects the drag event is properly part of the selection
237 if(imgid > UNKNOWN_IMAGE)
239}
240
241
242// --- Parent / focus ---------------------------------------------------------------------------
243
245{
246 // The filemanager grid overlays the center canvas and floats as an OVERLAY child so its size
247 // request stays decoupled from the panel (the outer GtkOverlay drives its allocation). It is
248 // not affected by the Wayland blank-until-hover issue because it is the focused content
249 // of the lighttable view, not a static sibling of a continuously repainted surface.
250 gtk_overlay_add_overlay(GTK_OVERLAY(table->parent_overlay), table->scroll_window);
251 gtk_widget_set_name(table->grid, "thumbtable-filemanager");
252 dt_gui_add_help_link(table->grid, dt_get_help_url("lighttable_filemanager"));
253 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(table->scroll_window), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
254}
255
257{
258 // This runs from a g_idle() callback (see dt_thumbtable_schedule_focus), so by the time it
259 // fires the user may already have switched to another view (e.g. Studio Capture). Grabbing
260 // the grid's focus regardless would steal it back from that view's own center widget.
262 if(IS_NULL_PTR(current_view) || strcmp(current_view->module_name, "lighttable")) return;
263
264 GtkWidget *focused = NULL;
265 GtkWidget *toplevel = gtk_widget_get_toplevel(table->grid);
266 if(!IS_NULL_PTR(toplevel) && GTK_IS_WINDOW(toplevel))
267 focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
268
269 // Grab focus here otherwise, on first click over the grid,
270 // scrolled window gets scrolled all the way to the top and it's annoying.
271 // This can work only if the grid is mapped and realized, which we ensure
272 // by wrapping that in a g_idle() method.
273 if(IS_NULL_PTR(focused) || (!GTK_IS_EDITABLE(focused) && !GTK_IS_TEXT_VIEW(focused)))
274 gtk_widget_grab_focus(table->grid);
275}
276
277
278// --- Keyboard ---------------------------------------------------------------------------------
279
280static gboolean _grid_handle_key(dt_thumbtable_t *table, GdkEventKey *event, guint key, int32_t imgid)
281{
282 switch(key)
283 {
284 case GDK_KEY_Up:
285 dt_thumbtable_move_in_grid(table, event, DT_TT_MOVE_UP, imgid);
286 return TRUE;
287 case GDK_KEY_Down:
288 dt_thumbtable_move_in_grid(table, event, DT_TT_MOVE_DOWN, imgid);
289 return TRUE;
290 case GDK_KEY_space:
291 {
292 if(dt_modifier_is(event->state, GDK_SHIFT_MASK))
293 {
295 int rowid = dt_thumbtable_find_rowid_from_imgid(table, imgid);
297 dt_thumbtable_select_range(table, rowid);
298 }
299 else if(dt_modifier_is(event->state, GDK_CONTROL_MASK))
301 else
303 return TRUE;
304 }
305 case GDK_KEY_nobreakspace:
306 {
307 // Shift + space is decoded as nobreakspace on BÉPO keyboards
309 int rowid = dt_thumbtable_find_rowid_from_imgid(table, imgid);
311 dt_thumbtable_select_range(table, rowid);
312 return TRUE;
313 }
314 }
315 return FALSE;
316}
317
318static void _grid_pre_activate(dt_thumbtable_t *table, int32_t imgid)
319{
320 // This is only to be consistent with mouse events:
321 // opening to darkroom happens with double click (aka ACTIVATE event),
322 // but the first click always select the clicked thumbnail before.
324}
325
326
327// --- Vtable -----------------------------------------------------------------------------------
328
330{
331 static const dt_thumbtable_layout_ops_t ops = {
333 .configure_dims = _grid_configure_dims,
334 .rowid_to_position = _grid_rowid_to_position,
335 .position_to_rowid = _grid_position_to_rowid,
336 .get_row_ids = _grid_get_row_ids,
337 .is_rowid_visible = _grid_is_rowid_visible,
338 .update_content_size = _grid_update_content_size,
339 .group_borders = _grid_group_borders,
340 .place_child = _grid_place_child,
341 .move_child = _grid_move_child,
342 .wants_scroll_value = _grid_wants_scroll_value,
343 .wants_page_size_notify = _grid_wants_page_size_notify,
344 .relevant_scrollbar_changed = _grid_relevant_scrollbar_changed,
345 .is_thumb_highlighted = _grid_is_thumb_highlighted,
346 .on_thumbnail_added = _grid_on_thumbnail_added,
347 .on_drag_begin = _grid_on_drag_begin,
348 .setup_parent = _grid_setup_parent,
349 .grab_focus = _grid_grab_focus,
350 .handle_key = _grid_handle_key,
351 .pre_activate = _grid_pre_activate,
352 };
353 return &ops;
354}
355
356
357// --- Grid-only public API ---------------------------------------------------------------------
358
360{
361 table->zoom = level;
364 dt_thumbtable_schedule_focus(table, G_PRIORITY_DEFAULT_IDLE);
365}
366
371
372void dt_thumbtable_offset_zoom(dt_thumbtable_t *table, const double delta_x, const double delta_y)
373{
375 GHashTableIter iter;
376 gpointer value = NULL;
377 g_hash_table_iter_init(&iter, table->list);
378 while(g_hash_table_iter_next(&iter, NULL, &value))
379 {
381 thumb->zoomx += delta_x;
382 thumb->zoomy += delta_y;
383 gtk_widget_queue_draw(thumb->w_image);
384 }
386}
387
395static gboolean _thumbtable_idle_apply_grid_configuration(gpointer user_data)
396{
397 dt_thumbtable_t *table = (dt_thumbtable_t *)user_data;
398 if(IS_NULL_PTR(table)) return G_SOURCE_REMOVE;
399
400 table->idle_update_id = 0;
401
402 // Reconfigure the grid with new column settings from config
404
405 // Update and populate visible thumbnails at new sizes
407
409
410 // Queue redraw for any unpopulated areas
411 if(table->thumb_nb == 0) gtk_widget_queue_draw(table->grid);
412
413 // Schedule scrolling as a follow-up idle callback with lower priority.
414 // This ensures the GTK widget grid is fully mapped and realized before we attempt to scroll.
415 // We use a lower priority (G_PRIORITY_LOW) to let the GTK layout pass complete first.
416 dt_thumbtable_schedule_focus(table, G_PRIORITY_LOW);
417
418 return G_SOURCE_REMOVE;
419}
420
422{
423 if(IS_NULL_PTR(table)) return;
424 if(table->scroll_window && !gtk_widget_is_visible(table->scroll_window)) return;
425
426 // Cancel any pending standard idle update to coalesce configuration changes
427 if(table->idle_update_id)
428 {
429 g_source_remove(table->idle_update_id);
430 table->idle_update_id = 0;
431 }
432
433 // Ensure we have the current active image so we can scroll back to it after grid size change
435
436 // Schedule the coordinated grid configuration with higher priority to ensure
437 // it runs before other pending updates
438 table->idle_update_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
440 table, NULL);
441}
442
443// clang-format off
444// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
445// vim: shiftwidth=2 expandtab tabstop=2 cindent
446// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
447// clang-format on
Handle default and user-set shortcuts (accelerators)
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int position()
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
static const int row
char * key
int dt_conf_get_int(const char *name)
darktable_t darktable
Definition darktable.c:183
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1600
#define UNKNOWN_IMAGE
Definition darktable.h:194
@ DT_DEBUG_LIGHTTABLE
Definition darktable.h:737
static const dt_aligned_pixel_simd_t value
Definition darktable.h:589
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
Definition darktable.h:945
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:293
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:384
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
void dt_thumbtable_set_zoom(dt_thumbtable_t *table, dt_thumbtable_zoom_t level)
static void _grid_place_child(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
void dt_thumbtable_offset_zoom(dt_thumbtable_t *table, const double delta_x, const double delta_y)
void dt_thumbtable_apply_grid_configuration(dt_thumbtable_t *table)
Apply grid configuration changes with proper event synchronization.
static void _grid_on_drag_begin(dt_thumbtable_t *table, int32_t imgid)
static void _grid_rowid_to_position(dt_thumbtable_t *table, int rowid, int *x, int *y)
Definition filemanager.c:83
static GtkWidget * _grid_create_content_widget(void)
Definition filemanager.c:40
static gboolean _grid_wants_page_size_notify(dt_thumbtable_t *table, GObject *object)
static gboolean _grid_wants_scroll_value(dt_thumbtable_t *table, GtkAdjustment *adjustment)
static gboolean _grid_is_thumb_highlighted(dt_thumbtable_t *table, int32_t imgid)
static gboolean _grid_is_rowid_visible(dt_thumbtable_t *table, int rowid)
static void _grid_get_row_ids(dt_thumbtable_t *table, int *rowid_min, int *rowid_max)
Definition filemanager.c:98
static void _grid_group_borders(dt_thumbtable_t *table, dt_thumbnail_t *thumb, dt_thumbnail_border_t *borders)
static void _grid_setup_parent(dt_thumbtable_t *table)
static gboolean _grid_handle_key(dt_thumbtable_t *table, GdkEventKey *event, guint key, int32_t imgid)
static gboolean _thumbtable_idle_apply_grid_configuration(gpointer user_data)
Idle callback for applying grid configuration.
static void _grid_move_child(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
static void _grid_update_content_size(dt_thumbtable_t *table)
static void _grid_grab_focus(dt_thumbtable_t *table)
static void _grid_on_thumbnail_added(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
dt_thumbtable_zoom_t dt_thumbtable_get_zoom(dt_thumbtable_t *table)
static int _grid_position_to_rowid(dt_thumbtable_t *table, const double x, const double y)
Definition filemanager.c:91
const dt_thumbtable_layout_ops_t * dt_thumbtable_grid_ops(void)
static void _grid_pre_activate(dt_thumbtable_t *table, int32_t imgid)
static gboolean _grid_relevant_scrollbar_changed(dt_thumbtable_t *table, GtkWidget *widget, GtkAllocation *allocation)
static void _grid_configure_dims(dt_thumbtable_t *table, int *new_width, int *new_height, int *per_row, int *thumb_width, int *thumb_height)
Definition filemanager.c:50
void dt_gui_add_help_link(GtkWidget *widget, char *link)
Definition gtk.c:2232
static const float x
gboolean dt_selection_is_id_selected(struct dt_selection_t *selection, int32_t imgid)
Definition selection.c:393
void dt_selection_select(dt_selection_t *selection, int32_t imgid)
Definition selection.c:273
void dt_selection_select_single(dt_selection_t *selection, int32_t imgid)
Definition selection.c:289
void dt_selection_toggle(dt_selection_t *selection, int32_t imgid)
Definition selection.c:296
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_selection_t * selection
Definition darktable.h:800
struct dt_view_manager_t * view_manager
Definition darktable.h:790
int32_t group_id
Definition image.h:319
uint32_t group_members
Definition image.h:320
int32_t id
Definition image.h:319
gboolean disable_actions
Definition thumbnail.h:104
dt_image_t info
Definition thumbnail.h:76
int32_t rowid
Definition thumbnail.h:68
GtkWidget * w_image
Definition thumbnail.h:84
GtkWidget * widget
Definition thumbnail.h:79
dt_thumbnail_t * thumb
Definition thumbtable.h:89
Per-mode layout strategy. One instance per frontend, shared (const) by all tables of that mode and st...
GtkWidget *(* create_content_widget)(void)
GHashTable * list
Definition thumbtable.h:117
GtkWidget * grid
Definition thumbtable.h:109
dt_pthread_mutex_t lock
Definition thumbtable.h:167
GtkAdjustment * v_scrollbar
Definition thumbtable.h:156
dt_thumbtable_zoom_t zoom
Definition thumbtable.h:184
int last_v_scrollbar_width
Definition thumbtable.h:202
GtkWidget * scroll_window
Definition thumbtable.h:153
dt_thumbtable_cache_t * lut
Definition thumbtable.h:151
uint32_t thumb_nb
Definition thumbtable.h:134
GtkWidget * parent_overlay
Definition thumbtable.h:162
char module_name[64]
Definition view.h:154
#define MAX(a, b)
Definition thinplate.c:29
void dt_thumbnail_update_selection(dt_thumbnail_t *thumb, gboolean selected)
Definition thumbnail.c:878
dt_thumbnail_border_t
Definition thumbnail.h:49
@ DT_THUMBNAIL_BORDER_BOTTOM
Definition thumbnail.h:54
@ DT_THUMBNAIL_BORDER_TOP
Definition thumbnail.h:52
@ DT_THUMBNAIL_BORDER_RIGHT
Definition thumbnail.h:53
@ DT_THUMBNAIL_BORDER_LEFT
Definition thumbnail.h:51
void dt_thumbtable_update(dt_thumbtable_t *table)
Definition thumbtable.c:776
void dt_thumbtable_set_active_rowid(dt_thumbtable_t *table)
Update internal active row tracking.
Definition thumbtable.c:368
void dt_thumbtable_configure(dt_thumbtable_t *table)
Definition thumbtable.c:543
int dt_thumbtable_thumb_cell_decoration(void)
Definition thumbtable.c:522
#define CLAMP_ROW(rowid)
Definition thumbtable.c:622
void dt_thumbtable_schedule_focus(dt_thumbtable_t *table, const gint priority)
Definition thumbtable.c:191
int dt_thumbtable_find_rowid_from_imgid(dt_thumbtable_t *table, const int32_t imgid)
Definition thumbtable.c:400
#define IS_COLLECTION_EDGE(rowid)
Definition thumbtable.c:623
void dt_thumbtable_move_in_grid(dt_thumbtable_t *table, GdkEventKey *event, dt_thumbtable_direction_t direction, int origin_imgid)
void dt_thumbtable_select_range(dt_thumbtable_t *table, const int rowid)
Select a range of images in the collection.
A widget to manage and display image thumbnails in Ansel's lighttable and filmstrip views.
dt_thumbtable_zoom_t
Zoom levels for thumbnail display.
Definition thumbtable.h:75
#define dt_thumbtable_refresh_thumbnail(table, imgid, reinit)
Definition thumbtable.h:292
Private interface shared between the thumbtable engine (thumbtable.c) and its two frontends (filemana...
@ DT_TT_MOVE_DOWN
@ DT_TT_MOVE_UP
char * dt_get_help_url(char *name)
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)
Definition view.c:141