[network-manager-applet] editor: enhance launch options with create and edit capabilities (bgo #644498)



commit 98899ba4470c90e8bf3c2c874d2c25bfac3d6878
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Mar 14 23:58:11 2011 -0500

    editor: enhance launch options with create and edit capabilities (bgo #644498)
    
    Allow the editor to be launched with --create and --edit options
    to suppress showing the main window while creating or editing
    different types of connections.
    
    (significantly reworked and cleaned up by dcbw)

 src/connection-editor/main.c                       |  252 +++++++++++++------
 .../nm-connection-editor-service.xml               |    2 +-
 src/connection-editor/nm-connection-list.c         |  258 +++++++++++++++-----
 src/connection-editor/nm-connection-list.h         |   11 +-
 4 files changed, 378 insertions(+), 145 deletions(-)
---
diff --git a/src/connection-editor/main.c b/src/connection-editor/main.c
index 82226e0..50d5d3f 100644
--- a/src/connection-editor/main.c
+++ b/src/connection-editor/main.c
@@ -17,7 +17,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2004-2005 Red Hat, Inc.
+ * Copyright (C) 2004 - 2011 Red Hat, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -40,14 +40,21 @@
 #include <nm-setting-gsm.h>
 #include <nm-setting-cdma.h>
 #include "nm-connection-list.h"
+#include "nm-connection-editor.h"
+#include "page-wired.h"
 
 static GMainLoop *loop = NULL;
 
-#define ARG_TYPE "type"
+#define ARG_TYPE      "type"
+#define ARG_CREATE    "create"
+#define ARG_SHOW      "show"
+#define ARG_UUID      "uuid"
 
-#define DBUS_TYPE_G_MAP_OF_VARIANT          (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+#define DBUS_TYPE_G_MAP_OF_VARIANT    (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
 
-#define NM_CE_DBUS_SERVICE_NAME "org.freedesktop.NetworkManager.Gnome.ConnectionEditor"
+#define NM_CE_DBUS_SERVICE_NAME       "org.gnome.nm_connection_editor"
+
+/*************************************************/
 
 #define NM_TYPE_CE_SERVICE            (nm_ce_service_get_type ())
 #define NM_CE_SERVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CE_SERVICE, NMCEService))
@@ -96,21 +103,20 @@ nm_ce_service_new (DBusGConnection *bus, DBusGProxy *proxy, NMConnectionList *li
 
 	/* Register our single-instance service.  Don't care if it fails. */
 	if (!dbus_g_proxy_call (proxy, "RequestName", &err,
-					    G_TYPE_STRING, NM_CE_DBUS_SERVICE_NAME,
-					    G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
-					    G_TYPE_INVALID,
-					    G_TYPE_UINT, &result,
-					    G_TYPE_INVALID)) {
+	                        G_TYPE_STRING, NM_CE_DBUS_SERVICE_NAME,
+	                        G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_UINT, &result,
+	                        G_TYPE_INVALID)) {
 		g_warning ("Could not acquire the connection editor service.\n"
-		            "  Message: '%s'", err->message);
+		           "  Message: '%s'", err->message);
 		g_error_free (err);
-	} else {
-		if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
-			g_warning ("Could not acquire the connection editor service as it is already taken.");
-		else {
-			/* success */
-			dbus_g_connection_register_g_object (bus, "/", object);
-		}
+		return (NMCEService *) object;
+	}
+
+	if (result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+		/* success; grab the bus name */
+		dbus_g_connection_register_g_object (bus, "/", object);
 	}
 
 	return (NMCEService *) object;
@@ -122,66 +128,110 @@ nm_ce_service_init (NMCEService *self)
 }
 
 static void
-nm_ce_service_class_init (NMCEServiceClass *config_class)
+nm_ce_service_class_init (NMCEServiceClass *service_class)
 {
-	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class),
-									 &dbus_glib_nm_connection_editor_service_object_info);
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (service_class),
+	                                 &dbus_glib_nm_connection_editor_service_object_info);
+}
+
+/*************************************************/
+
+static gboolean
+handle_arguments (NMConnectionList *list,
+                  const char *type,
+                  gboolean create,
+                  gboolean show,
+                  const char *edit_uuid,
+                  gboolean quit_after)
+{
+	gboolean show_list = TRUE;
+	GType ctype;
+
+	/* Grab type to create or show */
+	ctype = nm_connection_lookup_setting_type (type ? type : NM_SETTING_WIRED_SETTING_NAME);
+	if (ctype == 0) {
+		g_warning ("Unknown connection type '%s'", type);
+		return TRUE;
+	}
+
+	if (show) {
+		/* Just show the given connection type page */
+		nm_connection_list_set_type (list, ctype);
+	} else if (create) {
+		if (!type) {
+			g_warning ("'create' requested but no connection type given.");
+			return TRUE;
+		}
+		nm_connection_list_create (list, ctype);
+
+		show_list = FALSE;
+	} else if (edit_uuid) {
+		/* Show the edit dialog for the given UUID */
+		nm_connection_list_edit (list, edit_uuid);
+		show_list = FALSE;
+	}
+
+	/* If only editing a single connection, exit when done with that connection */
+	if (show_list == FALSE && quit_after == TRUE)
+		g_signal_connect_swapped (list, "editing-done", G_CALLBACK (g_main_loop_quit), loop);
+
+	return show_list;
 }
 
 static gboolean
 impl_start (NMCEService *self, GHashTable *table, GError **error)
 {
 	GValue *value;
-	GType def_type;
-	const char *str_type;
+	const char *type = NULL;
+	const char *uuid = NULL;
+	gboolean create = FALSE;
+	gboolean show = FALSE;
+	gboolean show_list;
 
 	value = g_hash_table_lookup (table, ARG_TYPE);
 	if (value && G_VALUE_HOLDS_STRING (value)) {
-		str_type = g_value_get_string (value);
-		g_assert (str_type);
-
-		if (!strcmp (str_type, NM_SETTING_CDMA_SETTING_NAME))
-			str_type = NM_SETTING_GSM_SETTING_NAME;
-		def_type = nm_connection_lookup_setting_type (str_type);
-		nm_connection_list_set_type (self->list, def_type);
+		type = g_value_get_string (value);
+		g_assert (type);
 	}
-	nm_connection_list_present (self->list);
 
-	return TRUE;
-}
+	value = g_hash_table_lookup (table, ARG_UUID);
+	if (value && G_VALUE_HOLDS_STRING (value)) {
+		uuid = g_value_get_string (value);
+		g_assert (uuid);
+	}
 
+	value = g_hash_table_lookup (table, ARG_CREATE);
+	if (value && G_VALUE_HOLDS_BOOLEAN (value))
+		create = g_value_get_boolean (value);
 
-static void
-signal_handler (int signo)
-{
-	if (signo == SIGINT || signo == SIGTERM) {
-		g_message ("Caught signal %d, shutting down...", signo);
-		g_main_loop_quit (loop);
-	}
-}
+	value = g_hash_table_lookup (table, ARG_SHOW);
+	if (value && G_VALUE_HOLDS_BOOLEAN (value))
+		show = g_value_get_boolean (value);
 
-static void
-setup_signals (void)
-{
-	struct sigaction action;
-	sigset_t mask;
+	show_list = handle_arguments (self->list, type, create, show, uuid, FALSE);
+	if (show_list)
+		nm_connection_list_present (self->list);
 
-	sigemptyset (&mask);
-	action.sa_handler = signal_handler;
-	action.sa_mask = mask;
-	action.sa_flags = 0;
-	sigaction (SIGTERM,  &action, NULL);
-	sigaction (SIGINT,  &action, NULL);
+	return TRUE;
 }
 
 static gboolean
