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

refactor(profileform): Integrate ProfileInfo in ProfileForm

This commit is contained in:
Diadlo 2017-10-07 20:02:03 +03:00
parent 49915c0a45
commit 36adfc89e9
No known key found for this signature in database
GPG Key ID: 5AF9F2E29107C727
4 changed files with 192 additions and 185 deletions

View File

@ -20,6 +20,7 @@
#include "profileform.h"
#include "ui_profileform.h"
#include "src/core/core.h"
#include "src/model/profile/iprofileinfo.h"
#include "src/net/toxme.h"
#include "src/nexus.h"
#include "src/persistence/profile.h"
@ -43,22 +44,73 @@
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QMap>
#include <QMenu>
#include <QMessageBox>
#include <QMouseEvent>
#include <QWindow>
ProfileForm::ProfileForm(QWidget* parent)
static const QMap<IProfileInfo::SetAvatarResult, QString> SET_AVATAR_ERROR = {
{ IProfileInfo::SetAvatarResult::CanNotOpen,
ProfileForm::tr("Unable to open this file.") },
{ IProfileInfo::SetAvatarResult::CanNotRead,
ProfileForm::tr("Unable to read this image.") },
{ IProfileInfo::SetAvatarResult::TooLarge,
ProfileForm::tr("The supplied image is too large.\nPlease use another image.") },
{ IProfileInfo::SetAvatarResult::EmptyPath,
ProfileForm::tr("Empty path is unavaliable") },
};
static const QMap<IProfileInfo::RenameResult, QPair<QString, QString>> RENAME_ERROR = {
{ IProfileInfo::RenameResult::Error,
{ ProfileForm::tr("Failed to rename"),
ProfileForm::tr("Couldn't rename the profile to \"%1\"") }
} ,
{ IProfileInfo::RenameResult::ProfileAlreadyExists,
{ ProfileForm::tr("Profile already exists"),
ProfileForm::tr("A profile named \"%1\" already exists.") }
},
{ IProfileInfo::RenameResult::EmptyName,
{ ProfileForm::tr("Empty name"),
ProfileForm::tr("Empty name is unavaliable") }
},
};
static const QMap<IProfileInfo::SaveResult, QPair<QString, QString>> SAVE_ERROR = {
{ IProfileInfo::SaveResult::NoWritePermission,
{ ProfileForm::tr("Location not writable", "Title of permissions popup"),
ProfileForm::tr("You do not have permission to write that location. Choose "
"another, or cancel the save dialog.", "text of permissions popup") },
},
{ IProfileInfo::SaveResult::Error,
{ ProfileForm::tr("Failed to copy file"),
ProfileForm::tr("The file you chose could not be written to.") }
},
{ IProfileInfo::SaveResult::EmptyPath,
{ ProfileForm::tr("Empty path"),
ProfileForm::tr("Empty path is unavaliable") }
},
};
static const QPair<QString, QString> CAN_NOT_CHANGE_PASSWORD = {
ProfileForm::tr("Couldn't change password"),
ProfileForm::tr("Couldn't change password on the database, "
"it might be corrupted or use the old password.")
};
ProfileForm::ProfileForm(IProfileInfo* profileInfo, QWidget* parent)
: QWidget{parent}
, qr{nullptr}
, profileInfo{profileInfo}
{
bodyUI = new Ui::IdentitySettings;
bodyUI->setupUi(this);
core = Core::getInstance();
bodyUI->userNameLabel->setToolTip(
tr("Tox user names cannot exceed %1 characters.").arg(tox_max_name_length()));
bodyUI->userName->setMaxLength(tox_max_name_length());
const uint32_t maxNameLength = tox_max_name_length();
const QString toolTip = tr("Tox user names cannot exceed %1 characters.").arg(maxNameLength);
bodyUI->userNameLabel->setToolTip(toolTip);
bodyUI->userName->setMaxLength(static_cast<int>(maxNameLength));
// tox
toxId = new ClickableTE();
@ -72,8 +124,8 @@ ProfileForm::ProfileForm(QWidget* parent)
/* Toxme section init */
bodyUI->toxmeServersList->addItem("toxme.io");
QString toxmeInfo = Settings::getInstance().getToxmeInfo();
if (toxmeInfo.isEmpty()) // User not registered
{
// User not registered
if (toxmeInfo.isEmpty()) {
showRegisterToxme();
} else {
showExistingToxme();
@ -95,6 +147,7 @@ ProfileForm::ProfileForm(QWidget* parent)
connect(profilePicture, &MaskablePixmapWidget::clicked, this, &ProfileForm::onAvatarClicked);
connect(profilePicture, &MaskablePixmapWidget::customContextMenuRequested,
this, &ProfileForm::showProfilePictureContextMenu);
QHBoxLayout* publicGrouplayout = qobject_cast<QHBoxLayout*>(bodyUI->publicGroup->layout());
publicGrouplayout->insertWidget(0, profilePicture);
publicGrouplayout->insertSpacing(1, 7);
@ -108,6 +161,7 @@ ProfileForm::ProfileForm(QWidget* parent)
connect(bodyUI->toxIdLabel, &CroppingLabel::clicked, this, &ProfileForm::copyIdClicked);
connect(toxId, &ClickableTE::clicked, this, &ProfileForm::copyIdClicked);
// TODO: Move to model
connect(core, &Core::idSet, this, &ProfileForm::setToxId);
connect(bodyUI->userName, &QLineEdit::editingFinished, this, &ProfileForm::onUserNameEdited);
connect(bodyUI->statusMessage, &QLineEdit::editingFinished,
@ -131,6 +185,7 @@ ProfileForm::ProfileForm(QWidget* parent)
connect(bodyUI->toxmeUpdateButton, &QPushButton::clicked,
this, &ProfileForm::onRegisterButtonClicked);
// TODO: Move to model
connect(core, &Core::usernameSet, this,
[=](const QString& val) { bodyUI->userName->setText(val); });
connect(core, &Core::statusMessageSet, this,
@ -147,8 +202,8 @@ ProfileForm::ProfileForm(QWidget* parent)
void ProfileForm::prFileLabelUpdate()
{
Nexus& nexus = Nexus::getInstance();
bodyUI->prFileLabel->setText(tr("Current profile: ") + nexus.getProfile()->getName() + ".tox");
const QString name = profileInfo->getProfileName();
bodyUI->prFileLabel->setText(tr("Current profile: ") + name + ".tox");
}
ProfileForm::~ProfileForm()
@ -201,40 +256,37 @@ bool ProfileForm::eventFilter(QObject* object, QEvent* event)
void ProfileForm::showProfilePictureContextMenu(const QPoint& point)
{
QPoint pos = profilePicture->mapToGlobal(point);
const QPoint pos = profilePicture->mapToGlobal(point);
QMenu contextMenu;
QAction* removeAction =
contextMenu.addAction(style()->standardIcon(QStyle::SP_DialogCancelButton), tr("Remove"));
QAction* selectedItem = contextMenu.exec(pos);
const QIcon icon = style()->standardIcon(QStyle::SP_DialogCancelButton);
const QAction* removeAction = contextMenu.addAction(icon, tr("Remove"));
const QAction* selectedItem = contextMenu.exec(pos);
if (selectedItem == removeAction)
Nexus::getProfile()->removeAvatar();
if (selectedItem == removeAction) {
profileInfo->removeAvatar();
}
}
void ProfileForm::copyIdClicked()
{
QString txt = toxId->text();
txt.remove(QRegularExpression("<[^>]*>"));
QApplication::clipboard()->setText(txt, QClipboard::Clipboard);
if (QApplication::clipboard()->supportsSelection())
QApplication::clipboard()->setText(txt, QClipboard::Selection);
profileInfo->copyId();
if (!hasCheck) {
bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text() + "");
hasCheck = true;
}
timer.start();
}
void ProfileForm::onUserNameEdited()
{
Core::getInstance()->setUsername(bodyUI->userName->text());
profileInfo->setUsername(bodyUI->userName->text());
}
void ProfileForm::onStatusMessageEdited()
{
Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text());
profileInfo->setStatusMessage(bodyUI->statusMessage->text());
}
void ProfileForm::onSelfAvatarLoaded(const QPixmap& pic)
@ -259,138 +311,89 @@ void ProfileForm::setToxId(const ToxId& id)
void ProfileForm::onAvatarClicked()
{
auto picToPng = [](QPixmap pic) {
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
return bytes;
};
const QString filter = Nexus::getSupportedImageFilter();
const QString path = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Choose a profile picture"),
QDir::homePath(), filter, nullptr);
QString path = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Choose a profile picture"),
QDir::homePath(), Nexus::getSupportedImageFilter(), 0);
if (path.isEmpty())
return;
QFile file(path);
file.open(QIODevice::ReadOnly);
if (!file.isOpen()) {
GUI::showError(tr("Error"), tr("Unable to open this file."));
const IProfileInfo::SetAvatarResult result = profileInfo->setAvatar(path);
if (result == IProfileInfo::SetAvatarResult::OK) {
return;
}
QPixmap pic;
if (!pic.loadFromData(file.readAll())) {
GUI::showError(tr("Error"), tr("Unable to read this image."));
return;
}
// 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"),
tr("The supplied image is too large.\nPlease use another image."));
return;
}
Nexus::getProfile()->setAvatar(bytes, core->getSelfPublicKey());
GUI::showError(tr("Error"), SET_AVATAR_ERROR[result]);
}
void ProfileForm::onRenameClicked()
{
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);
const QString cur = profileInfo->getProfileName();
const QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur);
const QString name = QInputDialog::getText(this, title, title + ":");
if (name.isEmpty()) {
return;
}
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 {
prFileLabelUpdate();
break;
}
} while (true);
const IProfileInfo::RenameResult result = profileInfo->renameProfile(name);
if (result == IProfileInfo::RenameResult::OK) {
return;
}
const QPair<QString, QString> error = RENAME_ERROR[result];
GUI::showError(error.first, error.second.arg(name));
prFileLabelUpdate();
}
void ProfileForm::onExportClicked()
{
QString current = Nexus::getProfile()->getName() + Core::TOX_EXT;
QString path = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Export profile", "save dialog title"),
QDir::home().filePath(current),
tr("Tox save file (*.tox)", "save dialog filter"), 0);
if (!path.isEmpty()) {
if (!Nexus::tryRemoveFile(path)) {
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;
}
if (!QFile::copy(Settings::getInstance().getSettingsDirPath() + current, path))
GUI::showWarning(tr("Failed to copy file"),
tr("The file you chose could not be written to."));
const QString current = profileInfo->getProfileName() + Core::TOX_EXT;
//:save dialog title
const QString path = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Export profile"),
QDir::home().filePath(current),
//: save dialog filter
tr("Tox save file (*.tox)"), nullptr);
const IProfileInfo::SaveResult result = profileInfo->exportProfile(path);
if (result == IProfileInfo::SaveResult::OK) {
return;
}
const QPair<QString, QString> error = SAVE_ERROR[result];
GUI::showWarning(error.first, error.second);
}
void ProfileForm::onDeleteClicked()
{
if (GUI::askQuestion(tr("Really delete profile?", "deletion confirmation title"),
tr("Are you sure you want to delete this profile?",
"deletion confirmation text"))) {
Nexus& nexus = Nexus::getInstance();
QVector<QString> manualDeleteFiles = nexus.getProfile()->remove();
if (!manualDeleteFiles.empty()) {
QString message =
tr("The following files could not be deleted:", "deletion failed text part 1") + "\n\n";
for (auto& file : manualDeleteFiles) {
message = message + file + "\n";
}
message =
message + "\n" + tr("Please manually remove them.", "deletion failed text part 2");
GUI::showError(tr("Files could not be deleted!", "deletion failed title"), message);
}
nexus.showLoginLater();
const QString title = tr("Really delete profile?", "deletion confirmation title");
const QString question = tr("Are you sure you want to delete this profile?",
"deletion confirmation text");
if (!GUI::askQuestion(title, question)) {
return;
}
// TODO: Use QStringList
const QVector<QString> manualDeleteFiles = profileInfo->removeProfile();
if (manualDeleteFiles.empty()) {
return;
}
//: deletion failed text part 1
QString message = tr("The following files could not be deleted:") + "\n\n";
for (const QString& file : manualDeleteFiles) {
message += file + "\n";
}
//: deletion failed text part 2
message += "\n" + tr("Please manually remove them.");
GUI::showError(tr("Files could not be deleted!", "deletion failed title"), message);
}
void ProfileForm::onLogoutClicked()
{
Nexus& nexus = Nexus::getInstance();
Settings::getInstance().saveGlobal();
nexus.showLoginLater();
profileInfo->logout();
}
void ProfileForm::setPasswordButtonsText()
{
if (Nexus::getProfile()->isEncrypted()) {
if (profileInfo->isEncrypted()) {
bodyUI->changePassButton->setText(tr("Change password", "button text"));
bodyUI->deletePassButton->setVisible(true);
} else {
@ -401,61 +404,55 @@ void ProfileForm::setPasswordButtonsText()
void ProfileForm::onCopyQrClicked()
{
QApplication::clipboard()->setImage(*qr->getImage());
profileInfo->copyQr(*qr->getImage());
}
void ProfileForm::onSaveQrClicked()
{
QString current = Nexus::getProfile()->getName() + ".png";
QString path = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Save", "save qr image"),
QDir::home().filePath(current),
tr("Save QrCode (*.png)", "save dialog filter"), 0);
if (!path.isEmpty()) {
if (!Nexus::tryRemoveFile(path)) {
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;
}
if (!qr->saveImage(path))
GUI::showWarning(tr("Failed to copy file"),
tr("The file you chose could not be written to."));
const QString current = profileInfo->getProfileName() + ".png";
const QString path = QFileDialog::getSaveFileName(
Q_NULLPTR, tr("Save", "save qr image"), QDir::home().filePath(current),
tr("Save QrCode (*.png)", "save dialog filter"), nullptr);
const IProfileInfo::SaveResult result = profileInfo->saveQr(*qr->getImage(), path);
if (result == IProfileInfo::SaveResult::OK) {
return;
}
const QPair<QString, QString> error = SAVE_ERROR[result];
GUI::showWarning(error.first, error.second);
}
void ProfileForm::onDeletePassClicked()
{
Profile* pro = Nexus::getProfile();
if (!pro->isEncrypted()) {
if (!profileInfo->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")))
const QString title = tr("Really delete password?", "deletion confirmation title");
//: deletion confirmation text
const QString body = tr("Are you sure you want to delete your password?");
if (!GUI::askQuestion(title, body)) {
return;
}
QString errorMsg = pro->setPassword(QString());
if (!errorMsg.isEmpty()) {
GUI::showInfo(tr("Couldn't change password"), errorMsg);
if (!profileInfo->deletePassword()) {
GUI::showInfo(CAN_NOT_CHANGE_PASSWORD.first, CAN_NOT_CHANGE_PASSWORD.second);
}
}
void ProfileForm::onChangePassClicked()
{
Profile* p = Nexus::getProfile();
SetPasswordDialog* dialog =
new SetPasswordDialog(tr("Please enter a new password."), QString(), 0);
int r = dialog->exec();
if (r == QDialog::Rejected)
const QString title = tr("Please enter a new password.");
SetPasswordDialog* dialog = new SetPasswordDialog(title, QString{}, nullptr);
if (dialog->exec() == QDialog::Rejected) {
return;
}
QString newPass = dialog->getPassword();
QString errorMsg = p->setPassword(newPass);
if (!errorMsg.isEmpty()) {
GUI::showInfo(tr("Couldn't change password"), errorMsg);
if (!profileInfo->setPassword(newPass)) {
GUI::showInfo(CAN_NOT_CHANGE_PASSWORD.first, CAN_NOT_CHANGE_PASSWORD.second);
}
}
@ -506,8 +503,9 @@ void ProfileForm::showExistingToxme()
void ProfileForm::onRegisterButtonClicked()
{
QString name = bodyUI->toxmeUsername->text();
if (name.isEmpty())
if (name.isEmpty()) {
return;
}
bodyUI->toxmeRegisterButton->setEnabled(false);
bodyUI->toxmeUpdateButton->setEnabled(false);

View File

@ -27,10 +27,10 @@
#include <QTimer>
#include <QVBoxLayout>
class CroppingLabel;
class Core;
class MaskablePixmapWidget;
class ContentLayout;
class CroppingLabel;
class IProfileInfo;
class MaskablePixmapWidget;
namespace Ui {
class IdentitySettings;
@ -54,7 +54,7 @@ class ProfileForm : public QWidget
{
Q_OBJECT
public:
explicit ProfileForm(QWidget* parent = nullptr);
ProfileForm(IProfileInfo* profileInfo, QWidget* parent = nullptr);
~ProfileForm();
virtual void show() final
{
@ -98,6 +98,7 @@ private:
bool hasCheck = false;
QRWidget* qr;
ClickableTE* toxId;
IProfileInfo* profileInfo;
void showRegisterToxme();
};

View File

@ -73,6 +73,8 @@
#include "src/widget/translator.h"
#include "tool/removefrienddialog.h"
#include <src/model/profile/profileinfo.h>
bool toxActivateEventHandler(const QByteArray&)
{
Widget* widget = Nexus::getDesktopGUI();
@ -228,12 +230,14 @@ void Widget::init()
filesForm = new FilesForm();
addFriendForm = new AddFriendForm;
groupInviteForm = new GroupInviteForm;
profileForm = new ProfileForm();
Profile* profile = Nexus::getProfile();
profileInfo = new ProfileInfo(profile);
profileForm = new ProfileForm(profileInfo);
// connect logout tray menu action
connect(actionLogout, &QAction::triggered, profileForm, &ProfileForm::onLogoutClicked);
Profile* profile = Nexus::getProfile();
connect(profile, &Profile::selfAvatarChanged, profileForm, &ProfileForm::onSelfAvatarLoaded);
const Settings& s = Settings::getInstance();

View File

@ -38,32 +38,33 @@ namespace Ui {
class MainWindow;
}
class AddFriendForm;
class Camera;
class ChatForm;
class GenericChatroomWidget;
class CircleWidget;
class ContentDialog;
class ContentLayout;
class Core;
class FilesForm;
class Friend;
class FriendListWidget;
class FriendWidget;
class GroupWidget;
class GenericChatroomWidget;
class Group;
class GroupInvite;
class Friend;
class QSplitter;
class VideoSurface;
class QMenu;
class Core;
class Camera;
class FriendListWidget;
class MaskablePixmapWidget;
class QTimer;
class SystemTrayIcon;
class FilesForm;
class ProfileForm;
class SettingsWidget;
class AddFriendForm;
class GroupInviteForm;
class CircleWidget;
class GroupWidget;
class MaskablePixmapWidget;
class ProfileForm;
class ProfileInfo;
class QActionGroup;
class ContentLayout;
class ContentDialog;
class QMenu;
class QPushButton;
class QSplitter;
class QTimer;
class SettingsWidget;
class SystemTrayIcon;
class VideoSurface;
class Widget final : public QMainWindow
{
@ -276,7 +277,10 @@ private:
ContentLayout* contentLayout;
AddFriendForm* addFriendForm;
GroupInviteForm* groupInviteForm;
ProfileInfo* profileInfo;
ProfileForm* profileForm;
QPointer<SettingsWidget> settingsWidget;
FilesForm* filesForm;
static Widget* instance;