71 gchar *tag_list = NULL;
72 for(GList *b = before; b; b = g_list_next(b))
74 if(!g_list_find(a, b->data))
79 if(tag_list) tag_list[strlen(tag_list) - 1] =
'\0';
86 gchar *tag_list = NULL;
87 for(GList *a = after; a; a = g_list_next(a))
89 if(!g_list_find(b, a->data))
94 " (SELECT (IFNULL(MAX(position),0) & 0xFFFFFFFF00000000) + (1 << 32)"
95 " FROM main.tagged_images)"
98 GPOINTER_TO_INT(a->data));
102 if(tag_list) tag_list[strlen(tag_list) - 1] =
'\0';
108 if(img > 0 && tag_list)
111 gchar *query = g_strdup_printf(
"DELETE FROM main.tagged_images WHERE imgid = %d AND tagid IN (%s)", img, tag_list);
114 sqlite3_finalize(stmt);
124 gchar *query = g_strdup_printf(
"INSERT INTO main.tagged_images (imgid, tagid, position) VALUES %s", tag_list);
127 sqlite3_finalize(stmt);
148 for(GList *list = (GList *)data; list; list = g_list_next(list))
155 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undotags->
imgid));
165 g_list_free(undotags->
before);
167 g_list_free(undotags->
after);
168 undotags->
after = NULL;
174 GList *l = (GList *)data;
189 rt = sqlite3_step(stmt);
193 if(!
IS_NULL_PTR(tagid)) *tagid = sqlite3_column_int64(stmt, 0);
194 sqlite3_finalize(stmt);
197 sqlite3_finalize(stmt);
203 sqlite3_finalize(stmt);
209 if(sqlite3_step(stmt) == SQLITE_ROW)
id = sqlite3_column_int(stmt, 0);
210 sqlite3_finalize(stmt);
212 if(
id && g_strstr_len(
name, -1,
"darktable|") ==
name)
215 "INSERT INTO memory.darktable_tags (tagid) VALUES (?1)",
219 sqlite3_finalize(stmt);
242 "SELECT COUNT(*) FROM main.tagged_images WHERE tagid=?1", -1, &stmt, NULL);
244 rv = sqlite3_step(stmt);
245 if(rv == SQLITE_ROW) count = sqlite3_column_int(stmt, 0);
246 sqlite3_finalize(stmt);
255 sqlite3_finalize(stmt);
261 sqlite3_finalize(stmt);
268 sqlite3_finalize(stmt);
278 gchar *query = g_strdup_printf(
"DELETE FROM data.tags WHERE id IN (%s)", flatlist);
281 sqlite3_finalize(stmt);
284 query = g_strdup_printf(
"DELETE FROM main.tagged_images WHERE tagid IN (%s)", flatlist);
287 sqlite3_finalize(stmt);
296 if (!tag_list)
return 0;
298 char *flatlist = NULL;
301 for (GList *taglist = tag_list; taglist ; taglist = g_list_next(taglist))
303 const guint tagid = ((
dt_tag_t *)taglist->data)->id;
306 if(flatlist && count > 1000)
308 flatlist[strlen(flatlist)-1] =
'\0';
311 tcount = tcount + count;
317 flatlist[strlen(flatlist)-1] =
'\0';
320 tcount = tcount + count;
333 rt = sqlite3_step(stmt);
334 if(rt == SQLITE_ROW)
name = g_strdup((
const char *)sqlite3_column_text(stmt, 0));
335 sqlite3_finalize(stmt);
344 if(
IS_NULL_PTR(new_tagname) || !new_tagname[0])
return;
348 "UPDATE data.tags SET name = ?2 WHERE id = ?1", -1, &stmt, NULL);
352 sqlite3_finalize(stmt);
363 rt = sqlite3_step(stmt);
367 if(!
IS_NULL_PTR(tagid)) *tagid = sqlite3_column_int64(stmt, 0);
368 sqlite3_finalize(stmt);
373 sqlite3_finalize(stmt);
379 gboolean res =
FALSE;
380 for(
const GList *
t = tags;
t;
t = g_list_next(
t))
382 if(!g_list_find(*list,
t->data))
384 *list = g_list_prepend(*list,
t->data);
393 const int nb_ini = g_list_length(*list);
394 for(
const GList *
t = tags;
t;
t = g_list_next(
t))
396 *list = g_list_remove(*list,
t->data);
398 return (g_list_length(*list) != nb_ini);
418static gboolean
_tag_execute(
const GList *tags,
const GList *imgs, GList **undo,
const gboolean undo_on,
421 gboolean res =
FALSE;
422 for(
const GList *images = imgs; images; images = g_list_next(images))
424 const int32_t image_id = GPOINTER_TO_INT(images->data);
426 undotags->
imgid = image_id;
439 undotags->
after = g_list_copy((GList *)tags);
442 if(dttags) undotags->
after = g_list_concat(undotags->
after, dttags);
446 undotags->
after = g_list_copy((GList *)tags);
456 *undo = g_list_append(*undo, undotags);
469 tags = g_list_prepend(tags, GINT_TO_POINTER(tagid));
485gboolean
dt_tag_attach(
const guint tagid,
const int32_t imgid,
const gboolean undo_on,
const gboolean group_on)
487 gboolean res =
FALSE;
498 GList *imgs = g_list_append(NULL, GINT_TO_POINTER(imgid));
506gboolean
dt_tag_set_tags(
const GList *tags,
const GList *img,
const gboolean ignore_dt_tags,
507 const gboolean clear_on,
const gboolean undo_on)
514 const gboolean res =
_tag_execute(tags, img, &undo, undo_on,
530 gchar **tokens = g_strsplit(tags,
",", 0);
531 gboolean res =
FALSE;
536 gchar **entry = tokens;
539 char *e = g_strstrip(*entry);
544 tagl = g_list_prepend(tagl, GINT_TO_POINTER(tagid));
575 tags = g_list_prepend(tags, GINT_TO_POINTER(tagid));
593gboolean
dt_tag_detach(
const guint tagid,
const int32_t imgid,
const gboolean undo_on,
const gboolean group_on)
599 imgs = g_list_prepend(imgs, GINT_TO_POINTER(imgid));
609 const gboolean group_on)
625 "INSERT INTO memory.darktable_tags (tagid)"
626 " SELECT DISTINCT id"
628 " WHERE name LIKE 'darktable|%%'",
632 sqlite3_finalize(stmt);
638 uint32_t nb_selected = 0;
648 if(imgid > 0 || nb_selected > 0)
658 "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms,"
659 " COUNT(DISTINCT I.imgid) AS inb"
660 " FROM main.tagged_images AS I"
661 " JOIN data.tags AS T ON T.id = I.tagid"
662 " WHERE I.imgid = ?1 AND T.id NOT IN memory.darktable_tags"
676 "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms,"
677 " COUNT(DISTINCT I.imgid) AS inb"
678 " FROM main.tagged_images AS I"
679 " JOIN data.tags AS T ON T.id = I.tagid"
680 " WHERE I.imgid = ?1"
689 sqlite3_clear_bindings(stmt);
700 "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms,"
701 " COUNT(DISTINCT I.imgid) AS inb"
702 " FROM main.tagged_images AS I"
703 " JOIN data.tags AS T ON T.id = I.tagid"
704 " JOIN main.selected_images AS S ON S.imgid = I.imgid"
705 " WHERE T.id NOT IN memory.darktable_tags"
719 "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms,"
720 " COUNT(DISTINCT I.imgid) AS inb"
721 " FROM main.tagged_images AS I"
722 " JOIN data.tags AS T ON T.id = I.tagid"
723 " JOIN main.selected_images AS S ON S.imgid = I.imgid"
732 sqlite3_clear_bindings(stmt);
737 while(sqlite3_step(stmt) == SQLITE_ROW)
740 t->id = sqlite3_column_int(stmt, 0);
741 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 1));
742 t->leave = g_strrstr(
t->tag,
"|");
743 t->leave =
t->leave ?
t->leave + 1 :
t->tag;
744 t->flags = sqlite3_column_int(stmt, 2);
745 t->synonym = g_strdup((
char *)sqlite3_column_text(stmt, 3));
746 const uint32_t imgnb = sqlite3_column_int(stmt, 4);
751 *result = g_list_append(*result,
t);
760 if(!(imgid > 0))
return 0;
765 "SELECT DISTINCT T.id, T.name, T.flags, T.synonyms"
766 " FROM data.tags AS T"
768 " JOIN (SELECT DISTINCT I.tagid, T.name"
769 " FROM main.tagged_images AS I"
770 " JOIN data.tags AS T ON T.id = I.tagid"
771 " WHERE I.imgid = ?1 AND T.id NOT IN memory.darktable_tags"
772 " ORDER by T.name) AS T1"
774 " ON T.id = T1.tagid"
775 " OR (T.name = SUBSTR(T1.name, 1, LENGTH(T.name))"
776 " AND SUBSTR(T1.name, LENGTH(T.name) + 1, 1) = '|')",
782 while(sqlite3_step(stmt) == SQLITE_ROW)
785 t->id = sqlite3_column_int(stmt, 0);
786 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 1));
787 t->leave = g_strrstr(
t->tag,
"|");
788 t->leave =
t->leave ?
t->leave + 1 :
t->tag;
789 t->flags = sqlite3_column_int(stmt, 2);
790 t->synonym = g_strdup((
char *)sqlite3_column_text(stmt, 3));
791 *result = g_list_append(*result,
t);
794 sqlite3_finalize(stmt);
804 return g_strcmp0(tuple_a->
tag, tuple_b->
tag);
812 return g_strcmp0(tuple_a->
leave, tuple_b->
leave);
828 for(GList *taglist = tags; taglist; taglist = g_list_next(taglist))
831 gchar *tag = ((
dt_tag_t *)taglist->data)->tag;
832 for(
char *letter = tag; *letter; letter++)
833 if(*letter ==
'|') *letter =
'\1';
836 for(GList *taglist = sorted_tags; taglist; taglist = g_list_next(taglist))
838 gchar *tag = ((
dt_tag_t *)taglist->data)->tag;
839 for(
char *letter = tag; *letter; letter++)
840 if(*letter ==
'\1') *letter =
'|';
852 GList *taglist = NULL;
859 if(count < 1)
return NULL;
861 for(GList *tag_iter = taglist; tag_iter; tag_iter = g_list_next(tag_iter))
866 gchar **pch = g_strsplit(
value,
"|", -1);
870 if(omit_tag_hierarchy)
873 for(; *iter && *(iter + 1); iter++);
874 if(*iter) tags = g_list_prepend(tags, g_strdup(*iter));
881 tags = g_list_prepend(tags, g_strdup(pch[j]));
896 GList *taglist = NULL;
901 if(count < 1)
return NULL;
903 for(GList *tag_iter = taglist; tag_iter; tag_iter = g_list_next(tag_iter))
906 tags = g_list_prepend(tags, g_strdup(
t->tag));
911 tags = g_list_reverse(tags);
920 images = g_strdup_printf(
"%d", imgid);
928 char query[256] = { 0 };
930 snprintf(query,
sizeof(query),
"SELECT DISTINCT T.id"
931 " FROM main.tagged_images AS I"
932 " JOIN data.tags T on T.id = I.tagid"
933 " WHERE I.imgid IN (%s) %s",
936 "AND NOT T.id IN memory.darktable_tags");
940 while(sqlite3_step(stmt) == SQLITE_ROW)
942 tags = g_list_prepend(tags, GINT_TO_POINTER(sqlite3_column_int(stmt, 0)));
945 sqlite3_finalize(stmt);
959 return ((g_strcmp0(ta->
tag, tb->
tag) == 0) &&
965 GList *taglist = NULL;
974 if(count < 1)
return NULL;
976 sorted_tags = g_list_reverse(sorted_tags);
979 if(export_private_tags)
981 for(GList *tagt = sorted_tags; tagt; tagt = g_list_next(tagt))
984 t->flags &= ~DT_TF_PRIVATE;
987 for(GList *sorted_iter = sorted_tags; sorted_iter; sorted_iter = g_list_next(sorted_iter))
993 gchar *tagname =
t->leave;
994 tags = g_list_prepend(tags, g_strdup(tagname));
998 if(!omit_tag_hierarchy)
1000 GList *next = g_list_next(sorted_iter);
1001 gchar *end = g_strrstr(
t->tag,
"|");
1005 end = g_strrstr(
t->tag,
"|");
1009 const gchar *tag = end ? end + 1 :
t->tag;
1010 tags = g_list_prepend(tags, g_strdup(tag));
1016 if (export_tag_synonyms)
1018 gchar *synonyms =
t->synonym;
1019 if (synonyms && synonyms[0])
1021 gchar **tokens = g_strsplit(synonyms,
",", 0);
1024 gchar **entry = tokens;
1029 tags = g_list_append(tags, g_strdup(e));
1045 GList *taglist = NULL;
1050 if(count < 1)
return NULL;
1053 for(GList *tag_iter = taglist; tag_iter; tag_iter = g_list_next(tag_iter))
1058 tags = g_list_prepend(tags, g_strdup(
t->tag));
1064 return g_list_reverse(tags);
1073 " FROM main.tagged_images"
1074 " WHERE imgid = ?1 AND tagid = ?2", -1, &stmt, NULL);
1079 const gboolean ret = (sqlite3_step(stmt) == SQLITE_ROW);
1080 sqlite3_finalize(stmt);
1086 GList *result = NULL;
1091 "SELECT imgid FROM main.tagged_images"
1092 " WHERE tagid = ?1",
1097 while(sqlite3_step(stmt) == SQLITE_ROW)
1099 int id = sqlite3_column_int(stmt, 0);
1100 result = g_list_prepend(result, GINT_TO_POINTER(
id));
1102 sqlite3_finalize(stmt);
1104 return g_list_reverse(result);
1109 GList *result = NULL;
1110 char *images = NULL;
1111 for(GList *imgs = (GList *)img; imgs; imgs = g_list_next(imgs))
1117 images[strlen(images) - 1] =
'\0';
1121 gchar *query = g_strdup_printf(
1122 "SELECT imgid FROM main.tagged_images"
1123 " WHERE tagid = %d AND imgid IN (%s)",
1128 while(sqlite3_step(stmt) == SQLITE_ROW)
1130 int id = sqlite3_column_int(stmt, 0);
1131 result = g_list_prepend(result, GINT_TO_POINTER(
id));
1134 sqlite3_finalize(stmt);
1138 return g_list_reverse(result);
1146 const int nb_recent =
dt_conf_get_int(
"plugins/lighttable/tagging/nb_recent_tags");
1147 const uint32_t confidence =
dt_conf_get_int(
"plugins/lighttable/tagging/confidence");
1153 "INSERT INTO memory.taglist (id, count, count2)"
1154 " SELECT S.tagid, COUNT(imgid) AS count,"
1155 " CASE WHEN count2 IS NULL THEN 0 ELSE count2 END AS count2"
1156 " FROM main.tagged_images AS S"
1158 " SELECT tagid, COUNT(imgid) AS count2"
1159 " FROM main.tagged_images"
1160 " WHERE imgid IN main.selected_images"
1161 " GROUP BY tagid) AS at"
1162 " ON at.tagid = S.tagid"
1163 " WHERE S.tagid NOT IN memory.darktable_tags"
1164 " GROUP BY S.tagid",
1168 sqlite3_finalize(stmt);
1171 if(confidence != 100)
1173 query = g_strdup_printf(
"SELECT td.name, tagid2, t21.count, t21.count2,"
1174 " td.flags, td.synonyms FROM ("
1176 " SELECT DISTINCT tagid2 FROM ("
1177 " SELECT tagid2 FROM ("
1179 " SELECT tagid1, tagid2, count(*) AS c12"
1181 " SELECT DISTINCT tagid AS tagid1, imgid FROM main.tagged_images"
1182 " JOIN memory.taglist AS t00"
1183 " ON t00.id = tagid1 AND t00.count2 > 0) AS t1"
1185 " SELECT DISTINCT tagid AS tagid2, imgid FROM main.tagged_images"
1186 " WHERE tagid NOT IN memory.darktable_tags) AS t2"
1187 " ON t2.imgid = t1.imgid AND tagid1 != tagid2"
1188 " GROUP BY tagid1, tagid2)"
1189 " JOIN memory.taglist AS t01"
1190 " ON t01.id = tagid1"
1191 " JOIN memory.taglist AS t02"
1192 " ON t02.id = tagid2"
1194 " WHERE (t01.count-t01.count2) != 0"
1195 " AND (100 * c12 / (t01.count-t01.count2) >= %d)"
1196 " AND t02.count2 != %d) "
1200 " SELECT tn.id AS tagid2 FROM data.tags AS tn"
1201 " JOIN memory.taglist AS t02"
1202 " ON t02.id = tn.id"
1203 " WHERE tn.name IN (\'%s\')"
1205 " AND t02.count2 != %d LIMIT %d)) "
1206 "LEFT JOIN memory.taglist AS t21 "
1207 "ON t21.id = tagid2 "
1208 "LEFT JOIN data.tags as td ON td.id = tagid2 ",
1209 confidence, nb_selected, slist, nb_selected, nb_recent);
1213 query = g_strdup_printf(
"SELECT tn.name, tn.id, count, count2,"
1214 " tn.flags, tn.synonyms "
1216 "FROM data.tags AS tn "
1217 "JOIN memory.taglist AS t02 "
1218 "ON t02.id = tn.id "
1219 "WHERE tn.name IN (\'%s\')"
1221 " AND t02.count2 != %d LIMIT %d",
1222 slist, nb_selected, nb_recent);
1228 while(sqlite3_step(stmt) == SQLITE_ROW)
1231 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 0));
1232 t->leave = g_strrstr(
t->tag,
"|");
1233 t->leave =
t->leave ?
t->leave + 1 :
t->tag;
1234 t->id = sqlite3_column_int(stmt, 1);
1235 t->count = sqlite3_column_int(stmt, 2);
1236 const uint32_t imgnb = sqlite3_column_int(stmt, 3);
1240 t->flags = sqlite3_column_int(stmt, 4);
1241 t->synonym = g_strdup((
char *)sqlite3_column_text(stmt, 5));
1242 *result = g_list_append(*result,
t);
1246 sqlite3_finalize(stmt);
1261 gchar *keyword_expr = g_strdup_printf(
"%s|", keyword);
1266 "INSERT INTO memory.similar_tags (tagid)"
1269 " WHERE name = ?1 OR SUBSTR(name, 1, LENGTH(?2)) = ?2",
1275 sqlite3_finalize(stmt);
1280 "SELECT COUNT(DISTINCT tagid) FROM memory.similar_tags",
1283 *tag_count = sqlite3_column_int(stmt, 0);
1284 sqlite3_finalize(stmt);
1288 "SELECT COUNT(DISTINCT ti.imgid)"
1289 " FROM main.tagged_images AS ti "
1290 " JOIN memory.similar_tags AS st"
1291 " ON st.tagid = ti.tagid",
1296 *img_count = sqlite3_column_int(stmt, 0);
1297 sqlite3_finalize(stmt);
1307 gchar *keyword_expr = g_strdup_printf(
"%s|", keyword);
1312 "INSERT INTO memory.similar_tags (tagid)"
1315 " WHERE name = ?1 OR SUBSTR(name, 1, LENGTH(?2)) = ?2",
1321 sqlite3_finalize(stmt);
1327 "SELECT ST.tagid, T.name"
1328 " FROM memory.similar_tags ST"
1330 " ON T.id = ST.tagid ",
1334 while(sqlite3_step(stmt) == SQLITE_ROW)
1337 t->id = sqlite3_column_int(stmt, 0);
1338 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 1));
1339 *tag_list = g_list_append((*tag_list),
t);
1341 sqlite3_finalize(stmt);
1344 "SELECT DISTINCT ti.imgid"
1345 " FROM main.tagged_images AS ti"
1346 " JOIN memory.similar_tags AS st"
1347 " ON st.tagid = ti.tagid",
1350 while(sqlite3_step(stmt) == SQLITE_ROW)
1352 *img_list = g_list_append((*img_list), GINT_TO_POINTER(sqlite3_column_int(stmt, 0)));
1354 sqlite3_finalize(stmt);
1365 "SELECT COUNT(DISTINCT imgid) AS imgnb"
1366 " FROM main.tagged_images"
1367 " WHERE tagid = ?1",
1372 const uint32_t nb_images = sqlite3_column_int(stmt, 0);
1373 sqlite3_finalize(stmt);
1384 "INSERT INTO memory.taglist (id, count)"
1385 " SELECT tagid, COUNT(*)"
1386 " FROM main.tagged_images"
1391 sqlite3_finalize(stmt);
1398 "SELECT T.name, T.id, MT.count, CT.imgnb, T.flags, T.synonyms"
1399 " FROM data.tags T "
1400 " LEFT JOIN memory.taglist MT ON MT.id = T.id "
1401 " LEFT JOIN (SELECT tagid, COUNT(DISTINCT imgid) AS imgnb"
1402 " FROM main.tagged_images "
1403 " WHERE imgid IN (SELECT imgid FROM main.selected_images) GROUP BY tagid) AS CT "
1404 " ON CT.tagid = T.id"
1405 " WHERE T.id NOT IN memory.darktable_tags "
1406 " ORDER BY T.name ",
1412 while(sqlite3_step(stmt) == SQLITE_ROW)
1415 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 0));
1416 t->leave = g_strrstr(
t->tag,
"|");
1417 t->leave =
t->leave ?
t->leave + 1 :
t->tag;
1418 t->id = sqlite3_column_int(stmt, 1);
1419 t->count = sqlite3_column_int(stmt, 2);
1420 const uint32_t imgnb = sqlite3_column_int(stmt, 3);
1424 t->flags = sqlite3_column_int(stmt, 4);
1425 t->synonym = g_strdup((
char *)sqlite3_column_text(stmt, 5));
1426 *result = g_list_append(*result,
t);
1430 sqlite3_finalize(stmt);
1443 "SELECT DISTINCT T.name, T.id"
1445 " JOIN main.tagged_images TI ON TI.tagid = T.id"
1446 " WHERE TI.imgid IN (SELECT imgid FROM memory.collected_images)"
1447 " AND T.id NOT IN memory.darktable_tags"
1453 while(sqlite3_step(stmt) == SQLITE_ROW)
1456 t->tag = g_strdup((
char *)sqlite3_column_text(stmt, 0));
1457 t->leave = g_strrstr(
t->tag,
"|");
1458 t->leave =
t->leave ?
t->leave + 1 :
t->tag;
1459 t->id = sqlite3_column_int(stmt, 1);
1460 *result = g_list_append(*result,
t);
1464 sqlite3_finalize(stmt);
1471 gchar *synonyms = NULL;
1472 for(
char *letter = synonyms_entry; *letter; letter++)
1474 if(*letter ==
';' || *letter ==
'\n') *letter =
',';
1475 if(*letter ==
'\r') *letter =
' ';
1477 gchar **tokens = g_strsplit(synonyms_entry,
",", 0);
1480 gchar **entry = tokens;
1483 char *e = g_strstrip(*entry);
1491 synonyms[strlen(synonyms) - 2] =
'\0';
1500 gchar *synonyms = NULL;
1503 "SELECT synonyms FROM data.tags WHERE id = ?1 ",
1507 if (sqlite3_step(stmt) == SQLITE_ROW)
1509 synonyms = g_strdup((
char *)sqlite3_column_text(stmt, 0));
1511 sqlite3_finalize(stmt);
1517 if (!synonyms_entry)
return;
1522 "UPDATE data.tags SET synonyms = ?2 WHERE id = ?1 ",
1527 sqlite3_finalize(stmt);
1536 "SELECT flags FROM data.tags WHERE id = ?1 ",
1541 if (sqlite3_step(stmt) == SQLITE_ROW)
1543 flags = sqlite3_column_int(stmt, 0);
1545 sqlite3_finalize(stmt);
1554 "UPDATE data.tags SET flags = ?2 WHERE id = ?1 ",
1559 sqlite3_finalize(stmt);
1571 synonyms = g_strdup(synonym);
1575 "UPDATE data.tags SET synonyms = ?2 WHERE id = ?1 ",
1580 sqlite3_finalize(stmt);
1594 if(result && *result)
1616 FILE *fd = g_fopen(filename,
"r");
1619 GList * hierarchy = NULL;
1624 guint previous_category_depth = 0;
1625 gboolean previous_category =
FALSE;
1626 gboolean previous_synonym =
FALSE;
1628 while(
getline(&line, &len, fd) != -1)
1632 while(*start ==
'\t' || *start ==
' ' || *start ==
',' || *start ==
';') start++;
1633 const int depth = start - line;
1635 char *end = line + strlen(line) - 1;
1636 while((*end ==
'\n' || *end ==
'\r' || *end ==
',' || *end ==
';') && end >= start)
1644 gboolean skip =
FALSE;
1645 gboolean category =
FALSE;
1646 gboolean synonym =
FALSE;
1647 if (*start ==
'[' && *end ==
']')
1653 else if (*start ==
'{' && *end ==
'}')
1670 char *tagname = g_strdup(start);
1680 GList *iter = g_list_nth(hierarchy, depth);
1683 GList *current = iter;
1684 iter = g_list_next(iter);
1685 hierarchy = g_list_delete_link(hierarchy, current);
1689 hierarchy = g_list_append(hierarchy, g_strdup(start));
1695 if (previous_category && (depth > previous_category_depth + 1))
1714 previous_category_depth = category ? depth : 0;
1715 previous_category = category;
1716 previous_synonym = synonym;
1751 FILE *fd = g_fopen(filename,
"w");
1760 gchar **hierarchy = NULL;
1761 for(GList *tag_elt = sorted_tags; tag_elt; tag_elt = g_list_next(tag_elt))
1763 const gchar *tag = ((
dt_tag_t *)tag_elt->data)->tag;
1764 const char *synonyms = ((
dt_tag_t *)tag_elt->data)->synonym;
1766 gchar **tokens = g_strsplit(tag,
"|", -1);
1770 for(common_start = 0; hierarchy && hierarchy[common_start] && tokens && tokens[common_start]; common_start++)
1772 if(g_strcmp0(hierarchy[common_start], tokens[common_start]))
break;
1775 g_strfreev(hierarchy);
1778 int tabs = common_start;
1779 for(
size_t i = common_start; tokens && tokens[
i];
i++, tabs++)
1781 for(
int j = 0; j < tabs; j++) fputc(
'\t', fd);
1786 fprintf(fd,
"[%s]\n", tokens[
i]);
1788 fprintf(fd,
"%s\n", tokens[
i]);
1789 if (synonyms && synonyms[0])
1791 gchar **tokens2 = g_strsplit(synonyms,
",", 0);
1794 gchar **entry = tokens2;
1799 for(
int j = 0; j < tabs+1; j++) fputc(
'\t', fd);
1800 fprintf(fd,
"{%s}\n", e);
1804 g_strfreev(tokens2);
1808 fprintf(fd,
"%s\n", tokens[
i]);
1812 g_strfreev(hierarchy);
1829 "SELECT DISTINCT T.name FROM main.tagged_images AS I "
1830 "INNER JOIN data.tags AS T "
1831 "ON T.id = I.tagid AND SUBSTR(T.name, 1, LENGTH(?2)) = ?2 "
1832 "WHERE I.imgid = ?1",
1837 while(sqlite3_step(stmt) == SQLITE_ROW)
1839 char *tag = (
char *)sqlite3_column_text(stmt, 0);
1841 if (tagnb >= rootnb + level)
1843 gchar **pch = g_strsplit(tag,
"|", -1);
1844 char *subtag = pch[rootnb + level];
1845 gboolean valid =
TRUE;
1847 if(tags && strlen(tags) >= strlen(subtag) + 1)
1849 gchar *found = g_strstr_len(tags, strlen(tags), subtag);
1850 if(found && found[strlen(subtag)] ==
',')
1858 if(tags) tags[strlen(tags) - 1] =
'\0';
1859 sqlite3_finalize(stmt);
1864 gboolean *descending)
1866 gboolean res =
FALSE;
1871 "SELECT T.flags FROM data.tags AS T "
1876 if(sqlite3_step(stmt) == SQLITE_ROW)
1878 const uint32_t
flags = sqlite3_column_int(stmt, 0);
1882 *sort = (
flags & ~DT_TF_DESCENDING) >> 16;
1887 sqlite3_finalize(stmt);
1896 const char *query =
"SELECT T.id, T.flags FROM data.tags AS T "
1897 "WHERE LOWER(T.name) = LOWER(?1)";
1901 query, -1, &stmt, NULL);
1903 if(sqlite3_step(stmt) == SQLITE_ROW)
1905 tagid = sqlite3_column_int(stmt, 0);
1907 sqlite3_finalize(stmt);
1912 const gboolean descending)
1921 " SET flags = (IFNULL(flags, 0) & ?3) | ?2 "
1929 sqlite3_finalize(stmt);
GList * dt_act_on_get_images()
int dt_conf_get_bool(const char *name)
int dt_conf_get_int(const char *name)
const char * dt_conf_get_string_const(const char *name)
static void dt_free_gpointer(gpointer ptr)
static const dt_aligned_pixel_simd_t value
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
sqlite3 * dt_database_get(const dt_database_t *db)
#define DT_DEBUG_SQLITE3_EXEC(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
void dt_grouping_add_grouped_images(GList **images)
dt_mipmap_buffer_dsc_flags flags
gchar * dt_selection_ids_to_string(struct dt_selection_t *selection)
int dt_selection_get_length(struct dt_selection_t *selection)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_TAG_CHANGED
This signal is raised when a tag is added/deleted/changed
struct dt_selection_t * selection
const struct dt_database_t * db
struct dt_control_signal_t * signals
void dt_undo_end_group(dt_undo_t *self)
void dt_undo_start_group(dt_undo_t *self, dt_undo_type_t type)
void dt_undo_record(dt_undo_t *self, gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, void(*undo)(gpointer user_data, dt_undo_type_t type, dt_undo_data_t item, dt_undo_action_t action, GList **imgs), void(*free_data)(gpointer data))
guint dt_util_string_count_char(const char *text, const char needle)
gchar * dt_util_glist_to_str(const gchar *separator, GList *items)
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)
GList * dt_util_glist_uniq(GList *items)