Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Profile dialog #677

Merged
merged 10 commits into from
Jul 26, 2020
Merged
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ set(quaternion_SRCS
client/chatedit.cpp
client/chatroomwidget.cpp
client/systemtrayicon.cpp
client/profiledialog.cpp
client/models/messageeventmodel.cpp
client/models/userlistmodel.cpp
client/models/roomlistmodel.cpp
Expand Down
7 changes: 7 additions & 0 deletions client/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "roomlistdock.h"
#include "userlistdock.h"
#include "chatroomwidget.h"
#include "profiledialog.h"
#include "logindialog.h"
#include "networkconfigdialog.h"
#include "roomdialogs.h"
Expand Down Expand Up @@ -795,6 +796,11 @@ void MainWindow::addConnection(Connection* c, const QString& deviceName)
if (connections.size() < 10)
menuCaption.prepend('&' % QString::number(connections.size()) % ' ');
auto accountMenu = new QMenu(menuCaption, connectionMenu);
accountMenu->addAction(QIcon::fromTheme("user-properties"), tr("Profile"),
this, [this,c,dlg=QPointer<ProfileDialog>{}]() mutable
{
summon(dlg, c->user(), this);
});
accountMenu->addAction(QIcon::fromTheme("view-certificate"),
tr("Show &access token"), this, [=]
{
Expand All @@ -812,6 +818,7 @@ void MainWindow::addConnection(Connection* c, const QString& deviceName)
accountTokenBox->setAttribute(Qt::WA_DeleteOnClose);
accountTokenBox->show();
});

accountMenu->addAction(QIcon::fromTheme("system-log-out"), tr("&Logout"),
this, [=] { logout(c); });
auto menuAction =
Expand Down
161 changes: 161 additions & 0 deletions client/profiledialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**************************************************************************
* *
* Copyright (C) 2019 Karol Kosek <[email protected]> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 3 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
**************************************************************************/

#include "profiledialog.h"

#include <connection.h>
#include <user.h>
#include <room.h>
#include <csapi/device_management.h>

#include <QtWidgets/QAction>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QTableWidgetItem>

using Quotient::BaseJob;

ProfileDialog::ProfileDialog(Quotient::User* u, QWidget* parent)
: Dialog(u->id(), parent)
, m_user(u)
, tabWidget(new QTabWidget)
, m_avatar(new QLabel)
, m_userId(new QLabel)
, m_displayName(new QLineEdit)
{
auto profileWidget = new QWidget(this);
{
auto topLayout = new QHBoxLayout;
{
auto avatarLayout = new QVBoxLayout;
m_avatar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_avatar->setPixmap({64, 64});
avatarLayout->addWidget(m_avatar);

auto uploadButton = new QPushButton(tr("Set Avatar..."));
connect(uploadButton, &QPushButton::clicked, this, [this] {
m_avatarUrl =
QFileDialog::getOpenFileName(this, tr("Set avatar"),
{}, tr("Images (*.png *.jpg)"));
if (!m_avatarUrl.isEmpty()) {
QImage img = QImage(m_avatarUrl).scaled({64, 64}, Qt::KeepAspectRatio);
m_avatar->setPixmap(QPixmap::fromImage(img));
}
});
connect(m_user, &Quotient::User::avatarChanged, this,
[=] (Quotient::User* user, const Quotient::Room* room) {
if (room)
return;

QImage img = user->avatar(64);
if (img.isNull())
m_avatar->setText(tr("No Avatar"));
else
m_avatar->setPixmap(QPixmap::fromImage(img));
});

avatarLayout->addWidget(uploadButton);
topLayout->addLayout(avatarLayout);
}

{
auto essentialsLayout = new QFormLayout;
essentialsLayout->addRow(tr("Account"), m_userId);
essentialsLayout->addRow(tr("Display Name"), m_displayName);
topLayout->addLayout(essentialsLayout);
}

profileWidget->setLayout(topLayout);
}
tabWidget->addTab(profileWidget, tr("Profile"));

m_deviceTable = new QTableWidget;
{
m_deviceTable->setColumnCount(3);
m_deviceTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
m_deviceTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_deviceTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
m_deviceTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_deviceTable->setSelectionBehavior(QAbstractItemView::SelectRows);

m_deviceTable->setHorizontalHeaderLabels(QStringList()
<< tr("Display Name")
<< tr("Device ID")
<< tr("Last Seen"));
}
tabWidget->addTab(m_deviceTable, tr("Devices"));

addWidget(tabWidget);
}

void ProfileDialog::load()
{
auto avatar = m_user->avatar(64);
if (avatar.isNull())
m_avatar->setText(tr("No Avatar"));
else
m_avatar->setPixmap(QPixmap::fromImage(avatar));
m_userId->setText(m_user->id());
m_displayName->setText(m_user->displayname());

auto devicesJob = m_user->connection()->callApi<Quotient::GetDevicesJob>();
connect(devicesJob, &BaseJob::success, this, [=] {
m_deviceTable->setRowCount(devicesJob->devices().size());

for (int i = 0; i < devicesJob->devices().size(); ++i) {
auto device = devicesJob->devices()[i];
m_devices[device.deviceId] = device.displayName;

auto name = new QTableWidgetItem(device.displayName);
m_deviceTable->setItem(i, 0, name);

auto id = new QTableWidgetItem(device.deviceId);
id->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
m_deviceTable->setItem(i, 1, id);

QDateTime lastSeen;
lastSeen.setMSecsSinceEpoch(device.lastSeenTs.value_or(0));
auto ip = new QTableWidgetItem(device.lastSeenIp
+ " @ " + QLocale().toString(lastSeen, QLocale::ShortFormat));
ip->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
m_deviceTable->setItem(i, 2, ip);
}
});
}

void ProfileDialog::apply()
{
if (m_displayName->text() != m_user->displayname())
m_user->rename(m_displayName->text());
if (!m_avatarUrl.isEmpty())
m_user->setAvatar(m_avatarUrl);

for (auto deviceIt = m_devices.cbegin(); deviceIt != m_devices.cend(); ++deviceIt) {
auto list = m_deviceTable->findItems(deviceIt.key(), Qt::MatchExactly);
auto newName = m_deviceTable->item(list[0]->row(), 0)->text();
if (!list.isEmpty() && newName != deviceIt.value())
m_user->connection()->callApi<Quotient::UpdateDeviceJob>(deviceIt.key(), newName);
}
accept();
}
57 changes: 57 additions & 0 deletions client/profiledialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**************************************************************************
* *
* Copyright (C) 2019 Karol Kosek <[email protected]> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 3 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
**************************************************************************/

#pragma once

#include "dialog.h"

class QAction;
class QLabel;
class QLineEdit;
class QTabWidget;
class QTableWidget;

namespace Quotient {
class User;
}

class ProfileDialog : public Dialog
{
Q_OBJECT

public:
explicit ProfileDialog(Quotient::User* u, QWidget* parent = 0);

private slots:
void load() override;
void apply() override;

private:
Quotient::User* m_user;
QTabWidget* tabWidget;

QTableWidget* m_deviceTable;
QAction* m_attachAction;
QLabel* m_avatar;
QLabel* m_userId;
QLineEdit* m_displayName;

QHash<QString, QString> m_devices;
QString m_avatarUrl;
};