-try_existing_instance (DBusGConnection *bus, DBusGProxy *proxy, const char *type)
+try_existing_instance (DBusGConnection *bus,
+                       DBusGProxy *proxy,
+                       const char *type,
+                       gboolean create,
+                       gboolean show,
+                       const char *uuid)
 {
 	gboolean has_owner = FALSE;
 	DBusGProxy *instance;
 	GHashTable *args;
 	GValue type_value = { 0, };
+	GValue create_value = { 0, };
+	GValue show_value = { 0, };
+	GValue uuid_value = { 0, };
 	gboolean success = FALSE;
+	GError *error = NULL;
 
 	if (!dbus_g_proxy_call (proxy, "NameHasOwner", NULL,
 	                        G_TYPE_STRING, NM_CE_DBUS_SERVICE_NAME, G_TYPE_INVALID,
@@ -203,19 +253,57 @@ try_existing_instance (DBusGConnection *bus, DBusGProxy *proxy, const char *type
 	if (type) {
 		g_value_init (&type_value, G_TYPE_STRING);
 		g_value_set_static_string (&type_value, type);
-		g_hash_table_insert (args, "type", &type_value);
+		g_hash_table_insert (args, ARG_TYPE, &type_value);
+	}
+	if (create) {
+		g_value_init (&create_value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (&create_value, TRUE);
+		g_hash_table_insert (args, ARG_CREATE, &create_value);
+	}
+	if (show) {
+		g_value_init (&show_value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (&show_value, TRUE);
+		g_hash_table_insert (args, ARG_SHOW, &show_value);
+	}
+	if (uuid) {
+		g_value_init (&uuid_value, G_TYPE_BOOLEAN);
+		g_value_set_static_string (&uuid_value, uuid);
+		g_hash_table_insert (args, ARG_UUID, &uuid_value);
 	}
 
-	if (dbus_g_proxy_call (instance, "Start", NULL,
+	if (dbus_g_proxy_call (instance, "Start", &error,
 	                       DBUS_TYPE_G_MAP_OF_VARIANT, args, G_TYPE_INVALID,
 	                       G_TYPE_INVALID))
 		success = TRUE;
+	else
+		g_warning ("%s: error calling start: %s", __func__, error->message);
 
 	g_hash_table_destroy (args);
 	g_object_unref (instance);
 	return success;
 }
 
+static void
+signal_handler (int signo)
+{
+	if (signo == SIGINT || signo == SIGTERM)
+		g_main_loop_quit (loop);
+}
+
+static void
+setup_signals (void)
+{
+	struct sigaction action;
+	sigset_t mask;
+
+	sigemptyset (&mask);
+	action.sa_handler = signal_handler;
+	action.sa_mask = mask;
+	action.sa_flags = 0;
+	sigaction (SIGTERM,  &action, NULL);
+	sigaction (SIGINT,  &action, NULL);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -224,12 +312,19 @@ main (int argc, char *argv[])
 	NMConnectionList *list;
 	DBusGConnection *bus;
 	char *type = NULL;
-	GType ctype;
+	gboolean create = FALSE;
+	gboolean show = FALSE;
+	gboolean success;
+	char *uuid = NULL;
 	NMCEService *service = NULL;
 	DBusGProxy *proxy = NULL;
+	gboolean show_list;
 
 	GOptionEntry entries[] = {
-		{ ARG_TYPE, 0, 0, G_OPTION_ARG_STRING, &type, "Type of connection to show at launch", NM_SETTING_WIRED_SETTING_NAME },
+		{ ARG_TYPE,   0, 0, G_OPTION_ARG_STRING, &type,   "Type of connection to show or create", NM_SETTING_WIRED_SETTING_NAME },
+		{ ARG_CREATE, 0, 0, G_OPTION_ARG_NONE,   &create, "Create a new connection", NULL },
+		{ ARG_SHOW,   0, 0, G_OPTION_ARG_NONE,   &show,   "Show a given connection type page", NULL },
+		{ "edit",     0, 0, G_OPTION_ARG_STRING, &uuid,   "Edit an existing connection with a given UUID", "UUID" },
 		{ NULL }
 	};
 
@@ -238,20 +333,21 @@ main (int argc, char *argv[])
 	gtk_init (&argc, &argv);
 	textdomain (GETTEXT_PACKAGE);
 
-	/* parse arguments: an idea is to use gconf://$setting_name / system://$setting_name to
-	   allow this program to work with both GConf and system-wide settings */
-
 	opt_ctx = g_option_context_new (NULL);
 	g_option_context_set_summary (opt_ctx, "Allows users to view and edit network connection settings");
 	g_option_context_add_main_entries (opt_ctx, entries, NULL);
+	success = g_option_context_parse (opt_ctx, &argc, &argv, &error);
+	g_option_context_free (opt_ctx);
 
-	if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) {
+	if (!success) {
 		g_warning ("%s\n", error->message);
 		g_error_free (error);
 		return 1;
 	}
 
-	g_option_context_free (opt_ctx);
+	/* Just one page for both CDMA & GSM, handle that here */
+	if (type && g_strcmp0 (type, NM_SETTING_CDMA_SETTING_NAME) == 0)
+		type = (char *) NM_SETTING_GSM_SETTING_NAME;
 
 	/* Inits the dbus-glib type system too */
 	bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
@@ -260,42 +356,44 @@ main (int argc, char *argv[])
 		                                   "org.freedesktop.DBus",
 		                                   "/org/freedesktop/DBus",
 		                                   "org.freedesktop.DBus");
-		/* Check for an existing instance on the bus */
-		if (proxy) {
-			if (try_existing_instance (bus, proxy, type))
-				goto exit;
-		}
+		g_assert (proxy);
+
+		/* Check for an existing instance on the bus, and if there
+		 * is one, send the arguments to it and exit instead of opening
+		 * a second instance of the connection editor.
+		 */
+		if (try_existing_instance (bus, proxy, type, create, show, uuid))
+			return 0;
 	}
 
 	loop = g_main_loop_new (NULL, FALSE);
 
-	if (!type)
-		type = (char *) NM_SETTING_WIRED_SETTING_NAME;
-	if (!strcmp (type, NM_SETTING_CDMA_SETTING_NAME))
-		type = (char *) NM_SETTING_GSM_SETTING_NAME;
-
-	ctype = nm_connection_lookup_setting_type (type);
-	list = nm_connection_list_new (ctype);
+	list = nm_connection_list_new ();
 	if (!list) {
 		g_warning ("Failed to initialize the UI, exiting...");
 		return 1;
 	}
+	g_signal_connect_swapped (list, "done", G_CALLBACK (g_main_loop_quit), loop);
 
 	/* Create our single-instance-app service if we can */
 	if (proxy)
 		service = nm_ce_service_new (bus, proxy, list);
 
-	g_signal_connect_swapped (G_OBJECT (list), "done", G_CALLBACK (g_main_loop_quit), loop);
-	nm_connection_list_run (list);
+	/* Show the dialog */
+	g_signal_connect_swapped (list, "done", G_CALLBACK (g_main_loop_quit), loop);
+
+	/* Figure out what page or editor window we'll show initially */
+	show_list = handle_arguments (list, type, create, show, uuid, (create || show || uuid));
+	if (show_list)
+		nm_connection_list_present (list);
 
 	setup_signals ();
 	g_main_loop_run (loop);
 
+	/* Cleanup */
 	g_object_unref (list);
 	if (service)
 		g_object_unref (service);
-
-exit:
 	if (proxy)
 		g_object_unref (proxy);
 	if (bus)
diff --git a/src/connection-editor/nm-connection-editor-service.xml b/src/connection-editor/nm-connection-editor-service.xml
index 69bd0cd..8370449 100644
--- a/src/connection-editor/nm-connection-editor-service.xml
+++ b/src/connection-editor/nm-connection-editor-service.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 
 <node name="/">
-  <interface name="org.freedesktop.NetworkManager.Gnome.ConnectionEditor">
+  <interface name="org.gnome.nm_connection_editor">
     <method name="Start">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_start"/>
       <arg name="args" type="a{sv}" direction="in"/>
diff --git a/src/connection-editor/nm-connection-list.c b/src/connection-editor/nm-connection-list.c
index 95b35b4..c55c674 100644
--- a/src/connection-editor/nm-connection-list.c
+++ b/src/connection-editor/nm-connection-list.c
@@ -33,6 +33,7 @@
 #include <nm-setting-connection.h>
 #include <nm-connection.h>
 #include <nm-setting.h>
+#include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-vpn.h>
@@ -60,6 +61,7 @@ G_DEFINE_TYPE (NMConnectionList, nm_connection_list, G_TYPE_OBJECT)
 
 enum {
 	LIST_DONE,
+	EDITING_DONE,
 	LIST_LAST_SIGNAL
 };
 
@@ -528,8 +530,10 @@ add_response_cb (NMConnectionEditor *editor, gint response, GError *error, gpoin
 	}
 
 	g_hash_table_remove (info->list->editors, nm_connection_editor_get_connection (editor));
+	g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 }
 
+
 static void
 really_add_connection (NMConnection *connection,
                        gboolean canceled,
@@ -543,14 +547,17 @@ really_add_connection (NMConnection *connection,
 
 	g_return_if_fail (info != NULL);
 
-	if (canceled)
+	if (canceled) {
+		g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 		return;
+	}
 
 	if (!connection) {
 		error_dialog (info->list_window,
 		              _("Could not create new connection"),
 		              "%s",
 		              (error && error->message) ? error->message : message);
+		g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 		return;
 	}
 
@@ -563,6 +570,7 @@ really_add_connection (NMConnection *connection,
 		              "%s",
 		              (editor_error && editor_error->message) ? editor_error->message : message);
 		g_clear_error (&editor_error);
+		g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 		return;
 	}
 
@@ -594,10 +602,10 @@ add_clicked (GtkButton *button, gpointer user_data)
 		return;
 	}
 
-	(*(info->new_func)) (GTK_WINDOW (list->dialog),
-	                     really_add_connection,
-	                     page_get_connections,
-	                     info);
+	info->new_func (GTK_WINDOW (list->dialog),
+	                really_add_connection,
+	                page_get_connections,
+	                info);
 }
 
 typedef struct {
@@ -666,6 +674,7 @@ edit_done_cb (NMConnectionEditor *editor, gint response, GError *error, gpointer
 			                       info);
 			g_error_free (edit_error);
 		}
+		g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 		break;
 	case GTK_RESPONSE_NONE:
 		/* Show an error dialog if the editor initialization failed */
@@ -676,21 +685,20 @@ edit_done_cb (NMConnectionEditor *editor, gint response, GError *error, gpointer
 	case GTK_RESPONSE_CANCEL:
 	default:
 		g_hash_table_remove (info->list->editors, connection);
+		g_signal_emit (info->list, list_signals[EDITING_DONE], 0, 0);
 		g_free (info);
 		break;
 	}
 }
 
 static void
-do_edit (ActionInfo *info)
+edit_connection (ActionInfo *info, NMConnection *connection)
 {
-	NMRemoteConnection *connection;
 	NMConnectionEditor *editor;
 	EditInfo *edit_info;
 	GError *error = NULL;
 	const char *message = _("The connection editor dialog could not be initialized due to an unknown error.");
 
-	connection = get_active_connection (info->treeview);
 	g_return_if_fail (connection != NULL);
 
 	/* Don't allow two editors for the same connection */
@@ -720,6 +728,12 @@ do_edit (ActionInfo *info)
 }
 
 static void
+do_edit (ActionInfo *info)
+{
+	edit_connection (info, NM_CONNECTION (get_active_connection (info->treeview)));
+}
+
+static void
 delete_result_cb (NMConnectionList *list,
                   GError *error,
                   gpointer user_data)
@@ -972,6 +986,9 @@ dispose (GObject *object)
 	if (list->editors)
 		g_hash_table_destroy (list->editors);
 
+	if (list->actions)
+		g_hash_table_destroy (list->actions);
+
 	if (list->wired_icon)
 		g_object_unref (list->wired_icon);
 	if (list->wireless_icon)
@@ -1013,6 +1030,15 @@ nm_connection_list_class_init (NMConnectionListClass *klass)
 					  NULL, NULL,
 					  g_cclosure_marshal_VOID__INT,
 					  G_TYPE_NONE, 1, G_TYPE_INT);
+
+	list_signals[EDITING_DONE] =
+		g_signal_new ("editing-done",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMConnectionListClass, done),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__INT,
+		              G_TYPE_NONE, 1, G_TYPE_INT);
 }
 
 static GtkTreeView *
