[network-manager-applet] connection-editor: Add a new New Connection dialog, merge in VPN stuff



commit e9b6758e530b6fb31bf5e191e2f98172232347bd
Author: Dan Winship <danw gnome org>
Date:   Fri Jul 20 09:06:58 2012 -0400

    connection-editor: Add a new New Connection dialog, merge in VPN stuff
    
    Add a new "New Connection" dialog, listing all connection types
    including VPN plugins. Use this (filtered to only show the VPN types)
    for the "New VPN Connection" dialog.
    
    (The dialog will be used for non-VPN stuff later.)

 po/POTFILES.in                                     |    1 +
 src/connection-editor/Makefile.am                  |    8 +-
 .../{ce-vpn-wizard.ui => ce-new-connection.ui}     |   50 ++-
 src/connection-editor/ce-page.h                    |    1 +
 src/connection-editor/main.c                       |   21 +-
 src/connection-editor/new-connection.c             |  392 ++++++++++++++++++++
 src/connection-editor/new-connection.h             |   60 +++
 src/connection-editor/nm-connection-list.c         |    4 +-
 src/connection-editor/nm-connection-list.h         |    2 +-
 src/connection-editor/page-dsl.c                   |    1 +
 src/connection-editor/page-dsl.h                   |    1 +
 src/connection-editor/page-mobile.c                |    1 +
 src/connection-editor/page-mobile.h                |    1 +
 src/connection-editor/page-vpn.c                   |   56 ++-
 src/connection-editor/page-vpn.h                   |    7 +
 src/connection-editor/page-wired.c                 |    1 +
 src/connection-editor/page-wired.h                 |    1 +
 src/connection-editor/page-wireless.c              |    1 +
 src/connection-editor/page-wireless.h              |    1 +
 src/connection-editor/vpn-helpers.c                |  178 ---------
 src/connection-editor/vpn-helpers.h                |    2 -
 21 files changed, 570 insertions(+), 220 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f255ea7..47746e6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,6 +31,7 @@ src/connection-editor/ce-page.c
 [type: gettext/glade]src/connection-editor/ce-vpn-wizard.ui
 src/connection-editor/ip4-routes-dialog.c
 src/connection-editor/ip6-routes-dialog.c
+src/connection-editor/new-connection.c
 src/connection-editor/page-dsl.c
 src/connection-editor/page-ip4.c
 src/connection-editor/page-ip6.c
diff --git a/src/connection-editor/Makefile.am b/src/connection-editor/Makefile.am
index d26b674..d3fd9b6 100644
--- a/src/connection-editor/Makefile.am
+++ b/src/connection-editor/Makefile.am
@@ -55,7 +55,9 @@ nm_connection_editor_SOURCES = \
 	ppp-auth-methods-dialog.c \
 	ppp-auth-methods-dialog.h \
 	ce-polkit-button.c \
-	ce-polkit-button.h
+	ce-polkit-button.h \
+	new-connection.c \
+	new-connection.h
 
 nm-connection-editor-service-glue.h: $(top_srcdir)/src/connection-editor/nm-connection-editor-service.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_connection_editor_service --mode=glib-server --output=$@ $<
@@ -72,6 +74,7 @@ nm_connection_editor_LDADD = \
 uidir = $(datadir)/nm-applet
 ui_DATA = \
 	nm-connection-editor.ui \
+	ce-new-connection.ui \
 	ce-page-wired.ui \
 	ce-page-wireless.ui \
 	ce-page-wireless-security.ui \
@@ -82,8 +85,7 @@ ui_DATA = \
 	ce-page-dsl.ui \
 	ce-page-mobile.ui \
 	ce-page-ppp.ui \
-	ce-ppp-auth-methods.ui \
-	ce-vpn-wizard.ui
+	ce-ppp-auth-methods.ui
 
 BUILT_SOURCES = nm-connection-editor-service-glue.h
 
diff --git a/src/connection-editor/ce-vpn-wizard.ui b/src/connection-editor/ce-new-connection.ui
similarity index 81%
rename from src/connection-editor/ce-vpn-wizard.ui
rename to src/connection-editor/ce-new-connection.ui
index d1c4fb7..c860fb9 100644
--- a/src/connection-editor/ce-vpn-wizard.ui
+++ b/src/connection-editor/ce-new-connection.ui
@@ -13,7 +13,7 @@
       </row>
     </data>
   </object>
-  <object class="GtkDialog" id="vpn_type_dialog">
+  <object class="GtkDialog" id="new_connection_type_dialog">
     <property name="border_width">5</property>
     <property name="title" translatable="yes"> </property>
     <property name="resizable">False</property>
@@ -47,10 +47,10 @@
                 <property name="visible">True</property>
                 <property name="spacing">12</property>
                 <child>
-                  <object class="GtkLabel" id="label1">
+                  <object class="GtkLabel" id="new_connection_primary_label">
                     <property name="visible">True</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Choose a VPN Connection Type</property>
+                    <property name="label" translatable="yes">Choose a Connection Type</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                       <attribute name="scale" value="1.2"/>
@@ -63,10 +63,12 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkLabel" id="label2">
+                  <object class="GtkLabel" id="new_connection_secondary_label">
                     <property name="visible">True</property>
                     <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Select the type of VPN you wish to use for the new connection.  If the type of VPN connection you wish to create does not appear in the list, you may not have the correct VPN plugin installed.</property>
+                    <property name="label" translatable="yes">Select the type of connection you wish to create.
+
+If you are creating a VPN, and the VPN connection you wish to create does not appear in the list, you may not have the correct VPN plugin installed.</property>
                     <property name="wrap">True</property>
                   </object>
                   <packing>
@@ -76,26 +78,32 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkVBox" id="vpn_vbox">
+                  <object class="GtkVBox" id="new_connection_vbox">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <child>
-                      <object class="GtkComboBox" id="vpn_type_combo">
+                      <object class="GtkComboBox" id="new_connection_type_combo">
                         <property name="visible">True</property>
-                        <property name="model">model1</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="renderer1"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
+                        <property name="model">new_connection_combo_model</property>
+			<child>
+			  <object class="GtkCellRendererPixbuf" id="renderer1"/>
+			  <attributes>
+			    <attribute name="pixbuf">0</attribute>
+			  </attributes>
+			</child>
+			<child>
+			  <object class="GtkCellRendererText" id="renderer2"/>
+			  <attributes>
+			    <attribute name="text">1</attribute>
+			  </attributes>
+			</child>
                       </object>
                       <packing>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="vpn_desc_label">
+                      <object class="GtkLabel" id="new_connection_desc_label">
                         <property name="visible">True</property>
                         <property name="xalign">0</property>
                         <property name="use_markup">True</property>
@@ -172,4 +180,16 @@
       <action-widget response="-5">create_button</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkListStore" id="new_connection_combo_model">
+    <columns>
+      <!-- column-name icon -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name new_func -->
+      <column type="gpointer"/>
+      <!-- column-name vpn_plugin -->
+      <column type="NMVpnPluginUiInterface"/>
+    </columns>
+  </object>
 </interface>
diff --git a/src/connection-editor/ce-page.h b/src/connection-editor/ce-page.h
index c3f2f15..3ab04c4 100644
--- a/src/connection-editor/ce-page.h
+++ b/src/connection-editor/ce-page.h
@@ -42,6 +42,7 @@ typedef void (*PageNewConnectionResultFunc) (NMConnection *connection,
 typedef GSList * (*PageGetConnectionsFunc) (gpointer user_data);
 
 typedef void (*PageNewConnectionFunc) (GtkWindow *parent,
+                                       const char *detail,
                                        NMRemoteSettings *settings,
                                        PageNewConnectionResultFunc result_func,
                                        gpointer user_data);
diff --git a/src/connection-editor/main.c b/src/connection-editor/main.c
index ead01a9..fc32a41 100644
--- a/src/connection-editor/main.c
+++ b/src/connection-editor/main.c
@@ -141,8 +141,9 @@ idle_create_connection (gpointer user_data)
 {
 	NMConnectionList *list = user_data;
 	GType ctype = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (list), "nm-connection-editor-ctype"));
+	char *detail = g_object_get_data (G_OBJECT (list), "nm-connection-editor-detail");
 
-	nm_connection_list_create (list, ctype);
+	nm_connection_list_create (list, ctype, detail);
 	return FALSE;
 }
 
@@ -156,11 +157,23 @@ handle_arguments (NMConnectionList *list,
 {
 	gboolean show_list = TRUE;
 	GType ctype;
+	char *type_tmp = NULL;
+	const char *p, *detail = NULL;
+
+	if (type) {
+		p = strchr (type, ':');
+		if (p) {
+			type = type_tmp = g_strndup (type, p - type);
+			detail = p + 1;
+		}
+	} else
+		type = NM_SETTING_WIRED_SETTING_NAME;
 
 	/* Grab type to create or show */
-	ctype = nm_connection_lookup_setting_type (type ? type : NM_SETTING_WIRED_SETTING_NAME);
+	ctype = nm_connection_lookup_setting_type (type);
 	if (ctype == 0) {
 		g_warning ("Unknown connection type '%s'", type);
+		g_free (type_tmp);
 		return TRUE;
 	}
 
@@ -170,6 +183,7 @@ handle_arguments (NMConnectionList *list,
 	} else if (create) {
 		if (!type) {
 			g_warning ("'create' requested but no connection type given.");
+			g_free (type_tmp);
 			return TRUE;
 		}
 
@@ -179,6 +193,8 @@ handle_arguments (NMConnectionList *list,
 		g_idle_add (idle_create_connection, list);
 		g_object_set_data (G_OBJECT (list), "nm-connection-editor-ctype",
 		                   GUINT_TO_POINTER (ctype));
+		g_object_set_data_full (G_OBJECT (list), "nm-connection-editor-detail",
+		                        g_strdup (detail), g_free);
 
 		show_list = FALSE;
 	} else if (edit_uuid) {
@@ -191,6 +207,7 @@ handle_arguments (NMConnectionList *list,
 	if (show_list == FALSE && quit_after == TRUE)
 		g_signal_connect_swapped (list, "editing-done", G_CALLBACK (g_main_loop_quit), loop);
 
+	g_free (type_tmp);
 	return show_list;
 }
 
diff --git a/src/connection-editor/new-connection.c b/src/connection-editor/new-connection.c
new file mode 100644
index 0000000..422eddf
--- /dev/null
+++ b/src/connection-editor/new-connection.c
@@ -0,0 +1,392 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+
+#include "new-connection.h"
+#include "nm-connection-list.h"
+#include "page-wired.h"
+#include "page-wireless.h"
+#include "page-mobile.h"
+#include "page-dsl.h"
+#include "page-vpn.h"
+#include "vpn-helpers.h"
+
+static GSList *vpn_plugins;
+
+#define COL_ICON       0
+#define COL_LABEL      1
+#define COL_NEW_FUNC   2
+#define COL_VPN_PLUGIN 3
+
+#define ICON_LOAD(x, y)	\
+	{ \
+		x = gtk_icon_theme_load_icon (theme, y, 16, 0, &error); \
+		if (x == NULL) { \
+			g_warning ("Icon %s missing: %s", y, error->message); \
+			g_error_free (error); \
+		} \
+	}
+
+static gint
+sort_vpn_plugins (gconstpointer a, gconstpointer b)
+{
+	NMVpnPluginUiInterface *aa = NM_VPN_PLUGIN_UI_INTERFACE (a);
+	NMVpnPluginUiInterface *bb = NM_VPN_PLUGIN_UI_INTERFACE (b);
+	char *aa_desc = NULL, *bb_desc = NULL;
+	int ret;
+
+	g_object_get (aa, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &aa_desc, NULL);
+	g_object_get (bb, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &bb_desc, NULL);
+
+	ret = g_strcmp0 (aa_desc, bb_desc);
+
+	g_free (aa_desc);
+	g_free (bb_desc);
+
+	return ret;
+}
+
+ConnectionTypeData *
+get_connection_type_list (void)
+{
+	GArray *array;
+	ConnectionTypeData data;
+	static ConnectionTypeData *list;
+	static GtkIconTheme *theme;
+	GError *error = NULL;
+	GHashTable *vpn_plugins_hash;
+	gboolean have_vpn_plugins;
+
+	if (list)
+		return list;
+
+	array = g_array_new (TRUE, FALSE, sizeof (ConnectionTypeData));
+	theme = gtk_icon_theme_get_default ();
+
+	data.name = _("Wired");
+	ICON_LOAD (data.icon, "nm-device-wired");
+	data.new_connection_func = wired_connection_new;
+	data.setting_type = NM_TYPE_SETTING_WIRED;
+	g_array_append_val (array, data);
+
+	data.name = _("Wireless");
+	ICON_LOAD (data.icon, "nm-device-wireless");
+	data.new_connection_func = wifi_connection_new;
+	data.setting_type = NM_TYPE_SETTING_WIRELESS;
+	g_array_append_val (array, data);
+
+	data.name = _("Mobile Broadband");
+	ICON_LOAD (data.icon, "nm-device-wwan");
+	data.new_connection_func = mobile_connection_new;
+	data.setting_type = NM_TYPE_SETTING_GSM;
+	g_array_append_val (array, data);
+
+	data.name = _("DSL");
+	ICON_LOAD (data.icon, "nm-device-wired");
+	data.new_connection_func = dsl_connection_new;
+	data.setting_type = NM_TYPE_SETTING_PPPOE;
+	g_array_append_val (array, data);
+
+	/* Add "VPN" only if there are plugins */
+	vpn_plugins_hash = vpn_get_plugins (NULL);
+	have_vpn_plugins  = vpn_plugins_hash && g_hash_table_size (vpn_plugins_hash);
+	if (have_vpn_plugins) {
+		GHashTableIter iter;
+		gpointer name, plugin;
+
+		data.name = _("VPN");
+		ICON_LOAD (data.icon, "nm-vpn-standalone-lock");
+		data.new_connection_func = vpn_connection_new;
+		data.setting_type = NM_TYPE_SETTING_VPN;
+		g_array_append_val (array, data);
+
+		vpn_plugins = NULL;
+		g_hash_table_iter_init (&iter, vpn_plugins_hash);
+		while (g_hash_table_iter_next (&iter, &name, &plugin))
+			vpn_plugins = g_slist_prepend (vpn_plugins, plugin);
+		vpn_plugins = g_slist_sort (vpn_plugins, sort_vpn_plugins);
+	}
+
+	return (ConnectionTypeData *)g_array_free (array, FALSE);
+}
+
+static gboolean
+combo_row_separator_func (GtkTreeModel *model,
+                          GtkTreeIter  *iter,
+                          gpointer      data)
+{
+	char *label;
+
+	gtk_tree_model_get (model, iter,
+	                    COL_LABEL, &label,
+	                    -1);
+	if (label) {
+		g_free (label);
+		return FALSE;
+	} else
+		return TRUE;
+}
+
+static void
+combo_changed_cb (GtkComboBox *combo, gpointer user_data)
+{
+	GtkLabel *label = GTK_LABEL (user_data);
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	NMVpnPluginUiInterface *plugin = NULL;
+	char *description, *markup;
+
+	if (!gtk_combo_box_get_active_iter (combo, &iter))
+		goto error;
+
+	model = gtk_combo_box_get_model (combo);
+	if (!model)
+		goto error;
+
+	gtk_tree_model_get (model, &iter, COL_VPN_PLUGIN, &plugin, -1);
+	if (!plugin)
+		goto error;
+
+	g_object_get (G_OBJECT (plugin), NM_VPN_PLUGIN_UI_INTERFACE_DESC, &description, NULL);
+	g_object_unref (plugin);
+	if (!description)
+		goto error;
+
+	markup = g_markup_printf_escaped ("<i>%s</i>", description);
+	gtk_label_set_markup (label, markup);
+	g_free (markup);
+	g_free (description);
+	return;
+
+error:
+	gtk_label_set_text (label, "");
+}
+
+static void
+set_up_connection_type_combo (GtkComboBox *combo,
+                              GtkLabel *description_label,
+                              NewConnectionTypeFilterFunc type_filter_func,
+                              gpointer user_data)
+{
+	GtkListStore *model = GTK_LIST_STORE (gtk_combo_box_get_model (combo));
+	ConnectionTypeData *list = get_connection_type_list ();
+	GtkTreeIter iter;
+	GSList *p;
+	int i, vpn_index = -1;
+	gboolean import_supported = FALSE;
+	gboolean added_any = FALSE;
+
+	gtk_combo_box_set_row_separator_func (combo, combo_row_separator_func, NULL, NULL);
+	g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (combo_changed_cb), description_label);
+
+	for (i = 0; list[i].name; i++) {
+		if (type_filter_func && !type_filter_func (list[i].setting_type, user_data))
+			continue;
+
+		if (list[i].setting_type == NM_TYPE_SETTING_VPN) {
+			vpn_index = i;
+			continue;
+		}
+
+		gtk_list_store_append (model, &iter);
+		gtk_list_store_set (model, &iter,
+		                    COL_ICON, list[i].icon,
+		                    COL_LABEL, list[i].name,
+		                    COL_NEW_FUNC, list[i].new_connection_func,
+		                    -1);
+		added_any = TRUE;
+	}
+
+	if (!vpn_plugins || vpn_index == -1)
+		return;
+
+	if (added_any) {
+		/* Separator */
+		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+	}
+
+	for (p = vpn_plugins; p; p = p->next) {
+		NMVpnPluginUiInterface *plugin = NM_VPN_PLUGIN_UI_INTERFACE (p->data);
+		char *desc;
+
+		g_object_get (plugin, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &desc, NULL);
+
+		gtk_list_store_append (model, &iter);
+		gtk_list_store_set (model, &iter,
+		                    COL_ICON, list[vpn_index].icon,
+		                    COL_LABEL, desc,
+		                    COL_NEW_FUNC, list[vpn_index].new_connection_func,
+		                    COL_VPN_PLUGIN, plugin,
+		                    -1);
+		g_free (desc);
+
+		if (nm_vpn_plugin_ui_interface_get_capabilities (plugin) & NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT)
+			import_supported = TRUE;
+	}
+
+	if (import_supported) {
+		/* Separator */
+		gtk_list_store_append (model, &iter);
+
+		gtk_list_store_append (model, &iter);
+		gtk_list_store_set (model, &iter,
+		                    COL_ICON, list[vpn_index].icon,
+		                    COL_LABEL, _("Import a saved VPN configuration..."),
+		                    COL_NEW_FUNC, vpn_connection_import,
+		                    -1);
+	}
+}
+
+typedef struct {
+	GtkWindow *parent_window;
+	NMRemoteSettings *settings;
+	PageNewConnectionResultFunc result_func;
+	gpointer user_data;
+} NewConnectionData;
+
+static void
+new_connection_result (NMConnection *connection,
+                       gboolean canceled,
+                       GError *error,
+                       gpointer user_data)
+{
+	NewConnectionData *ncd = user_data;
+	PageNewConnectionResultFunc result_func;
+
+	result_func = ncd->result_func;
+	user_data = ncd->user_data;
+	g_slice_free (NewConnectionData, ncd);
+
+	result_func (connection, canceled, error, user_data);
+}
+
+void
+new_connection_of_type (GtkWindow *parent_window,
+                        const char *detail,
+                        NMRemoteSettings *settings,
+                        PageNewConnectionFunc new_func,
+                        PageNewConnectionResultFunc result_func,
+                        gpointer user_data)
+{
+	NewConnectionData *ncd;
+
+	ncd = g_slice_new (NewConnectionData);
+	ncd->parent_window = parent_window;
+	ncd->settings = settings;
+	ncd->result_func = result_func;
+	ncd->user_data = user_data;
+
+	new_func (parent_window,
+	          detail,
+	          settings,
+	          new_connection_result,
+	          ncd);
+}
+
+void
+new_connection_dialog (GtkWindow *parent_window,
+                       NMRemoteSettings *settings,
+                       NewConnectionTypeFilterFunc type_filter_func,
+                       PageNewConnectionResultFunc result_func,
+                       gpointer user_data)
+{
+	new_connection_dialog_full (parent_window, settings,
+	                            NULL, NULL,
+	                            type_filter_func,
+	                            result_func,
+	                            user_data);
+}
+
+void
+new_connection_dialog_full (GtkWindow *parent_window,
+                            NMRemoteSettings *settings,
+                            const char *primary_label,
+                            const char *secondary_label,
+                            NewConnectionTypeFilterFunc type_filter_func,
+                            PageNewConnectionResultFunc result_func,
+                            gpointer user_data)
+{
+
+	GtkBuilder *gui;
+	GtkDialog *type_dialog;
+	GtkComboBox *combo;
+	GtkLabel *label;
+	GtkTreeIter iter;
+	int response;
+	PageNewConnectionFunc new_func = NULL;
+	NMVpnPluginUiInterface *plugin = NULL;
+	char *vpn_type = NULL;
+	GError *error = NULL;
+
+	/* load GUI */
+	gui = gtk_builder_new ();
+	if (!gtk_builder_add_from_file (gui,
+	                                UIDIR "/ce-new-connection.ui",
+	                                &error)) {
+		g_warning ("Couldn't load builder file: %s", error->message);
+		g_error_free (error);
+		g_object_unref (gui);
+		return;
+	}
+
+	type_dialog = GTK_DIALOG (gtk_builder_get_object (gui, "new_connection_type_dialog"));
+	gtk_window_set_transient_for (GTK_WINDOW (type_dialog), parent_window);
+
+	combo = GTK_COMBO_BOX (gtk_builder_get_object (gui, "new_connection_type_combo"));
+	label = GTK_LABEL (gtk_builder_get_object (gui, "new_connection_desc_label"));
+	set_up_connection_type_combo (combo, label, type_filter_func, user_data);
+	gtk_combo_box_set_active (combo, 0);
+
+	if (primary_label) {
+		label = GTK_LABEL (gtk_builder_get_object (gui, "new_connection_primary_label"));
+		gtk_label_set_text (label, primary_label);
+	}
+	if (secondary_label) {
+		label = GTK_LABEL (gtk_builder_get_object (gui, "new_connection_secondary_label"));
+		gtk_label_set_text (label, secondary_label);
+	}
+
+	response = gtk_dialog_run (type_dialog);
+	if (response == GTK_RESPONSE_OK) {
+		gtk_combo_box_get_active_iter (combo, &iter);
+		gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
+		                    COL_NEW_FUNC, &new_func,
+		                    COL_VPN_PLUGIN, &plugin,
+		                    -1);
+
+		if (plugin) {
+			g_object_get (G_OBJECT (plugin), NM_VPN_PLUGIN_UI_INTERFACE_SERVICE, &vpn_type, NULL);
+			g_object_unref (plugin);
+		}
+	}
+
+	gtk_widget_destroy (GTK_WIDGET (type_dialog));
+	g_object_unref (gui);
+
+	if (new_func)
+		new_connection_of_type (parent_window, vpn_type, settings, new_func, result_func, user_data);
+	else
+		result_func (NULL, TRUE, NULL, user_data);
+
+	g_free (vpn_type);
+}
diff --git a/src/connection-editor/new-connection.h b/src/connection-editor/new-connection.h
new file mode 100644
index 0000000..7361618
--- /dev/null
+++ b/src/connection-editor/new-connection.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#ifndef __CONNECTION_HELPERS_H__
+#define __CONNECTION_HELPERS_H__
+
+#include "ce-page.h"
+#include <nm-remote-settings.h>
+
+typedef struct {
+	const char *name;
+	GdkPixbuf *icon;
+	GType setting_type;
+	PageNewConnectionFunc new_connection_func;
+} ConnectionTypeData;
+
+ConnectionTypeData *get_connection_type_list (void);
+
+typedef gboolean (*NewConnectionTypeFilterFunc) (GType type,
+                                                 gpointer user_data);
+
+void new_connection_dialog      (GtkWindow *parent_window,
+                                 NMRemoteSettings *settings,
+                                 NewConnectionTypeFilterFunc type_filter_func,
+                                 PageNewConnectionResultFunc result_func,
+                                 gpointer user_data);
+void new_connection_dialog_full (GtkWindow *parent_window,
+                                 NMRemoteSettings *settings,
+                                 const char *primary_label,
+                                 const char *secondary_label,
+                                 NewConnectionTypeFilterFunc type_filter_func,
+                                 PageNewConnectionResultFunc result_func,
+                                 gpointer user_data);
+
+void new_connection_of_type (GtkWindow *parent_window,
+                             const char *detail,
+                             NMRemoteSettings *settings,
+                             PageNewConnectionFunc new_func,
+                             PageNewConnectionResultFunc result_func,
+                             gpointer user_data);
+
+#endif  /* __CONNECTION_HELPERS_H__ */
+
diff --git a/src/connection-editor/nm-connection-list.c b/src/connection-editor/nm-connection-list.c
index 4f36e09..daafa71 100644
--- a/src/connection-editor/nm-connection-list.c
+++ b/src/connection-editor/nm-connection-list.c
@@ -600,6 +600,7 @@ add_clicked (GtkButton *button, gpointer user_data)
 	}
 
 	info->new_func (GTK_WINDOW (list->dialog),
+	                NULL,
 	                list->settings,
 	                really_add_connection,
 	                info);
@@ -1355,7 +1356,7 @@ nm_connection_list_set_type (NMConnectionList *self, GType ctype)
 }
 
 void
-nm_connection_list_create (NMConnectionList *self, GType ctype)
+nm_connection_list_create (NMConnectionList *self, GType ctype, const char *detail)
 {
 	ActionInfo *info;
 
@@ -1368,6 +1369,7 @@ nm_connection_list_create (NMConnectionList *self, GType ctype)
 		              _("Don't know how to create '%s' connections"), g_type_name (ctype));
 	} else {
 		info->new_func (GTK_WINDOW (info->list->dialog),
+		                detail,
 		                info->list->settings,
 		                really_add_connection,
 		                info);
diff --git a/src/connection-editor/nm-connection-list.h b/src/connection-editor/nm-connection-list.h
index 2db6c23..30ce368 100644
--- a/src/connection-editor/nm-connection-list.h
+++ b/src/connection-editor/nm-connection-list.h
@@ -72,7 +72,7 @@ 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_create (NMConnectionList *list, GType ctype, const char *detail);
 void              nm_connection_list_edit (NMConnectionList *list, const gchar *uuid);
 
 #endif
diff --git a/src/connection-editor/page-dsl.c b/src/connection-editor/page-dsl.c
index 40b2a72..29819ec 100644
--- a/src/connection-editor/page-dsl.c
+++ b/src/connection-editor/page-dsl.c
@@ -222,6 +222,7 @@ ce_page_dsl_class_init (CEPageDslClass *dsl_class)
 
 void
 dsl_connection_new (GtkWindow *parent,
+                    const char *detail,
                     NMRemoteSettings *settings,
                     PageNewConnectionResultFunc result_func,
                     gpointer user_data)
diff --git a/src/connection-editor/page-dsl.h b/src/connection-editor/page-dsl.h
index 04f2b09..946e4f3 100644
--- a/src/connection-editor/page-dsl.h
+++ b/src/connection-editor/page-dsl.h
@@ -54,6 +54,7 @@ CEPage *ce_page_dsl_new (NMConnection *connection,
                          GError **error);
 
 void dsl_connection_new (GtkWindow *parent,
+                         const char *detail,
                          NMRemoteSettings *settings,
                          PageNewConnectionResultFunc callback,
                          gpointer user_data);
diff --git a/src/connection-editor/page-mobile.c b/src/connection-editor/page-mobile.c
index e59c07d..481e76f 100644
--- a/src/connection-editor/page-mobile.c
+++ b/src/connection-editor/page-mobile.c
@@ -614,6 +614,7 @@ cancel_dialog (GtkDialog *dialog)
 
 void
 mobile_connection_new (GtkWindow *parent,
+                       const char *detail,
                        NMRemoteSettings *settings,
                        PageNewConnectionResultFunc result_func,
                        gpointer user_data)
diff --git a/src/connection-editor/page-mobile.h b/src/connection-editor/page-mobile.h
index b5c27d0..9f08241 100644
--- a/src/connection-editor/page-mobile.h
+++ b/src/connection-editor/page-mobile.h
@@ -54,6 +54,7 @@ CEPage *ce_page_mobile_new (NMConnection *connection,
                             GError **error);
 
 void mobile_connection_new (GtkWindow *parent,
+                            const char *detail,
                             NMRemoteSettings *settings,
                             PageNewConnectionResultFunc result_func,
                             gpointer user_data);
diff --git a/src/connection-editor/page-vpn.c b/src/connection-editor/page-vpn.c
index d5604b4..9cdce22 100644
--- a/src/connection-editor/page-vpn.c
+++ b/src/connection-editor/page-vpn.c
@@ -35,6 +35,7 @@
 #include <nm-vpn-plugin-ui-interface.h>
 
 #include "page-vpn.h"
+#include "new-connection.h"
 #include "nm-connection-editor.h"
 #include "vpn-helpers.h"
 
@@ -254,30 +255,50 @@ import_cb (NMConnection *connection, gpointer user_data)
 }
 
 void
