void dt_dev_write_history(dt_develop_t *dev) { sqlite3_stmt *stmt; gboolean changed = FALSE; 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, dev->image_storage.id); sqlite3_step(stmt); sqlite3_finalize (stmt); GList *history = dev->history; for(int i=0; i<dev->history_end && history; i++) { dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); (void)dt_dev_write_history_item(&dev->image_storage, hist, i); history = g_list_next(history); changed = TRUE; } /* attach / detach changed tag reflecting actual change */ guint tagid = 0; dt_tag_new("darktable|changed",&tagid); if(changed) dt_tag_attach(tagid, dev->image_storage.id); else dt_tag_detach(tagid, dev->image_storage.id); }
int dt_lua_tag_detach(lua_State *L) { dt_lua_image_t imgid; dt_lua_tag_t tagid; if(luaL_testudata(L,1,"dt_lua_image_t")) { luaA_to(L,dt_lua_image_t,&imgid,1); luaA_to(L,dt_lua_tag_t,&tagid,2); } else { luaA_to(L,dt_lua_tag_t,&tagid,1); luaA_to(L,dt_lua_image_t,&imgid,2); } dt_tag_detach(tagid,imgid); return 0; }
int32_t dt_control_local_copy_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; guint tagid = 0; const int total = g_list_length(t); double fraction=0; gboolean is_copy = GPOINTER_TO_INT(job->user_data) == 1; char message[512]= {0}; if (is_copy) snprintf(message, 512, ngettext ("creating local copy of %d image", "creating local copies of %d images", total), total); else snprintf(message, 512, ngettext ("removing local copy of %d image", "removing local copies of %d images", total), total); dt_control_log(message); dt_tag_new("darktable|local-copy",&tagid); /* create a cancellable bgjob ui template */ const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message); dt_control_backgroundjobs_set_cancellable(darktable.control, jid, job); const dt_control_t *control = darktable.control; while(t && dt_control_job_get_state(job) != DT_JOB_STATE_CANCELLED) { imgid = GPOINTER_TO_INT(t->data); if (GPOINTER_TO_INT(job->user_data) == 1) { dt_image_local_copy_set(imgid); dt_tag_attach(tagid, imgid); } else { dt_image_local_copy_reset(imgid); dt_tag_detach(tagid, imgid); } t = g_list_delete_link(t, t); fraction += 1.0/total; dt_control_backgroundjobs_progress(control, jid, fraction); } dt_control_backgroundjobs_destroy(control, jid); dt_control_signal_raise(darktable.signals, DT_SIGNAL_FILMROLLS_CHANGED); return 0; }
static void detach_selected_tag(dt_lib_module_t *self, dt_lib_tagging_t *d) { GtkTreeIter iter; GtkTreeModel *model = NULL; GtkTreeView *view = d->current; GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return; guint tagid; gtk_tree_model_get(model, &iter, DT_LIB_TAGGING_COL_ID, &tagid, -1); int imgsel = -1; if(tagid <= 0) return; imgsel = dt_view_get_image_to_act_on(); dt_tag_detach(tagid, imgsel); dt_image_synch_xmp(imgsel); dt_control_signal_raise(darktable.signals, DT_SIGNAL_TAG_CHANGED); }
static void detach_selected_tag(dt_lib_module_t *self, dt_lib_tagging_t *d) { GtkTreeIter iter; GtkTreeModel *model = NULL; GtkTreeView *view = d->current; GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return; guint tagid; gtk_tree_model_get (model, &iter, DT_LIB_TAGGING_COL_ID, &tagid, -1); int imgsel = -1; if(tagid <= 0) return; DT_CTL_GET_GLOBAL(imgsel, lib_image_mouse_over_id); dt_tag_detach(tagid,imgsel); dt_image_synch_xmp(imgsel); }
int32_t dt_control_export_job_run(dt_job_t *job) { long int imgid = -1; dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param; dt_control_export_t *settings = (dt_control_export_t*)t1->data; GList *t = t1->index; const int total = g_list_length(t); int size = 0; dt_imageio_module_format_t *mformat = dt_imageio_get_format_by_index(settings->format_index); g_assert(mformat); dt_imageio_module_storage_t *mstorage = dt_imageio_get_storage_by_index(settings->storage_index); g_assert(mstorage); // Get max dimensions... uint32_t w,h,fw,fh,sw,sh; fw=fh=sw=sh=0; mstorage->dimension(mstorage, &sw,&sh); mformat->dimension(mformat, &fw,&fh); if( sw==0 || fw==0) w=sw>fw?sw:fw; else w=sw<fw?sw:fw; if( sh==0 || fh==0) h=sh>fh?sh:fh; else h=sh<fh?sh:fh; // get shared storage param struct (global sequence counter, one picasa connection etc) dt_imageio_module_data_t *sdata = mstorage->get_params(mstorage, &size); if(sdata == NULL) { dt_control_log(_("failed to get parameters from storage module, aborting export..")); g_free(t1->data); return 1; } dt_control_log(ngettext ("exporting %d image..", "exporting %d images..", total), total); char message[512]= {0}; snprintf(message, 512, ngettext ("exporting %d image to %s", "exporting %d images to %s", total), total, mstorage->name() ); /* create a cancellable bgjob ui template */ const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message ); dt_control_backgroundjobs_set_cancellable(darktable.control, jid, job); const dt_control_t *control = darktable.control; double fraction=0; #ifdef _OPENMP // limit this to num threads = num full buffers - 1 (keep one for darkroom mode) // use min of user request and mipmap cache entries const int full_entries = dt_conf_get_int ("parallel_export"); // GCC won't accept that this variable is used in a macro, considers // it set but not used, which makes for instance Fedora break. const __attribute__((__unused__)) int num_threads = MAX(1, MIN(full_entries, 8)); #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel default(none) private(imgid, size) shared(control, fraction, w, h, stderr, mformat, mstorage, t, sdata, job, jid, darktable, settings) num_threads(num_threads) if(num_threads > 1) #else #pragma omp parallel private(imgid, size) shared(control, fraction, w, h, mformat, mstorage, t, sdata, job, jid, darktable, settings) num_threads(num_threads) if(num_threads > 1) #endif { #endif // get a thread-safe fdata struct (one jpeg struct per thread etc): dt_imageio_module_data_t *fdata = mformat->get_params(mformat, &size); fdata->max_width = settings->max_width; fdata->max_height = settings->max_height; fdata->max_width = (w!=0 && fdata->max_width >w)?w:fdata->max_width; fdata->max_height = (h!=0 && fdata->max_height >h)?h:fdata->max_height; strcpy(fdata->style,settings->style); int num = 0; // Invariant: the tagid for 'darktable|changed' will not change while this function runs. Is this a sensible assumption? guint tagid = 0, etagid = 0; dt_tag_new("darktable|changed",&tagid); dt_tag_new("darktable|exported",&etagid); while(t && dt_control_job_get_state(job) != DT_JOB_STATE_CANCELLED) { #ifdef _OPENMP #pragma omp critical #endif { if(!t) imgid = 0; else { imgid = (long int)t->data; t = g_list_delete_link(t, t); num = total - g_list_length(t); } } // remove 'changed' tag from image dt_tag_detach(tagid, imgid); // make sure the 'exported' tag is set on the image dt_tag_attach(etagid, imgid); // check if image still exists: char imgfilename[DT_MAX_PATH_LEN]; const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, (int32_t)imgid); if(image) { dt_image_full_path(image->id, imgfilename, DT_MAX_PATH_LEN); if(!g_file_test(imgfilename, G_FILE_TEST_IS_REGULAR)) { dt_control_log(_("image `%s' is currently unavailable"), image->filename); fprintf(stderr, _("image `%s' is currently unavailable"), imgfilename); // dt_image_remove(imgid); dt_image_cache_read_release(darktable.image_cache, image); } else { dt_image_cache_read_release(darktable.image_cache, image); mstorage->store(sdata, imgid, mformat, fdata, num, total, settings->high_quality); } } #ifdef _OPENMP #pragma omp critical #endif { fraction+=1.0/total; dt_control_backgroundjobs_progress(control, jid, fraction); } } #ifdef _OPENMP #pragma omp barrier #pragma omp master #endif { dt_control_backgroundjobs_destroy(control, jid); if(mstorage->finalize_store) mstorage->finalize_store(mstorage, sdata); mstorage->free_params(mstorage, sdata); } // all threads free their fdata mformat->free_params (mformat, fdata); #ifdef _OPENMP } #endif g_free(t1->data); return 0; }