50#ifdef GDK_WINDOWING_QUARTZ
58#include <librsvg/rsvg.h>
61#include <librsvg/rsvg-cairo.h>
158 gboolean valid =
FALSE;
160 valid = !
import->scan_state->closing &&
import->scan_state->generation ==
import->generation;
168 gtk_label_set_text(GTK_LABEL(widget), label);
176 gchar *pathname = g_file_get_path(document);
182 if(pathname && g_file_test(pathname, G_FILE_TEST_IS_REGULAR) &&
dt_supported_image(pathname))
184 import->files = g_list_prepend(import->files, pathname);
188 else if(pathname && g_file_test(pathname, G_FILE_TEST_IS_DIR))
201 GFileEnumerator *files
202 = g_file_enumerate_children(folder, G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_TYPE,
203 G_FILE_QUERY_INFO_NONE, NULL, NULL);
207 while(g_file_enumerator_iterate(files, NULL, &file, NULL, NULL))
216 g_object_unref(files);
226 g_object_unref(files);
237 GVfs *vfs = g_vfs_get_default();
238 for(GSList *uri = selection; uri; uri = g_slist_next(uri))
240 GFile *file = g_vfs_get_file_for_uri(vfs, (
const char *)uri->data);
242 g_object_unref(file);
246 GFile *filepath = g_vfs_get_file_for_uri(vfs, (
const char *)selection->data);
247 gchar *first_element = g_file_get_path(filepath);
248 g_object_unref(filepath);
250 if(first_element)
dt_conf_set_string(
"ui_last/import_first_selected_str", first_element);
254 dt_conf_set_int(
"ui_last/import_selection_nb", g_slist_length(selection));
256 import->files = g_list_sort(import->files, (GCompareFunc) g_strcmp0);
269 import->elements = (
import->files) ? g_list_length(import->files) : 0;
274 if(valid && import->files)
281 else if(import->files)
284 import->files = NULL;
306 uint32_t generation = 0;
308 if(
d->scan_state->closing)
313 d->scan_state->generation++;
314 generation =
d->scan_state->generation;
320 dt_import_t *
import = dt_import_init(d, generation);
335 if(!filename || !g_file_test(filename, G_FILE_TEST_IS_REGULAR))
return NULL;
337 GdkPixbuf *pixbuf = NULL;
338 uint8_t *buffer = NULL;
341 char *mime_type = NULL;
342 const char *
const extension = g_strrstr(filename,
".");
348 const float ratio = ((float)th_height) / ((float)th_width);
352 th_width * th_height * 3 *
sizeof(uint8_t),
357 for(
size_t k = 0;
k < th_width * th_height;
k++)
359 const float alpha = buffer[
k * 4 + 3] > 0 ? buffer[
k * 4 + 3] / 255.0f : 1.0f;
360 rgb[
k * 3] = CLAMP((
int)roundf((buffer[
k * 4] / 255.0f * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
361 rgb[
k * 3 + 1] = CLAMP((
int)roundf((buffer[
k * 4 + 1] / 255.0f * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
362 rgb[
k * 3 + 2] = CLAMP((
int)roundf((buffer[
k * 4 + 2] / 255.0f * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
366 GdkPixbuf *tmp = gdk_pixbuf_new_from_data(
rgb, 0,
FALSE, 8, th_width, th_height,
367 th_width * 3 *
sizeof(uint8_t), NULL, NULL);
370 pixbuf = gdk_pixbuf_scale_simple(tmp, roundf((
float)
width / ratio),
height, GDK_INTERP_HYPER);
382 const gboolean use_internal_loader = !(file_type &
DT_IMAGE_RAW);
384 if(use_internal_loader)
397 const size_t pixels = (size_t)mipbuf.
width * mipbuf.
height;
401 const float *
const in = (
const float *
const)mipbuf.
buf;
403 for(
size_t k = 0;
k < pixels;
k++)
405 const float alpha = in[
k * 4 + 3] > 0.0f ?
CLAMPF(in[
k * 4 + 3], 0.0f, 1.0f) : 1.0f;
406 rgb[
k * 3] = CLAMP((
int)roundf((
CLAMPF(in[
k * 4], 0.0f, 1.0f) * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
407 rgb[
k * 3 + 1] = CLAMP((
int)roundf((
CLAMPF(in[
k * 4 + 1], 0.0f, 1.0f) * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
408 rgb[
k * 3 + 2] = CLAMP((
int)roundf((
CLAMPF(in[
k * 4 + 2], 0.0f, 1.0f) * alpha + (1.0f - alpha)) * 255.0f), 0, 255);
412 mipbuf.
width * 3 *
sizeof(uint8_t), NULL, NULL);
415 const float ratio = (float)mipbuf.
height / (
float)mipbuf.
width;
416 pixbuf = gdk_pixbuf_scale_simple(tmp, roundf((
float)
width / ratio),
height, GDK_INTERP_HYPER);
425 cache_entry.
data = NULL;
431 pixbuf = gdk_pixbuf_new_from_file_at_size(filename,
width,
height, NULL);
436 GdkPixbuf *tmp = pixbuf;
438 tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
440 tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
442 tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
444 if(pixbuf != tmp) g_object_unref(pixbuf);
459 else if(strstr(basedir,
"$(") != NULL)
491 GtkAllocation allocation;
492 gtk_widget_get_allocation(widget, &allocation);
499 gchar *text = g_strdup_printf(
"*.%s",
extension);
500 gchar *TEXT = g_utf8_strup(text, -1);
501 gtk_file_filter_add_pattern(filter, text);
502 gtk_file_filter_add_pattern(filter, TEXT);
513 GtkFileFilter *filter;
515 const char *raster[] = {
516 "jpg",
"jpeg",
"j2c",
"jp2",
"tif",
"tiff",
"png",
"exr",
517 "bmp",
"dng",
"heif",
"heic",
"avi",
"avif",
"webp", NULL };
519 const char *raw[] = {
520 "3fr",
"ari",
"arw",
"bay",
"bmq",
"cap",
"cine",
"cr2",
521 "cr3",
"crw",
"cs1",
"dc2",
"dcr",
"dng",
"gpr",
"erf",
522 "fff",
"hdr",
"ia",
"iiq",
"k25",
"kc2",
"kdc",
"mdc",
523 "mef",
"mos",
"mrw",
"nef",
"nrw",
"orf",
"ori",
"pef",
524 "pfm",
"pnm",
"pxn",
"qtk",
"raf",
"raw",
"rdc",
"rw2",
525 "rwl",
"sr2",
"srf",
"srw",
"sti",
"x3f", NULL };
528 filter = gtk_file_filter_new();
529 gtk_file_filter_set_name(filter, _(
"All image files"));
534 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
537 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(file_chooser), filter);
540 filter = gtk_file_filter_new();
541 gtk_file_filter_set_name(filter, _(
"Raw image files"));
543 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
546 filter = gtk_file_filter_new();
547 gtk_file_filter_set_name(filter, _(
"Raster image files"));
550 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
554 const char *label,
const GtkAlign align,
const gboolean fixed_width,
555 const gboolean full_width)
559 gtk_label_set_max_width_chars(GTK_LABEL(w), 25);
561 gtk_label_set_ellipsize(GTK_LABEL(w), PANGO_ELLIPSIZE_END);
562 gtk_grid_attach(GTK_GRID(grid), w, column,
row, full_width ? 2 : 1, 1);
563 gtk_label_set_xalign(GTK_LABEL(w), align);
564 gtk_widget_set_halign(w, align);
565 gtk_label_set_line_wrap(GTK_LABEL(w),
TRUE);
571 GtkWidget *w = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
572 gtk_grid_attach(GTK_GRID(grid), w, 0,
row, length, 1);
586 GError *
error = NULL;
587 GFileInfo *info = g_file_query_info(file,
588 G_FILE_ATTRIBUTE_STANDARD_NAME
","
589 G_FILE_ATTRIBUTE_TIME_MODIFIED,
590 G_FILE_QUERY_INFO_NONE, NULL, &
error);
597 const guint64 datetime = g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
601 g_object_unref(info);
613 if(
d->closing)
return;
614 gchar *uri = gtk_file_chooser_get_preview_uri(file_chooser);
617 gtk_file_chooser_set_preview_widget_active(file_chooser,
FALSE);
621 GVfs *vfs = g_vfs_get_default();
622 GFile *in = g_vfs_get_file_for_uri(vfs, (
const char *)uri);
623 char *filename = g_file_get_path(in);
625 gboolean have_file = (!
IS_NULL_PTR(filename)) && g_file_test(filename, G_FILE_TEST_IS_REGULAR);
626 gtk_file_chooser_set_preview_widget_active(file_chooser, have_file);
632 const char *
const extension = g_strrstr(filename,
".");
636 d->path_file = g_strdup(filename);
659 gtk_image_set_from_pixbuf(GTK_IMAGE(
d->preview), pixbuf);
660 if(pixbuf) g_object_unref(pixbuf);
663 gtk_widget_show_all(
d->preview);
678 gchar *basename = g_file_get_basename(in);
682 const gboolean is_in_lib = (is_path_in_lib > -1) || (is_metadata_in_lib > -1);
688 if(is_path_in_lib > -1)
689 imgid = is_path_in_lib;
690 else if(is_metadata_in_lib > -1)
691 imgid = is_metadata_in_lib;
693 char path[512] = { 0 };
710 gchar *exposure_field = g_strdup_printf(
"%.0f ISO - f/%.1f - %s", img->
exif_iso, img->
exif_aperture, exposure);
730 gchar *path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(file_chooser));
738 gtk_label_set_markup(
739 GTK_LABEL(
d->help_string),
740 _(
"<i>The files will be copied to the selected destination. You can rename them in batch below:</i>"));
742 gtk_label_set_markup(
743 GTK_LABEL(
d->help_string),
744 _(
"<i>The files will stay at their original location</i>"));
755 gtk_label_set_text(GTK_LABEL(
d->test_path), _(
"No copy."));
760 const char *date = gtk_entry_get_text(GTK_ENTRY(
d->datetime));
761 GList *file = g_list_prepend(NULL, g_strdup(
d->path_file));
771 gtk_label_set_text(GTK_LABEL(
d->test_path), _(
"Choose a file to see the result..."));
781 .base_folder = basedir,
789 gboolean free_after =
FALSE;
806 gchar * cut = g_strdup(g_strrstr(basedir, G_DIR_SEPARATOR_S));
807 gchar *fake_path = g_strdup(g_strrstr(_path, cut));
814 if(fake_path && fake_path[0] != 0)
817 gtk_label_set_text(GTK_LABEL(
d->test_path), _(
"Can't build a valid path."));
841 _gtk_label_set_and_free(
d->selected_files, g_strdup_printf(_(
"Detection in progress... (%i files found so far)"), elements));
847 if(
d->closing)
return;
848 gtk_label_set_text(GTK_LABEL(
d->selected_files), _(
"Detecting candidate files for import..."));
852 if(
d->selection_scan_timeout_id > 0) g_source_remove(
d->selection_scan_timeout_id);
871 if(
d->closing)
return G_SOURCE_REMOVE;
873 return G_SOURCE_REMOVE;
878 gboolean
state = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
880 gtk_widget_set_visible(GTK_WIDGET(
d->grid),
state);
881 gtk_widget_set_visible(GTK_WIDGET(
d->test_path),
state);
894 dt_conf_set_string(
"session/base_directory_pattern", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(self)));
900 dt_conf_set_string(
"session/sub_directory_pattern", gtk_entry_get_text(GTK_ENTRY(widget)));
906 dt_conf_set_string(
"session/filename_pattern", gtk_entry_get_text(GTK_ENTRY(widget)));
912 guint year, month,
day;
913 gtk_calendar_get_date(calendar, &year, &month, &
day);
914 GTimeZone *tz = g_time_zone_new_local();
917 GDateTime *datetime = g_date_time_new(tz, year, month + 1,
day, 0, 0, 0.);
918 g_time_zone_unref(tz);
919 gchar *date = g_date_time_format(datetime,
"%F");
920 gtk_entry_set_text(GTK_ENTRY(entry), date);
922 g_date_time_unref(datetime);
928 const char *date = gtk_entry_get_text(entry);
935 gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY,
"dialog-error");
936 gtk_entry_set_icon_tooltip_text(entry, GTK_ENTRY_ICON_SECONDARY,
937 _(
"Date should follow the ISO 8601 format, like :\n"
940 "YYYY-MM-DD HH:mm:ss\n"
941 "YYYY-MM-DDTHH:mm:ss"));
946 gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY,
"");
947 gtk_entry_set_icon_tooltip_text(entry, GTK_ENTRY_ICON_SECONDARY,
"");
950 gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_PRIMARY, NULL);
958 if(g_file_test(gtk_file_chooser_get_filename(chooser), G_FILE_TEST_IS_REGULAR)
961 gtk_dialog_response(dialog, GTK_RESPONSE_ACCEPT);
975static void _process_file_list(gpointer instance, GList *files,
int elements, gboolean finished, gpointer user_data)
977 if(!finished)
return;
993 .elements = elements,
1018 case GTK_RESPONSE_ACCEPT:
1020 if(
d->selection_scan_timeout_id > 0)
1022 g_source_remove(
d->selection_scan_timeout_id);
1023 d->selection_scan_timeout_id = 0;
1038 case GTK_RESPONSE_CANCEL:
1051 d->dialog = gtk_dialog_new_with_buttons
1052 ( _(
"Ansel - Open pictures"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
1053 _(
"Cancel"), GTK_RESPONSE_CANCEL,
1054 _(
"Import"), GTK_RESPONSE_ACCEPT,
1058#ifdef GDK_WINDOWING_QUARTZ
1065 gtk_window_set_position(GTK_WINDOW(
d->dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1068 gtk_window_set_default_size(GTK_WINDOW(
d->dialog),
1071 gtk_window_set_modal(GTK_WINDOW(
d->dialog),
FALSE);
1075 GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(
d->dialog));
1076 g_signal_connect(
d->dialog,
"check-resize", G_CALLBACK(
_resize_dialog), NULL);
1079 d->grid = gtk_grid_new();
1080 GtkGrid *grid = GTK_GRID(
d->grid);
1083 gtk_grid_set_column_homogeneous(grid,
FALSE);
1084 gtk_grid_set_row_homogeneous(grid,
FALSE);
1088 gtk_box_pack_start(GTK_BOX(content), rbox,
TRUE,
TRUE, 0);
1091 d->file_chooser = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN);
1092 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(
d->file_chooser),
TRUE);
1093 gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER(
d->file_chooser),
FALSE);
1094 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(
d->file_chooser),
1096 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(
d->file_chooser),
FALSE);
1097 gtk_box_pack_start(GTK_BOX(rbox),
d->file_chooser,
TRUE,
TRUE, 0);
1098 g_signal_connect(G_OBJECT(
d->file_chooser),
"current-folder-changed", G_CALLBACK(
_update_directory), NULL);
1099 g_signal_connect(G_OBJECT(
d->file_chooser),
"file-activated", G_CALLBACK(
_file_activated), GTK_DIALOG(
d->dialog));
1100 g_signal_connect(G_OBJECT(
d->file_chooser),
"selection-changed", G_CALLBACK(
_selection_changed),
d);
1101 g_signal_connect(G_OBJECT(
d->file_chooser),
"update-preview", G_CALLBACK(
update_preview_cb),
d);
1108 gtk_widget_set_halign(toolbox, GTK_ALIGN_END);
1110 GtkWidget *select_all = gtk_button_new_with_label(_(
"Select all"));
1111 gtk_box_pack_start(GTK_BOX(toolbox), select_all,
FALSE,
FALSE, 0);
1114 GtkWidget *select_none = gtk_button_new_with_label(_(
"Select none"));
1115 gtk_box_pack_start(GTK_BOX(toolbox), select_none,
FALSE,
FALSE, 0);
1118 GtkWidget *select_new = gtk_button_new_with_label(_(
"Select new"));
1119 gtk_box_pack_start(GTK_BOX(toolbox), select_new,
FALSE,
FALSE, 0);
1121 gtk_widget_set_tooltip_text(select_new,
1122 _(
"Selecting new files targets pictures that have never been added to the library. "
1123 "The lookup is done by searching for the original filename and date/time. "
1124 "It can detect files existing at another path, under a different name. "
1125 "False-positive can arise if two pictures have been taken at the same time with the same name."));
1127 d->selected_files = gtk_label_new(
"");
1128 gtk_box_pack_start(GTK_BOX(toolbox),
d->selected_files,
FALSE,
FALSE, 0);
1130 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(
d->file_chooser), toolbox);
1136 d->preview = gtk_image_new();
1138 gtk_box_pack_start(GTK_BOX(preview_box),
d->preview,
TRUE,
FALSE, 0);
1141 d->exif = gtk_grid_new();
1153 GtkWidget *imported_label = gtk_label_new(_(
"Imported:"));
1156 _(
"Images already in the library will not be imported again, selected or not. "
1157 "Remove them from the library first, or use the menu "
1158 "`Run \342\206\222 Resynchronize library and XMP` to update the local database from distant XMP.\n\n"
1159 "Ansel indexes images by their filename and parent folder (full path), "
1160 "not by their content. Therefore, renaming or moving images on the filesystem, "
1161 "or changing the mounting point of their external drive will make them "
1162 "look like new (unknown) images.\n\n"
1163 "If an XMP file is present alongside images, it will be imported as well, "
1164 "including the metadata and settings stored in it. If it is not what you want, "
1165 "you can reset metadata in the lighttable."));
1166 gtk_widget_set_halign(imported_label, GTK_ALIGN_END);
1167 gtk_grid_attach(GTK_GRID(
d->exif), GTK_WIDGET(help_box_inlib), 0,
EXIF_INLIB_FIELD, 1, 1);
1178 gtk_label_set_ellipsize(GTK_LABEL(
d->exif_info[
EXIF_PATH_FIELD]), PANGO_ELLIPSIZE_MIDDLE);
1180 gtk_box_pack_start(GTK_BOX(preview_box),
d->exif,
TRUE,
TRUE, 0);
1181 gtk_widget_show_all(
d->exif);
1183 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(
d->file_chooser), preview_box);
1187 GtkWidget *file_handling = gtk_label_new(
"");
1188 gtk_label_set_markup(GTK_LABEL(file_handling), _(
"<b>File handling</b>"));
1189 gtk_box_pack_start(GTK_BOX(files), GTK_WIDGET(file_handling),
FALSE,
FALSE, 0);
1192 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(
copy), NULL, _(
"Add to library"));
1193 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(
copy), NULL, _(
"Copy to disk"));
1195 gtk_box_pack_start(GTK_BOX(files), GTK_WIDGET(
copy),
FALSE,
FALSE, 0);
1198 d->help_string = gtk_label_new(
"");
1200 gtk_box_pack_start(GTK_BOX(files), GTK_WIDGET(
d->help_string),
FALSE,
FALSE, 0);
1202 gtk_box_pack_start(GTK_BOX(rbox), GTK_WIDGET(files),
FALSE,
FALSE, 0);
1205 GtkWidget *calendar_label = gtk_label_new(_(
"Project date"));
1206 gtk_widget_set_halign(calendar_label, GTK_ALIGN_START);
1207 d->datetime = gtk_entry_new();
1209 gtk_entry_set_width_chars(GTK_ENTRY(
d->datetime), 20);
1213 GDateTime *now = g_date_time_new_now_local();
1214 gchar *now_string = g_date_time_format(now,
"%F");
1215 gtk_entry_set_text(GTK_ENTRY(
d->datetime), now_string);
1219 GtkWidget *calendar = gtk_calendar_new();
1221 gtk_calendar_select_month(GTK_CALENDAR(calendar), g_date_time_get_month(now) - 1, g_date_time_get_year(now));
1222 const guint
day = g_date_time_get_day_of_month(now);
1223 gtk_calendar_select_day(GTK_CALENDAR(calendar),
day);
1224 gtk_calendar_mark_day(GTK_CALENDAR(calendar),
day);
1225 GtkBox *box_calendar =
attach_popover(
d->datetime,
"appointment-new", calendar);
1226 g_signal_connect(G_OBJECT(calendar),
"day-selected", G_CALLBACK(
_update_date),
d->datetime);
1229 g_date_time_unref(now);
1235 gtk_widget_set_hexpand(jobcode,
TRUE);
1236 g_signal_connect(G_OBJECT(jobcode),
"changed", G_CALLBACK(
_jobcode_changed),
d);
1238 GtkWidget *jobcode_label = gtk_label_new(_(
"Jobcode"));
1239 gtk_widget_set_halign(jobcode_label, GTK_ALIGN_START);
1241 GtkWidget *base_label = gtk_label_new(_(
"Base directory of all projects"));
1242 gtk_widget_set_halign(base_label, GTK_ALIGN_START);
1244 GtkWidget *dir_label = gtk_label_new(_(
"Project directory naming pattern"));
1245 gtk_widget_set_halign(dir_label, GTK_ALIGN_START);
1247 GtkWidget *file_label = gtk_label_new(_(
"File naming pattern"));
1248 gtk_widget_set_halign(file_label, GTK_ALIGN_START);
1251 = gtk_file_chooser_button_new(_(
"Select a base directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
1252 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(base_dir),
1255 gtk_widget_set_hexpand(base_dir,
TRUE);
1257 GtkWidget *sep1 = gtk_label_new(G_DIR_SEPARATOR_S);
1258 GtkWidget *sep2 = gtk_label_new(G_DIR_SEPARATOR_S);
1260 GtkWidget *project_dir = gtk_entry_new();
1263 gtk_widget_set_hexpand(project_dir,
TRUE);
1265 gtk_widget_set_tooltip_text(project_dir, _(
"Start typing `$(` to see available variables through auto-completion"));
1271 gtk_widget_set_hexpand(file,
TRUE);
1275 GtkWidget *pattern_label = gtk_label_new(_(
"Pattern result"));
1276 gtk_widget_set_halign(pattern_label, GTK_ALIGN_START);
1278 d->test_path = gtk_label_new(_(
"Choose a file to see the result..."));
1279 gtk_widget_set_halign(
d->test_path, GTK_ALIGN_START);
1280 gtk_label_set_line_wrap(GTK_LABEL(
d->test_path),
TRUE);
1281 gtk_label_set_max_width_chars(GTK_LABEL(
d->test_path), 60);
1290 gtk_grid_attach(grid, calendar_label, 0,
row, 1, 1);
1291 gtk_grid_attach(grid, jobcode_label, 2,
row, 1, 1);
1292 gtk_grid_attach(grid, pattern_label, 4,
row, 1, 1);
1296 gtk_grid_attach(grid, GTK_WIDGET(box_calendar), 0,
row, 1, 1);
1297 gtk_grid_attach(grid, jobcode, 2,
row, 1, 1);
1298 gtk_grid_attach(grid,
d->test_path, 4,
row, 1, 1);
1306 gtk_grid_attach(grid, base_label, 0,
row, 1, 1);
1307 gtk_grid_attach(grid, dir_label, 2,
row, 1, 1);
1308 gtk_grid_attach(grid, file_label, 4,
row, 1, 1);
1312 gtk_grid_attach(grid, base_dir, 0,
row, 1, 1);
1313 gtk_grid_attach(grid, sep1, 1,
row, 1, 1);
1314 gtk_grid_attach(grid, project_dir, 2,
row, 1, 1);
1315 gtk_grid_attach(grid, sep2, 3,
row, 1, 1);
1316 gtk_grid_attach(grid, file, 4,
row, 1, 1);
1319 gtk_box_pack_start(GTK_BOX(rbox), GTK_WIDGET(grid),
FALSE,
FALSE, 0);
1321 gtk_widget_show_all(
d->dialog);
1324 gtk_widget_set_visible(GTK_WIDGET(grid),
dt_conf_get_bool(
"ui_last/import_copy"));
1333 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(
d->file_chooser));
1338 gtk_file_chooser_select_all(GTK_FILE_CHOOSER(
d->file_chooser));
1347 GtkFileChooser *chooser = GTK_FILE_CHOOSER(
d->file_chooser);
1348 gchar *folder = gtk_file_chooser_get_current_folder(chooser);
1351 GFile *folder_file = g_file_new_for_path(folder);
1352 GFileEnumerator *files = NULL;
1356 files = g_file_enumerate_children(
1357 folder_file, G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_TYPE,
1358 G_FILE_QUERY_INFO_NONE, NULL, NULL);
1359 g_object_unref(folder_file);
1364 GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser);
1369 const GtkFileFilterFlags filter_needed = gtk_file_filter_get_needed(filter);
1372 while(g_file_enumerator_iterate(files, NULL, &file, NULL, NULL))
1378 gchar *parse_name = g_file_get_parse_name(file);
1379 gchar *uri = g_file_get_uri(file);
1380 gchar *basename = g_file_get_basename(file);
1381 gchar *filepath = g_file_get_path(file);
1382 GtkFileFilterInfo filter_info = { filter_needed,
1387 const gboolean is_regular = !
IS_NULL_PTR(filepath) && g_file_test(filepath, G_FILE_TEST_IS_REGULAR);
1390 const gboolean is_in_lib = (is_path_in_lib > -1) || (is_metadata_in_lib > -1);
1394 if(gtk_file_filter_filter(filter, &filter_info)
1395 && !(is_regular && !is_in_lib))
1397 gtk_file_chooser_unselect_file(chooser, file);
1418 if(
d->selection_scan_timeout_id > 0)
1420 g_source_remove(
d->selection_scan_timeout_id);
1421 d->selection_scan_timeout_id = 0;
1427 g_signal_handlers_disconnect_by_func(G_OBJECT(
d->file_chooser), G_CALLBACK(
_selection_changed),
d);
1428 g_signal_handlers_disconnect_by_func(G_OBJECT(
d->file_chooser), G_CALLBACK(
update_preview_cb),
d);
1429 g_signal_handlers_disconnect_by_func(G_OBJECT(
d->file_chooser), G_CALLBACK(
_file_activated), GTK_DIALOG(
d->dialog));
1430 g_signal_handlers_disconnect_by_func(G_OBJECT(
d->file_chooser), G_CALLBACK(
_update_directory), NULL);
1437 gtk_widget_destroy(
d->dialog);
1439 d->file_chooser = NULL;
1444 d->help_string = NULL;
1445 d->test_path = NULL;
1446 d->selected_files = NULL;
1455 d->selection_scan_timeout_id = 0;
1457 d->path_file = NULL;
1460 d->scan_state->generation = 0;
1461 d->scan_state->refcount = 1;
1462 d->scan_state->closing =
FALSE;
1476 gboolean release =
FALSE;
1478 d->scan_state->closing =
TRUE;
1479 d->scan_state->generation++;
1480 if(
d->scan_state->refcount > 0)
d->scan_state->refcount--;
1481 release = (
d->scan_state->refcount == 0);
1488 d->scan_state = NULL;
1504 dt_import_t *
import = g_malloc(sizeof(dt_import_t));
1506 import->files = NULL;
1507 import->elements = 0;
1509 import->scan_state =
d->scan_state;
1511 import->scan_state->refcount++;
1517 import->selection = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(
d->file_chooser));
1530 import->files = NULL;
1532 import->selection = NULL;
1535 gboolean release =
FALSE;
1537 if(import->scan_state->refcount > 0)
import->scan_state->refcount--;
1538 release = (
import->scan_state->refcount == 0);
1545 import->scan_state = NULL;
static void error(char *msg)
const char * extension(dt_imageio_module_data_t *data)
dt_colorspaces_color_profile_type_t
static dt_aligned_pixel_t rgb
int32_t dt_image_get_id(int32_t film_id, const gchar *filename)
gboolean dt_image_is_hdr(const dt_image_t *img)
void dt_image_init(dt_image_t *img)
void dt_image_film_roll_directory(const dt_image_t *img, char *pathname, size_t pathname_len)
void dt_conf_set_bool(const char *name, int val)
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)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_control_log(const char *msg,...)
gboolean dt_supported_image(const gchar *filename)
check if file is a supported image
#define dt_free_align(ptr)
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
static void dt_free_gpointer(gpointer ptr)
#define dt_pixelpipe_cache_free_align(mem)
#define __OMP_PARALLEL_FOR__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
GDateTime * dt_string_to_datetime(const char *string)
gboolean dt_datetime_img_to_local(char *local, const size_t local_size, const dt_image_t *img, const gboolean msec)
gboolean dt_datetime_unix_to_exif(char *exif, const size_t exif_size, const time_t *unix)
gboolean dt_datetime_entry_to_exif(char *exif, const size_t exif_size, const char *entry)
#define DT_DATETIME_LENGTH
#define DT_DATETIME_EXIF_LENGTH
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
int dt_exif_read(dt_image_t *img, const char *path)
gchar * dt_loc_get_home_dir(const gchar *user)
int32_t dt_film_get_id(const char *folder)
GtkBox * attach_help_popover(GtkWidget *widget, const char *label)
void dt_gui_refocus_center()
GtkBox * attach_popover(GtkWidget *widget, const char *icon, GtkWidget *content)
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnects accels when a text or search entry gets the focus, and reconnects them when it looses it....
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
void dt_gtkentry_setup_completion(GtkEntry *entry, const dt_gtkentry_completion_spec *compl_list, const char *trigger_char)
const dt_gtkentry_completion_spec * dt_gtkentry_get_default_path_compl_list()
@ ORIENTATION_ROTATE_CCW_90_DEG
@ ORIENTATION_ROTATE_CW_90_DEG
@ ORIENTATION_ROTATE_180_DEG
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)
dt_imageio_retval_t dt_imageio_open(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
dt_image_flags_t dt_imageio_get_type_from_extension(const char *extension)
Map Exiv2 preview MIME types to decoder format identifiers.
int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *th_width, int32_t *th_height, dt_colorspaces_color_profile_type_t *color_space, const int width, const int height)
Load the thumbnail embedded into a RAW file having at least the size MAX(width, height) x MAX(width,...
static void _resize_dialog(GtkWidget *widget)
static void _process_file_list(gpointer instance, GList *files, int elements, gboolean finished, gpointer user_data)
Import a list of file by copying them or not, and adding them to database.
static void dt_import_cleanup(void *import)
static void _datetime_changed_callback(GtkEntry *entry, dt_lib_import_t *d)
static void _do_select_all_clicked(GtkWidget *widget, dt_lib_import_t *d)
static int32_t _get_selected_files_job(dt_job_t *job)
static void _update_date(GtkCalendar *calendar, GtkWidget *entry)
void dt_control_get_selected_files(dt_lib_import_t *d, gboolean destroy_window)
static void _filename_changed(GtkWidget *widget, dt_lib_import_t *d)
static void _selection_changed(GtkWidget *filechooser, dt_lib_import_t *d)
static int _is_in_library_by_path(const gchar *folder, const char *filename)
static void gui_cleanup(dt_lib_import_t *d)
static dt_import_t * dt_import_init(dt_lib_import_t *d, const uint32_t generation)
static void _filelist_changed_callback(gpointer instance, GList *files, guint elements, guint finished, gpointer user_data)
static void _gtk_label_set_and_free(GtkWidget *widget, gchar *label)
static void _jobcode_changed(GtkFileChooserButton *widget, dt_lib_import_t *d)
static void _copy_toggled_callback(GtkWidget *combobox, dt_lib_import_t *d)
static gboolean _scan_still_valid(dt_import_t *const import)
static void _file_activated(GtkFileChooser *chooser, GtkDialog *dialog)
static void _set_test_path(dt_lib_import_t *d, dt_image_t *img)
static void _do_select_none_clicked(GtkWidget *widget, dt_lib_import_t *d)
static void _file_filters(GtkWidget *file_chooser)
static void _do_select_new_clicked(GtkWidget *widget, dt_lib_import_t *d)
static GdkPixbuf * _import_get_thumbnail(const gchar *filename, const int width, const int height, const gboolean valid_exif, dt_image_t *img)
static void _do_select_new(dt_lib_import_t *d)
static void _base_dir_changed(GtkFileChooserButton *self, dt_lib_import_t *d)
static void _cleanup(dt_lib_import_t *d)
static dt_lib_import_t * _init()
static GtkWidget * _attach_aligned_grid_item(GtkWidget *grid, const int row, const int column, const char *label, const GtkAlign align, const gboolean fixed_width, const gboolean full_width)
static int _is_in_library_by_metadata(GFile *file)
static void gui_init(dt_lib_import_t *d)
static void _project_dir_changed(GtkWidget *widget, dt_lib_import_t *d)
static void _build_filter(GtkFileFilter *filter, const gchar *extension)
static int32_t dt_get_selected_files(dt_import_t *import)
static void _do_select_all(dt_lib_import_t *d)
static void _filter_document(GVfs *vfs, GFile *document, dt_import_t *import)
void _file_chooser_response(GtkDialog *dialog, gint response_id, dt_lib_import_t *d)
static void _update_directory(GtkWidget *file_chooser, dt_lib_import_t *d)
static gboolean _selection_changed_scan_trigger(gpointer user_data)
Trigger recursive import candidate detection after selection settle time.
static void update_preview_cb(GtkFileChooser *file_chooser, gpointer userdata)
static void _exif_text_set_and_free(dt_lib_import_t *d, exif_fields_t field, gchar *label)
static void _recurse_selection(GSList *selection, dt_import_t *const import)
static void _do_select_none(dt_lib_import_t *d)
static void _recurse_folder(GVfs *vfs, GFile *folder, dt_import_t *const import)
static GtkWidget * _attach_grid_separator(GtkWidget *grid, const int row, const int length)
static void _set_help_string(dt_lib_import_t *d, gboolean copy)
gchar * dt_build_filename_from_pattern(const char *const filename, const int index, dt_image_t *img, dt_control_import_t *data)
Build a full path for a given image file, given a pattern.
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.
void dt_control_import_data_free(dt_control_import_t *data)
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)
void dt_control_job_dispose(_dt_job_t *job)
float *const restrict const size_t k
#define CLAMPF(a, mn, mx)
dt_colorspaces_color_profile_type_t color_space
void dt_osx_disallow_fullscreen(GtkWidget *widget)
void copy(double *dest, double *source, size_t num_el)
Copy a flat buffer.
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_FILELIST_CHANGED
Raised when the recursive file crawler returns. no params, return :
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
char * dt_variables_expand(dt_variables_params_t *params, gchar *source, gboolean iterate)
void dt_variables_params_destroy(dt_variables_params_t *params)
gboolean dt_get_user_pictures_dir(const gchar *homedir, gchar *picdir, size_t picdir_size)
Gets the path to the current OS pictures directory.
void dt_variables_params_init(dt_variables_params_t **params)
const float uint32_t state[4]
static const char *const day[7]
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_image_cache_t * image_cache
struct dt_control_t * control
char * target_file_pattern
char * target_subfolder_pattern
dt_image_orientation_t orientation
dt_import_scan_state_t * scan_state
GtkWidget * selected_files
dt_import_scan_state_t * scan_state
guint selection_scan_timeout_id
GtkWidget * exif_info[EXIF_LAST_FIELD]
dt_cache_entry_t * cache_entry
gchar * dt_util_path_get_dirname(const gchar *filename)
char * dt_util_format_exposure(const float exposuretime)