qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
paths.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 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 "paths.h"
21 
22 #include <QApplication>
23 #include <QDebug>
24 #include <QDir>
25 #include <QFile>
26 #include <QStandardPaths>
27 #include <QString>
28 #include <QStringBuilder>
29 #include <QStringList>
30 #include <QSettings>
31 
32 #include <cassert>
33 
34 namespace {
35 const QLatin1String globalSettingsFile{"qtox.ini"};
36 const QLatin1String profileFolder{"profiles"};
37 const QLatin1String themeFolder{"themes"};
38 const QLatin1String avatarsFolder{"avatars"};
39 const QLatin1String transfersFolder{"transfers"};
40 const QLatin1String screenshotsFolder{"screenshots"};
41 
42 // NOTE(sudden6): currently unused, but reflects the TCS at 2018-11
43 #ifdef Q_OS_WIN
44 const QLatin1String TCSToxFileFolder{"%APPDATA%/tox/"};
45 #elif defined(Q_OS_OSX)
46 const QLatin1String TCSToxFileFolder{"~/Library/Application Support/Tox"};
47 #else
48 const QLatin1String TCSToxFileFolder{"~/.config/tox/"};
49 #endif
50 } // namespace
51 
79 namespace {
80  using Portable = Paths::Portable;
81  bool portableFromMode(Portable mode)
82  {
83  bool portable = false;
84  const QString basePortable = qApp->applicationDirPath();
85  const QString baseNonPortable = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
86  const QString portableSettingsPath = basePortable % QDir::separator() % globalSettingsFile;
87 
88  switch (mode) {
89  case Portable::Portable:
90  qDebug() << "Forcing portable";
91  return true;
92  case Portable::NonPortable:
93  qDebug() << "Forcing non-portable";
94  return false;
95  case Portable::Auto:
96  if (QFile(portableSettingsPath).exists()) {
97  QSettings ps(portableSettingsPath, QSettings::IniFormat);
98  ps.setIniCodec("UTF-8");
99  ps.beginGroup("Advanced");
100  portable = ps.value("makeToxPortable", false).toBool();
101  ps.endGroup();
102  } else {
103  portable = false;
104  }
105  qDebug()<< "Auto portable mode:" << portable;
106  return portable;
107  }
108  assert(!"Unhandled enum class Paths::Portable value");
109  return false;
110  }
111 
112  QString basePathFromPortable(bool portable)
113  {
114  const QString basePortable = qApp->applicationDirPath();
115  const QString baseNonPortable = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
116  QString basePath = portable ? basePortable : baseNonPortable;
117  if (basePath.isEmpty()) {
118  assert(!"Couldn't find writeable path");
119  qCritical() << "Couldn't find writable path";
120  }
121  return basePath;
122  }
123 } // namespace
124 
126 {
127  portable = portableFromMode(mode);
128  basePath = basePathFromPortable(portable);
129 }
130 
136 bool Paths::setPortable(bool newPortable)
137 {
138  auto oldVal = portable.exchange(newPortable);
139  if (oldVal != newPortable) {
140  return true;
141  }
142  return false;
143 }
144 
149 bool Paths::isPortable() const
150 {
151  return portable;
152 }
153 
154 #if PATHS_VERSION_TCS_COMPLIANT
155 
159 QString Paths::getGlobalSettingsPath() const
160 {
161  QString path;
162 
163  if (portable) {
164  path = basePath;
165  } else {
166  path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
167  if (path.isEmpty()) {
168  qDebug() << "Can't find writable location for settings file";
169  return {};
170  }
171  }
172 
173  // we assume a writeable path for portable mode
174 
175  return path % QDir::separator() % globalSettingsFile;
176 }
177 
182 QString Paths::getProfilesDir() const
183 {
184  return basePath % QDir::separator() % profileFolder % QDir::separator();
185 }
186 
192 QString Paths::getToxSaveDir() const
193 {
194  if (isPortable()) {
195  return basePath % QDir::separator() % profileFolder % QDir::separator();
196  }
197 
198  // GenericDataLocation would be a better solution, but we keep this code for backward
199  // compatibility
200 
201 // workaround for https://bugreports.qt-project.org/browse/QTBUG-38845
202 #ifdef Q_OS_WIN
203  // TODO(sudden6): this doesn't really follow the Tox Client Standard and probably
204  // breaks when %APPDATA% is changed
205  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
206  + QDir::separator() + "AppData" + QDir::separator() + "Roaming"
207  + QDir::separator() + "tox")
208  + QDir::separator();
209 #elif defined(Q_OS_OSX)
210  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
211  + QDir::separator() + "Library" + QDir::separator()
212  + "Application Support" + QDir::separator() + "Tox")
213  + QDir::separator();
214 #else
215  // TODO(sudden6): This does not respect the XDG_* environment variables and also
216  // stores user data in a config location
217  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
218  + QDir::separator() + "tox")
219  + QDir::separator();
220 #endif
221 }
222 
228 QString Paths::getAvatarsDir() const
229 {
230  // follow the layout in
231  // https://tox.gitbooks.io/tox-client-standard/content/data_storage/export_format.html
232  QString path = getToxSaveDir();
233  if (path.isEmpty()) {
234  qDebug() << "Can't find location for avatars directory";
235  return {};
236  }
237 
238  return path % avatarsFolder % QDir::separator();
239 }
240 
245 QString Paths::getScreenshotsDir() const
246 {
247  return basePath % QDir::separator() % screenshotsFolder % QDir::separator();
248 }
249 
254 QString Paths::getTransfersDir() const
255 {
256  return basePath % QDir::separator() % transfersFolder % QDir::separator();
257 }
258 
264 QStringList Paths::getThemeDirs() const
265 {
266  QStringList themeFolders{};
267 
268  if (!isPortable()) {
269  themeFolders += QStandardPaths::locate(QStandardPaths::AppDataLocation, themeFolder,
270  QStandardPaths::LocateDirectory);
271  }
272 
273  // look for themes beside the qTox binary with lowest priority
274  const QString curPath = qApp->applicationDirPath();
275  themeFolders += curPath % QDir::separator() % themeFolder % QDir::separator();
276 
277  return themeFolders;
278 }
279 
280 #else
281 
287 {
288  if (portable)
289  return qApp->applicationDirPath() + QDir::separator();
290 
291 // workaround for https://bugreports.qt-project.org/browse/QTBUG-38845
292 #ifdef Q_OS_WIN
293  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
294  + QDir::separator() + "AppData" + QDir::separator() + "Roaming"
295  + QDir::separator() + "tox")
296  + QDir::separator();
297 #elif defined(Q_OS_OSX)
298  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
299  + QDir::separator() + "Library" + QDir::separator()
300  + "Application Support" + QDir::separator() + "Tox")
301  + QDir::separator();
302 #else
303  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
304  + QDir::separator() + "tox")
305  + QDir::separator();
306 #endif
307 }
308 
315 {
316  if (portable)
317  return qApp->applicationDirPath() + QDir::separator();
318 
319 // workaround for https://bugreports.qt-project.org/browse/QTBUG-38845
320 #ifdef Q_OS_WIN
321  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
322  + QDir::separator() + "AppData" + QDir::separator() + "Roaming"
323  + QDir::separator() + "tox")
324  + QDir::separator();
325 #elif defined(Q_OS_OSX)
326  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
327  + QDir::separator() + "Library" + QDir::separator()
328  + "Application Support" + QDir::separator() + "Tox")
329  + QDir::separator();
330 #else
331  /*
332  * TODO: Change QStandardPaths::DataLocation to AppDataLocation when upgrate Qt to 5.4+
333  * For now we need support Qt 5.3, so we use deprecated DataLocation
334  * BTW, it's not a big deal since for linux AppDataLocation and DataLocation are equal
335  */
336  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
337  + QDir::separator();
338 #endif
339 }
340 
347 {
348  if (portable)
349  return qApp->applicationDirPath() + QDir::separator();
350 
351 // workaround for https://bugreports.qt-project.org/browse/QTBUG-38845
352 #ifdef Q_OS_WIN
353  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
354  + QDir::separator() + "AppData" + QDir::separator() + "Roaming"
355  + QDir::separator() + "tox")
356  + QDir::separator();
357 #elif defined(Q_OS_OSX)
358  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
359  + QDir::separator() + "Library" + QDir::separator()
360  + "Application Support" + QDir::separator() + "Tox")
361  + QDir::separator();
362 #else
363  return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
364  + QDir::separator();
365 #endif
366 }
367 
369 {
370  QDir dir(getSettingsDirPath());
371  constexpr static char nodesFileName[] = "bootstrapNodes.json";
372  return dir.filePath(nodesFileName);
373 }
374 
375 #endif // PATHS_VERSION_TCS_COMPLIANT
Paths::getSettingsDirPath
QString getSettingsDirPath() const
Get path to directory, where the settings files are stored.
Definition: paths.cpp:286
Paths::Paths
Paths(Portable mode=Portable::Auto)
Definition: paths.cpp:125
Paths::portable
std::atomic_bool portable
Definition: paths.h:59
Paths::setPortable
bool setPortable(bool portable)
Set paths to passed portable or system wide.
Definition: paths.cpp:136
paths.h
Paths::basePath
QString basePath
Definition: paths.h:58
Paths::isPortable
bool isPortable() const
Check if qTox is running in portable mode.
Definition: paths.cpp:149
Paths::getAppCacheDirPath
QString getAppCacheDirPath() const
Get path to directory, where the application cache are stored.
Definition: paths.cpp:346
Paths::Portable
Portable
Definition: paths.h:31
Paths::getUserNodesFilePath
QString getUserNodesFilePath() const
Definition: paths.cpp:368
Paths::getAppDataDirPath
QString getAppDataDirPath() const
Get path to directory, where the application data are stored.
Definition: paths.cpp:314