80 return _(
"Auto style");
85 static const char *
v[] = {
"studio_capture", NULL };
101 for(GList *l =
d->pool; l; l = g_list_next(l))
102 if(!g_strcmp0((
const char *)l->data,
name))
return TRUE;
111 GString *conf = g_string_new(NULL);
112 for(GList *l =
d->pool; l; l = g_list_next(l))
115 g_string_append(conf, (
const char *)l->data);
119 g_string_free(conf,
TRUE);
129 for(GList *l =
d->pool; l; l = g_list_next(l))
131 gtk_list_store_append(
store, &iter);
134 gtk_tree_view_set_model(GTK_TREE_VIEW(
d->pool_treeview), GTK_TREE_MODEL(
store));
135 g_object_unref(
store);
146 GList *next = g_list_next(l);
147 gboolean found =
FALSE;
148 for(GList *s = all_styles; s && !found; s = g_list_next(s))
149 found = !g_strcmp0(((
dt_style_t *)s->data)->name, (
const char *)l->data);
153 d->pool = g_list_delete_link(
d->pool, l);
165 const gchar *segment_name)
167 GtkTreeIter parent = *iter;
171 if(!gtk_tree_model_get_iter_first(
model, iter))
173 gtk_tree_store_append(GTK_TREE_STORE(
model), iter, NULL);
179 if(!gtk_tree_model_iter_children(
model, iter, &parent))
181 gtk_tree_store_append(GTK_TREE_STORE(
model), iter, &parent);
188 gchar *node_name = NULL;
190 const gboolean match = !g_strcmp0(node_name, segment_name);
192 if(match)
return TRUE;
194 while(gtk_tree_model_iter_next(
model, iter));
196 gtk_tree_store_append(GTK_TREE_STORE(
model), iter, root ? NULL : &parent);
213 for(GList *s = all_styles; s; s = g_list_next(s))
216 gchar **segments = g_strsplit(style->
name,
"|", 0);
218 for(
int k = 0; segments[
k];
k++)
229 g_strfreev(segments);
232 gtk_tree_view_set_model(GTK_TREE_VIEW(
d->styles_treeview), GTK_TREE_MODEL(
store));
233 g_object_unref(
store);
245 GtkTreeModel *
model, GtkTreeIter *iter, gpointer user_data)
248 gchar *fullname = NULL;
252 g_object_set(renderer,
"foreground-set",
TRUE,
"foreground",
"#888", NULL);
254 g_object_set(renderer,
"foreground-set",
FALSE, NULL);
265 GtkTreeModel *
model, GtkTreeIter *iter, gpointer user_data)
268 gchar *fullname = NULL;
273 g_object_set(renderer,
"visible",
FALSE, NULL);
278 g_object_set(renderer,
"visible",
TRUE,
"pixbuf", in_pool ?
d->add_icon_disabled :
d->add_icon_enabled,
291 const int index = gtk_tree_path_get_indices(path)[0];
293 if(column ==
d->pool_up_col)
295 if(index <= 0)
return;
296 GList *previous = g_list_nth(
d->pool, index - 1);
297 GList *current = g_list_next(previous);
298 gpointer tmp = previous->data;
299 previous->data = current->data;
302 else if(column ==
d->pool_down_col)
304 GList *current = g_list_nth(
d->pool, index);
305 GList *next = current ? g_list_next(current) : NULL;
307 gpointer tmp = current->data;
308 current->data = next->data;
311 else if(column ==
d->pool_remove_col)
313 GList *link = g_list_nth(
d->pool, index);
315 char *removed_name = (
char *)link->data;
316 d->pool = g_list_delete_link(
d->pool, link);
317 gtk_widget_queue_draw(
d->styles_treeview);
336 if(
IS_NULL_PTR(event) ||
event->type != GDK_BUTTON_PRESS ||
event->button != GDK_BUTTON_PRIMARY)
return FALSE;
338 GtkTreePath *path = NULL;
339 GtkTreeViewColumn *column = NULL;
340 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, &column,
344 const gboolean consumed = column ==
d->pool_up_col || column ==
d->pool_down_col
345 || column ==
d->pool_remove_col;
347 gtk_tree_path_free(path);
352 GtkTooltip *
tooltip, gpointer user_data)
355 if(keyboard_tip)
return FALSE;
357 GtkTreePath *path = NULL;
358 GtkTreeViewColumn *column = NULL;
359 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview),
x, y, &path, &column, NULL, NULL))
return FALSE;
360 gtk_tree_path_free(path);
362 const char *text = NULL;
363 if(column ==
d->pool_up_col) text = _(
"Apply this style earlier");
364 else if(column ==
d->pool_down_col) text = _(
"Apply this style later");
365 else if(column ==
d->pool_remove_col) text = _(
"Remove this style from the pool");
368 gtk_tooltip_set_text(
tooltip, text);
377 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
379 if(!gtk_tree_model_get_iter(
model, &iter, path))
return FALSE;
381 gchar *fullname = NULL;
387 d->pool = g_list_append(
d->pool, g_strdup(fullname));
389 gtk_widget_queue_draw(
d->styles_treeview);
399 if(
IS_NULL_PTR(event) ||
event->type != GDK_BUTTON_PRESS ||
event->button != GDK_BUTTON_PRIMARY)
return FALSE;
401 GtkTreePath *path = NULL;
402 GtkTreeViewColumn *column = NULL;
403 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, &column,
407 gboolean consumed =
FALSE;
409 gtk_tree_path_free(path);
414 GtkTooltip *
tooltip, gpointer user_data)
417 if(keyboard_tip)
return FALSE;
419 GtkTreePath *path = NULL;
420 GtkTreeViewColumn *column = NULL;
421 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview),
x, y, &path, &column, NULL, NULL))
return FALSE;
422 gtk_tree_path_free(path);
424 if(column !=
d->styles_add_col)
return FALSE;
425 gtk_tooltip_set_text(
tooltip, _(
"Add this style to the pool"));
451 for(GList *l =
d->pool; l; l = g_list_next(l))
453 const char *pool_name = (
const char *)l->data;
473 dt_control_log(ngettext(
"Applied %d style.",
"Applied %d styles.", applied), applied);
493 for(gchar **pool_name =
names; *pool_name; pool_name++)
494 if((*pool_name)[0] !=
'\0')
d->pool = g_list_append(
d->pool, g_strdup(*pool_name));
504 GtkCellRenderer **out_renderer)
506 GtkTreeViewColumn *col = gtk_tree_view_column_new();
507 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
508 g_object_set(renderer,
"ellipsize", PANGO_ELLIPSIZE_END, (gchar *)0);
509 gtk_tree_view_column_pack_start(col, renderer,
TRUE);
510 gtk_tree_view_column_add_attribute(col, renderer,
"text", name_model_col);
511 gtk_tree_view_column_set_expand(col,
TRUE);
512 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
513 if(out_renderer) *out_renderer = renderer;
522 GtkCellRenderer **out_renderer)
524 GtkTreeViewColumn *col = gtk_tree_view_column_new();
525 GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
526 g_object_set(renderer,
"icon-name", icon_name,
"stock-size", GTK_ICON_SIZE_MENU, NULL);
527 gtk_tree_view_column_pack_start(col, renderer,
FALSE);
528 gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
530 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
531 if(out_renderer) *out_renderer = renderer;
545 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &
width, &
height);
547 GdkPixbuf *base = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), icon_name,
width,
548 GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
551 cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
width,
height);
552 cairo_t *cr = cairo_create(surface);
553 gdk_cairo_set_source_pixbuf(cr, base, 0, 0);
554 cairo_paint_with_alpha(cr, alpha);
557 GdkPixbuf *dimmed = gdk_pixbuf_get_from_surface(surface, 0, 0,
width,
height);
558 cairo_surface_destroy(surface);
559 g_object_unref(base);
566 self->
data = (
void *)
d;
571 GtkWidget *pool_label = gtk_label_new(_(
"Pool"));
572 gtk_widget_set_halign(pool_label, GTK_ALIGN_START);
575 d->pool_treeview = gtk_tree_view_new();
576 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(
d->pool_treeview),
FALSE);
582 gtk_widget_set_has_tooltip(
d->pool_treeview,
TRUE);
585 gtk_box_pack_start(GTK_BOX(self->
widget),
586 dt_ui_scroll_wrap(
d->pool_treeview, 100,
"plugins/darkroom/studio_style/poolwindowheight",
590 GtkWidget *apply = gtk_button_new_with_label(_(
"Apply to the displayed image"));
591 gtk_widget_set_tooltip_text(apply, _(
"Replace the history of the displayed image with the pool of styles"));
596 GtkWidget *styles_label = gtk_label_new(_(
"Styles"));
597 gtk_widget_set_halign(styles_label, GTK_ALIGN_START);
603 d->styles_treeview = gtk_tree_view_new();
604 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(
d->styles_treeview),
FALSE);
605 GtkCellRenderer *name_renderer = NULL;
606 GtkTreeViewColumn *name_col
610 GtkCellRenderer *add_renderer = NULL;
614 g_object_set(add_renderer,
"icon-name", NULL, NULL);
618 gtk_widget_set_has_tooltip(
d->styles_treeview,
TRUE);
621 gtk_box_pack_start(GTK_BOX(self->
widget),
641 if(!
IS_NULL_PTR(
d->add_icon_enabled)) g_object_unref(
d->add_icon_enabled);
642 if(!
IS_NULL_PTR(
d->add_icon_disabled)) g_object_unref(
d->add_icon_disabled);
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_conf_set_string(const char *name, const char *val)
void dt_image_history_changed(const int32_t imgid, const gboolean refresh_filmstrip)
void dt_control_log(const char *msg,...)
GHashTable * names
GtkWidget* -> the name the application knows it by.
GtkTreeStore * store
its model, owned by the view
#define DT_FOLDER_SURVEY_STYLES_SEPARATOR
#define DT_FOLDER_SURVEY_STYLES_CONF_KEY
void dt_hm_batch_state_cleanup(dt_hm_batch_state_t *batch)
Release resources held by a batch state (the cached order). Safe to call on a zeroed state.
@ DT_HISTORY_MERGE_APPEND
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...
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_DEVELOP_HISTORY_CHANGE
This signal is raised when develop history is changed no param, no returned value.
@ DT_SIGNAL_STYLE_CHANGED
This signal is raised when a style is added/deleted/changed
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
int dt_styles_apply_to_image_merge(const char *name, const int style_id, const int32_t newimgid, const dt_history_merge_strategy_t mode, dt_hm_batch_state_t *batch)
void dt_style_free(gpointer data)
int32_t dt_styles_get_id_by_name(const char *name)
GList * dt_styles_get_list(const char *filter)
GtkTreeViewColumn * pool_down_col
GtkWidget * pool_treeview
GtkWidget * styles_treeview
GdkPixbuf * add_icon_disabled
GtkTreeViewColumn * pool_up_col
GdkPixbuf * add_icon_enabled
GtkTreeViewColumn * styles_add_col
GtkTreeViewColumn * pool_remove_col
static gboolean _studio_style_styles_button_pressed(GtkWidget *treeview, GdkEventButton *event, gpointer user_data)
static GtkTreeViewColumn * _studio_style_add_name_column(GtkWidget *treeview, const int name_model_col, GtkCellRenderer **out_renderer)
Append the text column carrying the row's display name. Packed with expand=TRUE so any later-appended...
static gboolean _studio_style_pool_query_tooltip(GtkWidget *treeview, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer user_data)
static void _studio_style_populate_styles_tree(dt_lib_studio_style_t *d)
Rebuild the styles tree from every available style, grouping category segments split on "|" in the st...
static GtkTreeViewColumn * _studio_style_add_icon_column(GtkWidget *treeview, const char *icon_name, GtkCellRenderer **out_renderer)
Append one fixed-width icon column, for per-row action clicks handled by column identity (see the *_b...
static gboolean _studio_style_pool_contains(dt_lib_studio_style_t *d, const char *name)
static gboolean _studio_style_add_click(dt_lib_studio_style_t *d, GtkWidget *treeview, GtkTreePath *path)
Add the style leaf under a click to the end of the pool.
static gboolean _studio_style_get_node_for_name(GtkTreeModel *model, const gboolean root, GtkTreeIter *iter, const gchar *segment_name)
Find, or create as a child of the last found/created sibling, the tree node for one "|"-separated pat...
static void _studio_style_save(dt_lib_studio_style_t *d)
Persist the pool, in order, to conf.
void gui_cleanup(dt_lib_module_t *self)
static void _studio_style_changed_callback(gpointer instance, gpointer user_data)
static gboolean _studio_style_pool_button_pressed(GtkWidget *treeview, GdkEventButton *event, gpointer user_data)
Left click on a pool row's up/down/remove icon column.
static gboolean _studio_style_styles_query_tooltip(GtkWidget *treeview, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer user_data)
static void _studio_style_name_cell_data_func(GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
Gray a leaf's name when its style is already in the pool. Computed live at render time (not stored in...
uint32_t container(dt_lib_module_t *self)
static void _studio_style_pool_action_click(dt_lib_studio_style_t *d, GtkTreePath *path, GtkTreeViewColumn *column)
Apply the up/down/remove action for the pool row under a click, identified by which icon column was h...
static GdkPixbuf * _studio_style_load_icon(const char *icon_name, const double alpha)
Load a themed icon at the menu icon size, optionally pre-blended to a lower alpha....
static void _studio_style_apply_callback(GtkWidget *widget, gpointer user_data)
Re-apply the pool, in order, to the displayed image.
void gui_init(dt_lib_module_t *self)
const char ** views(dt_lib_module_t *self)
static void _studio_style_load_pool(dt_lib_studio_style_t *d)
Load the persisted, ordered pool from conf, once at startup.
static void _studio_style_rebuild_pool_ui(dt_lib_studio_style_t *d)
Rebuild the pool treeview, in order, from d->pool.
static void _studio_style_prune_pool(dt_lib_studio_style_t *d, GList *all_styles)
Drop pool entries whose style no longer exists.
static void _studio_style_add_cell_data_func(GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
Show the add icon only on leaves, swapping in a pre-dimmed pixbuf when the leaf's style is already in...
Telling the user something happened.
int32_t dt_view_active_images_get_first()
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER