[network-manager-applet: 18/20] libnma: add nma-ui-utils.[ch]
- From: Jiří Klimeš <jklimes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-applet: 18/20] libnma: add nma-ui-utils.[ch]
- Date: Thu, 9 Jul 2015 10:06:08 +0000 (UTC)
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]