1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/src/widget/form/profileform.cpp

339 lines
11 KiB
C++
Raw Normal View History

/*
This file is part of qTox, a Qt-based graphical interface for Tox.
This program is libre 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 COPYING file for more details.
*/
#include "src/core/core.h"
#include "src/nexus.h"
#include "ui_profileform.h"
#include "profileform.h"
#include "ui_mainwindow.h"
2014-10-08 12:26:25 +08:00
#include "src/widget/form/settingswidget.h"
#include "src/widget/maskablepixmapwidget.h"
2015-06-04 23:45:20 +08:00
#include "src/widget/form/setpassworddialog.h"
#include "src/misc/settings.h"
2014-10-08 12:26:25 +08:00
#include "src/widget/croppinglabel.h"
#include "src/widget/widget.h"
#include "src/widget/gui.h"
#include "src/historykeeper.h"
#include "src/misc/style.h"
2015-04-25 01:19:01 +08:00
#include "src/profilelocker.h"
#include "src/profile.h"
#include <QLabel>
#include <QLineEdit>
#include <QGroupBox>
#include <QApplication>
#include <QClipboard>
#include <QInputDialog>
#include <QFileDialog>
#include <QBuffer>
ProfileForm::ProfileForm(QWidget *parent) :
2015-05-10 04:35:58 +08:00
QWidget{parent}, qr{nullptr}
{
2014-10-06 00:17:01 +08:00
bodyUI = new Ui::IdentitySettings;
bodyUI->setupUi(this);
core = Core::getInstance();
head = new QWidget(this);
QHBoxLayout* headLayout = new QHBoxLayout();
head->setLayout(headLayout);
QLabel* imgLabel = new QLabel();
headLayout->addWidget(imgLabel);
QLabel* nameLabel = new QLabel();
QFont bold;
bold.setBold(true);
nameLabel->setFont(bold);
headLayout->addWidget(nameLabel);
headLayout->addStretch(1);
2015-05-18 20:43:18 +08:00
nameLabel->setText(QObject::tr("User Profile"));
imgLabel->setPixmap(QPixmap(":/img/settings/identity.png").scaledToHeight(40, Qt::SmoothTransformation));
// tox
toxId = new ClickableTE();
toxId->setReadOnly(true);
2014-10-09 16:59:35 +08:00
toxId->setFrame(false);
toxId->setFont(Style::getFont(Style::Small));
2015-03-17 05:15:34 +08:00
toxId->setToolTip(bodyUI->toxId->toolTip());
2015-03-15 23:45:28 +08:00
QVBoxLayout *toxIdGroup = qobject_cast<QVBoxLayout*>(bodyUI->toxGroup->layout());
toxIdGroup->replaceWidget(bodyUI->toxId, toxId);
bodyUI->toxId->hide();
2015-03-18 00:14:16 +08:00
bodyUI->qrLabel->setWordWrap(true);
profilePicture = new MaskablePixmapWidget(this, QSize(64, 64), ":/img/avatar_mask.svg");
2015-03-18 23:51:58 +08:00
profilePicture->setPixmap(QPixmap(":/img/contact_dark.svg"));
profilePicture->setClickable(true);
connect(profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked()));
QHBoxLayout *publicGrouplayout = qobject_cast<QHBoxLayout*>(bodyUI->publicGroup->layout());
publicGrouplayout->insertWidget(0, profilePicture);
publicGrouplayout->insertSpacing(1, 7);
2015-01-20 16:07:56 +08:00
timer.setInterval(750);
2014-11-11 07:20:10 +08:00
timer.setSingleShot(true);
2015-01-20 16:07:56 +08:00
connect(&timer, &QTimer::timeout, this, [=]() {bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace("", "")); hasCheck = false;});
2014-10-06 00:17:01 +08:00
connect(bodyUI->toxIdLabel, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
connect(core, &Core::idSet, this, &ProfileForm::setToxId);
2014-10-06 00:17:01 +08:00
connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited()));
connect(bodyUI->statusMessage, SIGNAL(editingFinished()), this, SLOT(onStatusMessageEdited()));
connect(bodyUI->renameButton, &QPushButton::clicked, this, &ProfileForm::onRenameClicked);
connect(bodyUI->exportButton, &QPushButton::clicked, this, &ProfileForm::onExportClicked);
connect(bodyUI->deleteButton, &QPushButton::clicked, this, &ProfileForm::onDeleteClicked);
connect(bodyUI->logoutButton, &QPushButton::clicked, this, &ProfileForm::onLogoutClicked);
2015-06-04 23:09:13 +08:00
connect(bodyUI->deletePassButton, &QPushButton::clicked, this, &ProfileForm::onDeletePassClicked);
connect(bodyUI->changePassButton, &QPushButton::clicked, this, &ProfileForm::onChangePassClicked);
2014-11-11 07:20:10 +08:00
connect(core, &Core::usernameSet, this, [=](const QString& val) { bodyUI->userName->setText(val); });
connect(core, &Core::statusMessageSet, this, [=](const QString& val) { bodyUI->statusMessage->setText(val); });
for (QComboBox* cb : findChildren<QComboBox*>())
{
cb->installEventFilter(this);
cb->setFocusPolicy(Qt::StrongFocus);
}
}
ProfileForm::~ProfileForm()
{
2015-05-10 04:35:58 +08:00
delete qr;
delete bodyUI;
head->deleteLater();
}
void ProfileForm::show(Ui::MainWindow &ui)
{
ui.mainHead->layout()->addWidget(head);
ui.mainContent->layout()->addWidget(this);
head->show();
QWidget::show();
bodyUI->userName->setFocus();
bodyUI->userName->selectAll();
}
void ProfileForm::copyIdClicked()
{
toxId->selectAll();
2014-10-06 02:02:12 +08:00
QString txt = toxId->text();
txt.replace('\n',"");
QApplication::clipboard()->setText(txt, QClipboard::Clipboard);
if (QApplication::clipboard()->supportsSelection())
QApplication::clipboard()->setText(txt, QClipboard::Selection);
2014-10-09 16:59:35 +08:00
toxId->setCursorPosition(0);
2014-11-11 07:20:10 +08:00
2015-01-20 16:07:56 +08:00
if (!hasCheck)
{
bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text() + "");
hasCheck = true;
}
2014-11-11 07:20:10 +08:00
timer.start();
}
void ProfileForm::onUserNameEdited()
{
2014-10-06 00:30:31 +08:00
Core::getInstance()->setUsername(bodyUI->userName->text());
}
void ProfileForm::onStatusMessageEdited()
{
2014-10-06 00:30:31 +08:00
Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text());
}
void ProfileForm::onSelfAvatarLoaded(const QPixmap& pic)
{
profilePicture->setPixmap(pic);
2014-10-06 00:17:01 +08:00
}
void ProfileForm::setToxId(const QString& id)
2014-10-06 00:17:01 +08:00
{
2014-10-18 09:15:26 +08:00
toxId->setText(id);
toxId->setCursorPosition(0);
2015-05-10 04:35:58 +08:00
delete qr;
qr = new QRWidget();
qr->setQRData("tox:"+id);
2015-03-15 23:45:28 +08:00
bodyUI->qrCode->setPixmap(QPixmap::fromImage(qr->getImage()->scaledToWidth(150)));
2014-10-06 00:17:01 +08:00
}
void ProfileForm::onAvatarClicked()
{
2015-05-10 06:56:41 +08:00
auto picToPng = [](QPixmap pic)
{
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
return bytes;
};
QString filename = QFileDialog::getOpenFileName(0,
tr("Choose a profile picture"),
QDir::homePath(),
Nexus::getSupportedImageFilter());
if (filename.isEmpty())
return;
2015-04-24 19:01:50 +08:00
QFile file(filename);
file.open(QIODevice::ReadOnly);
if (!file.isOpen())
{
GUI::showError(tr("Error"), tr("Unable to open this file."));
return;
}
QPixmap pic;
if (!pic.loadFromData(file.readAll()))
{
GUI::showError(tr("Error"), tr("Unable to read this image."));
return;
}
2015-05-10 06:56:41 +08:00
// Limit the avatar size to 64kB
// We do a first rescale to 256x256 in case the image was huge, then keep tryng from here
QByteArray bytes{picToPng(pic)};
if (bytes.size() > 65535)
{
pic = pic.scaled(256,256, Qt::KeepAspectRatio, Qt::SmoothTransformation);
bytes = picToPng(pic);
}
if (bytes.size() > 65535)
bytes = picToPng(pic.scaled(128,128, Qt::KeepAspectRatio, Qt::SmoothTransformation));
if (bytes.size() > 65535)
bytes = picToPng(pic.scaled(64,64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
if (bytes.size() > 65535)
bytes = picToPng(pic.scaled(32,32, Qt::KeepAspectRatio, Qt::SmoothTransformation));
// If this happens, you're really doing it on purpose.
if (bytes.size() > 65535)
{
QMessageBox::critical(this, tr("Error"),
2015-05-25 07:25:00 +08:00
tr("The supplied image is too large.\nPlease use another image."));
2015-05-10 06:56:41 +08:00
return;
}
Nexus::getCore()->setAvatar(bytes);
}
void ProfileForm::onRenameClicked()
{
2015-06-04 19:01:30 +08:00
Nexus& nexus = Nexus::getInstance();
QString cur = nexus.getProfile()->getName();
QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur);
do
{
QString name = QInputDialog::getText(this, title, title+":");
if (name.isEmpty()) break;
name = Core::sanitize(name);
2015-06-04 19:01:30 +08:00
2015-06-05 18:44:22 +08:00
if (Profile::exists(name))
GUI::showError(tr("Profile already exists", "rename failure title"),
tr("A profile named \"%1\" already exists.", "rename confirm text").arg(name));
else if (!nexus.getProfile()->rename(name))
GUI::showError(tr("Failed to rename", "rename failed title"),
tr("Couldn't rename the profile to \"%1\"").arg(cur));
else
break;
} while (true);
}
void ProfileForm::onExportClicked()
{
QString current = Nexus::getProfile()->getName() + Core::TOX_EXT;
QString path = QFileDialog::getSaveFileName(0, tr("Export profile", "save dialog title"),
2015-03-17 05:15:34 +08:00
QDir::home().filePath(current),
tr("Tox save file (*.tox)", "save dialog filter"));
if (!path.isEmpty())
2014-11-12 06:06:15 +08:00
{
if (!Nexus::tryRemoveFile(path))
2014-11-12 06:06:15 +08:00
{
2015-03-17 05:41:59 +08:00
GUI::showWarning(tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup"));
return;
2014-11-12 06:06:15 +08:00
}
2015-03-17 05:41:59 +08:00
if (!QFile::copy(QDir(Settings::getSettingsDirPath()).filePath(current), path))
GUI::showWarning(tr("Failed to copy file"), tr("The file you chose could not be written to."));
2014-11-12 06:06:15 +08:00
}
}
void ProfileForm::onDeleteClicked()
{
2015-06-04 18:43:28 +08:00
if (GUI::askQuestion(tr("Really delete profile?","deletion confirmation title"),
tr("Are you sure you want to delete this profile?","deletion confirmation text")))
{
2015-06-04 18:43:28 +08:00
Nexus& nexus = Nexus::getInstance();
nexus.getProfile()->remove();
nexus.showLogin();
}
}
void ProfileForm::onLogoutClicked()
{
2015-06-04 17:56:19 +08:00
Nexus& nexus = Nexus::getInstance();
Settings::getInstance().save();
nexus.showLogin();
}
void ProfileForm::onCopyQrClicked()
2015-03-15 23:45:28 +08:00
{
2015-03-16 02:53:10 +08:00
QApplication::clipboard()->setImage(*qr->getImage());
2015-03-15 23:45:28 +08:00
}
void ProfileForm::onSaveQrClicked()
2015-03-15 23:45:28 +08:00
{
QString current = Nexus::getProfile()->getName() + ".png";
2015-03-15 23:45:28 +08:00
QString path = QFileDialog::getSaveFileName(0, tr("Save", "save qr image"),
2015-03-17 05:41:59 +08:00
QDir::home().filePath(current),
2015-03-15 23:45:28 +08:00
tr("Save QrCode (*.png)", "save dialog filter"));
if (!path.isEmpty())
{
if (!Nexus::tryRemoveFile(path))
2015-03-15 23:45:28 +08:00
{
2015-03-17 05:41:59 +08:00
GUI::showWarning(tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup"));
return;
2015-03-15 23:45:28 +08:00
}
2015-03-17 05:41:59 +08:00
if (!qr->saveImage(path))
GUI::showWarning(tr("Failed to copy file"), tr("The file you chose could not be written to."));
2015-03-15 23:45:28 +08:00
}
}
2015-06-04 23:09:13 +08:00
void ProfileForm::onDeletePassClicked()
{
Profile* pro = Nexus::getProfile();
if (!pro->isEncrypted())
{
GUI::showInfo(tr("Nothing to remove"), tr("Your profile does not have a password!"));
return;
}
if (!GUI::askQuestion(tr("Really delete password?","deletion confirmation title"),
tr("Are you sure you want to delete your password?","deletion confirmation text")))
return;
Nexus::getProfile()->setPassword(QString());
}
void ProfileForm::onChangePassClicked()
{
2015-06-04 23:45:20 +08:00
SetPasswordDialog* dialog = new SetPasswordDialog(tr("Please enter a new password."), QString(), 0);
int r = dialog->exec();
if (r == QDialog::Rejected)
return;
2015-06-04 23:09:13 +08:00
2015-06-04 23:45:20 +08:00
QString newPass = dialog->getPassword();
Nexus::getProfile()->setPassword(newPass);
2015-06-04 23:09:13 +08:00
}