1 /*
2 This file is part of darktable,
3 Copyright (C) 2019-2020 darktable developers.
4
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.
9
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.
14
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/>.
17 */
18
19 #include "common/darktable.h"
20 #include "common/debug.h"
21 #include "control/signal.h"
22 #include "bauhaus/bauhaus.h"
23 #include "gui/gtk.h"
24 #include "libs/lib.h"
25 #include <gtk/gtk.h>
26 #include <stdlib.h>
27
28 DT_MODULE(1)
29
30 typedef struct dt_lib_ioporder_t
31 {
32 int current_mode;
33 GList *last_custom_iop_order;
34 GtkWidget *widget;
35 } dt_lib_ioporder_t;
36
name(dt_lib_module_t * self)37 const char *name(dt_lib_module_t *self)
38 {
39 return _("module order");
40 }
41
views(dt_lib_module_t * self)42 const char **views(dt_lib_module_t *self)
43 {
44 static const char *v[] = {"darkroom", NULL};
45 return v;
46 }
47
container(dt_lib_module_t * self)48 uint32_t container(dt_lib_module_t *self)
49 {
50 return DT_UI_CONTAINER_PANEL_RIGHT_BOTTOM;
51 }
52
position()53 int position()
54 {
55 return 880;
56 }
57
update(dt_lib_module_t * self)58 void update(dt_lib_module_t *self)
59 {
60 dt_lib_ioporder_t *d = (dt_lib_ioporder_t *)self->data;
61
62 const dt_iop_order_t kind = dt_ioppr_get_iop_order_list_kind(darktable.develop->iop_order_list);
63
64 if(kind == DT_IOP_ORDER_CUSTOM)
65 {
66 gchar *iop_order_list = dt_ioppr_serialize_text_iop_order_list(darktable.develop->iop_order_list);
67 gboolean found = FALSE;
68 int index = 0;
69
70 sqlite3_stmt *stmt;
71
72 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
73 "SELECT op_params, name"
74 " FROM data.presets"
75 " WHERE operation='ioporder'"
76 " ORDER BY writeprotect DESC", -1, &stmt, NULL);
77
78 while(sqlite3_step(stmt) == SQLITE_ROW)
79 {
80 const char *params = (char *)sqlite3_column_blob(stmt, 0);
81 const int32_t params_len = sqlite3_column_bytes(stmt, 0);
82 const char *name = (const char *)sqlite3_column_text(stmt, 1);
83 GList *iop_list = dt_ioppr_deserialize_iop_order_list(params, params_len);
84 gchar *iop_list_text = dt_ioppr_serialize_text_iop_order_list(iop_list);
85 g_list_free(iop_list);
86 index++;
87
88 if(!strcmp(iop_order_list, iop_list_text))
89 {
90 gtk_label_set_text(GTK_LABEL(d->widget), name);
91 d->current_mode = index;
92 found = TRUE;
93 g_free(iop_list_text);
94 break;
95 }
96
97 g_free(iop_list_text);
98 }
99
100 sqlite3_finalize(stmt);
101
102 g_free(iop_order_list);
103
104 if(!found)
105 {
106 d->current_mode = DT_IOP_ORDER_CUSTOM;
107 gtk_label_set_text(GTK_LABEL(d->widget), _(dt_iop_order_string(DT_IOP_ORDER_CUSTOM)));
108 }
109 }
110 else if(kind == DT_IOP_ORDER_LEGACY)
111 {
112 d->current_mode = kind;
113 gtk_label_set_text(GTK_LABEL(d->widget), _(dt_iop_order_string(DT_IOP_ORDER_LEGACY)));
114 }
115 else if(kind == DT_IOP_ORDER_V30)
116 {
117 d->current_mode = kind;
118 gtk_label_set_text(GTK_LABEL(d->widget), _(dt_iop_order_string(DT_IOP_ORDER_V30)));
119 }
120 }
121
_invalidate_pipe(dt_develop_t * dev)122 static void _invalidate_pipe(dt_develop_t *dev)
123 {
124 // we rebuild the pipe
125 dev->pipe->changed |= DT_DEV_PIPE_REMOVE;
126 dev->preview_pipe->changed |= DT_DEV_PIPE_REMOVE;
127 dev->preview2_pipe->changed |= DT_DEV_PIPE_REMOVE;
128 dev->pipe->cache_obsolete = 1;
129 dev->preview_pipe->cache_obsolete = 1;
130 dev->preview2_pipe->cache_obsolete = 1;
131
132 // invalidate buffers and force redraw of darkroom
133 dt_dev_invalidate_all(dev);
134 }
135
_image_loaded_callback(gpointer instance,gpointer user_data)136 static void _image_loaded_callback(gpointer instance, gpointer user_data)
137 {
138 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
139 update(self);
140 }
141
gui_init(dt_lib_module_t * self)142 void gui_init(dt_lib_module_t *self)
143 {
144 dt_lib_ioporder_t *d = (dt_lib_ioporder_t *)malloc(sizeof(dt_lib_ioporder_t));
145
146 self->data = (void *)d;
147 self->widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
148
149 GtkWidget *label = gtk_label_new(_("current order"));
150
151 d->widget = gtk_label_new("");
152 d->current_mode = -1;
153 d->last_custom_iop_order = NULL;
154
155 gtk_box_pack_start(GTK_BOX(self->widget), label, TRUE, TRUE, 0);
156 gtk_box_pack_start(GTK_BOX(self->widget), d->widget, TRUE, TRUE, 0);
157
158 DT_DEBUG_CONTROL_SIGNAL_CONNECT(darktable.signals, DT_SIGNAL_DEVELOP_IMAGE_CHANGED,
159 G_CALLBACK(_image_loaded_callback), self);
160 DT_DEBUG_CONTROL_SIGNAL_CONNECT(darktable.signals, DT_SIGNAL_DEVELOP_INITIALIZE,
161 G_CALLBACK(_image_loaded_callback), self);
162 DT_DEBUG_CONTROL_SIGNAL_CONNECT(darktable.signals, DT_SIGNAL_DEVELOP_HISTORY_CHANGE,
163 G_CALLBACK(_image_loaded_callback), self);
164 }
165
gui_cleanup(dt_lib_module_t * self)166 void gui_cleanup(dt_lib_module_t *self)
167 {
168 free(self->data);
169 self->data = NULL;
170 }
171
gui_reset(dt_lib_module_t * self)172 void gui_reset (dt_lib_module_t *self)
173 {
174 dt_lib_ioporder_t *d = (dt_lib_ioporder_t *)self->data;
175
176 // the module reset is use to select the v3.0 iop-order
177
178 GList *iop_order_list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30);
179
180 if(iop_order_list)
181 {
182 const int32_t imgid = darktable.develop->image_storage.id;
183
184 dt_ioppr_change_iop_order(darktable.develop, imgid, iop_order_list);
185
186 _invalidate_pipe(darktable.develop);
187
188 d->current_mode = DT_IOP_ORDER_V30;
189 gtk_label_set_text(GTK_LABEL(d->widget), _("v3.0"));
190 g_list_free_full(iop_order_list, free);
191 }
192 }
193
init_presets(dt_lib_module_t * self)194 void init_presets(dt_lib_module_t *self)
195 {
196 size_t size = 0;
197 char *params = NULL;
198 GList *list;
199
200 list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_LEGACY);
201 params = dt_ioppr_serialize_iop_order_list(list, &size);
202 dt_lib_presets_add(_("legacy"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE);
203 free(params);
204
205 list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30);
206 params = dt_ioppr_serialize_iop_order_list(list, &size);
207 dt_lib_presets_add(_("v3.0 (default)"), self->plugin_name, self->version(), (const char *)params, (int32_t)size,
208 TRUE);
209 free(params);
210 }
211
set_params(dt_lib_module_t * self,const void * params,int size)212 int set_params(dt_lib_module_t *self, const void *params, int size)
213 {
214 if(!params) return 1;
215
216 GList *iop_order_list = dt_ioppr_deserialize_iop_order_list(params, (size_t)size);
217
218 if(iop_order_list)
219 {
220 const int32_t imgid = darktable.develop->image_storage.id;
221
222 dt_ioppr_change_iop_order(darktable.develop, imgid, iop_order_list);
223
224 _invalidate_pipe(darktable.develop);
225
226 update(self);
227
228 g_list_free_full(iop_order_list, free);
229 return 0;
230 }
231 else
232 {
233 return 1;
234 }
235 }
236
get_params(dt_lib_module_t * self,int * size)237 void *get_params(dt_lib_module_t *self, int *size)
238 {
239 size_t p_size = 0;
240 void *params = dt_ioppr_serialize_iop_order_list(darktable.develop->iop_order_list, &p_size);
241 *size = (int)p_size;
242
243 return params;
244 }
245
246 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
247 // vim: shiftwidth=2 expandtab tabstop=2 cindent
248 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
249