Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
run.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2023-2026 Aurélien PIERRE.
4 Copyright (C) 2026 Guillaume Stutin.
5
6 Ansel is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Ansel is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "gui/actions/menu.h"
20#include "common/paths.h" // DT_PATH_MAX
21#include "control/control.h"
22#include "control/crawler.h"
23#include "database/database.h"
24#include "caches/mipmap_cache.h"
25#include "common/selection.h"
26#include "common/utility.h"
27#include "control/jobs.h"
29#include "develop/develop.h"
31#include "gui/application.h"
32#include "gui/dtgtk/thumbnail.h"
34
40
41static gboolean clear_caches_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
42{
43 dt_develop_t *const dev = dt_dev_get_global();
46 return TRUE;
47}
48
49static gboolean optimize_database_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
50{
52 return TRUE;
53}
54
55static gboolean backup_database_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
56{
58 return TRUE;
59}
60
61static gboolean crawl_xmp_changes(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
62{
63 GList *changed_xmp_files = dt_control_crawler_run();
64 dt_control_crawler_show_image_list(changed_xmp_files);
65 return TRUE;
66}
67
68// A quit cancels nothing (see doc/shutdown.md): without the second test, the closing window would
69// wait for the whole collection. Either way, the thumbnail being rendered is finished.
74
75static int32_t preload_image_cache(dt_job_t *job)
76{
77 // Retrieve the maximum mipmap size to generate from job parameters
79 const dt_mipmap_size_t max_mipmap_size = (params) ? params->max_mipmap_size : DT_MIPMAP_2;
80
81 // Load the mipmap cache sizes 0 to max_mipmap_size of the current selection
83 int i = 0;
84 float imgs = (float)dt_selection_get_length(dt_selection_get_global()) * (max_mipmap_size + 1);
85 GList *img = g_list_first(selection);
86
87 while(img && !_preload_should_stop(job))
88 {
89 const int32_t imgid = GPOINTER_TO_INT(img->data);
90
91 // Note : we generate from large scale to small,
92 // because the mipmap code has a mechanism that downscales
93 // higher resolution thumbnails if present, rather
94 // than recomputing a pipe from scratch.
95 for(int k = max_mipmap_size; k >= DT_MIPMAP_0 && !_preload_should_stop(job); k--)
96 {
97 char filename[DT_PATH_MAX] = { 0 };
98 dt_mipmap_get_cache_filename(filename, k, imgid);
99
100 // if a valid thumbnail file is already on disc - do nothing
101 if(dt_util_test_image_file(filename))
102 {
103 i++;
104 continue;
105 }
106
107 // else, generate thumbnail and store in mipmap cache.
109 dt_mipmap_cache_get(&buf, imgid, k, DT_MIPMAP_BLOCKING, 'r');
111
112 i++;
113 dt_control_job_set_progress(job, (float)i / imgs);
114 }
115
116 // and immediately write thumbs to disc and remove from mipmap cache.
118
119 img = g_list_next(img);
120 }
121
122 g_list_free(selection);
123 selection = NULL;
124 return 0;
125}
126
139
140// Callback functions for each mipmap size
141static gboolean preload_to_mipmap_0_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
142{
143 return _preload_image_cache_with_max_size(DT_MIPMAP_0, _("Preloading cache (up to 360x225 px) for current collection"));
144}
145
146static gboolean preload_to_mipmap_1_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
147{
148 return _preload_image_cache_with_max_size(DT_MIPMAP_1, _("Preloading cache (up to 720x450 px) for current collection"));
149}
150
151static gboolean preload_to_mipmap_2_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
152{
153 return _preload_image_cache_with_max_size(DT_MIPMAP_2, _("Preloading cache (up to 1440x900 px) for current collection"));
154}
155
156static gboolean preload_to_mipmap_3_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
157{
158 return _preload_image_cache_with_max_size(DT_MIPMAP_3, _("Preloading cache (up to Full HD 1080p) for current collection"));
159}
160
161static gboolean preload_to_mipmap_4_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
162{
163 return _preload_image_cache_with_max_size(DT_MIPMAP_4, _("Preloading cache (up to 2560x1440 px) for current collection"));
164}
165
166static gboolean preload_to_mipmap_5_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
167{
168 return _preload_image_cache_with_max_size(DT_MIPMAP_5, _("Preloading cache (up to 4K/UHD) for current collection"));
169}
170
171static gboolean preload_to_mipmap_6_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
172{
173 return _preload_image_cache_with_max_size(DT_MIPMAP_6, _("Preloading cache (up to 5K) for current collection"));
174}
175
176static gboolean preload_to_mipmap_7_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
177{
178 return _preload_image_cache_with_max_size(DT_MIPMAP_7, _("Preloading cache (up to 6K) for current collection"));
179}
180
181static gboolean preload_to_mipmap_8_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
182{
183 return _preload_image_cache_with_max_size(DT_MIPMAP_8, _("Preloading cache (up to 8K) for current collection"));
184}
185
186static gboolean preload_auto_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
187{
189 const int width = ceilf(table->thumb_width * dt_gui_get_global()->ppd);
190 const int height = ceilf(table->thumb_height * dt_gui_get_global()->ppd);
192 fprintf(stdout, "mipmap %i\n", mip);
193 return _preload_image_cache_with_max_size(mip, _("Preloading cache for current collection"));
194}
195
196static gboolean clear_image_cache(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
197{
199
200 for(GList *img = g_list_first(selection); img; img = g_list_next(img))
201 {
202 const int32_t imgid = GPOINTER_TO_INT(img->data);
204 }
205
206 g_list_free(selection);
207 selection = NULL;
208
209 // Redraw thumbnails
211 return TRUE;
212}
213
214static gboolean doc_screenshot_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
215{
217 return TRUE;
218}
219
222
223void append_run(GtkWidget **menus, GList **lists, const dt_menus_t index)
224{
225 add_sub_menu_entry(menus, lists, _("Clear darkroom pipeline caches"), index, NULL, clear_caches_callback, NULL, NULL, NULL, 0, 0);
226
227 // Create submenu for preloading selected thumbnails with different maximum mipmap sizes
228 add_top_submenu_entry(menus, lists, _("Preload selected thumbnails in cache"), index);
229 GtkWidget *parent = get_last_widget(lists);
230
231 // Add mipmap size options to the submenu
232 add_sub_sub_menu_entry(menus, parent, lists, _("up to 360x225 px"), index, NULL, preload_to_mipmap_0_callback, NULL, NULL, has_active_images, 0, 0);
233 add_sub_sub_menu_entry(menus, parent, lists, _("up to 720x450 px"), index, NULL, preload_to_mipmap_1_callback, NULL, NULL, has_active_images, 0, 0);
234 add_sub_sub_menu_entry(menus, parent, lists, _("up to 1440x900 px"), index, NULL, preload_to_mipmap_2_callback, NULL, NULL, has_active_images, 0, 0);
235 add_sub_sub_menu_entry(menus, parent, lists, _("up to Full HD 1080p"), index, NULL, preload_to_mipmap_3_callback, NULL, NULL, has_active_images, 0, 0);
236 add_sub_sub_menu_entry(menus, parent, lists, _("up to 2560x1440 px"), index, NULL, preload_to_mipmap_4_callback, NULL, NULL, has_active_images, 0, 0);
237 add_sub_sub_menu_entry(menus, parent, lists, _("up to 4K/UHD"), index, NULL, preload_to_mipmap_5_callback, NULL, NULL, has_active_images, 0, 0);
238 add_sub_sub_menu_entry(menus, parent, lists, _("up to 5K"), index, NULL, preload_to_mipmap_6_callback, NULL, NULL, has_active_images, 0, 0);
239 add_sub_sub_menu_entry(menus, parent, lists, _("up to 6K"), index, NULL, preload_to_mipmap_7_callback, NULL, NULL, has_active_images, 0, 0);
240 add_sub_sub_menu_entry(menus, parent, lists, _("up to 8K"), index, NULL, preload_to_mipmap_8_callback, NULL, NULL, has_active_images, 0, 0);
242 add_sub_sub_menu_entry(menus, parent, lists, _("for current grid size"), index, NULL, preload_auto_callback, NULL, NULL, has_active_images, 0, 0);
243
244 add_sub_menu_entry(menus, lists, _("Purge selected thumbnails from cache"), index, NULL, clear_image_cache, NULL, NULL, has_active_images, 0, 0);
245 add_menu_separator(menus[index]);
246 add_sub_menu_entry(menus, lists, _("Defragment the library"), index, NULL, optimize_database_callback, NULL, NULL, NULL, 0, 0);
247 add_sub_menu_entry(menus, lists, _("Backup the library"), index, NULL, backup_database_callback, NULL, NULL, NULL, 0, 0);
248 add_menu_separator(menus[index]);
249 add_sub_menu_entry(menus, lists, _("Synchronize developments from XMP to database"), index, NULL, crawl_xmp_changes, NULL, NULL, NULL, 0, 0);
250 add_sub_menu_entry(menus, lists, _("Synchronize developments from database to XMP"), index, NULL, GET_ACCEL_WRAPPER(dt_control_write_sidecar_files), NULL, NULL, has_active_images, 0, 0);
251 add_menu_separator(menus[index]);
252 add_sub_menu_entry(menus, lists, _("Resynchronize local copies with distant XMP"), index, NULL, GET_ACCEL_WRAPPER(dt_image_local_copy_synch), NULL, NULL, NULL, 0, 0);
253
254 // Documentation mode: the capture panel is only offered when the application was started
255 // with --doc, so a regular user never sees an entry that only serves the manual.
257 {
258 add_menu_separator(menus[index]);
259 add_sub_menu_entry(menus, lists, _("Capture widget screenshots..."), index, NULL, doc_screenshot_callback, NULL, NULL, NULL, 0, 0);
260 }
261}
struct dt_ui_t * dt_gui_get_ui(void)
const char ** description(struct dt_iop_module_t *self)
Definition ashift.c:168
#define TRUE
Definition ashift_lsd.c:162
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
void dt_image_local_copy_synch()
int dt_control_running()
Definition control.c:442
void dt_control_write_sidecar_files()
struct dt_control_t * dt_control_get_global(void)
Definition darktable.c:654
void dt_control_crawler_show_image_list(GList *images)
Definition crawler.c:989
GList * dt_control_crawler_run(void)
Definition crawler.c:533
struct dt_develop_t * dt_dev_get_global(void)
Definition darktable.c:531
struct dt_gui_gtk_t * dt_gui_get_global(void)
Definition darktable.c:526
gboolean dt_database_snapshot(void)
Definition database.c:4126
void dt_database_perform_maintenance(void)
Definition database.c:3891
void dt_dev_pixelpipe_reset_all(dt_develop_t *dev)
#define dt_dev_pixelpipe_resync_history_all(dev)
void dt_gui_doc_screenshot_window_show(void)
gboolean dt_gui_doc_screenshot_enabled(void)
#define UNKNOWN_IMAGE
Definition image.h:78
dt_job_state_t dt_control_job_get_state(_dt_job_t *job)
Definition jobs.c:106
dt_job_t * dt_control_job_create(dt_job_execute_callback execute, const char *msg,...)
Definition jobs.c:138
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
Definition jobs.c:419
void * dt_control_job_get_params(const _dt_job_t *job)
Definition jobs.c:132
void dt_control_job_set_progress(dt_job_t *job, double value)
Definition jobs.c:701
void dt_control_job_add_progress(dt_job_t *job, const char *message, gboolean cancellable)
Definition jobs.c:687
void dt_control_job_set_params(_dt_job_t *job, void *params, dt_job_destroy_callback callback)
Definition jobs.c:115
@ DT_JOB_QUEUE_USER_BG
Definition jobs.h:57
@ DT_JOB_STATE_CANCELLED
Definition jobs.h:48
static const dt_iop_drawlayer_params_t * params
Definition layers.h:80
float *const restrict const size_t k
static const int max_size
Definition map.c:132
void add_sub_sub_menu_entry(GtkWidget **menus, GtkWidget *parent, GList **lists, const gchar *label, const dt_menus_t index, void *data, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gboolean(*checked_callback)(GtkWidget *widget), gboolean(*active_callback)(GtkWidget *widget), gboolean(*sensitive_callback)(GtkWidget *widget), guint key_val, GdkModifierType mods)
Definition menu.c:597
GtkWidget * get_last_widget(GList **list)
Definition menu.c:631
void add_sub_menu_entry(GtkWidget **menus, GList **lists, const gchar *label, const dt_menus_t index, void *data, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gboolean(*checked_callback)(GtkWidget *widget), gboolean(*active_callback)(GtkWidget *widget), gboolean(*sensitive_callback)(GtkWidget *widget), guint key_val, GdkModifierType mods)
Definition menu.c:555
void add_sub_menu_separator(GtkWidget *parent)
Definition menu.c:618
void add_top_submenu_entry(GtkWidget **menus, GList **lists, const gchar *label, const dt_menus_t index)
Definition menu.c:528
void add_menu_separator(GtkWidget *menu)
Definition menu.c:611
gboolean has_active_images()
Definition menu.c:649
#define GET_ACCEL_WRAPPER(cb)
Definition menu.h:239
#define MAKE_ACCEL_WRAPPER(cb)
Definition menu.h:227
dt_menus_t
Definition menu.h:42
uint32_t width
Definition mipmap_cache.c:0
void dt_mipmap_cache_remove(const int32_t imgid, const gboolean flush_disk)
uint32_t height
Definition mipmap_cache.c:1
void dt_mimap_cache_evict(const int32_t imgid)
dt_mipmap_size_t dt_mipmap_cache_get_matching_size(const int32_t width, const int32_t height, const uint32_t imgid)
void dt_mipmap_get_cache_filename(char path[DT_PATH_MAX], dt_mipmap_size_t mip, const int32_t imgid)
@ DT_MIPMAP_BLOCKING
dt_mipmap_size_t
@ DT_MIPMAP_6
@ DT_MIPMAP_1
@ DT_MIPMAP_4
@ DT_MIPMAP_7
@ DT_MIPMAP_0
@ DT_MIPMAP_5
@ DT_MIPMAP_2
@ DT_MIPMAP_3
@ DT_MIPMAP_8
#define dt_mipmap_cache_get(B, C, D, E, F)
#define dt_mipmap_cache_release(B)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
static gboolean doc_screenshot_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:214
static gboolean preload_to_mipmap_8_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:181
static gboolean preload_to_mipmap_0_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:141
static gboolean preload_to_mipmap_7_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:176
static gboolean preload_to_mipmap_1_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:146
static gboolean preload_to_mipmap_6_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:171
void append_run(GtkWidget **menus, GList **lists, const dt_menus_t index)
Definition run.c:223
static int32_t preload_image_cache(dt_job_t *job)
Definition run.c:75
static gboolean preload_to_mipmap_3_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:156
static gboolean preload_to_mipmap_4_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:161
static gboolean _preload_image_cache_with_max_size(dt_mipmap_size_t max_size, const char *description)
Helper function to create a preload job with the specified maximum mipmap size.
Definition run.c:128
static gboolean clear_caches_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:41
static gboolean preload_auto_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:186
static gboolean preload_to_mipmap_5_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:166
static gboolean clear_image_cache(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:196
static gboolean backup_database_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:55
static gboolean optimize_database_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:49
static gboolean crawl_xmp_changes(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:61
struct _preload_cache_params_t preload_cache_params_t
Job parameters for preloading image cache with a maximum mipmap size.
static gboolean _preload_should_stop(dt_job_t *job)
Definition run.c:70
static gboolean preload_to_mipmap_2_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition run.c:151
struct dt_selection_t * dt_selection_get_global(void)
Definition selection.c:80
int dt_selection_get_length(struct dt_selection_t *selection)
Definition selection.c:193
GList * dt_selection_get_list(struct dt_selection_t *selection)
Definition selection.c:185
Job parameters for preloading image cache with a maximum mipmap size.
Definition run.c:37
dt_mipmap_size_t max_mipmap_size
Maximum mipmap size to generate.
Definition run.c:38
dt_thumbtable_t * thumbtable_lighttable
A widget to manage and display image thumbnails in Ansel's lighttable and filmstrip views.
#define dt_thumbtable_refresh_thumbnail(table, imgid, reinit)
Definition thumbtable.h:301
gboolean dt_util_test_image_file(const char *filename)
Definition utility.c:345