Skip to content

Commit 546efdb

Browse files
authored
Merge pull request #18692 from dterrahe/preset_menus
Make preset shortcuts survive language change
2 parents 9bb5b2f + bfb73f2 commit 546efdb

23 files changed

+143
-127
lines changed

data/themes/darktable.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,7 @@ treeview#delete-dialog:selected
18061806
}
18071807

18081808
/* set active menu items: needed for some Pango issues not rendering synthetic bold for all OS */
1809+
.active_menu_item,
18091810
.active_menu_item label
18101811
{
18111812
font-weight: bold;

src/common/darktable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ static inline void dt_unreachable_codepath_with_caller(const char *description,
958958
* NQ_ should be used to strip any context from the string.
959959
*/
960960
#undef NC_
961-
#define NC_(Context, String) (Context "|" String)
961+
#define NC_(Context, String) Context "|" String
962962

963963
static inline const gchar *NQ_(const gchar *String)
964964
{

src/common/presets.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ const char *dt_presets_get_multi_name(const char *name, const char *multi_name)
443443
// in auto-update mode : use either the multi_name if defined otherwise the name
444444
// in non auto-update mode : use only the multi_name if defined
445445
if(auto_module)
446-
return strlen(multi_name) > 0 ? multi_name : name;
446+
return strlen(multi_name) > 0 ? multi_name : dt_util_localize_segmented_name(name, FALSE);
447447
else
448448
return strlen(multi_name) > 0 ? multi_name : "";
449449
}

src/common/utility.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const char *dt_util_localize_string(const char *s)
5959
static const int prefix_len = sizeof(prefix)-1;
6060

6161
if(s && strncmp(s, prefix, prefix_len) == 0)
62-
return _(s+prefix_len);
62+
return Q_(s+prefix_len);
6363
else
6464
return s;
6565
}
@@ -70,7 +70,9 @@ gchar *dt_util_localize_segmented_name(const char *s,
7070
const char *sep = with_space ? " | " : "|";
7171
const int sep_len = strlen(sep);
7272

73-
gchar **split = g_strsplit(s, "|", 0);
73+
const char *local_s = g_str_has_prefix(s, BUILTIN_PREFIX)
74+
? _(s+sizeof(BUILTIN_PREFIX)-1) : s;
75+
gchar **split = g_strsplit(local_s, "|", 0);
7476
gchar *localized = NULL;
7577
if(split && split[0])
7678
{
@@ -81,8 +83,11 @@ gchar *dt_util_localize_segmented_name(const char *s,
8183
gchar *end = g_stpcpy(localized, dt_util_localize_string(split[0]));
8284
for(int i = 1; split[i] != NULL; i++)
8385
{
86+
while(*end == ' ') end--;
8487
end = g_stpcpy(end, sep);
85-
end = g_stpcpy(end, dt_util_localize_string(split[i]));
88+
gchar *part = split[i];
89+
while(*part == ' ' ) part++;
90+
end = g_stpcpy(end, dt_util_localize_string(part));
8691
}
8792
}
8893
g_strfreev(split);

src/common/utility.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const char *dt_util_localize_string(const char *s);
3232
/** caller must g_free() return value */
3333
gchar *dt_util_localize_segmented_name(const char *s,
3434
const gboolean with_space);
35+
#define BUILTIN_PREFIX "_builtin_"
3536

3637
/** dynamically allocate and concatenate string */
3738
void dt_util_str_cat(gchar **str, const gchar *format, ...) __attribute__((format(printf, 2, 3)));

src/gui/accelerators.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3790,9 +3790,9 @@ static float _process_action(dt_action_t *action,
37903790
}
37913791
else if(owner->type == DT_ACTION_TYPE_IOP)
37923792
{
3793-
dt_action_widget_toast(action_target, NULL, "\napplying preset '%s'", action->label);
3793+
dt_action_widget_toast(action_target, NULL, _("\napplying preset '%s'"), action->label);
37943794

3795-
dt_gui_presets_apply_preset(action->label, action_target);
3795+
dt_gui_presets_apply_preset(action->id, action_target);
37963796
}
37973797
else
37983798
dt_print(DT_DEBUG_ALWAYS,
@@ -4740,7 +4740,7 @@ dt_action_t *dt_action_locate(dt_action_t *owner,
47404740
new_action->id = clean_path;
47414741
new_action->label = needs_translation
47424742
? g_strdup(Q_(*path))
4743-
: dt_util_localize_segmented_name(*path, FALSE);
4743+
: dt_util_localize_segmented_name(*path, TRUE);
47444744
new_action->type = DT_ACTION_TYPE_SECTION;
47454745

47464746
dt_action_insert_sorted(owner, new_action);
@@ -5000,7 +5000,7 @@ void dt_action_rename(dt_action_t *action,
50005000
if(new_name)
50015001
{
50025002
action->id = path_without_symbols(new_name);
5003-
action->label = g_strdup(_(new_name));
5003+
action->label = dt_util_localize_segmented_name(new_name, TRUE);
50045004

50055005
dt_action_insert_sorted(action->owner, action);
50065006
}

src/gui/preferences.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,12 +777,14 @@ static void _update_preset_line(GtkTreeStore *tree_store,
777777
focal_length = g_strdup_printf("%d – %d", focal_length_min, focal_length_max);
778778
}
779779

780+
gchar *local_name = dt_util_localize_segmented_name(name, TRUE);
781+
780782
gtk_tree_store_set(GTK_TREE_STORE(tree_store), iter,
781783
P_ROWID_COLUMN, rowid,
782784
P_OPERATION_COLUMN, operation,
783785
P_MODULE_COLUMN, "",
784786
P_EDITABLE_COLUMN, writeprotect ? lock_pixbuf : NULL,
785-
P_NAME_COLUMN, name,
787+
P_NAME_COLUMN, local_name,
786788
P_MODEL_COLUMN, smodel,
787789
P_MAKER_COLUMN, smaker,
788790
P_LENS_COLUMN, slens,
@@ -793,6 +795,7 @@ static void _update_preset_line(GtkTreeStore *tree_store,
793795
P_AUTOAPPLY_COLUMN, autoapply ? check_pixbuf : NULL,
794796
-1);
795797

798+
g_free(local_name);
796799
g_free(focal_length);
797800
g_free(aperture);
798801
g_free(exposure);

src/gui/presets.c

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void dt_gui_presets_init()
8888
NULL, NULL);
8989
}
9090

91-
void dt_gui_presets_add_generic(const char *name,
91+
void (dt_gui_presets_add_generic)(const char *name,
9292
const dt_dev_operation_t op,
9393
const int32_t version,
9494
const void *params,
@@ -98,9 +98,11 @@ void dt_gui_presets_add_generic(const char *name,
9898
{
9999
dt_develop_blend_params_t default_blendop_params;
100100
dt_develop_blend_init_blend_parameters(&default_blendop_params, blend_cst);
101+
gchar *prefixed_name = g_strdup_printf(BUILTIN_PREFIX "%s", name);
101102
dt_gui_presets_add_with_blendop(
102-
name, op, version, params, params_size,
103+
prefixed_name, op, version, params, params_size,
103104
&default_blendop_params, enabled);
105+
g_free(prefixed_name);
104106
}
105107

106108
void dt_gui_presets_add_with_blendop(const char *name,
@@ -1588,11 +1590,13 @@ void dt_gui_favorite_presets_menu_show(GtkWidget *w)
15881590
gchar *txt = g_strdup_printf("ꬹ%s|%sꬹ", iop->so->op, name);
15891591
if(config && strstr(config, txt))
15901592
{
1591-
GtkWidget *mi = gtk_menu_item_new_with_label(name);
1593+
GtkWidget *mi = gtk_menu_item_new_with_label("");
1594+
gchar *local_name = dt_util_localize_segmented_name(name, TRUE);
15921595
gchar *tt = g_markup_printf_escaped("<b>%s %s</b> %s",
1593-
iop->name(), iop->multi_name, name);
1596+
iop->name(), iop->multi_name, local_name);
15941597
gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), tt);
15951598
g_free(tt);
1599+
g_free(local_name);
15961600
_menuitem_connect_preset(mi, name, iop);
15971601
gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(mi));
15981602
}
@@ -1616,6 +1620,27 @@ void dt_gui_favorite_presets_menu_show(GtkWidget *w)
16161620
dt_gui_menu_popup(menu, w, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST);
16171621
}
16181622

1623+
// Comparator function to sort menu items alphabetically by their labels in reverse order
1624+
static gint _compare_menu_items(GtkMenuItem *a, GtkMenuItem *b)
1625+
{
1626+
return - g_utf8_collate(gtk_menu_item_get_label(a), gtk_menu_item_get_label(b));
1627+
}
1628+
1629+
// Function to sort GtkMenuShell items
1630+
static void _sort_menu_shell(GtkWidget *menu_shell)
1631+
{
1632+
if(!GTK_IS_MENU_SHELL(menu_shell)) return;
1633+
GList *items = gtk_container_get_children(GTK_CONTAINER(menu_shell));
1634+
items = g_list_sort(items, (GCompareFunc)_compare_menu_items);
1635+
for(GList *iter = items; iter; iter = g_list_delete_link(iter, iter))
1636+
{
1637+
g_object_ref(iter->data);
1638+
gtk_container_remove(GTK_CONTAINER(menu_shell), GTK_WIDGET(iter->data));
1639+
_sort_menu_shell(gtk_menu_item_get_submenu(GTK_MENU_ITEM(iter->data)));
1640+
gtk_menu_shell_prepend(GTK_MENU_SHELL(menu_shell), GTK_WIDGET(iter->data));
1641+
g_object_unref(iter->data);
1642+
}
1643+
}
16191644

16201645
GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
16211646
{
@@ -1707,7 +1732,7 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
17071732
int last_wp = -1;
17081733
gchar **prev_split = NULL;
17091734
GtkWidget *submenu = GTK_WIDGET(menu);
1710-
GSList *menu_stack = NULL; // stack of submenus
1735+
GtkWidget *mainmenu = submenu;
17111736
GSList *menu_path = NULL; // stack of menuitems which are the parents of submenus on menu_stack
17121737
while(sqlite3_step(stmt) == SQLITE_ROW)
17131738
{
@@ -1740,23 +1765,19 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
17401765
if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0)
17411766
found = TRUE;
17421767

1743-
gchar **split = g_strsplit(name, "|", -1), **s = split, **p = prev_split;
1768+
gchar *local_name = dt_util_localize_segmented_name(name, FALSE);
1769+
gchar **split = g_strsplit(local_name, "|", -1), **s = split, **p = prev_split;
1770+
g_free(local_name);
17441771
for(; p && *(p+1) && *(s+1) && !g_strcmp0(*s, *p); p++, s++)
17451772
;
17461773
for(; p && *(p+1); p++)
17471774
{
1748-
submenu = menu_stack->data;
1749-
menu_stack = g_slist_delete_link(menu_stack, menu_stack); // pop
17501775
menu_path = g_slist_delete_link(menu_path, menu_path); // pop
1776+
submenu = menu_path ? gtk_menu_item_get_submenu(menu_path->data) : mainmenu;
17511777
}
17521778
for(; *(s+1); s++)
17531779
{
1754-
GtkWidget *sm = gtk_menu_item_new_with_label("");
1755-
GtkWidget *mi_label = gtk_bin_get_child(GTK_BIN(sm));
1756-
gchar *el = g_markup_escape_text(*s, -1);
1757-
gtk_label_set_markup(GTK_LABEL(mi_label), el);
1758-
g_free(el);
1759-
menu_stack = g_slist_prepend(menu_stack, submenu); // push
1780+
GtkWidget *sm = gtk_menu_item_new_with_label(*s);
17601781
menu_path = g_slist_prepend(menu_path, sm); // push
17611782

17621783
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), sm);
@@ -1779,13 +1800,9 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
17791800
label = g_strdup_printf("%s %s", *s, _("(default)"));
17801801
else
17811802
label = g_strdup(*s);
1782-
mi = gtk_check_menu_item_new_with_label("");
1783-
GtkWidget *mi_label = gtk_bin_get_child(GTK_BIN(mi));
1784-
gchar *el = g_markup_escape_text(label, -1);
1785-
gtk_label_set_markup(GTK_LABEL(mi_label), el);
1803+
mi = gtk_check_menu_item_new_with_label(label);
17861804
dt_gui_add_class(mi, "dt_transparent_background");
17871805
g_free(label);
1788-
g_free(el);
17891806

17901807
if(module
17911808
&& ((op_params_size == 0
@@ -1805,16 +1822,7 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
18051822
g_set_weak_pointer(&_active_menu_item, mi);
18061823
// walk back up the menu hierarchy and highlight the entire path down to the current leaf
18071824
for(const GSList *mp = menu_path; mp; mp = g_slist_next(mp))
1808-
{
1809-
const char *curr_label = gtk_menu_item_get_label(GTK_MENU_ITEM(mp->data));
1810-
if(curr_label)
1811-
{
1812-
gchar *boldface = g_strdup_printf("<b>%s</b>",curr_label);
1813-
GtkWidget *child = gtk_bin_get_child(GTK_BIN(mp->data));
1814-
gtk_label_set_markup(GTK_LABEL(child), boldface);
1815-
g_free(boldface);
1816-
}
1817-
}
1825+
dt_gui_add_class(gtk_bin_get_child(GTK_BIN(mp->data)), "active_menu_item");
18181826
}
18191827

18201828
if(isdisabled)
@@ -1831,9 +1839,11 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
18311839
cnt++;
18321840
}
18331841
sqlite3_finalize(stmt);
1834-
g_slist_free(menu_stack);
1842+
g_slist_free(menu_path);
18351843
g_strfreev(prev_split);
18361844

1845+
_sort_menu_shell(mainmenu);
1846+
18371847
if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
18381848

18391849
if(module)
@@ -1859,7 +1869,7 @@ GtkMenu *dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
18591869

18601870
if(darktable.gui->last_preset && found)
18611871
{
1862-
char *markup = g_markup_printf_escaped("%s <span weight='bold'>%s</span>",
1872+
char *markup = g_markup_printf_escaped("%s <b>%s</b>",
18631873
_("update preset"),
18641874
darktable.gui->last_preset);
18651875
mi = gtk_menu_item_new_with_label("");

src/gui/presets.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,16 @@ typedef struct dt_gui_presets_edit_dialog_t
7575
void dt_gui_presets_init();
7676

7777
/** add or replace a generic (i.e. non-exif specific) preset for this operation. */
78-
void dt_gui_presets_add_generic(const char *name,
78+
/** the names _have_ to be marked for translation with _("") otherwise use dt_gui_presets_add_with_blendop */
79+
#define dt_gui_presets_add_generic(name, ...) dt_gui_presets_add_generic(N##name, __VA_ARGS__)
80+
void (dt_gui_presets_add_generic)(const char *name,
7981
const dt_dev_operation_t op,
8082
const int32_t version,
8183
const void *params,
8284
const int32_t params_size,
8385
const int32_t enabled,
8486
const dt_develop_blend_colorspace_t blend_cst);
85-
87+
#define BUILTIN_PRESET(name) BUILTIN_PREFIX name
8688
/** same as add_generic but also supply blendop parameters for the presets. */
8789
void dt_gui_presets_add_with_blendop(const char *name,
8890
const dt_dev_operation_t op,

0 commit comments

Comments
 (0)