Commit 2da3d9c0 authored by aviau's avatar aviau Committed by Stepan Salenikovich

Implement Ring username registration

AccountCreationWizard:
 - Users can now choose to register a username. They can also decide
   to do it later.

UsernameRegistrationBox:
 - New widget that allows to lookup usernames and see if they are
   available. It can also be used to register a username with the
   Register button.

AccountGeneralTab:
 - Display the Ring username with the UsernameRegistrationBox and allow
   registering one.

Change-Id: I0c01ee34dc3749aac8a000a0d574ea8561453cba
Tuleap: #997
[stepan.salenikovich@savoirfairelinux.com: improve lookup usernames
 code; prevent sending querries when not using blockchain]
Signed-off-by: default avatarStepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
parent 110c89c7
......@@ -252,6 +252,8 @@ SET( SRC_FILES
src/accountmigrationview.cpp
src/accountgeneraltab.h
src/accountgeneraltab.cpp
src/usernameregistrationbox.h
src/usernameregistrationbox.cpp
src/accountaudiotab.h
src/accountaudiotab.cpp
src/accountdevicestab.h
......
......@@ -34,6 +34,7 @@
#include "utils/models.h"
#include "avatarmanipulation.h"
#include "accountcreationwizard.h"
#include "usernameregistrationbox.h"
struct _AccountCreationWizard
......@@ -52,6 +53,11 @@ struct _AccountCreationWizardPrivate
{
GtkWidget *stack_account_creation;
QMetaObject::Connection account_state_changed;
QMetaObject::Connection name_registration_ended;
gboolean username_available;
QString* password;
QString* alias;
/* choose_account_type_vbox */
GtkWidget *choose_account_type_vbox;
......@@ -74,17 +80,21 @@ struct _AccountCreationWizardPrivate
GtkWidget *entry_alias;
GtkWidget *entry_password;
GtkWidget *entry_password_confirm;
GtkWidget *label_default_name;
GtkWidget *label_paceholder;
GtkWidget *button_account_creation_next;
GtkWidget *button_account_creation_previous;
GtkWidget *box_avatarselection;
GtkWidget *avatar_manipulation;
GtkWidget *label_password_error;
GtkWidget *box_username_entry;
GtkWidget *checkbutton_sign_up_blockchain;
GtkWidget *username_registration_box;
/* generating_account_spinner */
GtkWidget *vbox_generating_account_spinner;
/* registering_username_spinner */
GtkWidget *vbox_registering_username_spinner;
/* error_view */
GtkWidget *error_view;
GtkWidget *button_error_view_ok;
......@@ -163,19 +173,21 @@ account_creation_wizard_class_init(AccountCreationWizardClass *klass)
/* account creation */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, account_creation);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_account_creation_entry);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_alias);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password_confirm);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_default_name);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_paceholder);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_next);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_previous);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_avatarselection);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_password_error);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_username_entry);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, checkbutton_sign_up_blockchain);
/* generating_account_spinner */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_generating_account_spinner);
/* registering_username_spinner */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_registering_username_spinner);
/* error view */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, error_view);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_error_view_ok);
......@@ -207,6 +219,27 @@ show_error_view(AccountCreationWizard *view)
gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->error_view);
}
static void
could_not_register_username_dialog(AccountCreationWizard *view)
{
GtkWidget* dialog = gtk_message_dialog_new(
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
_("Your account was created, but we could not register your username. Try again from the settings menu.")
);
gtk_dialog_run(GTK_DIALOG (dialog));
gtk_widget_destroy(dialog);
}
static void
show_registering_on_blockchain_spinner(AccountCreationWizard *view)
{
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_registering_username_spinner);
}
static gboolean
create_ring_account(AccountCreationWizard *view,
gchar *alias,
......@@ -216,6 +249,10 @@ create_ring_account(AccountCreationWizard *view,
g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(view), G_SOURCE_REMOVE);
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
// Copy password and alias, which will be used in our callbacks
priv->password = new QString(password);
priv->alias = new QString(alias);
g_object_ref(view); // ref so its not desroyed too early
/* create account and set UPnP enabled, as its not by default in the daemon */
......@@ -275,8 +312,56 @@ create_ring_account(AccountCreationWizard *view,
QObject::disconnect(priv->account_state_changed);
account << Account::EditAction::RELOAD;
g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
g_object_unref(view);
// Now try to register the username
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain)))
{
priv->name_registration_ended = QObject::connect(
account,
&Account::nameRegistrationEnded,
[=] (NameDirectory::RegisterNameStatus status, G_GNUC_UNUSED const QString& name) {
QObject::disconnect(priv->name_registration_ended);
switch(status)
{
case NameDirectory::RegisterNameStatus::INVALID_NAME:
case NameDirectory::RegisterNameStatus::WRONG_PASSWORD:
case NameDirectory::RegisterNameStatus::ALREADY_TAKEN:
case NameDirectory::RegisterNameStatus::NETWORK_ERROR:
{
could_not_register_username_dialog(view);
}
case NameDirectory::RegisterNameStatus::SUCCESS:
{
// Reload so that the username is displayed in the settings
account << Account::EditAction::RELOAD;
break;
}
}
g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
g_object_unref(view);
}
);
show_registering_on_blockchain_spinner(view);
bool register_name_result = account->registerName(*priv->password, *priv->alias);
priv->password->clear();
priv->alias->clear();
if (register_name_result == FALSE)
{
g_debug("Could not initialize registerName operation");
could_not_register_username_dialog(view);
QObject::disconnect(priv->name_registration_ended);
g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
g_object_unref(view);
}
}
else
{
g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
g_object_unref(view);
}
break;
}
case Account::RegistrationState::INITIALIZING:
......@@ -335,23 +420,6 @@ create_existing_ring_account(AccountCreationWizard *win)
return status;
}
static void
alias_entry_changed(GtkEditable *entry, AccountCreationWizard *win)
{
g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(win));
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
const gchar *alias = gtk_entry_get_text(GTK_ENTRY(entry));
if (!alias || strlen(alias) == 0) {
gtk_widget_show(priv->label_default_name);
gtk_widget_hide(priv->label_paceholder);
} else {
gtk_widget_hide(priv->label_default_name);
gtk_widget_show(priv->label_paceholder);
}
}
static void
show_generating_account_spinner(AccountCreationWizard *view)
{
......@@ -370,7 +438,7 @@ account_creation_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWi
if (g_strcmp0(password, password_confirm) != 0)
{
gtk_widget_show(priv->label_password_error);
gtk_label_set_text(GTK_LABEL(priv->label_password_error), _("Passwords don't match"));
return;
}
......@@ -402,17 +470,6 @@ existing_account_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWi
g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_existing_ring_account, win, NULL);
}
static void
entry_alias_activated(GtkEntry *entry, AccountCreationWizard *win)
{
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
const gchar *alias = gtk_entry_get_text(GTK_ENTRY(entry));
if (strlen(alias) > 0)
gtk_button_clicked(GTK_BUTTON(priv->button_account_creation_next));
}
static void
show_choose_account_type(AccountCreationWizard *view)
{
......@@ -439,8 +496,6 @@ show_account_creation(AccountCreationWizard *win)
gtk_box_pack_start(GTK_BOX(priv->box_avatarselection), priv->avatar_manipulation, true, true, 0);
}
gtk_widget_hide(priv->label_password_error);
gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->account_creation);
}
......@@ -469,14 +524,21 @@ entries_existing_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationW
}
static void
entries_new_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationWizard *view)
entries_new_account_changed(AccountCreationWizard *view)
{
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
const gchar *username = gtk_entry_get_text(GTK_ENTRY(priv->entry_alias));
const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));
if (strlen(password) > 0 && strlen(password_confirm) > 0)
const gboolean sign_up_blockchain = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain));
if (
strlen(password) > 0 && // Password is longer than 0
strlen(password_confirm) > 0 && // Confirmation is also longer than 0
strlen(username) > 0 && // username is set
(!sign_up_blockchain || priv->username_available) // either the username must be available, or don't sign up for the blockchain
)
{
gtk_widget_set_sensitive(priv->button_account_creation_next, TRUE);
}
......@@ -487,7 +549,33 @@ entries_new_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationWizard
}
static void
build_creation_wizard_view(AccountCreationWizard *view, bool show_cancel_button)
checkbutton_sign_up_blockchain_toggled(GtkToggleButton *toggle_button, AccountCreationWizard *view)
{
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
gboolean sign_up_blockchain = gtk_toggle_button_get_active(toggle_button);
username_registration_box_set_use_blockchain(
USERNAME_REGISTRATION_BOX(priv->username_registration_box),
sign_up_blockchain
);
/* Unchecking blockchain signup when there is an empty username should
* result in activating the next button.
*/
entries_new_account_changed(view);
}
static void
username_availability_changed(AccountCreationWizard *view, gboolean username_available)
{
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
priv->username_available = username_available;
entries_new_account_changed(view);
}
static void
build_creation_wizard_view(AccountCreationWizard *view, gboolean show_cancel_button)
{
g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
......@@ -502,6 +590,15 @@ build_creation_wizard_view(AccountCreationWizard *view, bool show_cancel_button)
} else
gtk_image_set_from_pixbuf(GTK_IMAGE(priv->choose_account_type_ring_logo), logo_ring);
/* create the username_registration_box */
priv->username_registration_box = username_registration_box_new(nullptr, FALSE);
gtk_container_add(GTK_CONTAINER(priv->box_username_entry), priv->username_registration_box);
gtk_widget_show(priv->username_registration_box);
priv->entry_alias = GTK_WIDGET(
username_registration_box_get_entry(
USERNAME_REGISTRATION_BOX(priv->username_registration_box)
)
);
/* use the real name / username of the logged in user as the default */
const char* real_name = g_get_real_name();
......@@ -525,11 +622,13 @@ build_creation_wizard_view(AccountCreationWizard *view, bool show_cancel_button)
/* account_creation signals */
g_signal_connect_swapped(priv->button_account_creation_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
g_signal_connect(priv->entry_alias, "changed", G_CALLBACK(alias_entry_changed), view);
g_signal_connect_swapped(priv->entry_alias, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect(priv->button_account_creation_next, "clicked", G_CALLBACK(account_creation_next_clicked), view);
g_signal_connect(priv->entry_alias, "activate", G_CALLBACK(entry_alias_activated), view);
g_signal_connect(priv->entry_password, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect(priv->entry_password_confirm, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect_swapped(priv->entry_password, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect_swapped(priv->entry_password_confirm, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect_swapped(priv->entry_alias, "changed", G_CALLBACK(entries_new_account_changed), view);
g_signal_connect(priv->checkbutton_sign_up_blockchain, "toggled", G_CALLBACK(checkbutton_sign_up_blockchain_toggled), view);
g_signal_connect_swapped(priv->username_registration_box, "username-availability-changed", G_CALLBACK(username_availability_changed), view);
/* existing_account singals */
g_signal_connect_swapped(priv->button_existing_account_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
......
......@@ -25,7 +25,9 @@
#include <account.h>
#include <bootstrapmodel.h>
#include "defines.h"
#include "namedirectory.h"
#include "utils/models.h"
#include "usernameregistrationbox.h"
struct _AccountGeneralTab
{
......@@ -101,6 +103,14 @@ account_alias_changed(GtkEditable *entry, AccountGeneralTab *view)
priv->account->setDisplayName(gtk_entry_get_text(GTK_ENTRY(entry)));
}
static void
entry_name_service_url_changed(GtkEditable *entry, AccountGeneralTab *view)
{
g_return_if_fail(IS_ACCOUNT_GENERAL_TAB(view));
AccountGeneralTabPrivate *priv = ACCOUNT_GENERAL_TAB_GET_PRIVATE(view);
priv->account->setNameServiceURL(QString(gtk_editable_get_chars(entry, 0, -1)));
}
static void
account_hostname_changed(GtkEditable *entry, AccountGeneralTab *view)
{
......@@ -236,7 +246,6 @@ bootstrap_servers_popup_menu(G_GNUC_UNUSED GtkWidget *widget, GdkEventButton *ev
return TRUE; /* we handled the event */
}
static void
build_tab_view(AccountGeneralTab *view)
{
......@@ -297,6 +306,7 @@ build_tab_view(AccountGeneralTab *view)
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_grid_attach(GTK_GRID(priv->grid_account), label, 0, grid_row, 1, 1);
entry_username = gtk_entry_new();
gtk_widget_set_halign(entry_username, GTK_ALIGN_START);
gtk_entry_set_placeholder_text(GTK_ENTRY(entry_username), _("auto-generating..."));
gtk_entry_set_text(GTK_ENTRY(entry_username), priv->account->username().toLocal8Bit().constData());
g_object_set(G_OBJECT(entry_username), "editable", FALSE, NULL);
......@@ -305,6 +315,13 @@ build_tab_view(AccountGeneralTab *view)
gtk_entry_set_alignment(GTK_ENTRY(entry_username), 0.5);
gtk_grid_attach(GTK_GRID(priv->grid_account), entry_username, 1, grid_row, 1, 1);
++grid_row;
label = gtk_label_new("Ring username");
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_grid_attach(GTK_GRID(priv->grid_account), label, 0, grid_row, 1, 1);
auto username_registration_box = username_registration_box_new(priv->account, TRUE);
gtk_grid_attach(GTK_GRID(priv->grid_account), username_registration_box, 1, grid_row, 2, 2);
grid_row+=2;
}
gtk_widget_show_all(priv->grid_account);
......@@ -424,6 +441,18 @@ build_tab_view(AccountGeneralTab *view)
g_signal_connect(renderer, "edited", G_CALLBACK(bootstrap_server_edited), view);
++grid_row;
/* Name service */
label = gtk_label_new(_("Name service URL"));
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_grid_attach(GTK_GRID(priv->grid_parameters), label, 0, grid_row, 1, 1);
GtkWidget* entry_name_service_url = gtk_entry_new();
gtk_widget_set_halign(entry_name_service_url, GTK_ALIGN_START);
gtk_entry_set_text(GTK_ENTRY(entry_name_service_url), priv->account->nameServiceURL().toLocal8Bit().constData());
gtk_grid_attach(GTK_GRID(priv->grid_parameters), entry_name_service_url, 1, grid_row, 1, 1);
g_signal_connect(entry_name_service_url, "changed", G_CALLBACK(entry_name_service_url_changed), view);
++grid_row;
}
/* auto answer */
......
......@@ -34,6 +34,7 @@
// Ring Client
#include "avatarmanipulation.h"
#include "accountmigrationview.h"
#include "usernameregistrationbox.h"
#include "utils/models.h"
#include "native/pixbufmanipulator.h"
#include "video/video_widget.h"
......@@ -68,6 +69,11 @@ struct _AccountMigrationViewPrivate
GtkWidget *error_view;
GtkWidget *button_error_view_ok;
/* choose_username_view */
GtkWidget *choose_username_view;
GtkWidget *box_username_registration_box;
GtkWidget *button_register_username_later;
/* main_view */
GtkWidget *main_view;
GtkWidget *label_account_alias;
......@@ -130,6 +136,11 @@ account_migration_view_class_init(AccountMigrationViewClass *klass)
/* migrating_account_view */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, migrating_account_view);
/* choose_username_view */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, choose_username_view);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, box_username_registration_box);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, button_register_username_later);
/* main_view */
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, main_view);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, label_account_alias);
......@@ -177,6 +188,13 @@ button_error_view_ok_clicked(G_GNUC_UNUSED GtkButton* button, AccountMigrationVi
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_FAILED], 0);
}
static void
show_choose_username(AccountMigrationView *view)
{
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_migration), priv->choose_username_view);
}
static void
migrate_account_clicked(G_GNUC_UNUSED GtkButton* button, AccountMigrationView *view)
{
......@@ -218,7 +236,13 @@ migrate_account_clicked(G_GNUC_UNUSED GtkButton* button, AccountMigrationView *v
// Make sure that the account is ready to be displayed.
priv->account << Account::EditAction::RELOAD;
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
QObject::disconnect(priv->state_changed); // only want to emit once
g_source_remove(priv->timeout_tag); // We didn't timeout
// Propose setting a username
show_choose_username(view);
break;
}
case Account::RegistrationState::ERROR:
......@@ -256,16 +280,40 @@ password_entry_changed(G_GNUC_UNUSED GtkEntry* entry, AccountMigrationView *view
}
}
static void
account_migration_completed(AccountMigrationView *view)
{
/* This check is needed because users may close the migration view while
* the registration is still ongoing.
*/
g_return_if_fail(IS_ACCOUNT_MIGRATION_VIEW(view));
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
}
static void
button_register_username_later_clicked(G_GNUC_UNUSED GtkButton* button, AccountMigrationView *view)
{
account_migration_completed(view);
}
static void
build_migration_view(AccountMigrationView *view)
{
g_return_if_fail(IS_ACCOUNT_MIGRATION_VIEW(view));
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
/* Create the username registration box */
auto username_registration_box = username_registration_box_new(priv->account, TRUE);
gtk_widget_show(username_registration_box);
gtk_container_add(GTK_CONTAINER(priv->box_username_registration_box), username_registration_box);
g_signal_connect(priv->button_migrate_account, "clicked", G_CALLBACK(migrate_account_clicked), view);
g_signal_connect(priv->button_error_view_ok, "clicked", G_CALLBACK(button_error_view_ok_clicked), view);
g_signal_connect(priv->entry_password, "changed", G_CALLBACK(password_entry_changed), view);
g_signal_connect(priv->entry_password_confirm, "changed", G_CALLBACK(password_entry_changed), view);
g_signal_connect(priv->button_register_username_later, "clicked", G_CALLBACK(button_register_username_later_clicked), view);
g_signal_connect_swapped(username_registration_box, "username-registration-completed", G_CALLBACK(account_migration_completed), view);
gtk_label_set_text(GTK_LABEL(priv->label_account_alias), priv->account->alias().toUtf8().constData());
gtk_label_set_text(GTK_LABEL(priv->label_account_id), priv->account->id().constData());
......
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Viau <alexandre.viau@savoirfairelinux.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 3 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.
*/
// GTK+ related
#include <gtk/gtk.h>
#include <glib/gi18n.h>
// LRC
#include <account.h>
// Ring Client
#include "usernameregistrationbox.h"
#include "utils/models.h"
struct _UsernameRegistrationBox
{
GtkGrid parent;
};
struct _UsernameRegistrationBoxClass
{
GtkGridClass parent_class;
};
typedef struct _UsernameRegistrationBoxPrivate UsernameRegistrationBoxPrivate;
struct _UsernameRegistrationBoxPrivate
{
Account *account;
//Widgets
GtkWidget *entry_username;
GtkWidget *icon_username_availability;
GtkWidget *spinner;
GtkWidget *button_register_username;
GtkWidget *label_status;
QMetaObject::Connection name_registration_ended;
//Lookup variables
QMetaObject::Connection registered_name_found;
QString* username_waiting_for_lookup_result;
gint lookup_timeout;
gboolean use_blockchain;
gboolean show_register_button;
};
G_DEFINE_TYPE_WITH_PRIVATE(UsernameRegistrationBox, username_registration_box, GTK_TYPE_GRID);
#define USERNAME_REGISTRATION_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), USERNAME_REGISTRATION_BOX_TYPE, UsernameRegistrationBoxPrivate))
/* signals */
enum {
USERNAME_AVAILABILITY_CHANGED,
USERNAME_REGISTRATION_COMPLETED,
LAST_SIGNAL
};
static guint username_registration_box_signals[LAST_SIGNAL] = { 0 };
static void
username_registration_box_dispose(GObject *object)
{
auto priv = USERNAME_REGISTRATION_BOX_GET_PRIVATE(object);
QObject::disconnect(priv->registered_name_found);
QObject::disconnect(priv->name_registration_ended);
if (priv->lookup_timeout) {
g_source_remove(priv->lookup_timeout);
priv->lookup_timeout = 0;
}
G_OBJECT_CLASS(username_registration_box_parent_class)->dispose(object);
}
static void
username_registration_box_init(UsernameRegistrationBox *view)
{
gtk_widget_init_template(GTK_WIDGET(view));
auto priv = USERNAME_REGISTRATION_BOX_GET_PRIVATE(view);
priv->registered_name_found = QObject::connect(
&NameDirectory::instance(),
&NameDirectory::registeredNameFound,
[=] (const Account*, NameDirectory::LookupStatus status, const QString&, const QString& name) {
// g_debug("Name lookup ended");
if (!priv->use_blockchain)
return;
// compare to the current username entry
const auto username_lookup = gtk_entry_get_text(GTK_ENTRY(priv->entry_username));
if (name.compare(username_lookup) != 0) {
// assume result is for older lookup
return;
}
//We may now stop the spinner
gtk_spinner_stop(GTK_SPINNER(priv->spinner));
gtk_widget_hide(priv->spinner);
switch(status)
{
case NameDirectory::LookupStatus::SUCCESS:
{
gtk_widget_set_sensitive(priv->button_register_username, FALSE);
gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon_username_availability), "error", GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_widget_set_tooltip_text(priv->icon_username_availability, _("The entered username is not available"));
gtk_label_set_text(GTK_LABEL(priv->label_status), _("Username is not available"));
gtk_widget_show(priv->icon_username_availability);
g_signal_emit(G_OBJECT(view), username_registration_box_signals[USERNAME_AVAILABILITY_CHANGED], 0, FALSE);
break;
}
case NameDirectory::LookupStatus::INVALID_NAME:
{
gtk_widget_set_sensitive(priv->button_register_username, FALSE);
gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon_username_availability), "error", GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_widget_set_tooltip_text(priv->icon_username_availability, _("The entered username is not valid"));
gtk_label_set_text(GTK_LABEL(priv->label_status), _("Username is not valid"));