mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-02-11 14:24:23 +00:00
Merge pull request #5214 from evsh/adjustable-config-name
Implement configurations and portable mode. Closes #465
This commit is contained in:
commit
07af8c9648
@ -4,11 +4,13 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|||||||
set(QBT_APP_HEADERS
|
set(QBT_APP_HEADERS
|
||||||
application.h
|
application.h
|
||||||
filelogger.h
|
filelogger.h
|
||||||
|
options.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QBT_APP_SOURCES
|
set(QBT_APP_SOURCES
|
||||||
application.cpp
|
application.cpp
|
||||||
filelogger.cpp
|
filelogger.cpp
|
||||||
|
options.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,11 +16,13 @@ usesystemqtsingleapplication {
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/application.h \
|
$$PWD/application.h \
|
||||||
$$PWD/filelogger.h
|
$$PWD/filelogger.h \
|
||||||
|
$$PWD/options.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/application.cpp \
|
$$PWD/application.cpp \
|
||||||
$$PWD/filelogger.cpp \
|
$$PWD/filelogger.cpp \
|
||||||
|
$$PWD/options.cpp \
|
||||||
$$PWD/main.cpp
|
$$PWD/main.cpp
|
||||||
|
|
||||||
unix: HEADERS += $$PWD/stacktrace.h
|
unix: HEADERS += $$PWD/stacktrace.h
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/settingsstorage.h"
|
#include "base/settingsstorage.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/iconprovider.h"
|
#include "base/iconprovider.h"
|
||||||
@ -93,17 +94,34 @@ namespace
|
|||||||
|
|
||||||
const QString LOG_FOLDER("logs");
|
const QString LOG_FOLDER("logs");
|
||||||
const char PARAMS_SEPARATOR[] = "|";
|
const char PARAMS_SEPARATOR[] = "|";
|
||||||
|
|
||||||
|
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile");
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(const QString &id, int &argc, char **argv)
|
Application::Application(const QString &id, int &argc, char **argv)
|
||||||
: BaseApplication(id, argc, argv)
|
: BaseApplication(id, argc, argv)
|
||||||
, m_running(false)
|
, m_running(false)
|
||||||
, m_shutdownAct(ShutdownDialogAction::Exit)
|
, m_shutdownAct(ShutdownDialogAction::Exit)
|
||||||
|
, m_commandLineArgs(parseCommandLine(this->arguments()))
|
||||||
{
|
{
|
||||||
|
setApplicationName("qBittorrent");
|
||||||
|
validateCommandLineParameters();
|
||||||
|
|
||||||
|
QString profileDir = m_commandLineArgs.portableMode
|
||||||
|
? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
|
||||||
|
: m_commandLineArgs.profileDir;
|
||||||
|
|
||||||
|
Profile::initialize(profileDir, m_commandLineArgs.configurationName,
|
||||||
|
m_commandLineArgs.relativeFastresumePaths || m_commandLineArgs.portableMode);
|
||||||
|
|
||||||
Logger::initInstance();
|
Logger::initInstance();
|
||||||
SettingsStorage::initInstance();
|
SettingsStorage::initInstance();
|
||||||
Preferences::initInstance();
|
Preferences::initInstance();
|
||||||
|
|
||||||
|
if (m_commandLineArgs.webUiPort > 0) { // it will be -1 when user did not set any value
|
||||||
|
Preferences::instance()->setWebUiPort(m_commandLineArgs.webUiPort);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_MACX) && !defined(DISABLE_GUI)
|
#if defined(Q_OS_MACX) && !defined(DISABLE_GUI)
|
||||||
if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
|
if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
|
||||||
// fix Mac OS X 10.9 (mavericks) font issue
|
// fix Mac OS X 10.9 (mavericks) font issue
|
||||||
@ -111,7 +129,6 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
|
QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setApplicationName("qBittorrent");
|
|
||||||
initializeTranslation();
|
initializeTranslation();
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
||||||
@ -137,6 +154,11 @@ QPointer<MainWindow> Application::mainWindow()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const QBtCommandLineParameters &Application::commandLineArgs() const
|
||||||
|
{
|
||||||
|
return m_commandLineArgs;
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::isFileLoggerEnabled() const
|
bool Application::isFileLoggerEnabled() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_ENABLED, true).toBool();
|
return settings()->loadValue(KEY_FILELOGGER_ENABLED, true).toBool();
|
||||||
@ -153,7 +175,8 @@ void Application::setFileLoggerEnabled(bool value)
|
|||||||
|
|
||||||
QString Application::fileLoggerPath() const
|
QString Application::fileLoggerPath() const
|
||||||
{
|
{
|
||||||
return settings()->loadValue(KEY_FILELOGGER_PATH, QVariant(Utils::Fs::QDesktopServicesDataLocation() + LOG_FOLDER)).toString();
|
return settings()->loadValue(KEY_FILELOGGER_PATH,
|
||||||
|
QVariant(specialFolderLocation(SpecialFolder::Data) + LOG_FOLDER)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setFileLoggerPath(const QString &value)
|
void Application::setFileLoggerPath(const QString &value)
|
||||||
@ -633,3 +656,12 @@ void Application::cleanup()
|
|||||||
Utils::Misc::shutdownComputer(m_shutdownAct);
|
Utils::Misc::shutdownComputer(m_shutdownAct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::validateCommandLineParameters()
|
||||||
|
{
|
||||||
|
if (m_commandLineArgs.portableMode && !m_commandLineArgs.profileDir.isEmpty())
|
||||||
|
throw CommandLineParameterError(tr("Portable mode and explicit profile directory options are mutually exclusive"));
|
||||||
|
|
||||||
|
if (m_commandLineArgs.portableMode && m_commandLineArgs.relativeFastresumePaths)
|
||||||
|
Logger::instance()->addMessage(tr("Portable mode implies relative fastresume"), Log::WARNING);
|
||||||
|
}
|
||||||
|
@ -51,6 +51,7 @@ typedef QtSingleCoreApplication BaseApplication;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#ifndef DISABLE_WEBUI
|
#ifndef DISABLE_WEBUI
|
||||||
class WebUI;
|
class WebUI;
|
||||||
@ -80,6 +81,8 @@ public:
|
|||||||
QPointer<MainWindow> mainWindow();
|
QPointer<MainWindow> mainWindow();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const QBtCommandLineParameters &commandLineArgs() const;
|
||||||
|
|
||||||
// FileLogger properties
|
// FileLogger properties
|
||||||
bool isFileLoggerEnabled() const;
|
bool isFileLoggerEnabled() const;
|
||||||
void setFileLoggerEnabled(bool value);
|
void setFileLoggerEnabled(bool value);
|
||||||
@ -116,6 +119,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
bool m_running;
|
bool m_running;
|
||||||
ShutdownDialogAction m_shutdownAct;
|
ShutdownDialogAction m_shutdownAct;
|
||||||
|
QBtCommandLineParameters m_commandLineArgs;
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
QPointer<MainWindow> m_window;
|
QPointer<MainWindow> m_window;
|
||||||
@ -136,6 +140,7 @@ private:
|
|||||||
void processParams(const QStringList ¶ms);
|
void processParams(const QStringList ¶ms);
|
||||||
void runExternalProgram(BitTorrent::TorrentHandle *const torrent) const;
|
void runExternalProgram(BitTorrent::TorrentHandle *const torrent) const;
|
||||||
void sendNotificationEmail(BitTorrent::TorrentHandle *const torrent);
|
void sendNotificationEmail(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
void validateCommandLineParameters();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPLICATION_H
|
#endif // APPLICATION_H
|
||||||
|
179
src/app/main.cpp
179
src/app/main.cpp
@ -68,6 +68,8 @@ Q_IMPORT_PLUGIN(QICOPlugin)
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
|
||||||
@ -86,44 +88,12 @@ const char *sysSigName[] = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct QBtCommandLineParameters
|
|
||||||
{
|
|
||||||
bool showHelp;
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
bool showVersion;
|
|
||||||
#endif
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
bool noSplash;
|
|
||||||
#else
|
|
||||||
bool shouldDaemonize;
|
|
||||||
#endif
|
|
||||||
int webUiPort;
|
|
||||||
QStringList torrents;
|
|
||||||
QString unknownParameter;
|
|
||||||
|
|
||||||
QBtCommandLineParameters()
|
|
||||||
: showHelp(false)
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
, showVersion(false)
|
|
||||||
#endif
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
, noSplash(Preferences::instance()->isSplashScreenDisabled())
|
|
||||||
#else
|
|
||||||
, shouldDaemonize(false)
|
|
||||||
#endif
|
|
||||||
, webUiPort(Preferences::instance()->getWebUiPort())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
void showSplashScreen();
|
void showSplashScreen();
|
||||||
#endif
|
#endif
|
||||||
void displayVersion();
|
void displayVersion();
|
||||||
void displayUsage(const QString &prg_name);
|
|
||||||
bool userAgreesWithLegalNotice();
|
bool userAgreesWithLegalNotice();
|
||||||
void displayBadArgMessage(const QString &message);
|
void displayBadArgMessage(const QString &message);
|
||||||
QBtCommandLineParameters parseCommandLine();
|
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -137,55 +107,39 @@ int main(int argc, char *argv[])
|
|||||||
macMigratePlists();
|
macMigratePlists();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
try {
|
||||||
migrateRSS();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create Application
|
// Create Application
|
||||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||||
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
const QBtCommandLineParameters params = parseCommandLine();
|
// after the application object creation because we need a profile to be set already
|
||||||
|
// for the migration
|
||||||
|
migrateRSS();
|
||||||
|
#endif
|
||||||
|
const QBtCommandLineParameters ¶ms = app->commandLineArgs();
|
||||||
|
|
||||||
if (!params.unknownParameter.isEmpty()) {
|
if (!params.unknownParameter.isEmpty()) {
|
||||||
displayBadArgMessage(QObject::tr("%1 is an unknown command line parameter.", "--random-parameter is an unknown command line parameter.")
|
throw CommandLineParameterError(QObject::tr("%1 is an unknown command line parameter.",
|
||||||
|
"--random-parameter is an unknown command line parameter.")
|
||||||
.arg(params.unknownParameter));
|
.arg(params.unknownParameter));
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
if (params.showVersion) {
|
if (params.showVersion) {
|
||||||
if (isOneArg) {
|
if (isOneArg) {
|
||||||
displayVersion();
|
displayVersion();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
else {
|
throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.")
|
||||||
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
|
|
||||||
.arg(QLatin1String("-v (or --version)")));
|
.arg(QLatin1String("-v (or --version)")));
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (params.showHelp) {
|
if (params.showHelp) {
|
||||||
if (isOneArg) {
|
if (isOneArg) {
|
||||||
displayUsage(argv[0]);
|
displayUsage(argv[0]);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
else {
|
throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.")
|
||||||
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
|
|
||||||
.arg(QLatin1String("-h (or --help)")));
|
.arg(QLatin1String("-h (or --help)")));
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((params.webUiPort > 0) && (params.webUiPort <= 65535)) {
|
|
||||||
Preferences::instance()->setWebUiPort(params.webUiPort);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
displayBadArgMessage(QObject::tr("%1 must specify the correct port (1 to 65535).")
|
|
||||||
.arg(QLatin1String("--webui-port")));
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set environment variable
|
// Set environment variable
|
||||||
@ -207,9 +161,8 @@ int main(int argc, char *argv[])
|
|||||||
if (app->isRunning()) {
|
if (app->isRunning()) {
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
if (params.shouldDaemonize) {
|
if (params.shouldDaemonize) {
|
||||||
displayBadArgMessage(QObject::tr("You cannot use %1: qBittorrent is already running for this user.")
|
throw CommandLineParameterError(QObject::tr("You cannot use %1: qBittorrent is already running for this user.")
|
||||||
.arg(QLatin1String("-d (or --daemon)")));
|
.arg(QLatin1String("-d (or --daemon)")));
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -254,7 +207,6 @@ int main(int argc, char *argv[])
|
|||||||
&& isatty(fileno(stdin))
|
&& isatty(fileno(stdin))
|
||||||
&& isatty(fileno(stdout)))) return EXIT_FAILURE;
|
&& isatty(fileno(stdout)))) return EXIT_FAILURE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DISABLE_GUI
|
#ifdef DISABLE_GUI
|
||||||
if (params.shouldDaemonize) {
|
if (params.shouldDaemonize) {
|
||||||
app.reset(); // Destroy current application
|
app.reset(); // Destroy current application
|
||||||
@ -271,7 +223,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!params.noSplash)
|
if (!(params.noSplash || Preferences::instance()->isSplashScreenDisabled()))
|
||||||
showSplashScreen();
|
showSplashScreen();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -283,59 +235,11 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return app->exec(params.torrents);
|
return app->exec(params.torrents);
|
||||||
}
|
|
||||||
|
|
||||||
QBtCommandLineParameters parseCommandLine()
|
|
||||||
{
|
|
||||||
QBtCommandLineParameters result;
|
|
||||||
QStringList appArguments = qApp->arguments();
|
|
||||||
|
|
||||||
for (int i = 1; i < appArguments.size(); ++i) {
|
|
||||||
const QString& arg = appArguments[i];
|
|
||||||
|
|
||||||
if ((arg.startsWith("--") && !arg.endsWith(".torrent")) ||
|
|
||||||
(arg.startsWith("-") && arg.size() == 2)) {
|
|
||||||
//Parse known parameters
|
|
||||||
if ((arg == QLatin1String("-h")) || (arg == QLatin1String("--help"))) {
|
|
||||||
result.showHelp = true;
|
|
||||||
}
|
}
|
||||||
#ifndef Q_OS_WIN
|
catch (CommandLineParameterError &er) {
|
||||||
else if ((arg == QLatin1String("-v")) || (arg == QLatin1String("--version"))) {
|
displayBadArgMessage(er.messageForUser());
|
||||||
result.showVersion = true;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (arg.startsWith(QLatin1String("--webui-port="))) {
|
|
||||||
QStringList parts = arg.split(QLatin1Char('='));
|
|
||||||
if (parts.size() == 2)
|
|
||||||
result.webUiPort = parts.last().toInt();
|
|
||||||
}
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
else if (arg == QLatin1String("--no-splash")) {
|
|
||||||
result.noSplash = true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
else if ((arg == QLatin1String("-d")) || (arg == QLatin1String("--daemon"))) {
|
|
||||||
result.shouldDaemonize = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else {
|
|
||||||
//Unknown argument
|
|
||||||
result.unknownParameter = arg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QFileInfo torrentPath;
|
|
||||||
torrentPath.setFile(arg);
|
|
||||||
|
|
||||||
if (torrentPath.exists())
|
|
||||||
result.torrents += torrentPath.absoluteFilePath();
|
|
||||||
else
|
|
||||||
result.torrents += arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
|
#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
|
||||||
@ -396,53 +300,6 @@ void displayVersion()
|
|||||||
std::cout << qPrintable(qApp->applicationName()) << " " << QBT_VERSION << std::endl;
|
std::cout << qPrintable(qApp->applicationName()) << " " << QBT_VERSION << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString makeUsage(const QString &prg_name)
|
|
||||||
{
|
|
||||||
QString text;
|
|
||||||
|
|
||||||
text += QObject::tr("Usage:") + QLatin1Char('\n');
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
text += QLatin1Char('\t') + prg_name + QLatin1String(" (-v | --version)") + QLatin1Char('\n');
|
|
||||||
#endif
|
|
||||||
text += QLatin1Char('\t') + prg_name + QLatin1String(" (-h | --help)") + QLatin1Char('\n');
|
|
||||||
text += QLatin1Char('\t') + prg_name
|
|
||||||
+ QLatin1String(" [--webui-port=<port>]")
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
+ QLatin1String(" [--no-splash]")
|
|
||||||
#else
|
|
||||||
+ QLatin1String(" [-d | --daemon]")
|
|
||||||
#endif
|
|
||||||
+ QLatin1String("[(<filename> | <url>)...]") + QLatin1Char('\n');
|
|
||||||
text += QObject::tr("Options:") + QLatin1Char('\n');
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
text += QLatin1String("\t-v | --version\t\t") + QObject::tr("Displays program version") + QLatin1Char('\n');
|
|
||||||
#endif
|
|
||||||
text += QLatin1String("\t-h | --help\t\t") + QObject::tr("Displays this help message") + QLatin1Char('\n');
|
|
||||||
text += QLatin1String("\t--webui-port=<port>\t")
|
|
||||||
+ QObject::tr("Changes the Web UI port (current: %1)").arg(QString::number(Preferences::instance()->getWebUiPort()))
|
|
||||||
+ QLatin1Char('\n');
|
|
||||||
#ifndef DISABLE_GUI
|
|
||||||
text += QLatin1String("\t--no-splash\t\t") + QObject::tr("Disable splash screen") + QLatin1Char('\n');
|
|
||||||
#else
|
|
||||||
text += QLatin1String("\t-d | --daemon\t\t") + QObject::tr("Run in daemon-mode (background)") + QLatin1Char('\n');
|
|
||||||
#endif
|
|
||||||
text += QLatin1String("\tfiles or urls\t\t") + QObject::tr("Downloads the torrents passed by the user");
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayUsage(const QString& prg_name)
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
std::cout << qPrintable(makeUsage(prg_name)) << std::endl;
|
|
||||||
#else
|
|
||||||
QMessageBox msgBox(QMessageBox::Information, QObject::tr("Help"), makeUsage(prg_name), QMessageBox::Ok);
|
|
||||||
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
|
||||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
|
||||||
msgBox.exec();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayBadArgMessage(const QString& message)
|
void displayBadArgMessage(const QString& message)
|
||||||
{
|
{
|
||||||
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
||||||
|
398
src/app/options.cpp
Normal file
398
src/app/options.cpp
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
* Copyright (C) 2006 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
* Contact : chris@qbittorrent.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QProcessEnvironment>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <QMessageBox>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "base/utils/misc.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Base option class. Encapsulates name operations.
|
||||||
|
class Option
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
constexpr Option(const char *name, char shortcut = 0)
|
||||||
|
: m_name {name}
|
||||||
|
, m_shortcut {shortcut}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fullParameter() const
|
||||||
|
{
|
||||||
|
return QLatin1String("--") + QLatin1String(m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString shortcutParameter() const
|
||||||
|
{
|
||||||
|
return QLatin1String("-") + QLatin1Char(m_shortcut);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasShortcut() const
|
||||||
|
{
|
||||||
|
return m_shortcut != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString envVarName() const
|
||||||
|
{
|
||||||
|
return QLatin1String("QBT_")
|
||||||
|
+ QString(QLatin1String(m_name)).toUpper().replace(QLatin1Char('-'), QLatin1Char('_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString padUsageText(const QString &usage)
|
||||||
|
{
|
||||||
|
const int TAB_WIDTH = 8;
|
||||||
|
QString res = QLatin1String("\t") + usage;
|
||||||
|
if (usage.size() < 2 * TAB_WIDTH)
|
||||||
|
return res + QLatin1String("\t\t");
|
||||||
|
else
|
||||||
|
return res + QLatin1String("\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *m_name;
|
||||||
|
const char m_shortcut;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Boolean option.
|
||||||
|
class BoolOption: protected Option
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr BoolOption(const char *name, char shortcut = 0)
|
||||||
|
: Option {name, shortcut}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const QString &arg) const
|
||||||
|
{
|
||||||
|
return (hasShortcut() && ((arg.size() == 2) && (arg == shortcutParameter())))
|
||||||
|
|| (arg == fullParameter());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool value(const QProcessEnvironment &env) const
|
||||||
|
{
|
||||||
|
QString val = env.value(envVarName());
|
||||||
|
// we accept "1" and "true" (upper or lower cased) as boolean 'true' values
|
||||||
|
return (val == QLatin1String("1") || val.toUpper() == QLatin1String("TRUE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString usage() const
|
||||||
|
{
|
||||||
|
QString res;
|
||||||
|
if (hasShortcut())
|
||||||
|
res += shortcutParameter() + QLatin1String(" | ");
|
||||||
|
res += fullParameter();
|
||||||
|
return padUsageText(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const QString &s, const BoolOption &o)
|
||||||
|
{
|
||||||
|
return o == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option with string value. May not have a shortcut
|
||||||
|
struct StringOption: protected Option
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr StringOption(const char *name)
|
||||||
|
: Option {name, 0}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const QString &arg) const
|
||||||
|
{
|
||||||
|
return arg.startsWith(parameterAssignment());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString value(const QString &arg) const
|
||||||
|
{
|
||||||
|
QStringList parts = arg.split(QLatin1Char('='));
|
||||||
|
if (parts.size() == 2)
|
||||||
|
return unquote(parts[1]);
|
||||||
|
throw CommandLineParameterError(QObject::tr("Parameter '%1' must follow syntax '%1=%2'",
|
||||||
|
"e.g. Parameter '--webui-port' must follow syntax '--webui-port=value'")
|
||||||
|
.arg(fullParameter()).arg(QLatin1String("<value>")));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString value(const QProcessEnvironment &env, const QString &defaultValue = QString()) const
|
||||||
|
{
|
||||||
|
QString val = env.value(envVarName());
|
||||||
|
return val.isEmpty() ? defaultValue : unquote(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString usage(const QString &valueName) const
|
||||||
|
{
|
||||||
|
return padUsageText(parameterAssignment() + QLatin1Char('<') + valueName + QLatin1Char('>'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString parameterAssignment() const
|
||||||
|
{
|
||||||
|
return fullParameter() + QLatin1Char('=');
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString unquote(const QString &s)
|
||||||
|
{
|
||||||
|
auto isStringQuoted =
|
||||||
|
[](const QString &s, QChar quoteChar)
|
||||||
|
{
|
||||||
|
return (s.startsWith(quoteChar) && s.endsWith(quoteChar));
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((s.size() >= 2) && (isStringQuoted(s, QLatin1Char('\'')) || isStringQuoted(s, QLatin1Char('"'))))
|
||||||
|
return s.mid(1, s.size() - 2);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const QString &s, const StringOption &o)
|
||||||
|
{
|
||||||
|
return o == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option with integer value. May not have a shortcut
|
||||||
|
class IntOption: protected StringOption
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr IntOption(const char *name)
|
||||||
|
: StringOption {name}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
using StringOption::operator==;
|
||||||
|
using StringOption::usage;
|
||||||
|
|
||||||
|
int value(const QString &arg) const
|
||||||
|
{
|
||||||
|
QString val = StringOption::value(arg);
|
||||||
|
bool ok = false;
|
||||||
|
int res = val.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
throw CommandLineParameterError(QObject::tr("Parameter '%1' must follow syntax '%1=%2'",
|
||||||
|
"e.g. Parameter '--webui-port' must follow syntax '--webui-port=<value>'")
|
||||||
|
.arg(fullParameter()).arg(QLatin1String("<integer value>")));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value(const QProcessEnvironment &env, int defaultValue) const
|
||||||
|
{
|
||||||
|
QString val = env.value(envVarName());
|
||||||
|
if (val.isEmpty()) return defaultValue;
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
int res = val.toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
qDebug() << QObject::tr("Expected integer number in environment variable '%1', but got '%2'")
|
||||||
|
.arg(envVarName()).arg(val);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const QString &s, const IntOption &o)
|
||||||
|
{
|
||||||
|
return o == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const BoolOption SHOW_HELP_OPTION = {"help", 'h'};
|
||||||
|
constexpr const BoolOption SHOW_VERSION_OPTION = {"version", 'v'};
|
||||||
|
#ifdef DISABLE_GUI
|
||||||
|
constexpr const BoolOption DAEMON_OPTION = {"daemon", 'd'};
|
||||||
|
#else
|
||||||
|
constexpr const BoolOption NO_SPLASH_OPTION = {"no-splash"};
|
||||||
|
#endif
|
||||||
|
constexpr const IntOption WEBUI_PORT_OPTION = {"webui-port"};
|
||||||
|
constexpr const StringOption PROFILE_OPTION = {"profile"};
|
||||||
|
constexpr const StringOption CONFIGURATION_OPTION = {"configuration"};
|
||||||
|
constexpr const BoolOption PORTABLE_OPTION = {"portable"};
|
||||||
|
constexpr const BoolOption RELATIVE_FASTRESUME = {"relative-fastresume"};
|
||||||
|
}
|
||||||
|
|
||||||
|
QBtCommandLineParameters::QBtCommandLineParameters(const QProcessEnvironment &env)
|
||||||
|
: showHelp(false)
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
, showVersion(false)
|
||||||
|
#endif
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
, noSplash(NO_SPLASH_OPTION.value(env))
|
||||||
|
#else
|
||||||
|
, shouldDaemonize(DAEMON_OPTION.value(env))
|
||||||
|
#endif
|
||||||
|
, webUiPort(WEBUI_PORT_OPTION.value(env, -1))
|
||||||
|
, profileDir(PROFILE_OPTION.value(env))
|
||||||
|
, relativeFastresumePaths(RELATIVE_FASTRESUME.value(env))
|
||||||
|
, portableMode(PORTABLE_OPTION.value(env))
|
||||||
|
, configurationName(CONFIGURATION_OPTION.value(env))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QBtCommandLineParameters parseCommandLine(const QStringList &args)
|
||||||
|
{
|
||||||
|
QBtCommandLineParameters result {QProcessEnvironment::systemEnvironment()};
|
||||||
|
|
||||||
|
for (int i = 1; i < args.count(); ++i) {
|
||||||
|
const QString &arg = args[i];
|
||||||
|
|
||||||
|
if ((arg.startsWith("--") && !arg.endsWith(".torrent"))
|
||||||
|
|| (arg.startsWith("-") && (arg.size() == 2))) {
|
||||||
|
// Parse known parameters
|
||||||
|
if ((arg == SHOW_HELP_OPTION)) {
|
||||||
|
result.showHelp = true;
|
||||||
|
}
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
else if (arg == SHOW_VERSION_OPTION) {
|
||||||
|
result.showVersion = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (arg == WEBUI_PORT_OPTION) {
|
||||||
|
result.webUiPort = WEBUI_PORT_OPTION.value(arg);
|
||||||
|
if ((result.webUiPort < 1) || (result.webUiPort > 65535))
|
||||||
|
throw CommandLineParameterError(QObject::tr("%1 must specify the correct port (1 to 65535).")
|
||||||
|
.arg(QLatin1String("--webui-port")));
|
||||||
|
}
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
else if (arg == NO_SPLASH_OPTION) {
|
||||||
|
result.noSplash = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
else if (arg == DAEMON_OPTION) {
|
||||||
|
result.shouldDaemonize = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (arg == PROFILE_OPTION) {
|
||||||
|
result.profileDir = PROFILE_OPTION.value(arg);
|
||||||
|
}
|
||||||
|
else if (arg == RELATIVE_FASTRESUME) {
|
||||||
|
result.relativeFastresumePaths = true;
|
||||||
|
}
|
||||||
|
else if (arg == PORTABLE_OPTION) {
|
||||||
|
result.portableMode = true;
|
||||||
|
}
|
||||||
|
else if (arg == CONFIGURATION_OPTION) {
|
||||||
|
result.configurationName = CONFIGURATION_OPTION.value(arg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Unknown argument
|
||||||
|
result.unknownParameter = arg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QFileInfo torrentPath;
|
||||||
|
torrentPath.setFile(arg);
|
||||||
|
|
||||||
|
if (torrentPath.exists())
|
||||||
|
result.torrents += torrentPath.absoluteFilePath();
|
||||||
|
else
|
||||||
|
result.torrents += arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandLineParameterError::CommandLineParameterError(const QString &messageForUser)
|
||||||
|
: std::runtime_error(messageForUser.toLocal8Bit().data())
|
||||||
|
, m_messageForUser(messageForUser)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& CommandLineParameterError::messageForUser() const
|
||||||
|
{
|
||||||
|
return m_messageForUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString makeUsage(const QString &prgName)
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
QTextStream stream(&text, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
stream << QObject::tr("Usage:") << '\n';
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
stream << '\t' << prgName << " [options] [(<filename> | <url>)...]" << '\n';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
stream << QObject::tr("Options:") << '\n';
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
stream << SHOW_VERSION_OPTION.usage() << QObject::tr("Displays program version and exit") << '\n';
|
||||||
|
#endif
|
||||||
|
stream << SHOW_HELP_OPTION.usage() << QObject::tr("Displays this help message and exit") << '\n';
|
||||||
|
stream << WEBUI_PORT_OPTION.usage(QLatin1String("port"))
|
||||||
|
<< QObject::tr("Changes the Web UI port")
|
||||||
|
<< '\n';
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
stream << NO_SPLASH_OPTION.usage() << QObject::tr("Disable splash screen") << '\n';
|
||||||
|
#else
|
||||||
|
stream << DAEMON_OPTION.usage() << QObject::tr("Run in daemon-mode (background)") << '\n';
|
||||||
|
#endif
|
||||||
|
stream << PROFILE_OPTION.usage(QLatin1String("dir")) << QObject::tr("Store configuration files in <dir>") << '\n';
|
||||||
|
stream << CONFIGURATION_OPTION.usage(QLatin1String("name")) << QObject::tr("Store configuration files in directories qBittorrent_<name>") << '\n';
|
||||||
|
stream << RELATIVE_FASTRESUME.usage() << QObject::tr("Hack into libtorrent fastresume files and make file paths relative to the profile directory") << '\n';
|
||||||
|
stream << PORTABLE_OPTION.usage() << QObject::tr("Shortcut for --profile=<exe dir>/profile --relative-fastresume") << '\n';
|
||||||
|
stream << "\tfiles or urls\t\t" << QObject::tr("Downloads the torrents passed by the user") << '\n'
|
||||||
|
<< '\n';
|
||||||
|
|
||||||
|
stream << QObject::tr("Option values may be supplied via environment variables.") << '\n'
|
||||||
|
<< QObject::tr("For option named 'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper case, '-' replaced with '_')") << '\n'
|
||||||
|
<< QObject::tr("To pass flag values, set the variable to '1' or 'TRUE'.") << '\n'
|
||||||
|
<< QObject::tr("For example, to disable the splash screen: ")
|
||||||
|
<< "QBT_NO_SPLASH=1 " << prgName << '\n'
|
||||||
|
<< '\n'
|
||||||
|
<< QObject::tr("Command line parameters take precedence over environment variables") << '\n';
|
||||||
|
|
||||||
|
stream << flush;
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayUsage(const QString &prgName)
|
||||||
|
{
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
std::cout << qPrintable(makeUsage(prgName)) << std::endl;
|
||||||
|
#else
|
||||||
|
QMessageBox msgBox(QMessageBox::Information, QObject::tr("Help"), makeUsage(prgName), QMessageBox::Ok);
|
||||||
|
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
||||||
|
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||||
|
msgBox.exec();
|
||||||
|
#endif
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2006 Christophe Dumez
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -28,46 +30,49 @@
|
|||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef QINISETTINGS_H
|
#ifndef APP_OPTIONS_H
|
||||||
#define QINISETTINGS_H
|
#define APP_OPTIONS_H
|
||||||
|
|
||||||
#include <QSettings>
|
#include <stdexcept>
|
||||||
|
|
||||||
class QIniSettings : public QSettings {
|
#include <QString>
|
||||||
Q_OBJECT
|
#include <QStringList>
|
||||||
Q_DISABLE_COPY (QIniSettings)
|
|
||||||
|
|
||||||
public:
|
class QProcessEnvironment;
|
||||||
QIniSettings(const QString &organization = "qBittorrent", const QString &application = "qBittorrent", QObject *parent = 0 ):
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
struct QBtCommandLineParameters
|
||||||
QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application, parent)
|
{
|
||||||
|
bool showHelp;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
bool showVersion;
|
||||||
|
#endif
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
bool noSplash;
|
||||||
#else
|
#else
|
||||||
QSettings(organization, application, parent)
|
bool shouldDaemonize;
|
||||||
#endif
|
#endif
|
||||||
{
|
int webUiPort;
|
||||||
|
QString profileDir;
|
||||||
|
bool relativeFastresumePaths;
|
||||||
|
bool portableMode;
|
||||||
|
QString configurationName;
|
||||||
|
QStringList torrents;
|
||||||
|
QString unknownParameter;
|
||||||
|
|
||||||
}
|
QBtCommandLineParameters(const QProcessEnvironment&);
|
||||||
|
|
||||||
QIniSettings(const QString &fileName, Format format, QObject *parent = 0 ) : QSettings(fileName, format, parent) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
QVariant value(const QString & key, const QVariant &defaultValue = QVariant()) const {
|
|
||||||
QString key_tmp(key);
|
|
||||||
QVariant ret = QSettings::value(key_tmp);
|
|
||||||
if (ret.isNull())
|
|
||||||
return defaultValue;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue(const QString &key, const QVariant &val) {
|
|
||||||
QString key_tmp(key);
|
|
||||||
if (format() == QSettings::NativeFormat) // Using registry, don't touch replace here
|
|
||||||
key_tmp.replace("\\", "/");
|
|
||||||
QSettings::setValue(key_tmp, val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QINISETTINGS_H
|
class CommandLineParameterError: public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CommandLineParameterError(const QString &messageForUser);
|
||||||
|
const QString& messageForUser() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_messageForUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
QBtCommandLineParameters parseCommandLine(const QStringList &args);
|
||||||
|
void displayUsage(const QString &prgName);
|
||||||
|
|
||||||
|
#endif // APP_OPTIONS_H
|
@ -47,13 +47,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <QSettings>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/qinisettings.h"
|
|
||||||
|
|
||||||
bool userAcceptsUpgrade()
|
bool userAcceptsUpgrade()
|
||||||
{
|
{
|
||||||
@ -145,7 +148,7 @@ bool upgrade(bool ask = true)
|
|||||||
// Upgrade preferences
|
// Upgrade preferences
|
||||||
Preferences::instance()->upgrade();
|
Preferences::instance()->upgrade();
|
||||||
|
|
||||||
QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup");
|
QString backupFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + "BT_backup");
|
||||||
QDir backupFolderDir(backupFolderPath);
|
QDir backupFolderDir(backupFolderPath);
|
||||||
|
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
@ -156,15 +159,10 @@ bool upgrade(bool ask = true)
|
|||||||
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
SettingsPtr oldResumeSettings = Profile::instance().applicationSettings(QLatin1String("qBittorrent-resume"));
|
||||||
// native .plist
|
|
||||||
QSettings *oldResumeSettings = new QSettings("qBittorrent", "qBittorrent-resume");
|
|
||||||
#else
|
|
||||||
QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume");
|
|
||||||
#endif
|
|
||||||
QString oldResumeFilename = oldResumeSettings->fileName();
|
QString oldResumeFilename = oldResumeSettings->fileName();
|
||||||
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
|
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
|
||||||
delete oldResumeSettings;
|
oldResumeSettings.reset();
|
||||||
|
|
||||||
if (oldResumeData.isEmpty()) {
|
if (oldResumeData.isEmpty()) {
|
||||||
Utils::Fs::forceRemove(oldResumeFilename);
|
Utils::Fs::forceRemove(oldResumeFilename);
|
||||||
@ -231,7 +229,7 @@ bool upgrade(bool ask = true)
|
|||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
void migratePlistToIni(const QString &application)
|
void migratePlistToIni(const QString &application)
|
||||||
{
|
{
|
||||||
QIniSettings iniFile("qBittorrent", application);
|
QSettings iniFile(QSettings::IniFormat, QSettings::UserScope, "qBittorrent", application);
|
||||||
if (!iniFile.allKeys().isEmpty()) return; // We copy the contents of plist, only if inifile does not exist(is empty).
|
if (!iniFile.allKeys().isEmpty()) return; // We copy the contents of plist, only if inifile does not exist(is empty).
|
||||||
|
|
||||||
QSettings *plistFile = new QSettings("qBittorrent", application);
|
QSettings *plistFile = new QSettings("qBittorrent", application);
|
||||||
@ -260,16 +258,16 @@ void macMigratePlists()
|
|||||||
void migrateRSS()
|
void migrateRSS()
|
||||||
{
|
{
|
||||||
// Copy old feed items to new file if needed
|
// Copy old feed items to new file if needed
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss-feeds");
|
SettingsPtr qBTRSS = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss-feeds"));
|
||||||
if (!qBTRSS.allKeys().isEmpty()) return; // We move the contents of RSS old_items only if inifile does not exist (is empty).
|
if (!qBTRSS->allKeys().isEmpty()) return; // We move the contents of RSS old_items only if inifile does not exist (is empty).
|
||||||
|
|
||||||
QIniSettings qBTRSSLegacy("qBittorrent", "qBittorrent-rss");
|
SettingsPtr qBTRSSLegacy = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss"));
|
||||||
QHash<QString, QVariant> allOldItems = qBTRSSLegacy.value("old_items", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> allOldItems = qBTRSSLegacy->value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
|
|
||||||
if (!allOldItems.empty()) {
|
if (!allOldItems.empty()) {
|
||||||
qDebug("Moving %d old items for feeds to qBittorrent-rss-feeds", allOldItems.size());
|
qDebug("Moving %d old items for feeds to qBittorrent-rss-feeds", allOldItems.size());
|
||||||
qBTRSS.setValue("old_items", allOldItems);
|
qBTRSS->setValue("old_items", allOldItems);
|
||||||
qBTRSSLegacy.remove("old_items");
|
qBTRSSLegacy->remove("old_items");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@ net/private/geoipdatabase.h
|
|||||||
net/proxyconfigurationmanager.h
|
net/proxyconfigurationmanager.h
|
||||||
net/reverseresolution.h
|
net/reverseresolution.h
|
||||||
net/smtp.h
|
net/smtp.h
|
||||||
|
private/profile_p.h
|
||||||
rss/private/rssparser.h
|
rss/private/rssparser.h
|
||||||
rss/rssarticle.h
|
rss/rssarticle.h
|
||||||
rss/rssdownloadrule.h
|
rss/rssdownloadrule.h
|
||||||
@ -52,7 +53,7 @@ iconprovider.h
|
|||||||
indexrange.h
|
indexrange.h
|
||||||
logger.h
|
logger.h
|
||||||
preferences.h
|
preferences.h
|
||||||
qinisettings.h
|
profile.h
|
||||||
scanfoldersmodel.h
|
scanfoldersmodel.h
|
||||||
searchengine.h
|
searchengine.h
|
||||||
settingsstorage.h
|
settingsstorage.h
|
||||||
@ -94,6 +95,7 @@ net/private/geoipdatabase.cpp
|
|||||||
net/proxyconfigurationmanager.cpp
|
net/proxyconfigurationmanager.cpp
|
||||||
net/reverseresolution.cpp
|
net/reverseresolution.cpp
|
||||||
net/smtp.cpp
|
net/smtp.cpp
|
||||||
|
private/profile_p.cpp
|
||||||
rss/private/rssparser.cpp
|
rss/private/rssparser.cpp
|
||||||
rss/rssarticle.cpp
|
rss/rssarticle.cpp
|
||||||
rss/rssdownloadrule.cpp
|
rss/rssdownloadrule.cpp
|
||||||
@ -112,6 +114,7 @@ filesystemwatcher.cpp
|
|||||||
iconprovider.cpp
|
iconprovider.cpp
|
||||||
logger.cpp
|
logger.cpp
|
||||||
preferences.cpp
|
preferences.cpp
|
||||||
|
profile.cpp
|
||||||
scanfoldersmodel.cpp
|
scanfoldersmodel.cpp
|
||||||
searchengine.cpp
|
searchengine.cpp
|
||||||
settingsstorage.cpp
|
settingsstorage.cpp
|
||||||
|
@ -2,7 +2,6 @@ HEADERS += \
|
|||||||
$$PWD/types.h \
|
$$PWD/types.h \
|
||||||
$$PWD/tristatebool.h \
|
$$PWD/tristatebool.h \
|
||||||
$$PWD/filesystemwatcher.h \
|
$$PWD/filesystemwatcher.h \
|
||||||
$$PWD/qinisettings.h \
|
|
||||||
$$PWD/logger.h \
|
$$PWD/logger.h \
|
||||||
$$PWD/settingsstorage.h \
|
$$PWD/settingsstorage.h \
|
||||||
$$PWD/settingvalue.h \
|
$$PWD/settingvalue.h \
|
||||||
@ -55,6 +54,8 @@ HEADERS += \
|
|||||||
$$PWD/utils/net.h \
|
$$PWD/utils/net.h \
|
||||||
$$PWD/utils/random.h \
|
$$PWD/utils/random.h \
|
||||||
$$PWD/utils/string.h \
|
$$PWD/utils/string.h \
|
||||||
|
$$PWD/profile.h \
|
||||||
|
$$PWD/private/profile_p.h \
|
||||||
$$PWD/unicodestrings.h \
|
$$PWD/unicodestrings.h \
|
||||||
$$PWD/torrentfileguard.h \
|
$$PWD/torrentfileguard.h \
|
||||||
$$PWD/torrentfilter.h \
|
$$PWD/torrentfilter.h \
|
||||||
@ -112,6 +113,8 @@ SOURCES += \
|
|||||||
$$PWD/utils/net.cpp \
|
$$PWD/utils/net.cpp \
|
||||||
$$PWD/utils/random.cpp \
|
$$PWD/utils/random.cpp \
|
||||||
$$PWD/utils/string.cpp \
|
$$PWD/utils/string.cpp \
|
||||||
|
$$PWD/profile.cpp \
|
||||||
|
$$PWD/private/profile_p.cpp \
|
||||||
$$PWD/torrentfileguard.cpp \
|
$$PWD/torrentfileguard.cpp \
|
||||||
$$PWD/torrentfilter.cpp \
|
$$PWD/torrentfilter.cpp \
|
||||||
$$PWD/scanfoldersmodel.cpp \
|
$$PWD/scanfoldersmodel.cpp \
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
#include "statistics.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
|
|
||||||
#include "base/qinisettings.h"
|
|
||||||
#include "base/bittorrent/sessionstatus.h"
|
#include "base/bittorrent/sessionstatus.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "statistics.h"
|
|
||||||
|
|
||||||
static const qint64 SAVE_INTERVAL = 15 * 60 * 1000;
|
static const qint64 SAVE_INTERVAL = 15 * 60 * 1000;
|
||||||
|
|
||||||
@ -64,19 +65,19 @@ void Statistics::save() const
|
|||||||
if (!m_dirty || ((now - m_lastWrite) < SAVE_INTERVAL))
|
if (!m_dirty || ((now - m_lastWrite) < SAVE_INTERVAL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QIniSettings s("qBittorrent", "qBittorrent-data");
|
SettingsPtr s = Profile::instance().applicationSettings(QLatin1String("qBittorrent-data"));
|
||||||
QVariantHash v;
|
QVariantHash v;
|
||||||
v.insert("AlltimeDL", m_alltimeDL + m_sessionDL);
|
v.insert("AlltimeDL", m_alltimeDL + m_sessionDL);
|
||||||
v.insert("AlltimeUL", m_alltimeUL + m_sessionUL);
|
v.insert("AlltimeUL", m_alltimeUL + m_sessionUL);
|
||||||
s.setValue("Stats/AllStats", v);
|
s->setValue("Stats/AllStats", v);
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
m_lastWrite = now;
|
m_lastWrite = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statistics::load()
|
void Statistics::load()
|
||||||
{
|
{
|
||||||
QIniSettings s("qBittorrent", "qBittorrent-data");
|
SettingsPtr s = Profile::instance().applicationSettings(QLatin1String("qBittorrent-data"));
|
||||||
QVariantHash v = s.value("Stats/AllStats").toHash();
|
QVariantHash v = s->value("Stats/AllStats").toHash();
|
||||||
|
|
||||||
m_alltimeDL = v["AlltimeDL"].toULongLong();
|
m_alltimeDL = v["AlltimeDL"].toULongLong();
|
||||||
m_alltimeUL = v["AlltimeUL"].toULongLong();
|
m_alltimeUL = v["AlltimeUL"].toULongLong();
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/net/downloadhandler.h"
|
#include "base/net/downloadhandler.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/net/portforwarder.h"
|
#include "base/net/portforwarder.h"
|
||||||
@ -132,7 +133,7 @@ namespace
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString normalizeSavePath(QString path, const QString &defaultPath = Utils::Fs::QDesktopServicesDownloadLocation())
|
QString normalizeSavePath(QString path, const QString &defaultPath = specialFolderLocation(SpecialFolder::Downloads))
|
||||||
{
|
{
|
||||||
path = path.trimmed();
|
path = path.trimmed();
|
||||||
if (path.isEmpty())
|
if (path.isEmpty())
|
||||||
@ -266,7 +267,7 @@ Session::Session(QObject *parent)
|
|||||||
, m_isProxyPeerConnectionsEnabled(BITTORRENT_SESSION_KEY("ProxyPeerConnections"), false)
|
, m_isProxyPeerConnectionsEnabled(BITTORRENT_SESSION_KEY("ProxyPeerConnections"), false)
|
||||||
, m_storedCategories(BITTORRENT_SESSION_KEY("Categories"))
|
, m_storedCategories(BITTORRENT_SESSION_KEY("Categories"))
|
||||||
, m_maxRatioAction(BITTORRENT_SESSION_KEY("MaxRatioAction"), Pause)
|
, m_maxRatioAction(BITTORRENT_SESSION_KEY("MaxRatioAction"), Pause)
|
||||||
, m_defaultSavePath(BITTORRENT_SESSION_KEY("DefaultSavePath"), Utils::Fs::QDesktopServicesDownloadLocation(), normalizePath)
|
, m_defaultSavePath(BITTORRENT_SESSION_KEY("DefaultSavePath"), specialFolderLocation(SpecialFolder::Downloads), normalizePath)
|
||||||
, m_tempPath(BITTORRENT_SESSION_KEY("TempPath"), defaultSavePath() + "temp/", normalizePath)
|
, m_tempPath(BITTORRENT_SESSION_KEY("TempPath"), defaultSavePath() + "temp/", normalizePath)
|
||||||
, m_isSubcategoriesEnabled(BITTORRENT_SESSION_KEY("SubcategoriesEnabled"), false)
|
, m_isSubcategoriesEnabled(BITTORRENT_SESSION_KEY("SubcategoriesEnabled"), false)
|
||||||
, m_isTempPathEnabled(BITTORRENT_SESSION_KEY("TempPathEnabled"), false)
|
, m_isTempPathEnabled(BITTORRENT_SESSION_KEY("TempPathEnabled"), false)
|
||||||
@ -3003,7 +3004,7 @@ bool Session::hasPerTorrentRatioLimit() const
|
|||||||
|
|
||||||
void Session::initResumeFolder()
|
void Session::initResumeFolder()
|
||||||
{
|
{
|
||||||
m_resumeFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + RESUME_FOLDER);
|
m_resumeFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + RESUME_FOLDER);
|
||||||
QDir resumeFolderDir(m_resumeFolderPath);
|
QDir resumeFolderDir(m_resumeFolderPath);
|
||||||
if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) {
|
if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) {
|
||||||
m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock"));
|
m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock"));
|
||||||
@ -3632,7 +3633,8 @@ namespace
|
|||||||
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
|
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
torrentData.savePath = Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath")));
|
torrentData.savePath = Profile::instance().fromPortablePath(
|
||||||
|
Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath"))));
|
||||||
torrentData.ratioLimit = QString::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble();
|
torrentData.ratioLimit = QString::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble();
|
||||||
// **************************************************************************************
|
// **************************************************************************************
|
||||||
// Workaround to convert legacy label to category
|
// Workaround to convert legacy label to category
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
@ -1477,7 +1478,11 @@ void TorrentHandle::handleSaveResumeDataAlert(libtorrent::save_resume_data_alert
|
|||||||
resumeData["qBt-paused"] = isPaused();
|
resumeData["qBt-paused"] = isPaused();
|
||||||
resumeData["qBt-forced"] = isForced();
|
resumeData["qBt-forced"] = isForced();
|
||||||
}
|
}
|
||||||
resumeData["qBt-savePath"] = m_useAutoTMM ? "" : m_savePath.toStdString();
|
else {
|
||||||
|
auto savePath = resumeData.find_key("save_path")->string();
|
||||||
|
resumeData["save_path"] = Profile::instance().toPortablePath(QString::fromStdString(savePath)).toStdString();
|
||||||
|
}
|
||||||
|
resumeData["qBt-savePath"] = m_useAutoTMM ? "" : Profile::instance().toPortablePath(m_savePath).toStdString();
|
||||||
resumeData["qBt-ratioLimit"] = QString::number(m_ratioLimit).toStdString();
|
resumeData["qBt-ratioLimit"] = QString::number(m_ratioLimit).toStdString();
|
||||||
resumeData["qBt-category"] = m_category.toStdString();
|
resumeData["qBt-category"] = m_category.toStdString();
|
||||||
resumeData["qBt-name"] = m_name.toStdString();
|
resumeData["qBt-name"] = m_name.toStdString();
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/gzip.h"
|
#include "base/utils/gzip.h"
|
||||||
#include "downloadmanager.h"
|
#include "downloadmanager.h"
|
||||||
@ -94,7 +95,7 @@ void GeoIPManager::loadDatabase()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString filepath = Utils::Fs::expandPathAbs(
|
QString filepath = Utils::Fs::expandPathAbs(
|
||||||
QString("%1%2/%3").arg(Utils::Fs::QDesktopServicesDataLocation())
|
QString("%1%2/%3").arg(specialFolderLocation(SpecialFolder::Data))
|
||||||
.arg(GEOIP_FOLDER).arg(GEOIP_FILENAME));
|
.arg(GEOIP_FOLDER).arg(GEOIP_FILENAME));
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
@ -431,7 +432,7 @@ void GeoIPManager::downloadFinished(const QString &url, QByteArray data)
|
|||||||
.arg(m_geoIPDatabase->type()).arg(m_geoIPDatabase->buildEpoch().toString()),
|
.arg(m_geoIPDatabase->type()).arg(m_geoIPDatabase->buildEpoch().toString()),
|
||||||
Log::INFO);
|
Log::INFO);
|
||||||
QString targetPath = Utils::Fs::expandPathAbs(
|
QString targetPath = Utils::Fs::expandPathAbs(
|
||||||
Utils::Fs::QDesktopServicesDataLocation() + GEOIP_FOLDER);
|
specialFolderLocation(SpecialFolder::Data) + GEOIP_FOLDER);
|
||||||
if (!QDir(targetPath).exists())
|
if (!QDir(targetPath).exists())
|
||||||
QDir().mkpath(targetPath);
|
QDir().mkpath(targetPath);
|
||||||
QFile targetFile(QString("%1/%2").arg(targetPath).arg(GEOIP_FILENAME));
|
QFile targetFile(QString("%1/%2").arg(targetPath).arg(GEOIP_FILENAME));
|
||||||
|
250
src/base/private/profile_p.cpp
Normal file
250
src/base/private/profile_p.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2012 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "profile_p.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <shlobj.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "base/utils/fs.h"
|
||||||
|
|
||||||
|
Private::Profile::Profile(const QString &configurationName)
|
||||||
|
: m_configurationName {configurationName.isEmpty()
|
||||||
|
? QCoreApplication::applicationName()
|
||||||
|
: QCoreApplication::applicationName() + QLatin1Char('_') + configurationName}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::Profile::configurationName() const
|
||||||
|
{
|
||||||
|
return m_configurationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Private::DefaultProfile::DefaultProfile(const QString &configurationName)
|
||||||
|
: Profile(configurationName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::DefaultProfile::baseDirectory() const
|
||||||
|
{
|
||||||
|
return QDir::homePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::DefaultProfile::cacheLocation() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||||
|
result = dataLocation() + QLatin1String("cache");
|
||||||
|
#else
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||||
|
FSRef ref;
|
||||||
|
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
||||||
|
if (err)
|
||||||
|
return QString();
|
||||||
|
QByteArray ba(2048, 0);
|
||||||
|
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||||
|
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||||
|
result += QLatin1Char('/') + configurationName();
|
||||||
|
#else
|
||||||
|
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
||||||
|
if (xdgCacheHome.isEmpty())
|
||||||
|
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||||
|
xdgCacheHome += QLatin1Char('/') + configurationName();
|
||||||
|
result = xdgCacheHome;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (!result.endsWith("/"))
|
||||||
|
result += "/";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::DefaultProfile::configLocation() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||||
|
result = dataLocation() + QLatin1String("config");
|
||||||
|
#else
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
result = QDir::homePath() + QLatin1String("/Library/Preferences/") + configurationName();
|
||||||
|
#else
|
||||||
|
QString xdgConfigHome = QLatin1String(qgetenv("XDG_CONFIG_HOME"));
|
||||||
|
if (xdgConfigHome.isEmpty())
|
||||||
|
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
|
||||||
|
xdgConfigHome += QLatin1Char('/') + configurationName();
|
||||||
|
result = xdgConfigHome;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::DefaultProfile::dataLocation() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
wchar_t path[MAX_PATH + 1] = {L'\0'};
|
||||||
|
if (SHGetSpecialFolderPathW(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||||
|
result = Utils::Fs::fromNativePath(QString::fromWCharArray(path));
|
||||||
|
if (!QCoreApplication::applicationName().isEmpty())
|
||||||
|
result += QLatin1String("/") + qApp->applicationName();
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
FSRef ref;
|
||||||
|
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||||
|
if (err)
|
||||||
|
return QString();
|
||||||
|
QByteArray ba(2048, 0);
|
||||||
|
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||||
|
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||||
|
result += QLatin1Char('/') + qApp->applicationName();
|
||||||
|
#else
|
||||||
|
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
||||||
|
if (xdgDataHome.isEmpty())
|
||||||
|
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||||
|
xdgDataHome += QLatin1String("/data/")
|
||||||
|
+ qApp->applicationName();
|
||||||
|
result = xdgDataHome;
|
||||||
|
#endif
|
||||||
|
if (!result.endsWith("/"))
|
||||||
|
result += "/";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::DefaultProfile::downloadLocation() const
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
if (QSysInfo::windowsVersion() <= QSysInfo::WV_XP) // Windows XP
|
||||||
|
return QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).absoluteFilePath(
|
||||||
|
QCoreApplication::translate("fsutils", "Downloads"));
|
||||||
|
#endif
|
||||||
|
return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPtr Private::DefaultProfile::applicationSettings(const QString &name) const
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
|
return SettingsPtr(new QSettings(QSettings::IniFormat, QSettings::UserScope, configurationName(), name));
|
||||||
|
#else
|
||||||
|
return SettingsPtr(new QSettings(configurationName(), name));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Private::CustomProfile::CustomProfile(const QString &rootPath, const QString &configurationName)
|
||||||
|
: Profile {configurationName}
|
||||||
|
, m_rootDirectory {QDir(rootPath).absoluteFilePath(this->configurationName())}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::CustomProfile::baseDirectory() const
|
||||||
|
{
|
||||||
|
return m_rootDirectory.canonicalPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::CustomProfile::cacheLocation() const
|
||||||
|
{
|
||||||
|
return m_rootDirectory.absoluteFilePath(QLatin1String(cacheDirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::CustomProfile::configLocation() const
|
||||||
|
{
|
||||||
|
return m_rootDirectory.absoluteFilePath(QLatin1String(configDirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::CustomProfile::dataLocation() const
|
||||||
|
{
|
||||||
|
return m_rootDirectory.absoluteFilePath(QLatin1String(dataDirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::CustomProfile::downloadLocation() const
|
||||||
|
{
|
||||||
|
return m_rootDirectory.absoluteFilePath(QLatin1String(downloadsDirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPtr Private::CustomProfile::applicationSettings(const QString &name) const
|
||||||
|
{
|
||||||
|
// here we force QSettings::IniFormat format always because we need it to be portable across platforms
|
||||||
|
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||||
|
constexpr const char *CONF_FILE_EXTENSION = ".ini";
|
||||||
|
#else
|
||||||
|
constexpr const char *CONF_FILE_EXTENSION = ".conf";
|
||||||
|
#endif
|
||||||
|
const QString settingsFileName {QDir(configLocation()).absoluteFilePath(name + QLatin1String(CONF_FILE_EXTENSION))};
|
||||||
|
return SettingsPtr(new QSettings(settingsFileName, QSettings::IniFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::NoConvertConverter::fromPortablePath(const QString &portablePath) const
|
||||||
|
{
|
||||||
|
return portablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::NoConvertConverter::toPortablePath(const QString &path) const
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
Private::Converter::Converter(const QString &basePath)
|
||||||
|
: m_baseDir {basePath}
|
||||||
|
{
|
||||||
|
m_baseDir.makeAbsolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::Converter::toPortablePath(const QString &path) const
|
||||||
|
{
|
||||||
|
if (path.isEmpty() || m_baseDir.path().isEmpty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (QDir::isAbsolutePath(path)) {
|
||||||
|
QChar driveLeter = path[0].toUpper();
|
||||||
|
QChar baseDriveLetter = m_baseDir.path()[0].toUpper();
|
||||||
|
bool onSameDrive = (driveLeter.category() == QChar::Letter_Uppercase) && (driveLeter == baseDriveLetter);
|
||||||
|
if (!onSameDrive)
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return m_baseDir.relativeFilePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Private::Converter::fromPortablePath(const QString &portablePath) const
|
||||||
|
{
|
||||||
|
if (QDir::isAbsolutePath(portablePath))
|
||||||
|
return portablePath;
|
||||||
|
|
||||||
|
return QDir::cleanPath(m_baseDir.absoluteFilePath(portablePath));
|
||||||
|
}
|
121
src/base/private/profile_p.h
Normal file
121
src/base/private/profile_p.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2012 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QBT_PROFILE_P_H
|
||||||
|
#define QBT_PROFILE_P_H
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include "base/profile.h"
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
class Profile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual QString baseDirectory() const = 0;
|
||||||
|
virtual QString cacheLocation() const = 0;
|
||||||
|
virtual QString configLocation() const = 0;
|
||||||
|
virtual QString dataLocation() const = 0;
|
||||||
|
virtual QString downloadLocation() const = 0;
|
||||||
|
virtual SettingsPtr applicationSettings(const QString &name) const = 0;
|
||||||
|
|
||||||
|
virtual ~Profile() = default;
|
||||||
|
|
||||||
|
QString configurationName() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Profile(const QString &configurationName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_configurationName;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Default implementation. Takes paths from system
|
||||||
|
class DefaultProfile: public Profile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DefaultProfile(const QString &configurationName);
|
||||||
|
|
||||||
|
QString baseDirectory() const override;
|
||||||
|
QString cacheLocation() const override;
|
||||||
|
QString configLocation() const override;
|
||||||
|
QString dataLocation() const override;
|
||||||
|
QString downloadLocation() const override;
|
||||||
|
SettingsPtr applicationSettings(const QString &name) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Custom tree: creates directories under the specified root directory
|
||||||
|
class CustomProfile: public Profile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CustomProfile(const QString &rootPath, const QString &configurationName);
|
||||||
|
|
||||||
|
QString baseDirectory() const override;
|
||||||
|
QString cacheLocation() const override;
|
||||||
|
QString configLocation() const override;
|
||||||
|
QString dataLocation() const override;
|
||||||
|
QString downloadLocation() const override;
|
||||||
|
SettingsPtr applicationSettings(const QString &name) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDir m_rootDirectory;
|
||||||
|
static constexpr const char *cacheDirName = "cache";
|
||||||
|
static constexpr const char *configDirName = "config";
|
||||||
|
static constexpr const char *dataDirName = "data";
|
||||||
|
static constexpr const char *downloadsDirName = "downloads";
|
||||||
|
};
|
||||||
|
|
||||||
|
class PathConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual QString toPortablePath(const QString &path) const = 0;
|
||||||
|
virtual QString fromPortablePath(const QString &portablePath) const = 0;
|
||||||
|
virtual ~PathConverter() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NoConvertConverter: public PathConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString toPortablePath(const QString &path) const override;
|
||||||
|
QString fromPortablePath(const QString &portablePath) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Converter: public PathConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Converter(const QString &basePath);
|
||||||
|
QString toPortablePath(const QString &path) const override;
|
||||||
|
QString fromPortablePath(const QString &portablePath) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDir m_baseDir;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // QBT_PROFILE_P_H
|
118
src/base/profile.cpp
Normal file
118
src/base/profile.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2012 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "profile.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "private/profile_p.h"
|
||||||
|
|
||||||
|
Profile *Profile::m_instance = nullptr;
|
||||||
|
|
||||||
|
Profile::Profile(Private::Profile *impl, Private::PathConverter *pathConverter)
|
||||||
|
: m_profileImpl(impl)
|
||||||
|
, m_pathConverterImpl(pathConverter)
|
||||||
|
{
|
||||||
|
ensureDirectoryExists(SpecialFolder::Cache);
|
||||||
|
ensureDirectoryExists(SpecialFolder::Config);
|
||||||
|
ensureDirectoryExists(SpecialFolder::Data);
|
||||||
|
ensureDirectoryExists(SpecialFolder::Downloads);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to generate correct call to ProfilePrivate::~ProfileImpl()
|
||||||
|
Profile::~Profile() = default;
|
||||||
|
|
||||||
|
void Profile::initialize(const QString &rootProfilePath, const QString &configurationName,
|
||||||
|
bool convertPathsToProfileRelative)
|
||||||
|
{
|
||||||
|
QScopedPointer<Private::Profile> profile(rootProfilePath.isEmpty()
|
||||||
|
? static_cast<Private::Profile *>(new Private::DefaultProfile(configurationName))
|
||||||
|
: static_cast<Private::Profile *>(new Private::CustomProfile(rootProfilePath, configurationName)));
|
||||||
|
|
||||||
|
QScopedPointer<Private::PathConverter> converter(convertPathsToProfileRelative
|
||||||
|
? static_cast<Private::PathConverter *>(new Private::Converter(profile->baseDirectory()))
|
||||||
|
: static_cast<Private::PathConverter *>(new Private::NoConvertConverter()));
|
||||||
|
m_instance = new Profile(profile.take(), converter.take());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Profile &Profile::instance()
|
||||||
|
{
|
||||||
|
return *m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Profile::location(SpecialFolder folder) const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
switch (folder) {
|
||||||
|
case SpecialFolder::Cache:
|
||||||
|
result = m_profileImpl->cacheLocation();
|
||||||
|
break;
|
||||||
|
case SpecialFolder::Config:
|
||||||
|
result = m_profileImpl->configLocation();
|
||||||
|
break;
|
||||||
|
case SpecialFolder::Data:
|
||||||
|
result = m_profileImpl->dataLocation();
|
||||||
|
break;
|
||||||
|
case SpecialFolder::Downloads:
|
||||||
|
result = m_profileImpl->downloadLocation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.endsWith(QLatin1Char('/')))
|
||||||
|
result += QLatin1Char('/');
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Profile::configurationName() const
|
||||||
|
{
|
||||||
|
return m_profileImpl->configurationName();
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPtr Profile::applicationSettings(const QString &name) const
|
||||||
|
{
|
||||||
|
return m_profileImpl->applicationSettings(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profile::ensureDirectoryExists(SpecialFolder folder)
|
||||||
|
{
|
||||||
|
QString locationPath = location(folder);
|
||||||
|
if (!locationPath.isEmpty() && !QDir().mkpath(locationPath))
|
||||||
|
qFatal("Could not create required directory '%s'", qPrintable(locationPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Profile::toPortablePath(const QString &absolutePath) const
|
||||||
|
{
|
||||||
|
return m_pathConverterImpl->toPortablePath(absolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Profile::fromPortablePath(const QString &portablePath) const
|
||||||
|
{
|
||||||
|
return m_pathConverterImpl->fromPortablePath(portablePath);
|
||||||
|
}
|
92
src/base/profile.h
Normal file
92
src/base/profile.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||||
|
* Copyright (C) 2012 Christophe Dumez
|
||||||
|
*
|
||||||
|
* This program is free 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QBT_PROFILE_H
|
||||||
|
#define QBT_PROFILE_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
class Application;
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
class Profile;
|
||||||
|
class PathConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
using SettingsPtr = std::unique_ptr<QSettings>;
|
||||||
|
|
||||||
|
enum class SpecialFolder
|
||||||
|
{
|
||||||
|
Cache,
|
||||||
|
Config,
|
||||||
|
Data,
|
||||||
|
Downloads
|
||||||
|
};
|
||||||
|
|
||||||
|
class Profile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString location(SpecialFolder folder) const;
|
||||||
|
SettingsPtr applicationSettings(const QString &name) const;
|
||||||
|
|
||||||
|
/// Returns either default name for configuration file (QCoreApplication::applicationName())
|
||||||
|
/// or the value, supplied via parameters
|
||||||
|
QString configurationName() const;
|
||||||
|
|
||||||
|
QString toPortablePath(const QString &absolutePath) const;
|
||||||
|
QString fromPortablePath(const QString &portablePath) const;
|
||||||
|
|
||||||
|
static const Profile &instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Profile(Private::Profile *impl, Private::PathConverter *pathConverter);
|
||||||
|
~Profile();
|
||||||
|
|
||||||
|
friend class ::Application;
|
||||||
|
static void initialize(const QString &rootProfilePath, const QString &configurationName,
|
||||||
|
bool convertPathsToProfileRelative);
|
||||||
|
void ensureDirectoryExists(SpecialFolder folder);
|
||||||
|
|
||||||
|
QScopedPointer<Private::Profile> m_profileImpl;
|
||||||
|
QScopedPointer<Private::PathConverter> m_pathConverterImpl;
|
||||||
|
static Profile *m_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QString specialFolderLocation(SpecialFolder folder)
|
||||||
|
{
|
||||||
|
return Profile::instance().location(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QBT_PROFILE_H
|
@ -28,13 +28,14 @@
|
|||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "rssdownloadrulelist.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/qinisettings.h"
|
#include "base/profile.h"
|
||||||
#include "rssdownloadrulelist.h"
|
|
||||||
|
|
||||||
using namespace Rss;
|
using namespace Rss;
|
||||||
|
|
||||||
@ -66,14 +67,14 @@ void DownloadRuleList::replace(DownloadRuleList *other)
|
|||||||
|
|
||||||
void DownloadRuleList::saveRulesToStorage()
|
void DownloadRuleList::saveRulesToStorage()
|
||||||
{
|
{
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
SettingsPtr qBTRSS = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss"));
|
||||||
qBTRSS.setValue("download_rules", toVariantHash());
|
qBTRSS->setValue("download_rules", toVariantHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadRuleList::loadRulesFromStorage()
|
void DownloadRuleList::loadRulesFromStorage()
|
||||||
{
|
{
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
SettingsPtr qBTRSS = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss"));
|
||||||
loadRulesFromVariantHash(qBTRSS.value("download_rules").toHash());
|
loadRulesFromVariantHash(qBTRSS->value("download_rules").toHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantHash DownloadRuleList::toVariantHash() const
|
QVariantHash DownloadRuleList::toVariantHash() const
|
||||||
|
@ -30,11 +30,13 @@
|
|||||||
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
|
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "rssfeed.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/qinisettings.h"
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/magneturi.h"
|
#include "base/bittorrent/magneturi.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
@ -46,7 +48,6 @@
|
|||||||
#include "rssarticle.h"
|
#include "rssarticle.h"
|
||||||
#include "rssfolder.h"
|
#include "rssfolder.h"
|
||||||
#include "rssmanager.h"
|
#include "rssmanager.h"
|
||||||
#include "rssfeed.h"
|
|
||||||
|
|
||||||
namespace Rss
|
namespace Rss
|
||||||
{
|
{
|
||||||
@ -99,7 +100,7 @@ void Feed::saveItemsToDisk()
|
|||||||
|
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
|
|
||||||
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss-feeds"));
|
||||||
QVariantList oldItems;
|
QVariantList oldItems;
|
||||||
|
|
||||||
ArticleHash::ConstIterator it = m_articles.begin();
|
ArticleHash::ConstIterator it = m_articles.begin();
|
||||||
@ -107,16 +108,15 @@ void Feed::saveItemsToDisk()
|
|||||||
for (; it != itend; ++it)
|
for (; it != itend; ++it)
|
||||||
oldItems << it.value()->toHash();
|
oldItems << it.value()->toHash();
|
||||||
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
||||||
QHash<QString, QVariant> allOldItems = qBTRSSFeeds.value("old_items", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> allOldItems = qBTRSSFeeds->value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
allOldItems[m_url] = oldItems;
|
allOldItems[m_url] = oldItems;
|
||||||
qBTRSSFeeds.setValue("old_items", allOldItems);
|
qBTRSSFeeds->setValue("old_items", allOldItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Feed::loadItemsFromDisk()
|
void Feed::loadItemsFromDisk()
|
||||||
{
|
{
|
||||||
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss-feeds"));
|
||||||
QHash<QString, QVariant> allOldItems = qBTRSSFeeds.value("old_items", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> allOldItems = qBTRSSFeeds->value("old_items", QHash<QString, QVariant>()).toHash();
|
||||||
|
|
||||||
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
|
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
|
||||||
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
|
||||||
|
|
||||||
@ -193,22 +193,22 @@ QString Feed::id() const
|
|||||||
void Feed::removeAllSettings()
|
void Feed::removeAllSettings()
|
||||||
{
|
{
|
||||||
qDebug() << "Removing all settings / history for feed: " << m_url;
|
qDebug() << "Removing all settings / history for feed: " << m_url;
|
||||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
SettingsPtr qBTRSS = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss"));
|
||||||
QVariantHash feedsWDownloader = qBTRSS.value("downloader_on", QVariantHash()).toHash();
|
QVariantHash feedsWDownloader = qBTRSS->value("downloader_on", QVariantHash()).toHash();
|
||||||
if (feedsWDownloader.contains(m_url)) {
|
if (feedsWDownloader.contains(m_url)) {
|
||||||
feedsWDownloader.remove(m_url);
|
feedsWDownloader.remove(m_url);
|
||||||
qBTRSS.setValue("downloader_on", feedsWDownloader);
|
qBTRSS->setValue("downloader_on", feedsWDownloader);
|
||||||
}
|
}
|
||||||
QVariantHash allFeedsFilters = qBTRSS.value("feed_filters", QVariantHash()).toHash();
|
QVariantHash allFeedsFilters = qBTRSS->value("feed_filters", QVariantHash()).toHash();
|
||||||
if (allFeedsFilters.contains(m_url)) {
|
if (allFeedsFilters.contains(m_url)) {
|
||||||
allFeedsFilters.remove(m_url);
|
allFeedsFilters.remove(m_url);
|
||||||
qBTRSS.setValue("feed_filters", allFeedsFilters);
|
qBTRSS->setValue("feed_filters", allFeedsFilters);
|
||||||
}
|
}
|
||||||
QIniSettings qBTRSSFeeds("qBittorrent", "qBittorrent-rss-feeds");
|
SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss-feeds"));
|
||||||
QVariantHash allOldItems = qBTRSSFeeds.value("old_items", QVariantHash()).toHash();
|
QVariantHash allOldItems = qBTRSSFeeds->value("old_items", QVariantHash()).toHash();
|
||||||
if (allOldItems.contains(m_url)) {
|
if (allOldItems.contains(m_url)) {
|
||||||
allOldItems.remove(m_url);
|
allOldItems.remove(m_url);
|
||||||
qBTRSSFeeds.setValue("old_items", allOldItems);
|
qBTRSSFeeds->setValue("old_items", allOldItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
|
#include "base/profile.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/net/downloadhandler.h"
|
#include "base/net/downloadhandler.h"
|
||||||
#include "searchengine.h"
|
#include "searchengine.h"
|
||||||
@ -325,7 +326,7 @@ QString SearchEngine::engineLocation()
|
|||||||
QString folder = "nova";
|
QString folder = "nova";
|
||||||
if (Utils::Misc::pythonVersion() >= 3)
|
if (Utils::Misc::pythonVersion() >= 3)
|
||||||
folder = "nova3";
|
folder = "nova3";
|
||||||
const QString location = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + folder);
|
const QString location = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + folder);
|
||||||
QDir locationDir(location);
|
QDir locationDir(location);
|
||||||
if (!locationDir.exists())
|
if (!locationDir.exists())
|
||||||
locationDir.mkpath(locationDir.absolutePath());
|
locationDir.mkpath(locationDir.absolutePath());
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "profile.h"
|
||||||
#include "utils/fs.h"
|
#include "utils/fs.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -62,16 +62,6 @@ namespace
|
|||||||
QString deserialize(const QString &name, QVariantHash &data);
|
QString deserialize(const QString &name, QVariantHash &data);
|
||||||
QString serialize(const QString &name, const QVariantHash &data);
|
QString serialize(const QString &name, const QVariantHash &data);
|
||||||
|
|
||||||
using SettingsPtr = std::unique_ptr<QSettings>;
|
|
||||||
SettingsPtr createSettings(const QString &name)
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
|
||||||
return SettingsPtr(new QSettings(QSettings::IniFormat, QSettings::UserScope, "qBittorrent", name));
|
|
||||||
#else
|
|
||||||
return SettingsPtr(new QSettings("qBittorrent", name));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -290,7 +280,7 @@ bool TransactionalSettings::write(const QVariantHash &data)
|
|||||||
|
|
||||||
QString TransactionalSettings::deserialize(const QString &name, QVariantHash &data)
|
QString TransactionalSettings::deserialize(const QString &name, QVariantHash &data)
|
||||||
{
|
{
|
||||||
SettingsPtr settings = createSettings(name);
|
SettingsPtr settings = Profile::instance().applicationSettings(name);
|
||||||
|
|
||||||
if (settings->allKeys().isEmpty())
|
if (settings->allKeys().isEmpty())
|
||||||
return QString();
|
return QString();
|
||||||
@ -306,7 +296,7 @@ QString TransactionalSettings::deserialize(const QString &name, QVariantHash &da
|
|||||||
|
|
||||||
QString TransactionalSettings::serialize(const QString &name, const QVariantHash &data)
|
QString TransactionalSettings::serialize(const QString &name, const QVariantHash &data)
|
||||||
{
|
{
|
||||||
SettingsPtr settings = createSettings(name);
|
SettingsPtr settings = Profile::instance().applicationSettings(name);
|
||||||
for (auto i = data.begin(); i != data.end(); ++i)
|
for (auto i = data.begin(); i != data.end(); ++i)
|
||||||
settings->setValue(i.key(), i.value());
|
settings->setValue(i.key(), i.value());
|
||||||
|
|
||||||
|
@ -28,19 +28,15 @@
|
|||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QSettings>
|
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
#include <CoreServices/CoreServices.h>
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -51,16 +47,9 @@
|
|||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <shlobj.h>
|
#include <Windows.h>
|
||||||
#include <winbase.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QStandardPaths>
|
|
||||||
|
|
||||||
|
|
||||||
#include "misc.h"
|
|
||||||
#include "fs.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a path to a string suitable for display.
|
* Converts a path to a string suitable for display.
|
||||||
* This function makes sure the directory separator used is consistent
|
* This function makes sure the directory separator used is consistent
|
||||||
@ -326,85 +315,6 @@ QString Utils::Fs::expandPathAbs(const QString& path)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Utils::Fs::QDesktopServicesDataLocation()
|
|
||||||
{
|
|
||||||
QString result;
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
wchar_t path[MAX_PATH + 1] = {L'\0'};
|
|
||||||
if (SHGetSpecialFolderPathW(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
|
||||||
result = fromNativePath(QString::fromWCharArray(path));
|
|
||||||
if (!QCoreApplication::applicationName().isEmpty())
|
|
||||||
result += QLatin1String("/") + qApp->applicationName();
|
|
||||||
#elif defined(Q_OS_MAC)
|
|
||||||
FSRef ref;
|
|
||||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
|
||||||
if (err)
|
|
||||||
return QString();
|
|
||||||
QByteArray ba(2048, 0);
|
|
||||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
|
||||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
|
||||||
result += QLatin1Char('/') + qApp->applicationName();
|
|
||||||
#else
|
|
||||||
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
|
||||||
if (xdgDataHome.isEmpty())
|
|
||||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
|
||||||
xdgDataHome += QLatin1String("/data/")
|
|
||||||
+ qApp->applicationName();
|
|
||||||
result = xdgDataHome;
|
|
||||||
#endif
|
|
||||||
if (!result.endsWith("/"))
|
|
||||||
result += "/";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Utils::Fs::QDesktopServicesCacheLocation()
|
|
||||||
{
|
|
||||||
QString result;
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
|
||||||
result = QDesktopServicesDataLocation() + QLatin1String("cache");
|
|
||||||
#else
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
|
||||||
FSRef ref;
|
|
||||||
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
|
||||||
if (err)
|
|
||||||
return QString();
|
|
||||||
QByteArray ba(2048, 0);
|
|
||||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
|
||||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
|
||||||
result += QLatin1Char('/') + qApp->applicationName();
|
|
||||||
#else
|
|
||||||
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
|
||||||
if (xdgCacheHome.isEmpty())
|
|
||||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
|
||||||
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
|
|
||||||
result = xdgCacheHome;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (!result.endsWith("/"))
|
|
||||||
result += "/";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Utils::Fs::QDesktopServicesDownloadLocation()
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
if (QSysInfo::windowsVersion() <= QSysInfo::WV_XP) // Windows XP
|
|
||||||
return QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).absoluteFilePath(
|
|
||||||
QCoreApplication::translate("fsutils", "Downloads"));
|
|
||||||
#endif
|
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Utils::Fs::cacheLocation()
|
|
||||||
{
|
|
||||||
QString location = expandPathAbs(QDesktopServicesCacheLocation());
|
|
||||||
QDir locationDir(location);
|
|
||||||
if (!locationDir.exists())
|
|
||||||
locationDir.mkpath(locationDir.absolutePath());
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Utils::Fs::tempPath()
|
QString Utils::Fs::tempPath()
|
||||||
{
|
{
|
||||||
static const QString path = QDir::tempPath() + "/.qBittorrent/";
|
static const QString path = QDir::tempPath() + "/.qBittorrent/";
|
||||||
|
@ -60,13 +60,6 @@ namespace Utils
|
|||||||
bool forceRemove(const QString& file_path);
|
bool forceRemove(const QString& file_path);
|
||||||
void removeDirRecursive(const QString& dirName);
|
void removeDirRecursive(const QString& dirName);
|
||||||
|
|
||||||
/* Ported from Qt4 to drop dependency on QtGui */
|
|
||||||
QString QDesktopServicesDataLocation();
|
|
||||||
QString QDesktopServicesCacheLocation();
|
|
||||||
QString QDesktopServicesDownloadLocation();
|
|
||||||
/* End of Qt4 code */
|
|
||||||
|
|
||||||
QString cacheLocation();
|
|
||||||
QString tempPath();
|
QString tempPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QSettings>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
@ -10,14 +10,14 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
#include "base/utils/fs.h"
|
#include "base/profile.h"
|
||||||
|
|
||||||
HtmlBrowser::HtmlBrowser(QWidget* parent)
|
HtmlBrowser::HtmlBrowser(QWidget* parent)
|
||||||
: QTextBrowser(parent)
|
: QTextBrowser(parent)
|
||||||
{
|
{
|
||||||
m_netManager = new QNetworkAccessManager(this);
|
m_netManager = new QNetworkAccessManager(this);
|
||||||
m_diskCache = new QNetworkDiskCache(this);
|
m_diskCache = new QNetworkDiskCache(this);
|
||||||
m_diskCache->setCacheDirectory(QDir::cleanPath(Utils::Fs::cacheLocation() + "/rss"));
|
m_diskCache->setCacheDirectory(QDir::cleanPath(specialFolderLocation(SpecialFolder::Cache) + "/rss"));
|
||||||
m_diskCache->setMaximumCacheSize(50 * 1024 * 1024);
|
m_diskCache->setMaximumCacheSize(50 * 1024 * 1024);
|
||||||
qDebug() << "HtmlBrowser cache path:" << m_diskCache->cacheDirectory() << " max size:" << m_diskCache->maximumCacheSize() / 1024 / 1024 << "MB";
|
qDebug() << "HtmlBrowser cache path:" << m_diskCache->cacheDirectory() << " max size:" << m_diskCache->maximumCacheSize() / 1024 / 1024 << "MB";
|
||||||
m_netManager->setCache(m_diskCache);
|
m_netManager->setCache(m_diskCache);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user