mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-13 16:53:08 -07:00
Add support for different configurations. Partially closes #465
It may be useful to have different configurations either for portable versions or for debugging purposes. To implement this we add two options, avaliable via command line switches 1. An option to change configuration name ("--configuration"). The name supplied via this option is appended to QCoreApplication::applicationName() to form "qBittorrent_<conf_name>" name for the configuration files. 2. An option to provide a path do directory where all the settings are stored (kind of profile directory). There is a shortcut "--portable" which means "use directory 'profile' near the executable location". In order to implement that we have to perform initialisation of the profile directories before the SettingStorage and Preferences singletones are initialised. Thus, options parsing shall be performed without defaults read from preferences.
This commit is contained in:
parent
6ad8a4d8b1
commit
0f746ffd5a
20 changed files with 901 additions and 398 deletions
317
src/app/main.cpp
317
src/app/main.cpp
|
@ -68,6 +68,8 @@ Q_IMPORT_PLUGIN(QICOPlugin)
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include "application.h"
|
||||
#include "options.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/preferences.h"
|
||||
|
||||
|
@ -86,44 +88,12 @@ const char *sysSigName[] = {
|
|||
};
|
||||
#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
|
||||
void showSplashScreen();
|
||||
#endif
|
||||
void displayVersion();
|
||||
void displayUsage(const QString &prg_name);
|
||||
bool userAgreesWithLegalNotice();
|
||||
void displayBadArgMessage(const QString &message);
|
||||
QBtCommandLineParameters parseCommandLine();
|
||||
|
||||
// Main
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -137,103 +107,86 @@ int main(int argc, char *argv[])
|
|||
macMigratePlists();
|
||||
#endif
|
||||
|
||||
try {
|
||||
// Create Application
|
||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
||||
#ifndef DISABLE_GUI
|
||||
migrateRSS();
|
||||
// after the application object creation because we need a profile to be set already
|
||||
// for the migration
|
||||
migrateRSS();
|
||||
#endif
|
||||
const QBtCommandLineParameters ¶ms = app->commandLineArgs();
|
||||
|
||||
// Create Application
|
||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||
QScopedPointer<Application> app(new Application(appId, argc, argv));
|
||||
|
||||
const QBtCommandLineParameters params = parseCommandLine();
|
||||
|
||||
if (!params.unknownParameter.isEmpty()) {
|
||||
displayBadArgMessage(QObject::tr("%1 is an unknown command line parameter.", "--random-parameter is an unknown command line parameter.")
|
||||
.arg(params.unknownParameter));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!params.unknownParameter.isEmpty()) {
|
||||
throw CommandLineParameterError(QObject::tr("%1 is an unknown command line parameter.",
|
||||
"--random-parameter is an unknown command line parameter.")
|
||||
.arg(params.unknownParameter));
|
||||
}
|
||||
#ifndef Q_OS_WIN
|
||||
if (params.showVersion) {
|
||||
if (isOneArg) {
|
||||
displayVersion();
|
||||
return EXIT_SUCCESS;
|
||||
if (params.showVersion) {
|
||||
if (isOneArg) {
|
||||
displayVersion();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.")
|
||||
.arg(QLatin1String("-v (or --version)")));
|
||||
}
|
||||
else {
|
||||
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
|
||||
.arg(QLatin1String("-v (or --version)")));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (params.showHelp) {
|
||||
if (isOneArg) {
|
||||
displayUsage(argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
displayBadArgMessage(QObject::tr("%1 must be the single command line parameter.")
|
||||
if (params.showHelp) {
|
||||
if (isOneArg) {
|
||||
displayUsage(argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.")
|
||||
.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
|
||||
if (!qputenv("QBITTORRENT", QBT_VERSION))
|
||||
std::cerr << "Couldn't set environment variable...\n";
|
||||
// Set environment variable
|
||||
if (!qputenv("QBITTORRENT", QBT_VERSION))
|
||||
std::cerr << "Couldn't set environment variable...\n";
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
if (!userAgreesWithLegalNotice())
|
||||
return EXIT_SUCCESS;
|
||||
if (!userAgreesWithLegalNotice())
|
||||
return EXIT_SUCCESS;
|
||||
#else
|
||||
if (!params.shouldDaemonize
|
||||
&& isatty(fileno(stdin))
|
||||
&& isatty(fileno(stdout))
|
||||
&& !userAgreesWithLegalNotice())
|
||||
return EXIT_SUCCESS;
|
||||
if (!params.shouldDaemonize
|
||||
&& isatty(fileno(stdin))
|
||||
&& isatty(fileno(stdout))
|
||||
&& !userAgreesWithLegalNotice())
|
||||
return EXIT_SUCCESS;
|
||||
#endif
|
||||
|
||||
// Check if qBittorrent is already running for this user
|
||||
if (app->isRunning()) {
|
||||
// Check if qBittorrent is already running for this user
|
||||
if (app->isRunning()) {
|
||||
#ifdef DISABLE_GUI
|
||||
if (params.shouldDaemonize) {
|
||||
displayBadArgMessage(QObject::tr("You cannot use %1: qBittorrent is already running for this user.")
|
||||
.arg(QLatin1String("-d (or --daemon)")));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
if (params.shouldDaemonize) {
|
||||
throw CommandLineParameterError(QObject::tr("You cannot use %1: qBittorrent is already running for this user.")
|
||||
.arg(QLatin1String("-d (or --daemon)")));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
qDebug("qBittorrent is already running for this user.");
|
||||
qDebug("qBittorrent is already running for this user.");
|
||||
|
||||
Utils::Misc::msleep(300);
|
||||
app->sendParams(params.torrents);
|
||||
Utils::Misc::msleep(300);
|
||||
app->sendParams(params.torrents);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
// This affects only Windows apparently and Qt5.
|
||||
// When QNetworkAccessManager is instantiated it regularly starts polling
|
||||
// the network interfaces to see what's available and their status.
|
||||
// This polling creates jitter and high ping with wifi interfaces.
|
||||
// So here we disable it for lack of better measure.
|
||||
// It will also spew this message in the console: QObject::startTimer: Timers cannot have negative intervals
|
||||
// For more info see:
|
||||
// 1. https://github.com/qbittorrent/qBittorrent/issues/4209
|
||||
// 2. https://bugreports.qt.io/browse/QTBUG-40332
|
||||
// 3. https://bugreports.qt.io/browse/QTBUG-46015
|
||||
// This affects only Windows apparently and Qt5.
|
||||
// When QNetworkAccessManager is instantiated it regularly starts polling
|
||||
// the network interfaces to see what's available and their status.
|
||||
// This polling creates jitter and high ping with wifi interfaces.
|
||||
// So here we disable it for lack of better measure.
|
||||
// It will also spew this message in the console: QObject::startTimer: Timers cannot have negative intervals
|
||||
// For more info see:
|
||||
// 1. https://github.com/qbittorrent/qBittorrent/issues/4209
|
||||
// 2. https://bugreports.qt.io/browse/QTBUG-40332
|
||||
// 3. https://bugreports.qt.io/browse/QTBUG-46015
|
||||
|
||||
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
||||
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
|
@ -248,94 +201,45 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
if (!upgrade()) return EXIT_FAILURE;
|
||||
if (!upgrade()) return EXIT_FAILURE;
|
||||
#else
|
||||
if (!upgrade(!params.shouldDaemonize
|
||||
&& isatty(fileno(stdin))
|
||||
&& isatty(fileno(stdout)))) return EXIT_FAILURE;
|
||||
if (!upgrade(!params.shouldDaemonize
|
||||
&& isatty(fileno(stdin))
|
||||
&& isatty(fileno(stdout)))) return EXIT_FAILURE;
|
||||
#endif
|
||||
|
||||
#ifdef DISABLE_GUI
|
||||
if (params.shouldDaemonize) {
|
||||
app.reset(); // Destroy current application
|
||||
if ((daemon(1, 0) == 0)) {
|
||||
app.reset(new Application(appId, argc, argv));
|
||||
if (app->isRunning()) {
|
||||
// Another instance had time to start.
|
||||
if (params.shouldDaemonize) {
|
||||
app.reset(); // Destroy current application
|
||||
if ((daemon(1, 0) == 0)) {
|
||||
app.reset(new Application(appId, argc, argv));
|
||||
if (app->isRunning()) {
|
||||
// Another instance had time to start.
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qCritical("Something went wrong while daemonizing, exiting...");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qCritical("Something went wrong while daemonizing, exiting...");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!params.noSplash)
|
||||
showSplashScreen();
|
||||
if (!(params.noSplash || Preferences::instance()->isSplashScreenDisabled()))
|
||||
showSplashScreen();
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
|
||||
signal(SIGINT, sigNormalHandler);
|
||||
signal(SIGTERM, sigNormalHandler);
|
||||
signal(SIGABRT, sigAbnormalHandler);
|
||||
signal(SIGSEGV, sigAbnormalHandler);
|
||||
signal(SIGINT, sigNormalHandler);
|
||||
signal(SIGTERM, sigNormalHandler);
|
||||
signal(SIGABRT, sigAbnormalHandler);
|
||||
signal(SIGSEGV, sigAbnormalHandler);
|
||||
#endif
|
||||
|
||||
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
|
||||
else if ((arg == QLatin1String("-v")) || (arg == QLatin1String("--version"))) {
|
||||
result.showVersion = true;
|
||||
}
|
||||
#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 app->exec(params.torrents);
|
||||
}
|
||||
catch (CommandLineParameterError &er) {
|
||||
displayBadArgMessage(er.messageForUser());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
|
||||
|
@ -396,53 +300,6 @@ void displayVersion()
|
|||
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)
|
||||
{
|
||||
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue