blob: 1cf09a96d03b914c2cd9c5105c573dee83f59cd2 [file] [log] [blame]
aviau6aeb4852016-08-18 16:01:09 -04001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2016-2017 Savoir-faire Linux Inc.
aviau6aeb4852016-08-18 16:01:09 -04003 * Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
Nicolas Jager84fe45e2017-03-01 09:14:17 -05004 * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>
aviau6aeb4852016-08-18 16:01:09 -04005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21
22// GTK+ related
23#include <gtk/gtk.h>
24#include <glib/gi18n.h>
25
26// LRC
27#include <codecmodel.h>
28#include <account.h>
29#include <accountmodel.h>
30#include <profilemodel.h>
31#include <profile.h>
32#include <personmodel.h>
33#include <globalinstances.h>
34
35// Ring Client
36#include "avatarmanipulation.h"
37#include "accountmigrationview.h"
aviau2da3d9c2016-09-06 11:28:36 -040038#include "usernameregistrationbox.h"
aviau6aeb4852016-08-18 16:01:09 -040039#include "utils/models.h"
40#include "native/pixbufmanipulator.h"
41#include "video/video_widget.h"
42
43/* size of avatar */
44static constexpr int AVATAR_WIDTH = 100; /* px */
45static constexpr int AVATAR_HEIGHT = 100; /* px */
46
47struct _AccountMigrationView
48{
49 GtkBox parent;
50};
51
52struct _AccountMigrationViewClass
53{
54 GtkBoxClass parent_class;
55};
56
57typedef struct _AccountMigrationViewPrivate AccountMigrationViewPrivate;
58
59struct _AccountMigrationViewPrivate
60{
61 Account *account;
aviau6aeb4852016-08-18 16:01:09 -040062 QMetaObject::Connection state_changed;
aviau6aeb4852016-08-18 16:01:09 -040063
aviau6aeb4852016-08-18 16:01:09 -040064 /* main_view */
65 GtkWidget *main_view;
66 GtkWidget *label_account_alias;
Stepan Salenikovicha6035422016-11-04 16:04:53 -040067 GtkWidget *label_account_ringid;
aviau6aeb4852016-08-18 16:01:09 -040068 GtkWidget *image_avatar;
Nicolas Jager84fe45e2017-03-01 09:14:17 -050069 GtkWidget *label_migration_error;
aviau6aeb4852016-08-18 16:01:09 -040070 GtkWidget *entry_password;
aviau6aeb4852016-08-18 16:01:09 -040071 GtkWidget *button_migrate_account;
72};
73
74G_DEFINE_TYPE_WITH_PRIVATE(AccountMigrationView, account_migration_view, GTK_TYPE_BOX);
75
76#define ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_MIGRATION_VIEW_TYPE, AccountMigrationViewPrivate))
77
78/* signals */
79enum {
80 ACCOUNT_MIGRATION_COMPLETED,
81 ACCOUNT_MIGRATION_FAILED,
82 LAST_SIGNAL
83};
84
85static guint account_migration_view_signals[LAST_SIGNAL] = { 0 };
86
87static void
88account_migration_view_dispose(GObject *object)
89{
Stepan Salenikovich56530b12016-10-20 17:51:34 -040090 auto priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(object);
91
92 // make sure to disconnect from all signals when disposing of view
93 QObject::disconnect(priv->state_changed);
94
aviau6aeb4852016-08-18 16:01:09 -040095 G_OBJECT_CLASS(account_migration_view_parent_class)->dispose(object);
96}
97
98static void
99account_migration_view_init(AccountMigrationView *view)
100{
101 gtk_widget_init_template(GTK_WIDGET(view));
102}
103
104static void
105account_migration_view_class_init(AccountMigrationViewClass *klass)
106{
107 G_OBJECT_CLASS(klass)->dispose = account_migration_view_dispose;
108
109 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
110 "/cx/ring/RingGnome/accountmigrationview.ui");
aviau6aeb4852016-08-18 16:01:09 -0400111 /* main_view */
112 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, main_view);
113 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, label_account_alias);
Stepan Salenikovicha6035422016-11-04 16:04:53 -0400114 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, label_account_ringid);
aviau6aeb4852016-08-18 16:01:09 -0400115 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, image_avatar);
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500116 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, label_migration_error);
aviau6aeb4852016-08-18 16:01:09 -0400117 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, entry_password);
aviau6aeb4852016-08-18 16:01:09 -0400118 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, button_migrate_account);
119
120 /* add signals */
121 account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED] = g_signal_new("account-migration-completed",
122 G_TYPE_FROM_CLASS(klass),
123 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
124 0,
125 nullptr,
126 nullptr,
127 g_cclosure_marshal_VOID__VOID,
128 G_TYPE_NONE, 0);
129
130 account_migration_view_signals[ACCOUNT_MIGRATION_FAILED] = g_signal_new("account-migration-failed",
131 G_TYPE_FROM_CLASS(klass),
132 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
133 0,
134 nullptr,
135 nullptr,
136 g_cclosure_marshal_VOID__VOID,
137 G_TYPE_NONE, 0);
138}
139
aviau6aeb4852016-08-18 16:01:09 -0400140static void
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500141migrate(AccountMigrationView *view)
aviau2da3d9c2016-09-06 11:28:36 -0400142{
143 AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500144 gtk_widget_set_sensitive(priv->button_migrate_account, FALSE);
aviau6aeb4852016-08-18 16:01:09 -0400145 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500146 priv->state_changed = QObject::connect(priv->account, &Account::migrationEnded,
147 [=] (const Account::MigrationEndedStatus state)
148 {
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500149 priv->account << Account::EditAction::RELOAD;
Stepan Salenikovich56530b12016-10-20 17:51:34 -0400150
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500151 switch(state)
152 {
153 case Account::MigrationEndedStatus::SUCCESS:
154 g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
155 break;
156 case Account::MigrationEndedStatus::INVALID:
157 case Account::MigrationEndedStatus::UNDEFINED_STATUS:
158 gtk_widget_show(priv->label_migration_error);
159 break;
aviau6aeb4852016-08-18 16:01:09 -0400160 }
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500161 });
aviau6aeb4852016-08-18 16:01:09 -0400162
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500163 priv->account->setArchivePassword(password);
164 gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
165 priv->account->performAction(Account::EditAction::SAVE);
Stepan Salenikovich155c4b82016-10-14 11:46:21 -0400166
aviau6aeb4852016-08-18 16:01:09 -0400167}
168
169static void
170password_entry_changed(G_GNUC_UNUSED GtkEntry* entry, AccountMigrationView *view)
171{
172 AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500173 gtk_widget_hide(priv->label_migration_error);
aviau6aeb4852016-08-18 16:01:09 -0400174
175 const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
aviau6aeb4852016-08-18 16:01:09 -0400176
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500177 if (strlen(password) > 0)
aviau6aeb4852016-08-18 16:01:09 -0400178 {
179 gtk_widget_set_sensitive(priv->button_migrate_account, TRUE);
180 }
181 else
182 {
183 gtk_widget_set_sensitive(priv->button_migrate_account, FALSE);
184 }
185}
186
187static void
188build_migration_view(AccountMigrationView *view)
189{
190 g_return_if_fail(IS_ACCOUNT_MIGRATION_VIEW(view));
191 AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
192
aviau6aeb4852016-08-18 16:01:09 -0400193 g_signal_connect(priv->entry_password, "changed", G_CALLBACK(password_entry_changed), view);
Nicolas Jager84fe45e2017-03-01 09:14:17 -0500194 g_signal_connect_swapped(priv->button_migrate_account, "clicked", G_CALLBACK(migrate), view);
195 g_signal_connect_swapped(priv->entry_password, "activate", G_CALLBACK(migrate), view);
aviau6aeb4852016-08-18 16:01:09 -0400196
197 gtk_label_set_text(GTK_LABEL(priv->label_account_alias), priv->account->alias().toUtf8().constData());
Stepan Salenikovicha6035422016-11-04 16:04:53 -0400198 // display the ringID (without "ring:")
199 gtk_label_set_text(GTK_LABEL(priv->label_account_ringid), URI(priv->account->username()).userinfo().toUtf8().constData());
aviau6aeb4852016-08-18 16:01:09 -0400200
201 /* set the avatar picture */
202 auto photo = GlobalInstances::pixmapManipulator().contactPhoto(
203 ProfileModel::instance().selectedProfile()->person(),
204 QSize(AVATAR_WIDTH, AVATAR_HEIGHT),
205 false);
206 std::shared_ptr<GdkPixbuf> pixbuf_photo = photo.value<std::shared_ptr<GdkPixbuf>>();
207
208 if (photo.isValid()) {
209 gtk_image_set_from_pixbuf (GTK_IMAGE(priv->image_avatar), pixbuf_photo.get());
210 } else {
211 g_warning("invalid pixbuf");
212 }
213}
214
215GtkWidget *
216account_migration_view_new(Account* account)
217{
218 gpointer view = g_object_new(ACCOUNT_MIGRATION_VIEW_TYPE, NULL);
219 AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
220 priv->account = account;
221 build_migration_view(ACCOUNT_MIGRATION_VIEW(view));
222 return (GtkWidget *)view;
223}