blob: 120f8f9518687063397e6b04ee2704d7e0dbc901 [file] [log] [blame]
aviau6aeb4852016-08-18 16:01:09 -04001/*
Guillaume Roguez77c579d2018-01-30 15:54:02 -05002 * Copyright (C) 2016-2018 Savoir-faire Linux Inc.
aviau6aeb4852016-08-18 16:01:09 -04003 * 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// GTK+ related
21#include <gtk/gtk.h>
22#include <glib/gi18n.h>
23
24// LRC
25#include <account.h>
26#include <codecmodel.h>
27#include "ringdevicemodel.h"
28#include "ringdevice.h"
29
30// Ring Client
31#include "accountdevicestab.h"
32#include "models/gtkqtreemodel.h"
33#include "utils/models.h"
34
35struct _AccountDevicesTab
36{
37 GtkBox parent;
38};
39
40struct _AccountDevicesTabClass
41{
42 GtkBoxClass parent_class;
43};
44
45typedef struct _AccountDevicesTabPrivate AccountDevicesTabPrivate;
46
47struct _AccountDevicesTabPrivate
48{
49 Account *account;
50 GtkWidget *stack_account_devices;
51 QMetaObject::Connection export_on_ring_ended;
52
53 /* generated_pin view */
54 GtkWidget *generated_pin;
55 GtkWidget *label_generated_pin;
56 GtkWidget *button_generated_pin_ok;
57
58 /* manage_devices view */
59 GtkWidget *manage_devices;
60 GtkWidget *label_device_id;
61 GtkWidget *treeview_devices;
62 GtkWidget *button_add_device;
63
64 /* add_device view */
65 GtkWidget *add_device;
66 GtkWidget *button_export_on_the_ring;
67 GtkWidget *button_add_device_cancel;
68 GtkWidget *entry_password;
69
70 /* generating account spinner */
71 GtkWidget *vbox_generating_pin_spinner;
72
73 /* export on ring error */
74 GtkWidget *export_on_ring_error;
75 GtkWidget *label_export_on_ring_error;
76 GtkWidget* button_export_on_ring_error_ok;
77
78};
79
80G_DEFINE_TYPE_WITH_PRIVATE(AccountDevicesTab, account_devices_tab, GTK_TYPE_BOX);
81
82#define ACCOUNT_DEVICES_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_DEVICES_TAB_TYPE, AccountDevicesTabPrivate))
83
84static void
85account_devices_tab_dispose(GObject *object)
86{
87 G_OBJECT_CLASS(account_devices_tab_parent_class)->dispose(object);
88}
89
90static void
91account_devices_tab_init(AccountDevicesTab *view)
92{
93 gtk_widget_init_template(GTK_WIDGET(view));
94}
95
96static void
97account_devices_tab_class_init(AccountDevicesTabClass *klass)
98{
99 G_OBJECT_CLASS(klass)->dispose = account_devices_tab_dispose;
100
101 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
102 "/cx/ring/RingGnome/accountdevicestab.ui");
103
104 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, stack_account_devices);
105
106 /* generated_pin view */
107 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, generated_pin);
108 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, label_generated_pin);
109 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, button_generated_pin_ok);
110
111 /* manage_devices view */
112 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, manage_devices);
113 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, label_device_id);
114 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, treeview_devices);
115 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, button_add_device);
116
117 /* add_device view */
118 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, add_device);
119 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, button_export_on_the_ring);
120 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, button_add_device_cancel);
121 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, entry_password);
122
123 /* generating pin spinner */
124 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, vbox_generating_pin_spinner);
125
126 /* export on ring error */
127 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, export_on_ring_error);
128 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, label_export_on_ring_error);
129 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountDevicesTab, button_export_on_ring_error_ok);
130}
131
132static void
133show_manage_devices_view(AccountDevicesTab *view)
134{
135 g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view));
136 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
137 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->manage_devices);
138}
139
140static void
141show_add_device_view(AccountDevicesTab *view)
142{
143 g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view));
144 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
145 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->add_device);
146}
147
148static void
149show_generated_pin_view(AccountDevicesTab *view)
150{
151 g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view));
152 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
153 gtk_widget_show(priv->generated_pin);
154 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->generated_pin);
155}
156
157static void
158show_generating_pin_spinner(AccountDevicesTab *view)
159{
160 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
161 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->vbox_generating_pin_spinner);
162}
163
164static void
165show_export_on_ring_error(AccountDevicesTab *view)
166{
167 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
168 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->export_on_ring_error);
169}
170
171static void
172export_on_the_ring_clicked(G_GNUC_UNUSED GtkButton *button, AccountDevicesTab *view)
173{
174 g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view));
175 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
176
177 auto password = QString(gtk_entry_get_text(GTK_ENTRY(priv->entry_password)));
178 gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
179
180 priv->export_on_ring_ended = QObject::connect(
181 priv->account,
182 &Account::exportOnRingEnded,
183 [=] (Account::ExportOnRingStatus status, QString pin) {
184 QObject::disconnect(priv->export_on_ring_ended);
185 switch (status)
186 {
187 case Account::ExportOnRingStatus::SUCCESS:
188 {
189 gtk_label_set_text(GTK_LABEL(priv->label_generated_pin), pin.toStdString().c_str());
190 show_generated_pin_view(view);
191 break;
192 }
193 case Account::ExportOnRingStatus::WRONG_PASSWORD:
194 {
195 gtk_label_set_text(GTK_LABEL(priv->label_export_on_ring_error), _("Bad password"));
196 show_export_on_ring_error(view);
197 break;
198 }
199 case Account::ExportOnRingStatus::NETWORK_ERROR:
200 {
201 gtk_label_set_text(GTK_LABEL(priv->label_export_on_ring_error), _("Network error, try again"));
202 show_export_on_ring_error(view);
203 break;
204 }
205 }
206 }
207 );
208
209 show_generating_pin_spinner(view);
210 if (!priv->account->exportOnRing(password))
211 {
212 QObject::disconnect(priv->export_on_ring_ended);
213 gtk_label_set_text(GTK_LABEL(priv->label_export_on_ring_error), _("Could not initiate export to the Ring, try again"));
214 g_debug("Could not initiate exportOnRing operation");
215 show_export_on_ring_error(view);
216 }
217}
218
219static void
220build_tab_view(AccountDevicesTab *view)
221{
222 g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view));
223 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
224
225 g_signal_connect_swapped(priv->button_add_device, "clicked", G_CALLBACK(show_add_device_view), view);
226 g_signal_connect_swapped(priv->button_add_device_cancel, "clicked", G_CALLBACK(show_manage_devices_view), view);
227 g_signal_connect(priv->button_export_on_the_ring, "clicked", G_CALLBACK(export_on_the_ring_clicked), view);
228 g_signal_connect_swapped(priv->button_generated_pin_ok, "clicked", G_CALLBACK(show_manage_devices_view), view);
229 g_signal_connect_swapped(priv->button_export_on_ring_error_ok, "clicked", G_CALLBACK(show_add_device_view), view);
230
231 gtk_label_set_text(GTK_LABEL(priv->label_device_id), priv->account->deviceId().toUtf8().constData());
232
233 /* treeview_devices */
234 auto *devices_model = gtk_q_tree_model_new(
235 (QAbstractItemModel*) priv->account->ringDeviceModel(),
236 2,
237 RingDevice::Column::Name, Qt::DisplayRole, G_TYPE_STRING,
238 RingDevice::Column::Id, Qt::DisplayRole, G_TYPE_STRING);
239
240 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_devices), GTK_TREE_MODEL(devices_model));
241
242 GtkCellRenderer* renderer;
243 GtkTreeViewColumn* column;
244
245 renderer = gtk_cell_renderer_text_new();
246 column = gtk_tree_view_column_new_with_attributes(C_("Device Name Column", "Name"), renderer, "text", 0, NULL);
247 gtk_tree_view_column_set_expand(column, TRUE);
248 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_devices), column);
249
250 renderer = gtk_cell_renderer_text_new();
251 column = gtk_tree_view_column_new_with_attributes(C_("Device ID Column", "ID"), renderer, "text", 1, NULL);
252 gtk_tree_view_column_set_expand(column, TRUE);
253 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_devices), column);
254
255 /* Show manage-devices view */
256 gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->manage_devices);
257}
258
259GtkWidget *
260account_devices_tab_new(Account *account)
261{
262 g_return_val_if_fail(account != NULL, NULL);
263
264 gpointer view = g_object_new(ACCOUNT_DEVICES_TAB_TYPE, NULL);
265
266 AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view);
267 priv->account = account;
268
269 build_tab_view(ACCOUNT_DEVICES_TAB(view));
270
271 return (GtkWidget *)view;
272}