2
This file is part of darktable,
3
copyright (c) 2009--2010 johannes hanika.
5
darktable is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
10
darktable is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with darktable. If not, see <http://www.gnu.org/licenses/>.
18
/** this is the view for the darkroom module. */
19
#include "views/view.h"
20
#include "develop/develop.h"
21
#include "control/jobs.h"
22
#include "control/control.h"
23
#include "control/conf.h"
24
#include "develop/imageop.h"
25
#include "common/image_cache.h"
26
#include "common/imageio.h"
27
#include "common/debug.h"
29
#include "gui/metadata.h"
30
#include "gui/iop_modulegroups.h"
35
#include <glade/glade.h>
36
#include <gdk/gdkkeysyms.h>
41
*name(dt_view_t *self)
50
self->data = malloc(sizeof(dt_develop_t));
51
dt_dev_init((dt_develop_t *)self->data, 1);
56
void cleanup(dt_view_t *self)
58
dt_develop_t *dev = (dt_develop_t *)self->data;
64
void expose(dt_view_t *self, cairo_t *cri, int32_t width_i, int32_t height_i, int32_t pointerx, int32_t pointery)
66
// if width or height > max pipeline pixels: center the view and clamp.
67
int32_t width = MIN(width_i, DT_IMAGE_WINDOW_SIZE);
68
int32_t height = MIN(height_i, DT_IMAGE_WINDOW_SIZE);
70
cairo_set_source_rgb (cri, .2, .2, .2);
71
cairo_rectangle(cri, 0, 0, fmaxf(0, width_i-DT_IMAGE_WINDOW_SIZE) *.5f, height);
73
cairo_rectangle(cri, fmaxf(0.0, width_i-DT_IMAGE_WINDOW_SIZE) *.5f + width, 0, width_i, height);
76
if(width_i > DT_IMAGE_WINDOW_SIZE) cairo_translate(cri, -(DT_IMAGE_WINDOW_SIZE-width_i) *.5f, 0.0f);
77
if(height_i > DT_IMAGE_WINDOW_SIZE) cairo_translate(cri, 0.0f, -(DT_IMAGE_WINDOW_SIZE-height_i)*.5f);
80
dt_develop_t *dev = (dt_develop_t *)self->data;
84
// synch module guis from gtk thread:
85
darktable.gui->reset = 1;
86
GList *modules = dev->iop;
89
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
90
dt_iop_gui_update(module);
91
modules = g_list_next(modules);
93
darktable.gui->reset = 0;
97
if(dev->image_dirty || dev->pipe->input_timestamp < dev->preview_pipe->input_timestamp) dt_dev_process_image(dev);
98
if(dev->preview_dirty) dt_dev_process_preview(dev);
100
dt_pthread_mutex_t *mutex = NULL;
101
int wd, ht, stride, closeup;
103
float zoom_x, zoom_y;
104
DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y);
105
DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
106
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
107
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
108
static cairo_surface_t *image_surface = NULL;
109
static int image_surface_width = 0, image_surface_height = 0, image_surface_imgid = -1;
111
if(image_surface_width != width || image_surface_height != height || image_surface == NULL)
113
// create double-buffered image to draw on, to make modules draw more fluently.
114
image_surface_width = width;
115
image_surface_height = height;
116
if(image_surface) cairo_surface_destroy(image_surface);
117
image_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
119
cairo_surface_t *surface;
120
cairo_t *cr = cairo_create(image_surface);
122
// adjust scroll bars
124
float zx = zoom_x, zy = zoom_y, boxw = 1., boxh = 1.;
125
dt_dev_check_zoom_bounds(dev, &zx, &zy, zoom, closeup, &boxw, &boxh);
126
dt_view_set_scrollbar(self, zx+.5-boxw*.5, 1.0, boxw, zy+.5-boxh*.5, 1.0, boxh);
129
if(!dev->image_dirty && dev->pipe->input_timestamp >= dev->preview_pipe->input_timestamp)
132
mutex = &dev->pipe->backbuf_mutex;
133
dt_pthread_mutex_lock(mutex);
134
wd = dev->pipe->backbuf_width;
135
ht = dev->pipe->backbuf_height;
136
stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd);
137
surface = cairo_image_surface_create_for_data (dev->pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride);
138
cairo_set_source_rgb (cr, .2, .2, .2);
140
cairo_translate(cr, .5f*(width-wd), .5f*(height-ht));
143
const float closeup_scale = 2.0;
144
cairo_scale(cr, closeup_scale, closeup_scale);
145
float boxw = 1, boxh = 1, zx0 = zoom_x, zy0 = zoom_y, zx1 = zoom_x, zy1 = zoom_y, zxm = -1.0, zym = -1.0;
146
dt_dev_check_zoom_bounds(dev, &zx0, &zy0, zoom, 0, &boxw, &boxh);
147
dt_dev_check_zoom_bounds(dev, &zx1, &zy1, zoom, 1, &boxw, &boxh);
148
dt_dev_check_zoom_bounds(dev, &zxm, &zym, zoom, 1, &boxw, &boxh);
149
const float fx = 1.0 - fmaxf(0.0, (zx0 - zx1)/(zx0 - zxm)), fy = 1.0 - fmaxf(0.0, (zy0 - zy1)/(zy0 - zym));
150
cairo_translate(cr, -wd/(2.0*closeup_scale) * fx, -ht/(2.0*closeup_scale) * fy);
152
cairo_rectangle(cr, 0, 0, wd, ht);
153
cairo_set_source_surface (cr, surface, 0, 0);
154
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);
155
cairo_fill_preserve(cr);
156
cairo_set_line_width(cr, 1.0);
157
cairo_set_source_rgb (cr, .3, .3, .3);
159
cairo_surface_destroy (surface);
160
dt_pthread_mutex_unlock(mutex);
161
image_surface_imgid = dev->image->id;
163
else if(!dev->preview_dirty)
164
// else if(!dev->preview_loading)
167
mutex = &dev->preview_pipe->backbuf_mutex;
168
dt_pthread_mutex_lock(mutex);
170
wd = dev->preview_pipe->backbuf_width;
171
ht = dev->preview_pipe->backbuf_height;
172
float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1);
173
cairo_set_source_rgb (cr, .2, .2, .2);
175
cairo_rectangle(cr, 0, 0, width, height);
177
stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd);
178
surface = cairo_image_surface_create_for_data (dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride);
179
cairo_translate(cr, width/2.0, height/2.0f);
180
cairo_scale(cr, zoom_scale, zoom_scale);
181
cairo_translate(cr, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht);
182
// avoid to draw the 1px garbage that sometimes shows up in the preview :(
183
cairo_rectangle(cr, 0, 0, wd-1, ht-1);
184
cairo_set_source_surface (cr, surface, 0, 0);
185
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);
187
cairo_surface_destroy (surface);
188
dt_pthread_mutex_unlock(mutex);
189
image_surface_imgid = dev->image->id;
193
if(image_surface_imgid == dev->image->id)
196
cairo_set_source_surface(cri, image_surface, 0, 0);
200
if(darktable.gui->request_snapshot)
202
cairo_surface_write_to_png(image_surface, darktable.gui->snapshot[0].filename);
203
darktable.gui->request_snapshot = 0;
205
// and if a snapshot is currently selected, draw it on top!
206
if(darktable.gui->snapshot_image)
208
cairo_set_source_surface(cri, darktable.gui->snapshot_image, 0, 0);
209
cairo_rectangle(cri, 0, 0, width*.5f, height);
211
cairo_set_source_rgb(cri, .7, .7, .7);
212
cairo_set_line_width(cri, 1.0);
213
cairo_move_to(cri, width*.5f, 0.0f);
214
cairo_line_to(cri, width*.5f, height);
218
// execute module callback hook.
219
if(dev->gui_module && dev->gui_module->request_color_pick)
221
int32_t zoom, closeup;
222
float zoom_x, zoom_y;
223
float wd = dev->preview_pipe->backbuf_width;
224
float ht = dev->preview_pipe->backbuf_height;
225
DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y);
226
DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
227
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
228
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
229
float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1);
231
cairo_translate(cri, width/2.0, height/2.0f);
232
cairo_scale(cri, zoom_scale, zoom_scale);
233
cairo_translate(cri, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht);
235
// cairo_set_operator(cri, CAIRO_OPERATOR_XOR);
236
cairo_set_line_width(cri, 1.0/zoom_scale);
237
cairo_set_source_rgb(cri, .2, .2, .2);
239
float *box = dev->gui_module->color_picker_box;
240
cairo_rectangle(cri, box[0]*wd, box[1]*ht, (box[2] - box[0])*wd, (box[3] - box[1])*ht);
242
cairo_translate(cri, 1.0/zoom_scale, 1.0/zoom_scale);
243
cairo_set_source_rgb(cri, .8, .8, .8);
244
cairo_rectangle(cri, box[0]*wd, box[1]*ht, (box[2] - box[0])*wd, (box[3] - box[1])*ht);
247
else if(dev->gui_module && dev->gui_module->gui_post_expose)
249
if(width_i > DT_IMAGE_WINDOW_SIZE) pointerx += (DT_IMAGE_WINDOW_SIZE-width_i) *.5f;
250
if(height_i > DT_IMAGE_WINDOW_SIZE) pointery += (DT_IMAGE_WINDOW_SIZE-height_i)*.5f;
251
dev->gui_module->gui_post_expose(dev->gui_module, cri, width, height, pointerx, pointery);
256
void reset(dt_view_t *self)
258
DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FIT);
259
DT_CTL_SET_GLOBAL(dev_zoom_x, 0);
260
DT_CTL_SET_GLOBAL(dev_zoom_y, 0);
261
DT_CTL_SET_GLOBAL(dev_closeup, 0);
265
static void module_show_callback(GtkToggleButton *togglebutton, gpointer user_data)
267
dt_iop_module_t *module = (dt_iop_module_t *)user_data;
269
snprintf(option, 512, "plugins/darkroom/%s/visible", module->op);
270
if(gtk_toggle_button_get_active(togglebutton))
272
dt_gui_iop_modulegroups_switch(module->groups());
273
gtk_widget_show(GTK_WIDGET(module->topwidget));
274
dt_conf_set_bool (option, TRUE);
275
gtk_expander_set_expanded(module->expander, TRUE);
276
snprintf(option, 512, _("hide %s"), module->name());
280
gtk_widget_hide(GTK_WIDGET(module->topwidget));
281
dt_conf_set_bool (option, FALSE);
282
gtk_expander_set_expanded(module->expander, FALSE);
283
snprintf(option, 512, _("show %s"), module->name());
285
gtk_object_set(GTK_OBJECT(module->showhide), "tooltip-text", option, (char *)NULL);
289
int try_enter(dt_view_t *self)
291
dt_develop_t *dev = (dt_develop_t *)self->data;
293
DT_CTL_GET_GLOBAL(selected, lib_image_mouse_over_id);
298
DT_DEBUG_SQLITE3_PREPARE_V2(darktable.db, "select * from selected_images", -1, &stmt, NULL);
299
if(sqlite3_step(stmt) == SQLITE_ROW)
300
selected = sqlite3_column_int(stmt, 0);
301
sqlite3_finalize(stmt);
307
dt_control_log(_("no image selected!"));
311
// this loads the image from db if needed:
312
dev->image = dt_image_cache_get(selected, 'r');
313
// get image and check if it has been deleted from disk first!
314
char imgfilename[1024];
315
dt_image_full_path(dev->image->id, imgfilename, 1024);
316
if(!g_file_test(imgfilename, G_FILE_TEST_IS_REGULAR))
318
dt_control_log(_("image `%s' is currently unavailable"), dev->image->filename);
319
// dt_image_remove(selected);
320
dt_image_cache_release(dev->image, 'r');
330
select_this_image(const int imgid)
332
// select this image, if no multiple selection:
335
DT_DEBUG_SQLITE3_PREPARE_V2(darktable.db, "select count(imgid) from selected_images", -1, &stmt, NULL);
336
if(sqlite3_step(stmt) == SQLITE_ROW)
337
count = sqlite3_column_int(stmt, 0);
338
sqlite3_finalize(stmt);
341
DT_DEBUG_SQLITE3_EXEC(darktable.db, "delete from selected_images", NULL, NULL, NULL);
342
DT_DEBUG_SQLITE3_PREPARE_V2(darktable.db, "insert into selected_images values (?1)", -1, &stmt, NULL);
343
DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
345
sqlite3_finalize(stmt);
350
dt_dev_change_image(dt_develop_t *dev, dt_image_t *image)
352
// stare last active group
353
dt_conf_set_int("plugins/darkroom/groups", dt_gui_iop_modulegroups_get());
354
// store last active plugin:
355
if(darktable.develop->gui_module)
356
dt_conf_set_string("plugins/darkroom/active", darktable.develop->gui_module->op);
358
dt_conf_set_string("plugins/darkroom/active", "");
359
g_assert(dev->gui_attached);
360
// commit image ops to db
361
dt_dev_write_history(dev);
363
dt_image_write_sidecar_file(dev->image->id);
365
// commit updated mipmaps to db
367
dt_dev_process_to_mip(dev);
368
// release full buffer
369
if(dev->image && dev->image->pixels)
370
dt_image_release(dev->image, DT_IMAGE_FULL, 'r');
372
dt_image_cache_flush(dev->image);
377
// clear history of old image
378
free(((dt_dev_history_item_t *)dev->history->data)->params);
379
free( (dt_dev_history_item_t *)dev->history->data);
380
dev->history = g_list_delete_link(dev->history, dev->history);
382
GList *modules = g_list_last(dev->iop);
385
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
386
if(strcmp(module->op, "gamma"))
389
snprintf(var, 1024, "plugins/darkroom/%s/expanded", module->op);
390
dt_conf_set_bool(var, gtk_expander_get_expanded (module->expander));
392
GtkWidget *top = GTK_WIDGET(module->topwidget);
393
GtkWidget *exp = GTK_WIDGET(module->expander);
394
GtkWidget *shh = GTK_WIDGET(module->showhide);
395
GtkWidget *parent = NULL;
396
g_object_get(G_OBJECT(module->widget), "parent", &parent, (char *)NULL);
397
// re-init and re-gui_init
398
module->gui_cleanup(module);
399
gtk_widget_destroy(GTK_WIDGET(module->widget));
400
dt_iop_reload_defaults(module);
401
module->gui_init(module);
402
// copy over already inited stuff:
403
module->topwidget = top;
404
module->expander = GTK_EXPANDER(exp);
405
module->showhide = shh;
407
gtk_container_add(GTK_CONTAINER(parent), module->widget);
408
gtk_widget_show_all(module->topwidget);
409
// all the signal handlers get passed module*, which is still valid.
411
modules = g_list_previous(modules);
413
// hack: now hide all custom expander widgets again.
417
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
418
if(strcmp(module->op, "gamma"))
421
snprintf(option, 1024, "plugins/darkroom/%s/visible", module->op);
422
gboolean active = dt_conf_get_bool (option);
423
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->showhide), !active);
424
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->showhide), active);
426
snprintf(option, 1024, "plugins/darkroom/%s/expanded", module->op);
427
active = dt_conf_get_bool (option);
428
gtk_expander_set_expanded (module->expander, active);
432
gtk_widget_hide_all(GTK_WIDGET(module->topwidget));
434
modules = g_list_next(modules);
436
dt_gui_iop_modulegroups_switch(dt_conf_get_int("plugins/darkroom/groups"));
437
dt_dev_read_history(dev);
438
dt_dev_pop_history_items(dev, dev->history_end);
439
dt_dev_raw_reload(dev);
441
// get last active plugin:
442
gchar *active_plugin = dt_conf_get_string("plugins/darkroom/active");
448
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
449
if(!strcmp(module->op, active_plugin))
450
dt_iop_request_focus(module);
451
modules = g_list_next(modules);
453
g_free(active_plugin);
458
film_strip_activated(const int imgid, void *data)
460
// switch images in darkroom mode:
461
dt_view_t *self = (dt_view_t *)data;
462
dt_develop_t *dev = (dt_develop_t *)self->data;
463
dt_image_t *image = dt_image_cache_get(imgid, 'r');
464
dt_dev_change_image(dev, image);
465
// release image struct with metadata.
466
dt_image_cache_release(dev->image, 'r');
467
// select newly loaded image
468
select_this_image(dev->image->id);
470
dt_control_queue_draw_all();
471
// prefetch next few from first selected image on.
472
dt_view_film_strip_prefetch();
476
zoom_key_accel(void *data)
478
dt_develop_t *dev = darktable.develop;
480
float zoom_x, zoom_y;
481
switch ((long int)data)
484
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
485
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
486
if(zoom == DT_ZOOM_1) closeup ^= 1;
487
DT_CTL_SET_GLOBAL(dev_closeup, closeup);
488
DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_1);
489
dt_dev_invalidate(dev);
492
DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FILL);
493
dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, DT_ZOOM_FILL, 0, NULL, NULL);
494
DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x);
495
DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y);
496
DT_CTL_SET_GLOBAL(dev_closeup, 0);
497
dt_dev_invalidate(dev);
500
DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FIT);
501
DT_CTL_SET_GLOBAL(dev_zoom_x, 0);
502
DT_CTL_SET_GLOBAL(dev_zoom_y, 0);
503
DT_CTL_SET_GLOBAL(dev_closeup, 0);
504
dt_dev_invalidate(dev);
512
film_strip_key_accel(void *data)
514
dt_view_film_strip_toggle(darktable.view_manager, film_strip_activated, data);
515
dt_control_queue_draw_all();
518
void enter(dt_view_t *self)
520
dt_print(DT_DEBUG_CONTROL, "[run_job+] 11 %f in darkroom mode\n", dt_get_wtime());
521
dt_develop_t *dev = (dt_develop_t *)self->data;
523
select_this_image(dev->image->id);
525
DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FIT);
526
DT_CTL_SET_GLOBAL(dev_zoom_x, 0);
527
DT_CTL_SET_GLOBAL(dev_zoom_y, 0);
528
DT_CTL_SET_GLOBAL(dev_closeup, 0);
530
dev->gui_leaving = 0;
531
dev->gui_module = NULL;
532
dt_dev_load_image(dev, dev->image);
536
gtk_widget_set_visible (glade_xml_get_widget (darktable.gui->main_window, "modulegroups_eventbox"), TRUE);
538
widget = glade_xml_get_widget (darktable.gui->main_window, "navigation_expander");
539
gtk_widget_set_visible(widget, TRUE);
540
widget = glade_xml_get_widget (darktable.gui->main_window, "histogram_expander");
541
gtk_widget_set_visible(widget, TRUE);
542
widget = glade_xml_get_widget (darktable.gui->main_window, "snapshots_eventbox");
543
gtk_widget_set_visible(widget, TRUE);
544
widget = glade_xml_get_widget (darktable.gui->main_window, "history_eventbox");
545
gtk_widget_set_visible(widget, TRUE);
546
widget = glade_xml_get_widget (darktable.gui->main_window, "bottom_darkroom_box");
547
gtk_widget_set_visible(widget, TRUE);
548
widget = glade_xml_get_widget (darktable.gui->main_window, "bottom_lighttable_box");
549
gtk_widget_set_visible(widget, FALSE);
550
widget = glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox_left");
551
gtk_widget_set_visible(widget, FALSE);
552
widget = glade_xml_get_widget (darktable.gui->main_window, "import_eventbox");
553
gtk_widget_set_visible(widget, FALSE);
554
widget = glade_xml_get_widget (darktable.gui->main_window, "module_list_eventbox");
555
gtk_widget_set_visible(widget, TRUE);
557
// get top level vbox containing all expanders, plugins_vbox:
558
GtkBox *box = GTK_BOX(glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox"));
559
GtkTable *module_list = GTK_TABLE(glade_xml_get_widget (darktable.gui->main_window, "module_list"));
560
GList *modules = g_list_last(dev->iop);
564
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
565
module->gui_init(module);
566
// add the widget created by gui_init to an expander and both to list.
567
GtkWidget *expander = dt_iop_gui_get_expander(module);
568
module->topwidget = GTK_WIDGET(expander);
569
gtk_box_pack_start(box, expander, FALSE, FALSE, 0);
570
if(strcmp(module->op, "gamma"))
572
module->showhide = gtk_toggle_button_new();
573
char filename[1024], datadir[1024];
574
dt_get_datadir(datadir, 1024);
575
snprintf(filename, 1024, "%s/pixmaps/plugins/darkroom/%s.png", datadir, module->op);
576
if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
577
snprintf(filename, 1024, "%s/pixmaps/plugins/darkroom/template.png", datadir);
578
GtkWidget *image = gtk_image_new_from_file(filename);
579
gtk_button_set_image(GTK_BUTTON(module->showhide), image);
580
g_signal_connect(G_OBJECT(module->showhide), "toggled",
581
G_CALLBACK(module_show_callback), module);
582
gtk_table_attach(module_list, module->showhide, ti, ti+1, tj, tj+1,
583
GTK_FILL | GTK_EXPAND | GTK_SHRINK,
593
modules = g_list_previous(modules);
595
// end marker widget:
596
GtkWidget *endmarker = gtk_drawing_area_new();
598
gtk_box_pack_start(box, endmarker, FALSE, FALSE, 0);
599
g_signal_connect (G_OBJECT (endmarker), "expose-event",
600
G_CALLBACK (dt_control_expose_endmarker), 0);
601
gtk_widget_set_size_request(endmarker, -1, 50);
603
gtk_widget_show_all(GTK_WIDGET(box));
604
gtk_widget_show_all(GTK_WIDGET(module_list));
607
/* set list of modules to modulegroups */
608
dt_gui_iop_modulegroups_set_list (dev->iop);
610
// hack: now hide all custom expander widgets again.
614
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
615
if(strcmp(module->op, "gamma"))
618
snprintf(option, 1024, "plugins/darkroom/%s/visible", module->op);
619
gboolean active = dt_conf_get_bool (option);
620
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->showhide), !active);
621
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->showhide), active);
623
snprintf(option, 1024, "plugins/darkroom/%s/expanded", module->op);
624
active = dt_conf_get_bool (option);
625
gtk_expander_set_expanded (module->expander, active);
629
gtk_widget_hide_all(GTK_WIDGET(module->topwidget));
631
modules = g_list_next(modules);
635
// synch gui and flag gegl pipe as dirty
636
// FIXME: this assumes static pipeline as well
637
// this is done here and not in dt_read_history, as it would else be triggered before module->gui_init.
638
dt_dev_pop_history_items(dev, dev->history_end);
640
if(dt_conf_get_bool("plugins/filmstrip/on"))
642
// double click callback:
643
dt_view_film_strip_scroll_to(darktable.view_manager, dev->image->id);
644
dt_view_film_strip_open(darktable.view_manager, film_strip_activated, self);
645
dt_view_film_strip_prefetch();
647
dt_gui_key_accel_register(GDK_CONTROL_MASK, GDK_f, film_strip_key_accel, self);
648
dt_gui_key_accel_register(GDK_MOD1_MASK, GDK_1, zoom_key_accel, (void *)1);
649
dt_gui_key_accel_register(GDK_MOD1_MASK, GDK_2, zoom_key_accel, (void *)2);
650
dt_gui_key_accel_register(GDK_MOD1_MASK, GDK_3, zoom_key_accel, (void *)3);
652
// switch on groups as they where last time:
653
dt_gui_iop_modulegroups_switch(dt_conf_get_int("plugins/darkroom/groups"));
655
// get last active plugin:
656
gchar *active_plugin = dt_conf_get_string("plugins/darkroom/active");
662
dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
663
if(!strcmp(module->op, active_plugin))
664
dt_iop_request_focus(module);
665
modules = g_list_next(modules);
667
g_free(active_plugin);
670
// image should be there now.
671
float zoom_x, zoom_y;
672
dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, DT_ZOOM_FIT, 0, NULL, NULL);
673
DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x);
674
DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y);
679
dt_dev_remove_child(GtkWidget *widget, gpointer data)
681
gtk_container_remove(GTK_CONTAINER(data), widget);
684
void leave(dt_view_t *self)
686
// store groups for next time:
687
dt_conf_set_int("plugins/darkroom/groups", dt_gui_iop_modulegroups_get());
689
// store last active plugin:
690
if(darktable.develop->gui_module)
691
dt_conf_set_string("plugins/darkroom/active", darktable.develop->gui_module->op);
693
dt_conf_set_string("plugins/darkroom/active", "");
695
if(dt_conf_get_bool("plugins/filmstrip/on"))
696
dt_view_film_strip_close(darktable.view_manager);
697
dt_gui_key_accel_unregister(film_strip_key_accel);
698
dt_gui_key_accel_unregister(zoom_key_accel);
700
GList *childs = gtk_container_get_children (
701
GTK_CONTAINER (glade_xml_get_widget (darktable.gui->main_window, "bottom_left_toolbox")));
704
gtk_widget_destroy ( GTK_WIDGET (childs->data));
705
childs=g_list_next(childs);
709
widget = glade_xml_get_widget (darktable.gui->main_window, "navigation_expander");
710
gtk_widget_set_visible(widget, FALSE);
711
widget = glade_xml_get_widget (darktable.gui->main_window, "histogram_expander");
712
gtk_widget_set_visible(widget, FALSE);
713
widget = glade_xml_get_widget (darktable.gui->main_window, "snapshots_eventbox");
714
gtk_widget_set_visible(widget, FALSE);
715
widget = glade_xml_get_widget (darktable.gui->main_window, "history_eventbox");
716
gtk_widget_set_visible(widget, FALSE);
717
widget = glade_xml_get_widget (darktable.gui->main_window, "bottom_darkroom_box");
718
gtk_widget_set_visible(widget, FALSE);
719
widget = glade_xml_get_widget (darktable.gui->main_window, "bottom_lighttable_box");
720
gtk_widget_set_visible(widget, TRUE);
721
widget = glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox_left");
722
gtk_widget_set_visible(widget, TRUE);
723
widget = glade_xml_get_widget (darktable.gui->main_window, "module_list_eventbox");
724
gtk_widget_set_visible(widget, FALSE);
726
dt_develop_t *dev = (dt_develop_t *)self->data;
727
// commit image ops to db
728
dt_dev_write_history(dev);
730
dt_image_write_sidecar_file(dev->image->id);
732
// commit updated mipmaps to db
733
dt_dev_process_to_mip(dev);
736
dev->gui_leaving = 1;
737
dt_pthread_mutex_lock(&dev->history_mutex);
738
dt_dev_pixelpipe_cleanup_nodes(dev->pipe);
739
dt_dev_pixelpipe_cleanup_nodes(dev->preview_pipe);
740
GtkBox *box = GTK_BOX(glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox"));
743
dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(dev->history->data);
744
// printf("removing history item %d - %s, data %f %f\n", hist->module->instance, hist->module->op, *(float *)hist->params, *((float *)hist->params+1));
748
dev->history = g_list_delete_link(dev->history, dev->history);
752
dt_iop_module_t *module = (dt_iop_module_t *)(dev->iop->data);
753
// printf("removing module %d - %s\n", module->instance, module->op);
755
snprintf(var, 1024, "plugins/darkroom/%s/expanded", module->op);
756
dt_conf_set_bool(var, gtk_expander_get_expanded (module->expander));
758
module->gui_cleanup(module);
759
module->cleanup(module);
761
dev->iop = g_list_delete_link(dev->iop, dev->iop);
763
gtk_container_foreach(GTK_CONTAINER(box), (GtkCallback)dt_dev_remove_child, (gpointer)box);
764
dt_pthread_mutex_unlock(&dev->history_mutex);
766
// release full buffer
767
if(dev->image->pixels)
768
dt_image_release(dev->image, DT_IMAGE_FULL, 'r');
770
// release image struct with metadata as well.
771
dt_image_cache_flush(dev->image);
772
dt_image_cache_release(dev->image, 'r');
773
dt_print(DT_DEBUG_CONTROL, "[run_job-] 11 %f in darkroom mode\n", dt_get_wtime());
776
void mouse_leave(dt_view_t *self)
778
// if we are not hovering over a thumbnail in the filmstrip -> show metadata of opened image.
779
dt_develop_t *dev = (dt_develop_t *)self->data;
780
int32_t mouse_over_id = dev->image->id;
781
DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id);
782
dt_gui_metadata_update();
784
// reset any changes the selected plugin might have made.
785
dt_control_change_cursor(GDK_LEFT_PTR);
788
void mouse_moved(dt_view_t *self, double x, double y, int which)
790
dt_develop_t *dev = (dt_develop_t *)self->data;
792
// if we are not hovering over a thumbnail in the filmstrip -> show metadata of opened image.
793
int32_t mouse_over_id = -1;
794
DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id);
795
if(mouse_over_id == -1)
797
mouse_over_id = dev->image->id;
798
DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id);
799
dt_gui_metadata_update();
802
dt_control_t *ctl = darktable.control;
803
const int32_t width_i = self->width;
804
const int32_t height_i = self->height;
805
int32_t offx = 0.0f, offy = 0.0f;
806
if(width_i > DT_IMAGE_WINDOW_SIZE) offx = (DT_IMAGE_WINDOW_SIZE-width_i) *.5f;
807
if(height_i > DT_IMAGE_WINDOW_SIZE) offy = (DT_IMAGE_WINDOW_SIZE-height_i)*.5f;
811
if(dev->gui_module && dev->gui_module->request_color_pick &&
813
ctl->button_down_which == 1)
815
// module requested a color box
816
float zoom_x, zoom_y, bzoom_x, bzoom_y;
817
dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y);
818
dt_dev_get_pointer_zoom_pos(dev, ctl->button_x + offx, ctl->button_y + offy, &bzoom_x, &bzoom_y);
819
dev->gui_module->color_picker_box[0] = fmaxf(0.0, fminf(.5f+bzoom_x, .5f+zoom_x));
820
dev->gui_module->color_picker_box[1] = fmaxf(0.0, fminf(.5f+bzoom_y, .5f+zoom_y));
821
dev->gui_module->color_picker_box[2] = fminf(1.0, fmaxf(.5f+bzoom_x, .5f+zoom_x));
822
dev->gui_module->color_picker_box[3] = fminf(1.0, fmaxf(.5f+bzoom_y, .5f+zoom_y));
824
dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH;
825
dt_dev_invalidate_all(dev);
826
dt_control_queue_draw_all();
829
if(dev->gui_module && dev->gui_module->mouse_moved) handled = dev->gui_module->mouse_moved(dev->gui_module, x, y, which);
832
if(darktable.control->button_down && darktable.control->button_down_which == 1)
834
// depending on dev_zoom, adjust dev_zoom_x/y.
837
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
838
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
840
dt_dev_get_processed_size(dev, &procw, &proch);
841
const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0);
842
float old_zoom_x, old_zoom_y;
843
DT_CTL_GET_GLOBAL(old_zoom_x, dev_zoom_x);
844
DT_CTL_GET_GLOBAL(old_zoom_y, dev_zoom_y);
845
float zx = old_zoom_x - (1.0/scale)*(x - ctl->button_x - offx)/procw;
846
float zy = old_zoom_y - (1.0/scale)*(y - ctl->button_y - offy)/proch;
847
dt_dev_check_zoom_bounds(dev, &zx, &zy, zoom, closeup, NULL, NULL);
848
DT_CTL_SET_GLOBAL(dev_zoom_x, zx);
849
DT_CTL_SET_GLOBAL(dev_zoom_y, zy);
850
ctl->button_x = x - offx;
851
ctl->button_y = y - offy;
852
dt_dev_invalidate(dev);
853
dt_control_queue_draw_all();
858
int button_released(dt_view_t *self, double x, double y, int which, uint32_t state)
860
dt_develop_t *dev = darktable.develop;
862
if(dev->gui_module && dev->gui_module->button_released) handled = dev->gui_module->button_released(dev->gui_module, x, y, which, state);
863
if(handled) return handled;
864
if(which == 1) dt_control_change_cursor(GDK_LEFT_PTR);
869
int button_pressed(dt_view_t *self, double x, double y, int which, int type, uint32_t state)
871
dt_develop_t *dev = (dt_develop_t *)self->data;
872
const int32_t width_i = self->width;
873
const int32_t height_i = self->height;
874
if(width_i > DT_IMAGE_WINDOW_SIZE) x += (DT_IMAGE_WINDOW_SIZE-width_i) *.5f;
875
if(height_i > DT_IMAGE_WINDOW_SIZE) y += (DT_IMAGE_WINDOW_SIZE-height_i)*.5f;
878
if(dev->gui_module && dev->gui_module->request_color_pick && which == 1)
880
float zoom_x, zoom_y;
881
dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y);
882
dev->gui_module->color_picker_box[0] = .5f+zoom_x;
883
dev->gui_module->color_picker_box[1] = .5f+zoom_y;
884
dev->gui_module->color_picker_box[2] = .5f+zoom_x;
885
dev->gui_module->color_picker_box[3] = .5f+zoom_y;
886
dt_control_queue_draw_all();
889
if(dev->gui_module && dev->gui_module->button_pressed) handled = dev->gui_module->button_pressed(dev->gui_module, x, y, which, type, state);
890
if(handled) return handled;
892
if(which == 1 && type == GDK_2BUTTON_PRESS) return 0;
895
dt_control_change_cursor(GDK_HAND1);
900
// zoom to 1:1 2:1 and back
902
int closeup, procw, proch;
903
float zoom_x, zoom_y;
904
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
905
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
906
DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
907
DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y);
908
dt_dev_get_processed_size(dev, &procw, &proch);
909
const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0);
910
zoom_x += (1.0/scale)*(x - .5f*dev->width )/procw;
911
zoom_y += (1.0/scale)*(y - .5f*dev->height)/proch;
912
if(zoom == DT_ZOOM_1)
914
if(!closeup) closeup = 1;
918
zoom_x = zoom_y = 0.0f;
922
else zoom = DT_ZOOM_1;
923
dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL);
924
DT_CTL_SET_GLOBAL(dev_zoom, zoom);
925
DT_CTL_SET_GLOBAL(dev_closeup, closeup);
926
DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x);
927
DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y);
928
dt_dev_invalidate(dev);
935
void scrolled(dt_view_t *self, double x, double y, int up, int state)
938
dt_develop_t *dev = (dt_develop_t *)self->data;
940
int closeup, procw, proch;
941
float zoom_x, zoom_y;
942
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
943
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
944
DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
945
DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y);
946
dt_dev_get_processed_size(dev, &procw, &proch);
947
float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0);
948
const float minscale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, 1.0, 0);
949
// offset from center now (current zoom_{x,y} points there)
950
float mouse_off_x = x - .5*dev->width, mouse_off_y = y - .5*dev->height;
951
zoom_x += mouse_off_x/(procw*scale);
952
zoom_y += mouse_off_y/(proch*scale);
955
if(up) scale += .1f*(1.0f - minscale);
956
else scale -= .1f*(1.0f - minscale);
957
DT_CTL_SET_GLOBAL(dev_zoom_scale, scale);
958
if(scale > 0.99) zoom = DT_ZOOM_1;
959
if(scale < minscale + 0.01) zoom = DT_ZOOM_FIT;
960
if(zoom != DT_ZOOM_1)
962
zoom_x -= mouse_off_x/(procw*scale);
963
zoom_y -= mouse_off_y/(proch*scale);
965
dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL);
966
DT_CTL_SET_GLOBAL(dev_zoom, zoom);
967
DT_CTL_SET_GLOBAL(dev_closeup, closeup);
968
if(zoom != DT_ZOOM_1)
970
DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x);
971
DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y);
973
dt_dev_invalidate(dev);
977
void border_scrolled(dt_view_t *view, double x, double y, int which, int up)
979
dt_develop_t *dev = (dt_develop_t *)view->data;
982
float zoom_x, zoom_y, scale;
983
DT_CTL_GET_GLOBAL(zoom, dev_zoom);
984
DT_CTL_GET_GLOBAL(closeup, dev_closeup);
985
DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
986
DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y);
987
DT_CTL_GET_GLOBAL(scale, dev_zoom_scale);
990
if(up) zoom_x -= 0.02;
995
if(up) zoom_y -= 0.02;
998
dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL);
999
DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x);
1000
DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y);
1001
dt_dev_invalidate(dev);
1002
dt_control_queue_draw_all();
1006
int key_pressed(dt_view_t *self, uint16_t which)
1008
dt_develop_t *dev = (dt_develop_t *)self->data;
1010
if(dev->gui_module && dev->gui_module->key_pressed) handled = dev->gui_module->key_pressed(dev->gui_module, which);
1011
if(handled) return handled;
1016
void configure(dt_view_t *self, int wd, int ht)
1018
dt_develop_t *dev = (dt_develop_t *)self->data;
1019
dt_dev_configure(dev, wd, ht);