63#ifdef GDK_WINDOWING_QUARTZ
66#include <gdk/gdkkeysyms.h>
95 static const char *
v[] = {
"lighttable",
"tethering", NULL};
108 return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(textview),
"tv_multiple"));
113 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
114 GtkTextIter start, end;
115 gtk_text_buffer_get_bounds(buffer, &start, &end);
116 return gtk_text_buffer_get_text(buffer, &start, &end,
TRUE);
121 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
122 GtkTextIter start, end;
123 gtk_text_buffer_get_bounds(buffer, &start, &end);
124 gtk_text_buffer_select_range(buffer, selected ? &start : &end, &end);
129 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
130 GtkTextIter start, end;
131 gtk_text_buffer_get_bounds(buffer, &start, &end);
133 gtk_text_buffer_apply_tag_by_name(buffer,
"italic", &start, &end);
135 gtk_text_buffer_remove_tag_by_name(buffer,
"italic", &start, &end);
140 g_signal_handlers_block_matched(buffer, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
_textbuffer_changed, NULL);
141 gtk_text_buffer_set_text(buffer, text, -1);
142 g_signal_handlers_unblock_matched(buffer, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
_textbuffer_changed, NULL);
148 gboolean multi =
FALSE;
150 GtkTextBuffer *buffer = gtk_text_view_get_buffer(
d->textview[
i]);
164 g_object_set_data(G_OBJECT(
d->textview[
i]),
"tv_multiple", GINT_TO_POINTER(multi));
178 if(imgs &&
d->last_act_on)
180 gboolean changed =
FALSE;
181 GList *l =
d->last_act_on;
182 GList *ll = (GList *)imgs;
185 if(GPOINTER_TO_INT(l->data) != GPOINTER_TO_INT(ll->data))
191 ll = g_list_next(ll);
200 g_list_free(
d->last_act_on);
201 d->last_act_on = NULL;
202 d->last_act_on = imgs;
210 metadata_count[
i] = 0;
215 const uint32_t imgs_count = g_list_length((GList *)imgs);
223 "SELECT m.key, m.value, COUNT(m.id) AS ct"
224 " FROM main.meta_data AS m"
225 " JOIN main.selected_images AS s ON s.imgid = m.id"
226 " GROUP BY m.key, m.value ORDER BY m.value",
232 sqlite3_clear_bindings(stmt);
234 while(sqlite3_step(stmt) == SQLITE_ROW)
236 if(sqlite3_column_bytes(stmt, 1))
238 const uint32_t
key = (uint32_t)sqlite3_column_int(stmt, 0);
241 char *
value = g_strdup((
char *)sqlite3_column_text(stmt, 1));
242 const uint32_t count = (uint32_t)sqlite3_column_int(stmt, 2);
243 metadata_count[
key] = (count == imgs_count) ? 2 : 1;
244 metadata[
key] = g_list_append(metadata[
key],
value);
255 d->metadata_list[
i] = metadata[keyid];
256 metadata[keyid] = NULL;
263 metadata[
key] = NULL;
266 gtk_widget_set_sensitive(GTK_WIDGET(
d->apply_button), imgs_count > 0);
276 *l = g_list_append(*l, (gchar *)
key);
277 *l = g_list_append(*l, (gchar *)
value);
294 GList *key_value = NULL;
297 const int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(textview),
"tv_index"));
310 for(GList *l = key_value; l; l = l->next)
315 g_list_free(key_value);
344 event->state &= ~GDK_CONTROL_MASK;
361 case GDK_KEY_ISO_Left_Tab:
380 return gtk_text_view_im_context_filter_keypress(GTK_TEXT_VIEW(textview), event);
387 GtkTextView *textview = GINT_TO_POINTER(g_object_get_data(G_OBJECT(textbuffer),
"buffer_tv"));
388 g_object_set_data(G_OBJECT(textview),
"tv_multiple", GINT_TO_POINTER(
FALSE));
393 GtkWidget *target = g_object_get_data(G_OBJECT(widget),
d == GTK_DIR_TAB_FORWARD ?
"meta_next" :
"meta_prev");
394 gtk_widget_grab_focus(target);
405 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
420 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
436 GtkWidget *first = NULL, *previous = NULL;
443 gchar *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name);
449 gtk_widget_set_visible(label, !hidden);
451 gtk_widget_set_visible(gtk_widget_get_parent(current), !hidden);
457 g_object_set_data(G_OBJECT(previous),
"meta_next", current);
458 g_object_set_data(G_OBJECT(current),
"meta_prev", previous);
460 g_object_set_data(G_OBJECT(current),
"meta_next", first);
461 g_object_set_data(G_OBJECT(first),
"meta_prev", current);
474 gchar *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name);
481 GtkTextBuffer *buffer = gtk_text_view_get_buffer(
d->textview[
i]);
491 GtkListStore *
store = (GtkListStore *)user_data;
493 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
496 gtk_tree_model_get_iter(GTK_TREE_MODEL(
store), &iter, path);
497 gtk_tree_model_get(GTK_TREE_MODEL(
store), &iter, column, &toggle, -1);
498 gtk_list_store_set(
store, &iter, column, !toggle, -1);
500 gtk_tree_path_free(path);
516 GtkWidget *dialog = gtk_dialog_new_with_buttons(_(
"metadata settings"), GTK_WINDOW(win),
517 GTK_DIALOG_DESTROY_WITH_PARENT, _(
"default"), GTK_RESPONSE_YES,
518 _(
"cancel"), GTK_RESPONSE_NONE, _(
"save"), GTK_RESPONSE_ACCEPT, NULL);
520 GtkWidget *area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
522 GtkWidget *w = gtk_scrolled_window_new(NULL, NULL);
524 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
526 gtk_box_pack_start(GTK_BOX(area), w,
TRUE,
TRUE, 0);
529 G_TYPE_INT, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
542 gchar *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name[
i]);
547 gtk_list_store_append(
store, &iter);
548 gtk_list_store_set(
store, &iter,
558 g_object_unref(
model);
559 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
560 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_(
"metadata"), renderer,
562 gtk_tree_view_column_set_expand(column,
TRUE);
563 gtk_tree_view_append_column(GTK_TREE_VIEW(
view), column);
564 renderer = gtk_cell_renderer_toggle_new();
566 column = gtk_tree_view_column_new_with_attributes(_(
"visible"), renderer,
568 gtk_tree_view_append_column(GTK_TREE_VIEW(
view), column);
569 GtkWidget *header = gtk_tree_view_column_get_button(column);
570 gtk_widget_set_tooltip_text(header,
571 _(
"tick if the corresponding metadata is of interest for you"
572 "\nit will be visible from metadata editor, collection and import module"
573 "\nit will be also exported"));
574 renderer = gtk_cell_renderer_toggle_new();
576 column = gtk_tree_view_column_new_with_attributes(_(
"private"), renderer,
578 gtk_tree_view_append_column(GTK_TREE_VIEW(
view), column);
579 header = gtk_tree_view_column_get_button(column);
580 gtk_widget_set_tooltip_text(header,
581 _(
"tick if you want to keep this information private (not exported with images)"));
583 gtk_container_add(GTK_CONTAINER(w),
view);
585#ifdef GDK_WINDOWING_QUARTZ
588 gtk_widget_show_all(dialog);
590 int res = gtk_dialog_run(GTK_DIALOG(dialog));
591 while(res == GTK_RESPONSE_YES)
593 gtk_tree_model_get_iter_first(
model, &iter);
600 gtk_list_store_set(
store, &iter,
604 gtk_tree_model_iter_next(
model, &iter);
607 res = gtk_dialog_run(GTK_DIALOG(dialog));
610 if(res == GTK_RESPONSE_ACCEPT)
612 gboolean meta_signal =
FALSE;
613 gboolean meta_remove =
FALSE;
614 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
617 gboolean new_visible;
618 gboolean new_private;
620 gtk_tree_model_get(
model, &iter,
627 gchar *setting = g_strdup_printf(
"plugins/lighttable/metadata/%s_flag",
name[
i]);
629 if(new_visible != visible[
i])
633 meta_remove = !new_visible ?
TRUE : meta_remove;
635 if(new_private !=
private[
i])
642 valid = gtk_tree_model_iter_next(
model, &iter);
649 gtk_widget_destroy(dialog);
654 GtkWidget *mi = gtk_menu_item_new_with_label(_(
"preferences..."));
656 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
661 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
662 gtk_text_buffer_set_text(buffer, gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem)))), -1);
670 const int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(textview),
"tv_index"));
674 gtk_menu_shell_append(GTK_MENU_SHELL(popup),gtk_separator_menu_item_new());
676 for(GList *item =
d->metadata_list[
i]; item; item = g_list_next(item))
678 GtkWidget *new_line = gtk_menu_item_new_with_label(item->data);
680 gtk_menu_shell_append(GTK_MENU_SHELL(popup), new_line);
682 gtk_widget_show_all(popup);
687 if(event->type == GDK_2BUTTON_PRESS)
689 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
693 e.type = GDK_KEY_PRESS;
694 e.keyval = GDK_KEY_Return;
696 e.window = gtk_text_view_get_window(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT);
698 g_signal_emit_by_name(G_OBJECT(widget),
"key-press-event", &e, &ret_val);
706 self->
data = (
void *)
d;
710 GtkGrid *grid = GTK_GRID(gtk_grid_new());
711 self->
widget = GTK_WIDGET(grid);
720 GtkWidget *labelev = gtk_event_box_new();
721 gtk_widget_add_events(labelev, GDK_BUTTON_PRESS_MASK);
722 gtk_container_add(GTK_CONTAINER(labelev), label);
723 gtk_grid_attach(grid, labelev, 0,
i, 1, 1);
724 gtk_widget_set_tooltip_text(GTK_WIDGET(label),
725 _(
"metadata text. ctrl-wheel scroll to resize the text box"
726 "\n ctrl-enter inserts a new line (caution, may not be compatible with standard metadata)."
727 "\nif <leave unchanged> selected images have different metadata."
728 "\nin that case, right-click gives the possibility to choose one of them."
729 "\npress escape to exit the popup window"));
731 GtkWidget *textview = gtk_text_view_new();
735 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
736 g_object_set_data(G_OBJECT(buffer),
"buffer_tv", GINT_TO_POINTER(textview));
737 g_object_set_data(G_OBJECT(textview),
"tv_index", GINT_TO_POINTER(
i));
738 g_object_set_data(G_OBJECT(textview),
"tv_multiple", GINT_TO_POINTER(
FALSE));
739 gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)),
740 "italic",
"style", PANGO_STYLE_ITALIC, NULL);
742 gtk_grid_attach(grid, textview, 1,
i, 1, 1);
743 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD_CHAR);
744 gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(textview),
FALSE);
745 gtk_widget_add_events(textview, GDK_FOCUS_CHANGE_MASK);
747 g_signal_connect(textview,
"key-press-event", G_CALLBACK(
_key_pressed), self);
748 g_signal_connect(textview,
"focus", G_CALLBACK(
_textview_focus), self);
750 g_signal_connect(textview,
"grab-focus", G_CALLBACK(
_got_focus), self);
751 g_signal_connect(textview,
"focus-out-event", G_CALLBACK(
_lost_focus), self);
752 g_signal_connect(labelev,
"button-press-event", G_CALLBACK(
_metadata_reset), textview);
755 d->textview[
i] = GTK_TEXT_VIEW(textview);
756 gtk_widget_set_hexpand(textview,
TRUE);
757 gtk_widget_set_vexpand(textview,
TRUE);
762 _(
"write metadata for selected images"), 0, 0);
770 gtk_widget_show_all(self->
widget);
771 gtk_widget_set_no_show_all(self->
widget,
TRUE);
788 g_signal_handlers_block_by_func(
d->textview[
i],
_lost_focus, self);
790 d->metadata_list[
i] = NULL;
798 g_list_free(
d->last_act_on);
799 d->last_act_on = NULL;
808 const unsigned int params_size = strlen(
string) + metadata_nb;
811 memcpy(params + 4,
string,
params_size - metadata_nb);
821 add_rights_preset(self, _(
"CC BY-SA"), _(
"Creative Commons Attribution-ShareAlike (CC BY-SA)"));
822 add_rights_preset(self, _(
"CC BY-ND"), _(
"Creative Commons Attribution-NoDerivs (CC BY-ND)"));
823 add_rights_preset(self, _(
"CC BY-NC"), _(
"Creative Commons Attribution-NonCommercial (CC BY-NC)"));
825 _(
"Creative Commons Attribution-NonCommercial-ShareAlike (CC BY-NC-SA)"));
827 _(
"Creative Commons Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)"));
832 const int old_version,
int *new_version,
size_t *new_size)
836 const size_t new_params_size = old_params_size + 1;
837 char *new_params = calloc(
sizeof(
char), new_params_size);
839 const char *buf = (
const char *)old_params;
852 metadata_len[
i] = strlen(metadata[
i]) + 1;
853 buf += metadata_len[
i];
858 memcpy(new_params + pos, metadata[3], metadata_len[3]);
859 pos += metadata_len[3];
860 memcpy(new_params + pos, metadata[4], metadata_len[4]);
861 pos += metadata_len[4];
862 memcpy(new_params + pos, metadata[0], metadata_len[0]);
863 pos += metadata_len[0];
864 memcpy(new_params + pos, metadata[1], metadata_len[1]);
865 pos += metadata_len[1];
866 memcpy(new_params + pos, metadata[2], metadata_len[2]);
868 *new_size = new_params_size;
872 else if(old_version == 2)
874 const size_t new_params_size = old_params_size + 1;
875 char *new_params = calloc(
sizeof(
char), new_params_size);
877 memcpy(new_params, old_params, old_params_size);
879 *new_size = new_params_size;
899 GtkTextBuffer *buffer = gtk_text_view_get_buffer((GtkTextView *)
d->textview[
i]);
900 GtkTextIter start, end;
901 gtk_text_buffer_get_bounds(buffer, &start, &end);
902 metadata[keyid] = gtk_text_buffer_get_text(buffer, &start, &end,
TRUE);
903 if(!metadata[keyid]) metadata[keyid] = g_strdup(
"");
904 metadata_len[keyid] = strlen(metadata[keyid]) + 1;
905 *
size = *
size + metadata_len[keyid];
908 char *params = (
char *)malloc(*
size);
916 memcpy(params + pos, metadata[
i], metadata_len[
i]);
917 pos += metadata_len[
i];
921 g_assert(pos == *
size);
932 char *buf = (
char *)params;
935 uint32_t total_len = 0;
942 metadata_len[
i] = strlen(metadata[
i]) + 1;
943 buf += metadata_len[
i];
944 total_len += metadata_len[
i];
947 if(
size != total_len)
950 GList *key_value = NULL;
962 g_list_free(key_value);
969 g_list_free(
d->last_act_on);
970 d->last_act_on = NULL;
GList * dt_act_on_get_images()
size_t params_size(dt_imageio_module_format_t *self)
void dt_image_synch_xmps(const GList *img)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
uint32_t view(const dt_view_t *self)
#define DT_MODULE(MODVER)
static void dt_free_gpointer(gpointer ptr)
static const dt_aligned_pixel_simd_t value
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#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_PREPARE_V2(a, b, c, d, e)
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int32_t imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_export_metadata_t *metadata)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
void dt_gui_textview_set_padding(GtkTextView *textview)
Apply the standard recessed-input text padding to a GtkTextView.
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnects accels when a text or search entry gets the focus, and reconnects them when it looses it....
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
static GtkWidget * dt_ui_label_new(const gchar *str)
gboolean dt_handle_dialog_enter(GtkWidget *widget, GdkEventKey *event, gpointer data)
void dt_lib_cancel_postponed_update(dt_lib_module_t *mod)
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
void dt_lib_presets_add(const char *name, const char *plugin_name, const int32_t version, const void *params, const int32_t params_size, gboolean readonly)
void dt_osx_disallow_fullscreen(GtkWidget *widget)
GList * dt_selection_get_list(struct dt_selection_t *selection)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_METADATA_CHANGED
This signal is raised when metadata status (shown/hidden) or value has changed.
@ DT_SIGNAL_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
struct dt_gui_gtk_t * gui
struct dt_selection_t * selection
const struct dt_database_t * db
struct dt_control_signal_t * signals
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER