37 #include <QProcessEnvironment>
38 #include <QTextStream>
40 #if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
41 #include <QMessageBox>
62 explicit constexpr
Option(
const char *name,
char shortcut = 0)
64 , m_shortcut {shortcut}
70 return QLatin1String(
"--") + QLatin1String(m_name);
75 return QLatin1String(
"-") + QLatin1Char(m_shortcut);
80 return m_shortcut != 0;
85 return QLatin1String(
"QBT_")
86 + QString::fromLatin1(m_name).toUpper().replace(QLatin1Char(
'-'), QLatin1Char(
'_'));
109 explicit constexpr
BoolOption(
const char *name,
char shortcut = 0)
116 return (hasShortcut() && ((arg.size() == 2) && (arg == shortcutParameter())))
117 || (arg == fullParameter());
120 bool value(
const QProcessEnvironment &env)
const
122 QString val = env.value(envVarName());
124 return ((val == QLatin1String(
"1")) || (val.toUpper() == QLatin1String(
"TRUE")));
131 res += shortcutParameter() + QLatin1String(
" | ");
132 res += fullParameter();
133 return padUsageText(res);
153 return arg.startsWith(parameterAssignment());
156 QString
value(
const QString &arg)
const
158 QStringList parts = arg.split(QLatin1Char(
'='));
159 if (parts.size() == 2)
162 "e.g. Parameter '--webui-port' must follow syntax '--webui-port=value'")
163 .arg(fullParameter(), QLatin1String(
"<value>")));
166 QString
value(
const QProcessEnvironment &env,
const QString &defaultValue = {})
const
168 QString val = env.value(envVarName());
172 QString
usage(
const QString &valueName)
const
174 return padUsageText(parameterAssignment() + QLatin1Char(
'<') + valueName + QLatin1Char(
'>'));
180 return fullParameter() + QLatin1Char(
'=');
198 using StringOption::operator==;
199 using StringOption::usage;
205 int res = val.toInt(&ok);
208 "e.g. Parameter '--webui-port' must follow syntax '--webui-port=<value>'")
209 .arg(fullParameter(), QLatin1String(
"<integer value>")));
213 int value(
const QProcessEnvironment &env,
int defaultValue)
const
215 QString val = env.value(envVarName());
216 if (val.isEmpty())
return defaultValue;
219 int res = val.toInt(&ok);
222 qDebug() << QObject::tr(
"Expected integer number in environment variable '%1', but got '%2'")
223 .arg(envVarName(), val);
242 , m_defaultValue(defaultValue)
248 QStringList parts = arg.split(QLatin1Char(
'='));
249 return parts[0] == fullParameter();
254 return padUsageText(fullParameter() + QLatin1String(
"=<true|false>"));
257 std::optional<bool>
value(
const QString &arg)
const
259 QStringList parts = arg.split(QLatin1Char(
'='));
261 if (parts.size() == 1)
263 return m_defaultValue;
265 if (parts.size() == 2)
267 QString val = parts[1];
269 if ((val.toUpper() == QLatin1String(
"TRUE")) || (val == QLatin1String(
"1")))
273 if ((val.toUpper() == QLatin1String(
"FALSE")) || (val == QLatin1String(
"0")))
280 "e.g. Parameter '--add-paused' must follow syntax "
281 "'--add-paused=<true|false>'")
282 .arg(fullParameter(), QLatin1String(
"<true|false>")));
285 std::optional<bool>
value(
const QProcessEnvironment &env)
const
287 const QString val = env.value(envVarName(),
"-1");
291 return m_defaultValue;
293 if (val == QLatin1String(
"-1"))
297 if ((val.toUpper() == QLatin1String(
"TRUE")) || (val == QLatin1String(
"1")))
301 if ((val.toUpper() == QLatin1String(
"FALSE")) || (val == QLatin1String(
"0")))
306 qDebug() << QObject::tr(
"Expected %1 in environment variable '%2', but got '%3'")
307 .arg(QLatin1String(
"true|false"), envVarName(), val);
321 #if defined(DISABLE_GUI) && !defined(Q_OS_WIN)
322 constexpr
const BoolOption DAEMON_OPTION {
"daemon",
'd'};
345 #
if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
350 #elif !defined(Q_OS_WIN)
351 , shouldDaemonize(DAEMON_OPTION.
value(env))
375 result.append(QLatin1String(
"@savePath=") +
savePath);
378 result.append(*
addPaused ? QLatin1String {
"@addPaused=1"} : QLatin1String {
"@addPaused=0"});
381 result.append(QLatin1String(
"@skipChecking"));
384 result.append(QLatin1String(
"@category=") +
category);
387 result.append(QLatin1String(
"@sequential"));
390 result.append(QLatin1String(
"@firstLastPiecePriority"));
393 result.append(*
skipDialog ? QLatin1String {
"@skipDialog=1"} : QLatin1String {
"@skipDialog=0"});
403 for (
int i = 1; i <
args.count(); ++i)
405 const QString &arg =
args[i];
407 if ((arg.startsWith(
"--") && !arg.endsWith(
".torrent"))
408 || (arg.startsWith(
'-') && (arg.size() == 2)))
413 result.showHelp =
true;
415 #if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
418 result.showVersion =
true;
424 if ((result.webUiPort < 1) || (result.webUiPort > 65535))
426 .arg(QLatin1String(
"--webui-port")));
431 result.noSplash =
true;
433 #elif !defined(Q_OS_WIN)
434 else if (arg == DAEMON_OPTION)
436 result.shouldDaemonize =
true;
445 result.relativeFastresumePaths =
true;
461 result.skipChecking =
true;
469 result.sequential =
true;
473 result.firstLastPiecePriority =
true;
482 result.unknownParameter = arg;
488 QFileInfo torrentPath;
489 torrentPath.setFile(arg);
491 if (torrentPath.exists())
492 result.torrents += torrentPath.absoluteFilePath();
494 result.torrents += arg;
503 QStringList words = text.split(
' ');
504 QStringList lines = {words.first()};
505 int currentLineMaxLength = wrapAtColumn - initialIndentation;
507 for (
const QString &word :
asConst(words.mid(1)))
509 if (lines.last().length() + word.length() + 1 < currentLineMaxLength)
511 lines.last().append(
' ' + word);
515 lines.append(QString(initialIndentation,
' ') + word);
516 currentLineMaxLength = wrapAtColumn;
520 return lines.join(
'\n');
526 QTextStream stream(&text, QIODevice::WriteOnly);
529 stream << QObject::tr(
"Usage:") <<
'\n'
530 << indentation << prgName << QLatin1String(
" [options] [(<filename> | <url>)...]") <<
'\n'
532 << QObject::tr(
"Options:") <<
'\n'
533 #if !defined(Q_OS_WIN) || defined(DISABLE_GUI)
538 <<
wrapText(QObject::tr(
"Change the Web UI port"))
542 #elif !defined(Q_OS_WIN)
543 << DAEMON_OPTION.usage() <<
wrapText(QObject::tr(
"Run in daemon-mode (background)")) <<
'\n'
547 <<
wrapText(QObject::tr(
"Store configuration files in <dir>")) <<
'\n'
549 <<
wrapText(QObject::tr(
"Store configuration files in directories qBittorrent_<name>")) <<
'\n'
551 <<
wrapText(QObject::tr(
"Hack into libtorrent fastresume files and make file paths relative "
552 "to the profile directory")) <<
'\n'
553 << Option::padUsageText(QObject::tr(
"files or URLs"))
554 <<
wrapText(QObject::tr(
"Download the torrents passed by the user")) <<
'\n'
557 <<
wrapText(QObject::tr(
"Options when adding new torrents:"), 0) <<
'\n'
562 <<
wrapText(QObject::tr(
"Assign torrents to category. If the category doesn't exist, it will be "
566 <<
wrapText(QObject::tr(
"Download first and last pieces first")) <<
'\n'
568 <<
wrapText(QObject::tr(
"Specify whether the \"Add New Torrent\" dialog opens when adding a "
572 <<
wrapText(QObject::tr(
"Option values may be supplied via environment variables. For option named "
573 "'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper "
574 "case, '-' replaced with '_'). To pass flag values, set the variable to '1' or "
575 "'TRUE'. For example, to disable the splash screen: "), 0) <<
"\n"
576 << QLatin1String(
"QBT_NO_SPLASH=1 ") << prgName <<
'\n'
577 <<
wrapText(QObject::tr(
"Command line parameters take precedence over environment variables"), 0) <<
'\n';
584 #if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
585 QMessageBox msgBox(QMessageBox::Information, QObject::tr(
"Help"),
makeUsage(prgName), QMessageBox::Ok);
590 printf(
"%s\n", qUtf8Printable(
makeUsage(prgName)));
QBITTORRENT_HAS_EXECINFO_H if(NOT QBITTORRENT_HAS_EXECINFO_H) message(FATAL_ERROR "execinfo.h header file not found.\n" "Please either disable the STACKTRACE feature or use a libc that has this header file
bool operator==(const QString &arg) const
constexpr BoolOption(const char *name, char shortcut=0)
bool value(const QProcessEnvironment &env) const
int value(const QString &arg) const
constexpr IntOption(const char *name)
int value(const QProcessEnvironment &env, int defaultValue) const
QString usage(const QString &valueName) const
static QString padUsageText(const QString &usage)
QString shortcutParameter() const
QString fullParameter() const
constexpr Option(const char *name, char shortcut=0)
QString envVarName() const
std::optional< bool > value(const QString &arg) const
bool operator==(const QString &arg) const
constexpr TriStateBoolOption(const char *name, bool defaultValue)
std::optional< bool > value(const QProcessEnvironment &env) const
void displayUsage(const QString &prgName)
QString makeUsage(const QString &prgName)
QString wrapText(const QString &text, int initialIndentation=USAGE_TEXT_COLUMN, int wrapAtColumn=WRAP_AT_COLUMN)
QBtCommandLineParameters parseCommandLine(const QStringList &args)
constexpr std::add_const_t< T > & asConst(T &t) noexcept
QPoint screenCenter(const QWidget *w)
T unquote(const T &str, const QString "es=QChar('"'))
constexpr const StringOption CATEGORY_OPTION
bool operator==(const QString &s, const TriStateBoolOption &o)
constexpr const StringOption SAVE_PATH_OPTION
constexpr const TriStateBoolOption SKIP_DIALOG_OPTION
constexpr const BoolOption NO_SPLASH_OPTION
const int USAGE_TEXT_COLUMN
constexpr const BoolOption SHOW_VERSION_OPTION
constexpr const BoolOption RELATIVE_FASTRESUME
constexpr const StringOption PROFILE_OPTION
constexpr const IntOption WEBUI_PORT_OPTION
constexpr const BoolOption SEQUENTIAL_OPTION
constexpr const BoolOption FIRST_AND_LAST_OPTION
constexpr const BoolOption SKIP_HASH_CHECK_OPTION
constexpr const BoolOption SHOW_HELP_OPTION
constexpr const StringOption CONFIGURATION_OPTION
constexpr const TriStateBoolOption PAUSED_OPTION
const int USAGE_INDENTATION
T value(const QString &key, const T &defaultValue={})
std::optional< bool > addPaused
QStringList paramList() const
QBtCommandLineParameters(const QProcessEnvironment &)
std::optional< bool > skipDialog
bool firstLastPiecePriority
QString parameterAssignment() const
QString value(const QProcessEnvironment &env, const QString &defaultValue={}) const
QString value(const QString &arg) const
constexpr StringOption(const char *name)
bool operator==(const QString &arg) const
QString usage(const QString &valueName) const