qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
profileinfo.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2017-2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "profileinfo.h"
21 #include "src/core/core.h"
22 #include "src/nexus.h"
26 
27 #include <QApplication>
28 #include <QBuffer>
29 #include <QClipboard>
30 #include <QFile>
31 #include <QImageReader>
32 
47  : profile{profile}
48  , core{core}
49 {
50  connect(core, &Core::idSet, this, &ProfileInfo::idChanged);
51  connect(core, &Core::usernameSet, this, &ProfileInfo::usernameChanged);
52  connect(core, &Core::statusMessageSet, this, &ProfileInfo::statusMessageChanged);
53 }
54 
60 bool ProfileInfo::setPassword(const QString& password)
61 {
62  QString errorMsg = profile->setPassword(password);
63  return errorMsg.isEmpty();
64 }
65 
71 {
72  QString errorMsg = profile->setPassword("");
73  return errorMsg.isEmpty();
74 }
75 
81 {
82  return profile->isEncrypted();
83 }
84 
88 void ProfileInfo::copyId() const
89 {
90  ToxId selfId = core->getSelfId();
91  QString txt = selfId.toString();
92  QClipboard* clip = QApplication::clipboard();
93  clip->setText(txt, QClipboard::Clipboard);
94  if (clip->supportsSelection()) {
95  clip->setText(txt, QClipboard::Selection);
96  }
97 }
98 
103 void ProfileInfo::setUsername(const QString& name)
104 {
105  core->setUsername(name);
106 }
107 
112 void ProfileInfo::setStatusMessage(const QString& status)
113 {
114  core->setStatusMessage(status);
115 }
116 
122 {
123  return profile->getName();
124 }
125 
131 static QString sanitize(const QString& src)
132 {
133  QString name = src;
134  // these are pretty much Windows banned filename characters
135  QList<QChar> banned{'/', '\\', ':', '<', '>', '"', '|', '?', '*'};
136  for (QChar c : banned) {
137  name.replace(c, '_');
138  }
139 
140  // also remove leading and trailing periods
141  if (name[0] == '.') {
142  name[0] = '_';
143  }
144 
145  if (name.endsWith('.')) {
146  name[name.length() - 1] = '_';
147  }
148 
149  return name;
150 }
151 
158 {
159  QString cur = profile->getName();
160  if (name.isEmpty()) {
162  }
163 
164  QString newName = sanitize(name);
165 
166  if (Profile::exists(newName)) {
168  }
169 
170  if (!profile->rename(name)) {
171  return RenameResult::Error;
172  }
173 
174  return RenameResult::OK;
175 }
176 
177 // TODO: Find out what is dangerous?
183 static bool tryRemoveFile(const QString& filepath)
184 {
185  QFile tmp(filepath);
186  bool writable = tmp.open(QIODevice::WriteOnly);
187  tmp.remove();
188  return writable;
189 }
190 
197 {
198  QString current = profile->getName() + Core::TOX_EXT;
199  if (path.isEmpty()) {
200  return SaveResult::EmptyPath;
201  }
202 
203  if (!tryRemoveFile(path)) {
205  }
206 
207  if (!QFile::copy(Settings::getInstance().getPaths().getSettingsDirPath() + current, path)) {
208  return SaveResult::Error;
209  }
210 
211  return SaveResult::OK;
212 }
213 
219 {
220  QStringList manualDeleteFiles = profile->remove();
221  QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin");
222  return manualDeleteFiles;
223 }
224 
229 {
230  // TODO(kriby): Refactor all of these invokeMethod calls with connect() properly when possible
232  QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin",
233  Q_ARG(QString, Settings::getInstance().getCurrentProfile()));
234 }
235 
240 void ProfileInfo::copyQr(const QImage& image) const
241 {
242  QApplication::clipboard()->setImage(image);
243 }
244 
251 IProfileInfo::SaveResult ProfileInfo::saveQr(const QImage& image, const QString& path) const
252 {
253  QString current = profile->getName() + ".png";
254  if (path.isEmpty()) {
255  return SaveResult::EmptyPath;
256  }
257 
258  if (!tryRemoveFile(path)) {
260  }
261 
262  // nullptr - image format same as file extension,
263  // 75-quality, png file is ~6.3kb
264  if (!image.save(path, nullptr, 75)) {
265  return SaveResult::Error;
266  }
267 
268  return SaveResult::OK;
269 }
270 
276 QByteArray picToPng(const QImage& pic)
277 {
278  QByteArray bytes;
279  QBuffer buffer(&bytes);
280  buffer.open(QIODevice::WriteOnly);
281  pic.save(&buffer, "PNG");
282  buffer.close();
283  return bytes;
284 }
285 
292 {
293  if (path.isEmpty()) {
295  }
296 
297  QFile file(path);
298  file.open(QIODevice::ReadOnly);
299  if (!file.isOpen()) {
301  }
302  QByteArray avatar;
303  const auto err = createAvatarFromFile(file, avatar);
304  if (err == SetAvatarResult::OK) {
305  profile->setAvatar(avatar);
306  }
307  return err;
308 }
309 
317 {
318  QByteArray fileContents{file.readAll()};
319  auto err = byteArrayToPng(fileContents, avatar);
320  if (err != SetAvatarResult::OK) {
321  return err;
322  }
323 
324  err = scalePngToAvatar(avatar);
325  return err;
326 }
327 
334 IProfileInfo::SetAvatarResult ProfileInfo::byteArrayToPng(QByteArray inData, QByteArray& outPng)
335 {
336  QBuffer inBuffer{&inData};
337  QImageReader reader{&inBuffer};
338  QImage image;
339  const auto format = reader.format();
340  // read whole image even if we're not going to use the QImage, to make sure the image is valid
341  if (!reader.read(&image)) {
343  }
344 
345  if (format == "png") {
346  // FIXME: re-encode the png even though inData is already valid. This strips the metadata
347  // since we don't have a good png metadata stripping method currently.
348  outPng = picToPng(image);
349  } else {
350  outPng = picToPng(image);
351  }
352  return SetAvatarResult::OK;
353 }
354 
355 /*
356  * @brief Scale a png to an acceptable file size.
357  * @param avatar byte array containing the avatar.
358  * @return SetAvatarResult
359  */
361 {
362  // We do a first rescale to 256x256 in case the image was huge, then keep tryng from here
363  constexpr int scaleSizes[] = {256, 128, 64, 32};
364 
365  for (auto scaleSize : scaleSizes) {
366  if (ToxClientStandards::IsValidAvatarSize(avatar.size()))
367  break;
368  QImage image;
369  image.loadFromData(avatar);
370  image = image.scaled(scaleSize, scaleSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
371  avatar = picToPng(image);
372  }
373 
374  // If this happens, you're really doing it on purpose.
375  if (!ToxClientStandards::IsValidAvatarSize(avatar.size())) {
377  }
378  return SetAvatarResult::OK;
379 }
380 
385 {
387 }
ProfileInfo::core
Core *const core
Definition: profileinfo.h:68
profile.h
ProfileInfo::deletePassword
bool deletePassword() override
Delete a user password for profile.
Definition: profileinfo.cpp:70
ToxId::toString
QString toString() const
Returns the Tox ID converted to QString. Is equal to getPublicKey() if the Tox ID was constructed fro...
Definition: toxid.cpp:160
IProfileInfo::SaveResult::EmptyPath
@ EmptyPath
ProfileInfo::ProfileInfo
ProfileInfo(Core *core, Profile *profile)
ProfileInfo constructor.
Definition: profileinfo.cpp:46
settings.h
IProfileInfo::RenameResult
RenameResult
Definition: iprofileinfo.h:31
ProfileInfo::createAvatarFromFile
IProfileInfo::SetAvatarResult createAvatarFromFile(QFile &file, QByteArray &avatar)
Create an avatar from an image file.
Definition: profileinfo.cpp:316
Profile
Handles all qTox internal paths.
Definition: profile.h:42
Profile::rename
bool rename(QString newName)
Tries to rename the profile.
Definition: profile.cpp:896
ProfileInfo::setStatusMessage
void setStatusMessage(const QString &status) override
Set self status message.
Definition: profileinfo.cpp:112
IProfileInfo::SaveResult::NoWritePermission
@ NoWritePermission
HistMessageContentType::file
@ file
Core::TOX_EXT
static const QString TOX_EXT
Definition: core.h:89
Profile::setPassword
QString setPassword(const QString &newPassword)
Changes the encryption password and re-saves everything with it.
Definition: profile.cpp:934
QList
Definition: friendlist.h:25
Profile::getName
QString getName() const
Definition: profile.cpp:435
ProfileInfo::saveQr
SaveResult saveQr(const QImage &image, const QString &path) const override
Save image to file.
Definition: profileinfo.cpp:251
IProfileInfo::SetAvatarResult::TooLarge
@ TooLarge
Profile::remove
QStringList remove()
Removes the profile permanently. Updates the profiles vector.
Definition: profile.cpp:847
Profile::removeSelfAvatar
void removeSelfAvatar()
Removes our own avatar.
Definition: profile.cpp:758
ProfileInfo::isEncrypted
bool isEncrypted() const override
Check if current profile is encrypted.
Definition: profileinfo.cpp:80
Profile::exists
static bool exists(QString name)
Definition: profile.cpp:804
ProfileInfo::copyQr
void copyQr(const QImage &image) const override
Copy image to clipboard.
Definition: profileinfo.cpp:240
IProfileInfo::SetAvatarResult::CanNotRead
@ CanNotRead
ToxClientStandards::IsValidAvatarSize
constexpr bool IsValidAvatarSize(uint64_t fileSize)
Definition: toxclientstandards.h:28
Core::getSelfId
ToxId getSelfId() const override
Returns our Tox ID.
Definition: core.cpp:1258
IProfileInfo::SaveResult
SaveResult
Definition: iprofileinfo.h:35
IProfileInfo::RenameResult::OK
@ OK
ProfileInfo::profile
Profile *const profile
Definition: profileinfo.h:67
ProfileInfo::copyId
void copyId() const override
Copy self ToxId to clipboard.
Definition: profileinfo.cpp:88
ProfileInfo::setUsername
void setUsername(const QString &name) override
Set self user name.
Definition: profileinfo.cpp:103
Core::usernameSet
void usernameSet(const QString &username)
ProfileInfo::scalePngToAvatar
IProfileInfo::SetAvatarResult scalePngToAvatar(QByteArray &avatar)
Definition: profileinfo.cpp:360
ProfileInfo::renameProfile
RenameResult renameProfile(const QString &name) override
Rename profile file.
Definition: profileinfo.cpp:157
Settings::saveGlobal
void saveGlobal()
Asynchronous, saves the global settings.
Definition: settings.cpp:582
ProfileInfo::setAvatar
SetAvatarResult setAvatar(const QString &path) override
Set self avatar.
Definition: profileinfo.cpp:291
IProfileInfo::RenameResult::EmptyName
@ EmptyName
ToxId
This class represents a Tox ID.
Definition: toxid.h:29
ProfileInfo::removeProfile
QStringList removeProfile() override
Remove profile.
Definition: profileinfo.cpp:218
Settings::getInstance
static Settings & getInstance()
Returns the singleton instance.
Definition: settings.cpp:88
picToPng
QByteArray picToPng(const QImage &pic)
Convert QImage to png image.
Definition: profileinfo.cpp:276
ProfileInfo::getProfileName
QString getProfileName() const override
Get name of tox profile file.
Definition: profileinfo.cpp:121
Core::statusMessageSet
void statusMessageSet(const QString &message)
Core::setUsername
void setUsername(const QString &username)
Definition: core.cpp:1235
ProfileInfo::byteArrayToPng
IProfileInfo::SetAvatarResult byteArrayToPng(QByteArray inData, QByteArray &outPng)
Create a png from image data.
Definition: profileinfo.cpp:334
ProfileInfo::removeAvatar
void removeAvatar() override
Remove self avatar.
Definition: profileinfo.cpp:384
IProfileInfo::SetAvatarResult
SetAvatarResult
Definition: iprofileinfo.h:39
ProfileInfo::exportProfile
SaveResult exportProfile(const QString &path) const override
Save profile in custom place.
Definition: profileinfo.cpp:196
IProfileInfo::SetAvatarResult::CanNotOpen
@ CanNotOpen
Core::idSet
void idSet(const ToxId &id)
IProfileInfo::SetAvatarResult::OK
@ OK
core.h
IProfileInfo::RenameResult::Error
@ Error
Nexus::getInstance
static Nexus & getInstance()
Returns the singleton instance.
Definition: nexus.cpp:259
profileinfo.h
ProfileInfo::setPassword
bool setPassword(const QString &password) override
Set a user password for profile.
Definition: profileinfo.cpp:60
Profile::setAvatar
void setAvatar(QByteArray pic)
Sets our own avatar.
Definition: profile.cpp:648
Core::setStatusMessage
void setStatusMessage(const QString &message)
Definition: core.cpp:1327
ProfileInfo::logout
void logout() override
Log out from current profile.
Definition: profileinfo.cpp:228
toxclientstandards.h
Profile::isEncrypted
bool isEncrypted() const
Checks, if profile has a password.
Definition: profile.cpp:814
nexus.h
IProfileInfo::SaveResult::Error
@ Error
Core
Definition: core.h:59
IProfileInfo::RenameResult::ProfileAlreadyExists
@ ProfileAlreadyExists
IProfileInfo::SetAvatarResult::EmptyPath
@ EmptyPath
IProfileInfo::SaveResult::OK
@ OK