From 4a11a0eb22766836f30584b5c9ccf69d271944ff Mon Sep 17 00:00:00 2001 From: Diadlo Date: Sat, 7 Oct 2017 14:42:32 +0300 Subject: [PATCH] refactor(profileinfo): Add profile info model class --- CMakeLists.txt | 3 + src/model/profile/iprofileinfo.h | 60 ++++++ src/model/profile/profileinfo.cpp | 298 ++++++++++++++++++++++++++++++ src/model/profile/profileinfo.h | 54 ++++++ 4 files changed, 415 insertions(+) create mode 100644 src/model/profile/iprofileinfo.h create mode 100644 src/model/profile/profileinfo.cpp create mode 100644 src/model/profile/profileinfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c7dc6e2a..042b6ff08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,9 @@ set(${PROJECT_NAME}_SOURCES src/model/group.cpp src/model/group.h src/model/interface.h + src/model/profile/iprofileinfo.h + src/model/profile/profileinfo.cpp + src/model/profile/profileinfo.h src/net/autoupdate.cpp src/net/autoupdate.h src/net/avatarbroadcaster.cpp diff --git a/src/model/profile/iprofileinfo.h b/src/model/profile/iprofileinfo.h new file mode 100644 index 000000000..1fdd31a71 --- /dev/null +++ b/src/model/profile/iprofileinfo.h @@ -0,0 +1,60 @@ +/* + Copyright © 2017 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 qTox. If not, see . +*/ + +#include + +class ToxId; + +class IProfileInfo : public QObject +{ + Q_OBJECT +public: + enum class RenameResult { + OK, EmptyName, ProfileAlreadyExists, Error + }; + + enum class SaveResult { + OK, EmptyPath, NoWritePermission, Error + }; + + enum class SetAvatarResult { + OK, EmptyPath, CanNotOpen, CanNotRead, TooLarge + }; + + virtual bool setPassword(const QString& password) = 0; + virtual bool deletePassword() = 0; + virtual bool isEncrypted() const = 0; + + virtual void copyId() const = 0; + + virtual void setUsername(const QString& name) = 0; + virtual void setStatusMessage(const QString& status) = 0; + + virtual QString getProfileName() const = 0; + virtual RenameResult renameProfile(const QString& name) = 0; + virtual SaveResult exportProfile(const QString& path) const = 0; + virtual QVector removeProfile() = 0; + virtual void logout() = 0; + + virtual void copyQr(const QImage& image) const = 0; + virtual SaveResult saveQr(const QImage& image, const QString& path) const = 0; + + virtual SetAvatarResult setAvatar(const QString& path) = 0; + virtual void removeAvatar() = 0; +}; diff --git a/src/model/profile/profileinfo.cpp b/src/model/profile/profileinfo.cpp new file mode 100644 index 000000000..620a31296 --- /dev/null +++ b/src/model/profile/profileinfo.cpp @@ -0,0 +1,298 @@ +/* + Copyright © 2017 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 qTox. If not, see . +*/ + +#include "profileinfo.h" +#include "src/core/core.h" +#include "src/persistence/profile.h" +#include "src/persistence/settings.h" +#include "src/nexus.h" + +#include +#include +#include +#include + +/** + * @class ProfileInfo + * @brief Implement interface, that provides invormation about self profile. + * Also, provide methods to work with profile file. + * @note Should be used only when QAppliaction constructed. + */ + +/** + * @brief ProfileInfo constructor. + * @param profile Pointer to Profile. + * @note All pointers parameters shouldn't be null. + */ + +ProfileInfo::ProfileInfo(Profile *profile) + : profile{profile} +{ +} + +/** + * @brief Set a user password for profile. + * @param password New password. + * @return True on success, false otherwise. + */ +bool ProfileInfo::setPassword(const QString &password) +{ + QString errorMsg = profile->setPassword(password); + return errorMsg.isEmpty(); +} + +/** + * @brief Delete a user password for profile. + * @return True on success, false otherwise. + */ +bool ProfileInfo::deletePassword() +{ + QString errorMsg = profile->setPassword(""); + return errorMsg.isEmpty(); +} + +/** + * @brief Check if current profile is encrypted. + * @return True if encrypted, false otherwise. + */ +bool ProfileInfo::isEncrypted() const +{ + return profile->isEncrypted(); +} + +/** + * @brief Copy self ToxId to clipboard. + */ +void ProfileInfo::copyId() const +{ + ToxId selfId = core->getSelfId(); + QString txt = selfId.toString(); + QClipboard* clip = QApplication::clipboard(); + clip->setText(txt, QClipboard::Clipboard); + if (clip->supportsSelection()) { + clip->setText(txt, QClipboard::Selection); + } +} + +/** + * @brief Set self user name. + * @param name New name. + */ +void ProfileInfo::setUsername(const QString &name) +{ + core->setUsername(name); +} + +/** + * @brief Set self status message. + * @param status New status message. + */ +void ProfileInfo::setStatusMessage(const QString &status) +{ + core->setStatusMessage(status); +} + +/** + * @brief Get name of tox profile file. + * @return Profile name. + */ +QString ProfileInfo::getProfileName() const +{ + return profile->getName(); +} + +/** + * @brief Rename profile file. + * @param name New profile name. + * @return Result code of rename operation. + */ +IProfileInfo::RenameResult ProfileInfo::renameProfile(const QString &name) +{ + QString cur = profile->getName(); + if (name.isEmpty()) { + return RenameResult::EmptyName; + } + + QString newName = Core::sanitize(name); + + if (Profile::exists(newName)) { + return RenameResult::ProfileAlreadyExists; + } + + if (!profile->rename(name)) { + return RenameResult::Error; + } + + return RenameResult::OK; +} + +/** + * @brief Save profile in cusom place. + * @param path Path to save profile. + * @return Result code of save operation. + */ +IProfileInfo::SaveResult ProfileInfo::exportProfile(const QString &path) const +{ + QString current = profile->getName() + Core::TOX_EXT; + if (path.isEmpty()) { + return SaveResult::EmptyPath; + } + + if (!Nexus::tryRemoveFile(path)) { + return SaveResult::NoWritePermission; + } + + if (!QFile::copy(Settings::getInstance().getSettingsDirPath() + current, path)) { + return SaveResult::Error; + } + + return SaveResult::OK; +} + +/** + * @brief Remove profile. + * @return List of files, which can't be removed automaticaly. + */ +// TODO: Use QStringList +QVector ProfileInfo::removeProfile() +{ + QVector manualDeleteFiles = profile->remove(); + Nexus::getInstance().showLoginLater(); + return manualDeleteFiles; +} + +/** + * @brief Log out from current profile. + */ +void ProfileInfo::logout() +{ + Settings::getInstance().saveGlobal(); + Nexus::getInstance().showLoginLater(); +} + +/** + * @brief Copy image to clipboard. + * @param image Image to copy. + */ +void ProfileInfo::copyQr(const QImage& image) const +{ + QApplication::clipboard()->setImage(image); +} + +/** + * @brief Save image to file. + * @param image Image to save. + * @param path Path to save. + * @return Result code of save operation. + */ +IProfileInfo::SaveResult ProfileInfo::saveQr(const QImage& image, const QString& path) const +{ + QString current = profile->getName() + ".png"; + if (path.isEmpty()) { + return SaveResult::EmptyPath; + } + + if (!Nexus::tryRemoveFile(path)) { + return SaveResult::NoWritePermission; + } + + // nullptr - image format same as file extension, + // 75-quality, png file is ~6.3kb + if (!image.save(path, nullptr, 75)) { + return SaveResult::Error; + } + + return SaveResult::OK; +} + +/** + * @brief Convert QPixmap to png image. + * @param pic Picture to convert. + * @return Byte array with png image. + */ +QByteArray picToPng(const QPixmap& pic) +{ + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + pic.save(&buffer, "PNG"); + buffer.close(); + return bytes; +}; + +/** + * @brief Set self avatar. + * @param path Path to image, which should be the new avatar. + * @return Code of set avatar operation. + */ +IProfileInfo::SetAvatarResult ProfileInfo::setAvatar(const QString &path) +{ + if (path.isEmpty()) { + return SetAvatarResult::EmptyPath; + } + + QFile file(path); + file.open(QIODevice::ReadOnly); + if (!file.isOpen()) { + return SetAvatarResult::CanNotOpen; + } + + QPixmap pic; + if (!pic.loadFromData(file.readAll())) { + return SetAvatarResult::CanNotRead; + } + + // Limit the avatar size to 64kB + // We do a first rescale to 256x256 in case the image was huge, then keep tryng from here + // TODO: Refactor + 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) { + return SetAvatarResult::TooLarge; + } + + Core* core = Core::getInstance(); + profile->setAvatar(bytes, core->getSelfPublicKey()); + return SetAvatarResult::OK; +} + +/** + * @brief Remove self avatar. + */ +void ProfileInfo::removeAvatar() +{ + profile->removeAvatar(); +} diff --git a/src/model/profile/profileinfo.h b/src/model/profile/profileinfo.h new file mode 100644 index 000000000..3786e9270 --- /dev/null +++ b/src/model/profile/profileinfo.h @@ -0,0 +1,54 @@ +/* + Copyright © 2017 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 qTox. If not, see . +*/ + +#include "iprofileinfo.h" + +class ToxId; +class QPoint; +class Profile; + +class ProfileInfo : public IProfileInfo +{ +public: + ProfileInfo(Profile* profile); + + bool setPassword(const QString& password) override; + bool deletePassword() override; + bool isEncrypted() const override; + + void copyId() const override; + + void setUsername(const QString& name) override; + void setStatusMessage(const QString& status) override; + + QString getProfileName() const override; + RenameResult renameProfile(const QString& name) override; + SaveResult exportProfile(const QString& path) const override; + QVector removeProfile() override; + void logout() override; + + void copyQr(const QImage& image) const override; + SaveResult saveQr(const QImage& image, const QString& path) const override; + + SetAvatarResult setAvatar(const QString& path) override; + void removeAvatar() override; + +private: + Profile* const profile; +};