Hello! I'm trying to create a popover with a GtkModelButton and a checkbox directly in C. I can achieve this using the following snippet: // ----------------------------------------------- const GActionEntry app_actions[] = { { "check", NULL, NULL, NULL, check_action } }; /* ... */ checkButton = gtk_model_button_new(); gtk_box_pack_start (GTK_BOX (popBox), checkButton, TRUE, TRUE, 0); gtk_button_set_label (GTK_BUTTON (checkButton), "Check Me"); // ????: Setting the following property shouldn't be required when // using action-name and action-target g_object_set (G_OBJECT (checkButton), "role", GTK_BUTTON_ROLE_CHECK, NULL); gtk_actionable_set_action_name (GTK_ACTIONABLE (checkButton), "app.check"); /* ... */ g_action_map_add_action_entries (G_ACTION_MAP (app), app_actions, G_N_ELEMENTS (app_actions), (gpointer) a); // ----------------------------------------------- Here setting the "role" property does the job. However, the documentation of GtkModelButton states that this shouldn't be required: [BEGIN CITE] When the action is specified via the “action-name” and “action-target” properties, the role of the button (i.e. whether it is a plain, check or radio button) is determined by the type of the action and doesn't have to be explicitly specified with the “role” property. [END CITE] I'm wondering how I can set the type of the action? I assume that I've to this in the GActionEntry, have, however, no real clue how to accomplish this? Below is my small demo program. Cheers, Martin //-------------------------------------------------- /*! * \mainpage A simple demo program to show-case a custom popover. */ #include <gtk/gtk.h> #include <glib/gprintf.h> typedef struct { GtkApplication *app; GtkWidget *window; GtkWidget *omButton; GtkWidget *popover; GtkAdjustment *spinAdj; GtkAdjustment *scaleAdj; } myWidgets; static void click_action (GSimpleAction *action, GVariant *parameter, gpointer data); static void check_action (GSimpleAction *action, GVariant *parameter, gpointer data); static void popover_action (GSimpleAction *action, GVariant *parameter, gpointer data); static void set_action (GSimpleAction *action, GVariant *parameter, gpointer data); GActionEntry app_actions[] = { { "click", click_action }, { "check", NULL, NULL, "false", check_action }, { "sclick", set_action }, { "show", popover_action } }; static void check_action (GSimpleAction *action, GVariant *parameter, gpointer data) { if (g_variant_get_boolean (parameter)) g_printf ("Item is checked.\n"); else g_printf ("Item is unchecked.\n"); g_simple_action_set_state (action, parameter); } static void click_action (GSimpleAction *action, GVariant *parameter, gpointer data) { static gint i = 1; g_printf ("Item cliked %d times.\n", i++); } static void set_action (GSimpleAction *action, GVariant *parameter, gpointer data) { gint ival; gdouble fval; myWidgets *a = (myWidgets *) data; ival = gtk_adjustment_get_value (a->spinAdj); g_printf ("Spin widget value: %d\n", ival); fval = gtk_adjustment_get_value (a->scaleAdj); g_printf ("Scale widget value: %1.2f\n", fval); // hide the popover after clicking the SET button gtk_widget_hide (a->popover); } /*! * \brief Construct the popover. */ static void popover_action (GSimpleAction *action, GVariant *parameter, gpointer data) { GtkWidget *popBox; GtkWidget *alabel; GtkWidget *clickButton; GtkWidget *checkButton; GtkWidget *sep; GtkWidget *slabel; GtkWidget *usBox, *usLabel; GtkWidget *lsBox, *lsLabel; GtkWidget *setButton; GtkWidget *scale, *spinner; GtkCssProvider *provider; GdkDisplay *display; GdkScreen *screen; gdouble marks[3] = { 0.0, 0.5, 1.0 }; const gchar *labels[3] = { "<small>0.0</small>", "<small>0.5</small>", "<small>1.0</small>" }; gdouble scaleVal, spinVal; myWidgets *a = (myWidgets *) data; // construct the popover associated to omButton a->popover = gtk_popover_new (a->omButton); gtk_popover_set_transitions_enabled (GTK_POPOVER (a->popover), TRUE); popBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (a->popover), popBox); gtk_container_set_border_width (GTK_CONTAINER (a->popover), 10); // a gray label alabel = gtk_label_new ("<span color=\"#666666\">Action:</span>"); gtk_label_set_use_markup (GTK_LABEL (alabel), TRUE); g_object_set (G_OBJECT (alabel), "xalign", 0.0, NULL); g_object_set (G_OBJECT (alabel), "margin", 2, NULL); gtk_box_pack_start (GTK_BOX (popBox), alabel, FALSE, FALSE, 0); // a clickable button clickButton = gtk_model_button_new(); gtk_box_pack_start (GTK_BOX (popBox), clickButton, TRUE, TRUE, 0); gtk_button_set_label (GTK_BUTTON (clickButton), "Click Me"); gtk_widget_set_size_request (clickButton, 90, 30); g_object_set (G_OBJECT (clickButton), "xalign", 0.0, NULL); g_object_set (G_OBJECT (clickButton), "margin", 2, NULL); gtk_actionable_set_action_name (GTK_ACTIONABLE (clickButton), "app.click"); // a checkbox button checkButton = gtk_model_button_new(); gtk_box_pack_start (GTK_BOX (popBox), checkButton, TRUE, TRUE, 0); gtk_button_set_label (GTK_BUTTON (checkButton), "Check Me"); gtk_widget_set_size_request (checkButton, 90, 30); g_object_set (G_OBJECT (checkButton), "xalign", 0.0, NULL); g_object_set (G_OBJECT (checkButton), "margin", 2, NULL); // TODO: Setting the following property shouldn't be required when using // action-name and action-target g_object_set (G_OBJECT (checkButton), "role", GTK_BUTTON_ROLE_CHECK, NULL); gtk_actionable_set_action_name (GTK_ACTIONABLE (checkButton), "app.check"); // a separator sep = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start (GTK_BOX (popBox), sep, FALSE, FALSE, 0); // a gray label slabel = gtk_label_new ("<span color=\"#666666\">Value:</span>"); gtk_label_set_use_markup (GTK_LABEL (slabel), TRUE); g_object_set (G_OBJECT (slabel), "xalign", 0.0, NULL); g_object_set (G_OBJECT (slabel), "margin", 2, NULL); gtk_box_pack_start (GTK_BOX (popBox), slabel, FALSE, FALSE, 0); // label (next to spinner) usBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (popBox), usBox, FALSE, FALSE, 0); usLabel = gtk_label_new ("Spin:"); gtk_widget_set_size_request (usLabel, 90, 25); g_object_set (G_OBJECT (usLabel), "xalign", 0.0, NULL); g_object_set (G_OBJECT (usLabel), "margin", 2, NULL); gtk_box_pack_start (GTK_BOX (usBox), usLabel, FALSE, FALSE, 0); // spinner if (a->spinAdj != NULL) { spinVal = gtk_adjustment_get_value (a->spinAdj); gtk_adjustment_set_value (GTK_ADJUSTMENT (a->spinAdj), spinVal); } else a->spinAdj = gtk_adjustment_new (5, 50, 300, 5, 0, 0); spinner = gtk_spin_button_new (a->spinAdj, 5, 0); gtk_box_pack_start (GTK_BOX (usBox), spinner, FALSE, FALSE, 0); // label (next to scale) lsBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (popBox), lsBox, FALSE, FALSE, 0); lsLabel = gtk_label_new ("Scale:"); gtk_widget_set_size_request (lsLabel, 90, 25); g_object_set (G_OBJECT (lsLabel), "xalign", 0.0, NULL); g_object_set (G_OBJECT (lsLabel), "margin", 2, NULL); gtk_box_pack_start (GTK_BOX (lsBox), lsLabel, FALSE, FALSE, 0); // scale if (a->scaleAdj != NULL) { scaleVal = gtk_adjustment_get_value (a->scaleAdj); gtk_adjustment_set_value (GTK_ADJUSTMENT (a->scaleAdj), scaleVal); } else a->scaleAdj = gtk_adjustment_new (0.5, 0.0, 1.0, 0.1, 0.1, 0.0); scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, a->scaleAdj); gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); gtk_scale_add_mark (GTK_SCALE (scale), marks[0], GTK_POS_BOTTOM, labels[0]); gtk_scale_add_mark (GTK_SCALE (scale), marks[1], GTK_POS_BOTTOM, labels[1]); gtk_scale_add_mark (GTK_SCALE (scale), marks[2], GTK_POS_BOTTOM, labels[2]); gtk_widget_set_size_request (scale, 120, 25); gtk_box_pack_start (GTK_BOX (lsBox), scale, FALSE, FALSE, 0); // a button setButton = gtk_button_new_with_label ("Set"); g_object_set (G_OBJECT (setButton), "xalign", 0.5, NULL); g_object_set (G_OBJECT (setButton), "margin", 2, NULL); gtk_box_pack_start (GTK_BOX (popBox), setButton, FALSE, FALSE, 0); gtk_actionable_set_action_name (GTK_ACTIONABLE (setButton), "app.sclick"); // add some padding to some labels provider = gtk_css_provider_new (); display = gdk_display_get_default (); screen = gdk_display_get_default_screen (display); gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), "GtkModelButton GtkLabel {\n" " padding-left: 10px;\n" "}\n" "\n" "GtkBox GtkBox GtkLabel {\n" " padding-left: 10px;\n" "}\n", -1, NULL); g_object_unref (provider); // display the popover gtk_widget_show_all (a->popover); } /*! * \brief Construct the main window. */ static void activate (GtkApplication *app, gpointer data) { GtkWidget *hBar; GtkWidget *omIcon; myWidgets *a = (myWidgets *) data; // create a window and set some properties a->window = gtk_application_window_new (app); gtk_window_set_application (GTK_WINDOW (a->window), GTK_APPLICATION (app)); gtk_window_set_default_size (GTK_WINDOW (a->window), 600, 500); // headerbar hBar = gtk_header_bar_new (); gtk_widget_show (hBar); gtk_header_bar_set_title (GTK_HEADER_BAR (hBar), "Popover Demo"); gtk_header_bar_set_subtitle (GTK_HEADER_BAR (hBar), "Showcase a Popover"); gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (hBar), TRUE); gtk_window_set_titlebar (GTK_WINDOW (a->window), hBar); // create the gear menu button a->omButton = gtk_button_new(); omIcon = gtk_image_new_from_icon_name ("format-justify-fill-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_button_set_image (GTK_BUTTON (a->omButton), omIcon); gtk_header_bar_pack_end (GTK_HEADER_BAR (hBar), a->omButton); gtk_actionable_set_action_name (GTK_ACTIONABLE (a->omButton), "app.show"); // associate actions with callback action functions g_action_map_add_action_entries (G_ACTION_MAP (app), app_actions, G_N_ELEMENTS (app_actions), (gpointer) a); // show the program gtk_widget_show_all (GTK_WIDGET (a->window)); } int main (int argc, char **argv) { int status; myWidgets *a = g_malloc (sizeof (myWidgets)); a->app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); g_signal_connect (a->app, "activate", G_CALLBACK (activate), (gpointer) a); status = g_application_run (G_APPLICATION (a->app), argc, argv); g_object_unref (a->app); g_free (a); return status; } /*! EOF */ _______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx https://mail.gnome.org/mailman/listinfo/gtk-list