[gnome-software] Add a dialog that can be used to get authentication data
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add a dialog that can be used to get authentication data
- Date: Fri, 10 Jun 2016 15:02:27 +0000 (UTC)
commit 94fee7ee93dee72bcfcca421de3859080bd66a01
Author: Richard Hughes <richard hughsie com>
Date: Fri Jun 10 15:51:49 2016 +0100
Add a dialog that can be used to get authentication data
po/POTFILES.in | 2 +
src/Makefile.am | 3 +
src/gnome-software.gresource.xml | 1 +
src/gs-auth-dialog.c | 332 +++++++++++++++++++++++++++++++++++
src/gs-auth-dialog.h | 45 +++++
src/gs-auth-dialog.ui | 360 ++++++++++++++++++++++++++++++++++++++
6 files changed, 743 insertions(+), 0 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c1800b6..f87752f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,8 @@ src/gs-application.c
src/gs-app-row.c
[type: gettext/glade]src/gs-app-row.ui
src/gs-app-tile.c
+src/gs-auth-dialog.c
+[type: gettext/glade]src/gs-auth-dialog.ui
src/gs-category.c
src/gs-dbus-helper.c
src/gs-feature-tile.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 3fbb5fa..86e2e7b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,7 @@ UI_FILES = \
gs-app-folder-dialog.ui \
gs-app-row.ui \
gs-app-tile.ui \
+ gs-auth-dialog.ui \
gs-category-tile.ui \
gs-feature-tile.ui \
gs-first-run-dialog.ui \
@@ -142,6 +143,8 @@ gnome_software_SOURCES = \
gs-app-list-private.h \
gs-auth.c \
gs-auth.h \
+ gs-auth-dialog.c \
+ gs-auth-dialog.h \
gs-category.c \
gs-category.h \
gs-category-private.h \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 773ce8e..23a127a 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -7,6 +7,7 @@
<file preprocess="xml-stripblanks">gs-app-folder-dialog.ui</file>
<file preprocess="xml-stripblanks">gs-app-row.ui</file>
<file preprocess="xml-stripblanks">gs-app-tile.ui</file>
+ <file preprocess="xml-stripblanks">gs-auth-dialog.ui</file>
<file preprocess="xml-stripblanks">gs-category-tile.ui</file>
<file preprocess="xml-stripblanks">gs-feature-tile.ui</file>
<file preprocess="xml-stripblanks">gs-first-run-dialog.ui</file>
diff --git a/src/gs-auth-dialog.c b/src/gs-auth-dialog.c
new file mode 100644
index 0000000..62c1681
--- /dev/null
+++ b/src/gs-auth-dialog.c
@@ -0,0 +1,332 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-auth.h"
+#include "gs-auth-dialog.h"
+#include "gs-common.h"
+
+struct _GsAuthDialog
+{
+ GtkDialog parent_instance;
+
+ GCancellable *cancellable;
+ GsPluginLoader *plugin_loader;
+ GsApp *app;
+ GsAuth *auth;
+ GtkWidget *box_error;
+ GtkWidget *button_cancel;
+ GtkWidget *button_continue;
+ GtkWidget *checkbutton_remember;
+ GtkWidget *entry_password;
+ GtkWidget *entry_pin;
+ GtkWidget *entry_username;
+ GtkWidget *image_vendor;
+ GtkWidget *label_error;
+ GtkWidget *label_title;
+ GtkWidget *radiobutton_already;
+ GtkWidget *radiobutton_lost_pwd;
+ GtkWidget *radiobutton_register;
+ GtkWidget *stack;
+};
+
+G_DEFINE_TYPE (GsAuthDialog, gs_auth_dialog, GTK_TYPE_DIALOG)
+
+static void
+gs_auth_dialog_check_ui (GsAuthDialog *dialog)
+{
+ g_autofree gchar *title = NULL;
+ const gchar *tmp;
+ const gchar *username = gtk_entry_get_text (GTK_ENTRY (dialog->entry_username));
+ const gchar *password = gtk_entry_get_text (GTK_ENTRY (dialog->entry_password));
+
+ /* set the header */
+ tmp = gs_auth_get_provider_name (dialog->auth);
+ if (tmp == NULL) {
+ /* TRANSLATORS: this is when the service name is not known */
+ title = g_strdup (_("To continue you need to sign in."));
+ gtk_label_set_label (GTK_LABEL (dialog->label_title), title);
+ } else {
+ /* TRANSLATORS: the %s is a service name, e.g. "Ubuntu One" */
+ title = g_strdup_printf (_("To continue you need to sign in to %s."), tmp);
+ gtk_label_set_label (GTK_LABEL (dialog->label_title), title);
+ }
+
+ /* set the vendor image */
+ tmp = gs_auth_get_provider_logo (dialog->auth);
+ if (tmp == NULL) {
+ gtk_widget_hide (dialog->image_vendor);
+ } else {
+ gtk_image_set_from_file (GTK_IMAGE (dialog->image_vendor), tmp);
+ gtk_widget_show (dialog->image_vendor);
+ }
+
+ /* need username and password to continue for known account */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_already))) {
+ gtk_widget_set_sensitive (dialog->button_continue,
+ username[0] != '\0' && password[0] != '\0');
+ gtk_widget_set_sensitive (dialog->checkbutton_remember, TRUE);
+ } else {
+ gtk_entry_set_text (GTK_ENTRY (dialog->entry_password), "");
+ gtk_widget_set_sensitive (dialog->button_continue,
+ username[0] != '\0');
+ gtk_widget_set_sensitive (dialog->checkbutton_remember, FALSE);
+ }
+}
+
+static void
+gs_auth_dialog_cancel_button_cb (GtkWidget *widget, GsAuthDialog *dialog)
+{
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+}
+
+static void
+gs_auth_dialog_authenticate_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
+ GsAuthDialog *dialog = GS_AUTH_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+
+ /* we failed */
+ if (!gs_plugin_loader_app_action_finish (plugin_loader, res, &error)) {
+ const gchar *url;
+
+ /* have we been given a link */
+ url = gs_utils_get_error_value (error);
+ if (url != NULL) {
+ g_autoptr(GError) error_local = NULL;
+ g_debug ("showing link in: %s", error->message);
+ if (!gtk_show_uri (NULL, url, GDK_CURRENT_TIME, &error_local)) {
+ g_warning ("failed to show URI %s: %s",
+ url, error_local->message);
+ }
+ return;
+ }
+
+ g_warning ("failed to authenticate: %s", error->message);
+ gtk_label_set_label (GTK_LABEL (dialog->label_error), error->message);
+ gtk_widget_set_visible (dialog->box_error, TRUE);
+ return;
+ }
+
+ /* we didn't get authenticated */
+ if (!gs_auth_has_flag (dialog->auth, GS_AUTH_FLAG_VALID)) {
+ return;
+ }
+
+ /* success */
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+}
+
+static void
+gs_auth_dialog_continue_button_cb (GtkWidget *widget, GsAuthDialog *dialog)
+{
+ GsPluginLoaderAction action = GS_AUTH_ACTION_LOGIN;
+
+ /* alternate actions */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_lost_pwd)))
+ action = GS_AUTH_ACTION_LOST_PASSWORD;
+ else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_register)))
+ action = GS_AUTH_ACTION_REGISTER;
+ gs_plugin_loader_auth_action_async (dialog->plugin_loader,
+ dialog->auth,
+ action,
+ dialog->cancellable,
+ gs_auth_dialog_authenticate_cb,
+ dialog);
+}
+
+static void
+gs_auth_dialog_setup (GsAuthDialog *dialog)
+{
+
+ /* update widgets with known values */
+ if (gs_auth_get_username (dialog->auth) != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->entry_username),
+ gs_auth_get_username (dialog->auth));
+ }
+ if (gs_auth_get_password (dialog->auth) != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->entry_password),
+ gs_auth_get_password (dialog->auth));
+ }
+
+ /* refresh UI */
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_notify_username_cb (GtkEntry *entry,
+ GParamSpec *pspec,
+ GsAuthDialog *dialog)
+{
+ gs_auth_set_username (dialog->auth, gtk_entry_get_text (entry));
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_notify_password_cb (GtkEntry *entry,
+ GParamSpec *pspec,
+ GsAuthDialog *dialog)
+{
+ gs_auth_set_password (dialog->auth, gtk_entry_get_text (entry));
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_notify_pin_cb (GtkEntry *entry,
+ GParamSpec *pspec,
+ GsAuthDialog *dialog)
+{
+ gs_auth_set_pin (dialog->auth, gtk_entry_get_text (entry));
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_toggled_cb (GtkToggleButton *togglebutton, GsAuthDialog *dialog)
+{
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_remember_cb (GtkToggleButton *togglebutton, GsAuthDialog *dialog)
+{
+ if (gtk_toggle_button_get_active (togglebutton))
+ gs_auth_add_flags (dialog->auth, GS_AUTH_FLAG_REMEMBER);
+ gs_auth_dialog_check_ui (dialog);
+}
+
+static void
+gs_auth_dialog_dispose (GObject *object)
+{
+ GsAuthDialog *dialog = GS_AUTH_DIALOG (object);
+
+ g_clear_object (&dialog->plugin_loader);
+ g_clear_object (&dialog->app);
+ g_clear_object (&dialog->auth);
+
+ if (dialog->cancellable != NULL) {
+ g_cancellable_cancel (dialog->cancellable);
+ g_clear_object (&dialog->cancellable);
+ }
+
+ G_OBJECT_CLASS (gs_auth_dialog_parent_class)->dispose (object);
+}
+
+static void
+gs_auth_dialog_init (GsAuthDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+
+ dialog->cancellable = g_cancellable_new ();
+
+ g_signal_connect (dialog->entry_username, "notify::text",
+ G_CALLBACK (gs_auth_dialog_notify_username_cb), dialog);
+ g_signal_connect (dialog->entry_password, "notify::text",
+ G_CALLBACK (gs_auth_dialog_notify_password_cb), dialog);
+ g_signal_connect (dialog->entry_pin, "notify::text",
+ G_CALLBACK (gs_auth_dialog_notify_pin_cb), dialog);
+ g_signal_connect (dialog->checkbutton_remember, "toggled",
+ G_CALLBACK (gs_auth_dialog_remember_cb), dialog);
+ g_signal_connect (dialog->radiobutton_already, "toggled",
+ G_CALLBACK (gs_auth_dialog_toggled_cb), dialog);
+ g_signal_connect (dialog->radiobutton_register, "toggled",
+ G_CALLBACK (gs_auth_dialog_toggled_cb), dialog);
+ g_signal_connect (dialog->radiobutton_lost_pwd, "toggled",
+ G_CALLBACK (gs_auth_dialog_toggled_cb), dialog);
+ g_signal_connect (dialog->button_cancel, "clicked",
+ G_CALLBACK (gs_auth_dialog_cancel_button_cb), dialog);
+ g_signal_connect (dialog->button_continue, "clicked",
+ G_CALLBACK (gs_auth_dialog_continue_button_cb), dialog);
+}
+
+static void
+gs_auth_dialog_class_init (GsAuthDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gs_auth_dialog_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-auth-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, box_error);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, button_cancel);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, button_continue);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, checkbutton_remember);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, entry_password);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, entry_pin);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, entry_username);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, image_vendor);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, label_error);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, label_title);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, radiobutton_already);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, radiobutton_lost_pwd);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, radiobutton_register);
+ gtk_widget_class_bind_template_child (widget_class, GsAuthDialog, stack);
+}
+
+GtkWidget *
+gs_auth_dialog_new (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ const gchar *provider_id,
+ GError **error)
+{
+ GsAuthDialog *dialog;
+ GsAuth *auth;
+
+ /* get the authentication provider */
+ if (provider_id == NULL) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "no auth-provider given for %s",
+ gs_app_get_id (app));
+ return NULL;
+ }
+ auth = gs_plugin_loader_get_auth_by_id (plugin_loader, provider_id);
+ if (auth == NULL) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ "no auth-provider %s for %s",
+ provider_id, gs_app_get_id (app));
+ return NULL;
+ }
+
+ /* create dialog */
+ dialog = g_object_new (GS_TYPE_AUTH_DIALOG,
+ "use-header-bar", TRUE,
+ NULL);
+ dialog->plugin_loader = g_object_ref (plugin_loader);
+ dialog->app = g_object_ref (app);
+ dialog->auth = g_object_ref (auth);
+ gs_auth_dialog_setup (dialog);
+
+ return GTK_WIDGET (dialog);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-auth-dialog.h b/src/gs-auth-dialog.h
new file mode 100644
index 0000000..5487c2b
--- /dev/null
+++ b/src/gs-auth-dialog.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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.
+ */
+
+#ifndef GS_AUTH_DIALOG_H
+#define GS_AUTH_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+#include "gs-plugin-loader.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_AUTH_DIALOG (gs_auth_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsAuthDialog, gs_auth_dialog, GS, AUTH_DIALOG, GtkDialog)
+
+GtkWidget *gs_auth_dialog_new (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ const gchar *provider_id,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* GS_AUTH_DIALOG_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-auth-dialog.ui b/src/gs-auth-dialog.ui
new file mode 100644
index 0000000..ce5a411
--- /dev/null
+++ b/src/gs-auth-dialog.ui
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="GsAuthDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="deletable">False</property>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">21</property>
+ <property name="row_spacing">9</property>
+ <property name="column_spacing">21</property>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">crossfade</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="name">intro</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="row_spacing">9</property>
+ <property name="column_spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">To continue you need an %NAME% account.</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Email address</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_username">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_bottom">15</property>
+ <property name="input_purpose">email</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_already">
+ <property name="label" translatable="yes">I have an account already</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Password</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_register">
+ <property name="label" translatable="yes">I want to register for an account
now</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_already</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_lost_pwd">
+ <property name="label" translatable="yes">I have forgotten my password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">radiobutton_already</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_remember">
+ <property name="label" translatable="yes">Sign in automatically next time</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">page0</property>
+ <property name="title" translatable="yes">page0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="name">2fa</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">9</property>
+ <property name="column_spacing">9</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Enter your one-time pin for two-factor
authentication.</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">PIN</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_pin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="input_purpose">password</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">page1</property>
+ <property name="title" translatable="yes">page1</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image_vendor">
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="stock">gtk-floppy</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="height">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_error">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="icon_name">dialog-warning-symbolic</property>
+ <property name="use_fallback">True</property>
+ <property name="icon_size">5</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_error">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">The supplied credentials were not correct</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title">Authenticate</property>
+ <child>
+ <object class="GtkButton" id="button_cancel">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_continue">
+ <property name="label" translatable="yes">Continue</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkSizeGroup" id="sizegroup_buttons">
+ <widgets>
+ <widget name="button_continue"/>
+ <widget name="button_cancel"/>
+ </widgets>
+ </object>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]