shell: Use GVariant to convey panel arguments instead of a string array

By using a GVariant of type "av" we can potentially pass more structured
data to panels, which will become relevant with the ability to invoke
them by GAction-based DBus-activation introduced in the following patch.

https://bugzilla.gnome.org/show_bug.cgi?id=696054
This commit is contained in:
Emanuele Aina 2013-03-01 11:18:08 +01:00
parent 397181e5d2
commit 9977bb200e
11 changed files with 127 additions and 60 deletions

View file

@ -37,7 +37,7 @@ struct _CcKeyboardPanelPrivate
enum { enum {
PROP_0, PROP_0,
PROP_ARGV PROP_PARAMETERS
}; };
enum { enum {
@ -81,14 +81,32 @@ cc_keyboard_panel_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_ARGV: { case PROP_PARAMETERS: {
gchar **args; GVariant *parameters, *v;
const gchar *page, *section;
args = g_value_get_boxed (value); parameters = g_value_get_variant (value);
if (!parameters)
if (args && args[0]) { break;
cc_keyboard_panel_set_page (panel, args[0], args[1]); page = section = NULL;
} switch (g_variant_n_children (parameters))
{
case 2:
g_variant_get_child (parameters, 1, "v", &v);
section = g_variant_get_string (v, NULL);
g_variant_unref (v);
/* fall-through */
case 1:
g_variant_get_child (parameters, 0, "v", &v);
page = g_variant_get_string (v, NULL);
g_variant_unref (v);
cc_keyboard_panel_set_page (panel, page, section);
/* fall-through */
case 0:
break;
default:
g_warning ("Unexpected parameters found, ignore request");
}
break; break;
} }
@ -164,7 +182,7 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
object_class->dispose = cc_keyboard_panel_dispose; object_class->dispose = cc_keyboard_panel_dispose;
object_class->finalize = cc_keyboard_panel_finalize; object_class->finalize = cc_keyboard_panel_finalize;
g_object_class_override_property (object_class, PROP_ARGV, "argv"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
} }
static void static void

View file

@ -102,7 +102,7 @@ enum {
enum { enum {
PROP_0, PROP_0,
PROP_ARGV PROP_PARAMETERS
}; };
static NetObject *find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out); static NetObject *find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out);
@ -163,6 +163,23 @@ verify_argv (CcNetworkPanel *self,
} }
} }
static GPtrArray *
variant_av_to_string_array (GVariant *array)
{
GVariantIter iter;
GVariant *v;
GPtrArray *strv;
gsize count;
count = g_variant_iter_init (&iter, array);
strv = g_ptr_array_sized_new (count + 1);
while (g_variant_iter_next (&iter, "v", &v)) {
g_ptr_array_add (strv, (gpointer *)g_variant_get_string (v, NULL));
g_variant_unref (v);
}
g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
return strv;
}
static void static void
cc_network_panel_set_property (GObject *object, cc_network_panel_set_property (GObject *object,
guint property_id, guint property_id,
@ -173,14 +190,18 @@ cc_network_panel_set_property (GObject *object,
CcNetworkPanelPrivate *priv = self->priv; CcNetworkPanelPrivate *priv = self->priv;
switch (property_id) { switch (property_id) {
case PROP_ARGV: { case PROP_PARAMETERS: {
gchar **args; GVariant *parameters;
reset_command_line_args (self); reset_command_line_args (self);
args = g_value_get_boxed (value); parameters = g_value_get_variant (value);
if (parameters) {
GPtrArray *array;
const gchar **args;
array = variant_av_to_string_array (parameters);
args = array->pdata;
if (args) {
g_debug ("Invoked with operation %s", args[0]); g_debug ("Invoked with operation %s", args[0]);
if (args[0]) if (args[0])
@ -192,9 +213,10 @@ cc_network_panel_set_property (GObject *object,
if (verify_argv (self, (const char **) args) == FALSE) { if (verify_argv (self, (const char **) args) == FALSE) {
reset_command_line_args (self); reset_command_line_args (self);
g_ptr_array_unref (array);
return; return;
} }
g_ptr_array_unref (array);
g_debug ("Calling handle_argv() after setting property"); g_debug ("Calling handle_argv() after setting property");
handle_argv (self); handle_argv (self);
} }
@ -377,7 +399,7 @@ cc_network_panel_class_init (CcNetworkPanelClass *klass)
object_class->finalize = cc_network_panel_finalize; object_class->finalize = cc_network_panel_finalize;
object_class->constructed = cc_network_panel_constructed; object_class->constructed = cc_network_panel_constructed;
g_object_class_override_property (object_class, PROP_ARGV, "argv"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
} }
static NetObject * static NetObject *

View file

@ -91,7 +91,7 @@ CC_PANEL_REGISTER (CcGoaPanel, cc_goa_panel);
enum { enum {
PROP_0, PROP_0,
PROP_ARGV PROP_PARAMETERS
}; };
static void static void
@ -102,14 +102,29 @@ cc_goa_panel_set_property (GObject *object,
{ {
switch (property_id) switch (property_id)
{ {
case PROP_ARGV: case PROP_PARAMETERS:
{ {
gchar **args; GVariant *parameters, *v;
const gchar *first_arg = NULL;
args = g_value_get_boxed (value); parameters = g_value_get_variant (value);
if (parameters == NULL)
return;
if (g_variant_n_children (parameters) > 0)
{
g_variant_get_child (parameters, 0, "v", &v);
if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
first_arg = g_variant_get_string (v, NULL);
else
g_warning ("Wrong type for the second argument GVariant, expected 's' but got '%s'",
(gchar *)g_variant_get_type (v));
g_variant_unref (v);
}
if (first_arg != NULL)
select_account_by_id (CC_GOA_PANEL (object), first_arg);
if (args != NULL && *args != '\0')
select_account_by_id (CC_GOA_PANEL (object), args[0]);
return; return;
} }
} }
@ -280,7 +295,7 @@ cc_goa_panel_class_init (CcGoaPanelClass *klass)
object_class->set_property = cc_goa_panel_set_property; object_class->set_property = cc_goa_panel_set_property;
object_class->finalize = cc_goa_panel_finalize; object_class->finalize = cc_goa_panel_finalize;
g_object_class_override_property (object_class, PROP_ARGV, "argv"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
} }
/* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */

View file

@ -38,7 +38,7 @@ CC_PANEL_REGISTER (CcSoundPanel, cc_sound_panel)
enum { enum {
PROP_0, PROP_0,
PROP_ARGV PROP_PARAMETERS
}; };
static void cc_sound_panel_finalize (GObject *object); static void cc_sound_panel_finalize (GObject *object);
@ -52,13 +52,15 @@ cc_sound_panel_set_property (GObject *object,
CcSoundPanel *self = CC_SOUND_PANEL (object); CcSoundPanel *self = CC_SOUND_PANEL (object);
switch (property_id) { switch (property_id) {
case PROP_ARGV: { case PROP_PARAMETERS: {
gchar **args; GVariant *parameters;
args = g_value_get_boxed (value); parameters = g_value_get_variant (value);
if (parameters && g_variant_n_children (parameters) > 0) {
if (args && args[0]) { GVariant *v;
gvc_mixer_dialog_set_page (self->dialog, args[0]); g_variant_get_child (parameters, 0, "v", &v);
gvc_mixer_dialog_set_page (self->dialog, g_variant_get_string (v, NULL));
g_variant_unref (v);
} }
break; break;
} }
@ -84,7 +86,7 @@ cc_sound_panel_class_init (CcSoundPanelClass *klass)
object_class->finalize = cc_sound_panel_finalize; object_class->finalize = cc_sound_panel_finalize;
object_class->set_property = cc_sound_panel_set_property; object_class->set_property = cc_sound_panel_set_property;
g_object_class_override_property (object_class, PROP_ARGV, "argv"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
} }
static void static void

View file

@ -180,6 +180,9 @@ cc_application_command_line (GApplication *application,
{ {
const char *start_id; const char *start_id;
GError *err = NULL; GError *err = NULL;
GVariant *parameters;
GVariantBuilder *builder;
int i;
start_id = start_panels[0]; start_id = start_panels[0];
@ -188,7 +191,11 @@ cc_application_command_line (GApplication *application,
else else
g_debug ("No extra argument"); g_debug ("No extra argument");
if (!cc_shell_set_active_panel_from_id (CC_SHELL (self->priv->window), start_id, (const gchar**)start_panels+1, &err)) builder = g_variant_builder_new (G_VARIANT_TYPE ("av"));
for (i = 1; start_panels[i] != NULL; i++)
g_variant_builder_add (builder, "v", g_variant_new_string (start_panels[i]));
parameters = g_variant_builder_end (builder);
if (!cc_shell_set_active_panel_from_id (CC_SHELL (self->priv->window), start_id, parameters, &err))
{ {
g_warning ("Could not load setting panel \"%s\": %s", start_id, g_warning ("Could not load setting panel \"%s\": %s", start_id,
(err) ? err->message : "Unknown error"); (err) ? err->message : "Unknown error");

View file

@ -200,7 +200,7 @@ ensure_panel_types (void)
CcPanel * CcPanel *
cc_panel_loader_load_by_name (CcShell *shell, cc_panel_loader_load_by_name (CcShell *shell,
const char *name, const char *name,
const char **argv) GVariant *parameters)
{ {
GType (*get_type) (void); GType (*get_type) (void);
@ -211,7 +211,7 @@ cc_panel_loader_load_by_name (CcShell *shell,
return g_object_new (get_type (), return g_object_new (get_type (),
"shell", shell, "shell", shell,
"argv", argv, "parameters", parameters,
NULL); NULL);
} }

View file

@ -32,7 +32,7 @@ void cc_panel_loader_fill_model (CcShellModel *model);
GList *cc_panel_loader_get_panels (void); GList *cc_panel_loader_get_panels (void);
CcPanel *cc_panel_loader_load_by_name (CcShell *shell, CcPanel *cc_panel_loader_load_by_name (CcShell *shell,
const char *name, const char *name,
const char **argv); GVariant *parameters);
G_END_DECLS G_END_DECLS

View file

@ -58,7 +58,7 @@ enum
{ {
PROP_0, PROP_0,
PROP_SHELL, PROP_SHELL,
PROP_ARGV PROP_PARAMETERS
}; };
G_DEFINE_ABSTRACT_TYPE (CcPanel, cc_panel, GTK_TYPE_BIN) G_DEFINE_ABSTRACT_TYPE (CcPanel, cc_panel, GTK_TYPE_BIN)
@ -80,11 +80,12 @@ cc_panel_set_property (GObject *object,
panel->priv->shell = g_value_get_object (value); panel->priv->shell = g_value_get_object (value);
break; break;
case PROP_ARGV: case PROP_PARAMETERS:
{ {
gchar **argv = g_value_get_boxed (value); GVariant *parameters = g_value_get_variant (value);
if (argv && argv[0])
g_warning ("Ignoring additional argument %s", argv[0]); if (parameters)
g_warning ("Ignoring additional parameters");
break; break;
} }
default: default:
@ -208,12 +209,13 @@ cc_panel_class_init (CcPanelClass *klass)
| G_PARAM_CONSTRUCT_ONLY); | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_SHELL, pspec); g_object_class_install_property (object_class, PROP_SHELL, pspec);
pspec = g_param_spec_boxed ("argv", pspec = g_param_spec_variant ("parameters",
"Argument vector", "Structured parameters",
"Additional arguments passed on the command line", "Additional parameters passed externally (ie. command line, dbus activation)",
G_TYPE_STRV, G_VARIANT_TYPE ("av"),
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); NULL,
g_object_class_install_property (object_class, PROP_ARGV, pspec); G_PARAM_WRITABLE);
g_object_class_install_property (object_class, PROP_PARAMETERS, pspec);
} }
static void static void

View file

@ -89,7 +89,8 @@ cc_shell_set_active_panel (CcShell *shell,
/** /**
* cc_shell_set_active_panel_from_id: * cc_shell_set_active_panel_from_id:
* @shell: A #CcShell * @shell: A #CcShell
* @id: the ID of the panel to set as active * @id: The ID of the panel to set as active
* @parameters: A #GVariant with additional parameters
* @error: A #GError * @error: A #GError
* *
* Find a panel corresponding to the specified id and set it as active. * Find a panel corresponding to the specified id and set it as active.
@ -99,7 +100,7 @@ cc_shell_set_active_panel (CcShell *shell,
gboolean gboolean
cc_shell_set_active_panel_from_id (CcShell *shell, cc_shell_set_active_panel_from_id (CcShell *shell,
const gchar *id, const gchar *id,
const gchar **argv, GVariant *parameters,
GError **error) GError **error)
{ {
CcShellInterface *iface; CcShellInterface *iface;
@ -117,7 +118,7 @@ cc_shell_set_active_panel_from_id (CcShell *shell,
} }
else else
{ {
return iface->set_active_panel_from_id (shell, id, argv, error); return iface->set_active_panel_from_id (shell, id, parameters, error);
} }
} }

View file

@ -52,7 +52,7 @@ struct _CcShellInterface
/* methods */ /* methods */
gboolean (*set_active_panel_from_id) (CcShell *shell, gboolean (*set_active_panel_from_id) (CcShell *shell,
const gchar *id, const gchar *id,
const gchar **argv, GVariant *parameters,
GError **error); GError **error);
GtkWidget * (*get_toplevel) (CcShell *shell); GtkWidget * (*get_toplevel) (CcShell *shell);
void (*embed_widget_in_header) (CcShell *shell, void (*embed_widget_in_header) (CcShell *shell,
@ -66,7 +66,7 @@ void cc_shell_set_active_panel (CcShell *shell,
CcPanel *panel); CcPanel *panel);
gboolean cc_shell_set_active_panel_from_id (CcShell *shell, gboolean cc_shell_set_active_panel_from_id (CcShell *shell,
const gchar *id, const gchar *id,
const gchar **argv, GVariant *parameters,
GError **error); GError **error);
GtkWidget * cc_shell_get_toplevel (CcShell *shell); GtkWidget * cc_shell_get_toplevel (CcShell *shell);

View file

@ -108,7 +108,7 @@ enum
static gboolean cc_window_set_active_panel_from_id (CcShell *shell, static gboolean cc_window_set_active_panel_from_id (CcShell *shell,
const gchar *start_id, const gchar *start_id,
const gchar **argv, GVariant *parameters,
GError **err); GError **err);
static const gchar * static const gchar *
@ -136,7 +136,7 @@ get_icon_name_from_g_icon (GIcon *gicon)
static gboolean static gboolean
activate_panel (CcWindow *self, activate_panel (CcWindow *self,
const gchar *id, const gchar *id,
const gchar **argv, GVariant *parameters,
const gchar *name, const gchar *name,
GIcon *gicon) GIcon *gicon)
{ {
@ -147,7 +147,7 @@ activate_panel (CcWindow *self,
if (!id) if (!id)
return FALSE; return FALSE;
priv->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, argv)); priv->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, parameters));
cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (priv->current_panel)); cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (priv->current_panel));
gtk_widget_show (priv->current_panel); gtk_widget_show (priv->current_panel);
@ -933,7 +933,7 @@ _shell_embed_widget_in_header (CcShell *shell,
static gboolean static gboolean
cc_window_set_active_panel_from_id (CcShell *shell, cc_window_set_active_panel_from_id (CcShell *shell,
const gchar *start_id, const gchar *start_id,
const gchar **argv, GVariant *parameters,
GError **err) GError **err)
{ {
GtkTreeIter iter; GtkTreeIter iter;
@ -943,10 +943,10 @@ cc_window_set_active_panel_from_id (CcShell *shell,
CcWindowPrivate *priv = CC_WINDOW (shell)->priv; CcWindowPrivate *priv = CC_WINDOW (shell)->priv;
GtkWidget *old_panel; GtkWidget *old_panel;
/* When loading the same panel again, just set the argv */ /* When loading the same panel again, just set its parameters */
if (g_strcmp0 (priv->current_panel_id, start_id) == 0) if (g_strcmp0 (priv->current_panel_id, start_id) == 0)
{ {
g_object_set (G_OBJECT (priv->current_panel), "argv", argv, NULL); g_object_set (G_OBJECT (priv->current_panel), "parameters", parameters, NULL);
return TRUE; return TRUE;
} }
@ -994,7 +994,7 @@ cc_window_set_active_panel_from_id (CcShell *shell,
{ {
g_warning ("Could not find settings panel \"%s\"", start_id); g_warning ("Could not find settings panel \"%s\"", start_id);
} }
else if (activate_panel (CC_WINDOW (shell), start_id, argv, else if (activate_panel (CC_WINDOW (shell), start_id, parameters,
name, gicon) == FALSE) name, gicon) == FALSE)
{ {
/* Failed to activate the panel for some reason, /* Failed to activate the panel for some reason,
@ -1020,11 +1020,11 @@ cc_window_set_active_panel_from_id (CcShell *shell,
static gboolean static gboolean
_shell_set_active_panel_from_id (CcShell *shell, _shell_set_active_panel_from_id (CcShell *shell,
const gchar *start_id, const gchar *start_id,
const gchar **argv, GVariant *parameters,
GError **err) GError **err)
{ {
add_current_panel_to_history (shell, start_id); add_current_panel_to_history (shell, start_id);
return cc_window_set_active_panel_from_id (shell, start_id, argv, err); return cc_window_set_active_panel_from_id (shell, start_id, parameters, err);
} }
static GtkWidget * static GtkWidget *