74#ifdef GDK_WINDOWING_QUARTZ
78#include <glib-object.h>
99 const gboolean can_clone = (src->
lut
121 for(uint32_t
i = 0;
i < count;
i++)
122 cloned_lut[
i].thumb = NULL;
127 dst->
lut = cloned_lut;
190 if(thumb_a->
rowid > thumb_b->
rowid)
return -1;
219 if(table->
thumb_nb == 0) gtk_widget_queue_draw(table->
grid);
220 return G_SOURCE_REMOVE;
301 for(
int rowid = row_start; rowid <= row_end; rowid++)
306 const gboolean mouse_over = thumb->
mouse_over;
313 gtk_widget_queue_draw(thumb->
widget);
319 for(
int rowid = row_start; rowid <= row_end; rowid++)
438 rowid = table->
rowid;
538 GtkWidgetPath *path = gtk_widget_path_new();
539 gtk_widget_path_append_type(path, GTK_TYPE_EVENT_BOX);
540 gtk_widget_path_iter_add_class(path, -1,
"thumb-cell");
542 GtkStyleContext *ctx = gtk_style_context_new();
543 gtk_style_context_set_path(ctx, path);
545 GtkBorder margin, border;
546 gtk_style_context_get_margin(ctx, GTK_STATE_FLAG_NORMAL, &margin);
547 gtk_style_context_get_border(ctx, GTK_STATE_FLAG_NORMAL, &border);
550 gtk_widget_path_unref(path);
552 return MAX(0, (border.left + border.right) + (margin.left + margin.right));
563 int new_thumbs_per_row = 0;
564 int new_thumb_width = 0;
565 int new_thumb_height = 0;
570 &new_thumb_width, &new_thumb_height);
574 if(new_width < 32 || new_height < 32)
584 const gboolean thumbs_changed = (!table->
configured
596 _grid_configure(table, new_width, new_height, new_thumbs_per_row, new_thumb_width, new_thumb_height);
612 gboolean found =
FALSE;
621 if(g_hash_table_lookup(table->
list, GINT_TO_POINTER(imgid)) == thumb)
636#define CLAMP_ROW(rowid) CLAMP(rowid, 0, table->collection_count - 1)
637#define IS_COLLECTION_EDGE(rowid) (rowid < 0 || rowid >= table->collection_count)
645 const int32_t rowid = thumb->
rowid;
659 const int32_t imgid = table->
lut[rowid].
imgid;
669 gboolean new_item =
TRUE;
670 gboolean new_position =
TRUE;
677 if(mapped_thumb == table->
lut[rowid].
thumb)
679 thumb = mapped_thumb;
680 new_position =
FALSE;
698 thumb->
rowid = rowid;
706 g_hash_table_insert(table->
list, GINT_TO_POINTER(thumb->
info.
id), thumb);
714 if(new_item || size_changed || table->
overlays != thumb->
over)
727 else if(new_position || size_changed)
742 gtk_widget_show(thumb->
widget);
762 gpointer
value = NULL;
763 g_hash_table_iter_init(&iter, table->
list);
764 while(g_hash_table_iter_next(&iter, NULL, &
value))
785 gtk_widget_queue_draw(thumb->
widget);
794 if(keep_max <= keep_min)
return;
797 GList *evicted = NULL;
801 gpointer
value = NULL;
802 g_hash_table_iter_init(&iter, table->
list);
803 while(g_hash_table_iter_next(&iter, NULL, &
value))
806 if(thumb->
rowid >= keep_min && thumb->
rowid < keep_max)
continue;
807 g_hash_table_iter_remove(&iter);
808 evicted = g_list_prepend(evicted, thumb);
814 const guint count = g_list_length(evicted);
815 for(GList *l = evicted; l; l = g_list_next(l))
818 gtk_widget_hide(thumb->
widget);
821 g_list_free(evicted);
834 return G_SOURCE_REMOVE;
856 gboolean empty_list = (table->
thumb_nb == 0);
875 const char *
const name = gtk_widget_get_name(table->
grid);
901 gboolean first =
TRUE;
915 if(g_hash_table_lookup(table->
list, GINT_TO_POINTER(table->
lut[rowid].
imgid)) != thumb)
921 const gboolean was_highlighted = thumb->
selected;
933 if(thumb->
selected != was_highlighted)
934 gtk_widget_queue_draw(thumb->
widget);
1003 GHashTableIter iter;
1004 gpointer
value = NULL;
1005 g_hash_table_iter_init(&iter, table->
list);
1006 while(g_hash_table_iter_next(&iter, NULL, &
value))
1034 for(GList *l = g_list_first(imgs); l; l = g_list_next(l))
1036 const int32_t imgid = GPOINTER_TO_INT(l->data);
1037 if(imgid <= 0)
continue;
1054 gtk_widget_queue_draw(thumb->
widget);
1075 const int32_t imgid =
row->id;
1076 const int32_t groupid =
row->group_id;
1119 if(
IS_NULL_PTR(collection) || collection->len == 0)
1123 old_lut = table->
lut;
1130 if(collection) g_array_free(collection,
TRUE);
1143 g_array_free(collection,
TRUE);
1151 old_lut = table->
lut;
1152 table->
lut = new_lut;
1158 g_array_free(collection,
TRUE);
1187 const int next, gpointer user_data)
1193 gboolean collapsing_changed = (table->
collapse_groups != collapse_groups);
1202 gboolean changed = hash_changed || collapsing_changed || grouping_changed;
1204 "[thumbtable] collection_changed_callback: query_change=%d changed_property=%d hash_changed=%d "
1205 "collapsing_changed=%d grouping_changed=%d -> changed=%d\n",
1206 query_change, changed_property, hash_changed, collapsing_changed, grouping_changed, changed);
1221 "The current filtered collection contains no image. Relax your filters or fetch a non-empty collection"));
1250 return g_strdup(
"dt_overlays_none");
1252 return g_strdup(
"dt_overlays_always");
1255 return g_strdup(
"dt_overlays_hover");
1263 gchar *txt = g_strdup(
"plugins/lighttable/overlays/global");
1274 if(over == table->
overlays)
return;
1295 const guint target_type,
const guint time, gpointer user_data)
1304 const int imgs_nb = g_list_length(table->
drag_list);
1307 uint32_t *imgs = malloc(
sizeof(uint32_t) * imgs_nb);
1309 for(
int i = 0;
i < imgs_nb;
i++)
1311 imgs[
i] = GPOINTER_TO_INT(l->data);
1314 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
1315 _DWORD, (guchar *)imgs, imgs_nb *
sizeof(uint32_t));
1327 gboolean from_cache =
TRUE;
1328 const int id = GPOINTER_TO_INT(l->data);
1330 gchar *uri = g_strdup_printf(
"file://%s", pathname);
1331 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
1332 _BYTE, (guchar *)uri, strlen(uri));
1337 GList *images = NULL;
1338 for(; l; l = g_list_next(l))
1340 const int id = GPOINTER_TO_INT(l->data);
1342 gboolean from_cache =
TRUE;
1344 gchar *uri = g_strdup_printf(
"file://%s", pathname);
1345 images = g_list_prepend(images, uri);
1347 images = g_list_reverse(images);
1351 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data),
_BYTE,
1352 (guchar *)uri_list, strlen(uri_list));
1368 cairo_surface_t *surface = NULL;
1375 if(thumb->
img_surf && cairo_surface_get_reference_count(thumb->
img_surf) > 0)
1377 surface = cairo_surface_reference(thumb->
img_surf);
1380 hotspot_x =
width / 2;
1387 GtkWidget *image = gtk_image_new_from_surface(surface);
1388 cairo_surface_destroy(surface);
1394 gtk_widget_set_size_request(image,
width,
height);
1396 gtk_widget_show(image);
1397 gtk_drag_set_icon_widget(context, image, hotspot_x, hotspot_y);
1421 fprintf(stdout,
"DND check: no pathname.\n");
1424 fprintf(stdout,
"DND check pathname: %s\n", pathname);
1426 if(g_file_test(pathname, G_FILE_TEST_IS_REGULAR))
1430 files = g_list_prepend(files, g_strdup(pathname));
1434 fprintf(stderr,
"`%s`: Unkonwn format.", pathname);
1436 else if(g_file_test(pathname, G_FILE_TEST_IS_DIR))
1438 *folders = g_list_prepend(*folders, g_strdup(pathname));
1442 fprintf(stderr,
"DND check: `%s` not a file or folder.\n", pathname);
1474 GFile *
folder = g_file_new_for_path(folder_path);
1475 GError *
error = NULL;
1476 GFileEnumerator *children = g_file_enumerate_children(
1477 folder, G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, &
error);
1484 g_error_free(
error);
1491 GFile *child = NULL;
1492 GError *iter_error = NULL;
1493 while(g_file_enumerator_iterate(children, NULL, &child, NULL, &iter_error))
1499 gchar *pathname = g_file_get_path(child);
1500 if(pathname && g_file_test(pathname, G_FILE_TEST_IS_REGULAR) &&
dt_import_passes_filter(filter_type, pathname))
1502 *files = g_list_prepend(*files, pathname);
1505 else if(pathname && g_file_test(pathname, G_FILE_TEST_IS_DIR))
1519 dt_print(
DT_DEBUG_IMPORT,
"[import] could not fully scan folder `%s': %s\n", folder_path, iter_error->message);
1520 g_error_free(iter_error);
1524 g_object_unref(children);
1534 GList *files = data->
files;
1537 guint scan_errors = 0;
1538 for(GList *l = data->
folders; l; l = g_list_next(l))
1541 const int elements = g_list_length(files);
1545 .datetime = g_date_time_new_now_local(),
1552 .elements = elements,
1560 dt_control_log(_(
"No matching file found in the dropped folder(s)."));
1564 dt_control_log(ngettext(
"%u folder could not be scanned (permission denied?)",
1565 "%u folders could not be scanned (permission denied?)", scan_errors),
1568 return elements > 0 ? 0 : 1;
1591 GtkWidget *dialog = gtk_message_dialog_new(
1592 GTK_WINDOW(
dt_gui_get_ui()->main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
1593 GTK_BUTTONS_NONE,
"%s",
1594 _(
"The dropped folder(s) will be scanned recursively.\nWhich files should be imported?"));
1595#ifdef GDK_WINDOWING_QUARTZ
1603 gtk_window_set_title(GTK_WINDOW(dialog), _(
"Import folder"));
1604 const gint choice = gtk_dialog_run(GTK_DIALOG(dialog));
1605 gtk_widget_destroy(dialog);
1627 data->
files = files;
1638 gchar **uris = gtk_selection_data_get_uris(selection_data);
1640 GList *files = NULL;
1641 GList *folders = NULL;
1645 GVfs *vfs = g_vfs_get_default();
1648 GFile *filepath = g_vfs_get_file_for_uri(vfs, uris[
i]);
1649 const gchar *pathname = g_strdup(g_file_get_path(filepath));
1651 g_object_unref(filepath);
1662 else if(elements > 0)
1668 .datetime = g_date_time_new_now_local(),
1675 .elements = elements,
1682 else fprintf(stderr,
"No files to import. Check your selection or use 'File > Import'.");
1692 GtkSelectionData *selection_data, guint target_type, guint time,
1695 gboolean success =
FALSE;
1698 && (gtk_selection_data_get_length(selection_data) >= 0))
1703 gtk_drag_finish(context, success,
FALSE, time);
1767 offset = - origin_imgid;
1774 int new_rowid = CLAMP(current_rowid + offset, 0, table->
collection_count - 1);
1777 int new_imgid = table->
lut[new_rowid].
imgid;
1801 GHashTableIter iter;
1802 gpointer
value = NULL;
1803 g_hash_table_iter_init(&iter, table->
list);
1804 while(g_hash_table_iter_next(&iter, NULL, &
value))
1831 if(imgid < 0 && table->
lut)
1841 if(event->keyval != GDK_KEY_Alt_L && event->keyval != GDK_KEY_Alt_R)
1864 case GDK_KEY_Page_Up:
1869 case GDK_KEY_Page_Down:
1884 case GDK_KEY_Return:
1902 case GDK_KEY_Delete:
1933 GtkStyleContext *context = gtk_widget_get_style_context(widget);
1934 GtkAllocation allocation;
1935 gtk_widget_get_allocation(widget, &allocation);
1936 gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height);
1937 gtk_render_frame(context, cr, 0, 0, allocation.width, allocation.height);
1980 gtk_widget_set_name(table->
scroll_window,
"thumbtable-scroll");
1981 gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(table->
scroll_window),
FALSE);
1983 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(table->
scroll_window), GTK_SHADOW_NONE);
2011 if(GTK_IS_VIEWPORT(viewport))
2012 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
2015 gtk_widget_set_has_tooltip(table->
grid,
FALSE);
2021 gtk_widget_set_can_focus(table->
grid, can_focus);
2022 gtk_widget_set_focus_on_click(table->
grid, can_focus);
2023 gtk_widget_add_events(table->
grid, GDK_LEAVE_NOTIFY_MASK);
2024 gtk_widget_set_app_paintable(table->
grid,
TRUE);
2025 g_signal_connect(G_OBJECT(table->
grid),
"leave-notify-event", G_CALLBACK(
_event_main_leave), table);
2030 GtkAdjustment *
dummy = gtk_adjustment_new(0., 0., 1., 1., 1., 1.);
2033 gtk_container_set_focus_hadjustment(GTK_CONTAINER(table->
grid),
dummy);
2034 gtk_container_set_focus_vadjustment(GTK_CONTAINER(table->
grid),
dummy);
2035 g_object_unref(
dummy);
2046 gtk_widget_add_events(table->
grid, GDK_STRUCTURE_MASK | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
2050 gtk_widget_show(table->
grid);
2058 table->
list = g_hash_table_new(g_direct_hash, g_direct_equal);
2083 gtk_widget_set_name(table->
grid,
"thumbtable-filemanager");
2108 GtkAccelGroup *accel_groups[] = {
2114 const char *path_bases[] = {
2115 _(
"Lighttable/Thumbtable"),
2116 _(
"Darkroom/Filmstrip"),
2117 _(
"Print/Filmstrip"),
2122 int first_group = 1, last_group = 4;
2134 for(
int group_index = first_group; group_index < last_group; group_index++)
2136 GtkAccelGroup *accel_group = accel_groups[group_index];
2137 const char *path_base = path_bases[group_index];
2141 path, table->
grid, GDK_KEY_Up, 0);
2145 path, table->
grid, GDK_KEY_Down, 0);
2149 path, table->
grid, GDK_KEY_Left, 0);
2153 path, table->
grid, GDK_KEY_Right, 0);
2157 path, table->
grid, GDK_KEY_Page_Up, 0);
2161 path, table->
grid, GDK_KEY_Page_Down, 0);
2165 path, table->
grid, GDK_KEY_Home, 0);
2169 path, table->
grid, GDK_KEY_End, 0);
2173 path, table->
grid, GDK_KEY_space, 0);
2179 path, table->
grid, GDK_KEY_space, GDK_CONTROL_MASK);
2181 path =
dt_accels_build_path(path_base, _(
"Expand the current selection up to the hovered thumbnail"));
2183 path, table->
grid, GDK_KEY_space, GDK_SHIFT_MASK);
2187 path, table->
grid, GDK_KEY_Return, 0);
2191 path, table->
grid, GDK_KEY_Alt_L, 0);
2197 path, table->
grid, GDK_KEY_Delete, 0);
2216 GList *thumbs = g_hash_table_get_values(table->
list);
2218 g_hash_table_remove_all(table->
list);
2221 for(GList *l = thumbs; l; l = g_list_next(l))
2224 gtk_widget_hide(thumb->
widget);
2227 g_list_free(thumbs);
2266 g_hash_table_destroy(table->
list);
2302 GList *thumbs = g_hash_table_get_values(table->
list);
2304 g_hash_table_remove_all(table->
list);
2307 for(GList *l = thumbs; l; l = g_list_next(l))
2310 gtk_widget_hide(thumb->
widget);
2313 g_list_free(thumbs);
2343 "Selecting all images will only target visible members of image groups.\n"
2344 "Uncollapse groups to select all their members"));
2350 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2368 "Selecting a range of images will only target visible members of image groups.\n"
2369 "Uncollapse groups to select all their members"));
2374 size_t rowid_end = 0;
2380 for(GList *s = g_list_first(
selected); s; s = g_list_next(s))
2382 int32_t imgid = GPOINTER_TO_INT(s->data);
2384 if(
row < 0)
continue;
2385 if(
row < rowid_start) rowid_start =
row;
2386 if(
row > rowid_end) rowid_end =
row;
2398 if(rowid_start > rowid_end)
2407 if(rowid > rowid_end && rowid_end < table->collection_count - 1)
2410 for(
int i = rowid_end + 1;
i <= rowid;
i++)
2411 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2413 else if(rowid < rowid_start && rowid_start > 0)
2416 for(
int i = rowid_start - 1;
i >= rowid;
i--)
2417 img = g_list_prepend(img, GINT_TO_POINTER(table->
lut[
i].
imgid));
2441 g_list_free(to_deselect);
2452 gint64 current_time = g_get_real_time();
2453 if(
type == GDK_KEY_PRESS ||
type == GDK_KEY_RELEASE)
2462 else if(
type == GDK_ENTER_NOTIFY ||
type == GDK_LEAVE_NOTIFY)
2474 else if(
type == GDK_MOTION_NOTIFY ||
type == GDK_BUTTON_PRESS ||
type == GDK_2BUTTON_PRESS)
2481 fprintf(stderr,
"[dt_thumbtable_dispatch_over] unsupported event type: %i\n",
type);
2491 if(!gtk_widget_has_focus(table->
grid))
2497 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)
Build the accel path of feature under scope.
Handle default and user-set shortcuts (accelerators)
#define DT_ACCELS_WIDGET_TOOLTIP_DISABLED_KEY
GList * dt_act_on_get_images()
struct dt_accels_t * dt_gui_get_accels(void)
struct dt_ui_t * dt_gui_get_ui(void)
void dt_gui_add_help_link(GtkWidget *widget, char *link)
static void error(char *msg)
dt_collection_t * dt_collection_get_global(void)
uint32_t dt_collection_get_count(const dt_collection_t *collection)
dt_collection_properties_t
@ DT_COLLECTION_PROP_GROUPING
@ DT_COLLECTION_CHANGE_BACKGROUND_SYNC
uint64_t dt_collection_query_get_generation(void)
dt_iop_colorout_gui_data_t dummy
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
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.
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)
struct dt_control_t * dt_control_get_global(void)
gboolean dt_control_remove_images()
struct dt_view_manager_t * dt_view_manager_get_global(void)
struct dt_gui_gtk_t * dt_gui_get_global(void)
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * folder
destination folder chooser
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)
Initialise a mutex. With mutexattr NULL – which is how 54 of the 56 call sites in this tree spell it ...
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
const dt_thumbtable_layout_ops_t * dt_thumbtable_grid_ops(void)
const dt_thumbtable_layout_ops_t * dt_thumbtable_filmstrip_ops(void)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
#define g_list_is_singleton(list)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
static gboolean enable(const dt_image_t *image)
dt_image_t * dt_image_cache_testget(const int32_t imgid, char mode)
void dt_image_derive_fields(dt_image_t *img)
Compute the fields the database does not store: rating, monochrome and HDR predicates,...
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
gboolean dt_supported_image(const gchar *filename)
void dt_image_repository_foreach_collected(dt_image_repository_collected_cb cb, void *user_data)
Every image of the current collection, in collection order, already mapped.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
gboolean dt_import_passes_filter(const dt_import_filter_type_t filter_type, const gchar *pathname)
@ DT_IMPORT_FILTER_RASTER
int 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.
dt_job_t * dt_control_job_create(dt_job_execute_callback execute, const char *msg,...)
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
void * dt_control_job_get_params(const _dt_job_t *job)
void dt_control_job_set_params(_dt_job_t *job, void *params, dt_job_destroy_callback callback)
_lib_location_type_t type
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#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 void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
void dt_osx_disallow_fullscreen(GtkWidget *widget)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
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)
struct dt_selection_t * dt_selection_get_global(void)
GList * dt_selection_get_list(struct dt_selection_t *selection)
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)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_VIEWMANAGER_THUMBTABLE_ACTIVATE
@ DT_SIGNAL_ACTIVE_IMAGES_CHANGE
This signal is raised when image shown in the main view change no param, no returned value.
@ 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_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)
static const dt_aligned_pixel_simd_t value
unsigned __int64 uint64_t
GtkAccelGroup * map_accels
GtkAccelGroup * print_accels
GtkAccelGroup * lighttable_accels
GtkAccelGroup * darkroom_accels
dt_import_filter_type_t filter_type
dt_thumbnail_overlay_t over
cairo_surface_t * img_surf
Cache entry for a single thumbnail.
Per-mode layout strategy. One instance per frontend, shared (const) by all tables of that mode and st...
void(* pre_activate)(dt_thumbtable_t *table, int32_t imgid)
void(* on_drag_begin)(dt_thumbtable_t *table, int32_t imgid)
int(* position_to_rowid)(dt_thumbtable_t *table, const double x, const double y)
void(* configure_dims)(dt_thumbtable_t *table, int *new_width, int *new_height, int *per_row, int *thumb_width, int *thumb_height)
void(* get_row_ids)(dt_thumbtable_t *table, int *rowid_min, int *rowid_max)
gboolean(* wants_page_size_notify)(dt_thumbtable_t *table, GObject *object)
void(* move_child)(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
void(* group_borders)(dt_thumbtable_t *table, dt_thumbnail_t *thumb, dt_thumbnail_border_t *borders)
gboolean(* wants_scroll_value)(dt_thumbtable_t *table, GtkAdjustment *adjustment)
void(* update_content_size)(dt_thumbtable_t *table)
void(* grab_focus)(dt_thumbtable_t *table)
gboolean(* is_rowid_visible)(dt_thumbtable_t *table, int rowid)
void(* rowid_to_position)(dt_thumbtable_t *table, int rowid, int *x, int *y)
void(* on_thumbnail_added)(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
gboolean(* relevant_scrollbar_changed)(dt_thumbtable_t *table, GtkWidget *widget, GtkAllocation *allocation)
gboolean(* is_thumb_highlighted)(dt_thumbtable_t *table, int32_t imgid)
GtkWidget *(* create_content_widget)(void)
gboolean(* handle_key)(dt_thumbtable_t *table, GdkEventKey *event, guint key, int32_t imgid)
void(* place_child)(dt_thumbtable_t *table, dt_thumbnail_t *thumb)
void(* setup_parent)(dt_thumbtable_t *table)
const dt_thumbtable_layout_ops_t * ops
gboolean collection_inited
dt_thumbtable_mode_t mode
int last_h_scrollbar_height
GtkAdjustment * v_scrollbar
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_OVERLAYS_HOVER_NORMAL
@ DT_THUMBNAIL_OVERLAYS_ALWAYS_NORMAL
@ DT_THUMBNAIL_OVERLAYS_NONE
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)
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)
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_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)
static void _dt_active_images_changed_callback(gpointer instance, gpointer user_data)
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 gboolean _evict_idle(gpointer user_data)
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)
@ _DT_DND_IMPORT_CHOICE_RASTER
@ _DT_DND_IMPORT_CHOICE_RAW
@ _DT_DND_IMPORT_CHOICE_ALL
gboolean _update_row_ids(dt_thumbtable_t *table)
static void _scrollbar_value_changed(GtkAdjustment *adjustment, gpointer user_data)
static const dt_thumbtable_layout_ops_t * _ops_for_mode(dt_thumbtable_mode_t mode)
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)
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)
static void _collection_lut_row(void *user_data, const dt_image_t *row)
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)
int dt_thumbtable_thumb_cell_decoration(void)
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.
void dt_thumbtable_schedule_focus_real(dt_thumbtable_t *table, const gint priority)
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)
int dt_thumbtable_find_rowid_from_imgid(dt_thumbtable_t *table, const int32_t imgid)
static void _evict_thumbnails(dt_thumbtable_t *table, const int keep_min, const int keep_max)
static void _event_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
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_move_in_grid(dt_thumbtable_t *table, GdkEventKey *event, dt_thumbtable_direction_t direction, int origin_imgid)
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)
static void _dnd_folder_import_job_cleanup(void *p)
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 _dnd_recurse_folder(const char *folder_path, dt_import_filter_type_t filter_type, GList **files, guint *scan_errors)
static void _thumbtable_dnd_scan_folders_and_import(GList *folders, GList *files)
GList * _thumbtable_dnd_import_check(GList *files, const char *pathname, int *elements, GList **folders)
static int32_t _dnd_folder_import_job_run(dt_job_t *job)
static void _refresh_highlights(dt_thumbtable_t *table)
dt_thumbnail_t * _find_thumb_by_imgid(dt_thumbtable_t *table, const int32_t imgid)
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
#define dt_thumbtable_refresh_thumbnail(table, imgid, reinit)
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)
static gboolean dt_thumbtable_info_is_grouped(const dt_image_t info)
Private interface shared between the thumbtable engine (thumbtable.c) and its two frontends (filemana...
#define dt_thumbtable_schedule_focus(table, priority)
dt_thumbtable_direction_t
@ DT_TT_MOVE_PREVIOUS_PAGE
static double dt_get_wtime(void)
char * dt_get_help_url(char *name)
gchar * dt_util_glist_to_str(const gchar *separator, GList *items)
void dt_view_image_info_update(int32_t imgid)