Commit 4dbd71c5 authored by Sébastien Blin's avatar Sébastien Blin Committed by Andreas Traczyk
Browse files

migrationview: reactive the migration view linked with new LRC models



Change-Id: I8a7f8a9b5f2d1a21a41701182320f0fc28794cf5
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 52980bb3
......@@ -23,26 +23,21 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
// Qt
#include <QSize>
#include <iostream>
// LRC
#include <codecmodel.h>
#include <account.h>
#include <accountmodel.h>
#include <profilemodel.h>
#include <profile.h>
#include <personmodel.h>
#include <globalinstances.h>
#include <api/newaccountmodel.h>
// Ring Client
#include "avatarmanipulation.h"
#include "accountmigrationview.h"
#include "usernameregistrationbox.h"
#include "utils/models.h"
#include "native/pixbufmanipulator.h"
#include "video/video_widget.h"
/* size of avatar */
static constexpr int AVATAR_WIDTH = 100; /* px */
static constexpr int AVATAR_HEIGHT = 100; /* px */
static constexpr int AVATAR_WIDTH = 150; /* px */
static constexpr int AVATAR_HEIGHT = 150; /* px */
struct _AccountMigrationView
{
......@@ -58,7 +53,7 @@ typedef struct _AccountMigrationViewPrivate AccountMigrationViewPrivate;
struct _AccountMigrationViewPrivate
{
Account *account;
AccountInfoPointer const *accountInfo_;
QMetaObject::Connection state_changed;
/* main_view */
......@@ -69,6 +64,8 @@ struct _AccountMigrationViewPrivate
GtkWidget *label_migration_error;
GtkWidget *entry_password;
GtkWidget *button_migrate_account;
GtkWidget *ringid_row;
GtkWidget *button_delete_account;
};
G_DEFINE_TYPE_WITH_PRIVATE(AccountMigrationView, account_migration_view, GTK_TYPE_BOX);
......@@ -116,6 +113,8 @@ account_migration_view_class_init(AccountMigrationViewClass *klass)
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, label_migration_error);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, entry_password);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, button_migrate_account);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, ringid_row);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountMigrationView, button_delete_account);
/* add signals */
account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED] = g_signal_new("account-migration-completed",
......@@ -140,29 +139,50 @@ account_migration_view_class_init(AccountMigrationViewClass *klass)
static void
migrate(AccountMigrationView *view)
{
g_return_if_fail(IS_ACCOUNT_MIGRATION_VIEW(view));
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
gtk_widget_set_sensitive(priv->button_migrate_account, FALSE);
const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
priv->state_changed = QObject::connect(priv->account, &Account::migrationEnded,
[=] (const Account::MigrationEndedStatus state)
priv->state_changed = QObject::connect((*priv->accountInfo_)->accountModel,
&lrc::api::NewAccountModel::migrationEnded,
[=] (const std::string& accountId, bool ok)
{
priv->account << Account::EditAction::RELOAD;
switch(state)
{
case Account::MigrationEndedStatus::SUCCESS:
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
break;
case Account::MigrationEndedStatus::INVALID:
case Account::MigrationEndedStatus::UNDEFINED_STATUS:
gtk_widget_show(priv->label_migration_error);
break;
if ((*priv->accountInfo_)->id != accountId) {
return;
}
if (ok) {
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
} else {
gtk_widget_show(priv->label_migration_error);
}
});
priv->account->setArchivePassword(password);
auto currentProp = (*priv->accountInfo_)->accountModel->getAccountConfig((*priv->accountInfo_)->id);
currentProp.archivePassword = password;
(*priv->accountInfo_)->accountModel->setAccountConfig((*priv->accountInfo_)->id, currentProp);
gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
priv->account->performAction(Account::EditAction::SAVE);
}
static void
delete_account(AccountMigrationView *view)
{
g_return_if_fail(IS_ACCOUNT_MIGRATION_VIEW(view));
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
auto* top_window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
auto* password_dialog = gtk_message_dialog_new(top_window,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
_("Warning! This action will remove this account on this device!\nNote: this action cannot be undone. Also, your registered name can be lost!"));
gtk_window_set_title(GTK_WINDOW(password_dialog), _("Delete account"));
gtk_dialog_set_default_response(GTK_DIALOG(password_dialog), GTK_RESPONSE_OK);
auto res = gtk_dialog_run(GTK_DIALOG(password_dialog));
if (res == GTK_RESPONSE_OK) {
(*priv->accountInfo_)->accountModel->removeAccount((*priv->accountInfo_)->id);
g_signal_emit(G_OBJECT(view), account_migration_view_signals[ACCOUNT_MIGRATION_COMPLETED], 0);
}
gtk_widget_destroy(password_dialog);
}
......@@ -171,8 +191,6 @@ password_entry_changed(G_GNUC_UNUSED GtkEntry* entry, AccountMigrationView *view
{
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
gtk_widget_hide(priv->label_migration_error);
gtk_widget_set_sensitive(priv->button_migrate_account, TRUE);
}
static void
......@@ -183,32 +201,55 @@ build_migration_view(AccountMigrationView *view)
g_signal_connect(priv->entry_password, "changed", G_CALLBACK(password_entry_changed), view);
g_signal_connect_swapped(priv->button_migrate_account, "clicked", G_CALLBACK(migrate), view);
g_signal_connect_swapped(priv->button_delete_account, "clicked", G_CALLBACK(delete_account), view);
g_signal_connect_swapped(priv->entry_password, "activate", G_CALLBACK(migrate), 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_alias), (*priv->accountInfo_)->profileInfo.alias.c_str());
// display the ringID (without "ring:")
gtk_label_set_text(GTK_LABEL(priv->label_account_ringid), URI(priv->account->username()).userinfo().toUtf8().constData());
/* set the avatar picture */
auto photo = GlobalInstances::pixmapManipulator().contactPhoto(
ProfileModel::instance().selectedProfile()->person(),
QSize(AVATAR_WIDTH, AVATAR_HEIGHT),
false);
std::shared_ptr<GdkPixbuf> pixbuf_photo = photo.value<std::shared_ptr<GdkPixbuf>>();
if (photo.isValid()) {
gtk_image_set_from_pixbuf (GTK_IMAGE(priv->image_avatar), pixbuf_photo.get());
} else {
g_warning("invalid pixbuf");
std::cout << "MIGRATE FOR " << (*priv->accountInfo_)->id << std::endl;
std::string username = (*priv->accountInfo_)->profileInfo.uri;
if (username.empty()) {
username = (*priv->accountInfo_)->profileInfo.uri;
}
gtk_label_set_text(GTK_LABEL(priv->label_account_ringid), username.c_str());
if (username.empty()) {
gtk_widget_hide(priv->ringid_row);
}
/* get the current or default profile avatar */
auto default_avatar = Interfaces::PixbufManipulator().generateAvatar("", "");
auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT));
auto photo = default_scaled;
auto photostr = (*priv->accountInfo_)->profileInfo.avatar;
if (!photostr.empty()) {
QByteArray byteArray(photostr.c_str(), photostr.length());
QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray);
auto pixbuf_photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT));
if (avatar.isValid()) {
photo = pixbuf_photo;
}
}
gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_avatar), photo.get());
// CSS styles
auto provider = gtk_css_provider_new();
std::string css = ".button_red { color: white; background: #dc3a37; border: 0; }";
css += ".button_red:hover { background: #dc2719; }";
gtk_css_provider_load_from_data(provider, css.c_str(), -1, nullptr);
gtk_style_context_add_provider_for_screen(gdk_display_get_default_screen(gdk_display_get_default()),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
GtkStyleContext* context;
context = gtk_widget_get_style_context(GTK_WIDGET(priv->button_delete_account));
gtk_style_context_add_class(context, "button_red");
}
GtkWidget *
account_migration_view_new(Account* account)
account_migration_view_new(AccountInfoPointer const & accountInfo)
{
gpointer view = g_object_new(ACCOUNT_MIGRATION_VIEW_TYPE, NULL);
AccountMigrationViewPrivate *priv = ACCOUNT_MIGRATION_VIEW_GET_PRIVATE(view);
priv->account = account;
priv->accountInfo_ = &accountInfo;
build_migration_view(ACCOUNT_MIGRATION_VIEW(view));
return (GtkWidget *)view;
}
......@@ -21,7 +21,8 @@
#include <gtk/gtk.h>
class Account;
#include <api/account.h>
#include "accountinfopointer.h"
G_BEGIN_DECLS
......@@ -35,6 +36,6 @@ typedef struct _AccountMigrationView AccountMigrationView;
typedef struct _AccountMigrationViewClass AccountMigrationViewClass;
GType account_migration_view_get_type (void) G_GNUC_CONST;
GtkWidget *account_migration_view_new (Account *account);
GtkWidget *account_migration_view_new (AccountInfoPointer const& accountInfo);
G_END_DECLS
......@@ -23,6 +23,8 @@
// GTK+ related
#include <glib/gi18n.h>
#include <iostream>
// LRC
#include <accountmodel.h> // Old lrc but still used
#include <api/account.h>
......@@ -289,6 +291,7 @@ public:
std::unique_ptr<lrc::api::Lrc> lrc_;
AccountInfoPointer accountInfo_ = nullptr;
AccountInfoPointer accountInfoForMigration_ = nullptr;
std::unique_ptr<lrc::api::conversation::Info> chatViewConversation_;
lrc::api::profile::Type currentTypeFilter_;
bool show_settings = false;
......@@ -637,32 +640,40 @@ on_handle_account_migrations(RingMainWindow* self)
priv->account_migration_view = nullptr;
}
auto accounts = AccountModel::instance().accountsToMigrate();
if (!accounts.isEmpty()) {
auto* account = accounts.first();
priv->account_migration_view = account_migration_view_new(account);
g_signal_connect_swapped(priv->account_migration_view, "account-migration-completed",
G_CALLBACK(on_handle_account_migrations), self);
g_signal_connect_swapped(priv->account_migration_view, "account-migration-failed",
G_CALLBACK(on_handle_account_migrations), self);
gtk_widget_hide(priv->ring_settings);
priv->cpp->showAccountSelectorWidget(false);
gtk_widget_show(priv->account_migration_view);
gtk_stack_add_named(
GTK_STACK(priv->stack_main_view),
priv->account_migration_view,
ACCOUNT_MIGRATION_VIEW_NAME
);
gtk_stack_set_visible_child_name(
GTK_STACK(priv->stack_main_view),
ACCOUNT_MIGRATION_VIEW_NAME
);
} else {
gtk_widget_show(priv->ring_settings);
priv->cpp->showAccountSelectorWidget();
auto accounts = priv->cpp->lrc_->getAccountModel().getAccountList();
for (const auto& accountId : accounts) {
priv->cpp->accountInfoForMigration_ = &priv->cpp->lrc_->getAccountModel().getAccountInfo(accountId);
if (priv->cpp->accountInfoForMigration_->status == lrc::api::account::Status::ERROR_NEED_MIGRATION) {
std::cout << "DO MIGRATION" << std::endl;
priv->account_migration_view = account_migration_view_new(priv->cpp->accountInfoForMigration_);
g_signal_connect_swapped(priv->account_migration_view, "account-migration-completed",
G_CALLBACK(on_handle_account_migrations), self);
g_signal_connect_swapped(priv->account_migration_view, "account-migration-failed",
G_CALLBACK(on_handle_account_migrations), self);
gtk_widget_hide(priv->ring_settings);
priv->cpp->showAccountSelectorWidget(false);
gtk_widget_show(priv->account_migration_view);
gtk_stack_add_named(
GTK_STACK(priv->stack_main_view),
priv->account_migration_view,
ACCOUNT_MIGRATION_VIEW_NAME);
gtk_stack_set_visible_child_name(
GTK_STACK(priv->stack_main_view),
ACCOUNT_MIGRATION_VIEW_NAME);
return;
}
}
priv->cpp->accountInfoForMigration_ = nullptr;
for (const auto& accountId : accounts) {
auto* accountInfo = &priv->cpp->lrc_->getAccountModel().getAccountInfo(accountId);
if (accountInfo->enabled) {
priv->cpp->updateLrc(accountId);
}
}
gtk_widget_show(priv->ring_settings);
priv->cpp->showAccountSelectorWidget();
}
} // namespace gtk_callbacks
......@@ -757,6 +768,7 @@ CppImpl::init()
decltype(accountIds)::value_type activeAccountId; // non-empty if a enabled account is found below
if (not accountIds.empty()) {
on_handle_account_migrations(self);
for (const auto& id : accountIds) {
const auto& accountInfo = lrc_->getAccountModel().getAccountInfo(id);
if (accountInfo.enabled) {
......
......@@ -2,10 +2,16 @@
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkImage" id="image-remove-account">
<property name="visible">True</property>
<property name="icon_name">user-trash-symbolic</property>
</object>
<template class="AccountMigrationView" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="valign">center</property>
<property name="halign">center</property>
<property name="spacing">15</property>
<child>
<object class="GtkLabel">
......@@ -17,144 +23,217 @@
<attribute name="scale" value="1.5"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="row_spacing">10</property>
<property name="column_spacing">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Alias:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<property name="label" translatable="yes">This account is malformed, please enter your password</property>
</object>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">out</property>
<property name="halign">fill</property>
<child>
<object class="GtkLabel" id="label_account_alias">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="orientation">vertical</property>
<property name="spacing">0</property>
<property name="halign">fill</property>
<child>
<object class="GtkListBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">fill</property>
<property name="valign">fill</property>
<property name="selection_mode">none</property>
<child>
<!-- Avatar -->
<object class="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_top">10</property>
<property name="halign">fill</property>
<child>
<object class="GtkImage" id="image_avatar">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
<child>
<!-- Alias -->
<object class="GtkListBoxRow" id="alias_row">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">fill</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="halign">fill</property>
<property name="orientation">horizontal</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Alias</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label_account_alias">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<!-- RingID -->
<object class="GtkListBoxRow" id="ringid_row">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">fill</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="halign">fill</property>
<property name="orientation">horizontal</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Ring ID</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label_account_ringid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<!-- Password -->
<object class="GtkListBoxRow" id="password_row">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">fill</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="halign">fill</property>
<property name="orientation">horizontal</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Password</property>
</object>
</child>
<child>
<object class="GtkEntry" id="entry_password">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">center</property>
<property name="visibility">False</property>
<property name="primary_icon_stock">gtk-dialog-authentication</property>
<property name="input_purpose">password</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">horizontal</property>
<property name="halign">fill</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel">
<object class="GtkButton" id="button_migrate_account">
<property name="label" translatable="yes">Migrate account</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label">RingID:</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">fill</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_account_ringid">
<object class="GtkButton" id="button_delete_account">
<property name="label" translatable="yes">Delete account</property>
<property name="image">image-remove-account</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">fill</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="image_avatar">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please enter your password:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_password">
<property name="visible">True</property>