[network-manager-applet: 18/20] libnma: add nma-ui-utils.[ch]



commit f84da926330cb43e7adf62ab805cbc08bd197f8b
Author: Jiří Klimeš <jklimes redhat com>
Date:   Thu Jul 9 11:14:56 2015 +0200

    libnma: add nma-ui-utils.[ch]
    
    It implements password storage functions. (Copied from libnm-gtk).

 po/POTFILES.in            |    1 +
 src/libnma/Makefile.am    |    4 +-
 src/libnma/nma-ui-utils.c |  420 +++++++++++++++++++++++++++++++++++++++++++++
 src/libnma/nma-ui-utils.h |   45 +++++
 4 files changed, 469 insertions(+), 1 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5ead43c..02b138b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -77,6 +77,7 @@ src/ethernet-dialog.c
 [type: gettext/glade]src/info.ui
 src/libnma/nma-mobile-providers.c
 src/libnma/nma-mobile-wizard.c
+src/libnma/nma-ui-utils.c
 src/libnma/nma-vpn-password-dialog.c
 src/libnma/nma-wifi-dialog.c
 [type: gettext/glade]src/libnma/wifi.ui
diff --git a/src/libnma/Makefile.am b/src/libnma/Makefile.am
index 2584822..c20ecdd 100644
--- a/src/libnma/Makefile.am
+++ b/src/libnma/Makefile.am
@@ -7,7 +7,8 @@ libnma_HEADERS = \
        nma-wifi-dialog.h \
        nma-mobile-wizard.h \
        nma-mobile-providers.h \
-       nma-vpn-password-dialog.h
+       nma-vpn-password-dialog.h \
+       nma-ui-utils.h
 
 lib_LTLIBRARIES = libnma.la
 
@@ -16,6 +17,7 @@ libnma_la_SOURCES = \
        nma-mobile-wizard.c \
        nma-mobile-providers.c \
        nma-vpn-password-dialog.c \
+       nma-ui-utils.c \
        init.c
 
 libnma_la_CFLAGS = \
diff --git a/src/libnma/nma-ui-utils.c b/src/libnma/nma-ui-utils.c
new file mode 100644
index 0000000..eea8e3d
--- /dev/null
+++ b/src/libnma/nma-ui-utils.c
@@ -0,0 +1,420 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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 2015 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "nma-ui-utils.h"
+
+/*---------------------------------------------------------------------------*/
+/* Password storage icon */
+
+#define PASSWORD_STORAGE_MENU_TAG  "password-storage-menu"
+#define MENU_WITH_NOT_REQUIRED_TAG "menu-with-not-required"
+#define SENSITIVE_ASK_ENTRY        "sensitive-ask-entry"
+
+typedef enum {
+       ITEM_STORAGE_USER    = 0,
+       ITEM_STORAGE_SYSTEM  = 1,
+       ITEM_STORAGE_ASK     = 2,
+       ITEM_STORAGE_UNUSED  = 3,
+       __ITEM_STORAGE_MAX,
+       ITEM_STORAGE_MAX = __ITEM_STORAGE_MAX - 1,
+} MenuItem;
+
+static const char *icon_name_table[ITEM_STORAGE_MAX + 1] = {
+       [ITEM_STORAGE_USER]    = "document-save",
+       [ITEM_STORAGE_SYSTEM]  = "document-save-as",
+       [ITEM_STORAGE_ASK]     = "dialog-question",
+       [ITEM_STORAGE_UNUSED]  = "edit-clear",
+};
+static const char *icon_desc_table[ITEM_STORAGE_MAX + 1] = {
+       [ITEM_STORAGE_USER]    = N_("Store the password only for this _user"),
+       [ITEM_STORAGE_SYSTEM]  = N_("Store the password for _all users"),
+       [ITEM_STORAGE_ASK]     = N_("As_k for this password every time"),
+       [ITEM_STORAGE_UNUSED]  = N_("The password is _not required"),
+};
+
+static void
+g_free_str0 (gpointer mem)
+{
+       /* g_free a char pointer and set it to 0 before (for passwords). */
+       if (mem) {
+               char *p = mem;
+               memset (p, 0, strlen (p));
+               g_free (p);
+       }
+}
+
+static void
+change_password_storage_icon (GtkWidget *passwd_entry, MenuItem item)
+{
+       const char *old_pwd;
+       gboolean sensitive_ask;
+
+       g_return_if_fail (item >= 0 && item <= ITEM_STORAGE_MAX);
+
+       gtk_entry_set_icon_from_icon_name (GTK_ENTRY (passwd_entry),
+                                          GTK_ENTRY_ICON_SECONDARY,
+                                          icon_name_table[item]);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY (passwd_entry),
+                                        GTK_ENTRY_ICON_SECONDARY,
+                                        icon_desc_table[item]);
+
+       /* We want to make entry insensitive when ITEM_STORAGE_ASK is selected
+        * Unfortunately, making GtkEntry insensitive will also make the icon
+        * insensitive, which prevents user from reverting the action.
+        * Let's workaround that by disabling focus for entry instead of
+        * sensitivity change.
+       */
+       sensitive_ask = !!g_object_get_data (G_OBJECT (passwd_entry), SENSITIVE_ASK_ENTRY);
+       if (   (item == ITEM_STORAGE_ASK && !sensitive_ask)
+           || item == ITEM_STORAGE_UNUSED) {
+               /* Store the old password */
+               old_pwd = gtk_entry_get_text (GTK_ENTRY (passwd_entry));
+               if (old_pwd && *old_pwd)
+                       g_object_set_data_full (G_OBJECT (passwd_entry), "password-old",
+                                               g_strdup (old_pwd), g_free_str0);
+               gtk_entry_set_text (GTK_ENTRY (passwd_entry), "");
+
+               if (gtk_widget_is_focus (passwd_entry))
+                       gtk_widget_child_focus ((gtk_widget_get_toplevel (passwd_entry)), 
GTK_DIR_TAB_BACKWARD);
+               gtk_widget_set_can_focus (passwd_entry, FALSE);
+       } else {
+               /* Set the old password to the entry */
+               old_pwd = g_object_get_data (G_OBJECT (passwd_entry), "password-old");
+               if (old_pwd && *old_pwd)
+                       gtk_entry_set_text (GTK_ENTRY (passwd_entry), old_pwd);
+               g_object_set_data (G_OBJECT (passwd_entry), "password-old", NULL);
+
+               if (!gtk_widget_get_can_focus (passwd_entry)) {
+                       gtk_widget_set_can_focus (passwd_entry, TRUE);
+                       gtk_widget_grab_focus (passwd_entry);
+               }
+       }
+}
+
+static MenuItem
+secret_flags_to_menu_item (NMSettingSecretFlags flags, gboolean with_not_required)
+{
+       MenuItem idx;
+
+       if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+               idx = ITEM_STORAGE_ASK;
+       else if (with_not_required && (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
+               idx = ITEM_STORAGE_UNUSED;
+       else if (flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+               idx = ITEM_STORAGE_USER;
+       else
+               idx = ITEM_STORAGE_SYSTEM;
+
+       return idx;
+}
+
+static NMSettingSecretFlags
+menu_item_to_secret_flags (MenuItem item)
+{
+       NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+       switch (item) {
+       case ITEM_STORAGE_USER:
+               flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+               break;
+       case ITEM_STORAGE_ASK:
+               flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
+               break;
+       case ITEM_STORAGE_UNUSED:
+               flags |= NM_SETTING_SECRET_FLAG_NOT_REQUIRED;
+               break;
+       case ITEM_STORAGE_SYSTEM:
+       default:
+               break;
+               
+       }
+       return flags;
+}
+
+typedef struct {
+       NMSetting *setting;
+       const char *password_flags_name;
+       MenuItem item_number;
+       GtkWidget *passwd_entry;
+} PopupMenuItemInfo;
+
+static void
+popup_menu_item_info_destroy (gpointer data)
+{
+       PopupMenuItemInfo *info = (PopupMenuItemInfo *) data;
+
+       if (info->setting)
+               g_object_unref (info->setting);
+       g_slice_free (PopupMenuItemInfo, data);
+}
+
+static void
+activate_menu_item_cb (GtkMenuItem *menuitem, gpointer user_data)
+{
+       PopupMenuItemInfo *info = (PopupMenuItemInfo *) user_data;
+       NMSettingSecretFlags flags;
+
+       /* Update password flags according to the password-storage popup menu */
+       if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem))) {
+               flags = menu_item_to_secret_flags (info->item_number);
+
+               /* Update the secret flags in the setting */
+               if (info->setting)
+                       nm_setting_set_secret_flags (info->setting, info->password_flags_name,
+                                                    flags, NULL);
+
+               /* Change icon */
+               change_password_storage_icon (info->passwd_entry, info->item_number);
+       }
+}
+
+static void
+icon_release_cb (GtkEntry *entry,
+                 GtkEntryIconPosition position,
+                 GdkEventButton *event,
+                 gpointer data)
+{
+       GtkMenu *menu = GTK_MENU (data);
+       if (position == GTK_ENTRY_ICON_SECONDARY) {
+               gtk_widget_show_all (GTK_WIDGET (data));
+               gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
+                               event->button, event->time);
+       }
+}
+
+/**
+ * nma_utils_setup_password_storage:
+ * @passwd_entry: password #GtkEntry which the icon is attached to
+ * @initial_flags: initial secret flags to setup password menu from
+ * @setting: #NMSetting containing the password, or NULL
+ * @password_flags_name: name of the secret flags (like psk-flags), or NULL
+ * @with_not_required: whether to include "Not required" menu item
+ * @sensitive_ask: %TRUE if entry should be sensivive on selected "always-ask"
+ *   icon (this is e.f. for nm-applet asking for password)
+ *
+ * Adds a secondary icon and creates a popup menu for password entry.
+ * The active menu item is set up according to initial_flags, or
+ * from @setting/@password_flags_name (if they are not NULL).
+ * If the @setting/@password_flags_name are not NULL, secret flags will
+ * be automatically updated in the setting when menu is changed.
+ */
+void
+nma_utils_setup_password_storage (GtkWidget *passwd_entry,
+                                  NMSettingSecretFlags initial_flags,
+                                  NMSetting *setting,
+                                  const char *password_flags_name,
+                                  gboolean with_not_required,
+                                  gboolean sensitive_ask)
+{
+       GtkWidget *popup_menu;
+       GtkWidget *item[4];
+       GSList *group;
+       MenuItem idx;
+       PopupMenuItemInfo *info;
+       NMSettingSecretFlags secret_flags;
+
+       /* Whether entry should be sensitive if "always-ask" is active " */
+       g_object_set_data (G_OBJECT (passwd_entry), SENSITIVE_ASK_ENTRY, GUINT_TO_POINTER (sensitive_ask));
+
+       popup_menu = gtk_menu_new ();
+       g_object_set_data (G_OBJECT (popup_menu), PASSWORD_STORAGE_MENU_TAG, GUINT_TO_POINTER (TRUE));
+       g_object_set_data (G_OBJECT (popup_menu), MENU_WITH_NOT_REQUIRED_TAG, GUINT_TO_POINTER 
(with_not_required));
+       group = NULL;
+       item[0] = gtk_radio_menu_item_new_with_mnemonic (group, icon_desc_table[0]);
+       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item[0]));
+       item[1] = gtk_radio_menu_item_new_with_mnemonic (group, icon_desc_table[1]);
+       item[2] = gtk_radio_menu_item_new_with_mnemonic (group, icon_desc_table[2]);
+       if (with_not_required)
+               item[3] = gtk_radio_menu_item_new_with_mnemonic (group, icon_desc_table[3]);
+
+       gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item[0]);
+       gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item[1]);
+       gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item[2]);
+       if (with_not_required)
+               gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item[3]);
+
+       if (setting)
+               g_object_ref (setting);
+
+       info = g_slice_new0 (PopupMenuItemInfo);
+       info->setting = setting;
+       info->password_flags_name = password_flags_name;
+       info->item_number = ITEM_STORAGE_USER;
+       info->passwd_entry = passwd_entry;
+       g_signal_connect_data (item[0], "activate",
+                              G_CALLBACK (activate_menu_item_cb),
+                              info,
+                              (GClosureNotify) popup_menu_item_info_destroy, 0);
+
+       info = g_slice_new0 (PopupMenuItemInfo);
+       info->setting = setting;
+       info->password_flags_name = password_flags_name;
+       info->item_number = ITEM_STORAGE_SYSTEM;
+       info->passwd_entry = passwd_entry;
+       g_signal_connect_data (item[1], "activate",
+                              G_CALLBACK (activate_menu_item_cb),
+                              info,
+                              (GClosureNotify) popup_menu_item_info_destroy, 0);
+
+       info = g_slice_new0 (PopupMenuItemInfo);
+       info->setting = setting;
+       info->password_flags_name = password_flags_name;
+       info->item_number = ITEM_STORAGE_ASK;
+       info->passwd_entry = passwd_entry;
+       g_signal_connect_data (item[2], "activate",
+                              G_CALLBACK (activate_menu_item_cb),
+                              info,
+                              (GClosureNotify) popup_menu_item_info_destroy, 0);
+
+
+       if (with_not_required) {
+               info = g_slice_new0 (PopupMenuItemInfo);
+               info->setting = setting;
+               info->password_flags_name = password_flags_name;
+               info->item_number = ITEM_STORAGE_UNUSED;
+               info->passwd_entry = passwd_entry;
+               g_signal_connect_data (item[3], "activate",
+                                      G_CALLBACK (activate_menu_item_cb),
+                                      info,
+                                      (GClosureNotify) popup_menu_item_info_destroy, 0);
+       }
+
+       g_signal_connect (passwd_entry, "icon-release", G_CALLBACK (icon_release_cb), popup_menu);
+       gtk_menu_attach_to_widget (GTK_MENU (popup_menu), passwd_entry, NULL);
+
+       /* Initialize active item for password-storage popup menu */
+       if (setting && password_flags_name)
+               nm_setting_get_secret_flags (setting, password_flags_name, &secret_flags, NULL);
+       else
+               secret_flags = initial_flags;
+
+       idx = secret_flags_to_menu_item (secret_flags, with_not_required);
+       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item[idx]), TRUE);
+       change_password_storage_icon (passwd_entry, idx);
+}
+
+/**
+ * nma_utils_menu_to_secret_flags:
+ * @passwd_entry: password #GtkEntry which the password icon/menu is attached to
+ *
+ * Returns secret flags corresponding to the selected password storage menu
+ * in the attached icon
+ *
+ * Returns: secret flags corresponding to the active item in password menu
+ */
+NMSettingSecretFlags
+nma_utils_menu_to_secret_flags (GtkWidget *passwd_entry)
+{
+       GList *menu_list, *iter;
+       GtkWidget *menu = NULL;
+       NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+       menu_list = gtk_menu_get_for_attach_widget (passwd_entry);
+       for (iter = menu_list; iter; iter = g_list_next (iter)) {
+               if (g_object_get_data (G_OBJECT (iter->data), PASSWORD_STORAGE_MENU_TAG)) {
+                       menu = iter->data;
+                       break;
+               }
+       }
+
+       /* Translate password popup menu to secret flags */
+       if (menu) {
+               MenuItem idx = 0;
+               GList *list;
+               int i, length;
+
+               list = gtk_container_get_children (GTK_CONTAINER (menu));
+               length = g_list_length (list);
+               for (i = 0; i < length; i++) {
+                       if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (list->data))) {
+                               idx =  (MenuItem) i;
+                               break;
+                       }
+                       list = g_list_next (list);
+               }
+
+               flags = menu_item_to_secret_flags (idx);
+       }
+       return flags;
+}
+
+/**
+ * nma_utils_update_password_storage:
+ * @passwd_entry: #GtkEntry with the password
+ * @secret_flags: secret flags to set
+ * @setting: #NMSetting containing the password, or NULL
+ * @password_flags_name: name of the secret flags (like psk-flags), or NULL
+ *
+ * Updates secret flags in the password storage popup menu and also
+ * in the @setting (if @setting and @password_flags_name are not NULL).
+ *
+ */
+void
+nma_utils_update_password_storage (GtkWidget *passwd_entry,
+                                   NMSettingSecretFlags secret_flags,
+                                   NMSetting *setting,
+                                   const char *password_flags_name)
+{
+       GList *menu_list, *iter;
+       GtkWidget *menu = NULL;
+
+       /* Update secret flags (WEP_KEY_FLAGS, PSK_FLAGS, ...) in the security setting */
+       if (setting && password_flags_name)
+               nm_setting_set_secret_flags (setting, password_flags_name, secret_flags, NULL);
+
+       /* Update password-storage popup menu to reflect secret flags */
+       menu_list = gtk_menu_get_for_attach_widget (passwd_entry);
+       for (iter = menu_list; iter; iter = g_list_next (iter)) {
+               if (g_object_get_data (G_OBJECT (iter->data), PASSWORD_STORAGE_MENU_TAG)) {
+                       menu = iter->data;
+                       break;
+               }
+       }
+
+       if (menu) {
+               GtkRadioMenuItem *item;
+               MenuItem idx;
+               GSList *group;
+               gboolean with_not_required;
+               int i, last;
+
+               /* radio menu group list contains the menu items in reverse order */
+               item = (GtkRadioMenuItem *) gtk_menu_get_active (GTK_MENU (menu));
+               group = gtk_radio_menu_item_get_group (item);
+               with_not_required = !!g_object_get_data (G_OBJECT (menu), MENU_WITH_NOT_REQUIRED_TAG);
+
+               idx = secret_flags_to_menu_item (secret_flags, with_not_required);
+               last = g_slist_length (group) - idx - 1;
+               for (i = 0; i < last; i++)
+                       group = g_slist_next (group);
+
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (group->data), TRUE);
+               change_password_storage_icon (passwd_entry, idx);
+       }
+}
+/*---------------------------------------------------------------------------*/
+
diff --git a/src/libnma/nma-ui-utils.h b/src/libnma/nma-ui-utils.h
new file mode 100644
index 0000000..30015c9
--- /dev/null
+++ b/src/libnma/nma-ui-utils.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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 2015 Red Hat, Inc.
+ */
+
+
+/* WARNING: this file is private API between nm-applet and various GNOME
+ * bits; it may change without notice and is not guaranteed to be stable.
+ */
+
+#ifndef NMA_UI_UTILS_H
+#define NMA_UI_UTILS_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+void nma_utils_setup_password_storage (GtkWidget *passwd_entry,
+                                       NMSettingSecretFlags initial_flags,
+                                       NMSetting *setting,
+                                       const char *password_flags_name,
+                                       gboolean with_not_required,
+                                       gboolean sensitive_ask);
+NMSettingSecretFlags nma_utils_menu_to_secret_flags (GtkWidget *passwd_entry);
+void nma_utils_update_password_storage (GtkWidget *passwd_entry,
+                                        NMSettingSecretFlags secret_flags,
+                                        NMSetting *setting,
+                                        const char *password_flags_name);
+
+#endif /* NMA_UI_UTILS_H */
+


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