PolKitGnomeAction

PolKitGnomeAction — A GtkAction subclass where instances can be tied to a specific PolicyKit action.

Synopsis

                    PolKitGnomeActionPrivate;
                    PolKitGnomeAction;
PolKitGnomeAction*  polkit_gnome_action_new             (const gchar *name);
PolKitGnomeAction*  polkit_gnome_action_new_default     (const gchar *name,
                                                         PolKitAction *polkit_action,
                                                         const gchar *label,
                                                         const gchar *tooltip);
PolKitResult        polkit_gnome_action_get_polkit_result
                                                        (PolKitGnomeAction *action);
gboolean            polkit_gnome_action_get_sensitive   (PolKitGnomeAction *action);
void                polkit_gnome_action_set_sensitive   (PolKitGnomeAction *action,
                                                         gboolean sensitive);
gboolean            polkit_gnome_action_get_visible     (PolKitGnomeAction *action);
void                polkit_gnome_action_set_visible     (PolKitGnomeAction *action,
                                                         gboolean visible);
GtkWidget*          polkit_gnome_action_create_button   (PolKitGnomeAction *action);

Object Hierarchy

  GObject
   +----GtkAction
         +----PolKitGnomeAction
               +----PolKitGnomeToggleAction

Implemented Interfaces

PolKitGnomeAction implements GtkBuildable.

Properties

  "auth-icon-name"           gchar*                : Read / Write
  "auth-label"               gchar*                : Read / Write
  "auth-sensitive"           gboolean              : Read / Write
  "auth-short-label"         gchar*                : Read / Write
  "auth-tooltip"             gchar*                : Read / Write
  "auth-visible"             gboolean              : Read / Write
  "master-sensitive"         gboolean              : Read / Write
  "master-visible"           gboolean              : Read / Write
  "no-icon-name"             gchar*                : Read / Write
  "no-label"                 gchar*                : Read / Write
  "no-sensitive"             gboolean              : Read / Write
  "no-short-label"           gchar*                : Read / Write
  "no-tooltip"               gchar*                : Read / Write
  "no-visible"               gboolean              : Read / Write
  "polkit-action"            gpointer              : Read / Write / Construct
  "polkit-action-sufficient" GValueArray*          : Read / Write / Construct
  "self-blocked-icon-name"   gchar*                : Read / Write
  "self-blocked-label"       gchar*                : Read / Write
  "self-blocked-sensitive"   gboolean              : Read / Write
  "self-blocked-short-label" gchar*                : Read / Write
  "self-blocked-tooltip"     gchar*                : Read / Write
  "self-blocked-visible"     gboolean              : Read / Write
  "target-pid"               guint                 : Read / Write / Construct
  "yes-icon-name"            gchar*                : Read / Write
  "yes-label"                gchar*                : Read / Write
  "yes-sensitive"            gboolean              : Read / Write
  "yes-short-label"          gchar*                : Read / Write
  "yes-tooltip"              gchar*                : Read / Write
  "yes-visible"              gboolean              : Read / Write

Signals

  "auth-end"                                       : Run Last
  "auth-start"                                     : Run Last
  "polkit-result-changed"                          : Run Last

Description

Actions in GTK+ represent operations that the user can be perform, along with some information how it should be presented in the interface. Each action provides methods to create icons, menu items and toolbar items representing itself. Each action can have one or more proxy menu item, toolbar button or other proxy widgets. Proxies mirror the state of the action (text label, tooltip, icon, visible, sensitive, etc), and should change when the action's state changes. When the proxy is activated, it should activate its action.

Instances of PolKitGnomeAction class updates the label, tooltip, icon-name, visible and properties of the parent GtkAction instance according to what result PolicyKit gives about a given PolKitAction object. The PolKitGnomeContext class is used internally to track changes. This means that external events (such as the editing of the /etc/PolicyKit/PolicyKit.conf file, ConsoleKit session activity changes or if the user gains a privilege via authentication) will trigger the action, and thus connected proxy widgets, to be updated.

