Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
film_repository.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2011 johannes hanika.
4 Copyright (C) 2010-2011 Henrik Andersson.
5 Copyright (C) 2011-2016 Tobias Ellinghaus.
6 Copyright (C) 2012, 2019-2022 Pascal Obry.
7 Copyright (C) 2025-2026 Aurélien PIERRE.
8
9 darktable is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 darktable is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with darktable. If not, see <http://www.gnu.org/licenses/>.
21*/
22
24#include "database/database.h"
25#include "database/sql_debug.h"
26#include "system/macros.h"
27#include "system/mem_alloc.h"
28
30{
31 if(IS_NULL_PTR(folder)) return -1;
32
33 int32_t filmroll_id = -1;
35 // Hoisted out of the macro call: a preprocessing directive inside the argument list of a
36 // function-like macro is undefined behaviour (C11 6.10.3p11). GCC and Clang accept it,
37 // which is exactly why it survives until a toolchain bump.
38#ifdef _WIN32
39 // Windows paths are matched case-insensitively, which LIKE gives us and = does not.
40 const char *query = "SELECT id FROM main.film_rolls WHERE folder LIKE ?1";
41#else
42 const char *query = "SELECT id FROM main.film_rolls WHERE folder = ?1";
43#endif
48 return filmroll_id;
49}
50
51char *dt_film_repository_get_folder(const int32_t id)
52{
53 char *folder = NULL;
55 // clang-format off
57 "SELECT id, folder"
58 " FROM main.film_rolls"
59 " WHERE id = ?1", -1, &stmt, NULL);
60 // clang-format on
63 folder = g_strdup((const char *)sqlite3_column_text(stmt, 1));
65 return folder;
66}
67
68gboolean dt_film_repository_insert(const char *folder)
69{
70 if(IS_NULL_PTR(folder)) return FALSE;
71
73 // clang-format off
75 "INSERT INTO main.film_rolls (id, access_timestamp, folder)"
76 " VALUES (NULL, strftime('%s', 'now'), ?1)",
77 -1, &stmt, NULL);
78 // clang-format on
80 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
82 return ok;
83}
84
85gboolean dt_film_repository_touch_access(const int32_t id)
86{
88 // clang-format off
90 "UPDATE main.film_rolls"
91 " SET access_timestamp = strftime('%s', 'now')"
92 " WHERE id = ?1", -1, &stmt,
93 NULL);
94 // clang-format on
96 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
98 return ok;
99}
100
101gboolean dt_film_repository_set_folder(const int32_t id, const char *folder)
102{
103 if(IS_NULL_PTR(folder)) return FALSE;
104
107 "UPDATE main.film_rolls SET folder=?1 WHERE id=?2", -1, &stmt, NULL);
110 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
112 return ok;
113}
114
115gboolean dt_film_repository_delete(const int32_t id)
116{
118 // due to foreign keys, all images with references to the film roll are deleted,
119 // and likewise all entries with references to those images
121 "DELETE FROM main.film_rolls WHERE id = ?1", -1,
122 &stmt, NULL);
124 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
126 return ok;
127}
128
129gboolean dt_film_repository_has_images(const int32_t id)
130{
131 gboolean has = FALSE;
134 "SELECT id FROM main.images WHERE film_id = ?1", -1,
135 &stmt, NULL);
139 return has;
140}
141
143{
144 GList *result = NULL;
147 "SELECT id FROM main.images WHERE film_id = ?1",
148 -1, &stmt, NULL);
150 while(sqlite3_step(stmt) == SQLITE_ROW)
151 {
152 const int id = sqlite3_column_int(stmt, 0);
153 result = g_list_prepend(result, GINT_TO_POINTER(id));
154 }
156 return g_list_reverse(result); // list was built in reverse order, so un-reverse it
157}
158
160{
161 if(IS_NULL_PTR(cb)) return;
162
165 "SELECT id, folder FROM main.film_rolls",
166 -1, &stmt, NULL);
167 while(sqlite3_step(stmt) == SQLITE_ROW)
168 cb(user_data, sqlite3_column_int(stmt, 0), (const char *)sqlite3_column_text(stmt, 1));
170}
171
173{
174 if(IS_NULL_PTR(cb)) return;
175
178 "SELECT id,folder"
179 " FROM main.film_rolls AS B"
180 " WHERE (SELECT COUNT(*)"
181 " FROM main.images AS A"
182 " WHERE A.film_id=B.id) = 0",
183 -1, &stmt, NULL);
184 while(sqlite3_step(stmt) == SQLITE_ROW)
185 cb(user_data, sqlite3_column_int(stmt, 0), (const char *)sqlite3_column_text(stmt, 1));
187}
188
190 void *user_data)
191{
192 if(IS_NULL_PTR(path) || IS_NULL_PTR(cb)) return;
193
195 gchar *like = g_strdup_printf("%s%%", path);
197 "SELECT id, folder FROM main.film_rolls WHERE folder LIKE ?1", -1, &stmt, NULL);
199 g_free(like);
200
201 while(sqlite3_step(stmt) == SQLITE_ROW)
202 cb(user_data, sqlite3_column_int(stmt, 0), (const char *)sqlite3_column_text(stmt, 1));
204}
205
207{
210 "DELETE FROM memory.film_folder",
211 -1, &stmt, NULL);
214}
215
216void dt_film_repository_folder_status_set(const int32_t id, const gboolean present)
217{
219 // clang-format off
221 "INSERT INTO memory.film_folder (id, status) "
222 "VALUES (?1, ?2)",
223 -1, &stmt, NULL);
224 // clang-format on
229}
230
231// clang-format off
232// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
233// vim: shiftwidth=2 expandtab tabstop=2 cindent
234// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
235// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
sqlite3 * dt_database_get_sqlite3_global(void)
Definition database.c:3790
GtkWidget * folder
destination folder chooser
char * dt_film_repository_get_folder(const int32_t id)
gboolean dt_film_repository_insert(const char *folder)
void dt_film_repository_foreach_empty(dt_film_repository_row_cb cb, void *user_data)
gboolean dt_film_repository_has_images(const int32_t id)
void dt_film_repository_foreach_under(const char *path, dt_film_repository_row_cb cb, void *user_data)
int32_t dt_film_repository_find_by_folder(const char *folder)
gboolean dt_film_repository_touch_access(const int32_t id)
void dt_film_repository_foreach(dt_film_repository_row_cb cb, void *user_data)
gboolean dt_film_repository_set_folder(const int32_t id, const char *folder)
gboolean dt_film_repository_delete(const int32_t id)
void dt_film_repository_folder_status_set(const int32_t id, const gboolean present)
GList * dt_film_repository_get_image_ids(const int32_t filmid)
void dt_film_repository_folder_status_clear(void)
void(* dt_film_repository_row_cb)(void *user_data, const int32_t id, const char *folder)
#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
Checked wrappers around the sqlite3_* calls: trace the statement, assert the return code,...
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition sql_debug.h:137
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e)
Definition sql_debug.h:148
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition sql_debug.h:145