mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 06:01:33 -06:00
Compare commits
11 Commits
46cc3a358e
...
f68bc3fef9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f68bc3fef9 | ||
|
|
ed9a8687ad | ||
|
|
6a4b1b9727 | ||
|
|
f2f4676824 | ||
|
|
8b9064a33c | ||
|
|
296c90d688 | ||
|
|
564afc975f | ||
|
|
a77b17e6da | ||
|
|
4a3922d152 | ||
|
|
1b96a48266 | ||
|
|
1f6e7519a0 |
7
.github/workflows/ci_macos.yaml
vendored
7
.github/workflows/ci_macos.yaml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
- name: Setup ccache
|
||||
uses: Chocobo1/setup-ccache-action@v1
|
||||
with:
|
||||
store_cache: ${{ github.ref == 'refs/heads/master' }}
|
||||
store_cache: ${{ (github.repository != 'qbittorrent/qBittorrent') || (github.ref == 'refs/heads/master') }}
|
||||
update_packager_index: false
|
||||
ccache_options: |
|
||||
max_size=1G
|
||||
@@ -119,6 +119,11 @@ jobs:
|
||||
cmake --build build --target qbt_update_translations
|
||||
cmake --build build
|
||||
cmake --build build --target check
|
||||
if [ "${{ matrix.qbt_gui }}" = "GUI=ON" ]; then
|
||||
build/qbittorrent.app/Contents/MacOS/qbittorrent -v
|
||||
else
|
||||
build/qbittorrent-nox.app/Contents/MacOS/qbittorrent-nox -v
|
||||
fi
|
||||
|
||||
- name: Prepare build artifacts
|
||||
run: |
|
||||
|
||||
9
.github/workflows/ci_ubuntu.yaml
vendored
9
.github/workflows/ci_ubuntu.yaml
vendored
@@ -39,12 +39,12 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt install \
|
||||
build-essential cmake ninja-build \
|
||||
libssl-dev libxkbcommon-x11-dev libxcb-cursor-dev zlib1g-dev
|
||||
libssl-dev zlib1g-dev
|
||||
|
||||
- name: Setup ccache
|
||||
uses: Chocobo1/setup-ccache-action@v1
|
||||
with:
|
||||
store_cache: ${{ github.ref == 'refs/heads/master' }}
|
||||
store_cache: ${{ (github.repository != 'qbittorrent/qBittorrent') || (github.ref == 'refs/heads/master') }}
|
||||
update_packager_index: false
|
||||
ccache_options: |
|
||||
max_size=1G
|
||||
@@ -123,6 +123,11 @@ jobs:
|
||||
cmake --build build --target qbt_update_translations
|
||||
cmake --build build
|
||||
cmake --build build --target check
|
||||
if [ "${{ matrix.qbt_gui }}" = "GUI=ON" ]; then
|
||||
QT_QPA_PLATFORM=offscreen build/qbittorrent -v
|
||||
else
|
||||
build/qbittorrent-nox -v
|
||||
fi
|
||||
DESTDIR="qbittorrent" cmake --install build
|
||||
|
||||
- name: Run CodeQL analysis
|
||||
|
||||
4
dist/windows/config.nsh
vendored
4
dist/windows/config.nsh
vendored
@@ -157,16 +157,20 @@ ${Case} 0
|
||||
${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on
|
||||
${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user
|
||||
MessageBox mb_YesNo|mb_IconExclamation|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, try again" /SD IDNO IDYES uac_tryagain IDNO 0
|
||||
SetErrorLevel 1314 # WinError.h: `ERROR_PRIVILEGE_NOT_HELD`
|
||||
${EndIf}
|
||||
;fall-through and die
|
||||
${Case} 1223
|
||||
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, aborting!"
|
||||
SetErrorLevel 1223 # WinError.h: `ERROR_CANCELLED`
|
||||
Quit
|
||||
${Case} 1062
|
||||
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!"
|
||||
SetErrorLevel 1062 # WinError.h: `ERROR_SERVICE_NOT_ACTIVE`
|
||||
Quit
|
||||
${Default}
|
||||
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate , error $0"
|
||||
SetErrorLevel 1603 # WinError.h: `ERROR_INSTALL_FAILURE`
|
||||
Quit
|
||||
${EndSwitch}
|
||||
|
||||
|
||||
@@ -776,8 +776,9 @@ void Application::allTorrentsFinished()
|
||||
bool isShutdown = pref->shutdownWhenDownloadsComplete();
|
||||
bool isSuspend = pref->suspendWhenDownloadsComplete();
|
||||
bool isHibernate = pref->hibernateWhenDownloadsComplete();
|
||||
bool isReboot = pref->rebootWhenDownloadsComplete();
|
||||
|
||||
bool haveAction = isExit || isShutdown || isSuspend || isHibernate;
|
||||
const bool haveAction = isExit || isShutdown || isSuspend || isHibernate || isReboot;
|
||||
if (!haveAction) return;
|
||||
|
||||
ShutdownDialogAction action = ShutdownDialogAction::Exit;
|
||||
@@ -787,6 +788,8 @@ void Application::allTorrentsFinished()
|
||||
action = ShutdownDialogAction::Hibernate;
|
||||
else if (isShutdown)
|
||||
action = ShutdownDialogAction::Shutdown;
|
||||
else if (isReboot)
|
||||
action = ShutdownDialogAction::Reboot;
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
// ask confirm
|
||||
@@ -808,6 +811,7 @@ void Application::allTorrentsFinished()
|
||||
pref->setShutdownWhenDownloadsComplete(false);
|
||||
pref->setSuspendWhenDownloadsComplete(false);
|
||||
pref->setHibernateWhenDownloadsComplete(false);
|
||||
pref->setRebootWhenDownloadsComplete(false);
|
||||
// Make sure preferences are synced before exiting
|
||||
m_shutdownAct = action;
|
||||
}
|
||||
|
||||
@@ -1186,25 +1186,7 @@ bool TorrentImpl::isCompleted() const
|
||||
|
||||
bool TorrentImpl::isActive() const
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case TorrentState::StalledDownloading:
|
||||
return (uploadPayloadRate() > 0);
|
||||
|
||||
case TorrentState::DownloadingMetadata:
|
||||
case TorrentState::ForcedDownloadingMetadata:
|
||||
case TorrentState::Downloading:
|
||||
case TorrentState::ForcedDownloading:
|
||||
case TorrentState::Uploading:
|
||||
case TorrentState::ForcedUploading:
|
||||
case TorrentState::Moving:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return false;
|
||||
return ((uploadPayloadRate() > 0) || (downloadPayloadRate() > 0));
|
||||
}
|
||||
|
||||
bool TorrentImpl::isInactive() const
|
||||
|
||||
@@ -494,10 +494,17 @@ void Preferences::setWinStartup(const bool b)
|
||||
settings.remove(profileID);
|
||||
}
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
QString Preferences::getStyle() const
|
||||
{
|
||||
return value<QString>(u"Appearance/Style"_s);
|
||||
#ifdef Q_OS_WIN
|
||||
const QString defaultStyleName = u"Fusion"_s;
|
||||
#else
|
||||
const QString defaultStyleName = u"system"_s;
|
||||
#endif
|
||||
const auto styleName = value<QString>(u"Appearance/Style"_s);
|
||||
return styleName.isEmpty() ? defaultStyleName : styleName;
|
||||
}
|
||||
|
||||
void Preferences::setStyle(const QString &styleName)
|
||||
@@ -507,7 +514,6 @@ void Preferences::setStyle(const QString &styleName)
|
||||
|
||||
setValue(u"Appearance/Style"_s, styleName);
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
// Downloads
|
||||
Path Preferences::getScanDirsLastPath() const
|
||||
@@ -1291,6 +1297,19 @@ void Preferences::setShutdownWhenDownloadsComplete(const bool shutdown)
|
||||
setValue(u"Preferences/Downloads/AutoShutDownOnCompletion"_s, shutdown);
|
||||
}
|
||||
|
||||
bool Preferences::rebootWhenDownloadsComplete() const
|
||||
{
|
||||
return value(u"Preferences/Downloads/AutoRebootOnCompletion"_s, false);
|
||||
}
|
||||
|
||||
void Preferences::setRebootWhenDownloadsComplete(const bool reboot)
|
||||
{
|
||||
if (reboot == rebootWhenDownloadsComplete())
|
||||
return;
|
||||
|
||||
setValue(u"Preferences/Downloads/AutoRebootOnCompletion"_s, reboot);
|
||||
}
|
||||
|
||||
bool Preferences::suspendWhenDownloadsComplete() const
|
||||
{
|
||||
return value(u"Preferences/Downloads/AutoSuspendOnCompletion"_s, false);
|
||||
|
||||
@@ -137,11 +137,11 @@ public:
|
||||
void setPreventFromSuspendWhenDownloading(bool b);
|
||||
bool preventFromSuspendWhenSeeding() const;
|
||||
void setPreventFromSuspendWhenSeeding(bool b);
|
||||
QString getStyle() const;
|
||||
void setStyle(const QString &styleName);
|
||||
#ifdef Q_OS_WIN
|
||||
bool WinStartup() const;
|
||||
void setWinStartup(bool b);
|
||||
QString getStyle() const;
|
||||
void setStyle(const QString &styleName);
|
||||
#endif
|
||||
|
||||
// Downloads
|
||||
@@ -287,6 +287,8 @@ public:
|
||||
|
||||
bool shutdownWhenDownloadsComplete() const;
|
||||
void setShutdownWhenDownloadsComplete(bool shutdown);
|
||||
bool rebootWhenDownloadsComplete() const;
|
||||
void setRebootWhenDownloadsComplete(bool reboot);
|
||||
bool suspendWhenDownloadsComplete() const;
|
||||
void setSuspendWhenDownloadsComplete(bool suspend);
|
||||
bool hibernateWhenDownloadsComplete() const;
|
||||
|
||||
@@ -37,7 +37,8 @@ enum class ShutdownDialogAction
|
||||
Exit,
|
||||
Shutdown,
|
||||
Suspend,
|
||||
Hibernate
|
||||
Hibernate,
|
||||
Reboot
|
||||
};
|
||||
|
||||
using QStringMap = QMap<QString, QString>;
|
||||
|
||||
@@ -87,22 +87,30 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
||||
{
|
||||
::SetSuspendState(TRUE, FALSE, FALSE);
|
||||
}
|
||||
else
|
||||
else if (action == ShutdownDialogAction::Shutdown)
|
||||
{
|
||||
std::wstring msg = QCoreApplication::translate("misc"
|
||||
, "qBittorrent will shutdown the computer now because all downloads are complete.").toStdWString();
|
||||
::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, FALSE);
|
||||
}
|
||||
else if (action == ShutdownDialogAction::Reboot)
|
||||
{
|
||||
std::wstring msg = QCoreApplication::translate("misc"
|
||||
, "qBittorrent will reboot the computer now because all downloads are complete.").toStdWString();
|
||||
::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, TRUE);
|
||||
}
|
||||
|
||||
// Disable shutdown privilege.
|
||||
tkp.Privileges[0].Attributes = 0;
|
||||
::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
||||
|
||||
#elif defined(Q_OS_MACOS)
|
||||
AEEventID EventToSend;
|
||||
if (action != ShutdownDialogAction::Shutdown)
|
||||
AEEventID EventToSend {};
|
||||
if (action == ShutdownDialogAction::Suspend)
|
||||
EventToSend = kAESleep;
|
||||
else
|
||||
else if (action == ShutdownDialogAction::Reboot)
|
||||
EventToSend = kAERestart;
|
||||
else if (action == ShutdownDialogAction::Shutdown)
|
||||
EventToSend = kAEShutDown;
|
||||
AEAddressDesc targetDesc;
|
||||
const ProcessSerialNumber kPSNOfSystemProcess = {0, kSystemProcess};
|
||||
@@ -133,7 +141,7 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
||||
|
||||
#elif defined(QBT_USES_DBUS)
|
||||
// Use dbus to power off / suspend the system
|
||||
if (action != ShutdownDialogAction::Shutdown)
|
||||
if ((action == ShutdownDialogAction::Suspend) || (action == ShutdownDialogAction::Hibernate))
|
||||
{
|
||||
// Some recent systems use systemd's logind
|
||||
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||
@@ -166,7 +174,7 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
||||
else
|
||||
halIface.call(u"Hibernate"_s);
|
||||
}
|
||||
else
|
||||
else if (action == ShutdownDialogAction::Shutdown)
|
||||
{
|
||||
// Some recent systems use systemd's logind
|
||||
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||
@@ -190,6 +198,30 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac
|
||||
QDBusConnection::systemBus());
|
||||
halIface.call(u"Shutdown"_s);
|
||||
}
|
||||
else if (action == ShutdownDialogAction::Reboot)
|
||||
{
|
||||
// Some recent systems use systemd's logind
|
||||
QDBusInterface login1Iface(u"org.freedesktop.login1"_s, u"/org/freedesktop/login1"_s,
|
||||
u"org.freedesktop.login1.Manager"_s, QDBusConnection::systemBus());
|
||||
if (login1Iface.isValid())
|
||||
{
|
||||
login1Iface.call(u"Reboot"_s, false);
|
||||
return;
|
||||
}
|
||||
// Else, other recent systems use ConsoleKit
|
||||
QDBusInterface consolekitIface(u"org.freedesktop.ConsoleKit"_s, u"/org/freedesktop/ConsoleKit/Manager"_s,
|
||||
u"org.freedesktop.ConsoleKit.Manager"_s, QDBusConnection::systemBus());
|
||||
if (consolekitIface.isValid())
|
||||
{
|
||||
consolekitIface.call(u"Restart"_s);
|
||||
return;
|
||||
}
|
||||
// HAL (older systems)
|
||||
QDBusInterface halIface(u"org.freedesktop.Hal"_s, u"/org/freedesktop/Hal/devices/computer"_s,
|
||||
u"org.freedesktop.Hal.Device.SystemPowerManagement"_s,
|
||||
QDBusConnection::systemBus());
|
||||
halIface.call(u"Reboot"_s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -388,10 +388,16 @@ MainWindow::MainWindow(IGUIApplication *app, const WindowState initialState, con
|
||||
autoShutdownGroup->addAction(m_ui->actionAutoShutdown);
|
||||
autoShutdownGroup->addAction(m_ui->actionAutoSuspend);
|
||||
autoShutdownGroup->addAction(m_ui->actionAutoHibernate);
|
||||
autoShutdownGroup->addAction(m_ui->actionAutoReboot);
|
||||
#if (!defined(Q_OS_UNIX) || defined(Q_OS_MACOS)) || defined(QBT_USES_DBUS)
|
||||
m_ui->actionAutoShutdown->setChecked(pref->shutdownWhenDownloadsComplete());
|
||||
m_ui->actionAutoReboot->setChecked(pref->rebootWhenDownloadsComplete());
|
||||
m_ui->actionAutoSuspend->setChecked(pref->suspendWhenDownloadsComplete());
|
||||
m_ui->actionAutoHibernate->setChecked(pref->hibernateWhenDownloadsComplete());
|
||||
#ifdef Q_OS_MACOS
|
||||
// macOS doesn't support Hibernate via Apple Events API
|
||||
m_ui->actionAutoHibernate->setDisabled(true);
|
||||
#endif
|
||||
#else
|
||||
m_ui->actionAutoShutdown->setDisabled(true);
|
||||
m_ui->actionAutoSuspend->setDisabled(true);
|
||||
@@ -1790,30 +1796,31 @@ void MainWindow::on_actionCriticalMessages_triggered(const bool checked)
|
||||
setExecutionLogMsgTypes(flags);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAutoExit_toggled(bool enabled)
|
||||
void MainWindow::on_actionAutoExit_toggled(const bool enabled)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << enabled;
|
||||
Preferences::instance()->setShutdownqBTWhenDownloadsComplete(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAutoSuspend_toggled(bool enabled)
|
||||
void MainWindow::on_actionAutoSuspend_toggled(const bool enabled)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << enabled;
|
||||
Preferences::instance()->setSuspendWhenDownloadsComplete(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAutoHibernate_toggled(bool enabled)
|
||||
void MainWindow::on_actionAutoHibernate_toggled(const bool enabled)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << enabled;
|
||||
Preferences::instance()->setHibernateWhenDownloadsComplete(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAutoShutdown_toggled(bool enabled)
|
||||
void MainWindow::on_actionAutoShutdown_toggled(const bool enabled)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << enabled;
|
||||
Preferences::instance()->setShutdownWhenDownloadsComplete(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAutoReboot_toggled(const bool enabled)
|
||||
{
|
||||
Preferences::instance()->setRebootWhenDownloadsComplete(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::updatePowerManagementState() const
|
||||
{
|
||||
const auto *pref = Preferences::instance();
|
||||
|
||||
@@ -158,6 +158,7 @@ private slots:
|
||||
void on_actionAutoSuspend_toggled(bool);
|
||||
void on_actionAutoHibernate_toggled(bool);
|
||||
void on_actionAutoShutdown_toggled(bool);
|
||||
void on_actionAutoReboot_toggled(bool);
|
||||
void on_actionAbout_triggered();
|
||||
void on_actionStatistics_triggered();
|
||||
void on_actionCreateTorrent_triggered();
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
<addaction name="actionAutoExit"/>
|
||||
<addaction name="actionAutoSuspend"/>
|
||||
<addaction name="actionAutoHibernate"/>
|
||||
<addaction name="actionAutoReboot"/>
|
||||
<addaction name="actionAutoShutdown"/>
|
||||
</widget>
|
||||
<addaction name="actionCreateTorrent"/>
|
||||
@@ -397,6 +398,14 @@
|
||||
<string>Sh&utdown System</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAutoReboot">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Reboot System</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAutoShutdownDisabled">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -43,13 +43,10 @@
|
||||
#include <QEvent>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStyleFactory>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QTranslator>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QStyleFactory>
|
||||
#endif
|
||||
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/sharelimitaction.h"
|
||||
#include "base/exceptions.h"
|
||||
@@ -376,11 +373,7 @@ void OptionsDialog::loadBehaviorTabOptions()
|
||||
m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled());
|
||||
|
||||
connect(m_ui->comboLanguage, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
connect(m_ui->comboStyle, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
#endif
|
||||
|
||||
#ifdef QBT_HAS_COLORSCHEME_OPTION
|
||||
connect(m_ui->comboColorScheme, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
#endif
|
||||
@@ -488,9 +481,7 @@ void OptionsDialog::saveBehaviorTabOptions() const
|
||||
}
|
||||
pref->setLocale(locale);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pref->setStyle(m_ui->comboStyle->currentData().toString());
|
||||
#endif
|
||||
|
||||
#ifdef QBT_HAS_COLORSCHEME_OPTION
|
||||
UIThemeManager::instance()->setColorScheme(m_ui->comboColorScheme->currentData().value<ColorScheme>());
|
||||
@@ -1126,6 +1117,8 @@ void OptionsDialog::loadBittorrentTabOptions()
|
||||
m_ui->spinUploadRateForSlowTorrents->setValue(session->uploadRateForSlowTorrents());
|
||||
m_ui->spinSlowTorrentsInactivityTimer->setValue(session->slowTorrentsInactivityTimer());
|
||||
|
||||
m_ui->spinMaxRatio->setMaximum(std::numeric_limits<int>::max());
|
||||
|
||||
if (session->globalMaxRatio() >= 0.)
|
||||
{
|
||||
// Enable
|
||||
@@ -1170,7 +1163,7 @@ void OptionsDialog::loadBittorrentTabOptions()
|
||||
|
||||
const QHash<BitTorrent::ShareLimitAction, int> actIndex =
|
||||
{
|
||||
{BitTorrent::ShareLimitAction::Stop, 0},
|
||||
{BitTorrent::ShareLimitAction::Stop, 0},
|
||||
{BitTorrent::ShareLimitAction::Remove, 1},
|
||||
{BitTorrent::ShareLimitAction::RemoveWithContent, 2},
|
||||
{BitTorrent::ShareLimitAction::EnableSuperSeeding, 3}
|
||||
@@ -1846,6 +1839,11 @@ void OptionsDialog::initializeStyleCombo()
|
||||
#ifdef Q_OS_WIN
|
||||
m_ui->labelStyleHint->setText(tr("%1 is recommended for best compatibility with Windows dark mode"
|
||||
, "Fusion is recommended for best compatibility with Windows dark mode").arg(u"Fusion"_s));
|
||||
#else
|
||||
m_ui->labelStyleHint->hide();
|
||||
m_ui->layoutStyle->removeWidget(m_ui->labelStyleHint);
|
||||
#endif
|
||||
|
||||
m_ui->comboStyle->addItem(tr("System", "System default Qt style"), u"system"_s);
|
||||
m_ui->comboStyle->setItemData(0, tr("Let Qt decide the style for this system"), Qt::ToolTipRole);
|
||||
m_ui->comboStyle->insertSeparator(1);
|
||||
@@ -1859,14 +1857,6 @@ void OptionsDialog::initializeStyleCombo()
|
||||
const QString selectedStyleName = prefStyleName.isEmpty() ? QApplication::style()->name() : prefStyleName;
|
||||
const int styleIndex = m_ui->comboStyle->findData(selectedStyleName, Qt::UserRole, Qt::MatchFixedString);
|
||||
m_ui->comboStyle->setCurrentIndex(std::max(0, styleIndex));
|
||||
#else
|
||||
m_ui->labelStyle->hide();
|
||||
m_ui->comboStyle->hide();
|
||||
m_ui->labelStyleHint->hide();
|
||||
m_ui->layoutStyle->removeWidget(m_ui->labelStyle);
|
||||
m_ui->layoutStyle->removeWidget(m_ui->comboStyle);
|
||||
m_ui->layoutStyle->removeWidget(m_ui->labelStyleHint);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OptionsDialog::initializeColorSchemeOptions()
|
||||
|
||||
@@ -1908,7 +1908,7 @@ readme[0-9].txt: filter 'readme1.txt', 'readme2.txt' but not 'readme10.txt'.</st
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
<number>2147483647</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
@@ -1944,7 +1944,7 @@ readme[0-9].txt: filter 'readme1.txt', 'readme2.txt' but not 'readme10.txt'.</st
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
<number>2147483647</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
@@ -1961,7 +1961,7 @@ readme[0-9].txt: filter 'readme1.txt', 'readme2.txt' but not 'readme10.txt'.</st
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinMaxUploads">
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
<number>2147483647</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
@@ -1978,7 +1978,7 @@ readme[0-9].txt: filter 'readme1.txt', 'readme2.txt' but not 'readme10.txt'.</st
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spinMaxUploadsPerTorrent">
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
<number>2147483647</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
@@ -3789,9 +3789,6 @@ Specify an IPv4 or IPv6 address. You can specify "0.0.0.0" for any IPv
|
||||
<layout class="QHBoxLayout" name="horizontalLayoutAPIKey">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textWebUIAPIKey">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -3805,89 +3802,35 @@ Specify an IPv4 or IPv6 address. You can specify "0.0.0.0" for any IPv
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Copy API key</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/edit-copy.svg</normaloff>:/icons/edit-copy.svg</iconset>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnWebUIAPIKeyRotate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Generate API key</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/view-refresh.svg</normaloff>:/icons/view-refresh.svg</iconset>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnWebUIAPIKeyDelete">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Delete API key</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/list-remove.svg</normaloff>:/icons/list-remove.svg</iconset>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -134,6 +134,11 @@ void ShutdownConfirmDialog::initText()
|
||||
okButton->setText(tr("&Hibernate Now"));
|
||||
setWindowTitle(tr("Hibernate confirmation"));
|
||||
break;
|
||||
case ShutdownDialogAction::Reboot:
|
||||
m_msg = tr("The computer is going to reboot.");
|
||||
okButton->setText(tr("&Reboot Now"));
|
||||
setWindowTitle(tr("Reboot confirmation"));
|
||||
break;
|
||||
}
|
||||
|
||||
m_msg += u'\n';
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "torrentsharelimitswidget.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "ui_torrentsharelimitswidget.h"
|
||||
|
||||
@@ -59,6 +61,7 @@ TorrentShareLimitsWidget::TorrentShareLimitsWidget(QWidget *parent)
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->spinBoxRatioValue->setEnabled(false);
|
||||
m_ui->spinBoxRatioValue->setMaximum(std::numeric_limits<int>::max());
|
||||
m_ui->spinBoxRatioValue->setSuffix({});
|
||||
m_ui->spinBoxRatioValue->clear();
|
||||
m_ui->spinBoxSeedingTimeValue->setEnabled(false);
|
||||
|
||||
@@ -76,13 +76,11 @@ UIThemeManager::UIThemeManager()
|
||||
, m_useSystemIcons {Preferences::instance()->useSystemIcons()}
|
||||
#endif
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (const QString styleName = Preferences::instance()->getStyle(); styleName.compare(u"system", Qt::CaseInsensitive) != 0)
|
||||
{
|
||||
if (!QApplication::setStyle(styleName.isEmpty() ? u"Fusion"_s : styleName))
|
||||
if (!QApplication::setStyle(styleName))
|
||||
LogMsg(tr("Set app style failed. Unknown style: \"%1\"").arg(styleName), Log::WARNING);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef QBT_HAS_COLORSCHEME_OPTION
|
||||
applyColorScheme();
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#include "uithemesource.h"
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)) && defined(Q_OS_WIN)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0))
|
||||
#define QBT_HAS_COLORSCHEME_OPTION
|
||||
#endif
|
||||
|
||||
|
||||
@@ -211,6 +211,18 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||
|
||||
// hide on body click
|
||||
document.body.addEventListener("click", (event) => {
|
||||
const parentNode = event.target.parentNode;
|
||||
|
||||
// make sure the click was on a context menu item
|
||||
if ((parentNode !== null) && (parentNode.tagName.toLowerCase() === "li")) {
|
||||
const grandParentNode = parentNode.parentNode;
|
||||
if ((grandParentNode !== null) && (grandParentNode.classList.contains("contextMenu"))) {
|
||||
const submenuNodes = parentNode.getElementsByTagName("ul");
|
||||
if (submenuNodes.length > 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.hide();
|
||||
this.options.element = null;
|
||||
});
|
||||
|
||||
@@ -761,13 +761,13 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
}
|
||||
|
||||
let select = false;
|
||||
for (const tr of this.getTrs()) {
|
||||
if ((tr.rowId === rowId1) || (tr.rowId === rowId2)) {
|
||||
for (const row of this.getFilteredAndSortedRows()) {
|
||||
if ((row.rowId === rowId1) || (row.rowId === rowId2)) {
|
||||
select = !select;
|
||||
this.selectedRows.push(tr.rowId);
|
||||
this.selectedRows.push(row.rowId);
|
||||
}
|
||||
else if (select) {
|
||||
this.selectedRows.push(tr.rowId);
|
||||
this.selectedRows.push(row.rowId);
|
||||
}
|
||||
}
|
||||
this.setRowClass();
|
||||
@@ -1552,7 +1552,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
}
|
||||
|
||||
applyFilter(row, filterName, category, tag, trackerHost, filterTerms) {
|
||||
const state = row["full_data"].state;
|
||||
const { state, upspeed, dlspeed } = row["full_data"];
|
||||
let inactive = false;
|
||||
|
||||
switch (filterName) {
|
||||
@@ -1592,11 +1592,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
inactive = true;
|
||||
// fallthrough
|
||||
case "active": {
|
||||
let r;
|
||||
if (state === "stalledDL")
|
||||
r = (row["full_data"].upspeed > 0);
|
||||
else
|
||||
r = (state === "metaDL") || (state === "forcedMetaDL") || (state === "downloading") || (state === "forcedDL") || (state === "uploading") || (state === "forcedUP");
|
||||
const r = (upspeed > 0) || (dlspeed > 0);
|
||||
if (r === inactive)
|
||||
return false;
|
||||
break;
|
||||
@@ -2363,6 +2359,9 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
|
||||
for (const [key, _] of this.collapseState)
|
||||
this.expandNode(key);
|
||||
|
||||
if (this.useVirtualList)
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
collapseAllNodes() {
|
||||
@@ -2374,6 +2373,9 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
if (state.depth >= 1)
|
||||
this.collapseNode(key);
|
||||
}
|
||||
|
||||
if (this.useVirtualList)
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
#updateNodeVisibility(node, shouldHide) {
|
||||
@@ -2745,8 +2747,10 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
|
||||
generateRowsSignature() {
|
||||
const rowsData = [];
|
||||
for (const { rowId } of this.getRowValues())
|
||||
rowsData.push({ ...this.getNode(rowId).serialize(), collapsed: this.isCollapsed(rowId) });
|
||||
for (const { rowId } of this.getRowValues()) {
|
||||
const node = this.getNode(rowId);
|
||||
rowsData.push({ ...node.serialize(), collapsed: this.isCollapsed(node.rowId) });
|
||||
}
|
||||
return JSON.stringify(rowsData);
|
||||
}
|
||||
|
||||
@@ -2775,7 +2779,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
// sort, then filter
|
||||
this.#sortNodesByColumn(root, this.columns[this.sortedColumn]);
|
||||
const rows = (() => {
|
||||
if (this.filterTerms.length === 0) {
|
||||
if (!this.useVirtualList && (this.filterTerms.length === 0)) {
|
||||
const nodeArray = this.fileTree.toArray();
|
||||
const filteredRows = nodeArray.map(node => this.getRow(node));
|
||||
return filteredRows;
|
||||
|
||||
@@ -74,6 +74,7 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
const new_hash = torrentsTable.getCurrentTorrentID();
|
||||
if (new_hash === "") {
|
||||
torrentFilesTable.clear();
|
||||
current_hash = "";
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
return;
|
||||
}
|
||||
@@ -176,6 +177,7 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
|
||||
const clear = () => {
|
||||
torrentFilesTable.clear();
|
||||
current_hash = "";
|
||||
};
|
||||
|
||||
return exports();
|
||||
|
||||
Reference in New Issue
Block a user