1 /*
2 This file is part of darktable,
3 Copyright (C) 2013-2021 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 #include "lua/tags.h"
19 #include "common/darktable.h"
20 #include "common/debug.h"
21 #include "common/image.h"
22 #include "common/tags.h"
23 #include "control/signal.h"
24 #include "lua/image.h"
25 #include "lua/types.h"
26
27
tag_name(lua_State * L)28 static int tag_name(lua_State *L)
29 {
30 dt_lua_tag_t tagid1;
31 luaA_to(L, dt_lua_tag_t, &tagid1, -2);
32 gchar *name = dt_tag_get_name(tagid1);
33 lua_pushstring(L, name);
34 free(name);
35 return 1;
36 }
37
tag_tostring(lua_State * L)38 static int tag_tostring(lua_State *L)
39 {
40 dt_lua_tag_t tagid1;
41 luaA_to(L, dt_lua_tag_t, &tagid1, -1);
42 gchar *name = dt_tag_get_name(tagid1);
43 lua_pushstring(L, name);
44 free(name);
45 return 1;
46 }
47
tag_length(lua_State * L)48 static int tag_length(lua_State *L)
49 {
50 dt_lua_tag_t tagid;
51 luaA_to(L, dt_lua_tag_t, &tagid, -1);
52 sqlite3_stmt *stmt;
53 int rv, count = -1;
54
55 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
56 "SELECT COUNT(*) FROM main.tagged_images WHERE tagid=?1", -1, &stmt, NULL);
57 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, tagid);
58 rv = sqlite3_step(stmt);
59 if(rv != SQLITE_ROW)
60 {
61 sqlite3_finalize(stmt);
62 return luaL_error(L, "unknown SQL error");
63 }
64 count = sqlite3_column_int(stmt, 0);
65 lua_pushinteger(L, count);
66 sqlite3_finalize(stmt);
67 return 1;
68 }
tag_index(lua_State * L)69 static int tag_index(lua_State *L)
70 {
71 dt_lua_tag_t tagid;
72 luaA_to(L, dt_lua_tag_t, &tagid, -2);
73 int index = luaL_checkinteger(L, -1);
74 if(index < 1)
75 {
76 return luaL_error(L, "incorrect index in database");
77 }
78 sqlite3_stmt *stmt = NULL;
79 char query[1024];
80 snprintf(query, sizeof(query),
81 "SELECT imgid FROM main.tagged_images WHERE tagid=?1 ORDER BY imgid LIMIT 1 OFFSET %d", index - 1);
82 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
83 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, tagid);
84 if(sqlite3_step(stmt) == SQLITE_ROW)
85 {
86 int imgid = sqlite3_column_int(stmt, 0);
87 luaA_push(L, dt_lua_image_t, &imgid);
88 }
89 else
90 {
91 sqlite3_finalize(stmt);
92 luaL_error(L, "incorrect index in database");
93 }
94 sqlite3_finalize(stmt);
95 return 1;
96 }
97
98
tag_lib_length(lua_State * L)99 static int tag_lib_length(lua_State *L)
100 {
101 sqlite3_stmt *stmt;
102 int rv, count = -1;
103
104 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT COUNT(*) FROM data.tags", -1, &stmt, NULL);
105 rv = sqlite3_step(stmt);
106 if(rv != SQLITE_ROW)
107 {
108 sqlite3_finalize(stmt);
109 return luaL_error(L, "unknown SQL error");
110 }
111 count = sqlite3_column_int(stmt, 0);
112 lua_pushinteger(L, count);
113 sqlite3_finalize(stmt);
114 return 1;
115 }
tag_lib_index(lua_State * L)116 static int tag_lib_index(lua_State *L)
117 {
118 int index = luaL_checkinteger(L, -1);
119 sqlite3_stmt *stmt = NULL;
120 char query[1024];
121 snprintf(query, sizeof(query), "SELECT id FROM data.tags ORDER BY id LIMIT 1 OFFSET %d", index - 1);
122 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
123 if(sqlite3_step(stmt) == SQLITE_ROW)
124 {
125 int tagid = sqlite3_column_int(stmt, 0);
126 luaA_push(L, dt_lua_tag_t, &tagid);
127 }
128 else
129 {
130 lua_pushnil(L);
131 }
132 sqlite3_finalize(stmt);
133 return 1;
134 }
135
tag_lib_create(lua_State * L)136 static int tag_lib_create(lua_State *L)
137 {
138 const char *name = luaL_checkstring(L, 1);
139 dt_lua_tag_t tagid;
140 if(!dt_tag_new_from_gui(name, &tagid))
141 {
142 return luaL_error(L, "error creating tag %s\n", name);
143 }
144 luaA_push(L, dt_lua_tag_t, &tagid);
145 return 1;
146 }
147
tag_delete(lua_State * L)148 static int tag_delete(lua_State *L)
149 {
150 dt_lua_tag_t tagid;
151 luaA_to(L, dt_lua_tag_t, &tagid, -1);
152
153 GList *tagged_images = NULL;
154 sqlite3_stmt *stmt;
155 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT imgid FROM main.tagged_images WHERE tagid=?1",
156 -1, &stmt, NULL);
157 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, tagid);
158 while(sqlite3_step(stmt) == SQLITE_ROW)
159 {
160 tagged_images = g_list_append(tagged_images, GINT_TO_POINTER(sqlite3_column_int(stmt, 0)));
161 }
162 sqlite3_finalize(stmt);
163
164 if(dt_tag_remove(tagid, TRUE))
165 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
166
167 for(const GList *list_iter = tagged_images; list_iter; list_iter = g_list_next(list_iter))
168 {
169 dt_image_synch_xmp(GPOINTER_TO_INT(list_iter->data));
170 }
171 g_list_free(tagged_images);
172
173 return 0;
174 }
175
176
dt_lua_tag_attach(lua_State * L)177 int dt_lua_tag_attach(lua_State *L)
178 {
179 dt_lua_image_t imgid = -1;
180 dt_lua_tag_t tagid = 0;
181 if(luaL_testudata(L, 1, "dt_lua_image_t"))
182 {
183 luaA_to(L, dt_lua_image_t, &imgid, 1);
184 luaA_to(L, dt_lua_tag_t, &tagid, 2);
185 }
186 else
187 {
188 luaA_to(L, dt_lua_tag_t, &tagid, 1);
189 luaA_to(L, dt_lua_image_t, &imgid, 2);
190 }
191 if(dt_tag_attach(tagid, imgid, TRUE, TRUE))
192 {
193 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
194 dt_image_synch_xmp(imgid);
195 }
196 return 0;
197 }
198
dt_lua_tag_detach(lua_State * L)199 int dt_lua_tag_detach(lua_State *L)
200 {
201 dt_lua_image_t imgid;
202 dt_lua_tag_t tagid;
203 if(luaL_testudata(L, 1, "dt_lua_image_t"))
204 {
205 luaA_to(L, dt_lua_image_t, &imgid, 1);
206 luaA_to(L, dt_lua_tag_t, &tagid, 2);
207 }
208 else
209 {
210 luaA_to(L, dt_lua_tag_t, &tagid, 1);
211 luaA_to(L, dt_lua_image_t, &imgid, 2);
212 }
213 if(dt_tag_detach(tagid, imgid, TRUE, TRUE))
214 {
215 dt_image_synch_xmp(imgid);
216 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
217 }
218 return 0;
219 }
220
tag_lib_find(lua_State * L)221 static int tag_lib_find(lua_State *L)
222 {
223 const char *name = luaL_checkstring(L, 1);
224 dt_lua_tag_t tagid;
225 if(!dt_tag_exists(name, &tagid))
226 {
227 lua_pushnil(L);
228 return 1;
229 }
230 luaA_push(L, dt_lua_tag_t, &tagid);
231 return 1;
232 }
233
dt_lua_tag_get_attached(lua_State * L)234 int dt_lua_tag_get_attached(lua_State *L)
235 {
236 dt_lua_image_t imgid;
237 int table_index = 1;
238 luaA_to(L, dt_lua_image_t, &imgid, 1);
239 sqlite3_stmt *stmt;
240
241 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT tagid FROM main.tagged_images WHERE imgid=?1",
242 -1, &stmt, NULL);
243 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
244 int rv = sqlite3_step(stmt);
245 lua_newtable(L);
246 while(rv == SQLITE_ROW)
247 {
248 int tagid = sqlite3_column_int(stmt, 0);
249 luaA_push(L, dt_lua_tag_t, &tagid);
250 lua_seti(L, -2, table_index);
251 table_index++;
252 rv = sqlite3_step(stmt);
253 }
254 sqlite3_finalize(stmt);
255 return 1;
256 }
257
258
dt_lua_tag_get_tagged_images(lua_State * L)259 int dt_lua_tag_get_tagged_images(lua_State *L)
260 {
261 dt_lua_tag_t tagid;
262 int table_index = 1;
263 luaA_to(L, dt_lua_tag_t, &tagid, 1);
264 sqlite3_stmt *stmt;
265
266 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT imgid FROM main.tagged_images WHERE tagid=?1",
267 -1, &stmt, NULL);
268 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, tagid);
269 int rv = sqlite3_step(stmt);
270 lua_newtable(L);
271 while(rv == SQLITE_ROW)
272 {
273 int imgid = sqlite3_column_int(stmt, 0);
274 luaA_push(L, dt_lua_image_t, &imgid);
275 lua_seti(L, -2, table_index);
276 table_index++;
277 rv = sqlite3_step(stmt);
278 }
279 sqlite3_finalize(stmt);
280 return 1;
281 }
282
283
dt_lua_init_tags(lua_State * L)284 int dt_lua_init_tags(lua_State *L)
285 {
286 dt_lua_init_int_type(L, dt_lua_tag_t);
287 lua_pushcfunction(L, tag_length);
288 lua_pushcfunction(L, tag_index);
289 dt_lua_type_register_number_const(L, dt_lua_tag_t);
290 lua_pushcfunction(L, tag_name);
291 dt_lua_type_register_const(L, dt_lua_tag_t, "name");
292 lua_pushcfunction(L, tag_delete);
293 lua_pushcclosure(L, dt_lua_type_member_common, 1);
294 dt_lua_type_register_const(L, dt_lua_tag_t, "delete");
295 lua_pushcfunction(L, dt_lua_tag_attach);
296 lua_pushcclosure(L, dt_lua_type_member_common, 1);
297 dt_lua_type_register_const(L, dt_lua_tag_t, "attach");
298 lua_pushcfunction(L, dt_lua_tag_detach);
299 lua_pushcclosure(L, dt_lua_type_member_common, 1);
300 dt_lua_type_register_const(L, dt_lua_tag_t, "detach");
301 lua_pushcfunction(L, tag_tostring);
302 dt_lua_type_setmetafield(L, dt_lua_tag_t, "__tostring");
303
304 /* tags */
305 dt_lua_push_darktable_lib(L);
306 luaA_Type type_id = dt_lua_init_singleton(L, "tag_table", NULL);
307 lua_setfield(L, -2, "tags");
308 lua_pop(L, 1);
309
310 lua_pushcfunction(L, tag_lib_length);
311 lua_pushcfunction(L, tag_lib_index);
312 dt_lua_type_register_number_const_type(L, type_id);
313 lua_pushcfunction(L, tag_lib_create);
314 lua_pushcclosure(L, dt_lua_type_member_common, 1);
315 dt_lua_type_register_const_type(L, type_id, "create");
316 lua_pushcfunction(L, tag_lib_find);
317 lua_pushcclosure(L, dt_lua_type_member_common, 1);
318 dt_lua_type_register_const_type(L, type_id, "find");
319 lua_pushcfunction(L, tag_delete);
320 lua_pushcclosure(L, dt_lua_type_member_common, 1);
321 dt_lua_type_register_const_type(L, type_id, "delete");
322 lua_pushcfunction(L, dt_lua_tag_attach);
323 lua_pushcclosure(L, dt_lua_type_member_common, 1);
324 dt_lua_type_register_const_type(L, type_id, "attach");
325 lua_pushcfunction(L, dt_lua_tag_detach);
326 lua_pushcclosure(L, dt_lua_type_member_common, 1);
327 dt_lua_type_register_const_type(L, type_id, "detach");
328 lua_pushcfunction(L, dt_lua_tag_get_attached);
329 lua_pushcclosure(L, dt_lua_type_member_common, 1);
330 dt_lua_type_register_const_type(L, type_id, "get_tags");
331 lua_pushcfunction(L, dt_lua_tag_get_tagged_images);
332 lua_pushcclosure(L, dt_lua_type_member_common, 1);
333 dt_lua_type_register_const_type(L, type_id, "get_tagged_images");
334
335
336 return 0;
337 }
338 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
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