int dt_history_load_and_apply_on_selection (gchar *filename) { int res=0; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select * from selected_images", -1, &stmt, NULL); while(sqlite3_step(stmt) == SQLITE_ROW) { int imgid = sqlite3_column_int(stmt, 0); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, (int32_t)imgid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); if(img) { if (dt_exif_xmp_read(img, filename, 1)) { res=1; break; } /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items (darktable.develop); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); } } sqlite3_finalize(stmt); return res; }
void dt_history_delete_on_image(int32_t imgid) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from mask where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); remove_preset_flag(imgid); /* if current image in develop reload history */ if (dt_dev_is_current_image (darktable.develop, imgid)) dt_dev_reload_history_items (darktable.develop); /* make sure mipmaps are recomputed */ dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); /* remove darktable|style|* tags */ dt_tag_detach_by_string("darktable|style%", imgid); }
void dt_styles_apply_to_image(const char *name,gboolean duplicate, int32_t imgid) { int id=0; sqlite3_stmt *stmt; int32_t newimgid; if ((id=dt_styles_get_id_by_name(name)) != 0) { /* check if we should make a duplicate before applying style */ if (duplicate) { newimgid = dt_image_duplicate (imgid); if(newimgid != -1) dt_history_copy_and_paste_on_image(imgid, newimgid, FALSE, NULL); } else newimgid = imgid; /* merge onto history stack, let's find history offest in destination image */ int32_t offs = 0; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT MAX(num)+1 FROM history WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newimgid); if (sqlite3_step (stmt) == SQLITE_ROW) offs = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); /* copy history items from styles onto image */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history (imgid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num+?2,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newimgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id); sqlite3_step (stmt); sqlite3_finalize (stmt); /* add tag */ guint tagid=0; gchar ntag[512]= {0}; g_snprintf(ntag,512,"darktable|style|%s",name); if (dt_tag_new(ntag,&tagid)) dt_tag_attach(tagid,newimgid); /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, newimgid)) { dt_dev_reload_history_items (darktable.develop); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); } /* update xmp file */ dt_image_synch_xmp(newimgid); /* remove old obsolete thumbnails */ dt_mipmap_cache_remove(darktable.mipmap_cache, newimgid); /* redraw center view to update visible mipmaps */ dt_control_queue_redraw_center(); } }
int dt_history_copy_and_paste_on_image (int32_t imgid, int32_t dest_imgid, gboolean merge) { sqlite3_stmt *stmt; if(imgid==dest_imgid) return 1; if(imgid==-1) { dt_control_log(_("you need to copy history from an image before you paste it onto another")); return 1; } /* if merge onto history stack, lets find history offest in destination image */ int32_t offs = 0; if (merge) { /* apply on top of history stack */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(num) from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); if (sqlite3_step (stmt) == SQLITE_ROW) offs = sqlite3_column_int (stmt, 0); } else { /* replace history stack */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step (stmt); } sqlite3_finalize (stmt); /* add the history items to stack offest */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history (imgid, num, module, operation, op_params, enabled, blendop_params, blendop_version) select ?1, num+?2, module, operation, op_params, enabled, blendop_params, blendop_version from history where imgid = ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, dest_imgid)) { dt_dev_reload_history_items (darktable.develop); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); } /* update xmp file */ dt_image_synch_xmp(dest_imgid); dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid); return 0; }
static gboolean _lib_filmstrip_copy_history_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)data; int32_t mouse_over_id = dt_control_get_mouse_over_id(); if(mouse_over_id <= 0) return FALSE; strip->history_copy_imgid = mouse_over_id; /* check if images is currently loaded in darkroom */ if(dt_dev_is_current_image(darktable.develop, mouse_over_id)) dt_dev_write_history(darktable.develop); return TRUE; }
static gboolean _lib_filmstrip_duplicate_image_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { int32_t mouse_over_id = dt_control_get_mouse_over_id(); if(mouse_over_id <= 0) return FALSE; /* check if images is currently loaded in darkroom */ if(dt_dev_is_current_image(darktable.develop, mouse_over_id)) dt_dev_write_history(darktable.develop); int32_t newimgid = dt_image_duplicate(mouse_over_id); if(newimgid != -1) dt_history_copy_and_paste_on_image(mouse_over_id, newimgid, FALSE, NULL); dt_control_queue_redraw_center(); return TRUE; }
int dt_history_load_and_apply(int imgid, gchar *filename, int history_only) { int res = 0; dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'w'); if(img) { if(dt_exif_xmp_read(img, filename, history_only)) return 1; /* if current image in develop reload history */ if(dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items(darktable.develop); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); } return res; }
void dt_styles_apply_to_image(const char *name,gboolean duplicate, int32_t imgid) { int id=0; sqlite3_stmt *stmt; int32_t newimgid; if ((id=dt_styles_get_id_by_name(name)) != 0) { /* check if we should make a duplicate before applying style */ if (duplicate) { newimgid = dt_image_duplicate (imgid); if(newimgid != -1) dt_history_copy_and_paste_on_image(imgid, newimgid, FALSE, NULL); } else newimgid = imgid; /* merge onto history stack, let's find history offest in destination image */ int32_t offs = 0; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT MAX(num)+1 FROM history WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newimgid); if (sqlite3_step (stmt) == SQLITE_ROW) offs = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); /* delete all items from the temp styles_items, this table is used only to get a ROWNUM of the results */ DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM memory.style_items",NULL,NULL,NULL); /* copy history items from styles onto temp table */ DT_DEBUG_SQLITE3_PREPARE_V2 (dt_database_get(darktable.db), "INSERT INTO MEMORY.style_items SELECT * FROM style_items WHERE styleid=?1 ORDER BY multi_priority DESC;", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id); sqlite3_step (stmt); sqlite3_finalize (stmt); /* copy the style items into the history */ DT_DEBUG_SQLITE3_PREPARE_V2 (dt_database_get(darktable.db), "INSERT INTO history (imgid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) SELECT ?1,?2+rowid,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name FROM MEMORY.style_items", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newimgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs); sqlite3_step (stmt); sqlite3_finalize (stmt); /* add tag */ guint tagid=0; gchar ntag[512]= {0}; g_snprintf(ntag,512,"darktable|style|%s",name); if (dt_tag_new(ntag,&tagid)) dt_tag_attach(tagid,newimgid); /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, newimgid)) { dt_dev_reload_history_items (darktable.develop); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); } /* update xmp file */ dt_image_synch_xmp(newimgid); /* remove old obsolete thumbnails */ dt_mipmap_cache_remove(darktable.mipmap_cache, newimgid); /* if we have created a duplicate, reset collected images */ if (duplicate) dt_control_signal_raise(darktable.signals, DT_SIGNAL_COLLECTION_CHANGED); /* redraw center view to update visible mipmaps */ dt_control_queue_redraw_center(); } }
int dt_history_copy_and_paste_on_image (int32_t imgid, int32_t dest_imgid, gboolean merge, GList *ops) { sqlite3_stmt *stmt; if(imgid==dest_imgid) return 1; if(imgid==-1) { dt_control_log(_("you need to copy history from an image before you paste it onto another")); return 1; } /* if merge onto history stack, lets find history offest in destination image */ int32_t offs = 0; if (merge) { /* apply on top of history stack */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT MAX(num)+1 FROM history WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); if (sqlite3_step (stmt) == SQLITE_ROW) offs = sqlite3_column_int (stmt, 0); } else { /* replace history stack */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step (stmt); } sqlite3_finalize (stmt); // prepare SQL request char req[2048]; strcpy (req, "insert into history (imgid, num, module, operation, op_params, enabled, blendop_params, blendop_version, multi_name, multi_priority) select ?1, num+?2, module, operation, op_params, enabled, blendop_params, blendop_version, multi_name, multi_priority from history where imgid = ?3"); // Add ops selection if any format: ... and num in (val1, val2) if (ops) { GList *l = ops; int first = 1; strcat (req, " and num in ("); while (l) { unsigned int value = GPOINTER_TO_UINT(l->data); char v[30]; if (!first) strcat (req, ","); snprintf (v, 30, "%u", value); strcat (req, v); first=0; l = g_list_next(l); } strcat (req, ")"); } /* add the history items to stack offest */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), req, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); if (merge && ops) _dt_history_cleanup_multi_instance(dest_imgid, offs); //we have to copy masks too //what to do with existing masks ? if (merge) { //there's very little chance that we will have same shapes id. //but we may want to handle this case anyway //and it's not trivial at all ! } else { //let's remove all existing shapes DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from mask where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); } //let's copy now strcpy (req, "insert into mask (imgid, formid, form, name, version, points, points_count, source) select ?1, formid, form, name, version, points, points_count, source from mask where imgid = ?2"); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), req, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, dest_imgid)) { dt_dev_reload_history_items (darktable.develop); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); } /* update xmp file */ dt_image_synch_xmp(dest_imgid); dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid); return 0; }
int dt_history_copy_and_paste_on_image(int32_t imgid, int32_t dest_imgid, gboolean merge, GList *ops) { sqlite3_stmt *stmt; if(imgid == dest_imgid) return 1; if(imgid == -1) { dt_control_log(_("you need to copy history from an image before you paste it onto another")); return 1; } // be sure the current history is written before pasting some other history data const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager); if(cv->view((dt_view_t *)cv) == DT_VIEW_DARKROOM) dt_dev_write_history(darktable.develop); /* if merge onto history stack, lets find history offest in destination image */ int32_t offs = 0; if(merge) { /* apply on top of history stack */ // first trim the stack to get rid of whatever is above the selected entry DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM main.history WHERE imgid = ?1 AND num >= (SELECT history_end " "FROM main.images WHERE id = imgid)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT IFNULL(MAX(num), -1)+1 FROM main.history WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); if(sqlite3_step(stmt) == SQLITE_ROW) offs = sqlite3_column_int(stmt, 0); } else { /* replace history stack */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM main.history WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step(stmt); } sqlite3_finalize(stmt); /* delete all items from the temp styles_items, this table is used only to get a ROWNUM of the results */ DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM memory.style_items", NULL, NULL, NULL); /* copy history items from styles onto temp table */ // prepare SQL request char req[2048]; g_strlcpy(req, "INSERT INTO memory.style_items (num, module, operation, op_params, enabled, blendop_params, " "blendop_version, multi_name, multi_priority) SELECT num, module, operation, " "op_params, enabled, blendop_params, blendop_version, multi_name, multi_priority FROM " "main.history WHERE imgid = ?1", sizeof(req)); // Add ops selection if any format: ... and num in (val1, val2) if(ops) { GList *l = ops; int first = 1; g_strlcat(req, " AND num IN (", sizeof(req)); while(l) { unsigned int value = GPOINTER_TO_UINT(l->data); char v[30]; if(!first) g_strlcat(req, ",", sizeof(req)); snprintf(v, sizeof(v), "%u", value); g_strlcat(req, v, sizeof(req)); first = 0; l = g_list_next(l); } g_strlcat(req, ")", sizeof(req)); } DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), req, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); /* copy the history items into the history of the dest image */ /* note: rowid starts at 1 while num has to start at 0! */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "INSERT INTO main.history " "(imgid,num,module,operation,op_params,enabled,blendop_params,blendop_" "version,multi_priority,multi_name) SELECT " "?1,?2+rowid-1,module,operation,op_params,enabled,blendop_params,blendop_" "version,multi_priority,multi_name FROM memory.style_items", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs); sqlite3_step(stmt); sqlite3_finalize(stmt); if(merge && ops) _dt_history_cleanup_multi_instance(dest_imgid, offs); // we have to copy masks too // what to do with existing masks ? if(merge) { // there's very little chance that we will have same shapes id. // but we may want to handle this case anyway // and it's not trivial at all ! } else { // let's remove all existing shapes DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM main.mask WHERE imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); } // let's copy now g_strlcpy(req, "INSERT INTO main.mask (imgid, formid, form, name, version, points, points_count, source) SELECT " "?1, formid, form, name, version, points, points_count, source FROM main.mask WHERE imgid = ?2", sizeof(req)); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), req, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); // always make the whole stack active DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "UPDATE main.images SET history_end = (SELECT MAX(num) + 1 FROM main.history " "WHERE imgid = ?1) WHERE id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dest_imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); /* if current image in develop reload history */ if(dt_dev_is_current_image(darktable.develop, dest_imgid)) { dt_dev_reload_history_items(darktable.develop); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); } /* update xmp file */ dt_image_synch_xmp(dest_imgid); dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid); return 0; }