[gnome-control-center/wip/networking2: 101/101] network: add integrated "Add New Connection"



commit b82986e14b0e3e49041d08ef91bda31f9e79b64c
Author: Dan Winship <danw gnome org>
Date:   Wed Jan 9 17:41:48 2013 -0500

    network: add integrated "Add New Connection"
    
    New VPN connections are created within the control center; other types
    currently hit the nm-connection-editor fallback.

 panels/network/cc-network-panel.c                  |   55 +---
 .../network/connection-editor/connection-editor.ui |  149 +++++++---
 .../connection-editor/net-connection-editor.c      |  339 +++++++++++++++++++-
 panels/network/connection-editor/vpn-helpers.c     |   26 +-
 panels/network/connection-editor/vpn-helpers.h     |    4 +-
 5 files changed, 475 insertions(+), 98 deletions(-)
---
diff --git a/panels/network/cc-network-panel.c b/panels/network/cc-network-panel.c
index 6526404..a7ba9be 100644
--- a/panels/network/cc-network-panel.c
+++ b/panels/network/cc-network-panel.c
@@ -46,6 +46,7 @@
 #include "panel-common.h"
 
 #include "network-dialogs.h"
+#include "connection-editor/net-connection-editor.h"
 
 CC_PANEL_REGISTER (CcNetworkPanel, cc_network_panel)
 
@@ -1151,45 +1152,25 @@ panel_check_network_manager_version (CcNetworkPanel *panel)
 }
 
 static void
+editor_done (NetConnectionEditor *editor,
+             gboolean             success,
+             gpointer             user_data)
+{
+        g_object_unref (editor);
+}
+
+static void
 add_connection_cb (GtkToolButton *button, CcNetworkPanel *panel)
 {
-        GtkWidget *dialog;
-        gint response;
-
-        dialog = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
-                                                     "connection_type_dialog"));
-        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel))));
-
-        response = gtk_dialog_run (GTK_DIALOG (dialog));
-
-        gtk_widget_hide (dialog);
-
-        if (response == GTK_RESPONSE_OK) {
-                GtkComboBox *combo;
-                GtkTreeModel *model;
-                GtkTreeIter iter;
-                gchar *type;
-                gchar *cmdline;
-                GError *error;
-
-                combo = GTK_COMBO_BOX (gtk_builder_get_object (panel->priv->builder,
-                                                               "connection_type_combo"));
-                model = gtk_combo_box_get_model (combo);
-                gtk_combo_box_get_active_iter (combo, &iter);
-                type = NULL;
-                gtk_tree_model_get (model, &iter, 1, &type, -1);
-
-                cmdline = g_strdup_printf ("nm-connection-editor --create --type %s", type);
-                g_debug ("Launching '%s'\n", cmdline);
-
-                error = NULL;
-                if (!g_spawn_command_line_async (cmdline, &error)) {
-                        g_warning ("Failed to launch nm-connection-editor: %s", error->message);
-                        g_error_free (error);
-                }
-                g_free (cmdline);
-                g_free (type);
-        }
+        NetConnectionEditor *editor;
+        GtkWindow *toplevel;
+
+        toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+        editor = net_connection_editor_new (toplevel, NULL, NULL, NULL,
+                                            panel->priv->client,
+                                            panel->priv->remote_settings);
+        g_signal_connect (editor, "done", G_CALLBACK (editor_done), panel);
+        net_connection_editor_run (editor);
 }
 
 static void
diff --git a/panels/network/connection-editor/connection-editor.ui b/panels/network/connection-editor/connection-editor.ui
index 94562f5..78c4ba9 100644
--- a/panels/network/connection-editor/connection-editor.ui
+++ b/panels/network/connection-editor/connection-editor.ui
@@ -1,14 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkListStore" id="details_store">
-    <columns>
-      <!-- column-name name -->
-      <column type="gchararray"/>
-      <!-- column-name page -->
-      <column type="gint"/>
-    </columns>
-  </object>
   <object class="GtkDialog" id="details_dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
@@ -63,63 +55,130 @@
           </packing>
         </child>
         <child>
