blob: 2dd759d154f9f1bda5b58210a6b84b1cbf0f4f45 [file] [log] [blame]
aviau6aeb4852016-08-18 16:01:09 -04001/*
2 * Copyright (C) 2016 Savoir-faire Linux Inc.
3 * Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20
21// GTK+ related
22#include <glib/gi18n.h>
23#include <gtk/gtk.h>
24
25// LRC
26#include <account.h>
27#include <codecmodel.h>
28#include <profilemodel.h>
29#include <profile.h>
30#include <accountmodel.h>
31#include <personmodel.h>
32
33// Ring Client
34#include "utils/models.h"
35#include "avatarmanipulation.h"
36#include "accountcreationwizard.h"
aviau2da3d9c2016-09-06 11:28:36 -040037#include "usernameregistrationbox.h"
aviau6aeb4852016-08-18 16:01:09 -040038
39
40struct _AccountCreationWizard
41{
42 GtkBox parent;
43};
44
45struct _AccountCreationWizardClass
46{
47 GtkBoxClass parent_class;
48};
49
50typedef struct _AccountCreationWizardPrivate AccountCreationWizardPrivate;
51
52struct _AccountCreationWizardPrivate
53{
54 GtkWidget *stack_account_creation;
55 QMetaObject::Connection account_state_changed;
aviau2da3d9c2016-09-06 11:28:36 -040056 QMetaObject::Connection name_registration_ended;
57 gboolean username_available;
58
59 QString* password;
aviau692fe6d2016-11-08 14:37:34 -050060 QString* username;
aviau6aeb4852016-08-18 16:01:09 -040061
62 /* choose_account_type_vbox */
63 GtkWidget *choose_account_type_vbox;
64 GtkWidget *choose_account_type_ring_logo;
65 GtkWidget *button_new_account;
66 GtkWidget *button_existing_account;
67 GtkWidget *button_wizard_cancel;
68
69 /* existing account */
70 GtkWidget *existing_account;
71 GtkWidget *button_existing_account_next;
72 GtkWidget *button_existing_account_previous;
73 GtkWidget *entry_existing_account_pin;
74 GtkWidget *entry_existing_account_password;
75 GtkWidget *retrieving_account;
76
77 /* account creation */
78 GtkWidget *account_creation;
79 GtkWidget *vbox_account_creation_entry;
aviau692fe6d2016-11-08 14:37:34 -050080 GtkWidget *entry_username;
aviau6aeb4852016-08-18 16:01:09 -040081 GtkWidget *entry_password;
82 GtkWidget *entry_password_confirm;
aviau6aeb4852016-08-18 16:01:09 -040083 GtkWidget *button_account_creation_next;
84 GtkWidget *button_account_creation_previous;
85 GtkWidget *box_avatarselection;
86 GtkWidget *avatar_manipulation;
87 GtkWidget *label_password_error;
aviau2da3d9c2016-09-06 11:28:36 -040088 GtkWidget *box_username_entry;
89 GtkWidget *checkbutton_sign_up_blockchain;
90 GtkWidget *username_registration_box;
aviau692fe6d2016-11-08 14:37:34 -050091 GtkWidget *entry_display_name;
aviau6aeb4852016-08-18 16:01:09 -040092
93 /* generating_account_spinner */
94 GtkWidget *vbox_generating_account_spinner;
95
aviau2da3d9c2016-09-06 11:28:36 -040096 /* registering_username_spinner */
97 GtkWidget *vbox_registering_username_spinner;
98
aviau6aeb4852016-08-18 16:01:09 -040099 /* error_view */
100 GtkWidget *error_view;
101 GtkWidget *button_error_view_ok;
102
103};
104
105G_DEFINE_TYPE_WITH_PRIVATE(AccountCreationWizard, account_creation_wizard, GTK_TYPE_BOX);
106
107#define ACCOUNT_CREATION_WIZARD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_CREATION_WIZARD_TYPE, AccountCreationWizardPrivate))
108
109/* signals */
110enum {
111 ACCOUNT_CREATION_CANCELED,
112 ACCOUNT_CREATION_COMPLETED,
113 LAST_SIGNAL
114};
115
116static guint account_creation_wizard_signals[LAST_SIGNAL] = { 0 };
117
118static void
119destroy_avatar_manipulation(AccountCreationWizard *view)
120{
121 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
122
123 /* make sure the AvatarManipulation widget is destroyed so the VideoWidget inside of it is too;
124 * NOTE: destorying its parent (box_avatarselection) first will cause a mystery 'BadDrawable'
125 * crash due to X error */
126 if (priv->avatar_manipulation)
127 {
128 gtk_container_remove(GTK_CONTAINER(priv->box_avatarselection), priv->avatar_manipulation);
129 priv->avatar_manipulation = nullptr;
130 }
131}
132
133static void
134account_creation_wizard_dispose(GObject *object)
135{
136 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(object);
137 destroy_avatar_manipulation(ACCOUNT_CREATION_WIZARD(object));
138 QObject::disconnect(priv->account_state_changed);
139 G_OBJECT_CLASS(account_creation_wizard_parent_class)->dispose(object);
140}
141
142static void
143account_creation_wizard_init(AccountCreationWizard *view)
144{
145 gtk_widget_init_template(GTK_WIDGET(view));
146}
147
148static void
149account_creation_wizard_class_init(AccountCreationWizardClass *klass)
150{
151 G_OBJECT_CLASS(klass)->dispose = account_creation_wizard_dispose;
152
153 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
154 "/cx/ring/RingGnome/accountcreationwizard.ui");
155
156 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, stack_account_creation);
157
158 /* choose_account_type_vbox */
159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_vbox);
160 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_ring_logo);
161 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_new_account);
162 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account);
163 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_wizard_cancel);
164
165 /* existing account */
166 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, existing_account);
167 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account_next);
168 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account_previous);
169 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_pin);
170 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_password);
171 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_password);
172 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, retrieving_account);
173
174 /* account creation */
175 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, account_creation);
176 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_account_creation_entry);
aviau6aeb4852016-08-18 16:01:09 -0400177 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password);
178 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password_confirm);
aviau6aeb4852016-08-18 16:01:09 -0400179 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_next);
180 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_previous);
181 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_avatarselection);
182 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_password_error);
aviau2da3d9c2016-09-06 11:28:36 -0400183 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_username_entry);
184 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, checkbutton_sign_up_blockchain);
aviau692fe6d2016-11-08 14:37:34 -0500185 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_display_name);
aviau6aeb4852016-08-18 16:01:09 -0400186
187 /* generating_account_spinner */
188 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_generating_account_spinner);
189
aviau2da3d9c2016-09-06 11:28:36 -0400190 /* registering_username_spinner */
191 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_registering_username_spinner);
192
aviau6aeb4852016-08-18 16:01:09 -0400193 /* error view */
194 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, error_view);
195 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_error_view_ok);
196
197 /* add signals */
198 account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED] = g_signal_new("account-creation-completed",
199 G_TYPE_FROM_CLASS(klass),
200 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
201 0,
202 nullptr,
203 nullptr,
204 g_cclosure_marshal_VOID__VOID,
205 G_TYPE_NONE, 0);
206
207 account_creation_wizard_signals[ACCOUNT_CREATION_CANCELED] = g_signal_new("account-creation-canceled",
208 G_TYPE_FROM_CLASS(klass),
209 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
210 0,
211 nullptr,
212 nullptr,
213 g_cclosure_marshal_VOID__VOID,
214 G_TYPE_NONE, 0);
215}
216
217static void
218show_error_view(AccountCreationWizard *view)
219{
220 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
221 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->error_view);
222}
223
aviau2da3d9c2016-09-06 11:28:36 -0400224static void
225could_not_register_username_dialog(AccountCreationWizard *view)
226{
227 GtkWidget* dialog = gtk_message_dialog_new(
228 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))),
229 GTK_DIALOG_DESTROY_WITH_PARENT,
230 GTK_MESSAGE_ERROR,
231 GTK_BUTTONS_OK,
232 _("Your account was created, but we could not register your username. Try again from the settings menu.")
233 );
234 gtk_dialog_run(GTK_DIALOG (dialog));
235 gtk_widget_destroy(dialog);
236}
237
238static void
239show_registering_on_blockchain_spinner(AccountCreationWizard *view)
240{
241 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
242 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_registering_username_spinner);
243}
244
aviau6aeb4852016-08-18 16:01:09 -0400245static gboolean
246create_ring_account(AccountCreationWizard *view,
aviau692fe6d2016-11-08 14:37:34 -0500247 gchar *display_name,
248 gchar *username,
aviau6aeb4852016-08-18 16:01:09 -0400249 gchar *password,
250 gchar *pin)
251{
aviau692fe6d2016-11-08 14:37:34 -0500252
aviau6aeb4852016-08-18 16:01:09 -0400253 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(view), G_SOURCE_REMOVE);
254 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
255
aviau2da3d9c2016-09-06 11:28:36 -0400256 // Copy password and alias, which will be used in our callbacks
aviau692fe6d2016-11-08 14:37:34 -0500257 priv->username = new QString(username);
aviau2da3d9c2016-09-06 11:28:36 -0400258 priv->password = new QString(password);
aviau2da3d9c2016-09-06 11:28:36 -0400259
aviau6aeb4852016-08-18 16:01:09 -0400260 g_object_ref(view); // ref so its not desroyed too early
261
262 /* create account and set UPnP enabled, as its not by default in the daemon */
263 Account *account = nullptr;
264
265 /* get profile (if so) */
266 auto profile = ProfileModel::instance().selectedProfile();
267
aviau692fe6d2016-11-08 14:37:34 -0500268 if (display_name && strlen(display_name) > 0) {
269 account = AccountModel::instance().add(display_name, Account::Protocol::RING);
aviau6aeb4852016-08-18 16:01:09 -0400270 if(profile && AccountModel::instance().size() == 1)
271 {
aviau692fe6d2016-11-08 14:37:34 -0500272 profile->person()->setFormattedName(display_name);
aviau6aeb4852016-08-18 16:01:09 -0400273 }
274 } else {
275 auto unknown_alias = C_("The default username / account alias, if none is set by the user", "Unknown");
276 account = AccountModel::instance().add(unknown_alias, Account::Protocol::RING);
277 if (profile && AccountModel::instance().size() == 1)
278 {
279 profile->person()->setFormattedName(unknown_alias);
280 }
281 }
282
283 /* Set the archive password */
284 account->setArchivePassword(password);
285
286 /* Set the archive pin (existng accounts) */
287 if(pin)
288 {
289 account->setArchivePin(pin);
290 }
291
aviau692fe6d2016-11-08 14:37:34 -0500292 account->setDisplayName(display_name); // set the display name to the same as the alias
aviau6aeb4852016-08-18 16:01:09 -0400293
294 account->setUpnpEnabled(TRUE);
295
296 /* show error window if the account errors */
297 priv->account_state_changed = QObject::connect(
298 account,
299 &Account::stateChanged,
300 [=] (Account::RegistrationState state) {
301 switch(state)
302 {
303 case Account::RegistrationState::ERROR:
304 {
305 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
306 QObject::disconnect(priv->account_state_changed);
307 show_error_view(view);
308 g_object_unref(view);
309 break;
310 }
311 case Account::RegistrationState::READY:
312 case Account::RegistrationState::TRYING:
313 case Account::RegistrationState::UNREGISTERED:
314 {
315 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
316 QObject::disconnect(priv->account_state_changed);
317
318 account << Account::EditAction::RELOAD;
aviau2da3d9c2016-09-06 11:28:36 -0400319
320 // Now try to register the username
aviau692fe6d2016-11-08 14:37:34 -0500321 if (priv->username && !priv->username->isEmpty() && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain)))
aviau2da3d9c2016-09-06 11:28:36 -0400322 {
323 priv->name_registration_ended = QObject::connect(
324 account,
325 &Account::nameRegistrationEnded,
326 [=] (NameDirectory::RegisterNameStatus status, G_GNUC_UNUSED const QString& name) {
327 QObject::disconnect(priv->name_registration_ended);
328 switch(status)
329 {
330 case NameDirectory::RegisterNameStatus::INVALID_NAME:
331 case NameDirectory::RegisterNameStatus::WRONG_PASSWORD:
332 case NameDirectory::RegisterNameStatus::ALREADY_TAKEN:
333 case NameDirectory::RegisterNameStatus::NETWORK_ERROR:
334 {
335 could_not_register_username_dialog(view);
336 }
337 case NameDirectory::RegisterNameStatus::SUCCESS:
338 {
339 // Reload so that the username is displayed in the settings
340 account << Account::EditAction::RELOAD;
341 break;
342 }
343 }
344 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
345 g_object_unref(view);
346 }
347 );
348
349 show_registering_on_blockchain_spinner(view);
350
aviau692fe6d2016-11-08 14:37:34 -0500351 bool register_name_result = account->registerName(*priv->password, *priv->username);
352 priv->username->clear();
aviau2da3d9c2016-09-06 11:28:36 -0400353 priv->password->clear();
aviau2da3d9c2016-09-06 11:28:36 -0400354
355 if (register_name_result == FALSE)
356 {
357 g_debug("Could not initialize registerName operation");
358 could_not_register_username_dialog(view);
359 QObject::disconnect(priv->name_registration_ended);
360 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
361 g_object_unref(view);
362 }
363 }
364 else
365 {
366 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
367 g_object_unref(view);
368 }
aviau6aeb4852016-08-18 16:01:09 -0400369 break;
370 }
371 case Account::RegistrationState::INITIALIZING:
372 case Account::RegistrationState::COUNT__:
373 {
374 // Keep waiting...
375 break;
376 }
377 }
378 }
379 );
380
381 account->performAction(Account::EditAction::SAVE);
382 profile->save();
383
384 return G_SOURCE_REMOVE;
385}
386
387static gboolean
388create_new_ring_account(AccountCreationWizard *win)
389{
390 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
391 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
392
aviau692fe6d2016-11-08 14:37:34 -0500393 gchar *display_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_display_name)));
394 gchar *username = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_username)));
aviau6aeb4852016-08-18 16:01:09 -0400395 gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_password)));
396 gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
397 gtk_entry_set_text(GTK_ENTRY(priv->entry_password_confirm), "");
398
aviau692fe6d2016-11-08 14:37:34 -0500399 auto status = create_ring_account(win, display_name, username, password, NULL);
aviau6aeb4852016-08-18 16:01:09 -0400400
aviau692fe6d2016-11-08 14:37:34 -0500401 g_free(display_name);
aviau6aeb4852016-08-18 16:01:09 -0400402 g_free(password);
aviau692fe6d2016-11-08 14:37:34 -0500403 g_free(username);
aviau6aeb4852016-08-18 16:01:09 -0400404
405 return status;
406}
407
408static gboolean
409create_existing_ring_account(AccountCreationWizard *win)
410{
411 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
412 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
413
414 gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_password)));
415 gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_password), "");
416
417 gchar *pin = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin)));
418 gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_pin), "");
419
aviau692fe6d2016-11-08 14:37:34 -0500420 auto status = create_ring_account(win, NULL, NULL, password, pin);
aviau6aeb4852016-08-18 16:01:09 -0400421
422 g_free(password);
423 g_free(pin);
424
425 return status;
426}
427
aviau6aeb4852016-08-18 16:01:09 -0400428static void
429show_generating_account_spinner(AccountCreationWizard *view)
430{
431 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
432 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_generating_account_spinner);
433}
434
435static void
436account_creation_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
437{
438 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
439
440 /* Check for correct password */
441 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
442 const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));
443
444 if (g_strcmp0(password, password_confirm) != 0)
445 {
aviau2da3d9c2016-09-06 11:28:36 -0400446 gtk_label_set_text(GTK_LABEL(priv->label_password_error), _("Passwords don't match"));
aviau6aeb4852016-08-18 16:01:09 -0400447 return;
448 }
449
450 show_generating_account_spinner(win);
451
452 /* now create account after a short timeout so that the the save doesn't
453 * happen freeze the client before the widget changes happen;
454 * the timeout function should then display the next step in account creation
455 */
456 g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_new_ring_account, win, NULL);
457}
458
459static void
460show_retrieving_account(AccountCreationWizard *win)
461{
462 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
463 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->retrieving_account);
464}
465
466static void
467existing_account_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
468{
469 show_retrieving_account(win);
470
471 /* now create account after a short timeout so that the the save doesn't
472 * happen freeze the client before the widget changes happen;
473 * the timeout function should then display the next step in account creation
474 */
475 g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_existing_ring_account, win, NULL);
476}
477
478static void
aviau6aeb4852016-08-18 16:01:09 -0400479show_choose_account_type(AccountCreationWizard *view)
480{
481 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
482 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->choose_account_type_vbox);
483}
484
485static void
486show_existing_account(AccountCreationWizard *view)
487{
488 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
489 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->existing_account);
490}
491
492static void
493show_account_creation(AccountCreationWizard *win)
494{
495 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
496
497 /* avatar manipulation widget */
498 if (!priv->avatar_manipulation)
499 {
500 priv->avatar_manipulation = avatar_manipulation_new_from_wizard();
501 gtk_box_pack_start(GTK_BOX(priv->box_avatarselection), priv->avatar_manipulation, true, true, 0);
502 }
503
aviau6aeb4852016-08-18 16:01:09 -0400504 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->account_creation);
505}
506
507static void
508wizard_cancel_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
509{
510 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_CANCELED], 0);
511}
512
513static void
514entries_existing_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationWizard *view)
515{
516 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
517
518 const gchar *pin = gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin));
519 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_password));
520
521 if (strlen(pin) > 0 && strlen(password) > 0)
522 {
523 gtk_widget_set_sensitive(priv->button_existing_account_next, TRUE);
524 }
525 else
526 {
527 gtk_widget_set_sensitive(priv->button_existing_account_next, FALSE);
528 }
529}
530
531static void
aviau2da3d9c2016-09-06 11:28:36 -0400532entries_new_account_changed(AccountCreationWizard *view)
aviau6aeb4852016-08-18 16:01:09 -0400533{
534 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
535
aviau692fe6d2016-11-08 14:37:34 -0500536 const gchar *display_name = gtk_entry_get_text(GTK_ENTRY(priv->entry_display_name));
537 const gchar *username = gtk_entry_get_text(GTK_ENTRY(priv->entry_username));
aviau6aeb4852016-08-18 16:01:09 -0400538 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
539 const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));
aviau2da3d9c2016-09-06 11:28:36 -0400540 const gboolean sign_up_blockchain = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain));
aviau6aeb4852016-08-18 16:01:09 -0400541
aviau2da3d9c2016-09-06 11:28:36 -0400542 if (
aviau692fe6d2016-11-08 14:37:34 -0500543 strlen(display_name) > 0 && // Display name is longer than 0
aviau2da3d9c2016-09-06 11:28:36 -0400544 strlen(password) > 0 && // Password is longer than 0
545 strlen(password_confirm) > 0 && // Confirmation is also longer than 0
aviau692fe6d2016-11-08 14:37:34 -0500546 (
547 (sign_up_blockchain && strlen(username) > 0 && priv->username_available) || // we are signing up, username is set and avaialble
548 !sign_up_blockchain // We are not signing up
549 )
aviau2da3d9c2016-09-06 11:28:36 -0400550 )
aviau6aeb4852016-08-18 16:01:09 -0400551 {
552 gtk_widget_set_sensitive(priv->button_account_creation_next, TRUE);
553 }
554 else
555 {
556 gtk_widget_set_sensitive(priv->button_account_creation_next, FALSE);
557 }
558}
559
560static void
aviau2da3d9c2016-09-06 11:28:36 -0400561checkbutton_sign_up_blockchain_toggled(GtkToggleButton *toggle_button, AccountCreationWizard *view)
562{
563 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
564 gboolean sign_up_blockchain = gtk_toggle_button_get_active(toggle_button);
565
566
567 username_registration_box_set_use_blockchain(
568 USERNAME_REGISTRATION_BOX(priv->username_registration_box),
569 sign_up_blockchain
570 );
571
aviau692fe6d2016-11-08 14:37:34 -0500572 gtk_widget_set_sensitive(priv->entry_username, sign_up_blockchain);
573
574 if (!sign_up_blockchain)
575 {
576 gtk_entry_set_text(GTK_ENTRY(priv->entry_username), "");
577 }
578
aviau2da3d9c2016-09-06 11:28:36 -0400579 /* Unchecking blockchain signup when there is an empty username should
580 * result in activating the next button.
581 */
582 entries_new_account_changed(view);
583}
584
585static void
586username_availability_changed(AccountCreationWizard *view, gboolean username_available)
587{
588 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
589 priv->username_available = username_available;
590 entries_new_account_changed(view);
591}
592
593static void
594build_creation_wizard_view(AccountCreationWizard *view, gboolean show_cancel_button)
aviau6aeb4852016-08-18 16:01:09 -0400595{
596 g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
597 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
598
599 /* set ring logo */
600 GError *error = NULL;
601 GdkPixbuf* logo_ring = gdk_pixbuf_new_from_resource_at_scale("/cx/ring/RingGnome/ring-logo-blue",
602 -1, 50, TRUE, &error);
603 if (logo_ring == NULL) {
604 g_debug("Could not load logo: %s", error->message);
605 g_clear_error(&error);
606 } else
607 gtk_image_set_from_pixbuf(GTK_IMAGE(priv->choose_account_type_ring_logo), logo_ring);
608
aviau2da3d9c2016-09-06 11:28:36 -0400609 /* create the username_registration_box */
610 priv->username_registration_box = username_registration_box_new(nullptr, FALSE);
611 gtk_container_add(GTK_CONTAINER(priv->box_username_entry), priv->username_registration_box);
612 gtk_widget_show(priv->username_registration_box);
aviau692fe6d2016-11-08 14:37:34 -0500613 priv->entry_username = GTK_WIDGET(
aviau2da3d9c2016-09-06 11:28:36 -0400614 username_registration_box_get_entry(
615 USERNAME_REGISTRATION_BOX(priv->username_registration_box)
616 )
617 );
aviau6aeb4852016-08-18 16:01:09 -0400618
619 /* use the real name / username of the logged in user as the default */
620 const char* real_name = g_get_real_name();
621 const char* user_name = g_get_user_name();
622 g_debug("real_name = %s",real_name);
623 g_debug("user_name = %s",user_name);
624
625 /* check first if the real name was determined */
626 if (g_strcmp0 (real_name,"Unknown") != 0)
aviau692fe6d2016-11-08 14:37:34 -0500627 gtk_entry_set_text(GTK_ENTRY(priv->entry_display_name), real_name);
aviau6aeb4852016-08-18 16:01:09 -0400628 else
aviau692fe6d2016-11-08 14:37:34 -0500629 gtk_entry_set_text(GTK_ENTRY(priv->entry_display_name), user_name);
630
631 gtk_entry_set_placeholder_text(GTK_ENTRY(priv->entry_username), user_name);
aviau6aeb4852016-08-18 16:01:09 -0400632
633 /* cancel button */
634 gtk_widget_set_visible(priv->button_wizard_cancel, show_cancel_button);
635
636 /* choose_account_type signals */
637 g_signal_connect_swapped(priv->button_new_account, "clicked", G_CALLBACK(show_account_creation), view);
638 g_signal_connect_swapped(priv->button_existing_account, "clicked", G_CALLBACK(show_existing_account), view);
639 g_signal_connect(priv->button_wizard_cancel, "clicked", G_CALLBACK(wizard_cancel_clicked), view);
640
641 /* account_creation signals */
642 g_signal_connect_swapped(priv->button_account_creation_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
aviau692fe6d2016-11-08 14:37:34 -0500643 g_signal_connect_swapped(priv->entry_username, "changed", G_CALLBACK(entries_new_account_changed), view);
aviau6aeb4852016-08-18 16:01:09 -0400644 g_signal_connect(priv->button_account_creation_next, "clicked", G_CALLBACK(account_creation_next_clicked), view);
aviau2da3d9c2016-09-06 11:28:36 -0400645 g_signal_connect_swapped(priv->entry_password, "changed", G_CALLBACK(entries_new_account_changed), view);
646 g_signal_connect_swapped(priv->entry_password_confirm, "changed", G_CALLBACK(entries_new_account_changed), view);
aviau692fe6d2016-11-08 14:37:34 -0500647 g_signal_connect_swapped(priv->entry_username, "changed", G_CALLBACK(entries_new_account_changed), view);
648 g_signal_connect_swapped(priv->entry_display_name, "changed", G_CALLBACK(entries_new_account_changed), view);
aviau2da3d9c2016-09-06 11:28:36 -0400649 g_signal_connect(priv->checkbutton_sign_up_blockchain, "toggled", G_CALLBACK(checkbutton_sign_up_blockchain_toggled), view);
650 g_signal_connect_swapped(priv->username_registration_box, "username-availability-changed", G_CALLBACK(username_availability_changed), view);
aviau6aeb4852016-08-18 16:01:09 -0400651
652 /* existing_account singals */
653 g_signal_connect_swapped(priv->button_existing_account_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
654 g_signal_connect(priv->button_existing_account_next, "clicked", G_CALLBACK(existing_account_next_clicked), view);
655 g_signal_connect(priv->entry_existing_account_pin, "changed", G_CALLBACK(entries_existing_account_changed), view);
656 g_signal_connect(priv->entry_existing_account_password, "changed", G_CALLBACK(entries_existing_account_changed), view);
657
658 /* error_view signals */
659 g_signal_connect_swapped(priv->button_error_view_ok, "clicked", G_CALLBACK(show_choose_account_type), view);
660
661 show_choose_account_type(view);
662}
663
664GtkWidget *
665account_creation_wizard_new(bool show_cancel_button)
666{
667 gpointer view = g_object_new(ACCOUNT_CREATION_WIZARD_TYPE, NULL);
668
669 build_creation_wizard_view(ACCOUNT_CREATION_WIZARD(view), show_cancel_button);
670 return (GtkWidget *)view;
671}