In addition, the PolKitGnomeAction class intercepts the ::activate signal defined in GtkAction. When the result from PolicyKit is yes, the signal is propagated. If the result is auth, polkit_gnome_auth_show_dialog() will be used to bring up an authentication dialog for the given PolKitAction. If the user succesfully gained the privilege, a ::activate signal will be synthesized. If the result is no, the signal is also propagated.

As a result, everything happens under the covers; the application programmer using PolKitGnomeAction will only get the ::activate signal when the answer from PolicyKit is yes and as such don't have to worry about bringing up authentication dialogs if the property "no-sensitive" is set to FALSE.

When an authentication dialog is show, the PolKitGnomeAction class will pass the XID of the top-level window that the proxy widget causing the activation to polkit_gnome_auth_show_dialog().

An example of how to use PolKitGnomeAction follows. First, build the following program

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 *
 * polkit-gnome-example: Simple example showing how a GTK+ application
 * can use PolicyKit.
 *
 * Copyright (C) 2007 David Zeuthen <david@fubar.dk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <glib/gi18n.h>
#include <polkit-gnome/polkit-gnome.h>

static GtkWidget *toplevel_window;
static PolKitGnomeContext *pkgc;

static void 
_button_toggled (GtkToggleButton *toggle_button, PolKitGnomeAction *action)
{
        g_debug ("in _button_toggled for action '%s'", gtk_action_get_name (GTK_ACTION (action)));
}

static void 
_button_clicked (GtkToggleButton *toggle_button, PolKitGnomeAction *action)
{
        g_debug ("in _button_clicked for '%s'", gtk_action_get_name (GTK_ACTION (action)));
}

/* This function is called when the following two conditions are true
 *
 *  - the user clicks one of the buttons created via the method
 *    polkit_gnome_action_create_button() (see main() below)
 *
 *  - For the PolKitAction associated with the button, PolicyKit
 *    reports either 'no' or 'yes'.
 *
 *  In the event the user clicks a button and he is not privileged
 *  (e.g. PolicyKit returns one of the 'auth' results) he will be
 *  asked to authenticate; this all happens behind the scenes; the
 *  application _only_ gets the ::activate signal on PolKitGnomeAction
 *  instances when PolicyKit reports that the user is privileged.
 *
 *  Note that for action org.gnome.policykit.examples.tweak, the
 *  corresponding PolKitGnomeAction is configured to be sensitive (see
 *  main() below) even when PolicyKit reports 'no'. Hence we need to
 *  handle that case too and we do that by popping up a dialog. Note
 *  that this can only be triggered by adding a stanza like
 *
 *  <match action="org.gnome.policykit.examples.tweak">
 *    <return result="no"/>
 *  </match>
 *
 *  to the /etc/PolicyKit/PolicyKit.conf file.
 */
static void
activate_polkit_gnome_action (PolKitGnomeAction *action, gpointer user_data)
{
        PolKitCaller *pk_caller;
        PolKitAction *pk_action;
        PolKitResult pk_result;
        DBusError dbus_error;

        if (strcmp (gtk_action_get_name (GTK_ACTION (action)), "toggle") == 0) {
                /* we're not supposed to run actions when the
                 * authorization is flipped.. we're supposed to make
                 * some UI sensitive and de-sensitive.. (one use at least) */
                g_debug ("toggled for '%s'", gtk_action_get_name (GTK_ACTION (action)));
                return;
        }

        g_debug ("pretending to be the mechanism for action '%s'", gtk_action_get_name (GTK_ACTION (action)));

        g_object_get (action, "polkit-action", &pk_action, NULL);
        
        dbus_error_init (&dbus_error);        
        pk_caller = polkit_tracker_get_caller_from_pid (pkgc->pk_tracker, 
                                                        getpid (),
                                                        &dbus_error);
        if (pk_caller == NULL) {
                g_warning ("Cannot get PolKitCaller object for ourselves (pid=%d): %s: %s",
                           getpid (), dbus_error.name, dbus_error.message);
                dbus_error_free (&dbus_error);
        } else {
                /* note how we pass #TRUE to revoke_if_one_shot - this is because we're
                 * pretending to be the mechanism
                 */
                pk_result = polkit_context_is_caller_authorized (pkgc->pk_context, 
                                                                 pk_action, 
                                                                 pk_caller,
                                                                 TRUE,
                                                                 NULL);
                
                polkit_caller_unref (pk_caller);
        }

        polkit_action_unref (pk_action);

}

static void
activate_action (GtkAction *action, gpointer user_data)
{
        if (g_ascii_strcasecmp (gtk_action_get_name (action), "Quit") == 0) {
                exit (0);
        } else if (g_ascii_strcasecmp (gtk_action_get_name (action), "About") == 0) {
                const char *authors[] = {
                        "David Zeuthen <david@fubar.dk>",
                        NULL};
                const char *documenters[] = {
                        "David Zeuthen <david@fubar.dk>",
                        NULL};


                gtk_show_about_dialog (NULL,
                                       "version", VERSION,
                                       "copyright", _("Copyright © 2007 David Zeuthen"),
                                       "website-label", _("PolicyKit-gnome Website"),
                                       "website", "http://hal.freedesktop.org/docs/PolicyKit-gnome/",
                                       "program-name", _("PolicyKit-gnome demo"),
                                       "comments", _("PolicyKit for the GNOME desktop"),
                                       "logo-icon-name", GTK_STOCK_DIALOG_AUTHENTICATION,
                                       "authors", authors,
                                       "documenters", documenters,
                                       NULL);

        }
}

static GtkActionEntry entries[] = {
        { "FileMenu", NULL, N_("_File") },               /* name, stock id, label */
        { "ActionsMenu", NULL, N_("_Actions") },         /* name, stock id, label */
        { "HelpMenu", NULL, N_("_Help") },               /* name, stock id, label */

        { "Quit", GTK_STOCK_QUIT,                        /* name, stock id */
          N_("_Quit"), "<control>Q",                     /* label, accelerator */     
          N_("Quit"),                                    /* tooltip */
          G_CALLBACK (activate_action) },

        { "About", GTK_STOCK_ABOUT,                      /* name, stock id */
          N_("_About"), "<control>A",                    /* label, accelerator */     
          N_("About"),                                   /* tooltip */  
          G_CALLBACK (activate_action) },
};
static guint n_entries = G_N_ELEMENTS (entries);

static const gchar *ui_info = 
"<ui>"
"  <menubar name='MenuBar'>"
"    <menu action='FileMenu'>"
"      <menuitem action='Quit'/>"
"    </menu>"
"    <menu action='ActionsMenu'>"
"      <menuitem action='frobnicate'/>"
"      <menuitem action='jump'/>"
"      <menuitem action='tweak'/>"
"      <menuitem action='twiddle'/>"
"      <menuitem action='punch'/>"
"      <menuitem action='toggle'/>"
"    </menu>"
"    <menu action='HelpMenu'>"
"      <menuitem action='About'/>"
"    </menu>"
"  </menubar>"
"  <toolbar  name='ToolBar'>"
"    <toolitem action='Quit'/>"
"    <toolitem action='About'/>"
"    <separator action='Sep1'/>"
"    <toolitem action='frobnicate'/>"
"    <toolitem action='jump'/>"
"    <toolitem action='tweak'/>"
"    <toolitem action='twiddle'/>"
"    <toolitem action='punch'/>"
"    <toolitem action='toggle'/>"
"  </toolbar>"
"</ui>";

int
main (int argc, char **argv)
{
        GtkWidget *hbox;
        GtkWidget *vbox;
        GtkWidget *vbox2;
        GtkWidget *label;
        GMainLoop*loop;
        PolKitAction *pk_action;
        PolKitGnomeAction *action;
        GtkWidget *button;
        GtkUIManager *ui;
        GtkActionGroup *actions;

        gtk_init (&argc, &argv);

        pkgc = polkit_gnome_context_get (NULL);

        loop = g_main_loop_new (NULL, FALSE);
        
        toplevel_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        actions = gtk_action_group_new ("Actions");
        gtk_action_group_add_actions (actions, entries, n_entries, NULL);

        ui = gtk_ui_manager_new ();
        gtk_ui_manager_insert_action_group (ui, actions, 0);

        gtk_window_add_accel_group (GTK_WINDOW (toplevel_window), 
                                    gtk_ui_manager_get_accel_group (ui));


        gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, NULL);

        /*----------------------------------------------------------------*/

        vbox = gtk_vbox_new (FALSE, 10);
        gtk_container_add (GTK_CONTAINER (toplevel_window), vbox);

        vbox2 = gtk_vbox_new (FALSE, 0);
        gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);

        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Frobnicate</b> requires the "
                                                   "user to authenticate. The authorization is kept for "
                                                   "the life time of the process"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.frobnicate");
        action = polkit_gnome_action_new_default ("frobnicate", pk_action, _("Frobnicate!"), NULL);
        polkit_action_unref (pk_action);
        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (action));
        button = polkit_gnome_action_create_button (action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            button, 
                            FALSE, FALSE, 0);
        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Jump</b> requires the "
                                                   "user to authenticate. This is a one-shot authorization."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.jump");
        action = polkit_gnome_action_new_default ("jump", pk_action, _("Jump!"), NULL);
        polkit_action_unref (pk_action);
        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (action));
        button = polkit_gnome_action_create_button (action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            button, 
                            FALSE, FALSE, 0);
        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Tweak</b> requires a system "
                                                   "administrator to authenticate. This instance "
                                                   "overrides the defaults set in polkit_gnome_action_new()."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.tweak");
        action = polkit_gnome_action_new_default ("tweak", pk_action, _("Tweak!"), NULL);
        polkit_action_unref (pk_action);

        /* For this particular GtkAction instance, we want to customize the appearence */
        g_object_set (action,
                      "no-visible",       TRUE,
                      "no-sensitive",     TRUE,
                      "no-short-label",   _("Tweak"),
                      "no-label",         _("Tweak (long)"),
                      "no-tooltip",       _("If your admin wasn't annoying, you could do this"),
                      "no-icon-name",     GTK_STOCK_NO,
                      
                      "auth-visible",     TRUE,
                      "auth-sensitive",   TRUE,
                      "auth-short-label", _("Tweak..."),
                      "auth-label",       _("Tweak... (long)"),
                      "auth-tooltip",     _("Only card carrying tweakers can do this!"),
                      "auth-icon-name",   GTK_STOCK_DIALOG_AUTHENTICATION,
                      
                      "yes-visible",      TRUE,
                      "yes-sensitive",    TRUE,
                      "yes-short-label",  _("Tweak!"),
                      "yes-label",        _("Tweak! (long)"),
                      "yes-tooltip",      _("Go ahead, tweak tweak tweak!"),
                      "yes-icon-name",    GTK_STOCK_YES,
                      NULL);

        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (action));
        button = polkit_gnome_action_create_button (action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            button, 
                            FALSE, FALSE, 0);
        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Twiddle</b> requires a system "
                                                   "administrator to authenticate. Once authenticated, this "
                                                   "privilege can be retained indefinitely."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.twiddle");
        action = polkit_gnome_action_new_default ("twiddle", pk_action, _("Twiddle!"), NULL);
        polkit_action_unref (pk_action);
        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (action));
        button = polkit_gnome_action_create_button (action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            button, 
                            FALSE, FALSE, 0);
        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("Making the helper <b>Punch</b> requires the user to "
                                                   "authenticate. Once authenticated, this privilege can "
                                                   "be retained for the remainder of the desktop session."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.punch");
        action = polkit_gnome_action_new_default ("punch", pk_action, _("Punch!"), NULL);
        polkit_action_unref (pk_action);
        g_signal_connect (action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (action));
        button = polkit_gnome_action_create_button (action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            polkit_gnome_action_create_button (action), 
                            FALSE, FALSE, 0);
        g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked), action);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("The <b>Toggle</b> action demonstrates the use of "
                                                   "PolicyKit to drive a GtkToggleButton; it's an intuitive "
                                                   "way to ask users to give up authorizations when they "
                                                   "are done with them. E.g. the button is 'pressed in' exactly"
                                                   "when the authorization is held. Toggling the button means "
                                                   "obtaining resp. revoking the authorization in question."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

        pk_action = polkit_action_new ();
        polkit_action_set_action_id (pk_action, "org.gnome.policykit.examples.toggle");
        PolKitGnomeToggleAction *toggle_action;
        toggle_action = polkit_gnome_toggle_action_new_default ("toggle", pk_action, 
                                                                _("Click to make changes..."),
                                                                _("Click to prevent changes"));
        //g_object_set (toggle_action, "target-pid", 24887, NULL);
        polkit_action_unref (pk_action);
        g_signal_connect (toggle_action, "activate", G_CALLBACK (activate_polkit_gnome_action), NULL);
        gtk_action_group_add_action (actions, GTK_ACTION (toggle_action));
        GtkWidget *toggle_button;
        toggle_button = polkit_gnome_toggle_action_create_toggle_button (toggle_action);
        g_signal_connect (toggle_button, "toggled", G_CALLBACK (_button_toggled), toggle_action);
        gtk_box_pack_start (GTK_BOX (vbox), 
                            toggle_button, 
                            FALSE, FALSE, 0);

        /*----------------------------------------------------------------*/
        gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
        /*----------------------------------------------------------------*/

        hbox = gtk_hbox_new (FALSE, 5);
        gtk_box_pack_start (GTK_BOX (hbox), gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, 
                                                                      GTK_ICON_SIZE_SMALL_TOOLBAR), FALSE, FALSE, 0);
        label = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (label), _("<i>Tip: try editing /etc/PolicyKit/Policy.conf and see the proxy widgets update in real-time.</i>."));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

        /*----------------------------------------------------------------*/

        g_object_unref (actions);

        gtk_box_pack_start (GTK_BOX (vbox2),
                            gtk_ui_manager_get_widget (ui, "/MenuBar"),
                            FALSE, FALSE, 0);

        GtkWidget *toolbar;
        toolbar = gtk_ui_manager_get_widget (ui, "/ToolBar");
        gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
        gtk_box_pack_start (GTK_BOX (vbox2),
                            toolbar,
                            FALSE, FALSE, 0);

        /*----------------------------------------------------------------*/

        gtk_window_set_default_size (GTK_WINDOW (toplevel_window), 700, 0);
        gtk_window_set_title (GTK_WINDOW (toplevel_window), _("PolicyKit-gnome demo"));
        g_signal_connect (toplevel_window, "delete-event", (GCallback) exit, NULL);
        gtk_widget_show_all (toplevel_window);

        g_main_loop_run (loop);
        return 0;
}

with

gcc -o polkit-gnome-example `pkg-config --cflags --libs polkit-gnome` polkit-gnome-example.c

Then, put the following content

FIXME: MISSING XINCLUDE CONTENT

into a file /usr/share/PolicyKit/policy/polkit-gnome-example.policy. Finally, run polkit-gnome-example. It should display a window like this:

If the "Twiddle!" button is pressed, an authentication dialog should pop up

Here is how what the application looks like if the user gains authorization for all the actions:

Regarding how to build an example mechanism that this GTK+ application can take advantage of, please refer to the PolKitContext class for examples.

Details

PolKitGnomeActionPrivate

typedef struct _PolKitGnomeActionPrivate PolKitGnomeActionPrivate;


PolKitGnomeAction

typedef struct _PolKitGnomeAction PolKitGnomeAction;

The PolKitGnomeAction struct contains only private data members and should not be accessed directly.


polkit_gnome_action_new ()

PolKitGnomeAction*  polkit_gnome_action_new             (const gchar *name);

Creates a new PolKitGnomeAction object. The typical use for this function is for specialized use where polkit_gnome_action_new_default() does not meet the needs of the application. A short example of the usage of this contructor follows.

If the 'polkit-action' property is NULL the behavior is similar to as if a PolKitAction returned POLKIT_RESULT_YES.

One can set the 'polkit-action-sufficient' property to a GValueArray of pointers to PolKitAction objects. The semantics of this property is that if the user is authorized for any of the given actions in 'polkit-action-sufficient' then the behavior is the same as if they're authorized for the action denoted by 'polkit-action'. This is useful in a setup where you have two similar actions and one implies the other. For example, in gnome-system-monitor there are two actions org.gnome.system-monitor.increase-own-priority (Increase the priority of a process owned by yourself) and org.gnome.system-monitor.change-priorty (Change priority of any process). As the latter clearly implies the former, one would set the latter in the 'polkit-action-sufficient' property when constructing a PolKitAction for the former.

PolKitAction *polkit_action;
PolKitGnomeAction *action;

polkit_action = polkit_action_new ();
polkit_action_set_action_id (polkit_action, "org.example.some-policykit-action");

action = polkit_gnome_action_new ("blabla", NULL);
g_object_set (action,
              "polkit-action",    polkit_action,
              "no-visible",       TRUE,
              "no-sensitive",     FALSE,
              "no-short-label",   "The Action no can do!",
              "no-label",         "The Action is not permitted!",
              "no-tooltip",       "The Tooltip (no)",
              "no-icon-name",     GTK_STOCK_NO,

              "auth-visible",     TRUE,
              "auth-sensitive",   TRUE,
              "auth-short-label", "The Action requires auth...",
              "auth-label",       "The Action requires auth...",
              "auth-tooltip",     "The Tooltip (auth)",
              "auth-icon-name",   GTK_STOCK_DIALOG_AUTHENTICATION,

              "yes-visible",      TRUE,
              "yes-sensitive",    TRUE,
              "yes-short-label",  "Action!",
              "yes-label",        "Just do the Action!",
              "yes-tooltip",      "The Tooltip (yes)",
              "yes-icon-name",    GTK_STOCK_YES,
              NULL);

name :

A unique name for the action

Returns :

a new PolKitGnomeAction or NULL if error is set

polkit_gnome_action_new_default ()

PolKitGnomeAction*  polkit_gnome_action_new_default     (const gchar *name,
                                                         PolKitAction *polkit_action,
                                                         const gchar *label,
                                                         const gchar *tooltip);

Creates a new PolKitGnomeAction object with the default behavior for a given PolKitAction object.

Default behavior is defined by the label and tooltip being identical across all three four states, the action being visible in all four states, and the action being insensitive only in the state where the result from PolicyKit is no and self-blocked. Only when PolicyKit returns one of the 'auth*' results, the icon_name property will be set to GTK_STOCK_DIALOG_AUTHENTICATION.

The caller can always modify individual aspects of the action after creation, e.g. change the tooltip for the self-blocked, no, auth and yes states.

If the given polkit_action is NULL the behavior is similar to as if a PolKitAction returned POLKIT_RESULT_YES.

name :

A unique name for the action

polkit_action :

the PolKitAction to track

label :

the label to use (will also apply to short-label)

tooltip :

the tool tip to use

Returns :

a new PolKitGnomeAction or NULL if error is set

polkit_gnome_action_get_polkit_result ()

PolKitResult        polkit_gnome_action_get_polkit_result
                                                        (PolKitGnomeAction *action);

Gets the PolKitResult that indicates whether the user is privileged to do the PolKitAction associated with this PolKitGnomeAction object.

action :

The PolKitGnomeAction object

Returns :

The PolKitAction object. The caller shall not unref this object.

polkit_gnome_action_get_sensitive ()

gboolean            polkit_gnome_action_get_sensitive   (PolKitGnomeAction *action);

Get the master sensitivity, see PolKitGnomeAction:master-sensitive: for details.

action :

The PolKitGnomeAction object

Returns :

the master sensitivity

polkit_gnome_action_set_sensitive ()

void                polkit_gnome_action_set_sensitive   (PolKitGnomeAction *action,
                                                         gboolean sensitive);

Set the master sensitivity, see PolKitGnomeAction:master-sensitive: for details.

action :

The PolKitGnomeAction object

sensitive :

master sensitivity

polkit_gnome_action_get_visible ()

gboolean            polkit_gnome_action_get_visible     (PolKitGnomeAction *action);

Get the master visibility, see PolKitGnomeAction:master-visible: for details.

action :

The PolKitGnomeAction object

Returns :

the master visibility

polkit_gnome_action_set_visible ()

void                polkit_gnome_action_set_visible     (PolKitGnomeAction *action,
                                                         gboolean visible);

Set the master visibility, see PolKitGnomeAction:master-visible: for details.

action :

The PolKitGnomeAction object

visible :

master visibility

polkit_gnome_action_create_button ()

GtkWidget*          polkit_gnome_action_create_button   (PolKitGnomeAction *action);

Create a button for the given action that displays the label, tooltip and icon_name corresponding to whether the state, according to PolicyKit, is no, auth or yes.

action :

The PolKitGnomeAction object

Returns :

A GtkButton instance connected to the action

Property Details

The "auth-icon-name" property

  "auth-icon-name"           gchar*                : Read / Write

If PolicyKit evaluates the result as 'auth', use this icon-name.

Default value: NULL


The "auth-label" property

  "auth-label"               gchar*                : Read / Write

If PolicyKit evaluates the result as 'auth', use this label.

Default value: NULL


The "auth-sensitive" property

  "auth-sensitive"           gboolean              : Read / Write

If PolicyKit evaluates the result as 'auth', whether the action will be sensitive.

Default value: TRUE


The "auth-short-label" property

  "auth-short-label"         gchar*                : Read / Write

If PolicyKit evaluates the result as 'auth', use this short-label.

Default value: NULL


The "auth-tooltip" property

  "auth-tooltip"             gchar*                : Read / Write

If PolicyKit evaluates the result as 'auth', use this tooltip.

Default value: NULL


The "auth-visible" property

  "auth-visible"             gboolean              : Read / Write

If PolicyKit evaluates the result as 'auth', whether the action will be visible.

Default value: TRUE


The "master-sensitive" property

  "master-sensitive"         gboolean              : Read / Write

Can be set to FALSE to force insensitivity no matter what PolicyKit reports.

Default value: TRUE


The "master-visible" property

  "master-visible"           gboolean              : Read / Write

Can be set to FALSE to force invisibility no matter what PolicyKit reports.

Default value: TRUE


The "no-icon-name" property

  "no-icon-name"             gchar*                : Read / Write

If PolicyKit evaluates the result as 'no', use this icon-name.

Default value: NULL


The "no-label" property

  "no-label"                 gchar*                : Read / Write

If PolicyKit evaluates the result as 'no', use this label.

Default value: NULL


The "no-sensitive" property

  "no-sensitive"             gboolean              : Read / Write

If PolicyKit evaluates the result as 'no', whether the action will be sensitive.

Default value: FALSE


The "no-short-label" property

  "no-short-label"           gchar*                : Read / Write

If PolicyKit evaluates the result as 'no', use this short-label.

Default value: NULL


The "no-tooltip" property

  "no-tooltip"               gchar*                : Read / Write

If PolicyKit evaluates the result as 'no', use this tooltip.

Default value: NULL


The "no-visible" property

  "no-visible"               gboolean              : Read / Write

If PolicyKit evaluates the result as 'no', whether the action will be visible.

Default value: TRUE


The "polkit-action" property

  "polkit-action"            gpointer              : Read / Write / Construct

The PolKitAction object this GTK+ action is tracking.


The "polkit-action-sufficient" property

  "polkit-action-sufficient" GValueArray*          : Read / Write / Construct

An array of PolKitAction objects that are sufficient to have authorizations for.


The "self-blocked-icon-name" property

  "self-blocked-icon-name"   gchar*                : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this icon-name.

Default value: NULL


The "self-blocked-label" property

  "self-blocked-label"       gchar*                : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this label.

Default value: NULL


The "self-blocked-sensitive" property

  "self-blocked-sensitive"   gboolean              : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be sensitive.

Default value: FALSE


The "self-blocked-short-label" property

  "self-blocked-short-label" gchar*                : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this short-label.

Default value: NULL


The "self-blocked-tooltip" property

  "self-blocked-tooltip"     gchar*                : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, use this tooltip.

Default value: NULL


The "self-blocked-visible" property

  "self-blocked-visible"     gboolean              : Read / Write

If PolicyKit evaluates the result as 'no' and the reason is that the user has a self-granted negative authorization, whether the action will be visible.

Default value: TRUE


The "target-pid" property

  "target-pid"               guint                 : Read / Write / Construct

The target process id to receive the authorization; if 0 it is the current process.

Default value: 0


The "yes-icon-name" property

  "yes-icon-name"            gchar*                : Read / Write

If PolicyKit evaluates the result as 'yes', use this icon-name.

Default value: NULL


The "yes-label" property

  "yes-label"                gchar*                : Read / Write

If PolicyKit evaluates the result as 'yes', use this label.

Default value: NULL


The "yes-sensitive" property

  "yes-sensitive"            gboolean              : Read / Write

If PolicyKit evaluates the result as 'yes', whether the action will be sensitive.

Default value: TRUE


The "yes-short-label" property

  "yes-short-label"          gchar*                : Read / Write

If PolicyKit evaluates the result as 'yes', use this short-label.

Default value: NULL


The "yes-tooltip" property

  "yes-tooltip"              gchar*                : Read / Write

If PolicyKit evaluates the result as 'yes', use this tooltip.

Default value: NULL


The "yes-visible" property

  "yes-visible"              gboolean              : Read / Write

If PolicyKit evaluates the result as 'yes', whether the action will be visible.

Default value: TRUE

Signal Details

The "auth-end" signal

void                user_function                      (PolKitGnomeAction *action,
                                                        gboolean           gained_privilege,
                                                        gpointer           user_data)             : Run Last

The ::auth-end signal is emitted when the an authentication session ends and carries information about whether the privilege was obtained or not.

action :

the object

gained_privilege :

whether the privilege was gained

user_data :

user data set when the signal handler was connected.

The "auth-start" signal

void                user_function                      (PolKitGnomeAction *action,
                                                        gpointer           user_data)      : Run Last

The ::auth-start signal is emitted when an authentication session starts.

action :

the object

user_data :

user data set when the signal handler was connected.

The "polkit-result-changed" signal

void                user_function                      (PolKitGnomeAction *action,
                                                        gint               current_result,
                                                        gpointer           user_data)           : Run Last

The ::polkit-result-changed signal is emitted when the PolicyKit result changes. This can happen when external factors (config file, ConsoleKit, privilege granted / revoked) change since the PolKitGnomeAction class listens for events using the PolKitGnomeContext class.

action :

the object

current_result :

current PolKitResult from PolicyKit regarding given PolKitAction object

user_data :

user data set when the signal handler was connected.