64#ifdef GDK_WINDOWING_QUARTZ
68#include <glib-object.h>
85 const gboolean can_clone = (src->
lut
107 for(uint32_t
i = 0;
i < count;
i++)
108 cloned_lut[
i].thumb = NULL;
113 dst->
lut = cloned_lut;
176 if(thumb_a->
rowid > thumb_b->
rowid)
return -1;
189 if(!
IS_NULL_PTR(toplevel) && GTK_IS_WINDOW(toplevel))
190 focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
196 if(
IS_NULL_PTR(focused) || (!GTK_IS_EDITABLE(focused) && !GTK_IS_TEXT_VIEW(focused)))
197 gtk_widget_grab_focus(table->
grid);
217 if(table->
thumb_nb == 0) gtk_widget_queue_draw(table->
grid);
218 return G_SOURCE_REMOVE;
262 if(table->
thumb_nb == 0) gtk_widget_queue_draw(table->
grid);
269 return G_SOURCE_REMOVE;
332 if(
object != (GObject *)table->
v_scrollbar)
return;
393 for(
int rowid = row_start; rowid <= row_end; rowid++)
398 const gboolean mouse_over = thumb->
mouse_over;
405 gtk_widget_queue_draw(thumb->
widget);
411 for(
int rowid = row_start; rowid <= row_end; rowid++)
552 rowid = table->
rowid;
590 float page_size = gtk_adjustment_get_page_size(table->
v_scrollbar);
606 float page_size = gtk_adjustment_get_page_size(table->
h_scrollbar);
627 int page_size = gtk_adjustment_get_page_size(table->
v_scrollbar);
629 int page_bottom = page_size +
position;
633 return img_top >=
position && img_bottom <= page_bottom;
637 int page_size = gtk_adjustment_get_page_size(table->
h_scrollbar);
639 int page_right = page_size +
position;
643 return img_left >=
position && img_right <= page_right;
669 double main_dimension = 0.;
670 int current_w = 0, current_h = 0;
671 gtk_widget_get_size_request(table->
grid, ¤t_w, ¤t_h);
672 gboolean changed =
FALSE;
691 main_dimension =
width;
702 if(current_w != -1 || current_h != -1)
704 gtk_widget_set_size_request(table->
grid, -1, -1);
746 GtkWidgetPath *path = gtk_widget_path_new();
747 gtk_widget_path_append_type(path, GTK_TYPE_EVENT_BOX);
748 gtk_widget_path_iter_add_class(path, -1,
"thumb-cell");
750 GtkStyleContext *ctx = gtk_style_context_new();
751 gtk_style_context_set_path(ctx, path);
753 GtkBorder margin, border;
754 gtk_style_context_get_margin(ctx, GTK_STATE_FLAG_NORMAL, &margin);
755 gtk_style_context_get_border(ctx, GTK_STATE_FLAG_NORMAL, &border);
758 gtk_widget_path_unref(path);
760 return MAX(0, (border.left + border.right) + (margin.left + margin.right));
772 int new_thumbs_per_row = 0;
773 int new_thumb_width = 0;
774 int new_thumb_height = 0;
781 gtk_widget_style_get(table->
scroll_window,
"scrollbar-spacing", &sb_spacing, NULL);
787 new_width = gtk_widget_get_allocated_width(table->
parent_overlay);
788 new_height = gtk_widget_get_allocated_height(table->
parent_overlay);
791 const int v_scroll_w = v_scroll ? gtk_widget_get_allocated_width(v_scroll) : 0;
792 if(v_scroll_w > 0) new_width -= v_scroll_w + sb_spacing;
801 new_width = gtk_widget_get_allocated_width(table->
parent_overlay);
802 new_height = gtk_widget_get_allocated_height(table->
parent_overlay);
807 h_scroll_h = gtk_widget_get_allocated_height(h_scroll);
808 if(h_scroll_h > 0) h_scroll_h += sb_spacing;
812 int req_w = -1, req_h = -1;
813 gtk_widget_get_size_request(table->
parent_overlay, &req_w, &req_h);
815 new_height =
MIN(new_height, req_h);
817 new_height -= h_scroll_h;
822 if(new_width < 32 || new_height < 32)
840 new_thumbs_per_row = cols;
841 new_thumb_width = (int)floorf((
float)(new_width - deco) / (
float)
MAX(new_thumbs_per_row, 1));
842 new_thumb_height = (new_thumbs_per_row == 1) ? new_height : new_thumb_width;
846 new_thumbs_per_row = 1;
847 new_thumb_height = new_height - deco;
848 new_thumb_width = new_thumb_height;
851 const gboolean thumbs_changed = (!table->
configured
863 _grid_configure(table, new_width, new_height, new_thumbs_per_row, new_thumb_width, new_thumb_height);
879 gboolean found =
FALSE;
888 if(g_hash_table_lookup(table->
list, GINT_TO_POINTER(imgid)) == thumb)
903#define CLAMP_ROW(rowid) CLAMP(rowid, 0, table->collection_count - 1)
904#define IS_COLLECTION_EDGE(rowid) (rowid < 0 || rowid >= table->collection_count)
912 const int32_t rowid = thumb->
rowid;
964 const int32_t imgid = table->
lut[rowid].
imgid;
974 gboolean new_item =
TRUE;
975 gboolean new_position =
TRUE;
982 if(mapped_thumb == table->
lut[rowid].
thumb)
984 thumb = mapped_thumb;
985 new_position =
FALSE;
1003 thumb->
rowid = rowid;
1011 g_hash_table_insert(table->
list, GINT_TO_POINTER(thumb->
info.
id), thumb);
1019 if(new_item || size_changed || table->
overlays != thumb->
over)
1029 gtk_fixed_put(GTK_FIXED(table->
grid), thumb->
widget, thumb->
x, thumb->
y);
1032 else if(new_position || size_changed)
1035 gtk_fixed_move(GTK_FIXED(table->
grid), thumb->
widget, thumb->
x, thumb->
y);
1055 gtk_widget_show(thumb->
widget);
1074 GHashTableIter iter;
1075 gpointer
value = NULL;
1076 g_hash_table_iter_init(&iter, table->
list);
1077 while(g_hash_table_iter_next(&iter, NULL, &
value))
1091 gtk_fixed_move(GTK_FIXED(table->
grid), thumb->
widget, thumb->
x, thumb->
y);
1098 gtk_widget_queue_draw(thumb->
widget);
1121 gboolean empty_list = (table->
thumb_nb == 0);
1132 const char *
const name = gtk_widget_get_name(table->
grid);
1150 gboolean first =
TRUE;
1164 if(g_hash_table_lookup(table->
list, GINT_TO_POINTER(table->
lut[rowid].
imgid)) != thumb)
1170 const gboolean selected = thumb->
selected;
1183 gtk_widget_queue_draw(thumb->
widget);
1190 table->
zoom = level;
1204 GHashTableIter iter;
1205 gpointer
value = NULL;
1206 g_hash_table_iter_init(&iter, table->
list);
1207 while(g_hash_table_iter_next(&iter, NULL, &
value))
1210 thumb->
zoomx += delta_x;
1211 thumb->
zoomy += delta_y;
1212 gtk_widget_queue_draw(thumb->
w_image);
1267 GHashTableIter iter;
1268 gpointer
value = NULL;
1269 g_hash_table_iter_init(&iter, table->
list);
1270 while(g_hash_table_iter_next(&iter, NULL, &
value))
1298 for(GList *l = g_list_first(imgs); l; l = g_list_next(l))
1300 const int32_t imgid = GPOINTER_TO_INT(l->data);
1301 if(imgid <= 0)
continue;
1318 gtk_widget_queue_draw(thumb->
widget);
1341 while(sqlite3_step(stmt) == SQLITE_ROW)
1343 const int32_t imgid = sqlite3_column_int(stmt, 0);
1344 const int32_t groupid = sqlite3_column_int(stmt, 1);
1359 g_array_append_val(collection, entry);
1374 sqlite3_reset(stmt);
1376 if(
IS_NULL_PTR(collection) || collection->len == 0)
1380 old_lut = table->
lut;
1387 if(collection) g_array_free(collection,
TRUE);
1400 g_array_free(collection,
TRUE);
1408 old_lut = table->
lut;
1409 table->
lut = new_lut;
1415 g_array_free(collection,
TRUE);
1422 size_t len = strlen(query);
1427 hash =
dt_hash(hash, (
char *)&num_pics,
sizeof(uint32_t));
1443 const int next, gpointer user_data)
1449 gboolean collapsing_changed = (table->
collapse_groups != collapse_groups);
1472 "The current filtered collection contains no image. Relax your filters or fetch a non-empty collection"));
1494 return g_strdup(
"dt_overlays_none");
1496 return g_strdup(
"dt_overlays_always");
1499 return g_strdup(
"dt_overlays_hover");
1507 gchar *txt = g_strdup(
"plugins/lighttable/overlays/global");
1518 if(over == table->
overlays)
return;
1539 const guint target_type,
const guint time, gpointer user_data)
1548 const int imgs_nb = g_list_length(table->
drag_list);
1551 uint32_t *imgs = malloc(
sizeof(uint32_t) * imgs_nb);
1553 for(
int i = 0;
i < imgs_nb;
i++)
1555 imgs[
i] = GPOINTER_TO_INT(l->data);
1558 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
1559 _DWORD, (guchar *)imgs, imgs_nb *
sizeof(uint32_t));
1571 gboolean from_cache =
TRUE;
1572 const int id = GPOINTER_TO_INT(l->data);
1574 gchar *uri = g_strdup_printf(
"file://%s", pathname);
1575 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
1576 _BYTE, (guchar *)uri, strlen(uri));
1581 GList *images = NULL;
1582 for(; l; l = g_list_next(l))
1584 const int id = GPOINTER_TO_INT(l->data);
1586 gboolean from_cache =
TRUE;
1588 gchar *uri = g_strdup_printf(
"file://%s", pathname);
1589 images = g_list_prepend(images, uri);
1591 images = g_list_reverse(images);
1595 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
_BYTE,
1596 (guchar *)uri_list, strlen(uri_list));
1608 const int32_t imgid = GPOINTER_TO_INT(table->
drag_list->data);
1612 cairo_surface_t *surface = NULL;
1617 if(thumb->
img_surf && cairo_surface_get_reference_count(thumb->
img_surf) > 0)
1619 surface = cairo_surface_reference(thumb->
img_surf);
1627 GtkWidget *image = gtk_image_new_from_surface(surface);
1628 cairo_surface_destroy(surface);
1630 gtk_widget_show(image);
1631 gtk_drag_set_icon_widget(context, image, hotspot_x, hotspot_y);
1654 fprintf(stdout,
"DND check: no pathname.\n");
1657 fprintf(stdout,
"DND check pathname: %s\n", pathname);
1659 if(g_file_test(pathname, G_FILE_TEST_IS_REGULAR))
1663 files = g_list_prepend(files, g_strdup(pathname));
1667 fprintf(stderr,
"`%s`: Unkonwn format.", pathname);
1669 else if(g_file_test(pathname, G_FILE_TEST_IS_DIR))
1671 fprintf(stderr,
"DND check: Folders are not allowed");
1672 dt_control_log(_(
"'%s': Please use 'File > Import' to import a folder."), pathname);
1676 fprintf(stderr,
"DND check: `%s` not a file or folder.\n", pathname);
1684 gchar **uris = gtk_selection_data_get_uris(selection_data);
1686 GList *files = NULL;
1690 GVfs *vfs = g_vfs_get_default();
1693 GFile *filepath = g_vfs_get_file_for_uri(vfs, uris[
i]);
1694 const gchar *pathname = g_strdup(g_file_get_path(filepath));
1696 g_object_unref(filepath);
1705 .datetime = g_date_time_new_now_local(),
1712 .elements = elements,
1718 else fprintf(stderr,
"No files to import. Check your selection or use 'File > Import'.");
1728 GtkSelectionData *selection_data, guint target_type, guint time,
1731 gboolean success =
FALSE;
1734 && (gtk_selection_data_get_length(selection_data) >= 0))
1739 gtk_drag_finish(context, success,
FALSE, time);
1816 offset = - origin_imgid;
1823 int new_rowid = CLAMP(current_rowid + offset, 0, table->
collection_count - 1);
1826 int new_imgid = table->
lut[new_rowid].
imgid;
1850 GHashTableIter iter;
1851 gpointer
value = NULL;
1852 g_hash_table_iter_init(&iter, table->
list);
1853 while(g_hash_table_iter_next(&iter, NULL, &
value))
1880 if(imgid < 0 && table->
lut)
1890 if(event->keyval != GDK_KEY_Alt_L && event->keyval != GDK_KEY_Alt_R)
1924 case GDK_KEY_Page_Up:
1929 case GDK_KEY_Page_Down:
1963 case GDK_KEY_nobreakspace:
1976 case GDK_KEY_Return:
1994 case GDK_KEY_Delete:
2021 GtkStyleContext *context = gtk_widget_get_style_context(widget);
2022 GtkAllocation allocation;
2023 gtk_widget_get_allocation(widget, &allocation);
2024 gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height);
2025 gtk_render_frame(context, cr, 0, 0, allocation.width, allocation.height);
2049 gtk_widget_set_name(table->
scroll_window,
"thumbtable-scroll");
2050 gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(table->
scroll_window),
FALSE);
2052 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(table->
scroll_window), GTK_SHADOW_NONE);
2070 table->
grid = gtk_fixed_new();
2077 if(GTK_IS_VIEWPORT(viewport))
2078 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
2081 gtk_widget_set_has_tooltip(table->
grid,
FALSE);
2082 gtk_widget_set_can_focus(table->
grid,
TRUE);
2083 gtk_widget_set_focus_on_click(table->
grid,
TRUE);
2084 gtk_widget_add_events(table->
grid, GDK_LEAVE_NOTIFY_MASK);
2085 gtk_widget_set_app_paintable(table->
grid,
TRUE);
2086 g_signal_connect(G_OBJECT(table->
grid),
"leave-notify-event", G_CALLBACK(
_event_main_leave), table);
2091 GtkAdjustment *
dummy = gtk_adjustment_new(0., 0., 1., 1., 1., 1.);
2094 gtk_container_set_focus_hadjustment(GTK_CONTAINER(table->
grid),
dummy);
2095 gtk_container_set_focus_vadjustment(GTK_CONTAINER(table->
grid),
dummy);
2096 g_object_unref(
dummy);
2107 gtk_widget_add_events(table->
grid, GDK_STRUCTURE_MASK | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
2111 gtk_widget_show(table->
grid);
2119 table->
list = g_hash_table_new(g_direct_hash, g_direct_equal);
2143 gtk_widget_set_name(table->
grid,
"thumbtable-filemanager");
2166 GtkAccelGroup *accel_groups[] = {
2172 const char *path_bases[] = {
2173 _(
"Lighttable/Thumbtable"),
2174 _(
"Darkroom/Filmstrip"),
2175 _(
"Print/Filmstrip"),
2182 for(
int group_index = first_group; group_index < last_group; group_index++)
2184 GtkAccelGroup *accel_group = accel_groups[group_index];
2185 const char *path_base = path_bases[group_index];
2189 path, table->
grid, GDK_KEY_Up, 0);
2193 path, table->
grid, GDK_KEY_Down, 0);
2197 path, table->
grid, GDK_KEY_Left, 0);
2201 path, table->
grid, GDK_KEY_Right, 0);
2205 path, table->
grid, GDK_KEY_Page_Up, 0);
2209 path, table->
grid, GDK_KEY_Page_Down, 0);
2213 path, table->
grid, GDK_KEY_Home, 0);
2217 path, table->
grid, GDK_KEY_End, 0);
2221 path, table->
grid, GDK_KEY_space, 0);
2225 path, table->
grid, GDK_KEY_space, GDK_CONTROL_MASK);
2227 path =
dt_accels_build_path(path_base, _(
"Expand the current selection up to the hovered thumbnail"));
2229 path, table->
grid, GDK_KEY_space, GDK_SHIFT_MASK);
2233 path, table->
grid, GDK_KEY_Return, 0);
2237 path, table->
grid, GDK_KEY_Alt_L, 0);
2243 path, table->
grid, GDK_KEY_Delete, 0);
2262 GList *thumbs = g_hash_table_get_values(table->
list);
2264 g_hash_table_remove_all(table->
list);
2267 for(GList *l = thumbs; l; l = g_list_next(l))
2270 gtk_widget_hide(thumb->
widget);
2273 g_list_free(thumbs);
2308 g_hash_table_destroy(table->
list);
2339 GList *thumbs = g_hash_table_get_values(table->
list);
2341 g_hash_table_remove_all(table->
list);
2344 for(GList *l = thumbs; l; l = g_list_next(l))
2347 gtk_widget_hide(thumb->
widget);
2350 g_list_free(thumbs);
2370 gtk_widget_set_name(table->
grid,
"thumbtable-filemanager");
2372 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(table->
scroll_window), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
2376 gtk_widget_set_name(table->
grid,
"thumbtable-filmstrip");
2378 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(table->
scroll_window), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
2388 "Selecting all images will only target visible members of image groups.\n"
2389 "Uncollapse groups to select all their members"));
2395 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2413 "Selecting a range of images will only target visible members of image groups.\n"
2414 "Uncollapse groups to select all their members"));
2419 size_t rowid_end = 0;
2425 for(GList *s = g_list_first(selected); s; s = g_list_next(s))
2427 int32_t imgid = GPOINTER_TO_INT(s->data);
2429 if(
row < 0)
continue;
2430 if(
row < rowid_start) rowid_start =
row;
2431 if(
row > rowid_end) rowid_end =
row;
2433 g_list_free(selected);
2443 if(rowid_start > rowid_end)
2452 if(rowid > rowid_end && rowid_end < table->collection_count - 1)
2455 for(
int i = rowid_end + 1;
i <= rowid;
i++)
2456 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2458 else if(rowid < rowid_start && rowid_start > 0)
2461 for(
int i = rowid_start - 1;
i >= rowid;
i--)
2462 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2486 g_list_free(to_deselect);
2497 gint64 current_time = g_get_real_time();
2498 if(
type == GDK_KEY_PRESS ||
type == GDK_KEY_RELEASE)
2507 else if(
type == GDK_ENTER_NOTIFY ||
type == GDK_LEAVE_NOTIFY)
2519 else if(
type == GDK_MOTION_NOTIFY ||
type == GDK_BUTTON_PRESS ||
type == GDK_2BUTTON_PRESS)
2526 fprintf(stderr,
"[dt_thumbtable_dispatch_over] unsupported event type: %i\n",
type);
2536 if(!gtk_widget_has_focus(table->
grid))
2542 gtk_widget_grab_focus(table->
grid);
void dt_accels_new_virtual_shortcut(dt_accels_t *accels, GtkAccelGroup *accel_group, const gchar *accel_path, GtkWidget *widget, guint key_val, GdkModifierType accel_mods)
Add a new virtual shortcut. Virtual shortcuts are immutable, read-only and don't trigger any action....
gchar * dt_accels_build_path(const gchar *scope, const gchar *feature)
Handle default and user-set shortcuts (accelerators)
#define DT_ACCELS_WIDGET_TOOLTIP_DISABLED_KEY
GList * dt_act_on_get_images()
const gchar * dt_collection_get_query(const dt_collection_t *collection)
uint32_t dt_collection_get_count(const dt_collection_t *collection)
dt_collection_properties_t
@ DT_COLLECTION_PROP_GROUPING
dt_iop_colorout_gui_data_t dummy
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_image_init(dt_image_t *img)
void dt_image_full_path(const int32_t imgid, char *pathname, size_t pathname_len, gboolean *from_cache, const char *calling_func)
Get the full path of an image out of the database.
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
int32_t dt_control_get_mouse_over_id()
void dt_control_set_mouse_over_id(int32_t value)
void dt_control_log(const char *msg,...)
int32_t dt_control_get_keyboard_over_id()
void dt_control_set_keyboard_over_id(int32_t value)
gboolean dt_control_remove_images()
gboolean dt_supported_image(const gchar *filename)
check if file is a supported image
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define g_list_is_singleton(list)
static void dt_free_gpointer(gpointer ptr)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static const GtkTargetEntry target_list_all[]
static const guint n_targets_all
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
void dt_gui_remove_class(GtkWidget *widget, const gchar *class_name)
void dt_gui_add_help_link(GtkWidget *widget, char *link)
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
static gboolean enable(dt_image_t *image)
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_from_stmt(dt_image_t *img, sqlite3_stmt *stmt)
dt_image_t * dt_image_cache_testget(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_control_import(dt_control_import_t data)
Process a list of images to import with or without copying the files on an arbitrary hard-drive.
int32_t dt_selection_get_first_id(struct dt_selection_t *selection)
void dt_selection_deselect_list(struct dt_selection_t *selection, const GList *const l)
GList * dt_selection_get_list(struct dt_selection_t *selection)
gboolean dt_selection_is_id_selected(struct dt_selection_t *selection, int32_t imgid)
void dt_selection_select_list(struct dt_selection_t *selection, const GList *const l)
void dt_selection_deselect(dt_selection_t *selection, int32_t imgid)
void dt_selection_select_single(dt_selection_t *selection, int32_t imgid)
void dt_selection_toggle(dt_selection_t *selection, int32_t imgid)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_VIEWMANAGER_THUMBTABLE_ACTIVATE
@ DT_SIGNAL_CONTROL_PROFILE_USER_CHANGED
This signal is raised when a profile is changed by the user 1 uint32_t : the profile type that has ch...
@ DT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE
This signal is raised when mouse hovers over image thumbs both on lighttable and in the filmstrip....
@ DT_SIGNAL_IMAGE_INFO_CHANGED
This signal is raised when any of image info has changed
@ DT_SIGNAL_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
@ DT_SIGNAL_VIEWMANAGER_FILMSTRIP_DRAG_BEGIN
This signal is raised when a drag starts from the filmstrip. Views that need filmstrip drags to commi...
@ DT_SIGNAL_COLLECTION_CHANGED
This signal is raised when collection changed. To avoid leaking the list, dt_collection_t is connecte...
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
unsigned __int64 uint64_t
struct dt_gui_gtk_t * gui
struct dt_collection_t * collection
struct dt_selection_t * selection
struct dt_control_signal_t * signals
struct dt_image_cache_t * image_cache
struct dt_view_manager_t * view_manager
GtkAccelGroup * map_accels
GtkAccelGroup * global_accels
GtkAccelGroup * print_accels
GtkAccelGroup * lighttable_accels
GtkAccelGroup * darkroom_accels
dt_thumbnail_overlay_t over
cairo_surface_t * img_surf
Cache entry for a single thumbnail.
gboolean collection_inited
dt_thumbtable_mode_t mode
int last_h_scrollbar_height
GtkAdjustment * v_scrollbar
dt_thumbtable_zoom_t zoom
int last_v_scrollbar_width
GtkWidget * scroll_window
dt_thumbtable_cache_t * lut
GtkAdjustment * h_scrollbar
dt_thumbnail_overlay_t overlays
gboolean reset_collection
GtkWidget * parent_overlay
gboolean draw_group_borders
dt_thumbtable_t * thumbtable_lighttable
dt_thumbtable_t * thumbtable_filmstrip
typedef double((*spd)(unsigned long int wavelength, double TempK))
dt_thumbnail_t * dt_thumbnail_new(int rowid, dt_thumbnail_overlay_t over, dt_thumbtable_t *table, dt_image_t *info)
void dt_thumbnail_set_mouseover(dt_thumbnail_t *thumb, gboolean over)
void dt_thumbnail_resync_info(dt_thumbnail_t *thumb, const dt_image_t *const info)
void dt_thumbnail_set_overlay(dt_thumbnail_t *thumb, dt_thumbnail_overlay_t mode)
void dt_thumbnail_set_group_border(dt_thumbnail_t *thumb, dt_thumbnail_border_t border)
int dt_thumbnail_destroy(dt_thumbnail_t *thumb)
void dt_thumbnail_update_gui(dt_thumbnail_t *thumb)
void dt_thumbnail_update_selection(dt_thumbnail_t *thumb, gboolean selected)
void dt_thumbnail_alternative_mode(dt_thumbnail_t *thumb, gboolean enable)
void dt_thumbnail_resize(dt_thumbnail_t *thumb, int width, int height)
#define dt_thumbnail_image_refresh(thumb)
static dt_thumbnail_overlay_t sanitize_overlays(dt_thumbnail_overlay_t overlays)
@ DT_THUMBNAIL_BORDER_BOTTOM
@ DT_THUMBNAIL_BORDER_TOP
@ DT_THUMBNAIL_BORDER_RIGHT
@ DT_THUMBNAIL_BORDER_LEFT
@ DT_THUMBNAIL_OVERLAYS_HOVER_NORMAL
@ DT_THUMBNAIL_OVERLAYS_ALWAYS_NORMAL
@ DT_THUMBNAIL_OVERLAYS_NONE
void dt_thumbtable_set_zoom(dt_thumbtable_t *table, dt_thumbtable_zoom_t level)
static int _position_to_rowid(dt_thumbtable_t *table, const double x, const double y)
void _add_thumbnail_at_rowid(dt_thumbtable_t *table, const size_t rowid, const int32_t mouse_over)
static void _scrollbar_page_size_notify(GObject *object, GParamSpec *pspec, gpointer user_data)
int dt_thumbtable_scroll_to_selection(dt_thumbtable_t *table)
Scroll to show selected content.
gboolean _event_main_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
int dt_thumbtable_scroll_to_imgid(dt_thumbtable_t *table, int32_t imgid)
Scroll the view to show a specific image.
static void _dt_collection_changed_callback(gpointer instance, dt_collection_change_t query_change, dt_collection_properties_t changed_property, gpointer imgs, const int next, gpointer user_data)
gboolean dt_thumbtable_get_focus_peaking(dt_thumbtable_t *table)
static gboolean _thumbtable_idle_update(gpointer user_data)
void dt_thumbtable_update(dt_thumbtable_t *table)
void dt_thumbtable_offset_zoom(dt_thumbtable_t *table, const double delta_x, const double delta_y)
static void _thumbtable_drag_set_icon(dt_thumbtable_t *table, GdkDragContext *context)
void dt_thumbtable_set_active_rowid(dt_thumbtable_t *table)
Update internal active row tracking.
void dt_thumbtable_get_scroll_position(dt_thumbtable_t *table, double *x, double *y)
static gint _thumb_compare_rowid_desc(gconstpointer a, gconstpointer b)
void _move_in_grid(dt_thumbtable_t *table, GdkEventKey *event, dt_thumbtable_direction_t direction, int origin_imgid)
static int _grab_focus(dt_thumbtable_t *table)
static int dt_thumbtable_scroll_to_position(dt_thumbtable_t *table, const double x, const double y)
static void _thumbs_update_overlays_mode(dt_thumbtable_t *table)
void dt_thumbtable_apply_grid_configuration(dt_thumbtable_t *table)
Apply grid configuration changes with proper event synchronization.
void dt_thumbtable_configure(dt_thumbtable_t *table)
void dt_thumbtable_cleanup(dt_thumbtable_t *table)
static gint64 next_over_time
void _grid_configure(dt_thumbtable_t *table, int width, int height, int per_row, int thumb_width, int thumb_height)
gboolean _is_rowid_visible(dt_thumbtable_t *table, int rowid)
int _imgid_to_rowid(dt_thumbtable_t *table, int32_t imgid)
gboolean dt_thumbtable_get_focus_regions(dt_thumbtable_t *table)
void dt_thumbtable_set_focus_peaking(dt_thumbtable_t *table, gboolean enable)
static int _find_rowid_from_imgid(dt_thumbtable_t *table, const int32_t imgid)
GList * _thumbtable_dnd_import_check(GList *files, const char *pathname, int *elements)
void dt_thumbtable_event_dnd_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, gpointer user_data)
Handle drag-and-drop data received.
static gboolean _thumbtable_dnd_import(GtkSelectionData *selection_data)
static void _scrollbar_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data)
static void _dt_collection_lut(dt_thumbtable_t *table)
void _resize_thumbnails(dt_thumbtable_t *table)
void _populate_thumbnails(dt_thumbtable_t *table)
void dt_thumbtable_invert_selection(dt_thumbtable_t *table)
Invert the current selection.
void _dt_thumbtable_empty_list(dt_thumbtable_t *table)
static gboolean _dt_collection_get_hash(dt_thumbtable_t *table)
static void _event_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
gboolean dt_thumbtable_get_thumbnail_info(dt_thumbtable_t *table, int32_t imgid, dt_image_t *out)
gboolean _update_row_ids(dt_thumbtable_t *table)
static void _scrollbar_value_changed(GtkAdjustment *adjustment, gpointer user_data)
static void _thumbtable_schedule_update(dt_thumbtable_t *table)
static void _parent_overlay_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data)
void _add_thumbnail_group_borders(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
void dt_thumbtable_stop(dt_thumbtable_t *table)
dt_thumbtable_direction_t
@ DT_TT_MOVE_PREVIOUS_PAGE
static gboolean _thumbtable_idle_apply_grid_configuration(gpointer user_data)
Idle callback for applying grid configuration.
void dt_thumbtable_set_focus_regions(dt_thumbtable_t *table, gboolean enable)
static void dt_thumbtable_scroll_to_rowid(dt_thumbtable_t *table, int rowid)
void _update_grid_area(dt_thumbtable_t *table)
int dt_thumbtable_scroll_to_active_rowid(dt_thumbtable_t *table)
Scroll to show the active row.
gboolean dt_thumbtable_get_draw_group_borders(dt_thumbtable_t *table)
void dt_thumbtable_dispatch_over(dt_thumbtable_t *table, GdkEventType type, int32_t imgid)
Update the mouse-over image ID with conflict resolution.
static gboolean _thumbtable_clone_lut(dt_thumbtable_t *dst)
void _alternative_mode(dt_thumbtable_t *table, gboolean enable)
gboolean dt_thumbtable_key_pressed_grid(GtkWidget *self, GdkEventKey *event, gpointer user_data)
void dt_thumbtable_set_overlays_mode(dt_thumbtable_t *table, dt_thumbnail_overlay_t over)
Set the overlay display mode for thumbnails.
static void _rowid_to_position(dt_thumbtable_t *table, int rowid, int *x, int *y)
static gboolean _draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data)
static void _dt_profile_change_callback(gpointer instance, int type, gpointer user_data)
static gboolean _get_row_ids(dt_thumbtable_t *table, int *rowid_min, int *rowid_max)
void dt_thumbtable_refresh_thumbnail_real(dt_thumbtable_t *table, int32_t imgid, gboolean reinit)
void dt_thumbtable_select_all(dt_thumbtable_t *table)
Select all images in the current grid.
static void _dt_selection_changed_callback(gpointer instance, gpointer user_data)
void dt_thumbtable_reset_collection(dt_thumbtable_t *table)
gboolean dt_thumbtable_key_released_grid(GtkWidget *self, GdkEventKey *event, gpointer user_data)
dt_thumbtable_zoom_t dt_thumbtable_get_zoom(dt_thumbtable_t *table)
static void _event_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
#define IS_COLLECTION_EDGE(rowid)
static gboolean _set_thumb_position(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
static void _event_dnd_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, const guint target_type, const guint time, gpointer user_data)
void dt_thumbtable_set_parent(dt_thumbtable_t *table, dt_thumbtable_mode_t mode)
static gchar * _thumbs_get_overlays_class(dt_thumbnail_overlay_t over)
void dt_thumbtable_queue_update(dt_thumbtable_t *table)
dt_thumbtable_t * dt_thumbtable_new(dt_thumbtable_mode_t mode)
Create a new thumbnail table widget.
void dt_thumbtable_set_draw_group_borders(dt_thumbtable_t *table, gboolean enable)
void _mouse_over_image_callback(gpointer instance, gpointer user_data)
void dt_thumbtable_select_range(dt_thumbtable_t *table, const int rowid)
Select a range of images in the collection.
static void _dt_image_info_changed_callback(gpointer instance, gpointer imgs, gpointer user_data)
static void _thumbtable_schedule_focus(dt_thumbtable_t *table, const gint priority)
dt_thumbnail_t * _find_thumb_by_imgid(dt_thumbtable_t *table, const int32_t imgid)
static int _thumb_cell_decoration(void)
void dt_thumbtable_update_parent(dt_thumbtable_t *table)
A widget to manage and display image thumbnails in Ansel's lighttable and filmstrip views.
dt_thumbtable_mode_t
Display modes for the thumbnail table.
@ DT_THUMBTABLE_MODE_FILMSTRIP
@ DT_THUMBTABLE_MODE_FILEMANAGER
dt_thumbtable_zoom_t
Zoom levels for thumbnail display.
#define dt_thumbtable_refresh_thumbnail(table, imgid, reinit)
void dt_thumbtable_info_cleanup(void)
void dt_thumbtable_info_debug_assert_matches_cache(const dt_image_t *sql_info)
void dt_thumbtable_info_seed_image_cache(const dt_image_t *info)
sqlite3_stmt * dt_thumbtable_info_get_collection_stmt(void)
static gboolean dt_thumbtable_info_is_grouped(const dt_image_t info)
char * dt_get_help_url(char *name)
gchar * dt_util_glist_to_str(const gchar *separator, GList *items)
gboolean dt_view_active_images_has_imgid(int32_t imgid)
void dt_view_image_info_update(int32_t imgid)