103#define SELECT_QUERY "SELECT DISTINCT * FROM %s"
104#define LIMIT_QUERY "LIMIT ?1, ?2"
188 return &collection->
params;
307 params->filter_flags =
flags;
321 params->text_filter = text_filter;
334 params->query_flags =
flags;
343 for(
int i = 0;
i < c->n_rules;
i++)
345 gchar *
t = (gchar *)c->rules[
i].text;
351 c->n_rules = n_rules;
352 for(
int i = 0;
i < n_rules;
i++)
354 c->rules[
i] = rules[
i];
355 c->rules[
i].text = rules[
i].
text ? g_strdup(rules[
i].text) : NULL;
364 collection->
tagid = tagid;
375 if(reverse != -1) params->descending = reverse;
392 char *col_name = NULL;
431 char *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name);
434 if(!hidden) col_name = _(
name);
458 GMatchInfo *match_info;
460 *number1 = *number2 = *
operator= NULL;
463 regex = g_regex_new(
"^\\s*\\[\\s*([-+]?[0-9]+\\.?[0-9]*)\\s*;\\s*([-+]?[0-9]+\\.?[0-9]*)\\s*\\]\\s*$", 0, 0, NULL);
464 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
465 int match_count = g_match_info_get_match_count(match_info);
469 *number1 = g_match_info_fetch(match_info, 1);
470 *number2 = g_match_info_fetch(match_info, 2);
471 *
operator= g_strdup(
"[]");
472 g_match_info_free(match_info);
473 g_regex_unref(regex);
477 g_match_info_free(match_info);
478 g_regex_unref(regex);
481 regex = g_regex_new(
"^\\s*(=|<|>|<=|>=|<>)?\\s*([-+]?[0-9]+\\.?[0-9]*)\\s*$", 0, 0, NULL);
482 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
483 match_count = g_match_info_get_match_count(match_info);
487 *
operator= g_match_info_fetch(match_info, 1);
488 *number1 = g_match_info_fetch(match_info, 2);
490 if(*
operator && strcmp(*
operator,
"") == 0)
496 g_match_info_free(match_info);
497 g_regex_unref(regex);
502 if(strlen(input) < 4)
return NULL;
506 if(strcmp(
operator,
">") == 0 || strcmp(
operator,
"<=") == 0)
511 return g_strdup(bound);
526 GMatchInfo *match_info;
528 *number1 = *number2 = *
operator= NULL;
532 regex = g_regex_new(
"^\\s*\\[\\s*(\\d{4}[:.\\d\\s]*)\\s*;\\s*(\\d{4}[:.\\d\\s]*)\\s*\\]\\s*$", 0, 0, NULL);
533 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
534 int match_count = g_match_info_get_match_count(match_info);
538 gchar *txt = g_match_info_fetch(match_info, 1);
539 gchar *txt2 = g_match_info_fetch(match_info, 2);
543 *
operator= g_strdup(
"[]");
547 g_match_info_free(match_info);
548 g_regex_unref(regex);
552 g_match_info_free(match_info);
553 g_regex_unref(regex);
557 regex = g_regex_new(
"^\\s*(=|<|>|<=|>=|<>)?\\s*(\\d{4}[:.\\d\\s]*)?\\s*%?\\s*$", 0, 0, NULL);
558 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
559 match_count = g_match_info_get_match_count(match_info);
563 *
operator= g_match_info_fetch(match_info, 1);
564 gchar *txt = g_match_info_fetch(match_info, 2);
566 if(strcmp(*
operator,
"") == 0 || strcmp(*
operator,
"=") == 0 || strcmp(*
operator,
"<>") == 0)
578 if(
IS_NULL_PTR(*
operator)) *
operator= g_strdup(
"");
580 g_match_info_free(match_info);
581 g_regex_unref(regex);
587 GMatchInfo *match_info;
589 *number1 = *number2 = *
operator= NULL;
592 regex = g_regex_new(
"^\\s*\\[\\s*(1/)?([0-9]+\\.?[0-9]*)(\")?\\s*;\\s*(1/)?([0-9]+\\.?[0-9]*)(\")?\\s*\\]\\s*$", 0, 0, NULL);
593 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
594 int match_count = g_match_info_get_match_count(match_info);
596 if(match_count == 6 || match_count == 7)
598 gchar *n1 = g_match_info_fetch(match_info, 2);
600 if(strstr(g_match_info_fetch(match_info, 1),
"1/") != NULL)
601 *number1 = g_strdup_printf(
"1.0/%s", n1);
605 gchar *n2 = g_match_info_fetch(match_info, 5);
607 if(strstr(g_match_info_fetch(match_info, 4),
"1/") != NULL)
608 *number2 = g_strdup_printf(
"1.0/%s", n2);
612 *
operator= g_strdup(
"[]");
613 g_match_info_free(match_info);
614 g_regex_unref(regex);
618 g_match_info_free(match_info);
619 g_regex_unref(regex);
622 regex = g_regex_new(
"^\\s*(=|<|>|<=|>=|<>)?\\s*(1/)?([0-9]+\\.?[0-9]*)(\")?\\s*$", 0, 0, NULL);
623 g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);
624 match_count = g_match_info_get_match_count(match_info);
625 if(match_count == 4 || match_count == 5)
627 *
operator= g_match_info_fetch(match_info, 1);
629 gchar *n1 = g_match_info_fetch(match_info, 3);
631 if(strstr(g_match_info_fetch(match_info, 2),
"1/") != NULL)
632 *number1 = g_strdup_printf(
"1.0/%s", n1);
636 if(*
operator && strcmp(*
operator,
"") == 0)
642 g_match_info_free(match_info);
643 g_regex_unref(regex);
660 alias,
sizeof(alias));
663 gchar *makermodel = g_strdup_printf(
"%s %s",
maker,
model);
687 gboolean apply_exclude =
FALSE;
691 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/mode%1d", rule);
696 gboolean metadata_hidden =
FALSE;
701 char *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name);
707 const char *filmroll_order_by =
708 (strcmp(filmroll_sort,
"id") == 0)
709 ?
"film_rolls_id DESC"
710 : (
dt_conf_get_bool(
"plugins/collect/descending") ?
"folder DESC" :
"folder");
713 .exclude_rule = rule,
714 .apply_exclude = apply_exclude,
715 .metadata_hidden = metadata_hidden,
716 .filmroll_order_by = filmroll_order_by };
724 const int num_rules =
dt_conf_get_int(
"plugins/lighttable/collect/num_rules");
725 c = snprintf(buf, bufsize,
"%d:", num_rules);
728 for(
int k = 0;
k < num_rules;
k++)
730 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/mode%1d",
k);
732 c = snprintf(buf, bufsize,
"%d:", mode);
735 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/item%1d",
k);
737 c = snprintf(buf, bufsize,
"%d:", item);
740 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/string%1d",
k);
745 gchar *str_recursive = NULL;
748 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/recursive%1d",
k);
751 const char *emit = str_recursive ? str_recursive : str;
752 if(emit && (emit[0] !=
'\0'))
753 c = snprintf(buf, bufsize,
"%s$", emit);
755 c = snprintf(buf, bufsize,
"%%$");
756 g_free(str_recursive);
766 sscanf(buf,
"%d", &num_rules);
777 int mode = 0, item = 0;
779 while(buf[0] !=
'\0' && buf[0] !=
':') buf++;
780 if(buf[0] ==
':') buf++;
781 char str[400], confname[200];
782 for(
int k = 0;
k < num_rules;
k++)
784 const int n = sscanf(buf,
"%d:%d:%399[^$]", &mode, &item, str);
787 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/mode%1d",
k);
789 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/item%1d",
k);
796 const size_t len = strlen(str);
797 const gboolean recursive = len > 0 && str[len - 1] ==
'*';
798 if(recursive) str[len - 1] =
'\0';
799 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/recursive%1d",
k);
802 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/string%1d",
k);
805 else if(num_rules == 1)
807 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/mode%1d",
k);
809 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/item%1d",
k);
811 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/string%1d",
k);
813 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/recursive%1d",
k);
822 while(buf[0] !=
'$' && buf[0] !=
'\0') buf++;
823 if(buf[0] ==
'$') buf++;
856 const int _n_r =
dt_conf_get_int(
"plugins/lighttable/collect/num_rules");
857 const int num_rules = CLAMP(_n_r, 1, 10);
860 gchar **texts = g_malloc0_n(num_rules,
sizeof(gchar *));
862 for(
int i = 0;
i < num_rules;
i++)
864 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/item%1d",
i);
866 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/string%1d",
i);
869 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/mode%1d",
i);
871 snprintf(confname,
sizeof(confname),
"plugins/lighttable/collect/recursive%1d",
i);
877 for(
int i = 0;
i < num_rules;
i++)
dt_free(texts[
i]);
929 selected = GPOINTER_TO_INT(selected_imgids->data);
933 g_list_free(selected_imgids);
934 selected_imgids = NULL;
935 message = g_strdup_printf(_(
"%d image of %d (#%d) in current collection is selected"), cs, c,
selected);
939 message = g_strdup_printf(
941 "%d image of %d in current collection is selected",
942 "%d images of %d in current collection are selected",
965 if(!g_strcmp0(current_view->
module_name,
"studio_capture"))
return;
974 else if(g_strcmp0(current_view->
module_name,
"lighttable"))
989 gboolean result = current_atelier && g_strcmp0(current_atelier->
module_name,
"lighttable")
990 && g_strcmp0(current_atelier->
module_name,
"studio_capture");
995 const gboolean is_lighttable = current_atelier && !g_strcmp0(current_atelier->
module_name,
"lighttable");
1014 *recursive = is_folders &&
dt_conf_get_bool(
"plugins/lighttable/collect/recursive0");
1017 const gboolean has_value = string0 && string0[0];
1018 if(has_value) g_strlcpy(
folder, string0, len);
1029 const gint64 now = g_get_monotonic_time();
1030 if(now - *last_refresh_us <= 250000)
return;
1031 *last_refresh_us = now;
1038 gboolean browsed_folder_recursive =
FALSE;
1039 const gboolean has_browsed_folder
1044 gboolean image_in_browsed_folder =
TRUE;
1046 if(has_browsed_folder)
1048 const gchar *image_folder = known_image_folder;
1052 image_folder = image_folder_buf;
1054 const size_t browsed_len = strlen(browsed_folder);
1055 image_in_browsed_folder = !g_strcmp0(image_folder, browsed_folder)
1056 || (browsed_folder_recursive && g_str_has_prefix(image_folder, browsed_folder)
1057 && image_folder[browsed_len] == G_DIR_SEPARATOR);
1069 if(image_in_browsed_folder)
1117 const gboolean is_studio_capture = !
IS_NULL_PTR(current_atelier)
1118 && !g_strcmp0(current_atelier->
module_name,
"studio_capture");
1119 const gboolean follow_import_folder = is_studio_capture
1123 if(follow_import_folder)
const char * dt_collection_name(dt_collection_properties_t prop)
void dt_collection_update_query(const dt_collection_t *collection, dt_collection_change_t query_change, dt_collection_properties_t changed_property, GList *list)
void dt_culling_mode_to_selection()
void dt_collection_reset(const dt_collection_t *collection)
static dt_collection_recents_handler_t _recents_handler
void dt_collection_set_query_flags(const dt_collection_t *collection, dt_collection_query_flags_t flags)
void dt_collection_deserialize(const char *buf)
const dt_collection_params_t * dt_collection_params(const dt_collection_t *collection)
static char * _dt_collection_compute_datetime(const char *operator, const char *input)
void dt_collection_split_operator_exposure(const gchar *input, char **number1, char **number2, char **operator)
void dt_collection_set_text_filter(const dt_collection_t *collection, char *text_filter)
dt_collection_t * dt_collection_get_global(void)
static int dt_collection_image_offset_with_collection(const dt_collection_t *collection, int32_t imgid)
char * dt_collection_get_text_filter(const dt_collection_t *collection)
gboolean dt_collection_get_sort_descending(const dt_collection_t *collection)
void dt_selection_to_culling_mode()
void dt_collection_set_filter_flags(const dt_collection_t *collection, dt_collection_filter_flag_t flags)
static const char * _order_names[DT_IOP_ORDER_LAST]
void dt_collection_memory_update()
void dt_collection_split_operator_number(const gchar *input, char **number1, char **number2, char **operator)
void dt_collection_set_recents_handler(dt_collection_recents_handler_t handler)
dt_collection_filter_flag_t dt_collection_get_filter_flags(const dt_collection_t *collection)
void dt_collection_get_makermodels(const gchar *filter, GList **sanitized, GList **exif)
GList * dt_collection_get_images_for_rule(const dt_collection_properties_t property, const char *text, gboolean recursive)
void dt_collection_notify_imported(const int32_t imgid, const gchar *known_image_folder, gint64 *last_refresh_us)
int32_t dt_collection_get_nth(const dt_collection_t *collection, const int nth)
gboolean dt_collection_get_browsed_folder(gchar *folder, size_t len, gboolean *recursive)
dt_collection_query_flags_t dt_collection_get_query_flags(const dt_collection_t *collection)
void dt_collection_set_rules(const dt_collection_t *collection, const dt_collection_rule_t *rules, const int n_rules)
dt_collection_sort_t dt_collection_get_sort_field(const dt_collection_t *collection)
void dt_collection_set_tag_id(dt_collection_t *collection, const uint32_t tagid)
static dt_collection_t * _collection_global
void dt_collection_name_value_free(gpointer value)
gchar * dt_collection_get_makermodel(const char *exif_maker, const char *exif_model)
gboolean dt_collection_hint_message_internal(void *message)
void dt_push_collection()
void dt_collection_split_operator_datetime(const gchar *input, char **number1, char **number2, char **operator)
void dt_collection_hint_message(const dt_collection_t *collection)
void dt_collection_cleanup_global(void)
int dt_collection_serialize(char *buf, int bufsize)
static gboolean _collection_folder_ui_inactive(const dt_view_t *current_atelier)
static void _dt_collection_change_view_after_import(const dt_view_t *current_view, dt_collection_import_view_t view_policy, const int32_t imgid)
GList * dt_collection_get(const dt_collection_t *collection, const uint32_t limit)
void dt_collection_set_sort(const dt_collection_t *collection, dt_collection_sort_t sort, gboolean reverse)
static int _resolve_iop_order_name(const char *text)
uint32_t dt_collection_get_count(const dt_collection_t *collection)
void dt_collection_init_global(void)
int dt_collection_update(const dt_collection_t *collection)
dt_collection_t * dt_collection_new()
void dt_collection_load_filmroll(dt_collection_t *collection, const int32_t imgid, dt_collection_import_view_t view_policy, gboolean set_mouse_over)
GList * dt_collection_get_property_values(const dt_collection_properties_t property, const int rule)
GList * dt_collection_get_all(const dt_collection_t *collection, int limit)
void dt_collection_free(const dt_collection_t *collection)
dt_collection_properties_t
@ DT_COLLECTION_PROP_EXPOSURE
@ DT_COLLECTION_PROP_MODULE
@ DT_COLLECTION_PROP_RATING
@ DT_COLLECTION_PROP_QUERY
@ DT_COLLECTION_PROP_TIME
@ DT_COLLECTION_PROP_METADATA
@ DT_COLLECTION_PROP_GROUPING
@ DT_COLLECTION_PROP_FILMROLL
@ DT_COLLECTION_PROP_LENS
@ DT_COLLECTION_PROP_CAMERA
@ DT_COLLECTION_PROP_LAST
@ DT_COLLECTION_PROP_LOCAL_COPY
@ DT_COLLECTION_PROP_GEOTAGGING
@ DT_COLLECTION_PROP_FILENAME
@ DT_COLLECTION_PROP_COLORLABEL
@ DT_COLLECTION_PROP_UNDEF
@ DT_COLLECTION_PROP_ORDER
@ DT_COLLECTION_PROP_FOLDERS
@ DT_COLLECTION_PROP_APERTURE
@ DT_COLLECTION_PROP_IMPORT_TIMESTAMP
@ DT_COLLECTION_PROP_FOCAL_LENGTH
@ DT_COLLECTION_PROP_EXPORT_TIMESTAMP
@ DT_COLLECTION_PROP_CHANGE_TIMESTAMP
@ DT_COLLECTION_PROP_HISTORY
@ DT_COLLECTION_PROP_PRINT_TIMESTAMP
dt_collection_query_flags_t
@ COLLECTION_QUERY_USE_WHERE_EXT
#define COLLECTION_QUERY_FULL
dt_collection_filter_flag_t
void(* dt_collection_recents_handler_t)(void)
@ DT_COLLECTION_CHANGE_NEW_QUERY
@ DT_COLLECTION_CHANGE_BACKGROUND_SYNC
dt_collection_import_view_t
@ DT_COLLECTION_IMPORT_VIEW_KEEP
@ DT_COLLECTION_IMPORT_VIEW_IMAGE
@ DT_COLLECTION_SORT_NONE
void dt_collection_query_set_order_names(const char *const *names, const int count)
void dt_collection_query_pop(void)
int dt_collection_query_set_rules(const dt_collection_params_t *params, const dt_collection_rule_t *rules, const int n_rules, const uint32_t tagid)
void dt_collection_query_set_order_resolver(dt_collection_query_order_resolver_t fn)
GList * dt_collection_query_get_property_values(const dt_collection_values_request_t *req)
void dt_collection_query_cleanup(void)
void dt_collection_query_push(void)
void dt_collection_query_get_makermodels(const gchar *filter, GList **sanitized, GList **exif)
void dt_collection_query_refresh_memory_table(void)
GList * dt_collection_query_get_images_for_rule(const dt_collection_properties_t property, const char *text, gboolean recursive)
uint32_t dt_collection_query_count(void)
int32_t dt_collection_query_find_neighbour(GList *imgids)
int32_t dt_collection_query_get_nth(const int nth)
GList * dt_collection_query_get_images(const uint32_t limit)
int dt_collection_query_image_offset(const int32_t imgid)
void dt_collection_query_restrict_to_selection(void)
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
void dt_get_dirname_from_imgid(gchar *dir, const int32_t imgid)
void dt_ctl_switch_mode_to(const char *mode)
void dt_control_set_mouse_over_id(int32_t value)
void dt_ctl_open_image_in_darkroom(const int32_t imgid)
open one specific image in the darkroom, from any view and any thread.
void dt_control_hinter_message(const struct dt_control_t *s, const char *message)
struct dt_control_t * dt_control_get_global(void)
struct dt_view_manager_t * dt_view_manager_get_global(void)
struct dt_gui_gtk_t * dt_gui_get_global(void)
gboolean dt_datetime_entry_to_exif_upper_bound(char *exif, const size_t exif_size, const char *entry)
gboolean dt_datetime_entry_to_exif(char *exif, const size_t exif_size, const char *entry)
#define DT_DATETIME_LENGTH
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * folder
destination folder chooser
gboolean dt_imageio_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
const char * dt_iop_order_string(const dt_iop_order_t order)
Return the human-readable name for an IOP order enum value.
_lib_location_type_t type
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
dt_mipmap_buffer_dsc_flags flags
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
struct dt_selection_t * dt_selection_get_global(void)
void dt_selection_push(dt_selection_t *selection)
int dt_selection_get_length(struct dt_selection_t *selection)
GList * dt_selection_get_list(struct dt_selection_t *selection)
void dt_selection_clear(dt_selection_t *selection)
void dt_selection_select(dt_selection_t *selection, int32_t imgid)
void dt_selection_pop(dt_selection_t *selection)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_TAG_CHANGED
This signal is raised when a tag is added/deleted/changed
@ DT_SIGNAL_COLLECTION_CHANGED
This signal is raised when collection changed. To avoid leaking the list, dt_collection_t is connecte...
static const dt_aligned_pixel_simd_t value
dt_collection_query_flags_t query_flags
dt_collection_sort_t sort
dt_collection_filter_flag_t filter_flags
dt_collection_properties_t property
dt_collection_params_t params
dt_collection_rule_t * rules
dt_collection_properties_t property
gboolean dt_util_dir_exist(const char *dir)
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)