69#ifdef GDK_WINDOWING_QUARTZ
105 return _(
"Static HTML gallery");
109 const size_t old_params_size,
const int old_version,
const int new_version,
112 if(old_version == 1 && new_version == 2)
114 typedef struct dt_imageio_gallery_v1_t
118 char cached_dirname[1024];
121 } dt_imageio_gallery_v1_t;
124 dt_imageio_gallery_v1_t *o = (dt_imageio_gallery_v1_t *)old_params;
126 g_strlcpy(
n->filename, o->filename,
sizeof(
n->filename));
127 g_strlcpy(
n->title, o->title,
sizeof(
n->title));
128 g_strlcpy(
n->cached_dirname, o->cached_dirname,
sizeof(
n->cached_dirname));
130 *new_size = self->params_size(self);
140 GtkFileChooserNative *filechooser = gtk_file_chooser_native_new(
141 _(
"select directory"), GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
142 _(
"_select as output destination"), _(
"_cancel"));
144 gchar *old = g_strdup(gtk_entry_get_text(
d->entry));
145 char *c = g_strstr_len(old, -1,
"$");
147 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filechooser), old);
149 if(gtk_native_dialog_run(GTK_NATIVE_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
151 gchar *dir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
152 char *composed = g_build_filename(dir,
"$(FILE_NAME)", NULL);
159 gtk_entry_set_text(GTK_ENTRY(
d->entry), escaped);
164 g_object_unref(filechooser);
169 dt_conf_set_string(
"plugins/imageio/storage/gallery/file_directory", gtk_entry_get_text(entry));
174 dt_conf_set_string(
"plugins/imageio/storage/gallery/title", gtk_entry_get_text(entry));
186 widget = gtk_entry_new();
188 gtk_entry_set_width_chars(GTK_ENTRY(widget), 0);
189 gtk_box_pack_start(GTK_BOX(hbox), widget,
TRUE,
TRUE, 0);
193 gtk_entry_set_text(GTK_ENTRY(widget), dir);
195 d->entry = GTK_ENTRY(widget);
199 gtk_widget_set_tooltip_text(widget,
200 _(
"enter the path where to put exported images\nvariables support bash like string manipulation\n"
201 "type '$(' to activate the completion and see the list of variables"));
205 gtk_widget_set_tooltip_text(widget, _(
"select directory"));
206 gtk_box_pack_start(GTK_BOX(hbox), widget,
FALSE,
FALSE, 0);
207 g_signal_connect(G_OBJECT(widget),
"clicked", G_CALLBACK(
button_clicked), self);
212 d->title_entry = GTK_ENTRY(gtk_entry_new());
214 gtk_entry_set_width_chars(
d->title_entry, 0);
215 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(
d->title_entry),
TRUE,
TRUE, 0);
216 gtk_widget_set_tooltip_text(GTK_WIDGET(
d->title_entry), _(
"enter the title of the website"));
220 gtk_entry_set_text(GTK_ENTRY(
d->title_entry), dir);
235 dt_conf_set_string(
"plugins/imageio/storage/gallery/file_directory", gtk_entry_get_text(
d->entry));
236 dt_conf_set_string(
"plugins/imageio/storage/gallery/title", gtk_entry_get_text(
d->title_entry));
241 return a->
pos - b->pos;
246 const gboolean high_quality,
const gboolean export_masks,
254 gboolean from_cache =
FALSE;
262 d->vp->filename = dirname;
263 d->vp->jobcode =
"export";
264 d->vp->imgid = imgid;
265 d->vp->sequence = num;
268 g_strlcpy(tmp_dir, result_tmp_dir,
sizeof(tmp_dir));
272 if(g_file_test(tmp_dir, G_FILE_TEST_IS_DIR)
273 || ((
d->filename + strlen(
d->filename) - 1)[0] ==
'/'
274 || (
d->filename + strlen(
d->filename) - 1)[0] ==
'\\'))
275 snprintf(
d->filename + strlen(
d->filename),
sizeof(
d->filename) - strlen(
d->filename),
"/$(FILE_NAME)");
278 if(total > 1 && !g_strrstr(
d->filename,
"$"))
280 snprintf(
d->filename + strlen(
d->filename),
sizeof(
d->filename) - strlen(
d->filename),
"_$(SEQUENCE)");
284 g_strlcpy(
d->filename, fixed_path,
sizeof(
d->filename));
288 g_strlcpy(filename, result_filename,
sizeof(filename));
291 g_strlcpy(dirname, filename,
sizeof(dirname));
293 const char *ext = format->extension(fdata);
294 char *c = dirname + strlen(dirname);
295 for(; c > dirname && *c !=
'/'; c--)
297 if(*c ==
'/') *c =
'\0';
298 if(g_mkdir_with_parents(dirname, 0755))
300 fprintf(stderr,
"[imageio_storage_gallery] could not create directory: `%s'!\n", dirname);
306 g_strlcpy(
d->cached_dirname, dirname,
sizeof(
d->cached_dirname));
308 c = filename + strlen(filename);
309 for(; c > filename && *c !=
'.' && *c !=
'/'; c--)
311 if(c <= filename || *c ==
'/') c = filename + strlen(filename);
313 sprintf(c,
".%s", ext);
319 GList *res_title = NULL, *res_desc = NULL;
326 title = res_title->data;
337 c = filename + strlen(filename);
338 for(; c > filename && *c !=
'/'; c--)
341 if(c <= filename) c = filename;
342 g_strlcpy(relfilename, c,
sizeof(relfilename));
343 g_strlcpy(relthumbfilename, relfilename,
sizeof(relthumbfilename));
344 c = relthumbfilename + strlen(relthumbfilename);
345 for(; c > relthumbfilename && *c !=
'.'; c--)
347 if(c <= relthumbfilename) c = relthumbfilename + strlen(relthumbfilename);
348 sprintf(c,
"-thumb.%s", ext);
351 g_strlcpy(subfilename,
d->cached_dirname,
sizeof(subfilename));
352 char *sc = subfilename + strlen(subfilename);
353 sprintf(sc,
"/img_%d.html", num);
354 snprintf(relsubfilename,
sizeof(relsubfilename),
"img_%d.html", num);
358 gchar *esc_relfilename = g_strescape(relfilename, NULL);
359 gchar *esc_relthumbfilename = g_strescape(relthumbfilename, NULL);
361 snprintf(
pair->line,
sizeof(
pair->line),
363 " <div><div class=\"dia\">\n"
364 " <img src=\"%s\" alt=\"img%d\" class=\"img\" onclick=\"openSwipe(%d)\"/></div>\n"
367 esc_relthumbfilename,
384 icc_filename, icc_intent, self, sdata, num, total, metadata) != 0)
386 fprintf(stderr,
"[imageio_storage_gallery] could not export to file: `%s'!\n", filename);
394 snprintf(
pair->item,
sizeof(
pair->item),
401 esc_relfilename, fdata->
width, fdata->
height, esc_relthumbfilename);
412 const int save_max_width = fdata->
max_width;
413 const int save_max_height = fdata->
max_height;
417 c = filename + strlen(filename);
418 for(; c > filename && *c !=
'.' && *c !=
'/'; c--)
420 if(c <= filename || *c ==
'/') c = filename + strlen(filename);
421 ext = format->extension(fdata);
422 sprintf(c,
"-thumb.%s", ext);
424 icc_intent, self, sdata, num, total, NULL) != 0)
426 fprintf(stderr,
"[imageio_storage_gallery] could not export to file: `%s'!\n", filename);
434 printf(
"[export_job] exported to `%s'\n", filename);
435 dt_control_log(ngettext(
"%d/%d exported to `%s'",
"%d/%d exported to `%s'", num),
436 num, total, filename);
444 g_strlcpy(filename,
d->cached_dirname,
sizeof(filename));
445 char *c = filename + strlen(filename);
448 sprintf(c,
"/style");
449 g_mkdir_with_parents(filename, 0755);
450 sprintf(c,
"/style/style.css");
452 sprintf(c,
"/style/favicon.ico");
456 sprintf(c,
"/pswp/default-skin/");
457 g_mkdir_with_parents(filename, 0755);
458 sprintf(c,
"/pswp/photoswipe.js");
460 sprintf(c,
"/pswp/photoswipe.min.js");
462 sprintf(c,
"/pswp/photoswipe-ui-default.js");
464 sprintf(c,
"/pswp/photoswipe.css");
466 sprintf(c,
"/pswp/photoswipe-ui-default.min.js");
468 sprintf(c,
"/pswp/default-skin/default-skin.css");
470 sprintf(c,
"/pswp/default-skin/default-skin.png");
472 sprintf(c,
"/pswp/default-skin/default-skin.svg");
474 sprintf(c,
"/pswp/default-skin/preloader.gif");
477 sprintf(c,
"/index.html");
479 const char *title =
d->title;
481 FILE *
f = g_fopen(filename,
"wb");
484 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
485 "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
486 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
488 " <meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n"
489 " <link rel=\"shortcut icon\" href=\"style/favicon.ico\" />\n"
490 " <link rel=\"stylesheet\" href=\"style/style.css\" type=\"text/css\" />\n"
491 " <link rel=\"stylesheet\" href=\"pswp/photoswipe.css\">\n"
492 " <link rel=\"stylesheet\" href=\"pswp/default-skin/default-skin.css\">\n"
493 " <script src=\"pswp/photoswipe.min.js\"></script>\n"
494 " <script src=\"pswp/photoswipe-ui-default.min.js\"></script>\n"
495 " <title>%s</title>\n"
498 " <div class=\"title\">%s</div>\n"
499 " <div class=\"page\">\n",
503 for(GList *tmp =
d->l; tmp; tmp = g_list_next(tmp))
506 fprintf(
f,
"%s",
p->line);
510 fprintf(
f,
" <p style=\"clear:both;\"></p>\n"
512 " <div class=\"footer\">\n"
513 " <script language=\"JavaScript\" type=\"text/javascript\">\n"
514 " document.write(\"download all: <em>curl -O# \" + document.documentURI.replace( /\\\\/g, '/' ).replace( /\\/[^\\/]*$/, '' ) + \"/img_[0000-%04zu].jpg</em>\")\n"
518 " <div class=\"pswp\" tabindex=\"-1\" role=\"dialog\" aria-hidden=\"true\">\n"
519 " <div class=\"pswp__bg\"></div>\n"
520 " <div class=\"pswp__scroll-wrap\">\n"
521 " <div class=\"pswp__container\">\n"
522 " <div class=\"pswp__item\"></div>\n"
523 " <div class=\"pswp__item\"></div>\n"
524 " <div class=\"pswp__item\"></div>\n"
526 " <div class=\"pswp__ui pswp__ui--hidden\">\n"
527 " <div class=\"pswp__top-bar\">\n"
528 " <div class=\"pswp__counter\"></div>\n"
529 " <button class=\"pswp__button pswp__button--close\" title=\"Close (Esc)\"></button>\n"
530 " <button class=\"pswp__button pswp__button--share\" title=\"Share\"></button>\n"
531 " <button class=\"pswp__button pswp__button--fs\" title=\"Toggle fullscreen\"></button>\n"
532 " <button class=\"pswp__button pswp__button--zoom\" title=\"Zoom in/out\"></button>\n"
533 " <div class=\"pswp__preloader\">\n"
534 " <div class=\"pswp__preloader__icn\">\n"
535 " <div class=\"pswp__preloader__cut\">\n"
536 " <div class=\"pswp__preloader__donut\"></div>\n"
541 " <div class=\"pswp__share-modal pswp__share-modal--hidden pswp__single-tap\">\n"
542 " <div class=\"pswp__share-tooltip\"></div>\n"
544 " <button class=\"pswp__button pswp__button--arrow--left\" title=\"Previous (arrow left)\">\n"
546 " <button class=\"pswp__button pswp__button--arrow--right\" title=\"Next (arrow right)\">\n"
548 " <div class=\"pswp__caption\">\n"
549 " <div class=\"pswp__caption__center\"></div>\n"
556 "var pswpElement = document.querySelectorAll('.pswp')[0];\n"
563 fprintf(
f,
"%s",
p->item);
565 d->l = g_list_delete_link(
d->l,
d->l);
568 "function openSwipe(img)\n"
570 " // define options (if needed)\n"
572 " // optionName: 'option value'\n"
573 " index: img // start at first slide\n"
575 " var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);\n"
600 g_strlcpy(
d->filename, text,
sizeof(
d->filename));
603 g_strlcpy(
d->title, text,
sizeof(
d->title));
618 if(
size != self->params_size(self))
return 1;
621 gtk_entry_set_text(GTK_ENTRY(
g->entry),
d->filename);
623 gtk_entry_set_text(GTK_ENTRY(
g->title_entry),
d->title);
630 const char *
mime = format->mime(NULL);
631 if(strcmp(
mime,
"image/jpeg") == 0)
633 if(strcmp(
mime,
"image/png") == 0)
635 if(strcmp(
mime,
"image/webp") == 0)
637 if (strcmp(
mime,
"image/avif") == 0)
return 1;
const char ** description(struct dt_iop_module_t *self)
const char * mime(dt_imageio_module_data_t *data)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
dt_colorspaces_color_profile_type_t
const dt_aligned_pixel_t f
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.
const char darktable_package_string[]
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
const char * dt_confgen_get(const char *name, dt_confgen_value_kind_t kind)
void dt_control_log(const char *msg,...)
#define DT_MODULE(MODVER)
static void dt_free_gpointer(gpointer ptr)
#define DT_MAX_PATH_FOR_PARAMS
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
void dtgtk_cairo_paint_directory(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void * get_params(dt_imageio_module_storage_t *self)
int supported(dt_imageio_module_storage_t *storage, dt_imageio_module_format_t *format)
static void title_changed_callback(GtkEntry *entry, gpointer user_data)
void gui_cleanup(dt_imageio_module_storage_t *self)
void free_params(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *params)
size_t params_size(dt_imageio_module_storage_t *self)
void gui_init(dt_imageio_module_storage_t *self)
void finalize_store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *dd)
void init(dt_imageio_module_storage_t *self)
void gui_reset(dt_imageio_module_storage_t *self)
void * legacy_params(dt_imageio_module_storage_t *self, const void *const old_params, const size_t old_params_size, const int old_version, const int new_version, size_t *new_size)
int set_params(dt_imageio_module_storage_t *self, const void *params, const int size)
static void button_clicked(GtkWidget *widget, dt_imageio_module_storage_t *self)
static void entry_changed_callback(GtkEntry *entry, gpointer user_data)
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int32_t imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_export_metadata_t *metadata)
static gint sort_pos(pair_t *a, pair_t *b)
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....
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
#define DT_GUI_BOX_SPACING
static GtkWidget * dt_ui_label_new(const gchar *str)
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()
int dt_imageio_export(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const gboolean high_quality, const gboolean copy_metadata, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata)
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)
void dt_variables_set_max_width_height(dt_variables_params_t *params, int max_width, int max_height)
void dt_variables_params_init(dt_variables_params_t **params)
struct dt_gui_gtk_t * gui
char filename[DT_MAX_PATH_FOR_PARAMS]
dt_variables_params_t * vp
char cached_dirname[DT_MAX_PATH_FOR_PARAMS]
GModule *GtkWidget * widget
gchar * dt_util_str_replace(const gchar *string, const gchar *pattern, const gchar *substitute)
void dt_copy_resource_file(const char *src, const char *dst)
gchar * dt_util_fix_path(const gchar *path)