+vpn_connection_import (GtkWindow *parent,
+                       const char *detail,
+                       NMRemoteSettings *settings,
+                       PageNewConnectionResultFunc result_func,
+                       gpointer user_data)
+{
+	NewVpnInfo *info;
+
+	info = g_slice_new (NewVpnInfo);
+	info->result_func = result_func;
+	info->settings = g_object_ref (settings);
+	info->user_data = user_data;
+	vpn_import (import_cb, info);
+}
+
+#define NEW_VPN_CONNECTION_PRIMARY_LABEL _("Choose a VPN Connection Type")
+#define NEW_VPN_CONNECTION_SECONDARY_LABEL _("Select the type of VPN you wish to use for the new connection.  If the type of VPN connection you wish to create does not appear in the list, you may not have the correct VPN plugin installed.")
+
+static gboolean
+vpn_type_filter_func (GType type, gpointer user_data)
+{
+	return type == NM_TYPE_SETTING_VPN;
+}
+
+void
 vpn_connection_new (GtkWindow *parent,
+                    const char *detail,
                     NMRemoteSettings *settings,
                     PageNewConnectionResultFunc result_func,
                     gpointer user_data)
 {
-	char *service = NULL;
 	NMConnection *connection;
 	NMSetting *s_vpn;
 
-	service = vpn_ask_connection_type (parent);
-	if (!service) {
-		(*result_func) (NULL, TRUE, NULL, user_data);
-		return;
-	}
-
-	if (!strcmp (service, "import")) {
-		NewVpnInfo *info;
-
-		g_free (service);
-		info = g_slice_new (NewVpnInfo);
-		info->result_func = result_func;
-		info->settings = g_object_ref (settings);
-		info->user_data = user_data;
-		vpn_import (import_cb, info);
+	if (!detail) {
+		/* This will happen if nm-c-e is launched from the command line
+		 * with "--create --type vpn". Dump the user back into the
+		 * new connection dialog to let them pick a subtype now.
+		 */
+		new_connection_dialog_full (parent, settings,
+		                            NEW_VPN_CONNECTION_PRIMARY_LABEL,
+		                            NEW_VPN_CONNECTION_SECONDARY_LABEL,
+		                            vpn_type_filter_func,
+		                            result_func, user_data);
 		return;
 	}
 
@@ -287,8 +308,7 @@ vpn_connection_new (GtkWindow *parent,
 	                                     settings,
 	                                     user_data);
 	s_vpn = nm_setting_vpn_new ();
-	g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, service, NULL);
-	g_free (service);
+	g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, detail, NULL);
 	nm_connection_add_setting (connection, s_vpn);
 
 	(*result_func) (connection, FALSE, NULL, user_data);