-          <object class="GtkBox" id="box6">
+          <object class="GtkNotebook" id="details_toplevel_notebook">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can_focus">True</property>
+            <property name="show_tabs">False</property>
+            <property name="show_border">False</property>
             <child>
-              <object class="GtkScrolledWindow" id="details_sidebar">
+              <object class="GtkBox" id="box6">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="shadow_type">in</property>
+                <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkTreeView" id="details_page_list">
+                  <object class="GtkScrolledWindow" id="details_sidebar">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="model">details_store</property>
-                    <property name="headers_visible">False</property>
-                    <property name="headers_clickable">False</property>
-                    <property name="search_column">0</property>
-                    <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="details_page_list_selection"/>
-                    </child>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="shadow_type">in</property>
                     <child>
-                      <object class="GtkTreeViewColumn" id="details_column">
-                        <child>
-                          <object class="GtkCellRendererText" id="details_cell">
-                            <property name="xpad">10</property>
-                          </object>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
+                      <object class="GtkTreeView" id="details_page_list">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="model">details_store</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                        <property name="search_column">0</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="details_page_list_selection"/>
                         </child>
                         <child>
-                          <object class="GtkCellRendererText" id="padding_cell">
-                            <property name="xpad">20</property>
+                          <object class="GtkTreeViewColumn" id="details_column">
+                            <child>
+                              <object class="GtkCellRendererText" id="details_cell">
+                                <property name="xpad">10</property>
+                              </object>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                            <child>
+                              <object class="GtkCellRendererText" id="padding_cell">
+                                <property name="xpad">20</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
                   </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
                 </child>
+                <child>
+                  <object class="GtkNotebook" id="details_notebook">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="show_tabs">False</property>
+                    <property name="show_border">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label">page 1</property>
               </object>
               <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="tab_fill">False</property>
               </packing>
             </child>
             <child>
-              <object class="GtkNotebook" id="details_notebook">
+              <object class="GtkBox" id="details_add_connection_outer_box">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="show_tabs">False</property>
-                <property name="show_border">False</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkBox" id="details_add_connection_inner_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkFrame" id="details_add_connection_frame">
+                        <property name="width_request">300</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label">page 2</property>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
                 <property name="position">1</property>
+                <property name="tab_fill">False</property>
               </packing>
             </child>
           </object>
@@ -136,4 +195,12 @@
       <action-widget response="0">details_apply_button</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkListStore" id="details_store">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name page -->
+      <column type="gint"/>
+    </columns>
+  </object>
 </interface>
diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c
index ff7c758..16d6bbd 100644
--- a/panels/network/connection-editor/net-connection-editor.c
+++ b/panels/network/connection-editor/net-connection-editor.c
@@ -38,6 +38,7 @@
 #include "ce-page-ethernet.h"
 #include "ce-page-8021x-security.h"
 #include "ce-page-vpn.h"
+#include "vpn-helpers.h"
 
 #include "egg-list-box/egg-list-box.h"
 
@@ -276,9 +277,14 @@ net_connection_editor_update_title (NetConnectionEditor *editor)
 {
         gchar *id;
 
-        if (editor->is_new_connection)
-                id = g_strdup (_("New Profile"));
-        else {
+        if (editor->is_new_connection) {
+                if (editor->device) {
+                        id = g_strdup (_("New Profile"));
+                } else {
+                        /* Leave it set to "Add New Connection" */
+                        return;
+                }
+        } else {
                 NMSettingWireless *sw;
                 sw = nm_connection_get_setting_wireless (editor->connection);
                 if (sw) {
@@ -483,6 +489,8 @@ net_connection_editor_set_connection (NetConnectionEditor *editor,
         GSList *pages, *l;
         NMSettingConnection *sc;
         const gchar *type;
+        GtkTreeSelection *selection;
+        GtkTreePath *path;
 
         editor->is_new_connection = !nm_remote_settings_get_connection_by_uuid (editor->settings,
                                                                                  nm_connection_get_uuid (connection));
@@ -502,7 +510,8 @@ net_connection_editor_set_connection (NetConnectionEditor *editor,
         sc = nm_connection_get_setting_connection (connection);
         type = nm_setting_connection_get_connection_type (sc);
 
-        add_page (editor, ce_page_details_new (editor->connection, editor->client, editor->settings, editor->device, editor->ap));
+        if (!editor->is_new_connection)
+                add_page (editor, ce_page_details_new (editor->connection, editor->client, editor->settings, editor->device, editor->ap));
 
         if (strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME) == 0)
                 add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings));
@@ -524,7 +533,8 @@ net_connection_editor_set_connection (NetConnectionEditor *editor,
         add_page (editor, ce_page_ip4_new (editor->connection, editor->client, editor->settings));
         add_page (editor, ce_page_ip6_new (editor->connection, editor->client, editor->settings));
 
-        add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings, editor));
+        if (!editor->is_new_connection)
+                add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings, editor));
 
         pages = g_slist_copy (editor->initializing_pages);
         for (l = pages; l; l = l->next) {
@@ -539,6 +549,320 @@ net_connection_editor_set_connection (NetConnectionEditor *editor,
                 }
         }
         g_slist_free (pages);
