Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
grouping.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011-2012, 2014, 2016 Tobias Ellinghaus.
4 Copyright (C) 2013 Simon Spannagel.
5 Copyright (C) 2014 johannes hanika.
6 Copyright (C) 2016 Roman Lebedev.
7 Copyright (C) 2019-2020 Philippe Weyland.
8 Copyright (C) 2020 Hanno Schwalm.
9 Copyright (C) 2020-2021 Hubert Kowalski.
10 Copyright (C) 2020-2021 Pascal Obry.
11 Copyright (C) 2021 Ralf Brown.
12 Copyright (C) 2022 Aldric Renaudin.
13 Copyright (C) 2022, 2025 Aurélien PIERRE.
14 Copyright (C) 2022 Martin Bařinka.
15 Copyright (C) 2026 Guillaume Stutin.
16
17 darktable is free software: you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation, either version 3 of the License, or
20 (at your option) any later version.
21
22 darktable is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with darktable. If not, see <http://www.gnu.org/licenses/>.
29*/
30
31#include "common/grouping.h"
32#include "common/collection.h"
33#include "system/macros.h"
34#include "system/mem_alloc.h"
37#include "caches/image_cache.h"
38
40void dt_grouping_add_to_group(const int32_t group_id, const int32_t image_id)
41{
42 // remove from old group
44
45 dt_image_t *img = dt_image_cache_get(image_id, 'w');
46 if(IS_NULL_PTR(img)) return;
47 img->group_id = group_id;
49}
50
52int dt_grouping_remove_from_group(const int32_t image_id)
53{
54 int new_group_id = -1;
55 GList *imgs = NULL;
56
57 const dt_image_t *img = dt_image_cache_get(image_id, 'r');
58 if(IS_NULL_PTR(img)) return -1;
59 const int img_group_id = img->group_id;
61 if(img_group_id == image_id)
62 {
63 // get a new group_id for all the others in the group. also write it to the dt_image_t struct.
64 GList *others = dt_image_repository_get_group_members(img_group_id, image_id);
65 for(GList *o = others; o; o = g_list_next(o))
66 {
67 const int other_id = GPOINTER_TO_INT(o->data);
68 // the group is not named after an image that cannot be read; the update below still moves its row
69 dt_image_t *other_img = dt_image_cache_get(other_id, 'w');
70 if(IS_NULL_PTR(other_img)) continue;
71 if(new_group_id == -1) new_group_id = other_id;
72 other_img->group_id = new_group_id;
74 imgs = g_list_prepend(imgs, GINT_TO_POINTER(other_id));
75 }
76 g_list_free(others);
77
78 if(new_group_id != -1)
79 {
80 dt_image_repository_reassign_group(img_group_id, new_group_id, image_id);
81 }
82 else
83 {
84 // no change was made, no point in raising signal, bailing early
85 return -1;
86 }
87 }
88 else
89 {
90 // change the group_id for this image.
91 dt_image_t *wimg = dt_image_cache_get(image_id, 'w');
92 if(IS_NULL_PTR(wimg)) return -1;
93 new_group_id = wimg->group_id;
94 wimg->group_id = image_id;
96 imgs = g_list_prepend(imgs, GINT_TO_POINTER(image_id));
97 // refresh also the group leader which may be alone now
98 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img_group_id));
99 }
100
101 return new_group_id;
102}
103
105int dt_grouping_change_representative(const int32_t image_id)
106{
107 dt_image_t *img = dt_image_cache_get(image_id, 'r');
108 if(IS_NULL_PTR(img)) return -1;
109 const int group_id = img->group_id;
111
112 GList *imgs = NULL;
113 GList *members = dt_image_repository_get_group_members(group_id, -1);
114 for(GList *m = members; m; m = g_list_next(m))
115 {
116 const int other_id = GPOINTER_TO_INT(m->data);
117 // a member that cannot be read is not written through the cache; the update below moves its row
118 dt_image_t *other_img = dt_image_cache_get(other_id, 'w');
119 if(IS_NULL_PTR(other_img)) continue;
120 other_img->group_id = image_id;
122 imgs = g_list_prepend(imgs, GINT_TO_POINTER(other_id));
123 }
124 g_list_free(members);
125 dt_image_repository_reassign_group(group_id, image_id, -1);
126
127 return image_id;
128}
129
131GList *dt_grouping_get_group_images(const int32_t imgid)
132{
133 GList *imgs = NULL;
134 const dt_image_t *image = dt_image_cache_get(imgid, 'r');
135 if(image)
136 {
137 const int img_group_id = image->group_id;
139
140 GList *members = dt_image_repository_get_group_members(img_group_id, -1);
141 for(GList *m = members; m; m = g_list_next(m))
142 imgs = g_list_prepend(imgs, m->data);
143 g_list_free(members);
144 }
145 return g_list_reverse(imgs);
146}
147
150{
151 if(IS_NULL_PTR(*images)) return;
152 GList *gimgs = NULL;
153 for(GList *imgs = *images; imgs; imgs = g_list_next(imgs))
154 {
155 const dt_image_t *image = dt_image_cache_get(GPOINTER_TO_INT(imgs->data), 'r');
156 if(image)
157 {
158 const int img_group_id = image->group_id;
161 {
162 GList *members = dt_collection_query_get_group_members(img_group_id,
163 GPOINTER_TO_INT(imgs->data));
164 for(GList *m = members; m; m = g_list_next(m))
165 gimgs = g_list_prepend(gimgs, m->data);
166 g_list_free(members);
167 }
168 }
169 }
170
171 if(gimgs)
172 *images = g_list_concat(*images, g_list_reverse(gimgs));
173}
174
175// clang-format off
176// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
177// vim: shiftwidth=2 expandtab tabstop=2 cindent
178// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
179// clang-format on
#define m
Definition basecurve.c:283
dt_collection_t * dt_collection_get_global(void)
Definition collection.c:138
GList * dt_collection_query_get_group_members(const int32_t group_id, const int32_t exclude_imgid)
int dt_grouping_change_representative(const int32_t image_id)
Definition grouping.c:105
int dt_grouping_remove_from_group(const int32_t image_id)
Definition grouping.c:52
void dt_grouping_add_grouped_images(GList **images)
Definition grouping.c:149
void dt_grouping_add_to_group(const int32_t group_id, const int32_t image_id)
Definition grouping.c:40
GList * dt_grouping_get_group_images(const int32_t imgid)
Definition grouping.c:131
void dt_image_cache_write_release(dt_image_t *img, dt_image_cache_write_mode_t mode)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
@ DT_IMAGE_CACHE_SAFE
Definition image_cache.h:48
void dt_image_repository_reassign_group(const int32_t from_group_id, const int32_t to_group_id, const int32_t exclude_imgid)
Move every member of from_group_id into to_group_id, except exclude_imgid.
GList * dt_image_repository_get_group_members(const int32_t group_id, const int32_t exclude_imgid)
Image ids in group group_id.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
#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 macros.h:96
#define o
int32_t group_id
Definition image.h:410