diff --git a/src/connection-editor/page-vpn.h b/src/connection-editor/page-vpn.h
index 66c1c81..a09dec5 100644
--- a/src/connection-editor/page-vpn.h
+++ b/src/connection-editor/page-vpn.h
@@ -56,8 +56,15 @@ CEPage *ce_page_vpn_new (NMConnection *connection,
 gboolean ce_page_vpn_can_export (CEPageVpn *page);
 
 void vpn_connection_new (GtkWindow *parent,
+                         const char *detail,
                          NMRemoteSettings *settings,
                          PageNewConnectionResultFunc result_func,
                          gpointer user_data);
 
+void vpn_connection_import (GtkWindow *parent,
+                            const char *detail,
+                            NMRemoteSettings *settings,
+                            PageNewConnectionResultFunc result_func,
+                            gpointer user_data);
+
 #endif  /* __PAGE_VPN_H__ */
diff --git a/src/connection-editor/page-wired.c b/src/connection-editor/page-wired.c
index e95dfc2..0b7f72c 100644
--- a/src/connection-editor/page-wired.c
+++ b/src/connection-editor/page-wired.c
@@ -440,6 +440,7 @@ ce_page_wired_class_init (CEPageWiredClass *wired_class)
 
 void
 wired_connection_new (GtkWindow *parent,
+                      const char *detail,
                       NMRemoteSettings *settings,
                       PageNewConnectionResultFunc result_func,
                       gpointer user_data)
diff --git a/src/connection-editor/page-wired.h b/src/connection-editor/page-wired.h
index b257d0e..221c3db 100644
--- a/src/connection-editor/page-wired.h
+++ b/src/connection-editor/page-wired.h
@@ -54,6 +54,7 @@ CEPage *ce_page_wired_new (NMConnection *connection,
                            GError **error);
 
 void wired_connection_new (GtkWindow *parent,
+                           const char *detail,
                            NMRemoteSettings *settings,
                            PageNewConnectionResultFunc result_func,
                            gpointer user_data);
diff --git a/src/connection-editor/page-wireless.c b/src/connection-editor/page-wireless.c
index b317ac6..1f03298 100644
--- a/src/connection-editor/page-wireless.c
+++ b/src/connection-editor/page-wireless.c
@@ -656,6 +656,7 @@ ce_page_wireless_class_init (CEPageWirelessClass *wireless_class)
 
 void
 wifi_connection_new (GtkWindow *parent,
+                     const char *detail,
                      NMRemoteSettings *settings,
                      PageNewConnectionResultFunc result_func,
                      gpointer user_data)
diff --git a/src/connection-editor/page-wireless.h b/src/connection-editor/page-wireless.h
index 5ab782e..3d9048e 100644
--- a/src/connection-editor/page-wireless.h
+++ b/src/connection-editor/page-wireless.h
@@ -58,6 +58,7 @@ GByteArray *ce_page_wireless_get_ssid (CEPageWireless *self);
 
 
 void wifi_connection_new (GtkWindow *parent,
+                          const char *detail,
                           NMRemoteSettings *settings,
                           PageNewConnectionResultFunc result_func,
                           gpointer user_data);
diff --git a/src/connection-editor/vpn-helpers.c b/src/connection-editor/vpn-helpers.c
index 82c2e99..ab9fe98 100644
--- a/src/connection-editor/vpn-helpers.c
+++ b/src/connection-editor/vpn-helpers.c
@@ -392,184 +392,6 @@ vpn_export (NMConnection *connection)
 	gtk_window_present (GTK_WINDOW (dialog));
 }
 
-static gint
-sort_plugins (gconstpointer a, gconstpointer b)
-{
-	NMVpnPluginUiInterface *aa = NM_VPN_PLUGIN_UI_INTERFACE (a);
-	NMVpnPluginUiInterface *bb = NM_VPN_PLUGIN_UI_INTERFACE (b);
-	char *aa_desc = NULL, *bb_desc = NULL;
-	gint ret;
-
-	g_object_get (aa, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &aa_desc, NULL);
-	g_object_get (bb, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &bb_desc, NULL);
-
-	if (!aa_desc)
-		ret = -1;
-	else if (!bb_desc)
-		ret = 1;
-	else
-		ret = strcmp (aa_desc, bb_desc);
-
-	g_free (aa_desc);
-	g_free (bb_desc);
-	return ret;
-}
-
-#define COL_PLUGIN_DESC 0
-#define COL_PLUGIN_OBJ  1
-
-static gboolean
-combo_row_separator_func (GtkTreeModel *model,
-                          GtkTreeIter  *iter,
-                          gpointer      data)
-{
-	char *desc;
-
-	gtk_tree_model_get (model, iter,
-	                    COL_PLUGIN_DESC, &desc,
-	                    -1);
-	if (desc) {
-		g_free (desc);
-		return FALSE;
-	} else
-		return TRUE;
-}
-
-static void
-combo_changed_cb (GtkComboBox *combo, gpointer user_data)
-{
-	GtkLabel *label = GTK_LABEL (user_data);
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	NMVpnPluginUiInterface *plugin = NULL;
-	char *desc = NULL;
-	char *tmp;
-
-	if (!gtk_combo_box_get_active_iter (combo, &iter))
-		goto error;
-
-	model = gtk_combo_box_get_model (combo);
-	if (!model)
-		goto error;
-
-	gtk_tree_model_get (model, &iter, COL_PLUGIN_OBJ, &plugin, -1);
-	if (!plugin)
-		goto error;
-
-	g_object_get (G_OBJECT (plugin), NM_VPN_PLUGIN_UI_INTERFACE_DESC, &desc, NULL);
-	g_object_unref (plugin);
-	if (!desc)
-		goto error;
-
-	tmp = g_strdup_printf ("<i>%s</i>", desc);
-	gtk_label_set_markup (label, tmp);
-	g_free (tmp);
-	g_free (desc);
-	return;
-
-error:
-	gtk_label_set_text (label, "");
-}
-
-char *
-vpn_ask_connection_type (GtkWindow *parent)
-{
-	GtkBuilder *builder;
-	GtkWidget *dialog, *combo, *widget;
-	GtkTreeModel *model;
-	GHashTableIter hash_iter;
-	gpointer key, value;
-	GSList *plugin_list = NULL, *iter;
-	gint response;
-	GtkTreeIter tree_iter;
-	char *service_type = NULL;
-	GError *error = NULL;
-	gboolean import_supported = FALSE;
-
-	if (!plugins || !g_hash_table_size (plugins)) {
-		g_warning ("%s: no VPN plugins could be found!", __func__);
-		return NULL;
-	}
-
-	builder = gtk_builder_new();
-
-	if (!gtk_builder_add_from_file (builder, UIDIR "/ce-vpn-wizard.ui", &error)) {
-		g_warning ("Couldn't load builder file: %s", error->message);
-		g_error_free (error);
-		return NULL;
-	}
-
-	dialog = GTK_WIDGET (gtk_builder_get_object (builder, "vpn_type_dialog"));
-	if (!dialog) {
-		g_warning ("%s: couldn't load VPN wizard dialog!", __func__);
-		g_object_unref (builder);
-		return NULL;
-	}
-
-	model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT));
-
-	g_hash_table_iter_init (&hash_iter, plugins);
-	while (g_hash_table_iter_next (&hash_iter, &key, &value))
-		plugin_list = g_slist_prepend (plugin_list, value);
-	plugin_list = g_slist_sort (plugin_list, sort_plugins);
-
-	for (iter = plugin_list; iter; iter = g_slist_next (iter)) {
-		NMVpnPluginUiInterface *plugin = NM_VPN_PLUGIN_UI_INTERFACE (iter->data);
-		char *desc;
-
-		gtk_list_store_append (GTK_LIST_STORE (model), &tree_iter);
-		g_object_get (plugin, NM_VPN_PLUGIN_UI_INTERFACE_NAME, &desc, NULL);
-		gtk_list_store_set (GTK_LIST_STORE (model), &tree_iter,
-		                    COL_PLUGIN_DESC, desc,
-		                    COL_PLUGIN_OBJ, plugin, -1);
-		g_free (desc);
-
-		if (nm_vpn_plugin_ui_interface_get_capabilities (plugin) & NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT)
-			import_supported = TRUE;
-	}
-	g_slist_free (plugin_list);
-
-	if (import_supported) {
-		gtk_list_store_append (GTK_LIST_STORE (model), &tree_iter);
-		gtk_list_store_set (GTK_LIST_STORE (model), &tree_iter,
-		                    COL_PLUGIN_DESC, NULL,
-		                    COL_PLUGIN_OBJ, NULL, -1);
-		gtk_list_store_append (GTK_LIST_STORE (model), &tree_iter);
-		gtk_list_store_set (GTK_LIST_STORE (model), &tree_iter,
-		                    COL_PLUGIN_DESC, _("Import a saved VPN configuration..."),
-		                    COL_PLUGIN_OBJ, NULL, -1);
-	}
-
-	combo = GTK_WIDGET (gtk_builder_get_object (builder, "vpn_type_combo"));
-	widget = GTK_WIDGET (gtk_builder_get_object (builder, "vpn_desc_label"));
-	g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (combo_changed_cb), widget);
-	gtk_combo_box_set_model (GTK_COMBO_BOX (combo), model);
-	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
-	gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), combo_row_separator_func, NULL, NULL);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
-	gtk_widget_show_all (dialog);
-	response = gtk_dialog_run (GTK_DIALOG (dialog));
-	if (response != GTK_RESPONSE_OK)
-		goto out;
-
-	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &tree_iter)) {
-		NMVpnPluginUiInterface *plugin = NULL;
-
-		gtk_tree_model_get (model, &tree_iter, COL_PLUGIN_OBJ, &plugin, -1);
-		if (plugin) {
-			g_object_get (G_OBJECT (plugin), NM_VPN_PLUGIN_UI_INTERFACE_SERVICE, &service_type, NULL);
-			g_object_unref (plugin);
-		} else
-			service_type = g_strdup ("import");
-	}
-
-out:
-	gtk_widget_destroy (dialog);
-	g_object_unref (builder);
-	return service_type;
-}
-
 gboolean
 vpn_supports_ipv6 (NMConnection *connection)
 {
diff --git a/src/connection-editor/vpn-helpers.h b/src/connection-editor/vpn-helpers.h
index c46372d..d14fc8f 100644
--- a/src/connection-editor/vpn-helpers.h
+++ b/src/connection-editor/vpn-helpers.h
@@ -39,8 +39,6 @@ void vpn_import (VpnImportSuccessCallback callback, gpointer user_data);
 
 void vpn_export (NMConnection *connection);
 
-char *vpn_ask_connection_type (GtkWindow *parent);
-
 gboolean vpn_supports_ipv6 (NMConnection *connection);
 
 #endif  /* _VPN_HELPERS_H_ */



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