Skip to content

Commit

Permalink
Merge pull request #677 from krkk/profile-dialog
Browse files Browse the repository at this point in the history
Profile dialog
  • Loading branch information
KitsuneRal authored Jul 26, 2020
2 parents 9975add + 97b4130 commit c793651
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 0 deletions.
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;
};

0 comments on commit c793651

Please sign in to comment.