+
+        selection = GTK_TREE_SELECTION (gtk_builder_get_object (editor->builder,
+                                                                "details_page_list_selection"));
+        path = gtk_tree_path_new_first ();
+        gtk_tree_selection_select_path (selection, path);
+        gtk_tree_path_free (path);
+}
+
+static void
+update_separator (GtkWidget **separator,
+                  GtkWidget  *child,
+                  GtkWidget  *before,
+                  gpointer    user_data)
+{
+  if (before == NULL)
+    return;
+
+  if (*separator == NULL)
+    {
+      *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+      gtk_widget_show (*separator);
+      g_object_ref_sink (*separator);
+    }
+}
+
+typedef struct {
+        const char *name;
+        GType (*type_func) (void);
+} NetConnectionType;
+
+static const NetConnectionType connection_types[] = {
+        { N_("VPN"), nm_setting_vpn_get_type },
+        { N_("Bond"), nm_setting_bond_get_type },
+        { N_("Bridge"), nm_setting_bridge_get_type },
+        { N_("VLAN"), nm_setting_vlan_get_type }
+};
+static const NetConnectionType *vpn_connection_type = &connection_types[0];
+
+static NMConnection *
+complete_connection_for_type (NetConnectionEditor *editor, NMConnection *connection,
+                              const NetConnectionType *connection_type)
+{
+        NMSettingConnection *s_con;
+        NMSetting *s_type;
+        GType connection_gtype;
+
+        if (!connection)
+                connection = nm_connection_new ();
+
+        s_con = nm_connection_get_setting_connection (connection);
+        if (!s_con) {
+                s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+                nm_connection_add_setting (connection, NM_SETTING (s_con));
+        }
+
+        if (!nm_setting_connection_get_uuid (s_con)) {
+                gchar *uuid = nm_utils_uuid_generate ();
+                g_object_set (s_con,
+                              NM_SETTING_CONNECTION_UUID, uuid,
+                              NULL);
+                g_free (uuid);
+        }
+
+        if (!nm_setting_connection_get_id (s_con)) {
+                GSList *connections;
+                gchar *id, *id_pattern;
+
+                connections = nm_remote_settings_list_connections (editor->settings);
+                id_pattern = g_strdup_printf ("%s %%d", _(connection_type->name));
+                id = ce_page_get_next_available_name (connections, id_pattern);
+                g_object_set (s_con,
+                              NM_SETTING_CONNECTION_ID, id,
+                              NULL);
+                g_free (id);
+                g_free (id_pattern);
+                g_slist_free (connections);
+        }
+
+        connection_gtype = connection_type->type_func ();
+        s_type = nm_connection_get_setting (connection, connection_gtype);
+        if (!s_type) {
+                s_type = g_object_new (connection_gtype, NULL);
+                nm_connection_add_setting (connection, s_type);
+        }
+
+        if (!nm_setting_connection_get_connection_type (s_con)) {
+                g_object_set (s_con,
+                              NM_SETTING_CONNECTION_TYPE, nm_setting_get_name (s_type),
+                              NULL);
+        }
+
+        return connection;
+}
+
+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;
+}
+
+static void
+finish_add_connection (NetConnectionEditor *editor, NMConnection *connection)
+{
+        GtkNotebook *notebook;
+        GtkBin *frame;
+
+        frame = GTK_BIN (gtk_builder_get_object (editor->builder, "details_add_connection_frame"));
+        gtk_widget_destroy (gtk_bin_get_child (frame));
+
+        notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_toplevel_notebook"));
+        gtk_notebook_set_current_page (notebook, 0);
+        gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button")));
+
+        if (connection)
+                net_connection_editor_set_connection (editor, connection);
+}
+
+static void
+vpn_import_complete (NMConnection *connection, gpointer user_data)
+{
+        NetConnectionEditor *editor = user_data;
+
+        if (!connection) {
+                /* The import code shows its own error dialogs. */
+                g_signal_emit (editor, signals[DONE], 0, FALSE);
+                return;
+        }
+
+        complete_connection_for_type (editor, connection, vpn_connection_type);
+        finish_add_connection (editor, connection);
+}
+
+static void
+vpn_type_activated (EggListBox *list, GtkWidget *row, NetConnectionEditor *editor)
+{
+        const char *service_name = g_object_get_data (G_OBJECT (row), "service_name");
+        NMConnection *connection;
+        NMSettingVPN *s_vpn;
+        NMSettingConnection *s_con;
+
+        if (!strcmp (service_name, "import")) {
+                vpn_import (GTK_WINDOW (editor->window), vpn_import_complete, editor);
+                return;
+        }
+
+        connection = complete_connection_for_type (editor, NULL, vpn_connection_type);
+        s_vpn = nm_connection_get_setting_vpn (connection);
+        g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, service_name, NULL);
+
+        /* Mark the connection as private to this user, and non-autoconnect */
+        s_con = nm_connection_get_setting_connection (connection);
+        g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL);
+        nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
+
+        finish_add_connection (editor, connection);
+}
+
+static void
+select_vpn_type (NetConnectionEditor *editor, EggListBox *list)
+{
+        GHashTable *vpn_plugins;
+        GHashTableIter vpn_iter;
+        gpointer service_name, vpn_plugin;
+        GList *children, *plugin_list, *iter;
+        GtkWidget *row, *name_label, *desc_label;
+        GError *error = NULL;
+
+        /* Get the available VPN types */
+        vpn_plugins = vpn_get_plugins (&error);
+        if (!vpn_plugins) {
+                net_connection_editor_error_dialog (editor,
+                                                    _("Could not load VPN plugins"),
+                                                    error->message);
+                g_error_free (error);
+                finish_add_connection (editor, NULL);
+                g_signal_emit (editor, signals[DONE], 0, FALSE);
+                return;
+        }
+        plugin_list = NULL;
+        g_hash_table_iter_init (&vpn_iter, vpn_plugins);
+        while (g_hash_table_iter_next (&vpn_iter, &service_name, &vpn_plugin))
+                plugin_list = g_list_prepend (plugin_list, vpn_plugin);
+        plugin_list = g_list_sort (plugin_list, sort_vpn_plugins);
+
+        /* Remove the previous menu contents */
+        children = gtk_container_get_children (GTK_CONTAINER (list));
+        for (iter = children; iter; iter = iter->next)
+                gtk_widget_destroy (iter->data);
+
+        /* Add the VPN types */
+        for (iter = plugin_list; iter; iter = iter->next) {
+                char *name, *desc, *desc_markup, *service_name;
+
+                g_object_get (iter->data,
+                              "name", &name,
+                              "desc", &desc,
+                              "service", &service_name,
+                              NULL);
+                // FIXME: can't hardcode fgcolor
+                desc_markup = g_markup_printf_escaped ("<span size='smaller' fgcolor='#7f7f7f'>%s</span>", desc);
+
+                row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+                gtk_widget_set_margin_left (row, 12);
+                gtk_widget_set_margin_right (row, 12);
+                gtk_widget_set_margin_top (row, 12);
+                gtk_widget_set_margin_bottom (row, 12);
+
+                name_label = gtk_label_new (name);
+                gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
+                gtk_box_pack_start (GTK_BOX (row), name_label, FALSE, TRUE, 0);
+
+                desc_label = gtk_label_new (NULL);
+                gtk_label_set_markup (GTK_LABEL (desc_label), desc_markup);
+                gtk_label_set_line_wrap (GTK_LABEL (desc_label), TRUE);
+                gtk_misc_set_alignment (GTK_MISC (desc_label), 0.0, 0.5);
+                gtk_box_pack_start (GTK_BOX (row), desc_label, FALSE, TRUE, 0);
+
+                g_free (name);
+                g_free (desc);
+                g_free (desc_markup);
+
+                gtk_widget_show_all (row);
+                g_object_set_data_full (G_OBJECT (row), "service_name", service_name, g_free);
+                gtk_container_add (GTK_CONTAINER (list), row);
+        }
+
+        /* Import */
+        row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        gtk_widget_set_margin_left (row, 12);
+        gtk_widget_set_margin_right (row, 12);
+        gtk_widget_set_margin_top (row, 12);
+        gtk_widget_set_margin_bottom (row, 12);
+
+        name_label = gtk_label_new (_("Import from fileâ"));
+        gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (row), name_label, FALSE, TRUE, 0);
+
+        gtk_widget_show_all (row);
+        g_object_set_data (G_OBJECT (row), "service_name", "import");
+        gtk_container_add (GTK_CONTAINER (list), row);
+
+        g_signal_connect (list, "child-activated",
+                          G_CALLBACK (vpn_type_activated), editor);
+}
+
+static void
+connection_type_activated (EggListBox *list, GtkWidget *row, NetConnectionEditor *editor)
+{
+        const NetConnectionType *connection_type = g_object_get_data (G_OBJECT (row), "connection_type");
+        NMConnection *connection;
+
+        g_signal_handlers_disconnect_by_func (list, G_CALLBACK (connection_type_activated), editor);
+
+        if (connection_type == vpn_connection_type) {
+                select_vpn_type (editor, list);
+                return;
+        }
+
+        connection = complete_connection_for_type (editor, NULL, connection_type);
+        finish_add_connection (editor, connection);
+}
+
+static void
+net_connection_editor_add_connection (NetConnectionEditor *editor)
+{
+        GtkNotebook *notebook;
+        GtkContainer *frame;
+        EggListBox *list;
+        int i;
+
+        notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_toplevel_notebook"));
+        frame = GTK_CONTAINER (gtk_builder_get_object (editor->builder, "details_add_connection_frame"));
+
+        list = egg_list_box_new ();
+        egg_list_box_set_selection_mode (list, GTK_SELECTION_NONE);
+        egg_list_box_set_separator_funcs (list, update_separator, NULL, NULL);
+        g_signal_connect (list, "child-activated",
+                          G_CALLBACK (connection_type_activated), editor);
+
+        for (i = 0; i < G_N_ELEMENTS (connection_types); i++) {
+                GtkWidget *row, *label;
+
+                row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+                label = gtk_label_new (_(connection_types[i].name));
+                gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+                gtk_widget_set_margin_left (label, 12);
+                gtk_widget_set_margin_right (label, 12);
+                gtk_widget_set_margin_top (label, 12);
+                gtk_widget_set_margin_bottom (label, 12);
+                gtk_box_pack_start (GTK_BOX (row), label, FALSE, TRUE, 0);
+                g_object_set_data (G_OBJECT (row), "connection_type", (gpointer) &connection_types[i]);
+
+                gtk_container_add (GTK_CONTAINER (list), row);
+        }
+
+        gtk_widget_show_all (GTK_WIDGET (list));
+        gtk_container_add (frame, GTK_WIDGET (list));
+
+        gtk_notebook_set_current_page (notebook, 1);
+        gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button")));
+        gtk_window_set_title (GTK_WINDOW (editor->window), _("Add Network Connection"));
 }
 
 static void
