mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-19 21:03:30 -07:00
commit
a6809efbbb
8 changed files with 105 additions and 25 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2025 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -124,6 +124,28 @@ namespace
|
|||
const int PIXMAP_CACHE_SIZE = 64 * 1024 * 1024; // 64MiB
|
||||
#endif
|
||||
|
||||
const QString PARAM_ADDSTOPPED = u"@addStopped"_s;
|
||||
const QString PARAM_CATEGORY = u"@category"_s;
|
||||
const QString PARAM_FIRSTLASTPIECEPRIORITY = u"@firstLastPiecePriority"_s;
|
||||
const QString PARAM_SAVEPATH = u"@savePath"_s;
|
||||
const QString PARAM_SEQUENTIAL = u"@sequential"_s;
|
||||
const QString PARAM_SKIPCHECKING = u"@skipChecking"_s;
|
||||
const QString PARAM_SKIPDIALOG = u"@skipDialog"_s;
|
||||
|
||||
QString bindParamValue(const QStringView paramName, const QStringView paramValue)
|
||||
{
|
||||
return paramName + u'=' + paramValue;
|
||||
}
|
||||
|
||||
std::pair<QStringView, QStringView> parseParam(const QStringView param)
|
||||
{
|
||||
const qsizetype sepIndex = param.indexOf(u'=');
|
||||
if (sepIndex >= 0)
|
||||
return {param.first(sepIndex), param.sliced(sepIndex + 1)};
|
||||
|
||||
return {param, {}};
|
||||
}
|
||||
|
||||
QString serializeParams(const QBtCommandLineParameters ¶ms)
|
||||
{
|
||||
QStringList result;
|
||||
|
@ -138,85 +160,86 @@ namespace
|
|||
const BitTorrent::AddTorrentParams &addTorrentParams = params.addTorrentParams;
|
||||
|
||||
if (!addTorrentParams.savePath.isEmpty())
|
||||
result.append(u"@savePath=" + addTorrentParams.savePath.data());
|
||||
result.append(bindParamValue(PARAM_SAVEPATH, addTorrentParams.savePath.data()));
|
||||
|
||||
if (addTorrentParams.addStopped.has_value())
|
||||
result.append(*addTorrentParams.addStopped ? u"@addStopped=1"_s : u"@addStopped=0"_s);
|
||||
result.append(bindParamValue(PARAM_ADDSTOPPED, (*addTorrentParams.addStopped ? u"1" : u"0")));
|
||||
|
||||
if (addTorrentParams.skipChecking)
|
||||
result.append(u"@skipChecking"_s);
|
||||
result.append(PARAM_SKIPCHECKING);
|
||||
|
||||
if (!addTorrentParams.category.isEmpty())
|
||||
result.append(u"@category=" + addTorrentParams.category);
|
||||
result.append(bindParamValue(PARAM_CATEGORY, addTorrentParams.category));
|
||||
|
||||
if (addTorrentParams.sequential)
|
||||
result.append(u"@sequential"_s);
|
||||
result.append(PARAM_SEQUENTIAL);
|
||||
|
||||
if (addTorrentParams.firstLastPiecePriority)
|
||||
result.append(u"@firstLastPiecePriority"_s);
|
||||
result.append(PARAM_FIRSTLASTPIECEPRIORITY);
|
||||
|
||||
if (params.skipDialog.has_value())
|
||||
result.append(*params.skipDialog ? u"@skipDialog=1"_s : u"@skipDialog=0"_s);
|
||||
result.append(bindParamValue(PARAM_SKIPDIALOG, (*params.skipDialog ? u"1" : u"0")));
|
||||
|
||||
result += params.torrentSources;
|
||||
|
||||
return result.join(PARAMS_SEPARATOR);
|
||||
}
|
||||
|
||||
QBtCommandLineParameters parseParams(const QString &str)
|
||||
QBtCommandLineParameters parseParams(const QStringView str)
|
||||
{
|
||||
QBtCommandLineParameters parsedParams;
|
||||
BitTorrent::AddTorrentParams &addTorrentParams = parsedParams.addTorrentParams;
|
||||
|
||||
for (QString param : asConst(str.split(PARAMS_SEPARATOR, Qt::SkipEmptyParts)))
|
||||
for (QStringView param : asConst(str.split(PARAMS_SEPARATOR, Qt::SkipEmptyParts)))
|
||||
{
|
||||
param = param.trimmed();
|
||||
const auto [paramName, paramValue] = parseParam(param);
|
||||
|
||||
// Process strings indicating options specified by the user.
|
||||
|
||||
if (param.startsWith(u"@savePath="))
|
||||
if (paramName == PARAM_SAVEPATH)
|
||||
{
|
||||
addTorrentParams.savePath = Path(param.mid(10));
|
||||
addTorrentParams.savePath = Path(paramValue.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param.startsWith(u"@addStopped="))
|
||||
if (paramName == PARAM_ADDSTOPPED)
|
||||
{
|
||||
addTorrentParams.addStopped = (QStringView(param).mid(11).toInt() != 0);
|
||||
addTorrentParams.addStopped = (paramValue.toInt() != 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == u"@skipChecking")
|
||||
if (paramName == PARAM_SKIPCHECKING)
|
||||
{
|
||||
addTorrentParams.skipChecking = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param.startsWith(u"@category="))
|
||||
if (paramName == PARAM_CATEGORY)
|
||||
{
|
||||
addTorrentParams.category = param.mid(10);
|
||||
addTorrentParams.category = paramValue.toString();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == u"@sequential")
|
||||
if (paramName == PARAM_SEQUENTIAL)
|
||||
{
|
||||
addTorrentParams.sequential = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == u"@firstLastPiecePriority")
|
||||
if (paramName == PARAM_FIRSTLASTPIECEPRIORITY)
|
||||
{
|
||||
addTorrentParams.firstLastPiecePriority = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param.startsWith(u"@skipDialog="))
|
||||
if (paramName == PARAM_SKIPDIALOG)
|
||||
{
|
||||
parsedParams.skipDialog = (QStringView(param).mid(12).toInt() != 0);
|
||||
parsedParams.skipDialog = (paramValue.toInt() != 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
parsedParams.torrentSources.append(param);
|
||||
parsedParams.torrentSources.append(param.toString());
|
||||
}
|
||||
|
||||
return parsedParams;
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QHostAddress>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
|
|
@ -2000,6 +2000,19 @@ void Preferences::setAddNewTorrentDialogSavePathHistoryLength(const int value)
|
|||
setValue(u"AddNewTorrentDialog/SavePathHistoryLength"_s, clampedValue);
|
||||
}
|
||||
|
||||
bool Preferences::isAddNewTorrentDialogAttached() const
|
||||
{
|
||||
return value(u"AddNewTorrentDialog/Attached"_s, false);
|
||||
}
|
||||
|
||||
void Preferences::setAddNewTorrentDialogAttached(const bool attached)
|
||||
{
|
||||
if (attached == isAddNewTorrentDialogAttached())
|
||||
return;
|
||||
|
||||
setValue(u"AddNewTorrentDialog/Attached"_s, attached);
|
||||
}
|
||||
|
||||
void Preferences::apply()
|
||||
{
|
||||
if (SettingsStorage::instance()->save())
|
||||
|
|
|
@ -423,6 +423,8 @@ public:
|
|||
void setAddNewTorrentDialogTopLevel(bool value);
|
||||
int addNewTorrentDialogSavePathHistoryLength() const;
|
||||
void setAddNewTorrentDialogSavePathHistoryLength(int value);
|
||||
bool isAddNewTorrentDialogAttached() const;
|
||||
void setAddNewTorrentDialogAttached(bool attached);
|
||||
|
||||
public slots:
|
||||
void setStatusFilterState(bool checked);
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace
|
|||
ENABLE_SPEED_WIDGET,
|
||||
#ifndef Q_OS_MACOS
|
||||
ENABLE_ICONS_IN_MENUS,
|
||||
USE_ATTACHED_ADD_NEW_TORRENT_DIALOG,
|
||||
#endif
|
||||
// embedded tracker
|
||||
TRACKER_STATUS,
|
||||
|
@ -323,6 +324,7 @@ void AdvancedSettings::saveAdvancedSettings() const
|
|||
pref->setSpeedWidgetEnabled(m_checkBoxSpeedWidgetEnabled.isChecked());
|
||||
#ifndef Q_OS_MACOS
|
||||
pref->setIconsInMenusEnabled(m_checkBoxIconsInMenusEnabled.isChecked());
|
||||
pref->setAddNewTorrentDialogAttached(m_checkBoxAttachedAddNewTorrentDialog.isChecked());
|
||||
#endif
|
||||
|
||||
// Tracker
|
||||
|
@ -835,6 +837,9 @@ void AdvancedSettings::loadAdvancedSettings()
|
|||
// Enable icons in menus
|
||||
m_checkBoxIconsInMenusEnabled.setChecked(pref->iconsInMenusEnabled());
|
||||
addRow(ENABLE_ICONS_IN_MENUS, tr("Enable icons in menus"), &m_checkBoxIconsInMenusEnabled);
|
||||
|
||||
m_checkBoxAttachedAddNewTorrentDialog.setChecked(pref->isAddNewTorrentDialogAttached());
|
||||
addRow(USE_ATTACHED_ADD_NEW_TORRENT_DIALOG, tr("Attach \"Add new torrent\" dialog to main window"), &m_checkBoxAttachedAddNewTorrentDialog);
|
||||
#endif
|
||||
// Tracker State
|
||||
m_checkBoxTrackerStatus.setChecked(session->isTrackerEnabled());
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
|
||||
#ifndef Q_OS_MACOS
|
||||
QCheckBox m_checkBoxIconsInMenusEnabled;
|
||||
QCheckBox m_checkBoxAttachedAddNewTorrentDialog;
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
|
||||
|
|
|
@ -225,12 +225,19 @@ bool GUIAddTorrentManager::processTorrent(const QString &source
|
|||
if (!hasMetadata)
|
||||
btSession()->downloadMetadata(torrentDescr);
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
const bool attached = false;
|
||||
#else
|
||||
const bool attached = Preferences::instance()->isAddNewTorrentDialogAttached();
|
||||
#endif
|
||||
|
||||
// By not setting a parent to the "AddNewTorrentDialog", all those dialogs
|
||||
// will be displayed on top and will not overlap with the main window.
|
||||
auto *dlg = new AddNewTorrentDialog(torrentDescr, params, nullptr);
|
||||
auto *dlg = new AddNewTorrentDialog(torrentDescr, params, (attached ? app()->mainWindow() : nullptr));
|
||||
// Qt::Window is required to avoid showing only two dialog on top (see #12852).
|
||||
// Also improves the general convenience of adding multiple torrents.
|
||||
dlg->setWindowFlags(Qt::Window);
|
||||
if (!attached)
|
||||
dlg->setWindowFlags(Qt::Window);
|
||||
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_dialogs[infoHash] = dlg;
|
||||
|
|
|
@ -80,7 +80,33 @@ inline QHash<QString, UIThemeColor> defaultUIThemeColors()
|
|||
{u"TransferList.StoppedUploading"_s, {Color::Primer::Light::doneFg, Color::Primer::Dark::doneFg}},
|
||||
{u"TransferList.Moving"_s, {Color::Primer::Light::successFg, Color::Primer::Dark::successFg}},
|
||||
{u"TransferList.MissingFiles"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
|
||||
{u"TransferList.Error"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}}
|
||||
{u"TransferList.Error"_s, {Color::Primer::Light::dangerFg, Color::Primer::Dark::dangerFg}},
|
||||
|
||||
{u"Palette.Window"_s, {{}, {}}},
|
||||
{u"Palette.WindowText"_s, {{}, {}}},
|
||||
{u"Palette.Base"_s, {{}, {}}},
|
||||
{u"Palette.AlternateBase"_s, {{}, {}}},
|
||||
{u"Palette.Text"_s, {{}, {}}},
|
||||
{u"Palette.ToolTipBase"_s, {{}, {}}},
|
||||
{u"Palette.ToolTipText"_s, {{}, {}}},
|
||||
{u"Palette.BrightText"_s, {{}, {}}},
|
||||
{u"Palette.Highlight"_s, {{}, {}}},
|
||||
{u"Palette.HighlightedText"_s, {{}, {}}},
|
||||
{u"Palette.Button"_s, {{}, {}}},
|
||||
{u"Palette.ButtonText"_s, {{}, {}}},
|
||||
{u"Palette.Link"_s, {{}, {}}},
|
||||
{u"Palette.LinkVisited"_s, {{}, {}}},
|
||||
{u"Palette.Light"_s, {{}, {}}},
|
||||
{u"Palette.Midlight"_s, {{}, {}}},
|
||||
{u"Palette.Mid"_s, {{}, {}}},
|
||||
{u"Palette.Dark"_s, {{}, {}}},
|
||||
{u"Palette.Shadow"_s, {{}, {}}},
|
||||
{u"Palette.WindowTextDisabled"_s, {{}, {}}},
|
||||
{u"Palette.TextDisabled"_s, {{}, {}}},
|
||||
{u"Palette.ToolTipTextDisabled"_s, {{}, {}}},
|
||||
{u"Palette.BrightTextDisabled"_s, {{}, {}}},
|
||||
{u"Palette.HighlightedTextDisabled"_s, {{}, {}}},
|
||||
{u"Palette.ButtonTextDisabled"_s, {{}, {}}}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue