80#include <gdk/gdkkeysyms.h>
84#ifdef GDK_WINDOWING_QUARTZ
179 N_(
"import timestamp"),
180 N_(
"change timestamp"),
181 N_(
"export timestamp"),
182 N_(
"print timestamp"),
193 N_(
"focus distance"),
203 "",
"",
"",
"",
"",
"",
"",
"",
219 return _(
"EXIF and IPTC");
224 static const char *
v[] = {
"darkroom",
"lighttable",
"map",
"print",
"slideshow",
"studio_capture", NULL};
259#define NODATA_STRING "-"
271 m->index =
m->order =
i;
273 d->metadata = g_list_prepend(
d->metadata,
m);
282 if(g_utf8_validate(
string, -1, 0))
return;
284 unsigned char *str = (
unsigned char *)
string;
287 while(*str !=
'\000' &&
n < length)
289 if((*str < 0x20) || (*str >= 0x7f)) *str =
'.';
302 if(
m->index == index)
315 GtkLabel *label = GTK_LABEL(gtk_grid_get_child_at(GTK_GRID(
d->grid), 1,
m->order));
316 char *markup = g_markup_printf_escaped(format, gtk_label_get_text(label));
317 gtk_label_set_markup(label, markup);
325 gboolean validated = g_utf8_validate(
value, -1, NULL);
334 m->value = g_strdup(str);
335 GtkWidget *w_value = gtk_grid_get_child_at(GTK_GRID(
d->grid), 1,
m->order);
336 gtk_label_set_text(GTK_LABEL(w_value), str);
337 const char *
tooltip =
m->tooltip ?
m->tooltip :
m->value;
338 gtk_widget_set_tooltip_text(GTK_WIDGET(w_value),
tooltip);
378#define EMPTY_FIELD '.'
379#define FALSE_FIELD '.'
380#define TRUE_FIELD '!'
384 char *flags_tooltip = NULL;
385 char *flag_descriptions[] = { N_(
"unused"),
386 N_(
"unused/deprecated"),
390 N_(
"marked for deletion"),
391 N_(
"auto-applying presets applied"),
392 N_(
"legacy flag. set for all new images"),
398 char *tooltip_parts[
FLAG_NB] = { 0 };
399 int next_tooltip_part = 0;
403 int stars = img->
flags & 0x7;
404 char *star_string = NULL;
408 tooltip_parts[next_tooltip_part++] = _(
"image rejected");
412 value[0] =
'0' + stars;
413 tooltip_parts[next_tooltip_part++] = star_string = g_strdup_printf(ngettext(
"image has %d star",
"image has %d stars", stars), stars);
420 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[0]);
428 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[1]);
436 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[2]);
442 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[3]);
448 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[4]);
454 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[5]);
460 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[6]);
466 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[7]);
472 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[8]);
478 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[9]);
484 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[10]);
490 tooltip_parts[next_tooltip_part++] = _(flag_descriptions[11]);
496 tooltip_parts[next_tooltip_part++] = loader_tooltip;
500 flags_tooltip = g_strjoinv(
"\n", tooltip_parts);
504 (
void)g_strlcpy(
tooltip, flags_tooltip, tooltip_size);
539 skip[md] = (counts[md] > 1);
544 gboolean same_tags =
TRUE;
545 gboolean same_categories =
TRUE;
583 if(!have_thumb_info)
return;
585 if(img_id ==
d->imgid)
return;
594 for(int32_t md = 0; md <
md_size; md++)
615 char tooltip_filmroll[300] = {0};
616 g_strlcpy(text, tinfo.
filmroll,
sizeof(text));
617 snprintf(tooltip_filmroll,
sizeof(tooltip_filmroll), _(
"double-click to jump to film roll\n%s"), text);
624 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
film_id);
629 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
id);
634 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
group_id);
643 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
version);
649 g_strlcpy(text, tinfo.
fullpath,
sizeof(text));
678 char tooltip_flags[300] = {0};
748 const gboolean milliseconds =
dt_conf_get_bool(
"lighttable/ui/milliseconds");
758 (
void)g_snprintf(text,
sizeof(text),
"%d (%d)", tinfo.
p_width, tinfo.
width);
763 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
width);
776 (
void)g_snprintf(text,
sizeof(text),
"%d", tinfo.
height);
853 char *tagstring = NULL;
854 char *categoriesstring = NULL;
858 for(GList *taglist = tags; taglist; taglist = g_list_next(taglist))
860 const char *tagname = ((
dt_tag_t *)taglist->data)->leave;
864 length = length + strlen(tagname) + 2u;
870 length = strlen(tagname) + 2u;
876 char *category = g_strdup(((
dt_tag_t *)taglist->data)->tag);
877 char *catend = g_strrstr(category,
"|");
881 char *catstart = g_strrstr(category,
"|");
882 catstart = catstart ? catstart + 1 : category;
883 categoriesstring =
dt_util_dstrcat(categoriesstring, categoriesstring ?
"\n%s: %s " :
"%s: %s ",
884 catstart, ((
dt_tag_t *)taglist->data)->leave);
887 categoriesstring =
dt_util_dstrcat(categoriesstring, categoriesstring ?
"\n%s" :
"%s",
888 ((
dt_tag_t *)taglist->data)->leave);
892 if(tagstring) tagstring[strlen(tagstring)-2] =
'\0';
923 g_strlcpy(text, (
char *)
res->data,
sizeof(text));
951 snprintf(collect,
sizeof(collect),
"1:0:0:%s$", path);
958 if(event->type != GDK_2BUTTON_PRESS)
return FALSE;
985 pref[strlen(pref) - 1] =
'\0';
1001 GtkWidget *w_name = gtk_grid_get_child_at(GTK_GRID(
d->grid), 0, j);
1002 gtk_label_set_text(GTK_LABEL(w_name), _(
m->name));
1003 gtk_widget_set_tooltip_text(w_name, _(
m->name));
1004 GtkWidget *w_value = gtk_grid_get_child_at(GTK_GRID(
d->grid), 1, j);
1005 gtk_label_set_text(GTK_LABEL(w_value),
m->value);
1006 const char *
tooltip =
m->tooltip ?
m->tooltip :
m->value;
1007 gtk_widget_set_tooltip_text(w_value,
tooltip);
1009 const int i =
m->index;
1010 gtk_label_set_ellipsize(GTK_LABEL(w_value),
1012 ? PANGO_ELLIPSIZE_END : PANGO_ELLIPSIZE_MIDDLE);
1016 if(
d->filmroll_event && GTK_IS_WIDGET(
d->filmroll_event))
1017 g_signal_handlers_disconnect_by_func(
d->filmroll_event, G_CALLBACK(
_filmroll_clicked), NULL);
1018 g_signal_connect(G_OBJECT(w_value),
"button-press-event", G_CALLBACK(
_filmroll_clicked), NULL);
1019 d->filmroll_event = G_OBJECT(w_value);
1022 gtk_widget_set_visible(w_name,
m->visible);
1023 gtk_widget_set_visible(w_value,
m->visible);
1037 GtkWidget *w_name = gtk_label_new(_(
m->name));
1038 gtk_widget_set_halign(w_name, GTK_ALIGN_START);
1039 gtk_label_set_xalign(GTK_LABEL(w_name), 0.0f);
1040 gtk_label_set_ellipsize(GTK_LABEL(w_name), PANGO_ELLIPSIZE_END);
1041 gtk_widget_set_tooltip_text(w_name, _(
m->name));
1044 gtk_widget_set_name(w_value,
"brightbg");
1045 gtk_label_set_selectable(GTK_LABEL(w_value),
TRUE);
1046 gtk_widget_set_halign(w_value, GTK_ALIGN_FILL);
1047 gtk_label_set_xalign(GTK_LABEL(w_value), 0.0f);
1049 gtk_grid_attach(GTK_GRID(
d->grid), w_name, 0, j, 1, 1);
1050 gtk_grid_attach(GTK_GRID(
d->grid), w_value, 1, j, 1, 1);
1057 if(!prefs_list || !prefs_list[0])
return;
1062 for(GList *pref = prefs; pref; pref = g_list_next(pref))
1064 const char *
name = (
char *)pref->data;
1065 gboolean visible =
TRUE;
1079 m->visible = visible;
1102 GtkListStore *
store = (GtkListStore *)user_data;
1104 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1107 gtk_tree_model_get_iter(GTK_TREE_MODEL(
store), &iter, path);
1111 gtk_tree_path_free(path);
1114static void _drag_data_inserted(GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
1124 GtkWidget *dialog = gtk_dialog_new_with_buttons(_(
"metadata settings"), GTK_WINDOW(win),
1125 GTK_DIALOG_DESTROY_WITH_PARENT, _(
"default"), GTK_RESPONSE_YES,
1126 _(
"cancel"), GTK_RESPONSE_NONE, _(
"save"), GTK_RESPONSE_ACCEPT, NULL);
1128 GtkWidget *area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1130 GtkWidget *w = gtk_scrolled_window_new(NULL, NULL);
1132 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1133 gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(w),
FALSE);
1135 gtk_box_pack_start(GTK_BOX(area), w,
TRUE,
TRUE, 0);
1138 G_TYPE_INT, G_TYPE_STRING, G_TYPE_BOOLEAN);
1148 gtk_list_store_append(
store, &iter);
1149 gtk_list_store_set(
store, &iter,
1157 g_object_unref(
model);
1158 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1159 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_(
"metadata"), renderer,
1161 gtk_tree_view_column_set_expand(column,
TRUE);
1162 gtk_tree_view_append_column(GTK_TREE_VIEW(
view), column);
1163 GtkWidget *header = gtk_tree_view_column_get_button(column);
1164 gtk_widget_set_tooltip_text(header,
1165 _(
"drag and drop one row at a time until you get the desired order"
1166 "\nuntick to hide metadata which are not of interest for you"
1167 "\nif different settings are needed, use presets"));
1168 renderer = gtk_cell_renderer_toggle_new();
1170 column = gtk_tree_view_column_new_with_attributes(_(
"visible"), renderer,
1172 gtk_tree_view_append_column(GTK_TREE_VIEW(
view), column);
1175 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(
view),
TRUE);
1178 gtk_container_add(GTK_CONTAINER(w),
view);
1180#ifdef GDK_WINDOWING_QUARTZ
1183 gtk_widget_show_all(dialog);
1185 int res = gtk_dialog_run(GTK_DIALOG(dialog));
1186 while(
res == GTK_RESPONSE_YES)
1188 gtk_tree_model_get_iter_first(
model, &iter);
1195 gtk_list_store_set(
store, &iter,
1200 gtk_tree_model_iter_next(
model, &iter);
1202 res = gtk_dialog_run(GTK_DIALOG(dialog));
1206 if(
res == GTK_RESPONSE_ACCEPT)
1208 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
1213 gtk_tree_model_get(
model, &iter,
1220 if(
m->index == index)
1223 m->visible = visible;
1228 valid = gtk_tree_model_iter_next(
model, &iter);
1234 gtk_widget_destroy(dialog);
1239 GtkWidget *mi = gtk_menu_item_new_with_label(_(
"preferences..."));
1241 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1249 *
size =strlen(params) + 1;
1269 m->order =
m->index;
1279 self->
data = (
void *)
d;
1284 GtkWidget *child_grid_window = gtk_grid_new();
1285 d->grid = child_grid_window;
1292 gtk_widget_show_all(
d->grid);
1293 gtk_widget_set_no_show_all(
d->grid,
TRUE);
1338 m->order =
m->index;
int32_t dt_act_on_get_first_image()
GtkWidget * dt_gui_main_window(void)
struct dt_ui_t * dt_gui_get_ui(void)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_collection_deserialize(const char *buf)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
int dt_conf_get_bool(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
gboolean dt_image_is_raw(const dt_image_t *img)
int dt_image_monochrome_flags(const dt_image_t *img)
gboolean dt_image_is_hdr(const dt_image_t *img)
gboolean dt_image_is_ldr(const dt_image_t *img)
void dt_image_film_roll_directory(const dt_image_t *img, char *pathname, size_t pathname_len)
int32_t dt_control_get_mouse_over_id()
struct dt_gui_gtk_t * dt_gui_get_global(void)
gboolean dt_datetime_gtimespan_to_local(char *local, const size_t local_size, const GTimeSpan gts, const gboolean msec, const gboolean tz)
GtkTreeStore * store
its model, owned by the view
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * view
the tree view
static const struct @4 loaders_info[LOADER_COUNT]
@ DT_IMAGE_NO_LEGACY_PRESETS
@ DT_IMAGE_AUTO_PRESETS_APPLIED
@ DT_IMAGE_THUMBNAIL_DEPRECATED
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
int * dt_image_repository_count_distinct_fields(GList *imgids)
How many DISTINCT values each dt_image_field_t takes over imgids.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
static CameraMetaData * meta
gboolean dt_handle_dialog_enter(GtkWidget *widget, GdkEventKey *event, gpointer data)
float *const restrict const size_t k
#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.
dt_mipmap_buffer_dsc_flags flags
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
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)
struct dt_selection_t * dt_selection_get_global(void)
int dt_selection_get_length(struct dt_selection_t *selection)
GList * dt_selection_get_list(struct dt_selection_t *selection)
int32_t dt_selection_repository_get_lowest_id(void)
The lowest selected image id, or UNKNOWN_IMAGE when nothing is selected.
main.selected_images, and the memory.selected_backup it is pushed onto.
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ 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_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
static const dt_aligned_pixel_simd_t value
unsigned __int64 uint64_t
GTimeSpan export_timestamp
float exif_focus_distance
GTimeSpan import_timestamp
GTimeSpan change_timestamp
GTimeSpan print_timestamp
GTimeSpan exif_datetime_taken
char filmroll[DT_PATH_MAX]
char filename[DT_MAX_FILENAME_LEN]
char fullpath[DT_PATH_MAX]
void dt_tag_repository_get_agreement(GList *imgids, gboolean *same_tags, gboolean *same_categories)
Do all of imgids carry exactly the same tags? The same categories?
data.tags and main.tagged_images.
typedef double((*spd)(unsigned long int wavelength, double TempK))
gboolean dt_thumbtable_get_thumbnail_info(dt_thumbtable_t *table, int32_t imgid, dt_image_t *out)
gchar * dt_util_longitude_str(float longitude)
gchar * dt_util_elevation_str(float elevation)
GList * dt_util_str_to_glist(const gchar *separator, const gchar *text)
char * dt_util_format_exposure(const float exposuretime)
gchar * dt_util_latitude_str(float latitude)
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER