Set the role of a GtkModelButton via “action-name”



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 */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]