static void edit_preset_response(GtkDialog *dialog, gint response_id, dt_gui_presets_edit_dialog_t *g) { gint is_new = 0; if(response_id == GTK_RESPONSE_ACCEPT) { sqlite3_stmt *stmt; const gchar *name = gtk_entry_get_text(g->name); if(((g->old_id >= 0) && (strcmp(g->original_name, name) != 0)) || (g->old_id < 0)) { if(strcmp(_("new preset"), name) == 0 || !(name && *name)) { // show error dialog GtkWidget *window = dt_ui_main_window(darktable.gui->ui); GtkWidget *dlg_changename = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("please give preset a name")); gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed preset")); gtk_dialog_run(GTK_DIALOG(dlg_changename)); gtk_widget_destroy(dlg_changename); return; } // editing existing preset with different name or store new preset -> check for a preset with the same // name: DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "select name from presets where name = ?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->module->op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->module->version()); if(sqlite3_step(stmt) == SQLITE_ROW) { sqlite3_finalize(stmt); // show overwrite question dialog GtkWidget *window = dt_ui_main_window(darktable.gui->ui); GtkWidget *dlg_overwrite = gtk_message_dialog_new( GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("preset `%s' already exists.\ndo you want to overwrite?"), name); gtk_window_set_title(GTK_WINDOW(dlg_overwrite), _("overwrite preset?")); gint dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg_overwrite)); gtk_widget_destroy(dlg_overwrite); // if result is BUTTON_NO exit without destroy dialog, to permit other name if(dlg_ret == GTK_RESPONSE_NO) return; } else { is_new = 1; sqlite3_finalize(stmt); } } if(g->old_id >= 0) { // now delete old preset: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, g->original_name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->module->op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->module->version()); sqlite3_step(stmt); sqlite3_finalize(stmt); } if(is_new == 0) { // delete preset, so we can re-insert the new values: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->module->op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->module->version()); sqlite3_step(stmt); sqlite3_finalize(stmt); } // rename accelerators char path[1024]; snprintf(path, sizeof(path), "%s/%s", _("preset"), g->original_name); dt_accel_rename_preset_iop(g->module, path, name); // commit all the user input fields DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "INSERT INTO presets (name, description, operation, op_version, op_params, enabled, " "blendop_params, blendop_version, multi_priority, multi_name, " "model, maker, lens, iso_min, iso_max, exposure_min, exposure_max, aperture_min, aperture_max, " "focal_length_min, focal_length_max, writeprotect, autoapply, filter, def, format) " "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, 0, '', ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, " "?19, 0, ?20, ?21, 0, ?22)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, gtk_entry_get_text(g->description), -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, g->module->op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, g->module->version()); DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 5, g->module->params, g->module->params_size, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 6, g->module->enabled); DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 7, g->module->blend_params, sizeof(dt_develop_blend_params_t), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 8, dt_develop_blend_version()); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 9, gtk_entry_get_text(GTK_ENTRY(g->model)), -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 10, gtk_entry_get_text(GTK_ENTRY(g->maker)), -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 11, gtk_entry_get_text(GTK_ENTRY(g->lens)), -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 12, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_min))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 13, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_max))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 14, dt_gui_presets_exposure_value[dt_bauhaus_combobox_get(g->exposure_min)]); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 15, dt_gui_presets_exposure_value[dt_bauhaus_combobox_get(g->exposure_max)]); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 16, dt_gui_presets_aperture_value[dt_bauhaus_combobox_get(g->aperture_min)]); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 17, dt_gui_presets_aperture_value[dt_bauhaus_combobox_get(g->aperture_max)]); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 18, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_min))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 19, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_max))); DT_DEBUG_SQLITE3_BIND_INT(stmt, 20, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->autoapply))); DT_DEBUG_SQLITE3_BIND_INT(stmt, 21, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->filter))); int format = 0; for(int k = 0; k < 3; k++) format += gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->format_btn[k])) * dt_gui_presets_format_flag[k]; DT_DEBUG_SQLITE3_BIND_INT(stmt, 22, format); sqlite3_step(stmt); sqlite3_finalize(stmt); dt_gui_store_last_preset(name); } gtk_widget_destroy(GTK_WIDGET(dialog)); g_free(g->original_name); free(g); }
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 id=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, newname, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, newdescription, -1, 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 (", 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), "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[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(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, sizeof(tmp_accel), 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, sizeof(tmp_accel), 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); }
int dt_film_import(const char *dirname) { int rc; sqlite3_stmt *stmt; GError *error = NULL; /* initialize a film object*/ dt_film_t *film = (dt_film_t *)malloc(sizeof(dt_film_t)); dt_film_init(film); film->id = -1; /* lookup if film exists and reuse id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT id FROM main.film_rolls WHERE folder = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, -1, SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); /* if we didn't find an id, lets instantiate a new filmroll */ if(film->id <= 0) { char datetime[20]; dt_gettime(datetime, sizeof(datetime)); /* insert a new film roll into database */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "INSERT INTO main.film_rolls (id, datetime_accessed, folder) VALUES " "(NULL, ?1, ?2)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, datetime, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dirname, -1, SQLITE_STATIC); rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) fprintf(stderr, "[film_import] failed to insert film roll! %s\n", sqlite3_errmsg(dt_database_get(darktable.db))); sqlite3_finalize(stmt); /* requery for filmroll and fetch new id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT id FROM main.film_rolls WHERE folder=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, -1, SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } /* bail out if we got troubles */ if(film->id <= 0) { // if the film is empty => remove it again. if(dt_film_is_empty(film->id)) { dt_film_remove(film->id); } dt_film_cleanup(film); free(film); return 0; } // when called without job system running the import will be done synchronously and destroy the film object int filmid = film->id; /* at last put import film job on queue */ film->last_loaded = 0; g_strlcpy(film->dirname, dirname, sizeof(film->dirname)); char *last = &film->dirname[strlen(film->dirname) - 1]; if(*last == '/' && last != film->dirname) *last = '\0'; // remove the closing /, unless it's also the start film->dir = g_dir_open(film->dirname, 0, &error); if(error) { fprintf(stderr, "[film_import] failed to open directory %s: %s\n", film->dirname, error->message); g_error_free(error); dt_film_cleanup(film); free(film); return 0; } dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_BG, dt_film_import1_create(film)); return filmid; }
int32_t dt_control_remove_images_job_run(dt_job_t *job) { int imgid = -1; dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param; GList *t = t1->index; char *imgs = _get_image_list(t); int total = g_list_length(t); char message[512]= {0}; double fraction=0; snprintf(message, 512, ngettext ("removing %d image", "removing %d images", total), total ); const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message); sqlite3_stmt *stmt = NULL; // check that we can safely remove the image gboolean remove_ok = TRUE; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT id FROM images WHERE id IN (?2) AND flags&?1=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, DT_IMAGE_LOCAL_COPY); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgs, -1, SQLITE_STATIC); while(sqlite3_step(stmt) == SQLITE_ROW) { int imgid = sqlite3_column_int(stmt, 0); if (!dt_image_safe_remove(imgid)) { remove_ok = FALSE; break; } } sqlite3_finalize(stmt); if (!remove_ok) { dt_control_log(_("cannot remove local copy when the original file is not accessible.")); dt_control_backgroundjobs_destroy(darktable.control, jid); free(imgs); return 0; } // update remove status _set_remove_flag(imgs); dt_collection_update(darktable.collection); // We need a list of files to regenerate .xmp files if there are duplicates GList *list = _get_full_pathname(imgs); free(imgs); while(t) { imgid = GPOINTER_TO_INT(t->data); dt_image_remove(imgid); t = g_list_delete_link(t, t); fraction=1.0/total; dt_control_backgroundjobs_progress(darktable.control, jid, fraction); } char *imgname; while(list) { imgname = (char *)list->data; dt_image_synch_all_xmp(imgname); list = g_list_delete_link(list, list); } dt_control_backgroundjobs_destroy(darktable.control, jid); dt_film_remove_empty(); dt_control_signal_raise(darktable.signals, DT_SIGNAL_FILMROLLS_CHANGED); dt_control_queue_redraw_center(); return 0; }
gboolean _variable_get_value(dt_variables_params_t *params, gchar *variable,gchar *value) { const gchar *file_ext=NULL; gboolean got_value=FALSE; struct tm *tim=localtime(¶ms->data->time); const gchar *homedir = dt_loc_get_home_dir(NULL); gchar *pictures_folder=NULL; if(g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) == NULL) pictures_folder=g_build_path(G_DIR_SEPARATOR_S,homedir,"Pictures",(char *)NULL); else pictures_folder=g_strdup( g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) ); if(params->filename) { file_ext=(g_strrstr(params->filename,".")+1); if(file_ext == (gchar*)1) file_ext = params->filename + strlen(params->filename); } /* image exif time */ gboolean have_exif_tm = FALSE; int exif_iso = 100; struct tm exif_tm= {0}; if (params->imgid) { const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, params->imgid); if (sscanf (img->exif_datetime_taken,"%d:%d:%d %d:%d:%d", &exif_tm.tm_year, &exif_tm.tm_mon, &exif_tm.tm_mday, &exif_tm.tm_hour, &exif_tm.tm_min, &exif_tm.tm_sec ) == 6 ) { exif_tm.tm_year-=1900; exif_tm.tm_mon--; have_exif_tm = TRUE; } exif_iso = img->exif_iso; dt_image_cache_read_release(darktable.image_cache, img); } if( g_strcmp0(variable,"$(YEAR)") == 0 && (got_value=TRUE) ) sprintf(value,"%.4d",tim->tm_year+1900); else if( g_strcmp0(variable,"$(MONTH)") == 0&& (got_value=TRUE) ) sprintf(value,"%.2d",tim->tm_mon+1); else if( g_strcmp0(variable,"$(DAY)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d",tim->tm_mday); else if( g_strcmp0(variable,"$(HOUR)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d",tim->tm_hour); else if( g_strcmp0(variable,"$(MINUTE)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d",tim->tm_min); else if( g_strcmp0(variable,"$(SECOND)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d",tim->tm_sec); else if( g_strcmp0(variable,"$(EXIF_YEAR)") == 0 && (got_value=TRUE) ) sprintf(value,"%.4d", (have_exif_tm?exif_tm.tm_year:tim->tm_year)+1900); else if( g_strcmp0(variable,"$(EXIF_MONTH)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d", (have_exif_tm?exif_tm.tm_mon:tim->tm_mon)+1); else if( g_strcmp0(variable,"$(EXIF_DAY)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d", (have_exif_tm?exif_tm.tm_mday:tim->tm_mday)); else if( g_strcmp0(variable,"$(EXIF_HOUR)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d", (have_exif_tm?exif_tm.tm_hour:tim->tm_hour)); else if( g_strcmp0(variable,"$(EXIF_MINUTE)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d", (have_exif_tm?exif_tm.tm_min:tim->tm_min)); else if( g_strcmp0(variable,"$(EXIF_SECOND)") == 0 && (got_value=TRUE) ) sprintf(value,"%.2d", (have_exif_tm?exif_tm.tm_sec:tim->tm_sec)); else if( g_strcmp0(variable,"$(EXIF_ISO)") == 0 && (got_value=TRUE) ) sprintf(value,"%d", exif_iso); else if( g_strcmp0(variable,"$(ID)") == 0 && (got_value=TRUE) ) sprintf(value,"%d", params->imgid); else if( g_strcmp0(variable,"$(JOBCODE)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",params->jobcode); else if( g_strcmp0(variable,"$(ROLL_NAME)") == 0 && params->filename && (got_value=TRUE) ) sprintf(value,"%s",g_path_get_basename(g_path_get_dirname(params->filename))); else if( g_strcmp0(variable,"$(FILE_DIRECTORY)") == 0 && params->filename && (got_value=TRUE) ) sprintf(value,"%s",g_path_get_dirname(params->filename)); // undocumented : backward compatibility else if( g_strcmp0(variable,"$(FILE_FOLDER)") == 0 && params->filename && (got_value=TRUE) ) sprintf(value,"%s",g_path_get_dirname(params->filename)); else if( g_strcmp0(variable,"$(FILE_NAME)") == 0 && params->filename && (got_value=TRUE) ) { sprintf(value,"%s",g_path_get_basename(params->filename)); if (g_strrstr(value,".")) *(g_strrstr(value,"."))=0; } else if( g_strcmp0(variable,"$(FILE_EXTENSION)") == 0 && params->filename && (got_value=TRUE) ) sprintf(value,"%s",file_ext); else if( g_strcmp0(variable,"$(SEQUENCE)") == 0 && (got_value=TRUE) ) sprintf(value,"%.4d",params->sequence>=0?params->sequence:params->data->sequence); else if( g_strcmp0(variable,"$(USERNAME)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",g_get_user_name()); else if( g_strcmp0(variable,"$(HOME_FOLDER)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",homedir); // undocumented : backward compatibility else if( g_strcmp0(variable,"$(HOME)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",homedir); else if( g_strcmp0(variable,"$(PICTURES_FOLDER)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",pictures_folder); else if( g_strcmp0(variable,"$(DESKTOP_FOLDER)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)); // undocumented : backward compatibility else if( g_strcmp0(variable,"$(DESKTOP)") == 0 && (got_value=TRUE) ) sprintf(value,"%s",g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)); #if 0 else if( g_strcmp0(variable,"$(VC)") == 0 && (got_value=TRUE) ) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(darktable.db, "select id from images where filename=?1", &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, params->filename); while(sqlite3_step(stmt) == SQLITE_ROW) { if(sqlite3_column_int(stmt) == ) { } } sqlite3_finalize(stmt); sprintf(value,"%s",g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)); }
static void auto_apply_presets(const int imgid) { if(imgid <= 0) return; int run = 0; const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); if(!(cimg->flags & DT_IMAGE_AUTO_PRESETS_APPLIED)) run = 1; // flag was already set? only apply presets once in the lifetime of a history stack. // (the flag will be cleared when removing it) if(!run || cimg->id <= 0) { dt_image_cache_read_release(darktable.image_cache, cimg); return; } // keep locked, we want to be alone messing with the history of the poor fellow: dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); // be extra sure that we don't mess up history in separate threads: dt_pthread_mutex_lock(&darktable.db_insert); // cleanup DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from memory.history", NULL, NULL, NULL); const char *preset_table[2] = {"presets", "legacy_presets"}; const int legacy = (image->flags & DT_IMAGE_NO_LEGACY_PRESETS) ? 0 : 1; char query[1024]; snprintf(query, 1024, "insert into memory.history select ?1, 0, op_version, operation, op_params, enabled, blendop_params, blendop_version, multi_priority, multi_name " "from %s where autoapply=1 and " "?2 like model and ?3 like maker and ?4 like lens and " "?5 between iso_min and iso_max and " "?6 between exposure_min and exposure_max and " "?7 between aperture_min and aperture_max and " "?8 between focal_length_min and focal_length_max and " "(isldr = 0 or isldr=?9) order by writeprotect desc, " "length(model), length(maker), length(lens)", preset_table[legacy]); // query for all modules at once: sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, cimg->exif_model, strlen(cimg->exif_model), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, cimg->exif_maker, strlen(cimg->exif_maker), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, cimg->exif_lens, strlen(cimg->exif_lens), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 5, fmaxf(0.0f, fminf(1000000, cimg->exif_iso))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, fmaxf(0.0f, fminf(1000000, cimg->exif_exposure))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, fmaxf(0.0f, fminf(1000000, cimg->exif_aperture))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmaxf(0.0f, fminf(1000000, cimg->exif_focal_length))); // 0: dontcare, 1: ldr, 2: raw DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, 2-dt_image_is_ldr(cimg)); if(sqlite3_step(stmt) == SQLITE_DONE) { sqlite3_finalize(stmt); int cnt = 0; // count what we found: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(*) from memory.history", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) { // if there is anything.. cnt = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // fprintf(stderr, "[auto_apply_presets] imageid %d found %d matching presets (legacy %d)\n", imgid, cnt, legacy); // advance the current history by that amount: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update history set num=num+?1 where imgid=?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, cnt); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); if(sqlite3_step(stmt) == SQLITE_DONE) { // and finally prepend the rest with increasing numbers (starting at 0) sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history select imgid, rowid-1, module, operation, op_params, enabled, " "blendop_params, blendop_version, multi_priority, multi_name from memory.history", -1, &stmt, NULL); sqlite3_step(stmt); } } } sqlite3_finalize(stmt); image->flags |= DT_IMAGE_AUTO_PRESETS_APPLIED | DT_IMAGE_NO_LEGACY_PRESETS; dt_pthread_mutex_unlock(&darktable.db_insert); // make sure these end up in the image_cache + xmp (sync through here if we set the flag) dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); }
static void dt_lib_presets_popup_menu_show(dt_lib_module_info_t *minfo) { GtkMenu *menu = darktable.gui->presets_popup_menu; if(menu) gtk_widget_destroy(GTK_WIDGET(menu)); darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new()); menu = darktable.gui->presets_popup_menu; GtkWidget *mi; int active_preset = -1, cnt = 0, writeprotect = 0; sqlite3_stmt *stmt; // order: get shipped defaults first DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, description from presets where operation=?1 and op_version=?2 order by writeprotect desc, rowid", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, minfo->plugin_name, strlen(minfo->plugin_name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, minfo->version); // collect all presets for op from db int found = 0; while(sqlite3_step(stmt) == SQLITE_ROW) { void *op_params = (void *)sqlite3_column_blob(stmt, 1); int32_t op_params_size = sqlite3_column_bytes(stmt, 1); const char *name = (char *)sqlite3_column_text(stmt, 0); if (darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name)==0) found = 1; // selected in bold: // printf("comparing %d bytes to %d\n", op_params_size, minfo->params_size); // for(int k=0;k<op_params_size && !memcmp(minfo->params, op_params, k);k++) printf("compare [%c %c] %d: %d\n", // ((const char*)(minfo->params))[k], // ((const char*)(op_params))[k], // k, memcmp(minfo->params, op_params, k)); if(op_params_size == minfo->params_size && !memcmp(minfo->params, op_params, op_params_size)) { active_preset = cnt; writeprotect = sqlite3_column_int(stmt, 2); char *markup; mi = gtk_menu_item_new_with_label(""); markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>", name); gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child(GTK_BIN(mi))), markup); g_free (markup); } else { mi = gtk_menu_item_new_with_label((const char *)name); } g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), minfo); g_object_set(G_OBJECT(mi), "tooltip-text", sqlite3_column_text(stmt, 3), (char *)NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); cnt ++; } sqlite3_finalize(stmt); if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); // FIXME: this doesn't seem to work. if(active_preset >= 0) { if(!writeprotect) { mi = gtk_menu_item_new_with_label(_("edit this preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_edit_preset), minfo); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); mi = gtk_menu_item_new_with_label(_("delete this preset")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_delete_preset), minfo); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); } } else { mi = gtk_menu_item_new_with_label(_("store new preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_new_preset), minfo); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); if (darktable.gui->last_preset && found) { char label[60]; strcpy (label, _("update preset")); strcat (label, " <span weight=\"bold\">%s</span>"); char *markup = g_markup_printf_escaped (label, darktable.gui->last_preset); mi = gtk_menu_item_new_with_label(""); gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child(GTK_BIN(mi))), markup); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_update_preset), minfo); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); g_free (markup); } } }
int dt_film_import(const char *dirname) { int rc; sqlite3_stmt *stmt; /* initialize a film object*/ dt_film_t *film = (dt_film_t *)malloc(sizeof(dt_film_t)); dt_film_init(film); film->id = -1; /* lookup if film exists and reuse id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, -1, SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); /* if we didn't find a id, lets instansiate a new filmroll */ if(film->id <= 0) { char datetime[20]; dt_gettime(datetime, sizeof(datetime)); /* insert a new film roll into database */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into film_rolls (id, datetime_accessed, folder) values " "(null, ?1, ?2)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, datetime, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dirname, -1, SQLITE_STATIC); rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) fprintf(stderr, "[film_import] failed to insert film roll! %s\n", sqlite3_errmsg(dt_database_get(darktable.db))); sqlite3_finalize(stmt); /* requery for filmroll and fetch new id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, -1, SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } /* bail out if we got troubles */ if(film->id <= 0) { // if the film is empty => remove it again. if(dt_film_is_empty(film->id)) { dt_film_remove(film->id); } dt_film_cleanup(film); free(film); return 0; } /* at last put import film job on queue */ film->last_loaded = 0; g_strlcpy(film->dirname, dirname, sizeof(film->dirname)); film->dir = g_dir_open(film->dirname, 0, NULL); dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_BG, dt_film_import1_create(film)); return film->id; }
static void edit_preset_response(GtkDialog *dialog, gint response_id, dt_lib_presets_edit_dialog_t *g) { gint dlg_ret; gint is_new = 0; if(response_id == GTK_RESPONSE_ACCEPT) { sqlite3_stmt *stmt; // now delete preset, so we can re-insert the new values: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, g->original_name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version); sqlite3_step(stmt); sqlite3_finalize(stmt); if ( ((g->old_id >= 0) && (strcmp(g->original_name, gtk_entry_get_text(g->name)) != 0)) || (g->old_id < 0) ) { // editing existing preset with different name or store new preset -> check for a preset with the same name: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name from presets where name = ?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version); if(sqlite3_step(stmt) == SQLITE_ROW) { sqlite3_finalize(stmt); GtkWidget *window = dt_ui_main_window(darktable.gui->ui); GtkWidget *dlg_overwrite = gtk_message_dialog_new (GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("preset `%s' already exists.\ndo you want to overwrite?"), gtk_entry_get_text(g->name) ); gtk_window_set_title(GTK_WINDOW (dlg_overwrite), _("overwrite preset?")); dlg_ret = gtk_dialog_run (GTK_DIALOG (dlg_overwrite)); gtk_widget_destroy (dlg_overwrite); // if result is BUTTON_NO exit without destroy dialog, to permit other name if (dlg_ret == GTK_RESPONSE_NO) return; } else { is_new = 1; sqlite3_finalize(stmt); } } if (is_new == 0) { // delete preset, so we can re-insert the new values: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version); sqlite3_step(stmt); sqlite3_finalize(stmt); } // commit all the user input fields char path[1024]; snprintf(path,1024,"preset/%s",g->original_name); dt_accel_rename_preset_lib(g->module,path,gtk_entry_get_text(g->name)); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into presets (name, description, operation, op_version, op_params, blendop_params, blendop_version, enabled, model, maker, lens, " "iso_min, iso_max, exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, focal_length_max, writeprotect, " "autoapply, filter, def, isldr) values (?1, ?2, ?3, ?4, ?5, null, 0, 1, '%', '%', '%', 0, 51200, 0, 100000000, 0, 100000000, 0, 1000, 0, 0, 0, 0, 0)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, gtk_entry_get_text(g->description), strlen(gtk_entry_get_text(g->description)), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, g->version); DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 5, g->params, g->params_size, SQLITE_TRANSIENT); sqlite3_step(stmt); sqlite3_finalize(stmt); dt_gui_store_last_preset (gtk_entry_get_text(g->name)); } gtk_widget_destroy(GTK_WIDGET(dialog)); g_free(g->original_name); free(g); }
static void _lib_duplicate_init_callback(gpointer instance, dt_lib_module_t *self) { dt_lib_duplicate_t *d = (dt_lib_duplicate_t *)self->data; d->imgid = 0; gtk_container_foreach(GTK_CONTAINER(d->duplicate_box), (GtkCallback)gtk_widget_destroy, 0); // retrieve all the versions of the image sqlite3_stmt *stmt; dt_develop_t *dev = darktable.develop; int first_imgid = -1; // we get a summarize of all versions of the image DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT i.version, i.id, m.value FROM images AS " "i LEFT JOIN meta_data AS m ON m.id = i.id AND " "m.key = ?3 WHERE film_id = ?1 AND filename = " "?2 ORDER BY i.version", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dev->image_storage.film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dev->image_storage.filename, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, DT_METADATA_XMP_DC_TITLE); while(sqlite3_step(stmt) == SQLITE_ROW) { GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); GtkWidget *dr = gtk_drawing_area_new(); const int imgid = sqlite3_column_int(stmt, 1); // select original picture if (first_imgid == -1) first_imgid = imgid; gtk_widget_set_size_request (dr, 100, 100); g_object_set_data (G_OBJECT (dr),"imgid",GINT_TO_POINTER(imgid)); gtk_widget_add_events(dr, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); g_signal_connect (G_OBJECT (dr), "draw", G_CALLBACK (_lib_duplicate_thumb_draw_callback), self); if (imgid != dev->image_storage.id) { g_signal_connect(G_OBJECT(dr), "button-press-event", G_CALLBACK(_lib_duplicate_thumb_press_callback), self); g_signal_connect(G_OBJECT(dr), "button-release-event", G_CALLBACK(_lib_duplicate_thumb_release_callback), self); } gchar chl[256]; gchar *path = (gchar *)sqlite3_column_text(stmt, 2); g_snprintf(chl, sizeof(chl), "%d", sqlite3_column_int(stmt, 0)); GtkWidget *tb = gtk_entry_new(); if(path) gtk_entry_set_text(GTK_ENTRY(tb), path); gtk_entry_set_width_chars(GTK_ENTRY(tb), 15); g_object_set_data (G_OBJECT (tb),"imgid",GINT_TO_POINTER(imgid)); g_signal_connect(G_OBJECT(tb), "focus-out-event", G_CALLBACK(_lib_duplicate_caption_out_callback), self); dt_gui_key_accel_block_on_focus_connect(GTK_WIDGET(tb)); GtkWidget *lb = gtk_label_new (g_strdup(chl)); GtkWidget *bt = dtgtk_button_new(dtgtk_cairo_paint_cancel, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER, NULL); g_object_set_data(G_OBJECT(bt), "imgid", GINT_TO_POINTER(imgid)); gtk_widget_set_size_request(bt, DT_PIXEL_APPLY_DPI(13), DT_PIXEL_APPLY_DPI(13)); g_signal_connect(G_OBJECT(bt), "clicked", G_CALLBACK(_lib_duplicate_delete), self); gtk_box_pack_start(GTK_BOX(hb), dr, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hb), tb, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hb), lb, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hb), bt, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(d->duplicate_box), hb, FALSE, FALSE, 0); } sqlite3_finalize (stmt); switch(d->select) { case DT_DUPLICATE_SELECT_FIRST: _do_select(first_imgid); break; case DT_DUPLICATE_SELECT_CURRENT: _do_select(darktable.develop->image_storage.id); break; case DT_DUPLICATE_SELECT_NONE: default: break; } d->select = DT_DUPLICATE_SELECT_NONE; gtk_widget_show_all(d->duplicate_box); }
uint32_t dt_image_import(const int32_t film_id, const char *filename, gboolean override_ignore_jpegs) { if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) return 0; const char *cc = filename + strlen(filename); for(; *cc!='.'&&cc>filename; cc--); if(!strcmp(cc, ".dt")) return 0; if(!strcmp(cc, ".dttags")) return 0; if(!strcmp(cc, ".xmp")) return 0; char *ext = g_ascii_strdown(cc+1, -1); if(override_ignore_jpegs == FALSE && (!strcmp(ext, "jpg") || !strcmp(ext, "jpeg")) && dt_conf_get_bool("ui_last/import_ignore_jpegs")) return 0; int supported = 0; char **extensions = g_strsplit(dt_supported_extensions, ",", 100); for(char **i=extensions; *i!=NULL; i++) if(!strcmp(ext, *i)) { supported = 1; break; } g_strfreev(extensions); if(!supported) { g_free(ext); return 0; } int rc; uint32_t id = 0; // select from images; if found => return gchar *imgfname; imgfname = g_path_get_basename((const gchar*)filename); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where film_id = ?1 and filename = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) { id = sqlite3_column_int(stmt, 0); g_free(imgfname); sqlite3_finalize(stmt); g_free(ext); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); img->flags &= ~DT_IMAGE_REMOVE; dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); return id; } sqlite3_finalize(stmt); // also need to set the no-legacy bit, to make sure we get the right presets (new ones) uint32_t flags = dt_conf_get_int("ui_last/import_initial_rating"); if(flags > 5) { flags = 1; dt_conf_set_int("ui_last/import_initial_rating", 1); } flags |= DT_IMAGE_NO_LEGACY_PRESETS; // insert dummy image entry in database DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into images (id, film_id, filename, caption, description, " "license, sha1sum, flags) values (null, ?1, ?2, '', '', '', '', ?3)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, flags); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) fprintf(stderr, "sqlite3 error %d\n", rc); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where film_id = ?1 and filename = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // Try to find out if this should be grouped already. gchar *basename = g_strdup(imgfname); gchar *cc2 = basename + strlen(basename); for(; *cc2!='.'&&cc2>basename; cc2--); *cc2='\0'; gchar *sql_pattern = g_strconcat(basename, ".%", NULL); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select group_id from images where film_id = ?1 and filename like ?2 and id != ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, sql_pattern, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id); int group_id; if(sqlite3_step(stmt) == SQLITE_ROW) group_id = sqlite3_column_int(stmt, 0); else group_id = id; sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update images set group_id = ?1 where id = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, group_id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, id); sqlite3_step(stmt); sqlite3_finalize(stmt); // printf("[image_import] importing `%s' to img id %d\n", imgfname, id); // lock as shortly as possible: const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); img->group_id = group_id; // read dttags and exif for database queries! (void) dt_exif_read(img, filename); char dtfilename[DT_MAX_PATH_LEN]; g_strlcpy(dtfilename, filename, DT_MAX_PATH_LEN); dt_image_path_append_version(id, dtfilename, DT_MAX_PATH_LEN); char *c = dtfilename + strlen(dtfilename); sprintf(c, ".xmp"); (void)dt_exif_xmp_read(img, dtfilename, 0); // write through to db, but not to xmp. dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); // add a tag with the file extension guint tagid = 0; char tagname[512]; snprintf(tagname, 512, "darktable|format|%s", ext); g_free(ext); dt_tag_new(tagname, &tagid); dt_tag_attach(tagid,id); // Search for sidecar files and import them if found. glob_t *globbuf = g_malloc(sizeof(glob_t)); // Add version wildcard gchar *fname = g_strdup(filename); gchar pattern[DT_MAX_PATH_LEN]; g_snprintf(pattern, DT_MAX_PATH_LEN, "%s", filename); char *c1 = pattern + strlen(pattern); while(*c1 != '.' && c1 > pattern) c1--; snprintf(c1, pattern + DT_MAX_PATH_LEN - c1, "_*"); char *c2 = fname + strlen(fname); while(*c2 != '.' && c2 > fname) c2--; snprintf(c1+2, pattern + DT_MAX_PATH_LEN - c1 - 2, "%s.xmp", c2); if (!glob(pattern, 0, NULL, globbuf)) { for (int i=0; i < globbuf->gl_pathc; i++) { int newid = -1; newid = dt_image_duplicate(id); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, newid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); (void)dt_exif_xmp_read(img, globbuf->gl_pathv[i], 0); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); } globfree(globbuf); } g_free(imgfname); g_free(fname); g_free(basename); g_free(sql_pattern); g_free(globbuf); dt_control_signal_raise(darktable.signals,DT_SIGNAL_IMAGE_IMPORT,id); return id; }
void dt_lib_init_presets(dt_lib_module_t *module) { // since lighttable presets can't end up in styles or any other place outside of the presets table it is // sufficient // to update that very table here and assume that everything is up to date elsewhere. // the intended logic is as follows: // - no set_params -> delete all presets // - op_version >= module_version -> done // - op_version < module_version -> // - module has legacy_params -> try to update // - module doesn't have legacy_params -> delete it if(module->set_params == NULL) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM data.presets WHERE operation=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->plugin_name, -1, SQLITE_TRANSIENT); sqlite3_step(stmt); sqlite3_finalize(stmt); } else { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT rowid, op_version, op_params, name FROM data.presets WHERE operation=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->plugin_name, -1, SQLITE_TRANSIENT); while(sqlite3_step(stmt) == SQLITE_ROW) { int rowid = sqlite3_column_int(stmt, 0); int op_version = sqlite3_column_int(stmt, 1); void *op_params = (void *)sqlite3_column_blob(stmt, 2); size_t op_params_size = sqlite3_column_bytes(stmt, 2); const char *name = (char *)sqlite3_column_text(stmt, 3); int version = module->version(module); if(op_version < version) { size_t new_params_size = 0; void *new_params = NULL; if(module->legacy_params && (new_params = _update_params(module, op_params, op_params_size, op_version, version, &new_params_size))) { // write the updated preset back to db fprintf(stderr, "[lighttable_init_presets] updating '%s' preset '%s' from version %d to version %d\n", module->plugin_name, name, op_version, version); sqlite3_stmt *innerstmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "UPDATE data.presets SET op_version=?1, op_params=?2 WHERE rowid=?3", -1, &innerstmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(innerstmt, 1, version); DT_DEBUG_SQLITE3_BIND_BLOB(innerstmt, 2, new_params, new_params_size, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(innerstmt, 3, rowid); sqlite3_step(innerstmt); sqlite3_finalize(innerstmt); } else { // delete the preset fprintf(stderr, "[lighttable_init_presets] Can't upgrade '%s' preset '%s' from version %d to %d, " "no legacy_params() implemented or unable to update\n", module->plugin_name, name, op_version, version); sqlite3_stmt *innerstmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM data.presets WHERE rowid=?1", -1, &innerstmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(innerstmt, 1, rowid); sqlite3_step(innerstmt); sqlite3_finalize(innerstmt); } free(new_params); } } sqlite3_finalize(stmt); } if(module->init_presets) module->init_presets(module); }
static void edit_preset(const char *name_in, dt_lib_module_info_t *minfo) { gchar *name = NULL; if(name_in == NULL) { name = get_active_preset_name(minfo); if(name == NULL) return; } else name = g_strdup(name_in); GtkWidget *dialog; /* Create the widgets */ char title[1024]; GtkWidget *window = dt_ui_main_window(darktable.gui->ui); snprintf(title, sizeof(title), _("edit `%s'"), name); dialog = gtk_dialog_new_with_buttons(title, GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, _("_ok"), GTK_RESPONSE_ACCEPT, _("_cancel"), GTK_RESPONSE_REJECT, NULL); GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))); GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5)); gtk_widget_set_margin_start(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_end(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_top(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_bottom(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_container_add(content_area, GTK_WIDGET(box)); dt_lib_presets_edit_dialog_t *g = (dt_lib_presets_edit_dialog_t *)g_malloc0(sizeof(dt_lib_presets_edit_dialog_t)); g->old_id = -1; g_strlcpy(g->plugin_name, minfo->plugin_name, sizeof(g->plugin_name)); g->version = minfo->version; g->params_size = minfo->params_size; g->params = minfo->params; g->name = GTK_ENTRY(gtk_entry_new()); g->module = minfo->module; g->original_name = name; gtk_entry_set_text(g->name, name); gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0); gtk_widget_set_tooltip_text(GTK_WIDGET(g->name), _("name of the preset")); g->description = GTK_ENTRY(gtk_entry_new()); gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0); gtk_widget_set_tooltip_text(GTK_WIDGET(g->description), _("description or further information")); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "SELECT rowid, description FROM data.presets WHERE name = ?1 AND operation = ?2 AND op_version = ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, minfo->plugin_name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, minfo->version); if(sqlite3_step(stmt) == SQLITE_ROW) { g->old_id = sqlite3_column_int(stmt, 0); gtk_entry_set_text(g->description, (const char *)sqlite3_column_text(stmt, 1)); } sqlite3_finalize(stmt); g_signal_connect(dialog, "response", G_CALLBACK(edit_preset_response), g); gtk_widget_show_all(dialog); }
static int dt_film_import_blocking(const char *dirname, const int blocking) { int rc; sqlite3_stmt *stmt; /* intialize a film object*/ dt_film_t *film = (dt_film_t *)malloc(sizeof(dt_film_t)); dt_film_init(film); film->id = -1; /* lookup if film exists and reuse id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, strlen(dirname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); /* if we didnt find a id, lets instansiate a new filmroll */ if(film->id <= 0) { char datetime[20]; dt_gettime(datetime); #if 0 /* Should we use one for the whole app? */ GVolumeMonitor *gv_monitor; gv_monitor = g_volume_monitor_get (); GList *mounts; mounts = g_volume_monitor_get_mounts(gv_monitor); gchar *mount_name = NULL; if (mounts != NULL) { GFile *mount_gfile; GMount *filmroll_mount; GError *error = NULL; gchar *filmroll_path; GFile *gdirname = g_file_new_for_path(dirname); filmroll_mount = g_file_find_enclosing_mount(gdirname, NULL, &error); g_object_unref(gdirname); if (!error) /* We are considering that the only error is that there is no mount * because the filmroll added is in a local drive */ { filmroll_path = g_file_get_path((g_mount_get_default_location(filmroll_mount))); for (int i=0; i < g_list_length (mounts); i++) { gchar *p; mount_gfile = g_mount_get_default_location((GMount *)g_list_nth_data(mounts, i)); p = g_file_get_path(mount_gfile); if (g_strcmp0(p, filmroll_path)) { mount_name = g_mount_get_name(g_list_nth_data(mounts, i)); break; } g_free(p); g_object_unref (mount_gfile); } g_free (filmroll_path); } if (filmroll_mount != NULL) g_object_unref (filmroll_mount); /* We haven't found the device in the list of connected devices. Let's suppose it is local */ if (mount_name == NULL) mount_name = g_strdup("Local"); } else mount_name = g_strdup("Local"); #endif /* insert a new film roll into database */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), // "insert into film_rolls (id, datetime_accessed, folder, external_drive) values " // "(null, ?1, ?2, ?3)", -1, &stmt, NULL); "insert into film_rolls (id, datetime_accessed, folder) values " "(null, ?1, ?2)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, datetime, strlen(datetime), SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dirname, strlen(dirname), SQLITE_STATIC); // DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, mount_name, strlen(mount_name), // SQLITE_STATIC); rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) fprintf(stderr, "[film_import] failed to insert film roll! %s\n", sqlite3_errmsg(dt_database_get(darktable.db))); sqlite3_finalize(stmt); // if (mount_name != NULL) g_free (mount_name); /* requery for filmroll and fetch new id */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from film_rolls where folder=?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, strlen(dirname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) film->id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } /* bail out if we got troubles */ if(film->id <= 0) { dt_film_cleanup(film); free(film); return 0; } /* at last put import film job on queue */ dt_job_t j; film->last_loaded = 0; g_strlcpy(film->dirname, dirname, 512); film->dir = g_dir_open(film->dirname, 0, NULL); dt_film_import1_init(&j, film); dt_control_add_job(darktable.control, &j); return film->id; }
static void edit_preset(const char *name_in, dt_iop_module_t *module) { gchar *name = NULL; if(name_in == NULL) { name = get_active_preset_name(module); if(name == NULL) return; } else name = g_strdup(name_in); GtkWidget *dialog; /* Create the widgets */ char title[1024]; GtkWidget *window = dt_ui_main_window(darktable.gui->ui); snprintf(title, sizeof(title), _("edit `%s' for module `%s'"), name, module->name()); dialog = gtk_dialog_new_with_buttons(title, GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, _("_ok"), GTK_RESPONSE_ACCEPT, _("_cancel"), GTK_RESPONSE_REJECT, NULL); GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))); GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5)); gtk_widget_set_margin_start(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_end(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_top(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_widget_set_margin_bottom(GTK_WIDGET(box), DT_PIXEL_APPLY_DPI(10)); gtk_container_add(content_area, GTK_WIDGET(box)); GtkWidget *label; dt_gui_presets_edit_dialog_t *g = (dt_gui_presets_edit_dialog_t *)malloc(sizeof(dt_gui_presets_edit_dialog_t)); g->old_id = -1; g->original_name = name; g->module = module; g->name = GTK_ENTRY(gtk_entry_new()); gtk_entry_set_text(g->name, name); gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0); gtk_widget_set_tooltip_text(GTK_WIDGET(g->name), _("name of the preset")); g->description = GTK_ENTRY(gtk_entry_new()); gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0); gtk_widget_set_tooltip_text(GTK_WIDGET(g->description), _("description or further information")); g->autoapply = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("auto apply this preset to matching images"))); gtk_box_pack_start(box, GTK_WIDGET(g->autoapply), FALSE, FALSE, 0); g->filter = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("only show this preset for matching images"))); gtk_widget_set_tooltip_text(GTK_WIDGET(g->filter), _("be very careful with this option. " "this might be the last time you see your preset.")); gtk_box_pack_start(box, GTK_WIDGET(g->filter), FALSE, FALSE, 0); g_signal_connect(G_OBJECT(g->autoapply), "toggled", G_CALLBACK(check_buttons_activated), g); g_signal_connect(G_OBJECT(g->filter), "toggled", G_CALLBACK(check_buttons_activated), g); int line = 0; g->details = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(g->details), DT_PIXEL_APPLY_DPI(5)); gtk_grid_set_column_spacing(GTK_GRID(g->details), DT_PIXEL_APPLY_DPI(10)); gtk_box_pack_start(box, GTK_WIDGET(g->details), TRUE, TRUE, 0); // model, maker, lens g->model = gtk_entry_new(); gtk_widget_set_hexpand(GTK_WIDGET(g->model), TRUE); gtk_widget_set_tooltip_text(g->model, _("string to match model (use % as wildcard)")); label = gtk_label_new(_("model")); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->model, label, GTK_POS_RIGHT, 2, 1); g->maker = gtk_entry_new(); gtk_widget_set_tooltip_text(g->maker, _("string to match maker (use % as wildcard)")); label = gtk_label_new(_("maker")); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->maker, label, GTK_POS_RIGHT, 2, 1); g->lens = gtk_entry_new(); gtk_widget_set_tooltip_text(g->lens, _("string to match lens (use % as wildcard)")); label = gtk_label_new(_("lens")); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->lens, label, GTK_POS_RIGHT, 2, 1); // iso label = gtk_label_new(_("ISO")); gtk_widget_set_halign(label, GTK_ALIGN_START); g->iso_min = gtk_spin_button_new_with_range(0, 51200, 100); gtk_widget_set_tooltip_text(g->iso_min, _("minimum ISO value")); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_min), 0); g->iso_max = gtk_spin_button_new_with_range(0, 51200, 100); gtk_widget_set_tooltip_text(g->iso_max, _("maximum ISO value")); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_max), 0); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_min, label, GTK_POS_RIGHT, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_max, g->iso_min, GTK_POS_RIGHT, 1, 1); // exposure label = gtk_label_new(_("exposure")); gtk_widget_set_halign(label, GTK_ALIGN_START); g->exposure_min = dt_bauhaus_combobox_new(NULL); g->exposure_max = dt_bauhaus_combobox_new(NULL); gtk_widget_set_tooltip_text(g->exposure_min, _("minimum exposure time")); gtk_widget_set_tooltip_text(g->exposure_max, _("maximum exposure time")); for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++) dt_bauhaus_combobox_add(g->exposure_min, dt_gui_presets_exposure_value_str[k]); for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++) dt_bauhaus_combobox_add(g->exposure_max, dt_gui_presets_exposure_value_str[k]); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_min, label, GTK_POS_RIGHT, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_max, g->exposure_min, GTK_POS_RIGHT, 1, 1); // aperture label = gtk_label_new(_("aperture")); gtk_widget_set_halign(label, GTK_ALIGN_START); g->aperture_min = dt_bauhaus_combobox_new(NULL); g->aperture_max = dt_bauhaus_combobox_new(NULL); gtk_widget_set_tooltip_text(g->aperture_min, _("minimum aperture value")); gtk_widget_set_tooltip_text(g->aperture_max, _("maximum aperture value")); for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++) dt_bauhaus_combobox_add(g->aperture_min, dt_gui_presets_aperture_value_str[k]); for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++) dt_bauhaus_combobox_add(g->aperture_max, dt_gui_presets_aperture_value_str[k]); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_min, label, GTK_POS_RIGHT, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_max, g->aperture_min, GTK_POS_RIGHT, 1, 1); // focal length label = gtk_label_new(_("focal length")); gtk_widget_set_halign(label, GTK_ALIGN_START); g->focal_length_min = gtk_spin_button_new_with_range(0, 1000, 10); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_min), 0); g->focal_length_max = gtk_spin_button_new_with_range(0, 1000, 10); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_max), 0); gtk_widget_set_tooltip_text(g->focal_length_min, _("minimum focal length")); gtk_widget_set_tooltip_text(g->focal_length_max, _("maximum focal length")); gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_min, label, GTK_POS_RIGHT, 1, 1); gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_max, g->focal_length_min, GTK_POS_RIGHT, 1, 1); // raw/hdr/ldr label = gtk_label_new(_("format")); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID(g->details), label, 0, line, 1, 1); for(int i = 0; i < 3; i++) { g->format_btn[i] = gtk_check_button_new_with_label(_(dt_gui_presets_format_value_str[i])); gtk_grid_attach(GTK_GRID(g->details), g->format_btn[i], 1, line + i, 2, 1); } gtk_widget_set_no_show_all(GTK_WIDGET(g->details), TRUE); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT rowid, description, model, maker, lens, iso_min, iso_max, " "exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, " "focal_length_max, autoapply, filter, format FROM presets WHERE name = ?1 AND " "operation = ?2 AND op_version = ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, module->op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, module->version()); if(sqlite3_step(stmt) == SQLITE_ROW) { g->old_id = sqlite3_column_int(stmt, 0); gtk_entry_set_text(GTK_ENTRY(g->description), (const char *)sqlite3_column_text(stmt, 1)); gtk_entry_set_text(GTK_ENTRY(g->model), (const char *)sqlite3_column_text(stmt, 2)); gtk_entry_set_text(GTK_ENTRY(g->maker), (const char *)sqlite3_column_text(stmt, 3)); gtk_entry_set_text(GTK_ENTRY(g->lens), (const char *)sqlite3_column_text(stmt, 4)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), sqlite3_column_double(stmt, 5)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), sqlite3_column_double(stmt, 6)); float val = sqlite3_column_double(stmt, 7); int k = 0; for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++) ; dt_bauhaus_combobox_set(g->exposure_min, k); val = sqlite3_column_double(stmt, 8); for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++) ; dt_bauhaus_combobox_set(g->exposure_max, k); val = sqlite3_column_double(stmt, 9); for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++) ; dt_bauhaus_combobox_set(g->aperture_min, k); val = sqlite3_column_double(stmt, 10); for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++) ; dt_bauhaus_combobox_set(g->aperture_max, k); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), sqlite3_column_double(stmt, 11)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), sqlite3_column_double(stmt, 12)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), sqlite3_column_int(stmt, 13)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), sqlite3_column_int(stmt, 14)); const int format = sqlite3_column_int(stmt, 15); for(k = 0; k < 3; k++) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), format & (dt_gui_presets_format_flag[k])); } else { gtk_entry_set_text(GTK_ENTRY(g->description), ""); gtk_entry_set_text(GTK_ENTRY(g->model), "%"); gtk_entry_set_text(GTK_ENTRY(g->maker), "%"); gtk_entry_set_text(GTK_ENTRY(g->lens), "%"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), 0); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), 51200); float val = 0; int k = 0; for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++) ; dt_bauhaus_combobox_set(g->exposure_min, k); val = 100000000; for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++) ; dt_bauhaus_combobox_set(g->exposure_max, k); val = 0; for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++) ; dt_bauhaus_combobox_set(g->aperture_min, k); val = 100000000; for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++) ; dt_bauhaus_combobox_set(g->aperture_max, k); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), 0); gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), 1000); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), 0); for(k = 0; k < 3; k++) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), TRUE); } sqlite3_finalize(stmt); g_signal_connect(dialog, "response", G_CALLBACK(edit_preset_response), g); gtk_widget_show_all(dialog); }
static void edit_preset (const char *name_in, dt_lib_module_info_t *minfo) { gchar *name = NULL; if(name_in == NULL) { name = get_active_preset_name(minfo); if(name == NULL) return; } else name = g_strdup(name_in); GtkWidget *dialog; /* Create the widgets */ char title[1024]; GtkWidget *window = dt_ui_main_window(darktable.gui->ui); snprintf(title, 1024, _("edit `%s'"), name); dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area (GTK_DIALOG (dialog))); GtkWidget *alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 5, 5, 5); gtk_container_add (content_area, alignment); GtkBox *box = GTK_BOX(gtk_vbox_new(FALSE, 5)); gtk_container_add (GTK_CONTAINER(alignment), GTK_WIDGET(box)); dt_lib_presets_edit_dialog_t *g = (dt_lib_presets_edit_dialog_t *)g_malloc0(sizeof(dt_lib_presets_edit_dialog_t)); g->old_id = -1; g_strlcpy(g->plugin_name, minfo->plugin_name, 128); g->version = minfo->version; g->params_size = minfo->params_size; g->params = minfo->params; g->name = GTK_ENTRY(gtk_entry_new()); g->module = minfo->module; g->original_name = name; gtk_entry_set_text(g->name, name); gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0); g_object_set(G_OBJECT(g->name), "tooltip-text", _("name of the preset"), (char *)NULL); g->description = GTK_ENTRY(gtk_entry_new()); gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0); g_object_set(G_OBJECT(g->description), "tooltip-text", _("description or further information"), (char *)NULL); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select rowid, description from presets where name = ?1 and operation = ?2 and op_version = ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, strlen(name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, minfo->plugin_name, strlen(minfo->plugin_name), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, minfo->version); if(sqlite3_step(stmt) == SQLITE_ROW) { g->old_id = sqlite3_column_int(stmt, 0); gtk_entry_set_text(g->description, (const char *)sqlite3_column_text(stmt, 1)); } sqlite3_finalize(stmt); g_signal_connect (dialog, "response", G_CALLBACK (edit_preset_response), g); gtk_widget_show_all (dialog); }
static void dt_gui_presets_popup_menu_show_internal(dt_dev_operation_t op, int32_t version, dt_iop_params_t *params, int32_t params_size, dt_develop_blend_params_t *bl_params, dt_iop_module_t *module, const dt_image_t *image, void (*pick_callback)(GtkMenuItem *, void *), void *callback_data) { GtkMenu *menu = darktable.gui->presets_popup_menu; if(menu) gtk_widget_destroy(GTK_WIDGET(menu)); darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new()); menu = darktable.gui->presets_popup_menu; GtkWidget *mi; int active_preset = -1, cnt = 0, writeprotect = 0; //, selected_default = 0; sqlite3_stmt *stmt; // order: get shipped defaults first if(image) { // only matching if filter is on: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, description, blendop_params, " "op_version, enabled from presets where operation=?1 and " "(filter=0 or ( " "((?2 like model and ?3 like maker) or (?4 like model and ?5 like maker)) and " "?6 like lens and " "?7 between iso_min and iso_max and " "?8 between exposure_min and exposure_max and " "?9 between aperture_min and aperture_max and " "?10 between focal_length_min and focal_length_max and " "(format = 0 or format&?9!=0)" " ) )" "order by writeprotect desc, lower(name), rowid", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, image->exif_iso); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, image->exif_exposure); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, image->exif_aperture); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, image->exif_focal_length); int ldr = dt_image_is_ldr(image) ? FOR_LDR : (dt_image_is_raw(image) ? FOR_RAW : FOR_HDR); DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, ldr); } else { // don't know for which image. show all we got: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, " "description, blendop_params, op_version, " "enabled from presets where operation=?1 " "order by writeprotect desc, lower(name), rowid", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT); } // collect all presets for op from db int found = 0; while(sqlite3_step(stmt) == SQLITE_ROW) { void *op_params = (void *)sqlite3_column_blob(stmt, 1); int32_t op_params_size = sqlite3_column_bytes(stmt, 1); void *blendop_params = (void *)sqlite3_column_blob(stmt, 4); int32_t bl_params_size = sqlite3_column_bytes(stmt, 4); int32_t preset_version = sqlite3_column_int(stmt, 5); int32_t enabled = sqlite3_column_int(stmt, 6); int32_t isdefault = 0; int32_t isdisabled = (preset_version == version ? 0 : 1); const char *name = (char *)sqlite3_column_text(stmt, 0); if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0) found = 1; if(module && !memcmp(module->default_params, op_params, MIN(op_params_size, module->params_size)) && !memcmp(module->default_blendop_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t)))) isdefault = 1; if(module && !memcmp(params, op_params, MIN(op_params_size, params_size)) && !memcmp(bl_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t))) && module->enabled == enabled) { active_preset = cnt; writeprotect = sqlite3_column_int(stmt, 2); char *markup; mi = gtk_menu_item_new_with_label(""); if(isdefault) { markup = g_markup_printf_escaped("<span weight=\"bold\">%s %s</span>", name, _("(default)")); } else markup = g_markup_printf_escaped("<span weight=\"bold\">%s</span>", name); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_free(markup); } else { if(isdefault) { char *markup; mi = gtk_menu_item_new_with_label(""); markup = g_markup_printf_escaped("%s %s", name, _("(default)")); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_free(markup); } else mi = gtk_menu_item_new_with_label((const char *)name); } if(isdisabled) { gtk_widget_set_sensitive(mi, 0); gtk_widget_set_tooltip_text(mi, _("disabled: wrong module version")); } else { if(module) g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_pick_preset), module); else if(pick_callback) g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), callback_data); gtk_widget_set_tooltip_text(mi, (const char *)sqlite3_column_text(stmt, 3)); } gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); cnt++; } sqlite3_finalize(stmt); if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); if(module) { if(active_preset >= 0 && !writeprotect) { mi = gtk_menu_item_new_with_label(_("edit this preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_edit_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); mi = gtk_menu_item_new_with_label(_("delete this preset")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_delete_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); } else { mi = gtk_menu_item_new_with_label(_("store new preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_new_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); if(darktable.gui->last_preset && found) { char *markup = g_markup_printf_escaped("%s <span weight=\"bold\">%s</span>", _("update preset"), darktable.gui->last_preset); mi = gtk_menu_item_new_with_label(""); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_update_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); g_free(markup); } } } }
void dt_styles_update (const char *name, const char *newname, const char *newdescription, GList *filter) { 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", (long int)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); } /* 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: sould 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, "styles/Apply %s", name); dt_accel_deregister_global(tmp_accel); gchar* tmp_name = g_strdup(newname); // freed by _destro_style_shortcut_callback snprintf(tmp_accel, 1024, "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); }