@@ -1070,8 +1096,28 @@ action_info_free (ActionInfo *info)
 	g_free (info);
 }
 
+static char *
+get_action_name (GType ctype, const char *action)
+{
+	return g_strdup_printf ("%s_%s", g_type_name (ctype), action);
+}
+
+static ActionInfo *
+find_action_info (NMConnectionList *list, GType ctype, const char *action)
+{
+	ActionInfo *ret;
+	char *name;
+
+	name = get_action_name (ctype, action);
+	ret = g_hash_table_lookup (list->actions, name);
+	g_free (name);
+	return ret;
+}
+
 static ActionInfo *
 action_info_new (NMConnectionList *list,
+                 gchar *action,
+                 GType ctype,
                  GtkTreeView *treeview,
                  GtkWindow *list_window,
                  GtkWidget *button)
@@ -1079,7 +1125,7 @@ action_info_new (NMConnectionList *list,
 	ActionInfo *info;
 
 	info = g_malloc0 (sizeof (ActionInfo));
-	g_object_weak_ref (G_OBJECT (list), (GWeakNotify) action_info_free, info);
+	g_hash_table_insert (list->actions, get_action_name (ctype, action), info);
 
 	info->list = list;
 	info->treeview = treeview;
@@ -1137,7 +1183,7 @@ add_connection_buttons (NMConnectionList *self,
 	name = g_strdup_printf ("%s_add", prefix);
 	button = GTK_WIDGET (gtk_builder_get_object (self->gui, name));
 	g_free (name);
-	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL);
+	info = action_info_new (self, "add", ctype, treeview, GTK_WINDOW (self->dialog), NULL);
 	g_signal_connect (button, "clicked", G_CALLBACK (add_clicked), info);
 	if (ctype == NM_TYPE_SETTING_VPN) {
 		GHashTable *plugins;
@@ -1158,7 +1204,7 @@ add_connection_buttons (NMConnectionList *self,
 	g_free (name);
 
 	/* Edit */
-	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL);
+	info = action_info_new (self, "edit", ctype, treeview, GTK_WINDOW (self->dialog), NULL);
 	button = ce_polkit_button_new (_("_Edit"),
 	                               _("Edit the selected connection"),
 	                               _("_Edit..."),
@@ -1176,7 +1222,7 @@ add_connection_buttons (NMConnectionList *self,
 	pk_button_selection_changed_cb (selection, info);
 
 	/* Delete */
-	info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), NULL);
+	info = action_info_new (self, "delete", ctype, treeview, GTK_WINDOW (self->dialog), NULL);
 	button = ce_polkit_button_new (_("_Delete"),
 	                               _("Delete the selected connection"),
 	                               _("_Delete..."),
@@ -1200,7 +1246,7 @@ add_connection_buttons (NMConnectionList *self,
 		gboolean import_supported = FALSE;
 		GHashTable *plugins;
 
-		info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), button);
+		info = action_info_new (self, "import", ctype, treeview, GTK_WINDOW (self->dialog), button);
 		g_signal_connect (button, "clicked", G_CALLBACK (import_vpn_cb), info);
 
 		plugins = vpn_get_plugins (NULL);
@@ -1214,7 +1260,7 @@ add_connection_buttons (NMConnectionList *self,
 	button = GTK_WIDGET (gtk_builder_get_object (self->gui, name));
 	g_free (name);
 	if (button) {
-		info = action_info_new (self, treeview, GTK_WINDOW (self->dialog), button);
+		info = action_info_new (self, "export", ctype, treeview, GTK_WINDOW (self->dialog), button);
 		g_signal_connect (button, "clicked", G_CALLBACK (export_vpn_cb), info);
 		g_signal_connect (selection, "changed", G_CALLBACK (vpn_list_selection_changed_cb), info);
 		gtk_widget_set_sensitive (button, FALSE);
@@ -1223,7 +1269,6 @@ add_connection_buttons (NMConnectionList *self,
 
 static void
 add_connection_tab (NMConnectionList *self,
-                    GType def_type,
                     GType ctype,
                     GdkPixbuf *pixbuf,
                     const char *prefix,
@@ -1233,7 +1278,6 @@ add_connection_tab (NMConnectionList *self,
 	char *name;
 	GtkWidget *child, *hbox, *notebook;
 	GtkTreeView *treeview;
-	int pnum;
 
 	name = g_strdup_printf ("%s_child", prefix);
 	child = GTK_WIDGET (gtk_builder_get_object (self->gui, name));
@@ -1257,37 +1301,11 @@ add_connection_tab (NMConnectionList *self,
 	add_connection_buttons (self, prefix, treeview, ctype, new_func);
 	gtk_widget_show_all (GTK_WIDGET (notebook));
 
-	g_object_set_data (G_OBJECT (treeview), TV_TYPE_TAG, GSIZE_TO_POINTER (ctype));
 	self->treeviews = g_slist_prepend (self->treeviews, treeview);
 
-	if (def_type == ctype) {
-		pnum = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), child);
-		gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), pnum);
-	}
-}
-
-static void
-add_connection_tabs (NMConnectionList *self, GType def_type)
-{
-	add_connection_tab (self, def_type, NM_TYPE_SETTING_WIRED,
-	                    self->wired_icon, "wired", _("Wired"),
-	                    wired_connection_new);
-
-	add_connection_tab (self, def_type, NM_TYPE_SETTING_WIRELESS,
-	                    self->wireless_icon, "wireless", _("Wireless"),
-	                    wifi_connection_new);
-
-	add_connection_tab (self, def_type, NM_TYPE_SETTING_GSM,
-	                    self->wwan_icon, "wwan", _("Mobile Broadband"),
-	                    mobile_connection_new);
-
-	add_connection_tab (self, def_type, NM_TYPE_SETTING_VPN,
-	                    self->vpn_icon, "vpn", _("VPN"),
-	                    vpn_connection_new);
-
-	add_connection_tab (self, def_type, NM_TYPE_SETTING_PPPOE,
-	                    self->wired_icon, "dsl", _("DSL"),
-	                    dsl_connection_new);
+	/* Tag the notebook child and the treeview with the type of connection they contain */
+	g_object_set_data (G_OBJECT (child), TV_TYPE_TAG, GSIZE_TO_POINTER (ctype));
+	g_object_set_data (G_OBJECT (treeview), TV_TYPE_TAG, GSIZE_TO_POINTER (ctype));
 }
 
 static void
@@ -1354,7 +1372,7 @@ connection_added (NMRemoteSettings *settings,
 	}
 
 NMConnectionList *
-nm_connection_list_new (GType def_type)
+nm_connection_list_new (void)
 {
 	NMConnectionList *list;
 	DBusGConnection *bus;
@@ -1402,10 +1420,31 @@ nm_connection_list_new (GType def_type)
 	                  G_CALLBACK (connection_added),
 	                  list);
 
-	add_connection_tabs (list, def_type);
-
 	list->editors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+	list->actions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) action_info_free);
+
+	/* Add each connection type tab */
+	add_connection_tab (list, NM_TYPE_SETTING_WIRED,
+	                    list->wired_icon, "wired", _("Wired"),
+	                    wired_connection_new);
+
+	add_connection_tab (list, NM_TYPE_SETTING_WIRELESS,
+	                    list->wireless_icon, "wireless", _("Wireless"),
+	                    wifi_connection_new);
+
+	add_connection_tab (list, NM_TYPE_SETTING_GSM,
+	                    list->wwan_icon, "wwan", _("Mobile Broadband"),
+	                    mobile_connection_new);
+
+	add_connection_tab (list, NM_TYPE_SETTING_VPN,
+	                    list->vpn_icon, "vpn", _("VPN"),
+	                    vpn_connection_new);
+
+	add_connection_tab (list, NM_TYPE_SETTING_PPPOE,
+	                    list->wired_icon, "dsl", _("DSL"),
+	                    dsl_connection_new);
 
+	/* Connect to the main dialog's response handler */
 	list->dialog = GTK_WIDGET (gtk_builder_get_object (list->gui, "NMConnectionList"));
 	if (!list->dialog)
 		goto error;
@@ -1424,14 +1463,6 @@ error:
 }
 
 void
-nm_connection_list_present (NMConnectionList *list)
-{
-	g_return_if_fail (NM_IS_CONNECTION_LIST (list));
-
-	gtk_window_present (GTK_WINDOW (list->dialog));
-}
-
-void
 nm_connection_list_set_type (NMConnectionList *self, GType ctype)
 {
 	GtkNotebook *notebook;
@@ -1454,9 +1485,105 @@ nm_connection_list_set_type (NMConnectionList *self, GType ctype)
 			break;
 		}
 	}
+}
+
+void
+nm_connection_list_create (NMConnectionList *self, GType ctype)
+{
+	ActionInfo *info;
+
+	g_return_if_fail (NM_IS_CONNECTION_LIST (self));
+
+	info = find_action_info (self, ctype, "add");
+	if (info == NULL) {
+		error_dialog (NULL,
+		              _("Error creating connection"),
+		              _("Don't know how to create '%s' connections"), g_type_name (ctype));
+	} else {
+		info->new_func (GTK_WINDOW (info->list->dialog),
+		                really_add_connection,
+		                page_get_connections,
+		                info);
+	}
+}
+
+static NMConnection *
+get_connection (NMRemoteSettings *settings, const gchar *id)
+{
+	const gchar *uuid;
+	NMConnection *connection = NULL;
+	GSList *list, *l;
+
+	list = nm_remote_settings_list_connections (settings);
+	for (l = list; l; l = l->next) {
+		connection = l->data;
+		uuid = nm_connection_get_uuid (connection);
+		if (g_strcmp0 (uuid, id) == 0) {
+			g_slist_free (list);
+			return connection;
+		}
+	}
+
+	g_slist_free (list);
+	return NULL;
+}
+
+typedef struct {
+	NMConnectionList *self;
+	const gchar *uuid;
+	gboolean wait;
+} EditData;
+
+static void
+connections_read (NMRemoteSettings *settings, EditData *data)
+{
+	NMConnection *connection;
+
+	connection = get_connection (data->self->settings, data->uuid);
+	if (connection) {
+		NMSettingConnection *s_con;
+		const char *type;
+		ActionInfo *info;
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+		type = nm_setting_connection_get_connection_type (s_con);
+		info = find_action_info (data->self, nm_connection_lookup_setting_type (type), "edit");
+		if (info != NULL)
+			edit_connection (info, connection);
+		else {
+			error_dialog (NULL,
+			              _("Error editing connection"),
+			              _("Don't know how to edit '%s' connections"), type);
+		}
+
+		g_object_unref (connection);
+	} else if (data->wait) {
+		data->wait = FALSE;
+		g_signal_connect (data->self->settings, "connections-read",
+		                  G_CALLBACK (connections_read), data);
+		return;
+	} else {
+		error_dialog (NULL,
+		              _("Error editing connection"),
+		              _("Did not find a connection with UUID '%s'"), data->uuid);
+	}
+
+	g_free (data);
+}
+
+void
+nm_connection_list_edit (NMConnectionList *self, const gchar *uuid)
+{
+	EditData *data;
 
-	/* Bring the connection list to the front */
-	nm_connection_list_present (self);
+	g_return_if_fail (NM_IS_CONNECTION_LIST (self));
+
+	data =  g_new0 (EditData, 1);
+	data->self = self;
+	data->uuid = uuid;
+	data->wait = TRUE;
+
+	connections_read (self->settings, data);
 }
 
 static void
@@ -1472,15 +1599,18 @@ list_close_cb (GtkDialog *dialog, gpointer user_data)
 }
 
 void
-nm_connection_list_run (NMConnectionList *list)
+nm_connection_list_present (NMConnectionList *list)
 {
 	g_return_if_fail (NM_IS_CONNECTION_LIST (list));
 
-	g_signal_connect (G_OBJECT (list->dialog), "response",
-	                  G_CALLBACK (list_response_cb), list);
-	g_signal_connect (G_OBJECT (list->dialog), "close",
-	                  G_CALLBACK (list_close_cb), list);
+	if (!list->signals_connected) {
+		g_signal_connect (G_OBJECT (list->dialog), "response",
+			              G_CALLBACK (list_response_cb), list);
+		g_signal_connect (G_OBJECT (list->dialog), "close",
+			              G_CALLBACK (list_close_cb), list);
+		list->signals_connected = TRUE;
+	}
 
-	nm_connection_list_present (list);
+	gtk_window_present (GTK_WINDOW (list->dialog));
 }
 
diff --git a/src/connection-editor/nm-connection-list.h b/src/connection-editor/nm-connection-list.h
index 314cc5e..2db6c23 100644
--- a/src/connection-editor/nm-connection-list.h
+++ b/src/connection-editor/nm-connection-list.h
@@ -40,6 +40,8 @@ typedef struct {
 	GHashTable *editors;
 	GSList *treeviews;
 
+	GHashTable *actions;
+
 	NMClient *nm_client;
 	NMRemoteSettings *settings;
 
@@ -52,6 +54,8 @@ typedef struct {
 	GdkPixbuf *vpn_icon;
 	GdkPixbuf *unknown_icon;
 	GtkIconTheme *icon_theme;
+
+	gboolean signals_connected;
 } NMConnectionList;
 
 typedef struct {
@@ -59,15 +63,16 @@ typedef struct {
 
 	/* Signals */
 	void (*done)  (NMConnectionList *list, gint result);
+	void (*editing_done)  (NMConnectionList *list, gint result);
 } NMConnectionListClass;
 
 GType             nm_connection_list_get_type (void);
-NMConnectionList *nm_connection_list_new (GType def_type);
-
-void              nm_connection_list_run (NMConnectionList *list);
+NMConnectionList *nm_connection_list_new (void);
 
 void              nm_connection_list_set_type (NMConnectionList *list, GType ctype);
 
 void              nm_connection_list_present (NMConnectionList *list);
+void              nm_connection_list_create (NMConnectionList *list, GType ctype);
+void              nm_connection_list_edit (NMConnectionList *list, const gchar *uuid);
 
 #endif



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