Skip to content

Commit 102b717

Browse files
committed
migrate collection popover menu
1 parent 1c7eebf commit 102b717

File tree

4 files changed

+134
-58
lines changed

4 files changed

+134
-58
lines changed

data/themes/darktable.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,22 @@ menuitem label,
894894
margin: 0;
895895
}
896896

897+
/*------------------------------------------------
898+
- Popup menu -
899+
----------------------------------------------*/
900+
popover.menu {
901+
padding: 0;
902+
}
903+
904+
popover.menu modelbutton {
905+
padding: 0.1em 0.5em;
906+
}
907+
908+
popover.menu modelbutton:hover {
909+
background-color: @selected_bg_color;
910+
}
911+
912+
897913
tooltip,
898914
#range-current
899915
{

src/gui/gtk.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4666,6 +4666,21 @@ void dt_gui_dialog_restore_size(GtkDialog *dialog, const char *conf)
46664666
g_signal_connect(dialog, "configure-event", G_CALLBACK(_resize_dialog), (gpointer)conf);
46674667
}
46684668

4669+
GtkWidget *dt_gui_popover_menu_from_model(GtkWidget *parent, GMenu *menu)
4670+
{
4671+
GtkWidget *popover_menu;
4672+
4673+
#if GTK_CHECK_VERSION(4, 0, 0)
4674+
popover_menu = gtk_popover_menu_new_from_model(G_MENU_MODEL(menu));
4675+
gtk_widget_set_parent(popover_menu, parent);
4676+
#else
4677+
popover_menu = gtk_popover_new_from_model(parent, G_MENU_MODEL(menu));
4678+
#endif
4679+
4680+
return popover_menu;
4681+
}
4682+
4683+
46694684
// clang-format off
46704685
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
46714686
// vim: shiftwidth=2 expandtab tabstop=2 cindent

src/gui/gtk.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,9 @@ void dt_gui_dialog_restore_size(GtkDialog *dialog, const char *conf);
637637

638638
// returns the session type at runtime
639639
dt_gui_session_type_t dt_gui_get_session_type(void);
640+
// Popover menu
641+
GtkWidget *dt_gui_popover_menu_from_model(GtkWidget *parent, GMenu *menu);
642+
640643

641644
G_END_DECLS
642645

src/libs/collect.c

Lines changed: 100 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ typedef struct dt_lib_collect_t
9696
gboolean inited;
9797

9898
GtkWidget *history_box;
99+
100+
GSimpleActionGroup *action_group;
99101
} dt_lib_collect_t;
100102

101103
typedef struct dt_lib_collect_params_rule_t
@@ -2926,9 +2928,41 @@ static gboolean entry_focus_in_callback(GtkWidget *w,
29262928
return FALSE;
29272929
}
29282930

2929-
static void menuitem_mode(GtkMenuItem *menuitem,
2930-
dt_lib_collect_rule_t *d)
2931+
static gboolean _process_variant_params(GVariant *parameter,
2932+
gpointer userdata,
2933+
dt_lib_collect_mode_t *mode,
2934+
dt_lib_collect_rule_t **d)
2935+
{
2936+
const gsize nb = g_variant_n_children(parameter);
2937+
2938+
if(nb != 2)
2939+
return FALSE;
2940+
2941+
dt_lib_collect_t *m = (dt_lib_collect_t *)userdata;
2942+
2943+
GVariant *v = g_variant_get_child_value(parameter, 0);
2944+
*mode = g_variant_get_int32(v);
2945+
g_variant_unref(v);
2946+
2947+
v = g_variant_get_child_value(parameter, 1);
2948+
const int rule_index = g_variant_get_int32(v);
2949+
g_variant_unref(v);
2950+
2951+
*d = &m->rule[rule_index];
2952+
2953+
return TRUE;
2954+
}
2955+
2956+
static void _menuitem_mode(GSimpleAction *action,
2957+
GVariant *parameter,
2958+
gpointer userdata)
29312959
{
2960+
dt_lib_collect_mode_t mode;
2961+
dt_lib_collect_rule_t *d = NULL;
2962+
2963+
if(!_process_variant_params(parameter, userdata, &mode, &d))
2964+
return;
2965+
29322966
// add next row with and operator
29332967
const int _a = dt_conf_get_int("plugins/lighttable/collect/num_rules");
29342968
const int active = CLAMP(_a, 1, MAX_RULES);
@@ -2937,8 +2971,6 @@ static void menuitem_mode(GtkMenuItem *menuitem,
29372971
{
29382972
char confname[200] = { 0 };
29392973
snprintf(confname, sizeof(confname), "plugins/lighttable/collect/mode%1d", active);
2940-
const dt_lib_collect_mode_t mode =
2941-
GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "menuitem_mode"));
29422974

29432975
dt_conf_set_int(confname, mode);
29442976
snprintf(confname, sizeof(confname), "plugins/lighttable/collect/string%1d", active);
@@ -2953,17 +2985,22 @@ static void menuitem_mode(GtkMenuItem *menuitem,
29532985
DT_COLLECTION_PROP_UNDEF, NULL);
29542986
}
29552987

