void dt_styles_create_from_style (const char *name, const char *newname, const char *description, GList *filter, int imgid, GList *update) { sqlite3_stmt *stmt; int id=0; int oldid=0; oldid = dt_styles_get_id_by_name(name); if(oldid == 0) return; /* create the style header */ if (!dt_styles_create_style_header(newname, description)) return; if ((id=dt_styles_get_id_by_name(newname)) != 0) { if (filter) { GList *list=filter; char tmp[64]; char include[2048]= {0}; g_strlcat(include,"num in (", 2048); do { if(list!=g_list_first(list)) g_strlcat(include,",", 2048); sprintf(tmp,"%ld",(glong)list->data); g_strlcat(include,tmp, 2048); } while ((list=g_list_next(list))); g_strlcat(include,")", 2048); char query[4096]= {0}; sprintf(query,"insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid=?2 and %s",include); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); } else DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where style_id=?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, oldid); sqlite3_step (stmt); sqlite3_finalize (stmt); /* insert items from imgid if defined */ _dt_style_update_from_image(id,imgid,filter,update); _dt_style_cleanup_multi_instance(id); /* backup style to disk */ char stylesdir[1024]; dt_loc_get_user_config_dir(stylesdir, 1024); g_strlcat(stylesdir,"/styles",1024); g_mkdir_with_parents(stylesdir,00755); dt_styles_save_to_file(newname,stylesdir,FALSE); char tmp_accel[1024]; gchar* tmp_name = g_strdup(newname); // freed by _destroy_style_shortcut_callback snprintf(tmp_accel,1024,C_("accel", "styles/apply %s"),newname); dt_accel_register_global( tmp_accel, 0, 0); GClosure *closure; closure = g_cclosure_new( G_CALLBACK(_apply_style_shortcut_callback), tmp_name, _destroy_style_shortcut_callback); dt_accel_connect_global(tmp_accel, closure); dt_control_log(_("style named '%s' successfully created"),newname); } }
gboolean dt_styles_exists (const char *name) { return (dt_styles_get_id_by_name(name))!=0?TRUE:FALSE; }
void dt_styles_update (const char *name, const char *newname, const char *newdescription, GList *filter, int imgid, GList *update) { sqlite3_stmt *stmt; int id=0; gchar *desc = NULL; id = dt_styles_get_id_by_name(name); if(id == 0) return; desc = dt_styles_get_description (name); if ((g_strcmp0(name, newname)) || (g_strcmp0(desc, newdescription))) { DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update styles set name=?1, description=?2 where rowid=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, newname, strlen (newname), SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, newdescription, strlen (newdescription), SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id); sqlite3_step(stmt); sqlite3_finalize(stmt); } if (filter) { GList *list=filter; char tmp[64]; char include[2048] = {0}; g_strlcat(include,"num not in (", 2048); do { if(list!=g_list_first(list)) g_strlcat(include, ",", 2048); sprintf(tmp, "%ld", (glong)list->data); g_strlcat(include, tmp, 2048); } while ((list=g_list_next(list))); g_strlcat(include,")", 2048); char query[4096]= {0}; sprintf(query,"delete from style_items where styleid=?1 and %s", include); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id); sqlite3_step(stmt); sqlite3_finalize(stmt); } _dt_style_update_from_image(id,imgid,filter,update); _dt_style_cleanup_multi_instance(id); /* backup style to disk */ char stylesdir[1024]; dt_loc_get_user_config_dir(stylesdir, 1024); g_strlcat(stylesdir,"/styles",1024); g_mkdir_with_parents(stylesdir,00755); dt_styles_save_to_file(newname,stylesdir,TRUE); /* delete old accelerator and create a new one */ //TODO: should better use dt_accel_rename_global() to keep the old accel_key untouched, but it seems to be buggy if (g_strcmp0(name, newname)) { char tmp_accel[1024]; snprintf(tmp_accel, 1024, C_("accel", "styles/apply %s"), name); dt_accel_deregister_global(tmp_accel); gchar* tmp_name = g_strdup(newname); // freed by _destroy_style_shortcut_callback snprintf(tmp_accel, 1024, C_("accel", "styles/apply %s"), newname); dt_accel_register_global( tmp_accel, 0, 0); GClosure *closure; closure = g_cclosure_new( G_CALLBACK(_apply_style_shortcut_callback), tmp_name, _destroy_style_shortcut_callback); dt_accel_connect_global(tmp_accel, closure); } g_free(desc); }
void dt_styles_save_to_file(const char *style_name,const char *filedir,gboolean overwrite) { int rc = 0; char stylename[520]; sqlite3_stmt *stmt; snprintf(stylename,512,"%s/%s.dtstyle",filedir,style_name); // check if file exists if( g_file_test(stylename, G_FILE_TEST_EXISTS) == TRUE ) { if(overwrite) { if(unlink(stylename)) { dt_control_log(_("failed to overwrite style file for %s"),style_name); return; } } else { dt_control_log(_("style file for %s exists"),style_name); return; } } if ( !dt_styles_exists (style_name) ) return; xmlTextWriterPtr writer = xmlNewTextWriterFilename(stylename, 0); if (writer == NULL) { fprintf(stderr,"[dt_styles_save_to_file] Error creating the xml writer\n, path: %s", stylename); return; } rc = xmlTextWriterStartDocument(writer, NULL, "ISO-8859-1", NULL); if (rc < 0) { fprintf(stderr,"[dt_styles_save_to_file]: Error on encoding setting"); return; } xmlTextWriterStartElement(writer, BAD_CAST "darktable_style"); xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST "1.0"); xmlTextWriterStartElement(writer, BAD_CAST "info"); xmlTextWriterWriteFormatElement(writer, BAD_CAST "name", "%s", style_name); xmlTextWriterWriteFormatElement(writer, BAD_CAST "description", "%s", dt_styles_get_description(style_name)); xmlTextWriterEndElement(writer); xmlTextWriterStartElement(writer, BAD_CAST "style"); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid =?1",-1, &stmt,NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt,1,dt_styles_get_id_by_name(style_name)); while (sqlite3_step (stmt) == SQLITE_ROW) { xmlTextWriterStartElement(writer, BAD_CAST "plugin"); xmlTextWriterWriteFormatElement(writer, BAD_CAST "num", "%d", sqlite3_column_int(stmt,0)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "module", "%d", sqlite3_column_int(stmt,1)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "operation", "%s", sqlite3_column_text(stmt,2)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "op_params", "%s", dt_style_encode(stmt,3)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "enabled", "%d", sqlite3_column_int(stmt,4)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "blendop_params", "%s", dt_style_encode(stmt,5)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "blendop_version", "%d", sqlite3_column_int(stmt,6)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "multi_priority", "%d", sqlite3_column_int(stmt,7)); xmlTextWriterWriteFormatElement(writer, BAD_CAST "multi_name", "%s", sqlite3_column_text(stmt,8)); xmlTextWriterEndElement(writer); } sqlite3_finalize(stmt); xmlTextWriterEndDocument(writer); xmlFreeTextWriter(writer); dt_control_log(_("style %s was successfully saved"),style_name); }
void dt_styles_apply_to_image(const char *name,gboolean duplicate, int32_t imgid) { int id=0; sqlite3_stmt *stmt; if ((id=dt_styles_get_id_by_name(name)) != 0) { /* check if we should make a duplicate before applying style */ if (duplicate) imgid = dt_image_duplicate (imgid); /* if merge onto history stack, lets find history offest in destination image */ int32_t offs = 0; #if 1 { /* 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, 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, imgid); sqlite3_step (stmt); } #endif 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, imgid); 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,imgid); /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, 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(imgid); /* remove old obsolete thumbnails */ dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); /* redraw center view to update visible mipmaps */ dt_control_queue_redraw_center(); } }
GList *dt_styles_get_item_list(const char *name, gboolean params, int imgid) { GList *result = NULL; sqlite3_stmt *stmt; int id = 0; if((id = dt_styles_get_id_by_name(name)) != 0) { if(params) DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select num, module, operation, enabled, op_params, blendop_params, " "multi_name from style_items where styleid=?1 order by num desc", -1, &stmt, NULL); else if(imgid != -1) { // get all items from the style // UNION // get all items from history, not in the style : select only the last operation, that is max(num) DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "select num, module, operation, enabled, (select max(num) from history where imgid=?2 and " "operation=style_items.operation group by multi_priority),multi_name from style_items where " "styleid=?1 UNION select " "-1,history.module,history.operation,history.enabled,history.num,multi_name from history where " "imgid=?2 and history.enabled=1 and (history.operation not in (select operation from style_items " "where styleid=?1) or (history.op_params not in (select op_params from style_items where " "styleid=?1 and operation=history.operation)) or (history.blendop_params not in (select " "blendop_params from style_items where styleid=?1 and operation=history.operation))) group by " "operation having max(num) order by num desc", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); } else DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select num, module, operation, enabled, 0, " "multi_name from style_items where " "styleid=?1 order by num desc", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id); while(sqlite3_step(stmt) == SQLITE_ROW) { char name[512] = { 0 }; dt_style_item_t *item = g_malloc(sizeof(dt_style_item_t)); if(sqlite3_column_type(stmt, 0) == SQLITE_NULL) item->num = -1; else item->num = sqlite3_column_int(stmt, 0); item->selimg_num = -1; item->module_version = sqlite3_column_int(stmt, 1); item->enabled = sqlite3_column_int(stmt, 3); if(params) { // when we get the parameters we do not want to get the operation localized as this // is used to compare against the internal module name. const char *multi_name = (const char *)sqlite3_column_text(stmt, 6); if(!(multi_name && *multi_name)) g_snprintf(name, sizeof(name), "%s", sqlite3_column_text(stmt, 2)); else g_snprintf(name, sizeof(name), "%s %s", sqlite3_column_text(stmt, 2), multi_name); const unsigned char *op_blob = sqlite3_column_blob(stmt, 4); const int32_t op_len = sqlite3_column_bytes(stmt, 4); const unsigned char *bop_blob = sqlite3_column_blob(stmt, 5); const int32_t bop_len = sqlite3_column_bytes(stmt, 5); item->params = malloc(op_len); memcpy(item->params, op_blob, op_len); item->blendop_params = malloc(bop_len); memcpy(item->blendop_params, bop_blob, bop_len); } else { const char *multi_name = (const char *)sqlite3_column_text(stmt, 5); gboolean has_multi_name = FALSE; if(multi_name && *multi_name && strcmp(multi_name, "0") != 0) has_multi_name = TRUE; if(has_multi_name) g_snprintf(name, sizeof(name), "%s %s (%s)", dt_iop_get_localized_name((gchar *)sqlite3_column_text(stmt, 2)), multi_name, (sqlite3_column_int(stmt, 3) != 0) ? _("on") : _("off")); else g_snprintf(name, sizeof(name), "%s (%s)", dt_iop_get_localized_name((gchar *)sqlite3_column_text(stmt, 2)), (sqlite3_column_int(stmt, 3) != 0) ? _("on") : _("off")); item->params = NULL; item->blendop_params = NULL; if(imgid != -1 && sqlite3_column_type(stmt, 4) != SQLITE_NULL) item->selimg_num = sqlite3_column_int(stmt, 4); } item->name = g_strdup(name); result = g_list_append(result, item); } sqlite3_finalize(stmt); } return result; }
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, sizeof(ntag), "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(); } }
gboolean dt_styles_create_from_image(const char *name, const char *description, int32_t imgid, GList *filter) { int id = 0; sqlite3_stmt *stmt; /* first create the style header */ if(!dt_styles_create_style_header(name, description)) return FALSE; if((id = dt_styles_get_id_by_name(name)) != 0) { /* create the style_items from source image history stack */ if(filter) { GList *list = filter; char tmp[64]; char include[2048] = { 0 }; g_strlcat(include, "num in (", sizeof(include)); do { if(list != g_list_first(list)) g_strlcat(include, ",", sizeof(include)); snprintf(tmp, sizeof(tmp), "%d", GPOINTER_TO_INT(list->data)); g_strlcat(include, tmp, sizeof(include)); } while((list = g_list_next(list))); g_strlcat(include, ")", sizeof(include)); char query[4096] = { 0 }; snprintf(query, sizeof(query), "insert into style_items " "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_" "version,multi_priority,multi_name) select ?1, " "num,module,operation,op_params,enabled,blendop_params,blendop_version," "multi_priority,multi_name from history where imgid=?2 and %s", include); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); } else DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into style_items " "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_" "version,multi_priority,multi_name) select ?1, " "num,module,operation,op_params,enabled,blendop_params,blendop_version," "multi_priority,multi_name from history where imgid=?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); _dt_style_cleanup_multi_instance(id); /* backup style to disk */ char stylesdir[PATH_MAX] = { 0 }; dt_loc_get_user_config_dir(stylesdir, sizeof(stylesdir)); g_strlcat(stylesdir, "/styles", sizeof(stylesdir)); g_mkdir_with_parents(stylesdir, 00755); dt_styles_save_to_file(name, stylesdir, FALSE); char tmp_accel[1024]; gchar *tmp_name = g_strdup(name); // freed by _destroy_style_shortcut_callback snprintf(tmp_accel, sizeof(tmp_accel), C_("accel", "styles/apply %s"), name); dt_accel_register_global(tmp_accel, 0, 0); GClosure *closure; closure = g_cclosure_new(G_CALLBACK(_apply_style_shortcut_callback), tmp_name, _destroy_style_shortcut_callback); dt_accel_connect_global(tmp_accel, closure); return TRUE; } return FALSE; }