blob: 2c800a6d2f09fe0be603081640b60ae96ca3918a [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;
60 QString* alias;
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;
80 GtkWidget *entry_alias;
81 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;
aviau6aeb4852016-08-18 16:01:09 -040091
92 /* generating_account_spinner */
93 GtkWidget *vbox_generating_account_spinner;
94
aviau2da3d9c2016-09-06 11:28:36 -040095 /* registering_username_spinner */
96 GtkWidget *vbox_registering_username_spinner;
97
aviau6aeb4852016-08-18 16:01:09 -040098 /* error_view */
99 GtkWidget *error_view;
100 GtkWidget *button_error_view_ok;
101
102};
103
104G_DEFINE_TYPE_WITH_PRIVATE(AccountCreationWizard, account_creation_wizard, GTK_TYPE_BOX);
105
106#define ACCOUNT_CREATION_WIZARD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_CREATION_WIZARD_TYPE, AccountCreationWizardPrivate))
107
108/* signals */
109enum {
110 ACCOUNT_CREATION_CANCELED,
111 ACCOUNT_CREATION_COMPLETED,
112 LAST_SIGNAL
113};
114
115static guint account_creation_wizard_signals[LAST_SIGNAL] = { 0 };
116
117static void
118destroy_avatar_manipulation(AccountCreationWizard *view)
119{
120 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
121
122 /* make sure the AvatarManipulation widget is destroyed so the VideoWidget inside of it is too;
123 * NOTE: destorying its parent (box_avatarselection) first will cause a mystery 'BadDrawable'
124 * crash due to X error */
125 if (priv->avatar_manipulation)
126 {
127 gtk_container_remove(GTK_CONTAINER(priv->box_avatarselection), priv->avatar_manipulation);
128 priv->avatar_manipulation = nullptr;
129 }
130}
131
132static void
133account_creation_wizard_dispose(GObject *object)
134{
135 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(object);
136 destroy_avatar_manipulation(ACCOUNT_CREATION_WIZARD(object));
137 QObject::disconnect(priv->account_state_changed);
138 G_OBJECT_CLASS(account_creation_wizard_parent_class)->dispose(object);
139}
140
141static void
142account_creation_wizard_init(AccountCreationWizard *view)
143{
144 gtk_widget_init_template(GTK_WIDGET(view));
145}
146
147static void
148account_creation_wizard_class_init(AccountCreationWizardClass *klass)
149{
150 G_OBJECT_CLASS(klass)->dispose = account_creation_wizard_dispose;
151
152 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
153 "/cx/ring/RingGnome/accountcreationwizard.ui");
154
155 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, stack_account_creation);
156
157 /* choose_account_type_vbox */
158 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_vbox);
159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_ring_logo);
160 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_new_account);
161 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account);
162 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_wizard_cancel);
163
164 /* existing account */
165 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, existing_account);
166 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account_next);
167 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_existing_account_previous);
168 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_pin);
169 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_password);
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, retrieving_account);
172
173 /* account creation */
174 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, account_creation);
175 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_account_creation_entry);
aviau6aeb4852016-08-18 16:01:09 -0400176 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password);
177 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password_confirm);
aviau6aeb4852016-08-18 16:01:09 -0400178 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_next);
179 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_previous);
180 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_avatarselection);
181 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_password_error);
aviau2da3d9c2016-09-06 11:28:36 -0400182 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_username_entry);
183 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, checkbutton_sign_up_blockchain);
aviau6aeb4852016-08-18 16:01:09 -0400184
185 /* generating_account_spinner */
186 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_generating_account_spinner);
187
aviau2da3d9c2016-09-06 11:28:36 -0400188 /* registering_username_spinner */
189 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_registering_username_spinner);
190
aviau6aeb4852016-08-18 16:01:09 -0400191 /* error view */
192 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, error_view);
193 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_error_view_ok);
194
195 /* add signals */
196 account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED] = g_signal_new("account-creation-completed",
197 G_TYPE_FROM_CLASS(klass),
198 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
199 0,
200 nullptr,
201 nullptr,
202 g_cclosure_marshal_VOID__VOID,
203 G_TYPE_NONE, 0);
204
205 account_creation_wizard_signals[ACCOUNT_CREATION_CANCELED] = g_signal_new("account-creation-canceled",
206 G_TYPE_FROM_CLASS(klass),
207 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
208 0,
209 nullptr,
210 nullptr,
211 g_cclosure_marshal_VOID__VOID,
212 G_TYPE_NONE, 0);
213}
214
215static void
216show_error_view(AccountCreationWizard *view)
217{
218 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
219 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->error_view);
220}
221
aviau2da3d9c2016-09-06 11:28:36 -0400222static void
223could_not_register_username_dialog(AccountCreationWizard *view)
224{
225 GtkWidget* dialog = gtk_message_dialog_new(
226 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))),
227 GTK_DIALOG_DESTROY_WITH_PARENT,
228 GTK_MESSAGE_ERROR,
229 GTK_BUTTONS_OK,
230 _("Your account was created, but we could not register your username. Try again from the settings menu.")
231 );
232 gtk_dialog_run(GTK_DIALOG (dialog));
233 gtk_widget_destroy(dialog);
234}
235
236static void
237show_registering_on_blockchain_spinner(AccountCreationWizard *view)
238{
239 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
240 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_registering_username_spinner);
241}
242
aviau6aeb4852016-08-18 16:01:09 -0400243static gboolean
244create_ring_account(AccountCreationWizard *view,
245 gchar *alias,
246 gchar *password,
247 gchar *pin)
248{
249 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(view), G_SOURCE_REMOVE);
250 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
251
aviau2da3d9c2016-09-06 11:28:36 -0400252 // Copy password and alias, which will be used in our callbacks
253 priv->password = new QString(password);
254 priv->alias = new QString(alias);
255
aviau6aeb4852016-08-18 16:01:09 -0400256 g_object_ref(view); // ref so its not desroyed too early
257
258 /* create account and set UPnP enabled, as its not by default in the daemon */
259 Account *account = nullptr;
260
261 /* get profile (if so) */
262 auto profile = ProfileModel::instance().selectedProfile();
263
264 if (alias && strlen(alias) > 0) {
265 account = AccountModel::instance().add(alias, Account::Protocol::RING);
266 if(profile && AccountModel::instance().size() == 1)
267 {
268 profile->person()->setFormattedName(alias);
269 }
270 } else {
271 auto unknown_alias = C_("The default username / account alias, if none is set by the user", "Unknown");
272 account = AccountModel::instance().add(unknown_alias, Account::Protocol::RING);
273 if (profile && AccountModel::instance().size() == 1)
274 {
275 profile->person()->setFormattedName(unknown_alias);
276 }
277 }
278
279 /* Set the archive password */
280 account->setArchivePassword(password);
281
282 /* Set the archive pin (existng accounts) */
283 if(pin)
284 {
285 account->setArchivePin(pin);
286 }
287
288 account->setDisplayName(alias); // set the display name to the same as the alias
289
290 account->setUpnpEnabled(TRUE);
291
292 /* show error window if the account errors */
293 priv->account_state_changed = QObject::connect(
294 account,
295 &Account::stateChanged,
296 [=] (Account::RegistrationState state) {
297 switch(state)
298 {
299 case Account::RegistrationState::ERROR:
300 {
301 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
302 QObject::disconnect(priv->account_state_changed);
303 show_error_view(view);
304 g_object_unref(view);
305 break;
306 }
307 case Account::RegistrationState::READY:
308 case Account::RegistrationState::TRYING:
309 case Account::RegistrationState::UNREGISTERED:
310 {
311 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
312 QObject::disconnect(priv->account_state_changed);
313
314 account << Account::EditAction::RELOAD;
aviau2da3d9c2016-09-06 11:28:36 -0400315
316 // Now try to register the username
317 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain)))
318 {
319 priv->name_registration_ended = QObject::connect(
320 account,
321 &Account::nameRegistrationEnded,
322 [=] (NameDirectory::RegisterNameStatus status, G_GNUC_UNUSED const QString& name) {
323 QObject::disconnect(priv->name_registration_ended);
324 switch(status)
325 {
326 case NameDirectory::RegisterNameStatus::INVALID_NAME:
327 case NameDirectory::RegisterNameStatus::WRONG_PASSWORD:
328 case NameDirectory::RegisterNameStatus::ALREADY_TAKEN:
329 case NameDirectory::RegisterNameStatus::NETWORK_ERROR:
330 {
331 could_not_register_username_dialog(view);
332 }
333 case NameDirectory::RegisterNameStatus::SUCCESS:
334 {
335 // Reload so that the username is displayed in the settings
336 account << Account::EditAction::RELOAD;
337 break;
338 }
339 }
340 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
341 g_object_unref(view);
342 }
343 );
344
345 show_registering_on_blockchain_spinner(view);
346
347 bool register_name_result = account->registerName(*priv->password, *priv->alias);
348 priv->password->clear();
349 priv->alias->clear();
350
351 if (register_name_result == FALSE)
352 {
353 g_debug("Could not initialize registerName operation");
354 could_not_register_username_dialog(view);
355 QObject::disconnect(priv->name_registration_ended);
356 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
357 g_object_unref(view);
358 }
359 }
360 else
361 {
362 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
363 g_object_unref(view);
364 }
aviau6aeb4852016-08-18 16:01:09 -0400365 break;
366 }
367 case Account::RegistrationState::INITIALIZING:
368 case Account::RegistrationState::COUNT__:
369 {
370 // Keep waiting...
371 break;
372 }
373 }
374 }
375 );
376
377 account->performAction(Account::EditAction::SAVE);
378 profile->save();
379
380 return G_SOURCE_REMOVE;
381}
382
383static gboolean
384create_new_ring_account(AccountCreationWizard *win)
385{
386 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
387 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
388
389 gchar *alias = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_alias)));
390
391 gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_password)));
392 gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
393 gtk_entry_set_text(GTK_ENTRY(priv->entry_password_confirm), "");
394
395 auto status = create_ring_account(win, alias, password, NULL);
396
397 g_free(alias);
398 g_free(password);
399
400 return status;
401}
402
403static gboolean
404create_existing_ring_account(AccountCreationWizard *win)
405{
406 g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
407 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
408
409 gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_password)));
410 gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_password), "");
411
412 gchar *pin = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin)));
413 gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_pin), "");
414
415 auto status = create_ring_account(win, NULL, password, pin);
416
417 g_free(password);
418 g_free(pin);
419
420 return status;
421}
422
aviau6aeb4852016-08-18 16:01:09 -0400423static void
424show_generating_account_spinner(AccountCreationWizard *view)
425{
426 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
427 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_generating_account_spinner);
428}
429
430static void
431account_creation_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
432{
433 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
434
435 /* Check for correct password */
436 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
437 const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));
438
439 if (g_strcmp0(password, password_confirm) != 0)
440 {
aviau2da3d9c2016-09-06 11:28:36 -0400441 gtk_label_set_text(GTK_LABEL(priv->label_password_error), _("Passwords don't match"));
aviau6aeb4852016-08-18 16:01:09 -0400442 return;
443 }
444
445 show_generating_account_spinner(win);
446
447 /* now create account after a short timeout so that the the save doesn't
448 * happen freeze the client before the widget changes happen;
449 * the timeout function should then display the next step in account creation
450 */
451 g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_new_ring_account, win, NULL);
452}
453
454static void
455show_retrieving_account(AccountCreationWizard *win)
456{
457 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
458 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->retrieving_account);
459}
460
461static void
462existing_account_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
463{
464 show_retrieving_account(win);
465
466 /* now create account after a short timeout so that the the save doesn't
467 * happen freeze the client before the widget changes happen;
468 * the timeout function should then display the next step in account creation
469 */
470 g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_existing_ring_account, win, NULL);
471}
472
473static void
aviau6aeb4852016-08-18 16:01:09 -0400474show_choose_account_type(AccountCreationWizard *view)
475{
476 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
477 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->choose_account_type_vbox);
478}
479
480static void
481show_existing_account(AccountCreationWizard *view)
482{
483 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
484 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->existing_account);
485}
486
487static void
488show_account_creation(AccountCreationWizard *win)
489{
490 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
491
492 /* avatar manipulation widget */
493 if (!priv->avatar_manipulation)
494 {
495 priv->avatar_manipulation = avatar_manipulation_new_from_wizard();
496 gtk_box_pack_start(GTK_BOX(priv->box_avatarselection), priv->avatar_manipulation, true, true, 0);
497 }
498
aviau6aeb4852016-08-18 16:01:09 -0400499 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->account_creation);
500}
501
502static void
503wizard_cancel_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
504{
505 g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_CANCELED], 0);
506}
507
508static void
509entries_existing_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationWizard *view)
510{
511 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
512
513 const gchar *pin = gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin));
514 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_password));
515
516 if (strlen(pin) > 0 && strlen(password) > 0)
517 {
518 gtk_widget_set_sensitive(priv->button_existing_account_next, TRUE);
519 }
520 else
521 {
522 gtk_widget_set_sensitive(priv->button_existing_account_next, FALSE);
523 }
524}
525
526static void
aviau2da3d9c2016-09-06 11:28:36 -0400527entries_new_account_changed(AccountCreationWizard *view)
aviau6aeb4852016-08-18 16:01:09 -0400528{
529 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
530
aviau2da3d9c2016-09-06 11:28:36 -0400531 const gchar *username = gtk_entry_get_text(GTK_ENTRY(priv->entry_alias));
aviau6aeb4852016-08-18 16:01:09 -0400532 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
533 const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));
aviau2da3d9c2016-09-06 11:28:36 -0400534 const gboolean sign_up_blockchain = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbutton_sign_up_blockchain));
aviau6aeb4852016-08-18 16:01:09 -0400535
aviau2da3d9c2016-09-06 11:28:36 -0400536 if (
537 strlen(password) > 0 && // Password is longer than 0
538 strlen(password_confirm) > 0 && // Confirmation is also longer than 0
539 strlen(username) > 0 && // username is set
540 (!sign_up_blockchain || priv->username_available) // either the username must be available, or don't sign up for the blockchain
541 )
aviau6aeb4852016-08-18 16:01:09 -0400542 {
543 gtk_widget_set_sensitive(priv->button_account_creation_next, TRUE);
544 }
545 else
546 {
547 gtk_widget_set_sensitive(priv->button_account_creation_next, FALSE);
548 }
549}
550
551static void
aviau2da3d9c2016-09-06 11:28:36 -0400552checkbutton_sign_up_blockchain_toggled(GtkToggleButton *toggle_button, AccountCreationWizard *view)
553{
554 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
555 gboolean sign_up_blockchain = gtk_toggle_button_get_active(toggle_button);
556
557
558 username_registration_box_set_use_blockchain(
559 USERNAME_REGISTRATION_BOX(priv->username_registration_box),
560 sign_up_blockchain
561 );
562
563 /* Unchecking blockchain signup when there is an empty username should
564 * result in activating the next button.
565 */
566 entries_new_account_changed(view);
567}
568
569static void
570username_availability_changed(AccountCreationWizard *view, gboolean username_available)
571{
572 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
573 priv->username_available = username_available;
574 entries_new_account_changed(view);
575}
576
577static void
578build_creation_wizard_view(AccountCreationWizard *view, gboolean show_cancel_button)
aviau6aeb4852016-08-18 16:01:09 -0400579{
580 g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
581 AccountCreationWizardPrivate *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
582
583 /* set ring logo */
584 GError *error = NULL;
585 GdkPixbuf* logo_ring = gdk_pixbuf_new_from_resource_at_scale("/cx/ring/RingGnome/ring-logo-blue",
586 -1, 50, TRUE, &error);
587 if (logo_ring == NULL) {
588 g_debug("Could not load logo: %s", error->message);
589 g_clear_error(&error);
590 } else
591 gtk_image_set_from_pixbuf(GTK_IMAGE(priv->choose_account_type_ring_logo), logo_ring);
592
aviau2da3d9c2016-09-06 11:28:36 -0400593 /* create the username_registration_box */
594 priv->username_registration_box = username_registration_box_new(nullptr, FALSE);
595 gtk_container_add(GTK_CONTAINER(priv->box_username_entry), priv->username_registration_box);
596 gtk_widget_show(priv->username_registration_box);
597 priv->entry_alias = GTK_WIDGET(
598 username_registration_box_get_entry(
599 USERNAME_REGISTRATION_BOX(priv->username_registration_box)
600 )
601 );
aviau6aeb4852016-08-18 16:01:09 -0400602
603 /* use the real name / username of the logged in user as the default */
604 const char* real_name = g_get_real_name();
605 const char* user_name = g_get_user_name();
606 g_debug("real_name = %s",real_name);
607 g_debug("user_name = %s",user_name);
608
609 /* check first if the real name was determined */
610 if (g_strcmp0 (real_name,"Unknown") != 0)
611 gtk_entry_set_text(GTK_ENTRY(priv->entry_alias), real_name);
612 else
613 gtk_entry_set_text(GTK_ENTRY(priv->entry_alias), user_name);
614
615 /* cancel button */
616 gtk_widget_set_visible(priv->button_wizard_cancel, show_cancel_button);
617
618 /* choose_account_type signals */
619 g_signal_connect_swapped(priv->button_new_account, "clicked", G_CALLBACK(show_account_creation), view);
620 g_signal_connect_swapped(priv->button_existing_account, "clicked", G_CALLBACK(show_existing_account), view);
621 g_signal_connect(priv->button_wizard_cancel, "clicked", G_CALLBACK(wizard_cancel_clicked), view);
622
623 /* account_creation signals */
624 g_signal_connect_swapped(priv->button_account_creation_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
aviau2da3d9c2016-09-06 11:28:36 -0400625 g_signal_connect_swapped(priv->entry_alias, "changed", G_CALLBACK(entries_new_account_changed), view);
aviau6aeb4852016-08-18 16:01:09 -0400626 g_signal_connect(priv->button_account_creation_next, "clicked", G_CALLBACK(account_creation_next_clicked), view);
aviau2da3d9c2016-09-06 11:28:36 -0400627 g_signal_connect_swapped(priv->entry_password, "changed", G_CALLBACK(entries_new_account_changed), view);
628 g_signal_connect_swapped(priv->entry_password_confirm, "changed", G_CALLBACK(entries_new_account_changed), view);
629 g_signal_connect_swapped(priv->entry_alias, "changed", G_CALLBACK(entries_new_account_changed), view);
630 g_signal_connect(priv->checkbutton_sign_up_blockchain, "toggled", G_CALLBACK(checkbutton_sign_up_blockchain_toggled), view);
631 g_signal_connect_swapped(priv->username_registration_box, "username-availability-changed", G_CALLBACK(username_availability_changed), view);
aviau6aeb4852016-08-18 16:01:09 -0400632
633 /* existing_account singals */
634 g_signal_connect_swapped(priv->button_existing_account_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
635 g_signal_connect(priv->button_existing_account_next, "clicked", G_CALLBACK(existing_account_next_clicked), view);
636 g_signal_connect(priv->entry_existing_account_pin, "changed", G_CALLBACK(entries_existing_account_changed), view);
637 g_signal_connect(priv->entry_existing_account_password, "changed", G_CALLBACK(entries_existing_account_changed), view);
638
639 /* error_view signals */
640 g_signal_connect_swapped(priv->button_error_view_ok, "clicked", G_CALLBACK(show_choose_account_type), view);
641
642 show_choose_account_type(view);
643}
644
645GtkWidget *
646account_creation_wizard_new(bool show_cancel_button)
647{
648 gpointer view = g_object_new(ACCOUNT_CREATION_WIZARD_TYPE, NULL);
649
650 build_creation_wizard_view(ACCOUNT_CREATION_WIZARD(view), show_cancel_button);
651 return (GtkWidget *)view;
652}