1 /*
2 This file is part of darktable,
3 Copyright (C) 2010-2021 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "common/history.h"
20 #include "common/collection.h"
21 #include "common/darktable.h"
22 #include "common/debug.h"
23 #include "common/exif.h"
24 #include "common/history_snapshot.h"
25 #include "common/image_cache.h"
26 #include "common/imageio.h"
27 #include "common/mipmap_cache.h"
28 #include "common/tags.h"
29 #include "common/undo.h"
30 #include "common/utility.h"
31 #include "control/control.h"
32 #include "develop/blend.h"
33 #include "develop/develop.h"
34 #include "develop/masks.h"
35 #include "gui/hist_dialog.h"
36
37 #define DT_IOP_ORDER_INFO (darktable.unmuted & DT_DEBUG_IOPORDER)
38
dt_history_item_free(gpointer data)39 void dt_history_item_free(gpointer data)
40 {
41 dt_history_item_t *item = (dt_history_item_t *)data;
42 g_free(item->op);
43 g_free(item->name);
44 item->op = NULL;
45 item->name = NULL;
46 g_free(item);
47 }
48
_remove_preset_flag(const int imgid)49 static void _remove_preset_flag(const int imgid)
50 {
51 dt_image_t *image = dt_image_cache_get(darktable.image_cache, imgid, 'w');
52
53 // clear flag
54 image->flags &= ~DT_IMAGE_AUTO_PRESETS_APPLIED;
55
56 // write through to sql+xmp
57 dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE);
58 }
59
dt_history_delete_on_image_ext(int32_t imgid,gboolean undo)60 void dt_history_delete_on_image_ext(int32_t imgid, gboolean undo)
61 {
62 dt_undo_lt_history_t *hist = undo?dt_history_snapshot_item_init():NULL;
63
64 if(undo)
65 {
66 hist->imgid = imgid;
67 dt_history_snapshot_undo_create(hist->imgid, &hist->before, &hist->before_history_end);
68 }
69
70 dt_lock_image(imgid);
71
72 sqlite3_stmt *stmt;
73
74 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
75 "DELETE FROM main.history WHERE imgid = ?1",
76 -1, &stmt, NULL);
77 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
78 sqlite3_step(stmt);
79 sqlite3_finalize(stmt);
80
81 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
82 "DELETE FROM main.module_order WHERE imgid = ?1",
83 -1, &stmt, NULL);
84 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
85 sqlite3_step(stmt);
86 sqlite3_finalize(stmt);
87
88 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
89 "UPDATE main.images"
90 " SET history_end = 0, aspect_ratio = 0.0"
91 " WHERE id = ?1",
92 -1, &stmt, NULL);
93 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
94 sqlite3_step(stmt);
95 sqlite3_finalize(stmt);
96
97 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
98 "DELETE FROM main.masks_history WHERE imgid = ?1",
99 -1, &stmt, NULL);
100 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
101 sqlite3_step(stmt);
102 sqlite3_finalize(stmt);
103
104 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
105 "DELETE FROM main.history_hash WHERE imgid = ?1",
106 -1, &stmt, NULL);
107 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
108 sqlite3_step(stmt);
109 sqlite3_finalize(stmt);
110
111 _remove_preset_flag(imgid);
112
113 /* if current image in develop reload history */
114 if(dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items(darktable.develop);
115
116 /* make sure mipmaps are recomputed */
117 dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
118 dt_image_update_final_size(imgid);
119
120 /* remove darktable|style|* tags */
121 dt_tag_detach_by_string("darktable|style|%", imgid, FALSE, FALSE);
122 dt_tag_detach_by_string("darktable|changed", imgid, FALSE, FALSE);
123
124 /* unset change timestamp */
125 dt_image_cache_unset_change_timestamp(darktable.image_cache, imgid);
126
127 // signal that the mipmap need to be updated
128 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_DEVELOP_MIPMAP_UPDATED, imgid);
129
130 dt_unlock_image(imgid);
131
132 // update history hash
133 dt_history_hash_write_from_history(imgid, DT_HISTORY_HASH_CURRENT);
134
135 if(undo)
136 {
137 dt_history_snapshot_undo_create(hist->imgid, &hist->after, &hist->after_history_end);
138
139 dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
140 dt_undo_record(darktable.undo, NULL, DT_UNDO_LT_HISTORY, (dt_undo_data_t)hist,
141 dt_history_snapshot_undo_pop, dt_history_snapshot_undo_lt_history_data_free);
142 dt_undo_end_group(darktable.undo);
143 }
144 }
145
dt_history_delete_on_image(int32_t imgid)146 void dt_history_delete_on_image(int32_t imgid)
147 {
148 dt_history_delete_on_image_ext(imgid, TRUE);
149 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
150 }
151
dt_history_load_and_apply(const int imgid,gchar * filename,int history_only)152 int dt_history_load_and_apply(const int imgid, gchar *filename, int history_only)
153 {
154 dt_lock_image(imgid);
155 dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'w');
156 if(img)
157 {
158 dt_undo_lt_history_t *hist = dt_history_snapshot_item_init();
159 hist->imgid = imgid;
160 dt_history_snapshot_undo_create(hist->imgid, &hist->before, &hist->before_history_end);
161
162 if(dt_exif_xmp_read(img, filename, history_only))
163 {
164 dt_image_cache_write_release(darktable.image_cache, img,
165 // ugly but if not history_only => called from crawler - do not write the xmp
166 history_only ? DT_IMAGE_CACHE_SAFE : DT_IMAGE_CACHE_RELAXED);
167 dt_unlock_image(imgid);
168 return 1;
169 }
170 dt_history_snapshot_undo_create(hist->imgid, &hist->after, &hist->after_history_end);
171 dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
172 dt_undo_record(darktable.undo, NULL, DT_UNDO_LT_HISTORY, (dt_undo_data_t)hist,
173 dt_history_snapshot_undo_pop, dt_history_snapshot_undo_lt_history_data_free);
174 dt_undo_end_group(darktable.undo);
175
176 /* if current image in develop reload history */
177 if(dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items(darktable.develop);
178
179 dt_image_cache_write_release(darktable.image_cache, img,
180 // ugly but if not history_only => called from crawler - do not write the xmp
181 history_only ? DT_IMAGE_CACHE_SAFE : DT_IMAGE_CACHE_RELAXED);
182 dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
183 dt_image_update_final_size(imgid);
184 }
185 dt_unlock_image(imgid);
186 // signal that the mipmap need to be updated
187 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_DEVELOP_MIPMAP_UPDATED, imgid);
188 return 0;
189 }
190
dt_history_load_and_apply_on_list(gchar * filename,const GList * list)191 int dt_history_load_and_apply_on_list(gchar *filename, const GList *list)
192 {
193 int res = 0;
194 dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
195 for(GList *l = (GList *)list; l; l = g_list_next(l))
196 {
197 const int imgid = GPOINTER_TO_INT(l->data);
198 if(dt_history_load_and_apply(imgid, filename, 1)) res = 1;
199 }
200 dt_undo_end_group(darktable.undo);
201 return res;
202 }
203
204 // returns the first history item with hist->module == module
_search_history_by_module(dt_develop_t * dev,dt_iop_module_t * module)205 static dt_dev_history_item_t *_search_history_by_module(dt_develop_t *dev, dt_iop_module_t *module)
206 {
207 dt_dev_history_item_t *hist_mod = NULL;
208 for(GList *history = dev->history; history; history = g_list_next(history))
209 {
210 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data);
211
212 if(hist->module == module)
213 {
214 hist_mod = hist;
215 break;
216 }
217 }
218 return hist_mod;
219 }
220
221 // returns the first history item with corresponding module->op
_search_history_by_op(dt_develop_t * dev,dt_iop_module_t * module)222 static dt_dev_history_item_t *_search_history_by_op(dt_develop_t *dev, dt_iop_module_t *module)
223 {
224 dt_dev_history_item_t *hist_mod = NULL;
225 for(GList *history = dev->history; history; history = g_list_next(history))
226 {
227 dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data);
228
229 if(strcmp(hist->module->op, module->op) == 0)
230 {
231 hist_mod = hist;
232 break;
233 }
234 }
235 return hist_mod;
236 }
237
238 // returns the module on modules_list that is equal to module
239 // used to check if module exists on the list
_search_list_iop_by_module(GList * modules_list,dt_iop_module_t * module)240 static dt_iop_module_t *_search_list_iop_by_module(GList *modules_list, dt_iop_module_t *module)
241 {
242 dt_iop_module_t *mod_ret = NULL;
243 for(GList *modules = modules_list; modules; modules = g_list_next(modules))
244 {
245 dt_iop_module_t *mod = (dt_iop_module_t *)(modules->data);
246
247 if(mod == module)
248 {
249 mod_ret = mod;
250 break;
251 }
252 }
253 return mod_ret;
254 }
255
256 // fills used with formid, if it is a group it recurs and fill all sub-forms
_fill_used_forms(GList * forms_list,int formid,int * used,int nb)257 static void _fill_used_forms(GList *forms_list, int formid, int *used, int nb)
258 {
259 // first, we search for the formid in used table
260 for(int i = 0; i < nb; i++)
261 {
262 if(used[i] == 0)
263 {
264 // we store the formid
265 used[i] = formid;
266 break;
267 }
268 if(used[i] == formid) break;
269 }
270
271 // if the form is a group, we iterate through the sub-forms
272 dt_masks_form_t *form = dt_masks_get_from_id_ext(forms_list, formid);
273 if(form && (form->type & DT_MASKS_GROUP))
274 {
275 for(GList *grpts = form->points; grpts; grpts = g_list_next(grpts))
276 {
277 dt_masks_point_group_t *grpt = (dt_masks_point_group_t *)grpts->data;
278 _fill_used_forms(forms_list, grpt->formid, used, nb);
279 }
280 }
281 }
282
283 // dev_src is used only to copy masks, if no mask will be copied it can be null
dt_history_merge_module_into_history(dt_develop_t * dev_dest,dt_develop_t * dev_src,dt_iop_module_t * mod_src,GList ** _modules_used,const int append)284 int dt_history_merge_module_into_history(dt_develop_t *dev_dest, dt_develop_t *dev_src, dt_iop_module_t *mod_src, GList **_modules_used, const int append)
285 {
286 int module_added = 1;
287 GList *modules_used = *_modules_used;
288 dt_iop_module_t *module = NULL;
289 dt_iop_module_t *mod_replace = NULL;
290
291 // one-instance modules always replace the existing one
292 if(mod_src->flags() & IOP_FLAGS_ONE_INSTANCE)
293 {
294 mod_replace = dt_iop_get_module_by_op_priority(dev_dest->iop, mod_src->op, -1);
295 if(mod_replace == NULL)
296 {
297 fprintf(stderr, "[dt_history_merge_module_into_history] can't find single instance module %s\n",
298 mod_src->op);
299 module_added = 0;
300 }
301 }
302
303 if(module_added && mod_replace == NULL && !append)
304 {
305 // we haven't found a module to replace
306 // check if there's a module with the same (operation, multi_name) on dev->iop
307 for(GList *modules_dest = dev_dest->iop; modules_dest; modules_dest = g_list_next(modules_dest))
308 {
309 dt_iop_module_t *mod_dest = (dt_iop_module_t *)modules_dest->data;
310
311 if(strcmp(mod_src->op, mod_dest->op) == 0 && strcmp(mod_src->multi_name, mod_dest->multi_name) == 0)
312 {
313 // but only if it hasn't been used already
314 if(_search_list_iop_by_module(modules_used, mod_dest) == NULL)
315 {
316 // we will replace this module
317 modules_used = g_list_append(modules_used, mod_dest);
318 mod_replace = mod_dest;
319 break;
320 }
321 }
322 }
323 }
324
325 if(module_added && mod_replace == NULL)
326 {
327 // we haven't found a module to replace, so we will create a new instance
328 // but if there's an un-used instance on dev->iop we will use that
329
330 if(_search_history_by_op(dev_dest, mod_src) == NULL)
331 {
332 // there should be only one instance of this iop (since is un-used)
333 mod_replace = dt_iop_get_module_by_op_priority(dev_dest->iop, mod_src->op, -1);
334 if(mod_replace == NULL)
335 {
336 fprintf(stderr, "[dt_history_merge_module_into_history] can't find base instance module %s\n", mod_src->op);
337 module_added = 0;
338 }
339 }
340 }
341
342 if(module_added)
343 {
344 // if we are creating a new instance, create a new module
345 if(mod_replace == NULL)
346 {
347 dt_iop_module_t *base = dt_iop_get_module_by_op_priority(dev_dest->iop, mod_src->op, -1);
348 module = (dt_iop_module_t *)calloc(1, sizeof(dt_iop_module_t));
349 if(dt_iop_load_module(module, base->so, dev_dest))
350 {
351 fprintf(stderr, "[dt_history_merge_module_into_history] can't load module %s\n", mod_src->op);
352 module_added = 0;
353 }
354 else
355 {
356 module->instance = mod_src->instance;
357 module->multi_priority = mod_src->multi_priority;
358 module->iop_order = dt_ioppr_get_iop_order(dev_dest->iop_order_list, module->op, module->multi_priority);
359 }
360 }
361 else
362 {
363 module = mod_replace;
364 }
365
366 module->enabled = mod_src->enabled;
367 g_strlcpy(module->multi_name, mod_src->multi_name, sizeof(module->multi_name));
368
369 memcpy(module->params, mod_src->params, module->params_size);
370 if(module->flags() & IOP_FLAGS_SUPPORTS_BLENDING)
371 {
372 memcpy(module->blend_params, mod_src->blend_params, sizeof(dt_develop_blend_params_t));
373 module->blend_params->mask_id = mod_src->blend_params->mask_id;
374 }
375 }
376
377 // we have the module, we will use the source module iop_order unless there's already
378 // a module with that order
379 if(module_added)
380 {
381 dt_iop_module_t *module_duplicate = NULL;
382 // check if there's a module with the same iop_order
383 for( GList *modules_dest = dev_dest->iop; modules_dest; modules_dest = g_list_next(modules_dest))
384 {
385 dt_iop_module_t *mod = (dt_iop_module_t *)(modules_dest->data);
386
387 if(module_duplicate != NULL)
388 {
389 module_duplicate = mod;
390 break;
391 }
392 if(mod->iop_order == mod_src->iop_order && mod != module)
393 {
394 module_duplicate = mod;
395 }
396 }
397
398 // do some checking...
399 if(mod_src->iop_order <= 0.0 || mod_src->iop_order == INT_MAX)
400 fprintf(stderr, "[dt_history_merge_module_into_history] invalid source module %s %s(%d)(%i)\n",
401 mod_src->op, mod_src->multi_name, mod_src->iop_order, mod_src->multi_priority);
402 if(module_duplicate && (module_duplicate->iop_order <= 0.0 || module_duplicate->iop_order == INT_MAX))
403 fprintf(stderr, "[dt_history_merge_module_into_history] invalid duplicate module module %s %s(%d)(%i)\n",
404 module_duplicate->op, module_duplicate->multi_name, module_duplicate->iop_order, module_duplicate->multi_priority);
405 if(module->iop_order <= 0.0 || module->iop_order == INT_MAX)
406 fprintf(stderr, "[dt_history_merge_module_into_history] invalid iop_order for module %s %s(%d)(%i)\n",
407 module->op, module->multi_name, module->iop_order, module->multi_priority);
408
409 // if this is a new module just add it to the list
410 if(mod_replace == NULL)
411 dev_dest->iop = g_list_insert_sorted(dev_dest->iop, module, dt_sort_iop_by_order);
412 else
413 dev_dest->iop = g_list_sort(dev_dest->iop, dt_sort_iop_by_order);
414 }
415
416 // and we add it to history
417 if(module_added)
418 {
419 // copy masks
420 guint nbf = 0;
421 int *forms_used_replace = NULL;
422
423 if(dev_src)
424 {
425 // we will copy only used forms
426 // record the masks used by this module
427 if(mod_src->flags() & IOP_FLAGS_SUPPORTS_BLENDING && mod_src->blend_params->mask_id > 0)
428 {
429 nbf = g_list_length(dev_src->forms);
430 forms_used_replace = calloc(nbf, sizeof(int));
431
432 _fill_used_forms(dev_src->forms, mod_src->blend_params->mask_id, forms_used_replace, nbf);
433
434 // now copy masks
435 for(int i = 0; i < nbf && forms_used_replace[i] > 0; i++)
436 {
437 dt_masks_form_t *form = dt_masks_get_from_id_ext(dev_src->forms, forms_used_replace[i]);
438 if(form)
439 {
440 // check if the form already exists in dest image
441 // if so we'll remove it, so it is replaced
442 dt_masks_form_t *form_dest = dt_masks_get_from_id_ext(dev_dest->forms, forms_used_replace[i]);
443 if(form_dest)
444 {
445 dev_dest->forms = g_list_remove(dev_dest->forms, form_dest);
446 // and add it to allforms to cleanup
447 dev_dest->allforms = g_list_append(dev_dest->allforms, form_dest);
448 }
449
450 // and add it to dest image
451 dt_masks_form_t *form_new = dt_masks_dup_masks_form(form);
452 dev_dest->forms = g_list_append(dev_dest->forms, form_new);
453 }
454 else
455 fprintf(stderr, "[dt_history_merge_module_into_history] form %i not found in source image\n", forms_used_replace[i]);
456 }
457 }
458 }
459
460 if(nbf > 0 && forms_used_replace[0] > 0)
461 dt_dev_add_masks_history_item_ext(dev_dest, module, FALSE, TRUE);
462 else
463 dt_dev_add_history_item_ext(dev_dest, module, FALSE, TRUE);
464
465 dt_ioppr_resync_modules_order(dev_dest);
466
467 dt_dev_pop_history_items_ext(dev_dest, dev_dest->history_end);
468
469 if(forms_used_replace) free(forms_used_replace);
470 }
471
472 *_modules_used = modules_used;
473
474 return module_added;
475 }
476
_history_copy_and_paste_on_image_merge(int32_t imgid,int32_t dest_imgid,GList * ops,const gboolean copy_full)477 static int _history_copy_and_paste_on_image_merge(int32_t imgid, int32_t dest_imgid, GList *ops, const gboolean copy_full)
478 {
479 GList *modules_used = NULL;
480
481 dt_develop_t _dev_src = { 0 };
482 dt_develop_t _dev_dest = { 0 };
483
484 dt_develop_t *dev_src = &_dev_src;
485 dt_develop_t *dev_dest = &_dev_dest;
486
487 // we will do the copy/paste on memory so we can deal with masks
488 dt_dev_init(dev_src, FALSE);
489 dt_dev_init(dev_dest, FALSE);
490
491 dev_src->iop = dt_iop_load_modules_ext(dev_src, TRUE);
492 dev_dest->iop = dt_iop_load_modules_ext(dev_dest, TRUE);
493
494 dt_dev_read_history_ext(dev_src, imgid, TRUE);
495
496 // This prepends the default modules and converts just in case it's an empty history
497 dt_dev_read_history_ext(dev_dest, dest_imgid, TRUE);
498
499 dt_ioppr_check_iop_order(dev_src, imgid, "_history_copy_and_paste_on_image_merge ");
500 dt_ioppr_check_iop_order(dev_dest, dest_imgid, "_history_copy_and_paste_on_image_merge ");
501
502 dt_dev_pop_history_items_ext(dev_src, dev_src->history_end);
503 dt_dev_pop_history_items_ext(dev_dest, dev_dest->history_end);
504
505 dt_ioppr_check_iop_order(dev_src, imgid, "_history_copy_and_paste_on_image_merge 1");
506 dt_ioppr_check_iop_order(dev_dest, dest_imgid, "_history_copy_and_paste_on_image_merge 1");
507
508 GList *mod_list = NULL;
509
510 if(ops)
511 {
512 if (DT_IOP_ORDER_INFO) fprintf(stderr," selected ops");
513 // copy only selected history entries
514 for(const GList *l = g_list_last(ops); l; l = g_list_previous(l))
515 {
516 const unsigned int num = GPOINTER_TO_UINT(l->data);
517
518 const dt_dev_history_item_t *hist = g_list_nth_data(dev_src->history, num);
519
520 if(hist)
521 {
522 if (!dt_iop_is_hidden(hist->module))
523 {
524 if (DT_IOP_ORDER_INFO)
525 fprintf(stderr,"\n module %20s, multiprio %i", hist->module->op, hist->module->multi_priority);
526
527 mod_list = g_list_prepend(mod_list, hist->module);
528 }
529 }
530 }
531 }
532 else
533 {
534 if (DT_IOP_ORDER_INFO) fprintf(stderr," all modules");
535 // we will copy all modules
536 for(GList *modules_src = dev_src->iop; modules_src; modules_src = g_list_next(modules_src))
537 {
538 dt_iop_module_t *mod_src = (dt_iop_module_t *)(modules_src->data);
539
540 // copy from history only if
541 if((_search_history_by_module(dev_src, mod_src) != NULL) // module is in history of source image
542 && !(mod_src->default_enabled && mod_src->enabled
543 && !memcmp(mod_src->params, mod_src->default_params, mod_src->params_size) // it's not a enabled by default module with unmodified settings
544 && !dt_iop_is_hidden(mod_src))
545 && (copy_full || !dt_history_module_skip_copy(mod_src->flags()))
546 )
547 {
548 mod_list = g_list_prepend(mod_list, mod_src);
549 }
550 }
551 }
552 if (DT_IOP_ORDER_INFO) fprintf(stderr,"\nvvvvv\n");
553
554 mod_list = g_list_reverse(mod_list); // list was built in reverse order, so un-reverse it
555
556 // update iop-order list to have entries for the new modules
557 dt_ioppr_update_for_modules(dev_dest, mod_list, FALSE);
558
559 for(GList *l = mod_list; l; l = g_list_next(l))
560 {
561 dt_iop_module_t *mod = (dt_iop_module_t *)l->data;
562 dt_history_merge_module_into_history(dev_dest, dev_src, mod, &modules_used, FALSE);
563 }
564
565 // update iop-order list to have entries for the new modules
566 dt_ioppr_update_for_modules(dev_dest, mod_list, FALSE);
567
568 dt_ioppr_check_iop_order(dev_dest, dest_imgid, "_history_copy_and_paste_on_image_merge 2");
569
570 // write history and forms to db
571 dt_dev_write_history_ext(dev_dest, dest_imgid);
572
573 dt_dev_cleanup(dev_src);
574 dt_dev_cleanup(dev_dest);
575
576 g_list_free(modules_used);
577
578 return 0;
579 }
580
_history_copy_and_paste_on_image_overwrite(const int32_t imgid,const int32_t dest_imgid,GList * ops,const gboolean copy_full)581 static int _history_copy_and_paste_on_image_overwrite(const int32_t imgid, const int32_t dest_imgid, GList *ops, const gboolean copy_full)
582 {
583 int ret_val = 0;
584 sqlite3_stmt *stmt;
585
586 // replace history stack
587 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
588 "DELETE FROM main.history WHERE imgid = ?1",
589 -1, &stmt, NULL);
590 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
591 sqlite3_step(stmt);
592 sqlite3_finalize(stmt);
593
594 // and shapes
595 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
596 "DELETE FROM main.masks_history WHERE imgid = ?1",
597 -1, &stmt, NULL);
598 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
599 sqlite3_step(stmt);
600 sqlite3_finalize(stmt);
601
602 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
603 "UPDATE main.images SET history_end = 0, aspect_ratio = 0.0 WHERE id = ?1",
604 -1, &stmt, NULL);
605 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
606 sqlite3_step(stmt);
607 sqlite3_finalize(stmt);
608
609 // the user wants an exact duplicate of the history, so just copy the db
610 if(!ops)
611 {
612 // let's build the list of IOP to not copy
613 gchar *skip_modules = NULL;
614
615 if(!copy_full)
616 {
617 for(GList *modules = darktable.iop; modules; modules = g_list_next(modules))
618 {
619 dt_iop_module_so_t *module = (dt_iop_module_so_t *)modules->data;
620
621 if(dt_history_module_skip_copy(module->flags()))
622 {
623 if(skip_modules)
624 skip_modules = dt_util_dstrcat(skip_modules, ",");
625
626 skip_modules = dt_util_dstrcat(skip_modules, "'%s'", module->op);
627 }
628 }
629 }
630
631 if(!skip_modules)
632 skip_modules = g_strdup("'@'");
633
634 gchar *query = g_strdup_printf
635 ("INSERT INTO main.history "
636 " (imgid,num,module,operation,op_params,enabled,blendop_params, "
637 " blendop_version,multi_priority,multi_name)"
638 " SELECT ?1,num,module,operation,op_params,enabled,blendop_params, "
639 " blendop_version,multi_priority,multi_name "
640 " FROM main.history"
641 " WHERE imgid=?2"
642 " AND operation NOT IN (%s)"
643 " ORDER BY num", skip_modules);
644
645 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
646 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
647 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
648 sqlite3_step(stmt);
649 sqlite3_finalize(stmt);
650
651 g_free(query);
652
653 query = g_strdup_printf
654 ("INSERT INTO main.masks_history "
655 " (imgid, num, formid, form, name, version, points, points_count, source)"
656 " SELECT ?1, num, formid, form, name, version, points, points_count, source "
657 " FROM main.masks_history"
658 " WHERE imgid = ?2"
659 " AND num NOT IN (SELECT num FROM history WHERE imgid=?2 AND OPERATION IN (%s))", skip_modules);
660
661 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
662 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
663 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
664 sqlite3_step(stmt);
665 sqlite3_finalize(stmt);
666
667 g_free(skip_modules);
668
669 int history_end = 0;
670 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
671 "SELECT history_end FROM main.images WHERE id = ?1",
672 -1, &stmt, NULL);
673 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
674 if(sqlite3_step(stmt) == SQLITE_ROW)
675 {
676 if(sqlite3_column_type(stmt, 0) != SQLITE_NULL)
677 history_end = sqlite3_column_int(stmt, 0);
678 }
679 sqlite3_finalize(stmt);
680
681 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
682 "UPDATE main.images SET history_end = ?2"
683 " WHERE id = ?1",
684 -1, &stmt, NULL);
685 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
686 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, history_end);
687 sqlite3_step(stmt);
688 sqlite3_finalize(stmt);
689
690 // copy the module order
691
692 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
693 "INSERT OR REPLACE INTO main.module_order (imgid, iop_list, version)"
694 " SELECT ?2, iop_list, version"
695 " FROM main.module_order"
696 " WHERE imgid = ?1",
697 -1, &stmt, NULL);
698 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
699 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, dest_imgid);
700 sqlite3_step(stmt);
701 sqlite3_finalize(stmt);
702
703 // it is possible the source image has no hash yet. make sure this is copied too
704
705 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
706 "DELETE FROM main.history_hash WHERE imgid = ?1",
707 -1, &stmt, NULL);
708 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid);
709 sqlite3_step(stmt);
710 sqlite3_finalize(stmt);
711
712 // and finally copy the history hash, except mipmap hash
713
714 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
715 "INSERT INTO main.history_hash"
716 " (imgid, basic_hash, auto_hash, current_hash)"
717 " SELECT ?2, basic_hash, auto_hash, current_hash"
718 " FROM main.history_hash "
719 " WHERE imgid = ?1",
720 -1, &stmt, NULL);
721 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
722 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, dest_imgid);
723 sqlite3_step(stmt);
724 sqlite3_finalize(stmt);
725 }
726 else
727 {
728 // since the history and masks where deleted we can do a merge
729 ret_val = _history_copy_and_paste_on_image_merge(imgid, dest_imgid, ops, copy_full);
730 }
731
732 return ret_val;
733 }
734
dt_history_copy_and_paste_on_image(const int32_t imgid,const int32_t dest_imgid,const gboolean merge,GList * ops,const gboolean copy_iop_order,const gboolean copy_full)735 int dt_history_copy_and_paste_on_image(const int32_t imgid, const int32_t dest_imgid,
736 const gboolean merge, GList *ops,
737 const gboolean copy_iop_order, const gboolean copy_full)
738 {
739 if(imgid == dest_imgid) return 1;
740
741 if(imgid == -1)
742 {
743 dt_control_log(_("you need to copy history from an image before you paste it onto another"));
744 return 1;
745 }
746
747 dt_lock_image_pair(imgid, dest_imgid);
748
749 // be sure the current history is written before pasting some other history data
750 const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager);
751 if(cv->view((dt_view_t *)cv) == DT_VIEW_DARKROOM) dt_dev_write_history(darktable.develop);
752
753 dt_undo_lt_history_t *hist = dt_history_snapshot_item_init();
754 hist->imgid = dest_imgid;
755 dt_history_snapshot_undo_create(hist->imgid, &hist->before, &hist->before_history_end);
756
757 if(copy_iop_order)
758 {
759 GList *iop_list = dt_ioppr_get_iop_order_list(imgid, FALSE);
760 dt_ioppr_write_iop_order_list(iop_list, dest_imgid);
761 g_list_free_full(iop_list, g_free);
762 }
763
764 int ret_val = 0;
765 if(merge)
766 ret_val = _history_copy_and_paste_on_image_merge(imgid, dest_imgid, ops, copy_full);
767 else
768 ret_val = _history_copy_and_paste_on_image_overwrite(imgid, dest_imgid, ops, copy_full);
769
770 dt_history_snapshot_undo_create(hist->imgid, &hist->after, &hist->after_history_end);
771 dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
772 dt_undo_record(darktable.undo, NULL, DT_UNDO_LT_HISTORY, (dt_undo_data_t)hist,
773 dt_history_snapshot_undo_pop, dt_history_snapshot_undo_lt_history_data_free);
774 dt_undo_end_group(darktable.undo);
775
776 /* attach changed tag reflecting actual change */
777 guint tagid = 0;
778 dt_tag_new("darktable|changed", &tagid);
779 dt_tag_attach(tagid, dest_imgid, FALSE, FALSE);
780 /* set change_timestamp */
781 dt_image_cache_set_change_timestamp(darktable.image_cache, dest_imgid);
782
783 /* if current image in develop reload history */
784 if(dt_dev_is_current_image(darktable.develop, dest_imgid))
785 {
786 dt_dev_reload_history_items(darktable.develop);
787 dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop));
788 }
789
790 /* update xmp file */
791 dt_image_synch_xmp(dest_imgid);
792
793 dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid);
794 dt_image_update_final_size(imgid);
795
796 /* update the aspect ratio. recompute only if really needed for performance reasons */
797 if(darktable.collection->params.sort == DT_COLLECTION_SORT_ASPECT_RATIO)
798 dt_image_set_aspect_ratio(dest_imgid, FALSE);
799 else
800 dt_image_reset_aspect_ratio(dest_imgid, FALSE);
801
802 // signal that the mipmap need to be updated
803 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_DEVELOP_MIPMAP_UPDATED, dest_imgid);
804
805 dt_unlock_image_pair(imgid, dest_imgid);
806
807 return ret_val;
808 }
809
dt_history_get_items(const int32_t imgid,gboolean enabled)810 GList *dt_history_get_items(const int32_t imgid, gboolean enabled)
811 {
812 GList *result = NULL;
813 sqlite3_stmt *stmt;
814
815 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
816 "SELECT num, operation, enabled, multi_name"
817 " FROM main.history"
818 " WHERE imgid=?1"
819 " AND num IN (SELECT MAX(num)"
820 " FROM main.history hst2"
821 " WHERE hst2.imgid=?1"
822 " AND hst2.operation=main.history.operation"
823 " GROUP BY multi_priority)"
824 " ORDER BY num DESC",
825 -1, &stmt, NULL);
826 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
827 while(sqlite3_step(stmt) == SQLITE_ROW)
828 {
829 if(strcmp((const char*)sqlite3_column_text(stmt, 1), "mask_manager") == 0) continue;
830
831 const int is_active = sqlite3_column_int(stmt, 2);
832
833 if(enabled == FALSE || is_active)
834 {
835 char name[512] = { 0 };
836 dt_history_item_t *item = g_malloc(sizeof(dt_history_item_t));
837 item->num = sqlite3_column_int(stmt, 0);
838 char *mname = g_strdup((gchar *)sqlite3_column_text(stmt, 3));
839 if(enabled)
840 {
841 if(strcmp(mname, "0") == 0)
842 g_snprintf(name, sizeof(name), "%s",
843 dt_iop_get_localized_name((char *)sqlite3_column_text(stmt, 1)));
844 else
845 g_snprintf(name, sizeof(name), "%s %s",
846 dt_iop_get_localized_name((char *)sqlite3_column_text(stmt, 1)),
847 (char *)sqlite3_column_text(stmt, 3));
848 }
849 else
850 {
851 if(strcmp(mname, "0") == 0)
852 g_snprintf(name, sizeof(name), "%s (%s)",
853 dt_iop_get_localized_name((char *)sqlite3_column_text(stmt, 1)),
854 (is_active != 0) ? _("on") : _("off"));
855 g_snprintf(name, sizeof(name), "%s %s (%s)",
856 dt_iop_get_localized_name((char *)sqlite3_column_text(stmt, 1)),
857 (char *)sqlite3_column_text(stmt, 3), (is_active != 0) ? _("on") : _("off"));
858 }
859 item->name = g_strdup(name);
860 item->op = g_strdup((gchar *)sqlite3_column_text(stmt, 1));
861 result = g_list_prepend(result, item);
862
863 g_free(mname);
864 }
865 }
866 sqlite3_finalize(stmt);
867 return g_list_reverse(result); // list was built in reverse order, so un-reverse it
868 }
869
dt_history_get_items_as_string(const int32_t imgid)870 char *dt_history_get_items_as_string(const int32_t imgid)
871 {
872 GList *items = NULL;
873 const char *onoff[2] = { _("off"), _("on") };
874 sqlite3_stmt *stmt;
875 DT_DEBUG_SQLITE3_PREPARE_V2(
876 dt_database_get(darktable.db),
877 "SELECT operation, enabled, multi_name FROM main.history WHERE imgid=?1 ORDER BY num DESC", -1, &stmt, NULL);
878 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
879
880 // collect all the entries in the history from the db
881 while(sqlite3_step(stmt) == SQLITE_ROW)
882 {
883 char *name = NULL, *multi_name = NULL;
884 const char *mn = (char *)sqlite3_column_text(stmt, 2);
885 if(mn && *mn && g_strcmp0(mn, " ") != 0 && g_strcmp0(mn, "0") != 0)
886 multi_name = g_strconcat(" ", sqlite3_column_text(stmt, 2), NULL);
887 name = g_strconcat(dt_iop_get_localized_name((char *)sqlite3_column_text(stmt, 0)),
888 multi_name ? multi_name : "", " (",
889 (sqlite3_column_int(stmt, 1) == 0) ? onoff[0] : onoff[1], ")", NULL);
890 items = g_list_prepend(items, name);
891 g_free(multi_name);
892 }
893 sqlite3_finalize(stmt);
894 items = g_list_reverse(items); // list was built in reverse order, so un-reverse it
895 char *result = dt_util_glist_to_str("\n", items);
896 g_list_free_full(items, g_free);
897 return result;
898 }
899
dt_history_set_compress_problem(const int32_t imgid,const gboolean set)900 void dt_history_set_compress_problem(const int32_t imgid, const gboolean set)
901 {
902 guint tagid = 0;
903 char tagname[64];
904 snprintf(tagname, sizeof(tagname), "darktable|problem|history-compress");
905 dt_tag_new(tagname, &tagid);
906 if (set)
907 dt_tag_attach(tagid, imgid, FALSE, FALSE);
908 else
909 dt_tag_detach(tagid, imgid, FALSE, FALSE);
910 }
911
dt_history_end_attop(const int32_t imgid)912 static int dt_history_end_attop(const int32_t imgid)
913 {
914 int size=0;
915 int end=0;
916 sqlite3_stmt *stmt;
917
918 // get highest num in history
919 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
920 "SELECT MAX(num) FROM main.history WHERE imgid=?1", -1, &stmt, NULL);
921 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
922
923 if (sqlite3_step(stmt) == SQLITE_ROW)
924 size = sqlite3_column_int(stmt, 0);
925 sqlite3_finalize(stmt);
926
927 // get history_end
928 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
929 "SELECT history_end FROM main.images WHERE id=?1", -1, &stmt, NULL);
930 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
931 if (sqlite3_step(stmt) == SQLITE_ROW)
932 end = sqlite3_column_int(stmt, 0);
933 sqlite3_finalize(stmt);
934
935 // fprintf(stderr,"\ndt_history_end_attop for image %i: size %i, end %i",imgid,size,end);
936
937 // a special case right after removing all history
938 // It must be absolutely fresh and untouched so history_end is always on top
939 if ((size==0) && (end==0)) return -1;
940
941 // return 1 if end is larger than size
942 if (end > size) return 1;
943
944 // no compression as history_end is right in the middle of stack
945 return 0;
946 }
947
948
949 /* Please note: dt_history_compress_on_image
950 - is used in lighttable and darkroom mode
951 - It compresses history *exclusively* in the database and does *not* touch anything on the history stack
952 */
dt_history_compress_on_image(const int32_t imgid)953 void dt_history_compress_on_image(const int32_t imgid)
954 {
955 dt_lock_image(imgid);
956 sqlite3_stmt *stmt;
957
958 // get history_end for image
959 int my_history_end = 0;
960 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
961 "SELECT history_end FROM main.images WHERE id=?1", -1, &stmt, NULL);
962 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
963
964 if (sqlite3_step(stmt) == SQLITE_ROW)
965 my_history_end = sqlite3_column_int(stmt, 0);
966 sqlite3_finalize(stmt);
967
968 if (my_history_end == 0)
969 {
970 dt_history_delete_on_image(imgid);
971 dt_unlock_image(imgid);
972 return;
973 }
974
975 int masks_count = 0;
976 const char *op_mask_manager = "mask_manager";
977 gboolean manager_position = FALSE;
978
979 DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "BEGIN", NULL, NULL, NULL);
980
981 // We must know for sure whether there is a mask manager at slot 0 in history
982 // because only if this is **not** true history nums and history_end must be increased
983 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
984 "SELECT COUNT(*) FROM main.history WHERE imgid = ?1 AND operation = ?2 AND num = 0", -1, &stmt, NULL);
985 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
986 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op_mask_manager, -1, SQLITE_TRANSIENT);
987 if(sqlite3_step(stmt) == SQLITE_ROW)
988 {
989 if (sqlite3_column_int(stmt, 0) == 1) manager_position = TRUE;
990 }
991 sqlite3_finalize(stmt);
992
993 // compress history, keep disabled modules as documented
994 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
995 "DELETE FROM main.history"
996 " WHERE imgid = ?1 AND num NOT IN"
997 " (SELECT MAX(num) FROM main.history"
998 " WHERE imgid = ?1 AND num < ?2"
999 " GROUP BY operation, multi_priority)",
1000 -1, &stmt, NULL);
1001 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1002 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, my_history_end);
1003 sqlite3_step(stmt);
1004 sqlite3_finalize(stmt);
1005
1006 // delete all mask_manager entries
1007 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1008 "DELETE FROM main.history WHERE imgid = ?1 AND operation = ?2", -1, &stmt, NULL);
1009 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1010 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op_mask_manager, -1, SQLITE_TRANSIENT);
1011 sqlite3_step(stmt);
1012 sqlite3_finalize(stmt);
1013
1014 // compress masks history
1015 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1016 "DELETE FROM main.masks_history"
1017 " WHERE imgid = ?1 "
1018 " AND num NOT IN (SELECT MAX(num)"
1019 " FROM main.masks_history"
1020 " WHERE imgid = ?1 AND num < ?2)", -1, &stmt, NULL);
1021 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1022 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, my_history_end);
1023 sqlite3_step(stmt);
1024 sqlite3_finalize(stmt);
1025
1026 // if there are masks create a mask manager entry, so we need to count them
1027 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1028 "SELECT COUNT(*) FROM main.masks_history WHERE imgid = ?1", -1, &stmt, NULL);
1029 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1030 if(sqlite3_step(stmt) == SQLITE_ROW) masks_count = sqlite3_column_int(stmt, 0);
1031 sqlite3_finalize(stmt);
1032
1033 if(masks_count > 0)
1034 {
1035 // Set num in masks history to make sure they are owned by the manager at slot 0.
1036 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1037 "UPDATE main.masks_history SET num = 0 WHERE imgid = ?1", -1, &stmt, NULL);
1038 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1039 sqlite3_step(stmt);
1040 sqlite3_finalize(stmt);
1041
1042 if (!manager_position)
1043 {
1044 // make room for mask manager history entry
1045 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1046 "UPDATE main.history SET num=num+1 WHERE imgid = ?1", -1, &stmt, NULL);
1047 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1048 sqlite3_step(stmt);
1049 sqlite3_finalize(stmt);
1050
1051 // update history end
1052 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1053 "UPDATE main.images SET history_end = history_end+1 WHERE id = ?1", -1, &stmt, NULL);
1054 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1055 sqlite3_step(stmt);
1056 sqlite3_finalize(stmt);
1057 }
1058
1059 // create a mask manager entry in history as first entry
1060 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1061 "INSERT INTO main.history (imgid, num, operation, op_params, module, enabled, "
1062 " blendop_params, blendop_version, multi_priority, multi_name) "
1063 " VALUES(?1, 0, ?2, NULL, 1, 0, NULL, 0, 0, '')",
1064 -1, &stmt, NULL);
1065 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1066 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op_mask_manager, -1, SQLITE_TRANSIENT);
1067 sqlite3_step(stmt);
1068 sqlite3_finalize(stmt);
1069 }
1070 dt_unlock_image(imgid);
1071 dt_history_hash_write_from_history(imgid, DT_HISTORY_HASH_CURRENT);
1072
1073 DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
1074
1075 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_DEVELOP_MIPMAP_UPDATED, imgid);
1076 }
1077
1078 /* Please note: dt_history_truncate_on_image
1079 - can be used in lighttable and darkroom mode
1080 - It truncates history *exclusively* in the database and does *not* touch anything on the history stack
1081 */
dt_history_truncate_on_image(const int32_t imgid,const int32_t history_end)1082 void dt_history_truncate_on_image(const int32_t imgid, const int32_t history_end)
1083 {
1084 dt_lock_image(imgid);
1085 sqlite3_stmt *stmt;
1086
1087 if (history_end == 0)
1088 {
1089 dt_history_delete_on_image(imgid);
1090 dt_unlock_image(imgid);
1091 return;
1092 }
1093
1094 DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "BEGIN", NULL, NULL, NULL);
1095
1096 // delete end of history
1097 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1098 "DELETE FROM main.history"
1099 " WHERE imgid = ?1 "
1100 " AND num >= ?2", -1, &stmt, NULL);
1101 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1102 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, history_end);
1103 sqlite3_step(stmt);
1104 sqlite3_finalize(stmt);
1105
1106 // delete end of masks history
1107 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1108 "DELETE FROM main.masks_history"
1109 " WHERE imgid = ?1 "
1110 " AND num >= ?2", -1, &stmt, NULL);
1111 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1112 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, history_end);
1113 sqlite3_step(stmt);
1114 sqlite3_finalize(stmt);
1115
1116 // update history end
1117 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1118 "UPDATE main.images"
1119 " SET history_end = ?1"
1120 " WHERE id = ?2 ", -1, &stmt, NULL);
1121 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, history_end);
1122 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
1123 sqlite3_step(stmt);
1124 sqlite3_finalize(stmt);
1125 dt_unlock_image(imgid);
1126 dt_history_hash_write_from_history(imgid, DT_HISTORY_HASH_CURRENT);
1127
1128 DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
1129
1130 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_DEVELOP_MIPMAP_UPDATED, imgid);
1131 }
1132
dt_history_compress_on_list(const GList * imgs)1133 int dt_history_compress_on_list(const GList *imgs)
1134 {
1135 int uncompressed=0;
1136
1137 // Get the list of selected images
1138 for(const GList *l = imgs; l; l = g_list_next(l))
1139 {
1140 const int imgid = GPOINTER_TO_INT(l->data);
1141 dt_lock_image(imgid);
1142 const int test = dt_history_end_attop(imgid);
1143 if (test == 1) // we do a compression and we know for sure history_end is at the top!
1144 {
1145 dt_history_set_compress_problem(imgid, FALSE);
1146 dt_history_compress_on_image(imgid);
1147
1148 // now the modules are in right order but need renumbering to remove leaks
1149 int max=0; // the maximum num in main_history for an image
1150 int size=0; // the number of items in main_history for an image
1151 int done=0; // used for renumbering index
1152
1153 sqlite3_stmt *stmt2;
1154
1155 // get highest num in history
1156 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1157 "SELECT MAX(num) FROM main.history WHERE imgid=?1", -1, &stmt2, NULL);
1158 DT_DEBUG_SQLITE3_BIND_INT(stmt2, 1, imgid);
1159 if (sqlite3_step(stmt2) == SQLITE_ROW)
1160 max = sqlite3_column_int(stmt2, 0);
1161 sqlite3_finalize(stmt2);
1162
1163 // get number of items in main.history
1164 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1165 "SELECT COUNT(*) FROM main.history WHERE imgid = ?1", -1, &stmt2, NULL);
1166 DT_DEBUG_SQLITE3_BIND_INT(stmt2, 1, imgid);
1167 if(sqlite3_step(stmt2) == SQLITE_ROW)
1168 size = sqlite3_column_int(stmt2, 0);
1169 sqlite3_finalize(stmt2);
1170
1171 if ((size>0) && (max>0))
1172 {
1173 for (int index=0;index<(max+1);index++)
1174 {
1175 sqlite3_stmt *stmt3;
1176 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1177 "SELECT num FROM main.history WHERE imgid=?1 AND num=?2", -1, &stmt3, NULL);
1178 DT_DEBUG_SQLITE3_BIND_INT(stmt3, 1, imgid);
1179 DT_DEBUG_SQLITE3_BIND_INT(stmt3, 2, index);
1180 if (sqlite3_step(stmt3) == SQLITE_ROW)
1181 {
1182 sqlite3_stmt *stmt4;
1183 // step by step set the correct num
1184 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1185 "UPDATE main.history SET num = ?3 WHERE imgid = ?1 AND num = ?2", -1, &stmt4, NULL);
1186 DT_DEBUG_SQLITE3_BIND_INT(stmt4, 1, imgid);
1187 DT_DEBUG_SQLITE3_BIND_INT(stmt4, 2, index);
1188 DT_DEBUG_SQLITE3_BIND_INT(stmt4, 3, done);
1189 sqlite3_step(stmt4);
1190 sqlite3_finalize(stmt4);
1191
1192 done++;
1193 }
1194 sqlite3_finalize(stmt3);
1195 }
1196 }
1197 // update history end
1198 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1199 "UPDATE main.images SET history_end = ?2 WHERE id = ?1", -1, &stmt2, NULL);
1200 DT_DEBUG_SQLITE3_BIND_INT(stmt2, 1, imgid);
1201 DT_DEBUG_SQLITE3_BIND_INT(stmt2, 2, done);
1202 sqlite3_step(stmt2);
1203 sqlite3_finalize(stmt2);
1204
1205 dt_image_write_sidecar_file(imgid);
1206 }
1207 if (test == 0) // no compression as history_end is right in the middle of history
1208 {
1209 uncompressed++;
1210 dt_history_set_compress_problem(imgid, TRUE);
1211 }
1212 if (test == -1)
1213 dt_history_set_compress_problem(imgid, FALSE);
1214
1215 dt_unlock_image(imgid);
1216 dt_history_hash_write_from_history(imgid, DT_HISTORY_HASH_CURRENT);
1217 }
1218
1219 return uncompressed;
1220 }
1221
dt_history_check_module_exists(int32_t imgid,const char * operation)1222 gboolean dt_history_check_module_exists(int32_t imgid, const char *operation)
1223 {
1224 gboolean result = FALSE;
1225 sqlite3_stmt *stmt;
1226
1227 DT_DEBUG_SQLITE3_PREPARE_V2(
1228 dt_database_get(darktable.db),
1229 "SELECT imgid FROM main.history WHERE imgid= ?1 AND operation = ?2", -1, &stmt, NULL);
1230 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1231 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, operation, -1, SQLITE_TRANSIENT);
1232 if (sqlite3_step(stmt) == SQLITE_ROW) result = TRUE;
1233 sqlite3_finalize(stmt);
1234
1235 return result;
1236 }
1237
dt_history_duplicate(GList * hist)1238 GList *dt_history_duplicate(GList *hist)
1239 {
1240 GList *result = NULL;
1241
1242 for(GList *h = hist; h; h = g_list_next(h))
1243 {
1244 const dt_dev_history_item_t *old = (dt_dev_history_item_t *)(h->data);
1245
1246 dt_dev_history_item_t *new = (dt_dev_history_item_t *)malloc(sizeof(dt_dev_history_item_t));
1247
1248 memcpy(new, old, sizeof(dt_dev_history_item_t));
1249
1250 int32_t params_size = 0;
1251 if(old->module)
1252 {
1253 params_size = old->module->params_size;
1254 }
1255 else
1256 {
1257 dt_iop_module_t *base = dt_iop_get_module(old->op_name);
1258 if(base)
1259 {
1260 params_size = base->params_size;
1261 }
1262 else
1263 {
1264 // nothing else to do
1265 fprintf(stderr, "[_duplicate_history] can't find base module for %s\n", old->op_name);
1266 }
1267 }
1268
1269 if(params_size > 0)
1270 {
1271 new->params = malloc(params_size);
1272 memcpy(new->params, old->params, params_size);
1273 }
1274
1275 new->blend_params = malloc(sizeof(dt_develop_blend_params_t));
1276 memcpy(new->blend_params, old->blend_params, sizeof(dt_develop_blend_params_t));
1277
1278 if(old->forms) new->forms = dt_masks_dup_forms_deep(old->forms, NULL);
1279
1280 result = g_list_prepend(result, new);
1281 }
1282 return g_list_reverse(result); // list was built in reverse order, so un-reverse it
1283 }
1284
1285 #if 0
1286 // for debug
1287 static gchar *_hash_history_to_string(guint8 *hash, const gsize checksum_len)
1288 {
1289 char *hash_text = NULL;
1290 guint8 *p = hash;
1291 for(int i=0; i<checksum_len; i++)
1292 {
1293 uint8_t byte = p[0];
1294 hash_text = dt_util_dstrcat(hash_text, "%02x", byte);
1295 p++;
1296 }
1297 return hash_text;
1298 }
1299 #endif
1300
1301 // if the image has no history return 0
_history_hash_compute_from_db(const int32_t imgid,guint8 ** hash)1302 static gsize _history_hash_compute_from_db(const int32_t imgid, guint8 **hash)
1303 {
1304 if(imgid == -1) return 0;
1305
1306 GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
1307 gsize hash_len = 0;
1308
1309 sqlite3_stmt *stmt;
1310
1311 // get history end
1312 int history_end = 0;
1313 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1314 "SELECT history_end FROM main.images WHERE id = ?1",
1315 -1, &stmt, NULL);
1316 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1317 if(sqlite3_step(stmt) == SQLITE_ROW)
1318 {
1319 if(sqlite3_column_type(stmt, 0) != SQLITE_NULL)
1320 history_end = sqlite3_column_int(stmt, 0);
1321 }
1322 sqlite3_finalize(stmt);
1323
1324 // get history. the active history for an image are all the latest operations (MAX(num))
1325 // which are enabled. this is important here as we want the hash to represent the actual
1326 // developement of the image.
1327 gboolean history_on = FALSE;
1328 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1329 "SELECT operation, op_params, blendop_params, enabled, MAX(num)"
1330 " FROM main.history"
1331 " WHERE imgid = ?1 AND num <= ?2"
1332 " GROUP BY operation, multi_priority"
1333 " ORDER BY num",
1334 -1, &stmt, NULL);
1335 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1336 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, history_end);
1337
1338 while(sqlite3_step(stmt) == SQLITE_ROW)
1339 {
1340 const int enabled = sqlite3_column_int(stmt, 3);
1341 if(enabled)
1342 {
1343 // operation
1344 char *buf = (char *)sqlite3_column_text(stmt, 0);
1345 if(buf) g_checksum_update(checksum, (const guchar *)buf, -1);
1346 // op_params
1347 buf = (char *)sqlite3_column_blob(stmt, 1);
1348 int params_len = sqlite3_column_bytes(stmt, 1);
1349 if(buf) g_checksum_update(checksum, (const guchar *)buf, params_len);
1350 // blendop_params
1351 buf = (char *)sqlite3_column_blob(stmt, 2);
1352 params_len = sqlite3_column_bytes(stmt, 2);
1353 if(buf) g_checksum_update(checksum, (const guchar *)buf, params_len);
1354 history_on = TRUE;
1355 }
1356 }
1357 sqlite3_finalize(stmt);
1358
1359 if(history_on)
1360 {
1361 // get module order
1362 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1363 "SELECT version, iop_list"
1364 " FROM main.module_order"
1365 " WHERE imgid = ?1",
1366 -1, &stmt, NULL);
1367 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1368 if(sqlite3_step(stmt) == SQLITE_ROW)
1369 {
1370 const int version = sqlite3_column_int(stmt, 0);
1371 g_checksum_update(checksum, (const guchar *)&version, sizeof(version));
1372 if(version == DT_IOP_ORDER_CUSTOM)
1373 {
1374 // iop_list
1375 const char *buf = (char *)sqlite3_column_text(stmt, 1);
1376 if(buf) g_checksum_update(checksum, (const guchar *)buf, -1);
1377 }
1378 }
1379 sqlite3_finalize(stmt);
1380
1381 const gsize checksum_len = g_checksum_type_get_length(G_CHECKSUM_MD5);
1382 *hash = g_malloc(checksum_len);
1383 hash_len = checksum_len;
1384 g_checksum_get_digest(checksum, *hash, &hash_len);
1385 }
1386 g_checksum_free(checksum);
1387
1388 return hash_len;
1389 }
1390
dt_history_hash_write_from_history(const int32_t imgid,const dt_history_hash_t type)1391 void dt_history_hash_write_from_history(const int32_t imgid, const dt_history_hash_t type)
1392 {
1393 if(imgid == -1) return;
1394
1395 guint8 *hash = NULL;
1396 gsize hash_len = _history_hash_compute_from_db(imgid, &hash);
1397 if(hash_len)
1398 {
1399 char *fields = NULL;
1400 char *values = NULL;
1401 char *conflict = NULL;
1402 if(type & DT_HISTORY_HASH_BASIC)
1403 {
1404 fields = g_strdup_printf("%s,", "basic_hash");
1405 values = g_strdup("?2,");
1406 conflict = g_strdup("basic_hash=?2,");
1407 }
1408 if(type & DT_HISTORY_HASH_AUTO)
1409 {
1410 fields = dt_util_dstrcat(fields, "%s,", "auto_hash");
1411 values = dt_util_dstrcat(values, "?2,");
1412 conflict = dt_util_dstrcat(conflict, "auto_hash=?2,");
1413 }
1414 if(type & DT_HISTORY_HASH_CURRENT)
1415 {
1416 fields = dt_util_dstrcat(fields, "%s,", "current_hash");
1417 values = dt_util_dstrcat(values, "?2,");
1418 conflict = dt_util_dstrcat(conflict, "current_hash=?2,");
1419 }
1420 // remove the useless last comma
1421 if(fields) fields[strlen(fields) - 1] = '\0';
1422 if(values) values[strlen(values) - 1] = '\0';
1423 if(conflict) conflict[strlen(conflict) - 1] = '\0';
1424
1425 if(fields)
1426 {
1427 sqlite3_stmt *stmt;
1428 #ifdef HAVE_SQLITE_324_OR_NEWER
1429 char *query = g_strdup_printf("INSERT INTO main.history_hash"
1430 " (imgid, %s) VALUES (?1, %s)"
1431 " ON CONFLICT (imgid)"
1432 " DO UPDATE SET %s",
1433 fields, values, conflict);
1434 #else
1435 char *query = NULL;
1436 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1437 "SELECT imgid FROM main.history_hash"
1438 " WHERE imgid = ?1",
1439 -1, &stmt, NULL);
1440 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1441 if(sqlite3_step(stmt) == SQLITE_ROW)
1442 {
1443 sqlite3_finalize(stmt);
1444 query = g_strdup_printf("UPDATE main.history_hash"
1445 " SET %s"
1446 " WHERE imgid = ?1",
1447 conflict);
1448 }
1449 else
1450 {
1451 sqlite3_finalize(stmt);
1452 query = g_strdup_printf("INSERT INTO main.history_hash"
1453 " (imgid, %s) VALUES (?1, %s)",
1454 fields, values);
1455 }
1456 #endif
1457 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1458 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1459 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 2, hash, hash_len, SQLITE_TRANSIENT);
1460 sqlite3_step(stmt);
1461 sqlite3_finalize(stmt);
1462 g_free(query);
1463 g_free(fields);
1464 g_free(values);
1465 g_free(conflict);
1466 }
1467 g_free(hash);
1468 }
1469 }
1470
dt_history_hash_write(const int32_t imgid,dt_history_hash_values_t * hash)1471 void dt_history_hash_write(const int32_t imgid, dt_history_hash_values_t *hash)
1472 {
1473 if(hash->basic || hash->auto_apply || hash->current)
1474 {
1475 sqlite3_stmt *stmt;
1476 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1477 "INSERT OR REPLACE INTO main.history_hash"
1478 " (imgid, basic_hash, auto_hash, current_hash)"
1479 " VALUES (?1, ?2, ?3, ?4)",
1480 -1, &stmt, NULL);
1481 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1482 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 2, hash->basic, hash->basic_len, SQLITE_TRANSIENT);
1483 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 3, hash->auto_apply, hash->auto_apply_len, SQLITE_TRANSIENT);
1484 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 4, hash->current, hash->current_len, SQLITE_TRANSIENT);
1485 sqlite3_step(stmt);
1486 sqlite3_finalize(stmt);
1487 g_free(hash->basic);
1488 g_free(hash->auto_apply);
1489 g_free(hash->current);
1490 }
1491 }
1492
dt_history_hash_read(const int32_t imgid,dt_history_hash_values_t * hash)1493 void dt_history_hash_read(const int32_t imgid, dt_history_hash_values_t *hash)
1494 {
1495 hash->basic = hash->auto_apply = hash->current = NULL;
1496 hash->basic_len = hash->auto_apply_len = hash->current_len = 0;
1497 sqlite3_stmt *stmt;
1498 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1499 "SELECT basic_hash, auto_hash, current_hash"
1500 " FROM main.history_hash"
1501 " WHERE imgid = ?1",
1502 -1, &stmt, NULL);
1503 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1504 if(sqlite3_step(stmt) == SQLITE_ROW)
1505 {
1506 void *buf = (void *)sqlite3_column_blob(stmt, 0);
1507 hash->basic_len = sqlite3_column_bytes(stmt, 0);
1508 if(buf)
1509 {
1510 hash->basic = malloc(hash->basic_len);
1511 memcpy(hash->basic, buf, hash->basic_len);
1512 }
1513 buf = (void *)sqlite3_column_blob(stmt, 1);
1514 hash->auto_apply_len = sqlite3_column_bytes(stmt, 1);
1515 if(buf)
1516 {
1517 hash->auto_apply = malloc(hash->auto_apply_len);
1518 memcpy(hash->auto_apply, buf, hash->auto_apply_len);
1519 }
1520 buf = (void *)sqlite3_column_blob(stmt, 2);
1521 hash->current_len = sqlite3_column_bytes(stmt, 2);
1522 if(buf)
1523 {
1524 hash->current = malloc(hash->current_len);
1525 memcpy(hash->current, buf, hash->current_len);
1526 }
1527 }
1528 sqlite3_finalize(stmt);
1529 }
1530
dt_history_hash_is_mipmap_synced(const int32_t imgid)1531 gboolean dt_history_hash_is_mipmap_synced(const int32_t imgid)
1532 {
1533 gboolean status = FALSE;
1534 if(imgid == -1) return status;
1535 sqlite3_stmt *stmt;
1536 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1537 "SELECT CASE"
1538 " WHEN mipmap_hash == current_hash THEN 1"
1539 " ELSE 0 END AS status"
1540 " FROM main.history_hash"
1541 " WHERE imgid = ?1",
1542 -1, &stmt, NULL);
1543 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1544 if(sqlite3_step(stmt) == SQLITE_ROW)
1545 {
1546 status = sqlite3_column_int(stmt, 0);
1547 }
1548 sqlite3_finalize(stmt);
1549 return status;
1550 }
1551
dt_history_hash_set_mipmap(const int32_t imgid)1552 void dt_history_hash_set_mipmap(const int32_t imgid)
1553 {
1554 if(imgid == -1) return;
1555 sqlite3_stmt *stmt;
1556 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1557 "UPDATE main.history_hash"
1558 " SET mipmap_hash = current_hash"
1559 " WHERE imgid = ?1",
1560 -1, &stmt, NULL);
1561 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
1562 sqlite3_step(stmt);
1563 sqlite3_finalize(stmt);
1564 }
1565
dt_history_hash_get_status(const int32_t imgid)1566 dt_history_hash_t dt_history_hash_get_status(const int32_t imgid)
1567 {
1568 dt_history_hash_t status = 0;
1569 if(imgid == -1) return status;
1570 sqlite3_stmt *stmt;
1571 char *query = g_strdup_printf("SELECT CASE"
1572 " WHEN basic_hash == current_hash THEN %d"
1573 " WHEN auto_hash == current_hash THEN %d"
1574 " WHEN (basic_hash IS NULL OR current_hash != basic_hash) AND"
1575 " (auto_hash IS NULL OR current_hash != auto_hash) THEN %d"
1576 " ELSE %d END AS status"
1577 " FROM main.history_hash"
1578 " WHERE imgid = %d",
1579 DT_HISTORY_HASH_BASIC, DT_HISTORY_HASH_AUTO,
1580 DT_HISTORY_HASH_CURRENT, DT_HISTORY_HASH_BASIC, imgid);
1581 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
1582 query, -1, &stmt, NULL);
1583 if(sqlite3_step(stmt) == SQLITE_ROW)
1584 {
1585 status = sqlite3_column_int(stmt, 0);
1586 }
1587 // if no history_hash basic status
1588 else status = DT_HISTORY_HASH_BASIC;
1589 sqlite3_finalize(stmt);
1590 g_free(query);
1591 return status;
1592 }
1593
dt_history_copy(int imgid)1594 gboolean dt_history_copy(int imgid)
1595 {
1596 // note that this routine does not copy anything, it just setup the copy_paste proxy
1597 // with the needed information that will be used while pasting.
1598
1599 if(imgid <= 0) return FALSE;
1600
1601 darktable.view_manager->copy_paste.copied_imageid = imgid;
1602 darktable.view_manager->copy_paste.full_copy = FALSE;
1603
1604 if(darktable.view_manager->copy_paste.selops)
1605 {
1606 g_list_free(darktable.view_manager->copy_paste.selops);
1607 darktable.view_manager->copy_paste.selops = NULL;
1608 }
1609
1610 // check if images is currently loaded in darkroom
1611 if(dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_write_history(darktable.develop);
1612
1613 return TRUE;
1614 }
1615
dt_history_copy_parts(int imgid)1616 gboolean dt_history_copy_parts(int imgid)
1617 {
1618 if(dt_history_copy(imgid))
1619 {
1620 // we want to copy all history and let user select the parts needed
1621 darktable.view_manager->copy_paste.full_copy = TRUE;
1622
1623 // run dialog, it will insert into selops the selected moduel
1624
1625 if(dt_gui_hist_dialog_new(&(darktable.view_manager->copy_paste), imgid, TRUE) == GTK_RESPONSE_CANCEL)
1626 return FALSE;
1627 return TRUE;
1628 }
1629 else
1630 return FALSE;
1631 }
1632
dt_history_paste_on_list(const GList * list,gboolean undo)1633 gboolean dt_history_paste_on_list(const GList *list, gboolean undo)
1634 {
1635 if(darktable.view_manager->copy_paste.copied_imageid <= 0) return FALSE;
1636 if(!list) // do we have any images to receive the pasted history?
1637 return FALSE;
1638
1639 const int mode = dt_conf_get_int("plugins/lighttable/copy_history/pastemode");
1640 gboolean merge = FALSE;
1641 if(mode == 0) merge = TRUE;
1642
1643 if(undo) dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
1644 for(GList *l = (GList *)list; l; l = g_list_next(l))
1645 {
1646 const int dest = GPOINTER_TO_INT(l->data);
1647 dt_history_copy_and_paste_on_image(darktable.view_manager->copy_paste.copied_imageid,
1648 dest, merge,
1649 darktable.view_manager->copy_paste.selops,
1650 darktable.view_manager->copy_paste.copy_iop_order,
1651 darktable.view_manager->copy_paste.full_copy);
1652 }
1653 if(undo) dt_undo_end_group(darktable.undo);
1654
1655 // In darkroom and if there is a copy of the iop-order we need to rebuild the pipe
1656 // to take into account the possible new order of modules.
1657
1658 const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager);
1659
1660 if(cv->view(cv) == DT_VIEW_DARKROOM
1661 && darktable.view_manager->copy_paste.copy_iop_order)
1662 {
1663 dt_dev_pixelpipe_rebuild(darktable.develop);
1664 }
1665
1666 return TRUE;
1667 }
1668
dt_history_paste_parts_on_list(const GList * list,gboolean undo)1669 gboolean dt_history_paste_parts_on_list(const GList *list, gboolean undo)
1670 {
1671 if(darktable.view_manager->copy_paste.copied_imageid <= 0) return FALSE;
1672 if(!list) // do we have any images to receive the pasted history?
1673 return FALSE;
1674
1675 const int mode = dt_conf_get_int("plugins/lighttable/copy_history/pastemode");
1676 gboolean merge = FALSE;
1677 if(mode == 0) merge = TRUE;
1678
1679 // at the time the dialog is started, some signals are sent and this in turn call
1680 // back dt_view_get_images_to_act_on() which free list and create a new one.
1681
1682 GList *l_copy = g_list_copy((GList *)list);
1683
1684 // we launch the dialog
1685 const int res = dt_gui_hist_dialog_new(&(darktable.view_manager->copy_paste),
1686 darktable.view_manager->copy_paste.copied_imageid, FALSE);
1687
1688 if(res != GTK_RESPONSE_OK)
1689 {
1690 g_list_free(l_copy);
1691 return FALSE;
1692 }
1693
1694 if(undo) dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
1695 for (const GList *l = l_copy; l; l = g_list_next(l))
1696 {
1697 const int dest = GPOINTER_TO_INT(l->data);
1698 dt_history_copy_and_paste_on_image(darktable.view_manager->copy_paste.copied_imageid,
1699 dest, merge,
1700 darktable.view_manager->copy_paste.selops,
1701 darktable.view_manager->copy_paste.copy_iop_order,
1702 darktable.view_manager->copy_paste.full_copy);
1703 }
1704 if(undo) dt_undo_end_group(darktable.undo);
1705
1706 g_list_free(l_copy);
1707
1708 // In darkroom and if there is a copy of the iop-order we need to rebuild the pipe
1709 // to take into account the possible new order of modules.
1710
1711 const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager);
1712
1713 if(cv->view(cv) == DT_VIEW_DARKROOM
1714 && darktable.view_manager->copy_paste.copy_iop_order)
1715 {
1716 dt_dev_pixelpipe_rebuild(darktable.develop);
1717 }
1718
1719 return TRUE;
1720 }
1721
dt_history_delete_on_list(const GList * list,gboolean undo)1722 gboolean dt_history_delete_on_list(const GList *list, gboolean undo)
1723 {
1724 if(!list) // do we have any images on which to operate?
1725 return FALSE;
1726
1727 if(undo) dt_undo_start_group(darktable.undo, DT_UNDO_LT_HISTORY);
1728
1729 for(GList *l = (GList *)list; l; l = g_list_next(l))
1730 {
1731 const int imgid = GPOINTER_TO_INT(l->data);
1732 dt_undo_lt_history_t *hist = dt_history_snapshot_item_init();
1733
1734 hist->imgid = imgid;
1735 dt_history_snapshot_undo_create(hist->imgid, &hist->before, &hist->before_history_end);
1736
1737 dt_history_delete_on_image_ext(imgid, FALSE);
1738
1739 dt_history_snapshot_undo_create(hist->imgid, &hist->after, &hist->after_history_end);
1740 dt_undo_record(darktable.undo, NULL, DT_UNDO_LT_HISTORY, (dt_undo_data_t)hist, dt_history_snapshot_undo_pop,
1741 dt_history_snapshot_undo_lt_history_data_free);
1742
1743 /* update the aspect ratio if the current sorting is based on aspect ratio, otherwise the aspect ratio will be
1744 recalculated when the mimpap will be recreated */
1745 if(darktable.collection->params.sort == DT_COLLECTION_SORT_ASPECT_RATIO)
1746 dt_image_set_aspect_ratio(imgid, FALSE);
1747 }
1748
1749 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
1750
1751 if(undo) dt_undo_end_group(darktable.undo);
1752 return TRUE;
1753 }
1754
1755 #undef DT_IOP_ORDER_INFO
1756 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
1757 // vim: shiftwidth=2 expandtab tabstop=2 cindent
1758 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1759