void dt_dev_reprocess_center(dt_develop_t *dev) { if(darktable.gui->reset) return; if(dev && dev->gui_attached) { dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dev->pipe->cache_obsolete = 1; // invalidate buffers and force redraw of darkroom dt_dev_invalidate_all(dev); /* redraw */ dt_control_queue_redraw_center(); } }
void dt_dev_pop_history_items(dt_develop_t *dev, int32_t cnt) { // printf("dev popping all history items >= %d\n", cnt); dt_pthread_mutex_lock(&dev->history_mutex); darktable.gui->reset = 1; dev->history_end = cnt; // reset gui params for all modules GList *modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); memcpy(module->params, module->default_params, module->params_size); memcpy(module->blend_params, module->default_blendop_params,sizeof(dt_develop_blend_params_t)); module->enabled = module->default_enabled; modules = g_list_next(modules); } // go through history and set gui params GList *history = dev->history; for(int i=0; i<cnt && history; i++) { dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); memcpy(hist->module->params, hist->params, hist->module->params_size); memcpy(hist->module->blend_params, hist->blend_params, sizeof(dt_develop_blend_params_t)); hist->module->enabled = hist->enabled; history = g_list_next(history); } // update all gui modules modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); dt_iop_gui_update(module); modules = g_list_next(modules); } dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; // again, fixed topology for now. darktable.gui->reset = 0; dt_dev_invalidate_all(dev); dt_pthread_mutex_unlock(&dev->history_mutex); dt_control_queue_redraw_center(); }
void dt_dev_read_history(dt_develop_t *dev) { if(!dev->image_storage.id) return; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid, num, module, operation, op_params, enabled, blendop_params, blendop_version from history where imgid = ?1 order by num", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dev->image_storage.id); dev->history_end = 0; while(sqlite3_step(stmt) == SQLITE_ROW) { // db record: // 0-img, 1-num, 2-module_instance, 3-operation char, 4-params blob, 5-enabled, 6-blend_params, 7-blendop_version dt_dev_history_item_t *hist = (dt_dev_history_item_t *)malloc(sizeof(dt_dev_history_item_t)); hist->enabled = sqlite3_column_int(stmt, 5); GList *modules = dev->iop; const char *opname = (const char *)sqlite3_column_text(stmt, 3); if(!opname) { fprintf(stderr, "[dev_read_history] database history for image `%s' seems to be corrupted!\n", dev->image_storage.filename); free(hist); continue; } hist->module = NULL; while(opname && modules) { dt_iop_module_t *module = (dt_iop_module_t *)modules->data; if(!strcmp(module->op, opname)) { hist->module = module; break; } modules = g_list_next(modules); } if(!hist->module) { fprintf(stderr, "[dev_read_history] the module `%s' requested by image `%s' is not installed on this computer!\n", opname, dev->image_storage.filename); free(hist); continue; } int modversion = sqlite3_column_int(stmt, 2); assert(strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op) == 0); hist->params = malloc(hist->module->params_size); hist->blend_params = malloc(sizeof(dt_develop_blend_params_t)); if(hist->module->version() != modversion || hist->module->params_size != sqlite3_column_bytes(stmt, 4) || strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op)) { if(!hist->module->legacy_params || hist->module->legacy_params(hist->module, sqlite3_column_blob(stmt, 4), labs(modversion), hist->params, labs(hist->module->version()))) { free(hist->params); free(hist->blend_params); fprintf(stderr, "[dev_read_history] module `%s' version mismatch: history is %d, dt %d.\n", hist->module->op, modversion, hist->module->version()); const char *fname = dev->image_storage.filename + strlen(dev->image_storage.filename); while(fname > dev->image_storage.filename && *fname != '/') fname --; if(fname > dev->image_storage.filename) fname++; dt_control_log(_("%s: module `%s' version mismatch: %d != %d"), fname, hist->module->op, hist->module->version(), modversion); free(hist); continue; } } else { memcpy(hist->params, sqlite3_column_blob(stmt, 4), hist->module->params_size); } const void *blendop_params = sqlite3_column_blob(stmt, 6); int bl_length = sqlite3_column_bytes(stmt, 6); int blendop_version = sqlite3_column_int(stmt, 7); if (blendop_params && (blendop_version == dt_develop_blend_version()) && (bl_length == sizeof(dt_develop_blend_params_t))) { memcpy(hist->blend_params, blendop_params, sizeof(dt_develop_blend_params_t)); } else if (blendop_params && dt_develop_blend_legacy_params(hist->module, blendop_params, blendop_version, hist->blend_params, dt_develop_blend_version(), bl_length) == 0) { // do nothing } else { memcpy(hist->blend_params, hist->module->default_blendop_params, sizeof(dt_develop_blend_params_t)); } // memcpy(hist->module->params, hist->params, hist->module->params_size); // hist->module->enabled = hist->enabled; // printf("[dev read history] img %d number %d for operation %d - %s params %f %f\n", sqlite3_column_int(stmt, 0), sqlite3_column_int(stmt, 1), instance, hist->module->op, *(float *)hist->params, *(((float*)hist->params)+1)); dev->history = g_list_append(dev->history, hist); dev->history_end ++; } if(dev->gui_attached) { dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; // again, fixed topology for now. dt_dev_invalidate_all(dev); /* signal history changed */ dt_control_signal_raise(darktable.signals,DT_SIGNAL_DEVELOP_HISTORY_CHANGE); } sqlite3_finalize (stmt); }
void dt_dev_add_history_item(dt_develop_t *dev, dt_iop_module_t *module, gboolean enable) { if(darktable.gui->reset) return; dt_pthread_mutex_lock(&dev->history_mutex); if(dev->gui_attached) { GList *history = g_list_nth (dev->history, dev->history_end); while(history) { GList *next = g_list_next(history); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); // printf("removing obsoleted history item: %s\n", hist->module->op); free(hist->params); free(hist->blend_params); free(history->data); dev->history = g_list_delete_link(dev->history, history); history = next; } history = g_list_nth(dev->history, dev->history_end-1); if(!history || module->instance != ((dt_dev_history_item_t *)history->data)->module->instance) { // new operation, push new item // printf("adding new history item %d - %s\n", dev->history_end, module->op); // if(history) printf("because item %d - %s is different operation.\n", dev->history_end-1, ((dt_dev_history_item_t *)history->data)->module->op); dev->history_end++; dt_dev_history_item_t *hist = (dt_dev_history_item_t *)malloc(sizeof(dt_dev_history_item_t)); if (enable) { module->enabled = TRUE; if(module->off) { darktable.gui->reset = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->off), module->enabled); darktable.gui->reset = 0; } } hist->enabled = module->enabled; hist->module = module; hist->params = malloc(module->params_size); /* allocate and set hist blend_params */ hist->blend_params = malloc(sizeof(dt_develop_blend_params_t)); memset(hist->blend_params, 0, sizeof(dt_develop_blend_params_t)); memcpy(hist->params, module->params, module->params_size); if(module->flags() & IOP_FLAGS_SUPPORTS_BLENDING) memcpy(hist->blend_params, module->blend_params, sizeof(dt_develop_blend_params_t)); dev->history = g_list_append(dev->history, hist); dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; // topology remains, as modules are fixed for now. } else { // same operation, change params // printf("changing same history item %d - %s\n", dev->history_end-1, module->op); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)history->data; memcpy(hist->params, module->params, module->params_size); if(module->flags() & IOP_FLAGS_SUPPORTS_BLENDING) memcpy(hist->blend_params, module->blend_params, sizeof(dt_develop_blend_params_t)); // if the user changed stuff and the module is still not enabled, do it: if(!hist->enabled && !module->enabled) { module->enabled = 1; if(module->off) { darktable.gui->reset = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->off), module->enabled); darktable.gui->reset = 0; } } hist->enabled = module->enabled; dev->pipe->changed |= DT_DEV_PIPE_TOP_CHANGED; dev->preview_pipe->changed |= DT_DEV_PIPE_TOP_CHANGED; } } #if 0 { // debug: printf("remaining %d history items:\n", dev->history_end); GList *history = dev->history; int i = 0; while(history) { dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); printf("%d %s\n", i, hist->module->op); history = g_list_next(history); i++; } } #endif /* invalidate image data*/ dt_similarity_image_dirty(dev->image_storage.id); // invalidate buffers and force redraw of darkroom dt_dev_invalidate_all(dev); dt_pthread_mutex_unlock(&dev->history_mutex); if(dev->gui_attached) { /* signal that history has changed */ dt_control_signal_raise(darktable.signals, DT_SIGNAL_DEVELOP_HISTORY_CHANGE); /* redraw */ dt_control_queue_redraw_center(); } }
void dt_dev_read_history(dt_develop_t *dev) { if(dev->image_storage.id <= 0) return; if(!dev->iop) return; // maybe prepend auto-presets to history before loading it: auto_apply_presets(dev); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid, num, module, operation, op_params, enabled, blendop_params, blendop_version, multi_priority, multi_name from history where imgid = ?1 order by num", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dev->image_storage.id); dev->history_end = 0; while(sqlite3_step(stmt) == SQLITE_ROW) { // db record: // 0-img, 1-num, 2-module_instance, 3-operation char, 4-params blob, 5-enabled, 6-blend_params, 7-blendop_version, 8 multi_priority, 9 multi_name dt_dev_history_item_t *hist = (dt_dev_history_item_t *)malloc(sizeof(dt_dev_history_item_t)); hist->enabled = sqlite3_column_int(stmt, 5); GList *modules = dev->iop; const char *opname = (const char *)sqlite3_column_text(stmt, 3); int multi_priority = sqlite3_column_int(stmt, 8); const char *multi_name = (const char *)sqlite3_column_text(stmt, 9); if(!opname) { fprintf(stderr, "[dev_read_history] database history for image `%s' seems to be corrupted!\n", dev->image_storage.filename); free(hist); continue; } hist->module = NULL; dt_iop_module_t *find_op = NULL; while(opname && modules) { dt_iop_module_t *module = (dt_iop_module_t *)modules->data; if(!strcmp(module->op, opname)) { if (module->multi_priority == multi_priority) { hist->module = module; if(multi_name && strcmp(module->multi_name, multi_name)) snprintf(module->multi_name, 128, "%s", multi_name); break; } else if (multi_priority > 0) { //we just say that we find the name, so we just have to add new instance of this module find_op = module; } } modules = g_list_next(modules); } if (!hist->module && find_op) { //we have to add a new instance of this module and set index to modindex dt_iop_module_t *new_module = (dt_iop_module_t *)malloc(sizeof(dt_iop_module_t)); if (!dt_iop_load_module(new_module, find_op->so, dev)) { new_module->multi_priority = multi_priority; snprintf(new_module->multi_name,128,"%s",multi_name); dev->iop = g_list_insert_sorted(dev->iop, new_module, sort_plugins); new_module->instance = find_op->instance; hist->module = new_module; } } if(!hist->module && opname) { fprintf(stderr, "[dev_read_history] the module `%s' requested by image `%s' is not installed on this computer!\n", opname, dev->image_storage.filename); free(hist); continue; } if(hist->module->flags() & IOP_FLAGS_NO_HISTORY_STACK) { free(hist); continue; } int modversion = sqlite3_column_int(stmt, 2); assert(strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op) == 0); hist->params = malloc(hist->module->params_size); hist->blend_params = malloc(sizeof(dt_develop_blend_params_t)); snprintf(hist->multi_name,128,"%s",multi_name); hist->multi_priority = multi_priority; const void *blendop_params = sqlite3_column_blob(stmt, 6); int bl_length = sqlite3_column_bytes(stmt, 6); int blendop_version = sqlite3_column_int(stmt, 7); if (blendop_params && (blendop_version == dt_develop_blend_version()) && (bl_length == sizeof(dt_develop_blend_params_t))) { memcpy(hist->blend_params, blendop_params, sizeof(dt_develop_blend_params_t)); } else if (blendop_params && dt_develop_blend_legacy_params(hist->module, blendop_params, blendop_version, hist->blend_params, dt_develop_blend_version(), bl_length) == 0) { // do nothing } else { memcpy(hist->blend_params, hist->module->default_blendop_params, sizeof(dt_develop_blend_params_t)); } if(hist->module->version() != modversion || hist->module->params_size != sqlite3_column_bytes(stmt, 4) || strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op)) { if(!hist->module->legacy_params || hist->module->legacy_params(hist->module, sqlite3_column_blob(stmt, 4), labs(modversion), hist->params, labs(hist->module->version()))) { free(hist->params); free(hist->blend_params); fprintf(stderr, "[dev_read_history] module `%s' version mismatch: history is %d, dt %d.\n", hist->module->op, modversion, hist->module->version()); const char *fname = dev->image_storage.filename + strlen(dev->image_storage.filename); while(fname > dev->image_storage.filename && *fname != '/') fname --; if(fname > dev->image_storage.filename) fname++; dt_control_log(_("%s: module `%s' version mismatch: %d != %d"), fname, hist->module->op, hist->module->version(), modversion); free(hist); continue; } } else { memcpy(hist->params, sqlite3_column_blob(stmt, 4), hist->module->params_size); } // make sure that always-on modules are always on. duh. if(hist->module->default_enabled == 1 && hist->module->hide_enable_button == 1) { hist->enabled = 1; } // memcpy(hist->module->params, hist->params, hist->module->params_size); // hist->module->enabled = hist->enabled; // printf("[dev read history] img %d number %d for operation %d - %s params %f %f\n", sqlite3_column_int(stmt, 0), sqlite3_column_int(stmt, 1), instance, hist->module->op, *(float *)hist->params, *(((float*)hist->params)+1)); dev->history = g_list_append(dev->history, hist); dev->history_end ++; } if(dev->gui_attached) { dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; // again, fixed topology for now. dt_dev_invalidate_all(dev); /* signal history changed */ dt_control_signal_raise(darktable.signals,DT_SIGNAL_DEVELOP_HISTORY_CHANGE); } sqlite3_finalize (stmt); }
int button_pressed(dt_view_t *self, double x, double y, int which, int type, uint32_t state) { const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; dt_develop_t *dev = (dt_develop_t *)self->data; const int32_t width_i = self->width; const int32_t height_i = self->height; if(width_i > capwd) x += (capwd-width_i) *.5f; if(height_i > capht) y += (capht-height_i)*.5f; int handled = 0; if(dev->gui_module && dev->gui_module->request_color_pick && which == 1) { float zoom_x, zoom_y; dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y); if(darktable.lib->proxy.colorpicker.size) { dev->gui_module->color_picker_box[0] = .5f+zoom_x; dev->gui_module->color_picker_box[1] = .5f+zoom_y; dev->gui_module->color_picker_box[2] = .5f+zoom_x; dev->gui_module->color_picker_box[3] = .5f+zoom_y; } else { dev->gui_module->color_picker_point[0] = .5f+zoom_x; dev->gui_module->color_picker_point[1] = .5f+zoom_y; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; dt_dev_invalidate_all(dev); } dt_control_queue_redraw(); return 1; } if(dev->gui_module && dev->gui_module->button_pressed) handled = dev->gui_module->button_pressed(dev->gui_module, x, y, which, type, state); if(handled) return handled; if(which == 1 && type == GDK_2BUTTON_PRESS) return 0; if(which == 1) { dt_control_change_cursor(GDK_HAND1); return 1; } if(which == 2) { // zoom to 1:1 2:1 and back dt_dev_zoom_t zoom; int closeup, procw, proch; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); dt_dev_get_processed_size(dev, &procw, &proch); const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0); zoom_x += (1.0/scale)*(x - .5f*dev->width )/procw; zoom_y += (1.0/scale)*(y - .5f*dev->height)/proch; if(zoom == DT_ZOOM_1) { if(!closeup) closeup = 1; else { zoom = DT_ZOOM_FIT; zoom_x = zoom_y = 0.0f; closeup = 0; } } else zoom = DT_ZOOM_1; dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom, zoom); DT_CTL_SET_GLOBAL(dev_closeup, closeup); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); dt_dev_invalidate(dev); return 1; } return 0; }
void mouse_moved(dt_view_t *self, double x, double y, int which) { const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; dt_develop_t *dev = (dt_develop_t *)self->data; // if we are not hovering over a thumbnail in the filmstrip -> show metadata of opened image. int32_t mouse_over_id = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id == -1) { mouse_over_id = dev->image_storage.id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } dt_control_t *ctl = darktable.control; const int32_t width_i = self->width; const int32_t height_i = self->height; int32_t offx = 0.0f, offy = 0.0f; if(width_i > capwd) offx = (capwd-width_i) *.5f; if(height_i > capht) offy = (capht-height_i)*.5f; int handled = 0; x += offx; y += offy; if(dev->gui_module && dev->gui_module->request_color_pick && ctl->button_down && ctl->button_down_which == 1) { // module requested a color box float zoom_x, zoom_y, bzoom_x, bzoom_y; dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y); dt_dev_get_pointer_zoom_pos(dev, ctl->button_x + offx, ctl->button_y + offy, &bzoom_x, &bzoom_y); if(darktable.lib->proxy.colorpicker.size) { dev->gui_module->color_picker_box[0] = fmaxf(0.0, fminf(.5f+bzoom_x, .5f+zoom_x)); dev->gui_module->color_picker_box[1] = fmaxf(0.0, fminf(.5f+bzoom_y, .5f+zoom_y)); dev->gui_module->color_picker_box[2] = fminf(1.0, fmaxf(.5f+bzoom_x, .5f+zoom_x)); dev->gui_module->color_picker_box[3] = fminf(1.0, fmaxf(.5f+bzoom_y, .5f+zoom_y)); } else { dev->gui_module->color_picker_point[0] = .5f + zoom_x; dev->gui_module->color_picker_point[1] = .5f + zoom_y; } dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; dt_dev_invalidate_all(dev); dt_control_queue_redraw(); return; } if(dev->gui_module && dev->gui_module->mouse_moved) handled = dev->gui_module->mouse_moved(dev->gui_module, x, y, which); if(handled) return; if(darktable.control->button_down && darktable.control->button_down_which == 1) { // depending on dev_zoom, adjust dev_zoom_x/y. dt_dev_zoom_t zoom; int closeup; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); int procw, proch; dt_dev_get_processed_size(dev, &procw, &proch); const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0); float old_zoom_x, old_zoom_y; DT_CTL_GET_GLOBAL(old_zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(old_zoom_y, dev_zoom_y); float zx = old_zoom_x - (1.0/scale)*(x - ctl->button_x - offx)/procw; float zy = old_zoom_y - (1.0/scale)*(y - ctl->button_y - offy)/proch; dt_dev_check_zoom_bounds(dev, &zx, &zy, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zx); DT_CTL_SET_GLOBAL(dev_zoom_y, zy); ctl->button_x = x - offx; ctl->button_y = y - offy; dt_dev_invalidate(dev); dt_control_queue_redraw(); } }