Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
backgroundjobs.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Henrik Andersson.
4 Copyright (C) 2011, 2013 Pascal de Bruijn.
5 Copyright (C) 2012-2013 parafin.
6 Copyright (C) 2012 Richard Wonka.
7 Copyright (C) 2012, 2014-2018 Tobias Ellinghaus.
8 Copyright (C) 2013 johannes hanika.
9 Copyright (C) 2013 Simon Spannagel.
10 Copyright (C) 2014 Edouard Gomez.
11 Copyright (C) 2014-2015 Jérémy Rosen.
12 Copyright (C) 2014, 2020-2021 Pascal Obry.
13 Copyright (C) 2014-2016 Roman Lebedev.
14 Copyright (C) 2019, 2025 Aurélien PIERRE.
15 Copyright (C) 2020 Marco.
16 Copyright (C) 2021 Ralf Brown.
17 Copyright (C) 2022 Aldric Renaudin.
18 Copyright (C) 2022 Martin Bařinka.
19 Copyright (C) 2022 Nicolas Auffray.
20
21 darktable is free software: you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation, either version 3 of the License, or
24 (at your option) any later version.
25
26 darktable is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with darktable. If not, see <http://www.gnu.org/licenses/>.
33*/
34
35#include "common/darktable.h"
36#include "common/debug.h"
37#include "common/image_cache.h"
38#include "control/conf.h"
39#include "control/control.h"
40#include "control/progress.h"
41#include "develop/develop.h"
42#include "dtgtk/button.h"
43#include "gui/draw.h"
44#include "gui/gtk.h"
45#include "libs/lib.h"
46#include "libs/lib_api.h"
47
48DT_MODULE(1)
49
51{
52 GtkWidget *widget, *label, *progressbar, *hbox;
54
55/* proxy functions */
56static void *_lib_backgroundjobs_added(dt_lib_module_t *self, gboolean has_progress_bar, const gchar *message);
59 dt_progress_t *progress);
61 double value);
63 const gchar *message);
64
65
66const char *name(struct dt_lib_module_t *self)
67{
68 return _("background jobs");
69}
70
71const char **views(dt_lib_module_t *self)
72{
73 static const char *v[] = {"*", NULL};
74 return v;
75}
76
81
83{
84 return 1;
85}
86
88{
89 return 0;
90}
91
93{
94 /* initialize base */
95 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
96 gtk_widget_set_no_show_all(self->widget, TRUE);
97
98 /* setup proxy */
100
101 darktable.control->progress_system.proxy.module = self;
107
108 // iterate over darktable.control->progress_system.list and add everything that is already there and update
109 // its gui_data!
110 for(const GList *iter = darktable.control->progress_system.list; iter; iter = g_list_next(iter))
111 {
112 dt_progress_t *progress = (dt_progress_t *)iter->data;
113 void *gui_data = dt_control_progress_get_gui_data(progress);
114 dt_free(gui_data);
117 dt_control_progress_set_gui_data(progress, gui_data);
118 if(dt_control_progress_cancellable(progress)) _lib_backgroundjobs_cancellable(self, gui_data, progress);
120 }
121
123}
124
136
143
144static gboolean _added_gui_thread(gpointer user_data)
145{
146 _added_gui_thread_t *params = (_added_gui_thread_t *)user_data;
147
148 /* lets show jobbox if its hidden */
149 gtk_box_pack_start(GTK_BOX(params->self_widget), params->instance_widget, TRUE, FALSE, 0);
150 gtk_box_reorder_child(GTK_BOX(params->self_widget), params->instance_widget, 1);
151 gtk_widget_show_all(params->instance_widget);
152 gtk_widget_show(params->self_widget);
153
154 dt_free(params);
155 return FALSE;
156}
157
158static void *_lib_backgroundjobs_added(dt_lib_module_t *self, gboolean has_progress_bar, const gchar *message)
159{
160 // add a new gui thingy
163 if(IS_NULL_PTR(instance)) return NULL;
165 if(IS_NULL_PTR(params))
166 {
167 dt_free(instance);
168 return NULL;
169 }
170
171 instance->widget = gtk_event_box_new();
172
173 /* initialize the ui elements for job */
174 gtk_widget_set_name(GTK_WIDGET(instance->widget), "background-job-eventbox");
175 dt_gui_add_class(GTK_WIDGET(instance->widget), "dt_big_btn_canvas");
176 GtkBox *vbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
177 instance->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
178 gtk_container_add(GTK_CONTAINER(instance->widget), GTK_WIDGET(vbox));
179
180 /* add job label */
181 instance->label = gtk_label_new(message);
182 gtk_widget_set_halign(instance->label, GTK_ALIGN_START);
183 gtk_label_set_ellipsize(GTK_LABEL(instance->label), PANGO_ELLIPSIZE_END);
184 gtk_box_pack_start(GTK_BOX(instance->hbox), GTK_WIDGET(instance->label), TRUE, TRUE, 0);
185 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(instance->hbox), TRUE, TRUE, 0);
186
187 /* use progressbar ? */
188 if(has_progress_bar)
189 {
190 instance->progressbar = gtk_progress_bar_new();
191 gtk_box_pack_start(GTK_BOX(vbox), instance->progressbar, TRUE, FALSE, 0);
192 }
193
194 /* lets show jobbox if its hidden */
195 params->self_widget = self->widget;
196 params->instance_widget = instance->widget;
197 g_main_context_invoke(NULL, _added_gui_thread, params);
198
199 // return the gui thingy container
200 return instance;
201}
202
208
209static gboolean _destroyed_gui_thread(gpointer user_data)
210{
212
213 /* remove job widget from jobbox */
214 if(params->instance->widget && GTK_IS_WIDGET(params->instance->widget))
215 gtk_container_remove(GTK_CONTAINER(params->self->widget), params->instance->widget);
216 params->instance->widget = NULL;
217
218 /* if jobbox is empty let's hide */
219 if(!dt_gui_container_has_children(GTK_CONTAINER(params->self->widget)))
220 gtk_widget_hide(params->self->widget);
221
222 // free data
223 dt_free(params->instance);
224 dt_free(params);
225 return FALSE;
226}
227
228// remove the gui that is pointed to in instance
230{
232 if(IS_NULL_PTR(params)) return;
233 params->self = self;
234 params->instance = instance;
235 g_main_context_invoke(NULL, _destroyed_gui_thread, params);
236}
237
238static void _lib_backgroundjobs_cancel_callback_new(GtkWidget *w, gpointer user_data)
239{
240 dt_progress_t *progress = (dt_progress_t *)user_data;
242}
243
249
250static gboolean _cancellable_gui_thread(gpointer user_data)
251{
253
254 GtkBox *hbox = GTK_BOX(params->instance->hbox);
256 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_lib_backgroundjobs_cancel_callback_new), params->progress);
257 gtk_box_pack_start(hbox, GTK_WIDGET(button), FALSE, FALSE, 0);
258 gtk_widget_show_all(button);
259
260 dt_free(params);
261 return FALSE;
262}
263
265 dt_progress_t *progress)
266{
267 // add a cancel button to the gui. when clicked we want dt_control_progress_cancel(darktable.control,
268 // progress); to be called
269 if(!darktable.control->running) return;
270
272 if(IS_NULL_PTR(params)) return;
273 params->instance = instance;
274 params->progress = progress;
275 g_main_context_invoke(NULL, _cancellable_gui_thread, params);
276}
277
283
284static gboolean _update_gui_thread(gpointer user_data)
285{
286 _update_gui_thread_t *params = (_update_gui_thread_t *)user_data;
287
288 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(params->instance->progressbar), CLAMP(params->value, 0, 1.0));
289
290 dt_free(params);
291 return FALSE;
292}
293
295 double value)
296{
297 // update the progress bar
298 if(!darktable.control->running) return;
299
301 if(IS_NULL_PTR(params)) return;
302 params->instance = instance;
303 params->value = value;
304 g_main_context_invoke(NULL, _update_gui_thread, params);
305}
306
312
313static gboolean _update_message_gui_thread(gpointer user_data)
314{
316
317 gtk_label_set_text(GTK_LABEL(params->instance->label), params->message);
318
319 dt_free(params->message);
320 dt_free(params);
321 return FALSE;
322}
323
325 const char *message)
326{
327 // update the progress bar
328 if(!darktable.control->running) return;
329
331 if(IS_NULL_PTR(params)) return;
332 params->instance = instance;
333 params->message = g_strdup(message);
334 g_main_context_invoke(NULL, _update_message_gui_thread, params);
335}
336
337// clang-format off
338// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
339// vim: shiftwidth=2 expandtab tabstop=2 cindent
340// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
341// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
static gboolean _added_gui_thread(gpointer user_data)
static void * _lib_backgroundjobs_added(dt_lib_module_t *self, gboolean has_progress_bar, const gchar *message)
static void _lib_backgroundjobs_updated(dt_lib_module_t *self, dt_lib_backgroundjob_element_t *instance, double value)
static gboolean _destroyed_gui_thread(gpointer user_data)
static gboolean _cancellable_gui_thread(gpointer user_data)
static void _lib_backgroundjobs_destroyed(dt_lib_module_t *self, dt_lib_backgroundjob_element_t *instance)
void gui_cleanup(dt_lib_module_t *self)
static void _lib_backgroundjobs_cancel_callback_new(GtkWidget *w, gpointer user_data)
static gboolean _update_gui_thread(gpointer user_data)
static void _lib_backgroundjobs_cancellable(dt_lib_module_t *self, dt_lib_backgroundjob_element_t *instance, dt_progress_t *progress)
uint32_t container(dt_lib_module_t *self)
static gboolean _update_message_gui_thread(gpointer user_data)
void gui_init(dt_lib_module_t *self)
int position()
const char ** views(dt_lib_module_t *self)
int expandable(dt_lib_module_t *self)
static void _lib_backgroundjobs_message_updated(dt_lib_module_t *self, dt_lib_backgroundjob_element_t *instance, const gchar *message)
GtkWidget * dtgtk_button_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
Definition button.c:134
char * name
darktable_t darktable
Definition darktable.c:181
#define DT_MODULE(MODVER)
Definition darktable.h:140
#define dt_free(ptr)
Definition darktable.h:456
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
void dtgtk_cairo_paint_cancel(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:364
gboolean dt_gui_container_has_children(GtkContainer *container)
Definition gtk.c:2862
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
Definition gtk.c:133
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
const float v
double dt_control_progress_get_progress(dt_progress_t *progress)
Definition progress.c:373
gboolean dt_control_progress_cancellable(dt_progress_t *progress)
Definition progress.c:427
const gchar * dt_control_progress_get_message(dt_progress_t *progress)
Definition progress.c:381
void dt_control_progress_set_gui_data(dt_progress_t *progress, void *data)
Definition progress.c:404
void dt_control_progress_cancel(dt_control_t *control, dt_progress_t *progress)
Definition progress.c:338
gboolean dt_control_progress_has_progress_bar(dt_progress_t *progress)
Definition progress.c:419
void * dt_control_progress_get_gui_data(dt_progress_t *progress)
Definition progress.c:411
struct _GtkWidget GtkWidget
Definition splash.h:29
GtkWidget * instance_widget
dt_lib_backgroundjob_element_t * instance
dt_lib_backgroundjob_element_t * instance
dt_lib_module_t * self
dt_lib_backgroundjob_element_t * instance
dt_lib_backgroundjob_element_t * instance
struct dt_control_t * control
Definition darktable.h:773
dt_pthread_mutex_t mutex
Definition control.h:276
int32_t running
Definition control.h:254
void(* destroyed)(dt_lib_module_t *self, struct dt_lib_backgroundjob_element_t *instance)
Definition control.h:287
struct dt_control_t::@13 progress_system
struct dt_control_t::@13::@15 proxy
GList * list
Definition control.h:272
void(* message_updated)(dt_lib_module_t *self, struct dt_lib_backgroundjob_element_t *instance, const char *message)
Definition control.h:291
void(* updated)(dt_lib_module_t *self, struct dt_lib_backgroundjob_element_t *instance, double value)
Definition control.h:290
dt_lib_module_t *void *(* added)(dt_lib_module_t *self, gboolean has_progress_bar, const gchar *message)
Definition control.h:286
void(* cancellable)(dt_lib_module_t *self, struct dt_lib_backgroundjob_element_t *instance, dt_progress_t *progress)
Definition control.h:288
GtkWidget * widget
Definition lib.h:84
@ DT_UI_CONTAINER_PANEL_LEFT_BOTTOM