2956-
static void menuitem_mode_change(GtkMenuItem *menuitem,
2957-
dt_lib_collect_rule_t *d)
2988+
static void _menuitem_mode_change(GSimpleAction *action,
2989+
GVariant *parameter,
2990+
gpointer userdata)
29582991
{
2992+
dt_lib_collect_mode_t mode;
2993+
dt_lib_collect_rule_t *d = NULL;
2994+
2995+
if(!_process_variant_params(parameter, userdata, &mode, &d))
2996+
return;
2997+
29592998
// add next row with and operator
29602999
const int num = d->num + 1;
29613000
if(num < MAX_RULES && num > 0)
29623001
{
29633002
char confname[200] = { 0 };
29643003
snprintf(confname, sizeof(confname), "plugins/lighttable/collect/mode%1d", num);
2965-
const dt_lib_collect_mode_t mode =
2966-
GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "menuitem_mode"));
29673004
dt_conf_set_int(confname, mode);
29683005
}
29693006
dt_lib_collect_t *c = get_collect(d);
@@ -3186,9 +3223,15 @@ static void _metadata_changed(gpointer instance,
31863223
}
31873224
}
31883225

3189-
static void menuitem_clear(GtkMenuItem *menuitem,
3190-
dt_lib_collect_rule_t *d)
3226+
static void _menuitem_clear(GSimpleAction *simple,
3227+
GVariant *parameter,
3228+
gpointer userdata)
31913229
{
3230+
dt_lib_collect_t *m = (dt_lib_collect_t*) userdata;
3231+
3232+
const int index = g_variant_get_int32(parameter);
3233+
dt_lib_collect_rule_t *d = &m->rule[index];
3234+
31923235
// remove this row, or if 1st, clear text entry box
31933236
const int _a = dt_conf_get_int("plugins/lighttable/collect/num_rules");
31943237
const int active = CLAMP(_a, 1, MAX_RULES);
@@ -3233,72 +3276,58 @@ static void menuitem_clear(GtkMenuItem *menuitem,
32333276
DT_COLLECTION_PROP_UNDEF, NULL);
32343277
}
32353278

3236-
static gboolean popup_button_callback(GtkWidget *widget,
3279+
static gboolean popup_button_callback(GtkWidget *button,
32373280
GdkEventButton *event,
32383281
dt_lib_collect_rule_t *d)
32393282
{
32403283
if(event->button != 1)
32413284
return FALSE;
32423285

3243-
GtkWidget *menu = gtk_menu_new();
3244-
GtkWidget *mi;
3286+
GMenu *menu = g_menu_new();
32453287
const int _a = dt_conf_get_int("plugins/lighttable/collect/num_rules");
32463288
const int active = CLAMP(_a, 1, MAX_RULES);
32473289

3248-
mi = gtk_menu_item_new_with_label(_("clear this rule"));
3249-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3250-
g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_clear), d);
3251-
3290+
gchar *action;
3291+
3292+
action = g_strdup_printf("collect.clear(%d)", d->num);
3293+
g_menu_append(menu, _("clear this rule"), action);
3294+
g_free(action);
3295+
32523296
if(d->num == active - 1)
32533297
{
3254-
mi = gtk_menu_item_new_with_label(_("narrow down search"));
3255-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3256-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_AND));
3257-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3258-
g_signal_connect(G_OBJECT(mi), "activate",
3259-
G_CALLBACK(menuitem_mode), d);
3260-
3261-
mi = gtk_menu_item_new_with_label(_("add more images"));
3262-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3263-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_OR));
3264-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3265-
g_signal_connect(G_OBJECT(mi), "activate",
3266-
G_CALLBACK(menuitem_mode), d);
3267-
3268-
mi = gtk_menu_item_new_with_label(_("exclude images"));
3269-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3270-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_AND_NOT));
3271-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3272-
g_signal_connect(G_OBJECT(mi), "activate",
3273-
G_CALLBACK(menuitem_mode), d);
3298+
const char *fmt = "collect.mode((%d,%d))";
3299+
3300+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_AND, d->num);
3301+
g_menu_append(menu, _("narrow down search"), action);
3302+
g_free(action);
3303+
3304+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_OR, d->num);
3305+
g_menu_append(menu, _("add more images"), action);
3306+
g_free(action);
3307+
3308+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_AND_NOT, d->num);
3309+
g_menu_append(menu, _("exclude images"), action);
3310+
g_free(action);
32743311
}
32753312
else if(d->num < active - 1)
32763313
{
3277-
mi = gtk_menu_item_new_with_label(_("change to: and"));
3278-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3279-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_AND));
3280-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3281-
g_signal_connect(G_OBJECT(mi), "activate",
3282-
G_CALLBACK(menuitem_mode_change), d);
3314+
const char *fmt = "collect.modechange((%d,%d))";
32833315

3284-
mi = gtk_menu_item_new_with_label(_("change to: or"));
3285-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3286-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_OR));
3287-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3288-
g_signal_connect(G_OBJECT(mi), "activate",
3289-
G_CALLBACK(menuitem_mode_change), d);
3316+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_AND, d->num);
3317+
g_menu_append(menu, _("change to: and"), action);
3318+
g_free(action);
32903319

3291-
mi = gtk_menu_item_new_with_label(_("change to: except"));
3292-
g_object_set_data(G_OBJECT(mi), "menuitem_mode",
3293-
GINT_TO_POINTER(DT_LIB_COLLECT_MODE_AND_NOT));
3294-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
3295-
g_signal_connect(G_OBJECT(mi), "activate",
3296-
G_CALLBACK(menuitem_mode_change), d);
3297-
}
3320+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_OR, d->num);
3321+
g_menu_append(menu, _("change to: or"), action);
3322+
g_free(action);
32983323

3299-
gtk_widget_show_all(GTK_WIDGET(menu));
3324+
action = g_strdup_printf(fmt, DT_LIB_COLLECT_MODE_AND_NOT, d->num);
3325+
g_menu_append(menu, _("change to: except"), action);
3326+
g_free(action);
3327+
}
33003328

3301-
gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent *)event);
3329+
GtkWidget *popover_menu = dt_gui_popover_menu_from_model(button, menu);
3330+
gtk_popover_popup(GTK_POPOVER(popover_menu));
33023331

33033332
return TRUE;
33043333
}
@@ -3656,6 +3685,17 @@ void gui_init(dt_lib_module_t *self)
36563685
self->widget = dt_gui_vbox();
36573686
dt_gui_add_class(self->widget, "dt_spacing_sw");
36583687

3688+
// setup the actions for this module
3689+
const GActionEntry entries[] = {
3690+
{ "clear", _menuitem_clear, "i" },
3691+
{ "mode", _menuitem_mode, "(ii)" },
3692+
{ "modechange", _menuitem_mode_change, "(ii)" }
3693+
};
3694+
3695+
d->action_group = g_simple_action_group_new();
3696+
g_action_map_add_action_entries(G_ACTION_MAP(d->action_group), entries, G_N_ELEMENTS(entries), d);
3697+
gtk_widget_insert_action_group(self->widget, "collect", G_ACTION_GROUP(d->action_group));
3698+
36593699
d->active_rule = 0;
36603700
d->nb_rules = 0;
36613701
d->params = (dt_lib_collect_params_t *)malloc(sizeof(dt_lib_collect_params_t));
@@ -3810,6 +3850,8 @@ void gui_cleanup(dt_lib_module_t *self)
38103850
g_object_unref(d->listfilter);
38113851
g_object_unref(d->vmonitor);
38123852

3853+
g_object_unref(d->action_group);
3854+
38133855
/* TODO: Make sure we are cleaning up all allocations */
38143856

38153857
free(self->data);

0 commit comments

Comments
 (0)