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