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

feat(paths): create class to combine all qTox managed paths

This will be the central location for all of qTox managed directories.
This commit is contained in:
sudden6 2018-11-08 21:47:44 +01:00
parent e1201f901f
commit 3ee8c665df
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
3 changed files with 271 additions and 0 deletions

View File

@ -319,6 +319,8 @@ set(${PROJECT_NAME}_SOURCES
src/persistence/ifriendsettings.h
src/persistence/offlinemsgengine.cpp
src/persistence/offlinemsgengine.h
src/persistence/paths.cpp
src/persistence/paths.h
src/persistence/profile.cpp
src/persistence/profile.h
src/persistence/profilelocker.cpp

234
src/persistence/paths.cpp Normal file
View File

@ -0,0 +1,234 @@
#include "paths.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QStandardPaths>
#include <QString>
#include <QStringBuilder>
#include <QStringList>
namespace {
const QLatin1Literal globalSettingsFile{"qtox.ini"};
const QLatin1Literal profileFolder{"profiles"};
const QLatin1Literal themeFolder{"themes"};
const QLatin1Literal avatarsFolder{"avatars"};
const QLatin1Literal transfersFolder{"transfers"};
const QLatin1Literal screenshotsFolder{"screenshots"};
// NOTE(sudden6): currently unused, but reflects the TCS at 2018-11
#ifdef Q_OS_WIN
const QLatin1Literal TCSToxFileFolder{"%APPDATA%/tox/"};
#elif defined(Q_OS_OSX)
const QLatin1Literal TCSToxFileFolder{"~/Library/Application Support/Tox"};
#else
const QLatin1Literal TCSToxFileFolder{"~/.config/tox/"};
#endif
} // namespace
/**
* @class Profile
* @brief Handles all qTox internal paths
*
* The qTox internal file layout starts at `<BASE_PATH>`. This directory is platform
* specific and depends on if qTox runs in portable mode.
*
* Example file layout for non-portable mode:
* @code
* <BASE_PATH>/themes/
* /profiles/
* /...
* @endcode
*
* Example file layout for portable mode:
* @code
* <BASE_PATH>/themes/
* /profiles/
* /qtox.ini
* @endcode
*
* All qTox or Tox specific directories should be looked up through this module.
*/
/**
* @brief Paths::makePaths Factory method for the Paths object
* @param mode
* @return Pointer to Paths object on success, nullptr else
*/
Paths* Paths::makePaths(Portable mode)
{
bool portable = false;
const QString basePortable = qApp->applicationDirPath();
const QString baseNonPortable = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
const QString portableSettingsPath = basePortable % QDir::separator() % globalSettingsFile;
switch (mode) {
case Portable::Portable:
qDebug() << "Forcing portable";
portable = true;
break;
case Portable::NonPortable:
qDebug() << "Forcing non-portable";
portable = false;
break;
case Portable::Auto:
// auto detect
if (QFile{portableSettingsPath}.exists()) {
qDebug() << "Automatic portable";
portable = true;
} else {
qDebug() << "Automatic non-portable";
portable = false;
}
break;
}
QString basePath = portable ? basePortable : baseNonPortable;
if (basePath.isEmpty()) {
qCritical() << "Couldn't find writeable path";
return nullptr;
}
return new Paths(basePath, portable);
}
Paths::Paths(const QString& basePath, bool portable)
: basePath{basePath}
, portable{portable}
{}
/**
* @brief Check if qTox is running in portable mode.
* @return True if running in portable mode, false else.
*/
bool Paths::isPortable() const
{
return portable;
}
/**
* @brief Returns the path to the global settings file "qtox.ini"
* @return The path to the folder.
*/
QString Paths::getGlobalSettingsPath() const
{
QString path;
if (portable) {
path = basePath;
} else {
path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
if (path.isEmpty()) {
qDebug() << "Can't find writable location for settings file";
return {};
}
}
// we assume a writeable path for portable mode
return path % QDir::separator() % globalSettingsFile;
}
/**
* @brief Get the folder where profile specific information is stored, e.g. <profile>.ini
* @return The path to the folder.
*/
QString Paths::getProfilesDir() const
{
return basePath % QDir::separator() % profileFolder % QDir::separator();
}
/**
* @brief Get the folder where the <profile>.tox file is stored
* @note Expect a change here, since TCS will probably be updated.
* @return The path to the folder on success, empty string else.
*/
QString Paths::getToxSaveDir() const
{
if (isPortable()) {
return basePath % QDir::separator() % profileFolder % QDir::separator();
}
// GenericDataLocation would be a better solution, but we keep this code for backward
// compatibility
// workaround for https://bugreports.qt-project.org/browse/QTBUG-38845
#ifdef Q_OS_WIN
// TODO(sudden6): this doesn't really follow the Tox Client Standard and probably
// breaks when %APPDATA% is changed
return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
+ QDir::separator() + "AppData" + QDir::separator() + "Roaming"
+ QDir::separator() + "tox")
+ QDir::separator();
#elif defined(Q_OS_OSX)
return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
+ QDir::separator() + "Library" + QDir::separator()
+ "Application Support" + QDir::separator() + "Tox")
+ QDir::separator();
#else
// TODO(sudden6): This does not respect the XDG_* environment variables and also
// stores user data in a config location
return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)
+ QDir::separator() + "tox")
+ QDir::separator();
#endif
}
/**
* @brief Get the folder where avatar files are stored
* @note Expect a change here, since TCS will probably be updated.
* @return The path to the folder on success, empty string else.
*/
QString Paths::getAvatarsDir() const
{
// follow the layout in
// https://tox.gitbooks.io/tox-client-standard/content/data_storage/export_format.html
QString path = getToxSaveDir();
if (path.isEmpty()) {
qDebug() << "Can't find location for avatars directory";
return {};
}
return path % QDir::separator() % avatarsFolder % QDir::separator();
}
/**
* @brief Get the folder where screenshots are stored
* @return The path to the folder.
*/
QString Paths::getScreenshotsDir() const
{
return basePath % QDir::separator() % screenshotsFolder % QDir::separator();
}
/**
* @brief Get the folder where file transfer data is stored
* @return The path to the folder.
*/
QString Paths::getTransfersDir() const
{
return basePath % QDir::separator() % transfersFolder % QDir::separator();
}
/**
* @brief Get a prioritized list with directories that contain themes.
* @return A list of directories sorted from most important to least important.
* @note Users of this function should use the theme from the folder that appears first in the list.
*/
QStringList Paths::getThemeDirs() const
{
QStringList themeFolders{};
if (!isPortable()) {
themeFolders += QStandardPaths::locate(QStandardPaths::AppDataLocation, themeFolder,
QStandardPaths::LocateDirectory);
}
// look for themes beside the qTox binary with lowest priority
const QString curPath = qApp->applicationDirPath();
themeFolders += curPath % QDir::separator() % themeFolder % QDir::separator();
return themeFolders;
}

35
src/persistence/paths.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef PATHS_H
#define PATHS_H
#include <QString>
#include <QStringList>
class Paths
{
public:
enum class Portable {
Auto, /** Auto detect if portable or non-portable */
Portable, /** Force portable mode */
NonPortable /** Force non-portable mode */
};
static Paths* makePaths(Portable mode = Portable::Auto);
bool isPortable() const;
QString getGlobalSettingsPath() const;
QString getProfilesDir() const;
QString getToxSaveDir() const;
QString getAvatarsDir() const;
QString getTransfersDir() const;
QStringList getThemeDirs() const;
QString getScreenshotsDir() const;
private:
Paths(const QString &basePath, bool portable);
private:
QString basePath{};
bool portable = false;
};
#endif // PATHS_H