@@ -586,7 +910,10 @@ net_connection_editor_new (GtkWindow        *parent_window,
         editor->permission_id = g_signal_connect (editor->client, "permission-changed",
                                                   G_CALLBACK (permission_changed), editor);
 
-        net_connection_editor_set_connection (editor, connection);
+        if (connection)
+                net_connection_editor_set_connection (editor, connection);
+        else
+                net_connection_editor_add_connection (editor);
 
         return editor;
 }
diff --git a/panels/network/connection-editor/vpn-helpers.c b/panels/network/connection-editor/vpn-helpers.c
index 5be39ad..48beae5 100644
--- a/panels/network/connection-editor/vpn-helpers.c
+++ b/panels/network/connection-editor/vpn-helpers.c
@@ -164,7 +164,7 @@ vpn_get_plugins (GError **error)
 }
 
 typedef struct {
-	VpnImportSuccessCallback callback;
+	VpnImportCallback callback;
 	gpointer user_data;
 } ActionInfo;
 
@@ -194,14 +194,12 @@ import_vpn_from_file_cb (GtkWidget *dialog, gint response, gpointer user_data)
 		connection = nm_vpn_plugin_ui_interface_import (plugin, filename, &error);
 	}
 
-	if (connection)
-		info->callback (connection, info->user_data);
-	else {
+	if (!connection) {
 		GtkWidget *err_dialog;
 		char *bname = g_path_get_basename (filename);
 
-		err_dialog = gtk_message_dialog_new (NULL,
-		                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+		err_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+		                                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
 		                                     GTK_MESSAGE_ERROR,
 		                                     GTK_BUTTONS_OK,
 		                                     _("Cannot import VPN connection"));
@@ -211,39 +209,43 @@ import_vpn_from_file_cb (GtkWidget *dialog, gint response, gpointer user_data)
 		g_free (bname);
 		g_signal_connect (err_dialog, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
 		g_signal_connect (err_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
-		gtk_widget_show_all (err_dialog);
-		gtk_window_present (GTK_WINDOW (err_dialog));
+		gtk_dialog_run (GTK_DIALOG (err_dialog));
 	}
-
 	g_clear_error (&error);
 	g_free (filename);
 
 out:
 	gtk_widget_hide (dialog);
 	gtk_widget_destroy (dialog);
+
+	info->callback (connection, info->user_data);
 	g_free (info);
 }
 
 static void
 destroy_import_chooser (GtkWidget *dialog, gpointer user_data)
 {
-	g_free (user_data);
+	ActionInfo *info = (ActionInfo *) user_data;
+
 	gtk_widget_destroy (dialog);
+	info->callback (NULL, info->user_data);
+	g_free (info);
 }
 
 void
-vpn_import (VpnImportSuccessCallback callback, gpointer user_data)
+vpn_import (GtkWindow *parent, VpnImportCallback callback, gpointer user_data)
 {
 	GtkWidget *dialog;
 	ActionInfo *info;
 	const char *home_folder;
 
 	dialog = gtk_file_chooser_dialog_new (_("Select file to import"),
-	                                      NULL,
+	                                      parent,
 	                                      GTK_FILE_CHOOSER_ACTION_OPEN,
 	                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 	                                      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
 	                                      NULL);
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 	home_folder = g_get_home_dir ();
 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), home_folder);
 
diff --git a/panels/network/connection-editor/vpn-helpers.h b/panels/network/connection-editor/vpn-helpers.h
index d14fc8f..d1a8c5e 100644
--- a/panels/network/connection-editor/vpn-helpers.h
+++ b/panels/network/connection-editor/vpn-helpers.h
@@ -34,8 +34,8 @@ GHashTable *vpn_get_plugins (GError **error);
 
 NMVpnPluginUiInterface *vpn_get_plugin_by_service (const char *service);
 
-typedef void (*VpnImportSuccessCallback) (NMConnection *connection, gpointer user_data);
-void vpn_import (VpnImportSuccessCallback callback, gpointer user_data);
+typedef void (*VpnImportCallback) (NMConnection *connection, gpointer user_data);
+void vpn_import (GtkWindow *parent, VpnImportCallback callback, gpointer user_data);
 
 void vpn_export (NMConnection *connection);
 



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