[network-manager-applet/danw/virtual-devs: 1/5] applet: add VLAN, Bridge and Bond device support



commit 14549451442f09379d5b6e2f3fc520a9da567ffa
Author: Dan Williams <dcbw redhat com>
Date:   Wed May 15 10:07:10 2013 -0400

    applet: add VLAN, Bridge and Bond device support

 po/POTFILES.in             |    3 +
 src/Makefile.am            |    6 +
 src/applet-device-bond.c   |  293 ++++++++++++++++++++++++++++++++++++++++
 src/applet-device-bond.h   |   31 +++++
 src/applet-device-bridge.c |  292 ++++++++++++++++++++++++++++++++++++++++
 src/applet-device-bridge.h |   31 +++++
 src/applet-device-vlan.c   |  316 ++++++++++++++++++++++++++++++++++++++++++++
 src/applet-device-vlan.h   |   31 +++++
 src/applet.c               |  104 ++++++++++-----
 src/applet.h               |    6 +
 10 files changed, 1076 insertions(+), 37 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9d63756..115e5c5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,11 +6,14 @@ nm-connection-editor.desktop.in
 org.gnome.nm-applet.gschema.xml.in
 [type: gettext/glade]src/8021x.ui
 src/applet.c
+src/applet-device-bond.c
+src/applet-device-bridge.c
 src/applet-device-bt.c
 src/applet-device-cdma.c
 src/applet-device-ethernet.c
 src/applet-device-broadband.c
 src/applet-device-gsm.c
+src/applet-device-vlan.c
 src/applet-device-wifi.c
 src/applet-device-wimax.c
 src/applet-dialogs.c
diff --git a/src/Makefile.am b/src/Makefile.am
index eecd788..23bae47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,12 @@ nm_applet_SOURCES = \
        applet-device-bt.c \
        applet-device-wimax.h \
        applet-device-wimax.c \
+       applet-device-vlan.h \
+       applet-device-vlan.c \
+       applet-device-bond.h \
+       applet-device-bond.c \
+       applet-device-bridge.h \
+       applet-device-bridge.c \
        fallback-icon.h \
        shell-watcher.h \
        shell-watcher.c
diff --git a/src/applet-device-bond.c b/src/applet-device-bond.c
new file mode 100644
index 0000000..5da6afb
--- /dev/null
+++ b/src/applet-device-bond.c
@@ -0,0 +1,293 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-bond.h>
+#include <nm-device-bond.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-bond.h"
+#include "utils.h"
+
+typedef struct {
+       NMApplet *applet;
+       NMDevice *device;
+       NMConnection *connection;
+} BondMenuItemInfo;
+
+static void
+bond_menu_item_info_destroy (gpointer data)
+{
+       BondMenuItemInfo *info = (BondMenuItemInfo *) data;
+
+       g_object_unref (G_OBJECT (info->device));
+       if (info->connection)
+               g_object_unref (G_OBJECT (info->connection));
+
+       g_slice_free (BondMenuItemInfo, data);
+}
+
+static void
+bond_menu_item_activate (GtkMenuItem *item, gpointer user_data)
+{
+       BondMenuItemInfo *info = (BondMenuItemInfo *) user_data;
+
+       applet_menu_item_activate_helper (info->device,
+                                         info->connection,
+                                         "/",
+                                         info->applet,
+                                         user_data);
+}
+
+
+typedef enum {
+       ADD_ACTIVE = 1,
+       ADD_INACTIVE = 2,
+} AddActiveInactiveEnum;
+
+static void
+add_connection_items (NMDevice *device,
+                      GSList *connections,
+                      NMConnection *active,
+                      AddActiveInactiveEnum flag,
+                      GtkWidget *menu,
+                      NMApplet *applet)
+{
+       GSList *iter;
+       BondMenuItemInfo *info;
+
+       for (iter = connections; iter; iter = g_slist_next (iter)) {
+               NMConnection *connection = NM_CONNECTION (iter->data);
+               GtkWidget *item;
+
+               if (active == connection) {
+                       if ((flag & ADD_ACTIVE) == 0)
+                               continue;
+               } else {
+                       if ((flag & ADD_INACTIVE) == 0)
+                               continue;
+               }
+
+               item = applet_new_menu_item_helper (connection, active, (flag & ADD_ACTIVE));
+               gtk_widget_set_sensitive (item, TRUE);
+
+               info = g_slice_new0 (BondMenuItemInfo);
+               info->applet = applet;
+               info->device = g_object_ref (G_OBJECT (device));
+               info->connection = g_object_ref (connection);
+
+               g_signal_connect_data (item, "activate",
+                                      G_CALLBACK (bond_menu_item_activate),
+                                      info,
+                                      (GClosureNotify) bond_menu_item_info_destroy, 0);
+
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       }
+}
+
+static void
+add_default_connection_item (NMDevice *device,
+                             GtkWidget *menu,
+                             NMApplet *applet)
+{
+       BondMenuItemInfo *info;
+       GtkWidget *item;
+       
+       item = gtk_check_menu_item_new_with_label (_("Configure bond connections..."));
+       gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
+       gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
+
+       info = g_slice_new0 (BondMenuItemInfo);
+       info->applet = applet;
+       info->device = g_object_ref (G_OBJECT (device));
+
+       g_signal_connect_data (item, "activate",
+                              G_CALLBACK (bond_menu_item_activate),
+                              info,
+                              (GClosureNotify) bond_menu_item_info_destroy, 0);
+
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+}
+
+static void
+bond_add_menu_item (NMDevice *device,
+                    guint32 n_devices,
+                    NMConnection *active,
+                    GtkWidget *menu,
+                    NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+       GSList *connections, *all;
+
+       all = applet_get_all_connections (applet);
+       connections = nm_device_filter_connections (device, all);
+       g_slist_free (all);
+
+       text = g_strdup_printf (_("Bond (%s)"), nm_device_get_iface (device));
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               add_connection_items (device, connections, active, ADD_ACTIVE, menu, applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       item = nma_menu_device_get_menu_item (device, applet, NULL);
+       if (item) {
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+               gtk_widget_show (item);
+       }
+
+       if (!nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       add_connection_items (device, connections, active, ADD_INACTIVE, menu, applet);
+               else
+                       add_default_connection_item (device, menu, applet);
+       }
+
+       g_slist_free (connections);
+}
+
+static void
+bond_device_state_changed (NMDevice *device,
+                           NMDeviceState new_state,
+                           NMDeviceState old_state,
+                           NMDeviceStateReason reason,
+                           NMApplet *applet)
+{
+       if (new_state == NM_DEVICE_STATE_ACTIVATED) {
+               NMConnection *connection;
+               NMSettingConnection *s_con = NULL;
+               char *str = NULL;
+
+               connection = applet_find_active_connection_for_device (device, applet, NULL);
+               if (connection) {
+                       const char *id;
+                       s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+                       id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
+                       if (id)
+                               str = g_strdup_printf (_("You are now connected to '%s'."), id);
+               }
+
+               applet_do_notify_with_pref (applet,
+                                           _("Connection Established"),
+                                           str ? str : _("You are now connected to the VLAN."),
+                                           "nm-device-wired",
+                                           PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+               g_free (str);
+       }
+}
+
+static GdkPixbuf *
+bond_get_icon (NMDevice *device,
+               NMDeviceState state,
+               NMConnection *connection,
+               char **tip,
+               NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+bond_new_auto_connection (NMDevice *device,
+                          gpointer dclass_data,
+                          AppletNewAutoConnectionCallback callback,
+                          gpointer callback_data)
+{
+       nma_edit_connections ();
+       return FALSE;
+}
+
+
+static gboolean
+bond_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on bonds */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_bond_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = bond_new_auto_connection;
+       dclass->add_menu_item = bond_add_menu_item;
+       dclass->device_state_changed = bond_device_state_changed;
+       dclass->get_icon = bond_get_icon;
+       dclass->get_secrets = bond_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-bond.h b/src/applet-device-bond.h
new file mode 100644
index 0000000..227c951
--- /dev/null
+++ b/src/applet-device-bond.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_BOND_H__
+#define __APPLET_DEVICE_BOND_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_bond_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_BOND_H__ */
diff --git a/src/applet-device-bridge.c b/src/applet-device-bridge.c
new file mode 100644
index 0000000..e6633d9
--- /dev/null
+++ b/src/applet-device-bridge.c
@@ -0,0 +1,292 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-bridge.h>
+#include <nm-device-bridge.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-bridge.h"
+#include "utils.h"
+
+typedef struct {
+       NMApplet *applet;
+       NMDevice *device;
+       NMConnection *connection;
+} BridgeMenuItemInfo;
+
+static void
+bridge_menu_item_info_destroy (gpointer data)
+{
+       BridgeMenuItemInfo *info = (BridgeMenuItemInfo *) data;
+
+       g_object_unref (G_OBJECT (info->device));
+       if (info->connection)
+               g_object_unref (G_OBJECT (info->connection));
+
+       g_slice_free (BridgeMenuItemInfo, data);
+}
+
+static void
+bridge_menu_item_activate (GtkMenuItem *item, gpointer user_data)
+{
+       BridgeMenuItemInfo *info = (BridgeMenuItemInfo *) user_data;
+
+       applet_menu_item_activate_helper (info->device,
+                                         info->connection,
+                                         "/",
+                                         info->applet,
+                                         user_data);
+}
+
+
+typedef enum {
+       ADD_ACTIVE = 1,
+       ADD_INACTIVE = 2,
+} AddActiveInactiveEnum;
+
+static void
+add_connection_items (NMDevice *device,
+                      GSList *connections,
+                      NMConnection *active,
+                      AddActiveInactiveEnum flag,
+                      GtkWidget *menu,
+                      NMApplet *applet)
+{
+       GSList *iter;
+       BridgeMenuItemInfo *info;
+
+       for (iter = connections; iter; iter = g_slist_next (iter)) {
+               NMConnection *connection = NM_CONNECTION (iter->data);
+               GtkWidget *item;
+
+               if (active == connection) {
+                       if ((flag & ADD_ACTIVE) == 0)
+                               continue;
+               } else {
+                       if ((flag & ADD_INACTIVE) == 0)
+                               continue;
+               }
+
+               item = applet_new_menu_item_helper (connection, active, (flag & ADD_ACTIVE));
+               gtk_widget_set_sensitive (item, TRUE);
+
+               info = g_slice_new0 (BridgeMenuItemInfo);
+               info->applet = applet;
+               info->device = g_object_ref (G_OBJECT (device));
+               info->connection = g_object_ref (connection);
+
+               g_signal_connect_data (item, "activate",
+                                      G_CALLBACK (bridge_menu_item_activate),
+                                      info,
+                                      (GClosureNotify) bridge_menu_item_info_destroy, 0);
+
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       }
+}
+
+static void
+add_default_connection_item (NMDevice *device,
+                             GtkWidget *menu,
+                             NMApplet *applet)
+{
+       BridgeMenuItemInfo *info;
+       GtkWidget *item;
+       
+       item = gtk_check_menu_item_new_with_label (_("Configure bridge connections..."));
+       gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
+       gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
+
+       info = g_slice_new0 (BridgeMenuItemInfo);
+       info->applet = applet;
+       info->device = g_object_ref (G_OBJECT (device));
+
+       g_signal_connect_data (item, "activate",
+                              G_CALLBACK (bridge_menu_item_activate),
+                              info,
+                              (GClosureNotify) bridge_menu_item_info_destroy, 0);
+
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+}
+
+static void
+bridge_add_menu_item (NMDevice *device,
+                      guint32 n_devices,
+                      NMConnection *active,
+                      GtkWidget *menu,
+                      NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+       GSList *connections, *all;
+
+       all = applet_get_all_connections (applet);
+       connections = nm_device_filter_connections (device, all);
+       g_slist_free (all);
+
+       text = g_strdup_printf (_("Bridge (%s)"), nm_device_get_iface (device));
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               add_connection_items (device, connections, active, ADD_ACTIVE, menu, applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       item = nma_menu_device_get_menu_item (device, applet, NULL);
+       if (item) {
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+               gtk_widget_show (item);
+       }
+
+       if (!nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       add_connection_items (device, connections, active, ADD_INACTIVE, menu, applet);
+               else
+                       add_default_connection_item (device, menu, applet);
+       }
+
+       g_slist_free (connections);
+}
+
+static void
+bridge_device_state_changed (NMDevice *device,
+                             NMDeviceState new_state,
+                             NMDeviceState old_state,
+                             NMDeviceStateReason reason,
+                             NMApplet *applet)
+{
+       if (new_state == NM_DEVICE_STATE_ACTIVATED) {
+               NMConnection *connection;
+               NMSettingConnection *s_con = NULL;
+               char *str = NULL;
+
+               connection = applet_find_active_connection_for_device (device, applet, NULL);
+               if (connection) {
+                       const char *id;
+                       s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+                       id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
+                       if (id)
+                               str = g_strdup_printf (_("You are now connected to '%s'."), id);
+               }
+
+               applet_do_notify_with_pref (applet,
+                                           _("Connection Established"),
+                                           str ? str : _("You are now connected to the VLAN."),
+                                           "nm-device-wired",
+                                           PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+               g_free (str);
+       }
+}
+
+static GdkPixbuf *
+bridge_get_icon (NMDevice *device,
+                 NMDeviceState state,
+                 NMConnection *connection,
+                 char **tip,
+                 NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+bridge_new_auto_connection (NMDevice *device,
+                            gpointer dclass_data,
+                            AppletNewAutoConnectionCallback callback,
+                            gpointer callback_data)
+{
+       nma_edit_connections ();
+       return FALSE;
+}
+
+static gboolean
+bridge_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on bridges */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_bridge_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = bridge_new_auto_connection;
+       dclass->add_menu_item = bridge_add_menu_item;
+       dclass->device_state_changed = bridge_device_state_changed;
+       dclass->get_icon = bridge_get_icon;
+       dclass->get_secrets = bridge_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-bridge.h b/src/applet-device-bridge.h
new file mode 100644
index 0000000..33dc49a
--- /dev/null
+++ b/src/applet-device-bridge.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_BRIDGE_H__
+#define __APPLET_DEVICE_BRIDGE_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_bridge_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_BRIDGE_H__ */
diff --git a/src/applet-device-vlan.c b/src/applet-device-vlan.c
new file mode 100644
index 0000000..8c7325a
--- /dev/null
+++ b/src/applet-device-vlan.c
@@ -0,0 +1,316 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-vlan.h>
+#include <nm-device-vlan.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-vlan.h"
+#include "nm-ui-utils.h"
+
+typedef struct {
+       NMApplet *applet;
+       NMDevice *device;
+       NMConnection *connection;
+} VlanMenuItemInfo;
+
+static void
+vlan_menu_item_info_destroy (gpointer data)
+{
+       VlanMenuItemInfo *info = (VlanMenuItemInfo *) data;
+
+       g_object_unref (G_OBJECT (info->device));
+       if (info->connection)
+               g_object_unref (G_OBJECT (info->connection));
+
+       g_slice_free (VlanMenuItemInfo, data);
+}
+
+static void
+vlan_menu_item_activate (GtkMenuItem *item, gpointer user_data)
+{
+       VlanMenuItemInfo *info = (VlanMenuItemInfo *) user_data;
+
+       applet_menu_item_activate_helper (info->device,
+                                         info->connection,
+                                         "/",
+                                         info->applet,
+                                         user_data);
+}
+
+
+typedef enum {
+       ADD_ACTIVE = 1,
+       ADD_INACTIVE = 2,
+} AddActiveInactiveEnum;
+
+static void
+add_connection_items (NMDevice *device,
+                      GSList *connections,
+                      gboolean carrier,
+                      NMConnection *active,
+                      AddActiveInactiveEnum flag,
+                      GtkWidget *menu,
+                      NMApplet *applet)
+{
+       GSList *iter;
+       VlanMenuItemInfo *info;
+
+       for (iter = connections; iter; iter = g_slist_next (iter)) {
+               NMConnection *connection = NM_CONNECTION (iter->data);
+               GtkWidget *item;
+
+               if (active == connection) {
+                       if ((flag & ADD_ACTIVE) == 0)
+                               continue;
+               } else {
+                       if ((flag & ADD_INACTIVE) == 0)
+                               continue;
+               }
+
+               item = applet_new_menu_item_helper (connection, active, (flag & ADD_ACTIVE));
+               gtk_widget_set_sensitive (item, carrier);
+
+               info = g_slice_new0 (VlanMenuItemInfo);
+               info->applet = applet;
+               info->device = g_object_ref (G_OBJECT (device));
+               info->connection = g_object_ref (connection);
+
+               g_signal_connect_data (item, "activate",
+                                      G_CALLBACK (vlan_menu_item_activate),
+                                      info,
+                                      (GClosureNotify) vlan_menu_item_info_destroy, 0);
+
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       }
+}
+
+static void
+add_default_connection_item (NMDevice *device,
+                             gboolean carrier,
+                             GtkWidget *menu,
+                             NMApplet *applet)
+{
+       VlanMenuItemInfo *info;
+       GtkWidget *item;
+       
+       item = gtk_check_menu_item_new_with_label (_("Configure VLAN connections..."));
+       gtk_widget_set_sensitive (GTK_WIDGET (item), carrier);
+       gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
+
+       info = g_slice_new0 (VlanMenuItemInfo);
+       info->applet = applet;
+       info->device = g_object_ref (G_OBJECT (device));
+
+       g_signal_connect_data (item, "activate",
+                              G_CALLBACK (vlan_menu_item_activate),
+                              info,
+                              (GClosureNotify) vlan_menu_item_info_destroy, 0);
+
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+}
+
+static void
+vlan_add_menu_item (NMDevice *device,
+                    guint32 n_devices,
+                    NMConnection *active,
+                    GtkWidget *menu,
+                    NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+       GSList *connections, *all;
+       gboolean carrier = TRUE;
+
+       all = applet_get_all_connections (applet);
+       connections = nm_device_filter_connections (device, all);
+       g_slist_free (all);
+
+       if (n_devices > 1) {
+               const char *desc;
+
+               desc = nma_utils_get_device_description (device);
+
+               if (g_slist_length (connections) > 1)
+                       text = g_strdup_printf (_("VLANs (%s)"), desc);
+               else
+                       text = g_strdup_printf (_("VLAN (%s)"), desc);
+       } else {
+               if (g_slist_length (connections) > 1)
+                       text = g_strdup (_("VLANs"));
+               else
+                       text = g_strdup (_("VLAN"));
+       }
+
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       /* Only dim the item if the device supports carrier detection AND
+        * we know it doesn't have a link.
+        */
+       if (nm_device_get_capabilities (device) & NM_DEVICE_CAP_CARRIER_DETECT)
+               carrier = nm_device_vlan_get_carrier (NM_DEVICE_VLAN (device));
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               add_connection_items (device, connections, carrier, active, ADD_ACTIVE, menu, applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       item = nma_menu_device_get_menu_item (device, applet, carrier ? NULL : _("disconnected"));
+       if (item) {
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+               gtk_widget_show (item);
+       }
+
+       if (!nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       add_connection_items (device, connections, carrier, active, ADD_INACTIVE, menu, 
applet);
+               else
+                       add_default_connection_item (device, carrier, menu, applet);
+       }
+
+       g_slist_free (connections);
+}
+
+static void
+vlan_device_state_changed (NMDevice *device,
+                           NMDeviceState new_state,
+                           NMDeviceState old_state,
+                           NMDeviceStateReason reason,
+                           NMApplet *applet)
+{
+       if (new_state == NM_DEVICE_STATE_ACTIVATED) {
+               NMConnection *connection;
+               NMSettingConnection *s_con = NULL;
+               char *str = NULL;
+
+               connection = applet_find_active_connection_for_device (device, applet, NULL);
+               if (connection) {
+                       const char *id;
+                       s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+                       id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
+                       if (id)
+                               str = g_strdup_printf (_("You are now connected to '%s'."), id);
+               }
+
+               applet_do_notify_with_pref (applet,
+                                           _("Connection Established"),
+                                           str ? str : _("You are now connected to the VLAN."),
+                                           "nm-device-wired",
+                                           PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+               g_free (str);
+       }
+}
+
+static GdkPixbuf *
+vlan_get_icon (NMDevice *device,
+               NMDeviceState state,
+               NMConnection *connection,
+               char **tip,
+               NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+vlan_new_auto_connection (NMDevice *device,
+                          gpointer dclass_data,
+                          AppletNewAutoConnectionCallback callback,
+                          gpointer callback_data)
+{
+       nma_edit_connections ();
+       return FALSE;
+}
+
+static gboolean
+vlan_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on VLANs */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_vlan_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = vlan_new_auto_connection;
+       dclass->add_menu_item = vlan_add_menu_item;
+       dclass->device_state_changed = vlan_device_state_changed;
+       dclass->get_icon = vlan_get_icon;
+       dclass->get_secrets = vlan_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-vlan.h b/src/applet-device-vlan.h
new file mode 100644
index 0000000..e905f42
--- /dev/null
+++ b/src/applet-device-vlan.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_VLAN_H__
+#define __APPLET_DEVICE_VLAN_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_vlan_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_VLAN_H__ */
diff --git a/src/applet.c b/src/applet.c
index 3ab1942..164dad3 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -45,10 +45,14 @@
 #include <dbus/dbus-glib-lowlevel.h>
 
 #include <NetworkManagerVPN.h>
+#include <nm-device-bond.h>
+#include <nm-device-bridge.h>
+#include <nm-device-bt.h>
 #include <nm-device-ethernet.h>
-#include <nm-device-wifi.h>
+#include <nm-device-infiniband.h>
 #include <nm-device-modem.h>
-#include <nm-device-bt.h>
+#include <nm-device-vlan.h>
+#include <nm-device-wifi.h>
 #include <nm-device-wimax.h>
 #include <nm-utils.h>
 #include <nm-connection.h>
@@ -67,11 +71,14 @@
 #include <libnotify/notify.h>
 
 #include "applet.h"
+#include "applet-device-bond.h"
+#include "applet-device-bridge.h"
+#include "applet-device-bt.h"
+#include "applet-device-cdma.h"
 #include "applet-device-ethernet.h"
-#include "applet-device-wifi.h"
 #include "applet-device-gsm.h"
-#include "applet-device-cdma.h"
-#include "applet-device-bt.h"
+#include "applet-device-vlan.h"
+#include "applet-device-wifi.h"
 #include "applet-device-wimax.h"
 #include "applet-dialogs.h"
 #include "nm-wifi-dialog.h"
@@ -258,6 +265,12 @@ get_device_class (NMDevice *device, NMApplet *applet)
                return applet->bt_class;
        else if (NM_IS_DEVICE_WIMAX (device))
                return applet->wimax_class;
+       else if (NM_IS_DEVICE_VLAN (device))
+               return applet->vlan_class;
+       else if (NM_IS_DEVICE_BOND (device))
+               return applet->bond_class;
+       else if (NM_IS_DEVICE_BRIDGE (device))
+               return applet->bridge_class;
        else
                g_debug ("%s: Unknown device type '%s'", __func__, G_OBJECT_TYPE_NAME (device));
        return NULL;
@@ -659,10 +672,8 @@ applet_menu_item_activate_helper (NMDevice *device,
        g_assert (dclass);
        if (!dclass->new_auto_connection (device, dclass_data,
                                          applet_menu_item_activate_helper_new_connection,
-                                         info)) {
-               g_warning ("Couldn't create default connection.");
+                                         info))
                applet_item_activate_info_destroy (info);
-       }
 }
 
 void
@@ -1339,15 +1350,44 @@ static void nma_menu_add_text_item (GtkWidget *menu, char *text)
        gtk_widget_show (menu_item);
 }
 
+static guint
+get_device_order (GType dtype)
+{
+       static GType order[30] = { G_TYPE_INVALID };
+       guint i = 0;
+
+       if (G_UNLIKELY (order[0] == G_TYPE_INVALID)) {
+               order[i++] = NM_TYPE_DEVICE_BRIDGE;
+               order[i++] = NM_TYPE_DEVICE_BOND;
+               order[i++] = NM_TYPE_DEVICE_ETHERNET;
+               order[i++] = NM_TYPE_DEVICE_INFINIBAND;
+               order[i++] = NM_TYPE_DEVICE_VLAN;
+               order[i++] = NM_TYPE_DEVICE_WIFI;
+               order[i++] = NM_TYPE_DEVICE_MODEM;
+               order[i++] = NM_TYPE_DEVICE_BT;
+               /* LAST */
+               order[i++] = G_TYPE_INVALID;
+       }
+
+       for (i = 0; i < G_N_ELEMENTS (order) && order[i] != G_TYPE_INVALID; i++) {
+               if (order[i] == dtype)
+                       break;
+       }
+
+       return i;
+}
+
 static gint
 sort_devices (gconstpointer a, gconstpointer b)
 {
        NMDevice *aa = NM_DEVICE (a);
        NMDevice *bb = NM_DEVICE (b);
-       GType aa_type = G_OBJECT_TYPE (G_OBJECT (aa));
-       GType bb_type = G_OBJECT_TYPE (G_OBJECT (bb));
+       guint aa_order, bb_order;
 
-       if (aa_type == bb_type) {
+       aa_order = get_device_order (G_OBJECT_TYPE (aa));
+       bb_order = get_device_order (G_OBJECT_TYPE (bb));
+
+       if (aa_order == bb_order) {
                const char *aa_desc = NULL;
                const char *bb_desc = NULL;
 
@@ -1357,31 +1397,9 @@ sort_devices (gconstpointer a, gconstpointer b)
                return g_strcmp0 (aa_desc, bb_desc);
        }
 
-       /* Ethernet always first */
-       if (aa_type == NM_TYPE_DEVICE_ETHERNET)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_ETHERNET)
-               return 1;
-
-       /* Modems next */
-       if (aa_type == NM_TYPE_DEVICE_MODEM)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_MODEM)
-               return 1;
-
-       /* Bluetooth next */
-       if (aa_type == NM_TYPE_DEVICE_BT)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_BT)
-               return 1;
-
-       /* WiMAX next */
-       if (aa_type == NM_TYPE_DEVICE_WIMAX)
+       if (aa_order < bb_order)
                return -1;
-       if (bb_type == NM_TYPE_DEVICE_WIMAX)
-               return 1;
 
-       /* WiFi last because it has many menu items */
        return 1;
 }
 
@@ -2004,8 +2022,8 @@ ce_child_setup (gpointer user_data G_GNUC_UNUSED)
        setpgid (pid, pid);
 }
 
-static void
-nma_edit_connections_cb (GtkMenuItem *mi, NMApplet *applet)
+void
+nma_edit_connections (void)
 {
        char *argv[2];
        GError *error = NULL;
@@ -2107,7 +2125,7 @@ static GtkWidget *nma_context_menu_create (NMApplet *applet)
        applet->connections_menu_item = gtk_image_menu_item_new_with_mnemonic (_("Edit Connections..."));
        g_signal_connect (applet->connections_menu_item,
                                   "activate",
-                                  G_CALLBACK (nma_edit_connections_cb),
+                                  G_CALLBACK (nma_edit_connections),
                                   applet);
        image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->connections_menu_item), image);
@@ -3472,6 +3490,15 @@ constructor (GType type,
        applet->wimax_class = applet_device_wimax_get_class (applet);
        g_assert (applet->wimax_class);
 
+       applet->vlan_class = applet_device_vlan_get_class (applet);
+       g_assert (applet->vlan_class);
+
+       applet->bond_class = applet_device_bond_get_class (applet);
+       g_assert (applet->bond_class);
+
+       applet->bridge_class = applet_device_bridge_get_class (applet);
+       g_assert (applet->bridge_class);
+
        foo_client_setup (applet);
 
 #if WITH_MODEM_MANAGER_1
@@ -3514,6 +3541,9 @@ static void finalize (GObject *object)
 #endif
        g_slice_free (NMADeviceClass, applet->bt_class);
        g_slice_free (NMADeviceClass, applet->wimax_class);
+       g_slice_free (NMADeviceClass, applet->vlan_class);
+       g_slice_free (NMADeviceClass, applet->bond_class);
+       g_slice_free (NMADeviceClass, applet->bridge_class);
 
        if (applet->update_icon_id)
                g_source_remove (applet->update_icon_id);
diff --git a/src/applet.h b/src/applet.h
index 647500b..1bb32b8 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -116,6 +116,9 @@ typedef struct
 #endif
        NMADeviceClass *bt_class;
        NMADeviceClass *wimax_class;
+       NMADeviceClass *vlan_class;
+       NMADeviceClass *bond_class;
+       NMADeviceClass *bridge_class;
 
        /* Data model elements */
        guint                   update_icon_id;
@@ -331,4 +334,7 @@ gboolean applet_wifi_connect_to_8021x_network (NMApplet *applet,
 gboolean applet_wifi_create_wifi_network (NMApplet *applet);
 gboolean applet_wifi_can_create_wifi_network (NMApplet *applet);
 
+void nma_edit_connections (void);
+
+
 #endif



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