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;
+};