2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 #include "optionsdialog.h"
34 #include <QApplication>
36 #include <QDesktopServices>
37 #include <QDialogButtonBox>
39 #include <QFileDialog>
40 #include <QMessageBox>
41 #include <QSystemTrayIcon>
42 #include <QTranslator>
44 #include "base/bittorrent/session.h"
45 #include "base/exceptions.h"
46 #include "base/global.h"
47 #include "base/net/portforwarder.h"
48 #include "base/net/proxyconfigurationmanager.h"
49 #include "base/path.h"
50 #include "base/preferences.h"
51 #include "base/rss/rss_autodownloader.h"
52 #include "base/rss/rss_session.h"
53 #include "base/torrentfileguard.h"
54 #include "base/torrentfileswatcher.h"
55 #include "base/utils/misc.h"
56 #include "base/utils/net.h"
57 #include "base/utils/password.h"
58 #include "base/utils/random.h"
59 #include "addnewtorrentdialog.h"
60 #include "advancedsettings.h"
61 #include "banlistoptionsdialog.h"
62 #include "interfaces/iguiapplication.h"
63 #include "ipsubnetwhitelistoptionsdialog.h"
64 #include "rss/automatedrssdownloader.h"
65 #include "ui_optionsdialog.h"
66 #include "uithemedialog.h"
67 #include "uithememanager.h"
69 #include "watchedfolderoptionsdialog.h"
70 #include "watchedfoldersmodel.h"
73 #include "base/net/dnsupdater.h"
76 #define SETTINGS_KEY(name) u"OptionsDialog/" name
80 QStringList
translatedWeekdayNames()
82 // return translated strings from Monday to Sunday in user selected locale
84 const QLocale locale
{Preferences::instance()->getLocale()};
85 const QDate date
{2018, 11, 5}; // Monday
87 for (int i
= 0; i
< 7; ++i
)
88 ret
.append(locale
.toString(date
.addDays(i
), u
"dddd"_qs
));
92 class WheelEventEater final
: public QObject
95 using QObject::QObject
;
98 bool eventFilter(QObject
*, QEvent
*event
) override
100 return (event
->type() == QEvent::Wheel
);
104 // Shortcuts for frequently used signals that have more than one overload. They would require
105 // type casts and that is why we declare required member pointer here instead.
106 void (QComboBox::*qComboBoxCurrentIndexChanged
)(int) = &QComboBox::currentIndexChanged
;
107 void (QSpinBox::*qSpinBoxValueChanged
)(int) = &QSpinBox::valueChanged
;
111 OptionsDialog::OptionsDialog(IGUIApplication
*app
, QWidget
*parent
)
113 , GUIApplicationComponent(app
)
114 , m_ui
{new Ui::OptionsDialog
}
115 , m_storeDialogSize
{SETTINGS_KEY(u
"Size"_qs
)}
116 , m_storeHSplitterSize
{SETTINGS_KEY(u
"HorizontalSplitterSizes"_qs
)}
117 , m_storeLastViewedPage
{SETTINGS_KEY(u
"LastViewedPage"_qs
)}
120 m_applyButton
= m_ui
->buttonBox
->button(QDialogButtonBox::Apply
);
123 setWindowTitle(tr("Preferences"));
126 m_ui
->hsplitter
->setCollapsible(0, false);
127 m_ui
->hsplitter
->setCollapsible(1, false);
130 m_ui
->tabSelection
->item(TAB_UI
)->setIcon(UIThemeManager::instance()->getIcon(u
"preferences-desktop"_qs
));
131 m_ui
->tabSelection
->item(TAB_BITTORRENT
)->setIcon(UIThemeManager::instance()->getIcon(u
"preferences-bittorrent"_qs
, u
"preferences-system-network"_qs
));
132 m_ui
->tabSelection
->item(TAB_CONNECTION
)->setIcon(UIThemeManager::instance()->getIcon(u
"network-connect"_qs
, u
"network-wired"_qs
));
133 m_ui
->tabSelection
->item(TAB_DOWNLOADS
)->setIcon(UIThemeManager::instance()->getIcon(u
"download"_qs
, u
"folder-download"_qs
));
134 m_ui
->tabSelection
->item(TAB_SPEED
)->setIcon(UIThemeManager::instance()->getIcon(u
"speedometer"_qs
, u
"chronometer"_qs
));
135 m_ui
->tabSelection
->item(TAB_RSS
)->setIcon(UIThemeManager::instance()->getIcon(u
"application-rss"_qs
, u
"application-rss+xml"_qs
));
137 m_ui
->tabSelection
->item(TAB_WEBUI
)->setHidden(true);
139 m_ui
->tabSelection
->item(TAB_WEBUI
)->setIcon(UIThemeManager::instance()->getIcon(u
"preferences-webui"_qs
, u
"network-server"_qs
));
141 m_ui
->tabSelection
->item(TAB_ADVANCED
)->setIcon(UIThemeManager::instance()->getIcon(u
"preferences-advanced"_qs
, u
"preferences-other"_qs
));
143 // set uniform size for all icons
145 for (int i
= 0; i
< m_ui
->tabSelection
->count(); ++i
)
146 maxHeight
= std::max(maxHeight
, m_ui
->tabSelection
->visualItemRect(m_ui
->tabSelection
->item(i
)).size().height());
147 for (int i
= 0; i
< m_ui
->tabSelection
->count(); ++i
)
149 const QSize
size(std::numeric_limits
<int>::max(), static_cast<int>(maxHeight
* 1.2));
150 m_ui
->tabSelection
->item(i
)->setSizeHint(size
);
153 connect(m_ui
->tabSelection
, &QListWidget::currentItemChanged
, this, &ThisType::changePage
);
156 loadBehaviorTabOptions();
157 loadDownloadsTabOptions();
158 loadConnectionTabOptions();
159 loadSpeedTabOptions();
160 loadBittorrentTabOptions();
162 #ifndef DISABLE_WEBUI
163 loadWebUITabOptions();
166 // Load Advanced settings
167 m_advancedSettings
= new AdvancedSettings(app
, m_ui
->tabAdvancedPage
);
168 m_ui
->advPageLayout
->addWidget(m_advancedSettings
);
169 connect(m_advancedSettings
, &AdvancedSettings::settingsChanged
, this, &ThisType::enableApplyButton
);
171 // setup apply button
172 m_applyButton
->setEnabled(false);
173 connect(m_applyButton
, &QPushButton::clicked
, this, &OptionsDialog::applySettings
);
175 // disable mouse wheel event on widgets to avoid mis-selection
176 auto *wheelEventEater
= new WheelEventEater(this);
177 for (QComboBox
*widget
: asConst(findChildren
<QComboBox
*>()))
178 widget
->installEventFilter(wheelEventEater
);
179 for (QSpinBox
*widget
: asConst(findChildren
<QSpinBox
*>()))
180 widget
->installEventFilter(wheelEventEater
);
182 m_ui
->tabSelection
->setCurrentRow(m_storeLastViewedPage
);
184 if (const QSize dialogSize
= m_storeDialogSize
; dialogSize
.isValid())
188 OptionsDialog::~OptionsDialog()
190 // save dialog states
191 m_storeDialogSize
= size();
193 QStringList hSplitterSizes
;
194 for (const int size
: asConst(m_ui
->hsplitter
->sizes()))
195 hSplitterSizes
.append(QString::number(size
));
196 m_storeHSplitterSize
= hSplitterSizes
;
198 m_storeLastViewedPage
= m_ui
->tabSelection
->currentRow();
203 void OptionsDialog::loadBehaviorTabOptions()
205 const auto *pref
= Preferences::instance();
206 const auto *session
= BitTorrent::Session::instance();
208 initializeLanguageCombo();
209 setLocale(pref
->getLocale());
211 m_ui
->checkUseCustomTheme
->setChecked(Preferences::instance()->useCustomUITheme());
212 m_ui
->customThemeFilePath
->setSelectedPath(Preferences::instance()->customUIThemePath());
213 m_ui
->customThemeFilePath
->setMode(FileSystemPathEdit::Mode::FileOpen
);
214 m_ui
->customThemeFilePath
->setDialogCaption(tr("Select qBittorrent UI Theme file"));
215 m_ui
->customThemeFilePath
->setFileNameFilter(tr("qBittorrent UI Theme file (*.qbtheme config.json)"));
216 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
217 m_ui
->checkUseSystemIcon
->setChecked(pref
->useSystemIcons());
219 m_ui
->checkUseSystemIcon
->setVisible(false);
222 m_ui
->confirmDeletion
->setChecked(pref
->confirmTorrentDeletion());
223 m_ui
->checkAltRowColors
->setChecked(pref
->useAlternatingRowColors());
224 m_ui
->checkHideZero
->setChecked(pref
->getHideZeroValues());
225 m_ui
->comboHideZero
->setCurrentIndex(pref
->getHideZeroComboValues());
226 m_ui
->comboHideZero
->setEnabled(m_ui
->checkHideZero
->isChecked());
228 m_ui
->actionTorrentDlOnDblClBox
->setItemData(0, TOGGLE_PAUSE
);
229 m_ui
->actionTorrentDlOnDblClBox
->setItemData(1, OPEN_DEST
);
230 m_ui
->actionTorrentDlOnDblClBox
->setItemData(2, PREVIEW_FILE
);
231 m_ui
->actionTorrentDlOnDblClBox
->setItemData(3, SHOW_OPTIONS
);
232 m_ui
->actionTorrentDlOnDblClBox
->setItemData(4, NO_ACTION
);
233 int actionDownloading
= pref
->getActionOnDblClOnTorrentDl();
234 if ((actionDownloading
< 0) || (actionDownloading
>= m_ui
->actionTorrentDlOnDblClBox
->count()))
235 actionDownloading
= TOGGLE_PAUSE
;
236 m_ui
->actionTorrentDlOnDblClBox
->setCurrentIndex(m_ui
->actionTorrentDlOnDblClBox
->findData(actionDownloading
));
238 m_ui
->actionTorrentFnOnDblClBox
->setItemData(0, TOGGLE_PAUSE
);
239 m_ui
->actionTorrentFnOnDblClBox
->setItemData(1, OPEN_DEST
);
240 m_ui
->actionTorrentFnOnDblClBox
->setItemData(2, PREVIEW_FILE
);
241 m_ui
->actionTorrentFnOnDblClBox
->setItemData(3, SHOW_OPTIONS
);
242 m_ui
->actionTorrentFnOnDblClBox
->setItemData(4, NO_ACTION
);
243 int actionSeeding
= pref
->getActionOnDblClOnTorrentFn();
244 if ((actionSeeding
< 0) || (actionSeeding
>= m_ui
->actionTorrentFnOnDblClBox
->count()))
245 actionSeeding
= OPEN_DEST
;
246 m_ui
->actionTorrentFnOnDblClBox
->setCurrentIndex(m_ui
->actionTorrentFnOnDblClBox
->findData(actionSeeding
));
248 m_ui
->checkBoxHideZeroStatusFilters
->setChecked(pref
->getHideZeroStatusFilters());
251 m_ui
->checkStartup
->setVisible(false);
253 m_ui
->checkShowSplash
->setChecked(!pref
->isSplashScreenDisabled());
254 m_ui
->checkProgramExitConfirm
->setChecked(pref
->confirmOnExit());
255 m_ui
->checkProgramAutoExitConfirm
->setChecked(!pref
->dontConfirmAutoExit());
257 m_ui
->windowStateComboBox
->addItem(tr("Normal"), QVariant::fromValue(WindowState::Normal
));
258 m_ui
->windowStateComboBox
->addItem(tr("Minimized"), QVariant::fromValue(WindowState::Minimized
));
260 m_ui
->windowStateComboBox
->addItem(tr("Hidden"), QVariant::fromValue(WindowState::Hidden
));
262 m_ui
->windowStateComboBox
->setCurrentIndex(m_ui
->windowStateComboBox
->findData(QVariant::fromValue(app()->startUpWindowState())));
264 #if !(defined(Q_OS_WIN) || defined(Q_OS_MACOS))
265 m_ui
->groupFileAssociation
->setVisible(false);
266 m_ui
->checkProgramUpdates
->setVisible(false);
270 // Disable systray integration if it is not supported by the system
271 if (!QSystemTrayIcon::isSystemTrayAvailable())
273 m_ui
->checkShowSystray
->setChecked(false);
274 m_ui
->checkShowSystray
->setEnabled(false);
275 m_ui
->checkShowSystray
->setToolTip(tr("Disabled due to failed to detect system tray presence"));
277 m_ui
->checkShowSystray
->setChecked(pref
->systemTrayEnabled());
278 m_ui
->checkMinimizeToSysTray
->setChecked(pref
->minimizeToTray());
279 m_ui
->checkCloseToSystray
->setChecked(pref
->closeToTray());
280 m_ui
->comboTrayIcon
->setCurrentIndex(static_cast<int>(pref
->trayIconStyle()));
284 m_ui
->checkStartup
->setChecked(pref
->WinStartup());
285 m_ui
->checkAssociateTorrents
->setChecked(Preferences::isTorrentFileAssocSet());
286 m_ui
->checkAssociateMagnetLinks
->setChecked(Preferences::isMagnetLinkAssocSet());
290 m_ui
->checkShowSystray
->setVisible(false);
291 m_ui
->checkAssociateTorrents
->setChecked(Preferences::isTorrentFileAssocSet());
292 m_ui
->checkAssociateTorrents
->setEnabled(!m_ui
->checkAssociateTorrents
->isChecked());
293 m_ui
->checkAssociateMagnetLinks
->setChecked(Preferences::isMagnetLinkAssocSet());
294 m_ui
->checkAssociateMagnetLinks
->setEnabled(!m_ui
->checkAssociateMagnetLinks
->isChecked());
297 #if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
298 m_ui
->checkProgramUpdates
->setChecked(pref
->isUpdateCheckEnabled());
301 m_ui
->checkPreventFromSuspendWhenDownloading
->setChecked(pref
->preventFromSuspendWhenDownloading());
302 m_ui
->checkPreventFromSuspendWhenSeeding
->setChecked(pref
->preventFromSuspendWhenSeeding());
304 m_ui
->textFileLogPath
->setDialogCaption(tr("Choose a save directory"));
305 m_ui
->textFileLogPath
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
306 m_ui
->textFileLogPath
->setSelectedPath(app()->fileLoggerPath());
307 const bool fileLogBackup
= app()->isFileLoggerBackup();
308 m_ui
->checkFileLogBackup
->setChecked(fileLogBackup
);
309 m_ui
->spinFileLogSize
->setEnabled(fileLogBackup
);
310 const bool fileLogDelete
= app()->isFileLoggerDeleteOld();
311 m_ui
->checkFileLogDelete
->setChecked(fileLogDelete
);
312 m_ui
->spinFileLogAge
->setEnabled(fileLogDelete
);
313 m_ui
->comboFileLogAgeType
->setEnabled(fileLogDelete
);
314 m_ui
->spinFileLogSize
->setValue(app()->fileLoggerMaxSize() / 1024);
315 m_ui
->spinFileLogAge
->setValue(app()->fileLoggerAge());
316 m_ui
->comboFileLogAgeType
->setCurrentIndex(app()->fileLoggerAgeType());
317 // Groupbox's check state must be initialized after some of its children if they are manually enabled/disabled
318 m_ui
->checkFileLog
->setChecked(app()->isFileLoggerEnabled());
320 m_ui
->checkBoxPerformanceWarning
->setChecked(session
->isPerformanceWarningEnabled());
322 connect(m_ui
->comboI18n
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
324 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
325 connect(m_ui
->checkUseSystemIcon
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
327 connect(m_ui
->checkUseCustomTheme
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
328 connect(m_ui
->customThemeFilePath
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
330 m_ui
->buttonCustomizeUITheme
->setEnabled(!m_ui
->checkUseCustomTheme
->isChecked());
331 connect(m_ui
->checkUseCustomTheme
, &QGroupBox::toggled
, this, [this]
333 m_ui
->buttonCustomizeUITheme
->setEnabled(!m_ui
->checkUseCustomTheme
->isChecked());
335 connect(m_ui
->buttonCustomizeUITheme
, &QPushButton::clicked
, this, [this]
337 auto dialog
= new UIThemeDialog(this);
338 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
342 connect(m_ui
->confirmDeletion
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
343 connect(m_ui
->checkAltRowColors
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
344 connect(m_ui
->checkHideZero
, &QAbstractButton::toggled
, m_ui
->comboHideZero
, &QWidget::setEnabled
);
345 connect(m_ui
->checkHideZero
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
346 connect(m_ui
->comboHideZero
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
347 connect(m_ui
->actionTorrentDlOnDblClBox
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
348 connect(m_ui
->actionTorrentFnOnDblClBox
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
349 connect(m_ui
->checkBoxHideZeroStatusFilters
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
352 connect(m_ui
->checkStartup
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
354 connect(m_ui
->checkShowSplash
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
355 connect(m_ui
->checkProgramExitConfirm
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
356 connect(m_ui
->checkProgramAutoExitConfirm
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
357 connect(m_ui
->checkShowSystray
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
358 connect(m_ui
->checkMinimizeToSysTray
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
359 connect(m_ui
->checkCloseToSystray
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
360 connect(m_ui
->comboTrayIcon
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
361 connect(m_ui
->windowStateComboBox
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
363 connect(m_ui
->checkPreventFromSuspendWhenDownloading
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
364 connect(m_ui
->checkPreventFromSuspendWhenSeeding
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
366 #if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
367 connect(m_ui
->checkAssociateTorrents
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
368 connect(m_ui
->checkAssociateMagnetLinks
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
369 connect(m_ui
->checkProgramUpdates
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
372 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) && !defined(QT_DBUS_LIB)
373 m_ui
->checkPreventFromSuspendWhenDownloading
->setDisabled(true);
374 m_ui
->checkPreventFromSuspendWhenSeeding
->setDisabled(true);
377 connect(m_ui
->checkFileLog
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
378 connect(m_ui
->textFileLogPath
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
379 connect(m_ui
->checkFileLogBackup
, &QAbstractButton::toggled
, m_ui
->spinFileLogSize
, &QWidget::setEnabled
);
380 connect(m_ui
->checkFileLogBackup
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
381 connect(m_ui
->checkFileLogDelete
, &QAbstractButton::toggled
, m_ui
->comboFileLogAgeType
, &QWidget::setEnabled
);
382 connect(m_ui
->checkFileLogDelete
, &QAbstractButton::toggled
, m_ui
->spinFileLogAge
, &QWidget::setEnabled
);
383 connect(m_ui
->checkFileLogDelete
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
384 connect(m_ui
->spinFileLogSize
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
385 connect(m_ui
->spinFileLogAge
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
386 connect(m_ui
->comboFileLogAgeType
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
388 connect(m_ui
->checkBoxPerformanceWarning
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
391 void OptionsDialog::saveBehaviorTabOptions() const
393 auto *pref
= Preferences::instance();
394 auto *session
= BitTorrent::Session::instance();
396 // Load the translation
397 const QString locale
= getLocale();
398 if (pref
->getLocale() != locale
)
400 auto *translator
= new QTranslator
;
401 if (translator
->load(u
":/lang/qbittorrent_"_qs
+ locale
))
402 qDebug("%s locale recognized, using translation.", qUtf8Printable(locale
));
404 qDebug("%s locale unrecognized, using default (en).", qUtf8Printable(locale
));
405 qApp
->installTranslator(translator
);
407 pref
->setLocale(locale
);
409 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
410 pref
->useSystemIcons(m_ui
->checkUseSystemIcon
->isChecked());
412 pref
->setUseCustomUITheme(m_ui
->checkUseCustomTheme
->isChecked());
413 pref
->setCustomUIThemePath(m_ui
->customThemeFilePath
->selectedPath());
415 pref
->setConfirmTorrentDeletion(m_ui
->confirmDeletion
->isChecked());
416 pref
->setAlternatingRowColors(m_ui
->checkAltRowColors
->isChecked());
417 pref
->setHideZeroValues(m_ui
->checkHideZero
->isChecked());
418 pref
->setHideZeroComboValues(m_ui
->comboHideZero
->currentIndex());
420 pref
->setActionOnDblClOnTorrentDl(m_ui
->actionTorrentDlOnDblClBox
->currentData().toInt());
421 pref
->setActionOnDblClOnTorrentFn(m_ui
->actionTorrentFnOnDblClBox
->currentData().toInt());
423 pref
->setHideZeroStatusFilters(m_ui
->checkBoxHideZeroStatusFilters
->isChecked());
425 pref
->setSplashScreenDisabled(isSplashScreenDisabled());
426 pref
->setConfirmOnExit(m_ui
->checkProgramExitConfirm
->isChecked());
427 pref
->setDontConfirmAutoExit(!m_ui
->checkProgramAutoExitConfirm
->isChecked());
430 pref
->setWinStartup(WinStartup());
432 Preferences::setTorrentFileAssoc(m_ui
->checkAssociateTorrents
->isChecked());
433 Preferences::setMagnetLinkAssoc(m_ui
->checkAssociateMagnetLinks
->isChecked());
437 pref
->setSystemTrayEnabled(m_ui
->checkShowSystray
->isChecked());
438 pref
->setTrayIconStyle(TrayIcon::Style(m_ui
->comboTrayIcon
->currentIndex()));
439 pref
->setCloseToTray(m_ui
->checkCloseToSystray
->isChecked());
440 pref
->setMinimizeToTray(m_ui
->checkMinimizeToSysTray
->isChecked());
444 if (m_ui
->checkAssociateTorrents
->isChecked())
446 Preferences::setTorrentFileAssoc();
447 m_ui
->checkAssociateTorrents
->setChecked(Preferences::isTorrentFileAssocSet());
448 m_ui
->checkAssociateTorrents
->setEnabled(!m_ui
->checkAssociateTorrents
->isChecked());
450 if (m_ui
->checkAssociateMagnetLinks
->isChecked())
452 Preferences::setMagnetLinkAssoc();
453 m_ui
->checkAssociateMagnetLinks
->setChecked(Preferences::isMagnetLinkAssocSet());
454 m_ui
->checkAssociateMagnetLinks
->setEnabled(!m_ui
->checkAssociateMagnetLinks
->isChecked());
458 #if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
459 pref
->setUpdateCheckEnabled(m_ui
->checkProgramUpdates
->isChecked());
462 pref
->setPreventFromSuspendWhenDownloading(m_ui
->checkPreventFromSuspendWhenDownloading
->isChecked());
463 pref
->setPreventFromSuspendWhenSeeding(m_ui
->checkPreventFromSuspendWhenSeeding
->isChecked());
465 app()->setFileLoggerPath(m_ui
->textFileLogPath
->selectedPath());
466 app()->setFileLoggerBackup(m_ui
->checkFileLogBackup
->isChecked());
467 app()->setFileLoggerMaxSize(m_ui
->spinFileLogSize
->value() * 1024);
468 app()->setFileLoggerAge(m_ui
->spinFileLogAge
->value());
469 app()->setFileLoggerAgeType(m_ui
->comboFileLogAgeType
->currentIndex());
470 app()->setFileLoggerDeleteOld(m_ui
->checkFileLogDelete
->isChecked());
471 app()->setFileLoggerEnabled(m_ui
->checkFileLog
->isChecked());
473 app()->setStartUpWindowState(m_ui
->windowStateComboBox
->currentData().value
<WindowState
>());
475 session
->setPerformanceWarningEnabled(m_ui
->checkBoxPerformanceWarning
->isChecked());
478 void OptionsDialog::loadDownloadsTabOptions()
480 const auto *pref
= Preferences::instance();
481 const auto *session
= BitTorrent::Session::instance();
483 m_ui
->checkAdditionDialog
->setChecked(AddNewTorrentDialog::isEnabled());
484 m_ui
->checkAdditionDialogFront
->setChecked(AddNewTorrentDialog::isTopLevel());
486 m_ui
->contentLayoutComboBox
->setCurrentIndex(static_cast<int>(session
->torrentContentLayout()));
487 m_ui
->checkAddToQueueTop
->setChecked(session
->isAddTorrentToQueueTop());
488 m_ui
->checkStartPaused
->setChecked(session
->isAddTorrentPaused());
490 m_ui
->stopConditionComboBox
->setToolTip(
491 u
"<html><body><p><b>" + tr("None") + u
"</b> - " + tr("No stop condition is set.") + u
"</p><p><b>" +
492 tr("Metadata received") + u
"</b> - " + tr("Torrent will stop after metadata is received.") +
493 u
" <em>" + tr("Torrents that have metadata initially aren't affected.") + u
"</em></p><p><b>" +
494 tr("Files checked") + u
"</b> - " + tr("Torrent will stop after files are initially checked.") +
495 u
" <em>" + tr("This will also download metadata if it wasn't there initially.") + u
"</em></p></body></html>");
496 m_ui
->stopConditionComboBox
->setItemData(0, QVariant::fromValue(BitTorrent::Torrent::StopCondition::None
));
497 m_ui
->stopConditionComboBox
->setItemData(1, QVariant::fromValue(BitTorrent::Torrent::StopCondition::MetadataReceived
));
498 m_ui
->stopConditionComboBox
->setItemData(2, QVariant::fromValue(BitTorrent::Torrent::StopCondition::FilesChecked
));
499 m_ui
->stopConditionComboBox
->setCurrentIndex(m_ui
->stopConditionComboBox
->findData(QVariant::fromValue(session
->torrentStopCondition())));
500 m_ui
->stopConditionLabel
->setEnabled(!m_ui
->checkStartPaused
->isChecked());
501 m_ui
->stopConditionComboBox
->setEnabled(!m_ui
->checkStartPaused
->isChecked());
503 const TorrentFileGuard::AutoDeleteMode autoDeleteMode
= TorrentFileGuard::autoDeleteMode();
504 m_ui
->deleteTorrentBox
->setChecked(autoDeleteMode
!= TorrentFileGuard::Never
);
505 m_ui
->deleteCancelledTorrentBox
->setChecked(autoDeleteMode
== TorrentFileGuard::Always
);
506 m_ui
->deleteTorrentWarningIcon
->setPixmap(QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical
).pixmap(16, 16));
507 m_ui
->deleteTorrentWarningIcon
->hide();
508 m_ui
->deleteTorrentWarningLabel
->hide();
509 m_ui
->deleteTorrentWarningLabel
->setToolTip(u
"<html><body><p>" +
510 tr("By enabling these options, you can <strong>irrevocably lose</strong> your .torrent files!") +
512 tr("When these options are enabled, qBittorrent will <strong>delete</strong> .torrent files "
513 "after they were successfully (the first option) or not (the second option) added to its "
514 "download queue. This will be applied <strong>not only</strong> to the files opened via "
515 "“Add torrent” menu action but to those opened via <strong>file type association</strong> as well") +
517 tr("If you enable the second option (“Also when addition is cancelled”) the "
518 ".torrent file <strong>will be deleted</strong> even if you press “<strong>Cancel</strong>” in "
519 "the “Add torrent” dialog") +
520 u
"</p></body></html>");
522 m_ui
->checkPreallocateAll
->setChecked(session
->isPreallocationEnabled());
523 m_ui
->checkAppendqB
->setChecked(session
->isAppendExtensionEnabled());
524 m_ui
->checkRecursiveDownload
->setChecked(pref
->isRecursiveDownloadEnabled());
526 m_ui
->comboSavingMode
->setCurrentIndex(!session
->isAutoTMMDisabledByDefault());
527 m_ui
->comboTorrentCategoryChanged
->setCurrentIndex(session
->isDisableAutoTMMWhenCategoryChanged());
528 m_ui
->comboCategoryChanged
->setCurrentIndex(session
->isDisableAutoTMMWhenCategorySavePathChanged());
529 m_ui
->comboCategoryDefaultPathChanged
->setCurrentIndex(session
->isDisableAutoTMMWhenDefaultSavePathChanged());
531 m_ui
->checkUseSubcategories
->setChecked(session
->isSubcategoriesEnabled());
532 m_ui
->checkUseCategoryPaths
->setChecked(session
->useCategoryPathsInManualMode());
534 m_ui
->textSavePath
->setDialogCaption(tr("Choose a save directory"));
535 m_ui
->textSavePath
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
536 m_ui
->textSavePath
->setSelectedPath(session
->savePath());
538 m_ui
->checkUseDownloadPath
->setChecked(session
->isDownloadPathEnabled());
539 m_ui
->textDownloadPath
->setDialogCaption(tr("Choose a save directory"));
540 m_ui
->textDownloadPath
->setEnabled(m_ui
->checkUseDownloadPath
->isChecked());
541 m_ui
->textDownloadPath
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
542 m_ui
->textDownloadPath
->setSelectedPath(session
->downloadPath());
544 const bool isExportDirEmpty
= session
->torrentExportDirectory().isEmpty();
545 m_ui
->checkExportDir
->setChecked(!isExportDirEmpty
);
546 m_ui
->textExportDir
->setDialogCaption(tr("Choose export directory"));
547 m_ui
->textExportDir
->setEnabled(m_ui
->checkExportDir
->isChecked());
548 m_ui
->textExportDir
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
549 if (!isExportDirEmpty
)
550 m_ui
->textExportDir
->setSelectedPath(session
->torrentExportDirectory());
552 const bool isExportDirFinEmpty
= session
->finishedTorrentExportDirectory().isEmpty();
553 m_ui
->checkExportDirFin
->setChecked(!isExportDirFinEmpty
);
554 m_ui
->textExportDirFin
->setDialogCaption(tr("Choose export directory"));
555 m_ui
->textExportDirFin
->setEnabled(m_ui
->checkExportDirFin
->isChecked());
556 m_ui
->textExportDirFin
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
557 if (!isExportDirFinEmpty
)
558 m_ui
->textExportDirFin
->setSelectedPath(session
->finishedTorrentExportDirectory());
560 auto *watchedFoldersModel
= new WatchedFoldersModel(TorrentFilesWatcher::instance(), this);
561 connect(watchedFoldersModel
, &QAbstractListModel::dataChanged
, this, &ThisType::enableApplyButton
);
562 m_ui
->scanFoldersView
->header()->setSectionResizeMode(QHeaderView::ResizeToContents
);
563 m_ui
->scanFoldersView
->setModel(watchedFoldersModel
);
564 connect(m_ui
->scanFoldersView
->selectionModel(), &QItemSelectionModel::selectionChanged
, this, &ThisType::handleWatchedFolderViewSelectionChanged
);
565 connect(m_ui
->scanFoldersView
, &QTreeView::doubleClicked
, this, &ThisType::editWatchedFolderOptions
);
567 m_ui
->groupExcludedFileNames
->setChecked(session
->isExcludedFileNamesEnabled());
568 m_ui
->textExcludedFileNames
->setPlainText(session
->excludedFileNames().join(u
'\n'));
570 m_ui
->groupMailNotification
->setChecked(pref
->isMailNotificationEnabled());
571 m_ui
->senderEmailTxt
->setText(pref
->getMailNotificationSender());
572 m_ui
->lineEditDestEmail
->setText(pref
->getMailNotificationEmail());
573 m_ui
->lineEditSmtpServer
->setText(pref
->getMailNotificationSMTP());
574 m_ui
->checkSmtpSSL
->setChecked(pref
->getMailNotificationSMTPSSL());
575 m_ui
->groupMailNotifAuth
->setChecked(pref
->getMailNotificationSMTPAuth());
576 m_ui
->mailNotifUsername
->setText(pref
->getMailNotificationSMTPUsername());
577 m_ui
->mailNotifPassword
->setText(pref
->getMailNotificationSMTPPassword());
579 m_ui
->groupBoxRunOnAdded
->setChecked(pref
->isAutoRunOnTorrentAddedEnabled());
580 m_ui
->groupBoxRunOnFinished
->setChecked(pref
->isAutoRunOnTorrentFinishedEnabled());
581 m_ui
->lineEditRunOnAdded
->setText(pref
->getAutoRunOnTorrentAddedProgram());
582 m_ui
->lineEditRunOnFinished
->setText(pref
->getAutoRunOnTorrentFinishedProgram());
583 #if defined(Q_OS_WIN)
584 m_ui
->autoRunConsole
->setChecked(pref
->isAutoRunConsoleEnabled());
586 m_ui
->autoRunConsole
->hide();
588 const auto autoRunStr
= u
"%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n %11\n %12\n %13\n%14"_qs
589 .arg(tr("Supported parameters (case sensitive):")
590 , tr("%N: Torrent name")
592 , tr("%G: Tags (separated by comma)")
593 , tr("%F: Content path (same as root path for multifile torrent)")
594 , tr("%R: Root path (first torrent subdirectory path)")
595 , tr("%D: Save path")
596 , tr("%C: Number of files")
597 , tr("%Z: Torrent size (bytes)"))
598 .arg(tr("%T: Current tracker")
599 , tr("%I: Info hash v1 (or '-' if unavailable)")
600 , tr("%J: Info hash v2 (or '-' if unavailable)")
601 , tr("%K: Torrent ID (either sha-1 info hash for v1 torrent or truncated sha-256 info hash for v2/hybrid torrent)")
602 , tr("Tip: Encapsulate parameter with quotation marks to avoid text being cut off at whitespace (e.g., \"%N\")"));
603 m_ui
->labelAutoRunParam
->setText(autoRunStr
);
605 connect(m_ui
->checkAdditionDialog
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
606 connect(m_ui
->checkAdditionDialogFront
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
608 connect(m_ui
->contentLayoutComboBox
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
610 connect(m_ui
->checkAddToQueueTop
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
611 connect(m_ui
->checkStartPaused
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
612 connect(m_ui
->checkStartPaused
, &QAbstractButton::toggled
, this, [this](const bool checked
)
614 m_ui
->stopConditionLabel
->setEnabled(!checked
);
615 m_ui
->stopConditionComboBox
->setEnabled(!checked
);
617 connect(m_ui
->stopConditionComboBox
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
618 connect(m_ui
->deleteTorrentBox
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
619 connect(m_ui
->deleteCancelledTorrentBox
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
621 connect(m_ui
->checkPreallocateAll
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
622 connect(m_ui
->checkAppendqB
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
623 connect(m_ui
->checkRecursiveDownload
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
625 connect(m_ui
->comboSavingMode
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
626 connect(m_ui
->comboTorrentCategoryChanged
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
627 connect(m_ui
->comboCategoryChanged
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
628 connect(m_ui
->comboCategoryDefaultPathChanged
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
630 connect(m_ui
->checkUseSubcategories
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
631 connect(m_ui
->checkUseCategoryPaths
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
633 connect(m_ui
->textSavePath
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
634 connect(m_ui
->textDownloadPath
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
636 connect(m_ui
->checkExportDir
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
637 connect(m_ui
->checkExportDir
, &QAbstractButton::toggled
, m_ui
->textExportDir
, &QWidget::setEnabled
);
638 connect(m_ui
->checkExportDirFin
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
639 connect(m_ui
->checkExportDirFin
, &QAbstractButton::toggled
, m_ui
->textExportDirFin
, &QWidget::setEnabled
);
640 connect(m_ui
->textExportDir
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
641 connect(m_ui
->textExportDirFin
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
642 connect(m_ui
->checkUseDownloadPath
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
643 connect(m_ui
->checkUseDownloadPath
, &QAbstractButton::toggled
, m_ui
->textDownloadPath
, &QWidget::setEnabled
);
645 connect(m_ui
->addWatchedFolderButton
, &QAbstractButton::clicked
, this, &ThisType::enableApplyButton
);
647 connect(m_ui
->groupExcludedFileNames
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
648 connect(m_ui
->textExcludedFileNames
, &QPlainTextEdit::textChanged
, this, &ThisType::enableApplyButton
);
649 connect(m_ui
->removeWatchedFolderButton
, &QAbstractButton::clicked
, this, &ThisType::enableApplyButton
);
651 connect(m_ui
->groupMailNotification
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
652 connect(m_ui
->senderEmailTxt
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
653 connect(m_ui
->lineEditDestEmail
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
654 connect(m_ui
->lineEditSmtpServer
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
655 connect(m_ui
->checkSmtpSSL
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
656 connect(m_ui
->groupMailNotifAuth
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
657 connect(m_ui
->mailNotifUsername
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
658 connect(m_ui
->mailNotifPassword
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
660 connect(m_ui
->autoRunBox
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
661 connect(m_ui
->lineEditRunOnAdded
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
662 connect(m_ui
->lineEditRunOnFinished
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
663 connect(m_ui
->autoRunConsole
, &QCheckBox::toggled
, this, &ThisType::enableApplyButton
);
666 void OptionsDialog::saveDownloadsTabOptions() const
668 auto *pref
= Preferences::instance();
669 auto *session
= BitTorrent::Session::instance();
671 AddNewTorrentDialog::setEnabled(useAdditionDialog());
672 AddNewTorrentDialog::setTopLevel(m_ui
->checkAdditionDialogFront
->isChecked());
674 session
->setTorrentContentLayout(static_cast<BitTorrent::TorrentContentLayout
>(m_ui
->contentLayoutComboBox
->currentIndex()));
676 session
->setAddTorrentToQueueTop(m_ui
->checkAddToQueueTop
->isChecked());
677 session
->setAddTorrentPaused(addTorrentsInPause());
678 session
->setTorrentStopCondition(m_ui
->stopConditionComboBox
->currentData().value
<BitTorrent::Torrent::StopCondition
>());
679 TorrentFileGuard::setAutoDeleteMode(!m_ui
->deleteTorrentBox
->isChecked() ? TorrentFileGuard::Never
680 : !m_ui
->deleteCancelledTorrentBox
->isChecked() ? TorrentFileGuard::IfAdded
681 : TorrentFileGuard::Always
);
683 session
->setPreallocationEnabled(preAllocateAllFiles());
684 session
->setAppendExtensionEnabled(m_ui
->checkAppendqB
->isChecked());
685 pref
->setRecursiveDownloadEnabled(m_ui
->checkRecursiveDownload
->isChecked());
687 session
->setAutoTMMDisabledByDefault(m_ui
->comboSavingMode
->currentIndex() == 0);
688 session
->setDisableAutoTMMWhenCategoryChanged(m_ui
->comboTorrentCategoryChanged
->currentIndex() == 1);
689 session
->setDisableAutoTMMWhenCategorySavePathChanged(m_ui
->comboCategoryChanged
->currentIndex() == 1);
690 session
->setDisableAutoTMMWhenDefaultSavePathChanged(m_ui
->comboCategoryDefaultPathChanged
->currentIndex() == 1);
692 session
->setSubcategoriesEnabled(m_ui
->checkUseSubcategories
->isChecked());
693 session
->setUseCategoryPathsInManualMode(m_ui
->checkUseCategoryPaths
->isChecked());
695 session
->setSavePath(Path(m_ui
->textSavePath
->selectedPath()));
696 session
->setDownloadPathEnabled(m_ui
->checkUseDownloadPath
->isChecked());
697 session
->setDownloadPath(m_ui
->textDownloadPath
->selectedPath());
698 session
->setTorrentExportDirectory(getTorrentExportDir());
699 session
->setFinishedTorrentExportDirectory(getFinishedTorrentExportDir());
701 auto watchedFoldersModel
= static_cast<WatchedFoldersModel
*>(m_ui
->scanFoldersView
->model());
702 watchedFoldersModel
->apply();
704 session
->setExcludedFileNamesEnabled(m_ui
->groupExcludedFileNames
->isChecked());
705 session
->setExcludedFileNames(m_ui
->textExcludedFileNames
->toPlainText().split(u
'\n', Qt::SkipEmptyParts
));
707 pref
->setMailNotificationEnabled(m_ui
->groupMailNotification
->isChecked());
708 pref
->setMailNotificationSender(m_ui
->senderEmailTxt
->text());
709 pref
->setMailNotificationEmail(m_ui
->lineEditDestEmail
->text());
710 pref
->setMailNotificationSMTP(m_ui
->lineEditSmtpServer
->text());
711 pref
->setMailNotificationSMTPSSL(m_ui
->checkSmtpSSL
->isChecked());
712 pref
->setMailNotificationSMTPAuth(m_ui
->groupMailNotifAuth
->isChecked());
713 pref
->setMailNotificationSMTPUsername(m_ui
->mailNotifUsername
->text());
714 pref
->setMailNotificationSMTPPassword(m_ui
->mailNotifPassword
->text());
716 pref
->setAutoRunOnTorrentAddedEnabled(m_ui
->groupBoxRunOnAdded
->isChecked());
717 pref
->setAutoRunOnTorrentAddedProgram(m_ui
->lineEditRunOnAdded
->text().trimmed());
718 pref
->setAutoRunOnTorrentFinishedEnabled(m_ui
->groupBoxRunOnFinished
->isChecked());
719 pref
->setAutoRunOnTorrentFinishedProgram(m_ui
->lineEditRunOnFinished
->text().trimmed());
720 #if defined(Q_OS_WIN)
721 pref
->setAutoRunConsoleEnabled(m_ui
->autoRunConsole
->isChecked());
725 void OptionsDialog::loadConnectionTabOptions()
727 const auto *session
= BitTorrent::Session::instance();
729 m_ui
->comboProtocol
->setCurrentIndex(static_cast<int>(session
->btProtocol()));
730 m_ui
->spinPort
->setValue(session
->port());
731 m_ui
->checkUPnP
->setChecked(Net::PortForwarder::instance()->isEnabled());
733 int intValue
= session
->maxConnections();
737 m_ui
->checkMaxConnections
->setChecked(true);
738 m_ui
->spinMaxConnec
->setEnabled(true);
739 m_ui
->spinMaxConnec
->setValue(intValue
);
744 m_ui
->checkMaxConnections
->setChecked(false);
745 m_ui
->spinMaxConnec
->setEnabled(false);
747 intValue
= session
->maxConnectionsPerTorrent();
751 m_ui
->checkMaxConnectionsPerTorrent
->setChecked(true);
752 m_ui
->spinMaxConnecPerTorrent
->setEnabled(true);
753 m_ui
->spinMaxConnecPerTorrent
->setValue(intValue
);
758 m_ui
->checkMaxConnectionsPerTorrent
->setChecked(false);
759 m_ui
->spinMaxConnecPerTorrent
->setEnabled(false);
761 intValue
= session
->maxUploads();
765 m_ui
->checkMaxUploads
->setChecked(true);
766 m_ui
->spinMaxUploads
->setEnabled(true);
767 m_ui
->spinMaxUploads
->setValue(intValue
);
772 m_ui
->checkMaxUploads
->setChecked(false);
773 m_ui
->spinMaxUploads
->setEnabled(false);
775 intValue
= session
->maxUploadsPerTorrent();
779 m_ui
->checkMaxUploadsPerTorrent
->setChecked(true);
780 m_ui
->spinMaxUploadsPerTorrent
->setEnabled(true);
781 m_ui
->spinMaxUploadsPerTorrent
->setValue(intValue
);
786 m_ui
->checkMaxUploadsPerTorrent
->setChecked(false);
787 m_ui
->spinMaxUploadsPerTorrent
->setEnabled(false);
790 m_ui
->textI2PHost
->setText(session
->I2PAddress());
791 m_ui
->spinI2PPort
->setValue(session
->I2PPort());
792 m_ui
->checkI2PMixed
->setChecked(session
->I2PMixedMode());
793 m_ui
->groupI2P
->setChecked(session
->isI2PEnabled());
795 const auto *proxyConfigManager
= Net::ProxyConfigurationManager::instance();
796 const Net::ProxyConfiguration proxyConf
= proxyConfigManager
->proxyConfiguration();
798 m_ui
->comboProxyType
->addItem(tr("SOCKS4"), QVariant::fromValue(Net::ProxyType::SOCKS4
));
799 m_ui
->comboProxyType
->addItem(tr("SOCKS5"), QVariant::fromValue(Net::ProxyType::SOCKS5
));
800 m_ui
->comboProxyType
->addItem(tr("HTTP"), QVariant::fromValue(Net::ProxyType::HTTP
));
801 m_ui
->comboProxyType
->setCurrentIndex(m_ui
->comboProxyType
->findData(QVariant::fromValue(proxyConf
.type
)));
802 adjustProxyOptions();
804 m_ui
->textProxyIP
->setText(proxyConf
.ip
);
805 m_ui
->spinProxyPort
->setValue(proxyConf
.port
);
806 m_ui
->textProxyUsername
->setText(proxyConf
.username
);
807 m_ui
->textProxyPassword
->setText(proxyConf
.password
);
808 m_ui
->checkProxyAuth
->setChecked(proxyConf
.authEnabled
);
809 m_ui
->checkProxyHostnameLookup
->setChecked(proxyConf
.hostnameLookupEnabled
);
811 m_ui
->checkProxyPeerConnections
->setChecked(session
->isProxyPeerConnectionsEnabled());
812 m_ui
->checkProxyBitTorrent
->setChecked(Preferences::instance()->useProxyForBT());
813 m_ui
->checkProxyRSS
->setChecked(Preferences::instance()->useProxyForRSS());
814 m_ui
->checkProxyMisc
->setChecked(Preferences::instance()->useProxyForGeneralPurposes());
816 m_ui
->checkIPFilter
->setChecked(session
->isIPFilteringEnabled());
817 m_ui
->textFilterPath
->setDialogCaption(tr("Choose an IP filter file"));
818 m_ui
->textFilterPath
->setEnabled(m_ui
->checkIPFilter
->isChecked());
819 m_ui
->textFilterPath
->setFileNameFilter(tr("All supported filters") + u
" (*.dat *.p2p *.p2b);;.dat (*.dat);;.p2p (*.p2p);;.p2b (*.p2b)");
820 m_ui
->textFilterPath
->setSelectedPath(session
->IPFilterFile());
822 m_ui
->IpFilterRefreshBtn
->setIcon(UIThemeManager::instance()->getIcon(u
"view-refresh"_qs
));
823 m_ui
->IpFilterRefreshBtn
->setEnabled(m_ui
->checkIPFilter
->isChecked());
824 m_ui
->checkIpFilterTrackers
->setChecked(session
->isTrackerFilteringEnabled());
826 connect(m_ui
->comboProtocol
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
827 connect(m_ui
->spinPort
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
828 connect(m_ui
->checkUPnP
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
830 connect(m_ui
->checkMaxConnections
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
831 connect(m_ui
->checkMaxConnectionsPerTorrent
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
832 connect(m_ui
->checkMaxUploads
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
833 connect(m_ui
->checkMaxUploadsPerTorrent
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
834 connect(m_ui
->spinMaxConnec
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
835 connect(m_ui
->spinMaxConnecPerTorrent
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
836 connect(m_ui
->spinMaxUploads
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
837 connect(m_ui
->spinMaxUploadsPerTorrent
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
839 connect(m_ui
->comboProxyType
, qComboBoxCurrentIndexChanged
, this, &ThisType::adjustProxyOptions
);
840 connect(m_ui
->comboProxyType
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
841 connect(m_ui
->textProxyIP
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
842 connect(m_ui
->spinProxyPort
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
844 connect(m_ui
->textI2PHost
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
845 connect(m_ui
->spinI2PPort
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
846 connect(m_ui
->checkI2PMixed
, &QCheckBox::toggled
, this, &ThisType::enableApplyButton
);
847 connect(m_ui
->groupI2P
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
849 connect(m_ui
->checkProxyBitTorrent
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
850 connect(m_ui
->checkProxyBitTorrent
, &QGroupBox::toggled
, this, &ThisType::adjustProxyOptions
);
851 connect(m_ui
->checkProxyPeerConnections
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
852 connect(m_ui
->checkProxyHostnameLookup
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
853 connect(m_ui
->checkProxyRSS
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
854 connect(m_ui
->checkProxyMisc
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
856 connect(m_ui
->checkProxyAuth
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
857 connect(m_ui
->textProxyUsername
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
858 connect(m_ui
->textProxyPassword
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
860 connect(m_ui
->checkIPFilter
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
861 connect(m_ui
->checkIPFilter
, &QAbstractButton::toggled
, m_ui
->textFilterPath
, &QWidget::setEnabled
);
862 connect(m_ui
->checkIPFilter
, &QAbstractButton::toggled
, m_ui
->IpFilterRefreshBtn
, &QWidget::setEnabled
);
863 connect(m_ui
->textFilterPath
, &FileSystemPathEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
864 connect(m_ui
->checkIpFilterTrackers
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
867 void OptionsDialog::saveConnectionTabOptions() const
869 auto *session
= BitTorrent::Session::instance();
871 session
->setBTProtocol(static_cast<BitTorrent::BTProtocol
>(m_ui
->comboProtocol
->currentIndex()));
872 session
->setPort(getPort());
873 Net::PortForwarder::instance()->setEnabled(isUPnPEnabled());
875 session
->setMaxConnections(getMaxConnections());
876 session
->setMaxConnectionsPerTorrent(getMaxConnectionsPerTorrent());
877 session
->setMaxUploads(getMaxUploads());
878 session
->setMaxUploadsPerTorrent(getMaxUploadsPerTorrent());
880 session
->setI2PEnabled(m_ui
->groupI2P
->isChecked());
881 session
->setI2PAddress(m_ui
->textI2PHost
->text().trimmed());
882 session
->setI2PPort(m_ui
->spinI2PPort
->value());
883 session
->setI2PMixedMode(m_ui
->checkI2PMixed
->isChecked());
885 auto proxyConfigManager
= Net::ProxyConfigurationManager::instance();
886 Net::ProxyConfiguration proxyConf
;
887 proxyConf
.type
= getProxyType();
888 proxyConf
.ip
= getProxyIp();
889 proxyConf
.port
= getProxyPort();
890 proxyConf
.authEnabled
= m_ui
->checkProxyAuth
->isChecked();
891 proxyConf
.username
= getProxyUsername();
892 proxyConf
.password
= getProxyPassword();
893 proxyConf
.hostnameLookupEnabled
= m_ui
->checkProxyHostnameLookup
->isChecked();
894 proxyConfigManager
->setProxyConfiguration(proxyConf
);
896 Preferences::instance()->setUseProxyForBT(m_ui
->checkProxyBitTorrent
->isChecked());
897 Preferences::instance()->setUseProxyForRSS(m_ui
->checkProxyRSS
->isChecked());
898 Preferences::instance()->setUseProxyForGeneralPurposes(m_ui
->checkProxyMisc
->isChecked());
900 session
->setProxyPeerConnectionsEnabled(m_ui
->checkProxyPeerConnections
->isChecked());
903 session
->setIPFilteringEnabled(isIPFilteringEnabled());
904 session
->setTrackerFilteringEnabled(m_ui
->checkIpFilterTrackers
->isChecked());
905 session
->setIPFilterFile(m_ui
->textFilterPath
->selectedPath());
908 void OptionsDialog::loadSpeedTabOptions()
910 const auto *pref
= Preferences::instance();
911 const auto *session
= BitTorrent::Session::instance();
913 m_ui
->labelGlobalRate
->setPixmap(UIThemeManager::instance()->getScaledPixmap(u
"slow_off"_qs
, Utils::Gui::mediumIconSize(this).height()));
914 m_ui
->spinUploadLimit
->setValue(session
->globalUploadSpeedLimit() / 1024);
915 m_ui
->spinDownloadLimit
->setValue(session
->globalDownloadSpeedLimit() / 1024);
917 m_ui
->labelAltRate
->setPixmap(UIThemeManager::instance()->getScaledPixmap(u
"slow"_qs
, Utils::Gui::mediumIconSize(this).height()));
918 m_ui
->spinUploadLimitAlt
->setValue(session
->altGlobalUploadSpeedLimit() / 1024);
919 m_ui
->spinDownloadLimitAlt
->setValue(session
->altGlobalDownloadSpeedLimit() / 1024);
921 m_ui
->comboBoxScheduleDays
->addItems(translatedWeekdayNames());
923 m_ui
->groupBoxSchedule
->setChecked(session
->isBandwidthSchedulerEnabled());
924 m_ui
->timeEditScheduleFrom
->setTime(pref
->getSchedulerStartTime());
925 m_ui
->timeEditScheduleTo
->setTime(pref
->getSchedulerEndTime());
926 m_ui
->comboBoxScheduleDays
->setCurrentIndex(static_cast<int>(pref
->getSchedulerDays()));
928 m_ui
->checkLimituTPConnections
->setChecked(session
->isUTPRateLimited());
929 m_ui
->checkLimitTransportOverhead
->setChecked(session
->includeOverheadInLimits());
930 m_ui
->checkLimitLocalPeerRate
->setChecked(!session
->ignoreLimitsOnLAN());
932 connect(m_ui
->spinUploadLimit
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
933 connect(m_ui
->spinDownloadLimit
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
935 connect(m_ui
->spinUploadLimitAlt
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
936 connect(m_ui
->spinDownloadLimitAlt
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
938 connect(m_ui
->groupBoxSchedule
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
939 connect(m_ui
->timeEditScheduleFrom
, &QDateTimeEdit::timeChanged
, this, &ThisType::enableApplyButton
);
940 connect(m_ui
->timeEditScheduleTo
, &QDateTimeEdit::timeChanged
, this, &ThisType::enableApplyButton
);
941 connect(m_ui
->comboBoxScheduleDays
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
943 connect(m_ui
->checkLimituTPConnections
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
944 connect(m_ui
->checkLimitTransportOverhead
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
945 connect(m_ui
->checkLimitLocalPeerRate
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
948 void OptionsDialog::saveSpeedTabOptions() const
950 auto *pref
= Preferences::instance();
951 auto *session
= BitTorrent::Session::instance();
953 session
->setGlobalUploadSpeedLimit(m_ui
->spinUploadLimit
->value() * 1024);
954 session
->setGlobalDownloadSpeedLimit(m_ui
->spinDownloadLimit
->value() * 1024);
956 session
->setAltGlobalUploadSpeedLimit(m_ui
->spinUploadLimitAlt
->value() * 1024);
957 session
->setAltGlobalDownloadSpeedLimit(m_ui
->spinDownloadLimitAlt
->value() * 1024);
959 session
->setBandwidthSchedulerEnabled(m_ui
->groupBoxSchedule
->isChecked());
960 pref
->setSchedulerStartTime(m_ui
->timeEditScheduleFrom
->time());
961 pref
->setSchedulerEndTime(m_ui
->timeEditScheduleTo
->time());
962 pref
->setSchedulerDays(static_cast<Scheduler::Days
>(m_ui
->comboBoxScheduleDays
->currentIndex()));
964 session
->setUTPRateLimited(m_ui
->checkLimituTPConnections
->isChecked());
965 session
->setIncludeOverheadInLimits(m_ui
->checkLimitTransportOverhead
->isChecked());
966 session
->setIgnoreLimitsOnLAN(!m_ui
->checkLimitLocalPeerRate
->isChecked());
969 void OptionsDialog::loadBittorrentTabOptions()
971 const auto *session
= BitTorrent::Session::instance();
973 m_ui
->checkDHT
->setChecked(session
->isDHTEnabled());
974 m_ui
->checkPeX
->setChecked(session
->isPeXEnabled());
975 m_ui
->checkLSD
->setChecked(session
->isLSDEnabled());
976 m_ui
->comboEncryption
->setCurrentIndex(session
->encryption());
977 m_ui
->checkAnonymousMode
->setChecked(session
->isAnonymousModeEnabled());
979 m_ui
->spinBoxMaxActiveCheckingTorrents
->setValue(session
->maxActiveCheckingTorrents());
981 m_ui
->checkEnableQueueing
->setChecked(session
->isQueueingSystemEnabled());
982 m_ui
->spinMaxActiveDownloads
->setValue(session
->maxActiveDownloads());
983 m_ui
->spinMaxActiveUploads
->setValue(session
->maxActiveUploads());
984 m_ui
->spinMaxActiveTorrents
->setValue(session
->maxActiveTorrents());
986 m_ui
->checkIgnoreSlowTorrentsForQueueing
->setChecked(session
->ignoreSlowTorrentsForQueueing());
987 const QString slowTorrentsExplanation
= u
"<html><body><p>"
988 + tr("A torrent will be considered slow if its download and upload rates stay below these values for \"Torrent inactivity timer\" seconds")
989 + u
"</p></body></html>";
990 m_ui
->labelDownloadRateForSlowTorrents
->setToolTip(slowTorrentsExplanation
);
991 m_ui
->labelUploadRateForSlowTorrents
->setToolTip(slowTorrentsExplanation
);
992 m_ui
->labelSlowTorrentInactivityTimer
->setToolTip(slowTorrentsExplanation
);
993 m_ui
->spinDownloadRateForSlowTorrents
->setValue(session
->downloadRateForSlowTorrents());
994 m_ui
->spinUploadRateForSlowTorrents
->setValue(session
->uploadRateForSlowTorrents());
995 m_ui
->spinSlowTorrentsInactivityTimer
->setValue(session
->slowTorrentsInactivityTimer());
997 if (session
->globalMaxRatio() >= 0.)
1000 m_ui
->checkMaxRatio
->setChecked(true);
1001 m_ui
->spinMaxRatio
->setEnabled(true);
1002 m_ui
->comboRatioLimitAct
->setEnabled(true);
1003 m_ui
->spinMaxRatio
->setValue(session
->globalMaxRatio());
1008 m_ui
->checkMaxRatio
->setChecked(false);
1009 m_ui
->spinMaxRatio
->setEnabled(false);
1011 if (session
->globalMaxSeedingMinutes() >= 0)
1014 m_ui
->checkMaxSeedingMinutes
->setChecked(true);
1015 m_ui
->spinMaxSeedingMinutes
->setEnabled(true);
1016 m_ui
->spinMaxSeedingMinutes
->setValue(session
->globalMaxSeedingMinutes());
1021 m_ui
->checkMaxSeedingMinutes
->setChecked(false);
1022 m_ui
->spinMaxSeedingMinutes
->setEnabled(false);
1024 m_ui
->comboRatioLimitAct
->setEnabled((session
->globalMaxSeedingMinutes() >= 0) || (session
->globalMaxRatio() >= 0.));
1026 const QHash
<MaxRatioAction
, int> actIndex
=
1031 {EnableSuperSeeding
, 3}
1033 m_ui
->comboRatioLimitAct
->setCurrentIndex(actIndex
.value(session
->maxRatioAction()));
1035 m_ui
->checkEnableAddTrackers
->setChecked(session
->isAddTrackersEnabled());
1036 m_ui
->textTrackers
->setPlainText(session
->additionalTrackers());
1038 connect(m_ui
->checkDHT
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1039 connect(m_ui
->checkPeX
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1040 connect(m_ui
->checkLSD
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1041 connect(m_ui
->comboEncryption
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
1042 connect(m_ui
->checkAnonymousMode
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1044 connect(m_ui
->spinBoxMaxActiveCheckingTorrents
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1046 connect(m_ui
->checkEnableQueueing
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1047 connect(m_ui
->spinMaxActiveDownloads
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1048 connect(m_ui
->spinMaxActiveUploads
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1049 connect(m_ui
->spinMaxActiveTorrents
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1050 connect(m_ui
->checkIgnoreSlowTorrentsForQueueing
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1051 connect(m_ui
->spinDownloadRateForSlowTorrents
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1052 connect(m_ui
->spinUploadRateForSlowTorrents
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1053 connect(m_ui
->spinSlowTorrentsInactivityTimer
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1055 connect(m_ui
->checkMaxRatio
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1056 connect(m_ui
->checkMaxRatio
, &QAbstractButton::toggled
, this, &ThisType::toggleComboRatioLimitAct
);
1057 connect(m_ui
->spinMaxRatio
, qOverload
<double>(&QDoubleSpinBox::valueChanged
),this, &ThisType::enableApplyButton
);
1058 connect(m_ui
->comboRatioLimitAct
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
1059 connect(m_ui
->checkMaxSeedingMinutes
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1060 connect(m_ui
->checkMaxSeedingMinutes
, &QAbstractButton::toggled
, this, &ThisType::toggleComboRatioLimitAct
);
1061 connect(m_ui
->spinMaxSeedingMinutes
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1063 connect(m_ui
->checkEnableAddTrackers
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1064 connect(m_ui
->textTrackers
, &QPlainTextEdit::textChanged
, this, &ThisType::enableApplyButton
);
1067 void OptionsDialog::saveBittorrentTabOptions() const
1069 auto *session
= BitTorrent::Session::instance();
1071 session
->setDHTEnabled(isDHTEnabled());
1072 session
->setPeXEnabled(m_ui
->checkPeX
->isChecked());
1073 session
->setLSDEnabled(isLSDEnabled());
1074 session
->setEncryption(getEncryptionSetting());
1075 session
->setAnonymousModeEnabled(m_ui
->checkAnonymousMode
->isChecked());
1077 session
->setMaxActiveCheckingTorrents(m_ui
->spinBoxMaxActiveCheckingTorrents
->value());
1079 session
->setQueueingSystemEnabled(isQueueingSystemEnabled());
1080 session
->setMaxActiveDownloads(m_ui
->spinMaxActiveDownloads
->value());
1081 session
->setMaxActiveUploads(m_ui
->spinMaxActiveUploads
->value());
1082 session
->setMaxActiveTorrents(m_ui
->spinMaxActiveTorrents
->value());
1083 session
->setIgnoreSlowTorrentsForQueueing(m_ui
->checkIgnoreSlowTorrentsForQueueing
->isChecked());
1084 session
->setDownloadRateForSlowTorrents(m_ui
->spinDownloadRateForSlowTorrents
->value());
1085 session
->setUploadRateForSlowTorrents(m_ui
->spinUploadRateForSlowTorrents
->value());
1086 session
->setSlowTorrentsInactivityTimer(m_ui
->spinSlowTorrentsInactivityTimer
->value());
1088 session
->setGlobalMaxRatio(getMaxRatio());
1089 session
->setGlobalMaxSeedingMinutes(getMaxSeedingMinutes());
1090 const QVector
<MaxRatioAction
> actIndex
=
1097 session
->setMaxRatioAction(actIndex
.value(m_ui
->comboRatioLimitAct
->currentIndex()));
1099 session
->setAddTrackersEnabled(m_ui
->checkEnableAddTrackers
->isChecked());
1100 session
->setAdditionalTrackers(m_ui
->textTrackers
->toPlainText());
1103 void OptionsDialog::loadRSSTabOptions()
1105 const auto *rssSession
= RSS::Session::instance();
1106 const auto *autoDownloader
= RSS::AutoDownloader::instance();
1108 m_ui
->checkRSSEnable
->setChecked(rssSession
->isProcessingEnabled());
1109 m_ui
->spinRSSRefreshInterval
->setValue(rssSession
->refreshInterval());
1110 m_ui
->spinRSSMaxArticlesPerFeed
->setValue(rssSession
->maxArticlesPerFeed());
1111 m_ui
->checkRSSAutoDownloaderEnable
->setChecked(autoDownloader
->isProcessingEnabled());
1112 m_ui
->textSmartEpisodeFilters
->setPlainText(autoDownloader
->smartEpisodeFilters().join(u
'\n'));
1113 m_ui
->checkSmartFilterDownloadRepacks
->setChecked(autoDownloader
->downloadRepacks());
1115 connect(m_ui
->checkRSSEnable
, &QCheckBox::toggled
, this, &OptionsDialog::enableApplyButton
);
1116 connect(m_ui
->checkRSSAutoDownloaderEnable
, &QCheckBox::toggled
, this, &OptionsDialog::enableApplyButton
);
1117 connect(m_ui
->btnEditRules
, &QPushButton::clicked
, this, [this]()
1119 auto *downloader
= new AutomatedRssDownloader(this);
1120 downloader
->setAttribute(Qt::WA_DeleteOnClose
);
1123 connect(m_ui
->textSmartEpisodeFilters
, &QPlainTextEdit::textChanged
, this, &OptionsDialog::enableApplyButton
);
1124 connect(m_ui
->checkSmartFilterDownloadRepacks
, &QCheckBox::toggled
, this, &OptionsDialog::enableApplyButton
);
1125 connect(m_ui
->spinRSSRefreshInterval
, qSpinBoxValueChanged
, this, &OptionsDialog::enableApplyButton
);
1126 connect(m_ui
->spinRSSMaxArticlesPerFeed
, qSpinBoxValueChanged
, this, &OptionsDialog::enableApplyButton
);
1129 void OptionsDialog::saveRSSTabOptions() const
1131 auto *rssSession
= RSS::Session::instance();
1132 auto *autoDownloader
= RSS::AutoDownloader::instance();
1134 rssSession
->setProcessingEnabled(m_ui
->checkRSSEnable
->isChecked());
1135 rssSession
->setRefreshInterval(m_ui
->spinRSSRefreshInterval
->value());
1136 rssSession
->setMaxArticlesPerFeed(m_ui
->spinRSSMaxArticlesPerFeed
->value());
1137 autoDownloader
->setProcessingEnabled(m_ui
->checkRSSAutoDownloaderEnable
->isChecked());
1138 autoDownloader
->setSmartEpisodeFilters(m_ui
->textSmartEpisodeFilters
->toPlainText().split(u
'\n', Qt::SkipEmptyParts
));
1139 autoDownloader
->setDownloadRepacks(m_ui
->checkSmartFilterDownloadRepacks
->isChecked());
1142 #ifndef DISABLE_WEBUI
1143 void OptionsDialog::loadWebUITabOptions()
1145 const auto *pref
= Preferences::instance();
1147 m_ui
->textWebUIHttpsCert
->setMode(FileSystemPathEdit::Mode::FileOpen
);
1148 m_ui
->textWebUIHttpsCert
->setFileNameFilter(tr("Certificate") + u
" (*.cer *.crt *.pem)");
1149 m_ui
->textWebUIHttpsCert
->setDialogCaption(tr("Select certificate"));
1150 m_ui
->textWebUIHttpsKey
->setMode(FileSystemPathEdit::Mode::FileOpen
);
1151 m_ui
->textWebUIHttpsKey
->setFileNameFilter(tr("Private key") + u
" (*.key *.pem)");
1152 m_ui
->textWebUIHttpsKey
->setDialogCaption(tr("Select private key"));
1153 m_ui
->textWebUIRootFolder
->setMode(FileSystemPathEdit::Mode::DirectoryOpen
);
1154 m_ui
->textWebUIRootFolder
->setDialogCaption(tr("Choose Alternative UI files location"));
1156 m_ui
->checkWebUi
->setChecked(pref
->isWebUiEnabled());
1157 m_ui
->textWebUiAddress
->setText(pref
->getWebUiAddress());
1158 m_ui
->spinWebUiPort
->setValue(pref
->getWebUiPort());
1159 m_ui
->checkWebUIUPnP
->setChecked(pref
->useUPnPForWebUIPort());
1160 m_ui
->checkWebUiHttps
->setChecked(pref
->isWebUiHttpsEnabled());
1161 webUIHttpsCertChanged(pref
->getWebUIHttpsCertificatePath());
1162 webUIHttpsKeyChanged(pref
->getWebUIHttpsKeyPath());
1163 m_ui
->textWebUiUsername
->setText(pref
->getWebUiUsername());
1164 m_ui
->checkBypassLocalAuth
->setChecked(!pref
->isWebUiLocalAuthEnabled());
1165 m_ui
->checkBypassAuthSubnetWhitelist
->setChecked(pref
->isWebUiAuthSubnetWhitelistEnabled());
1166 m_ui
->IPSubnetWhitelistButton
->setEnabled(m_ui
->checkBypassAuthSubnetWhitelist
->isChecked());
1167 m_ui
->spinBanCounter
->setValue(pref
->getWebUIMaxAuthFailCount());
1168 m_ui
->spinBanDuration
->setValue(pref
->getWebUIBanDuration().count());
1169 m_ui
->spinSessionTimeout
->setValue(pref
->getWebUISessionTimeout());
1171 m_ui
->groupAltWebUI
->setChecked(pref
->isAltWebUiEnabled());
1172 m_ui
->textWebUIRootFolder
->setSelectedPath(pref
->getWebUiRootFolder());
1174 m_ui
->checkClickjacking
->setChecked(pref
->isWebUiClickjackingProtectionEnabled());
1175 m_ui
->checkCSRFProtection
->setChecked(pref
->isWebUiCSRFProtectionEnabled());
1176 m_ui
->checkSecureCookie
->setEnabled(pref
->isWebUiHttpsEnabled());
1177 m_ui
->checkSecureCookie
->setChecked(pref
->isWebUiSecureCookieEnabled());
1178 m_ui
->groupHostHeaderValidation
->setChecked(pref
->isWebUIHostHeaderValidationEnabled());
1179 m_ui
->textServerDomains
->setText(pref
->getServerDomains());
1180 // Custom HTTP headers
1181 m_ui
->groupWebUIAddCustomHTTPHeaders
->setChecked(pref
->isWebUICustomHTTPHeadersEnabled());
1182 m_ui
->textWebUICustomHTTPHeaders
->setPlainText(pref
->getWebUICustomHTTPHeaders());
1184 m_ui
->groupEnableReverseProxySupport
->setChecked(pref
->isWebUIReverseProxySupportEnabled());
1185 m_ui
->textTrustedReverseProxiesList
->setText(pref
->getWebUITrustedReverseProxiesList());
1187 m_ui
->checkDynDNS
->setChecked(pref
->isDynDNSEnabled());
1188 m_ui
->comboDNSService
->setCurrentIndex(static_cast<int>(pref
->getDynDNSService()));
1189 m_ui
->domainNameTxt
->setText(pref
->getDynDomainName());
1190 m_ui
->DNSUsernameTxt
->setText(pref
->getDynDNSUsername());
1191 m_ui
->DNSPasswordTxt
->setText(pref
->getDynDNSPassword());
1193 connect(m_ui
->checkWebUi
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1194 connect(m_ui
->textWebUiAddress
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1195 connect(m_ui
->spinWebUiPort
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1196 connect(m_ui
->checkWebUIUPnP
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1197 connect(m_ui
->checkWebUiHttps
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1198 connect(m_ui
->textWebUIHttpsCert
, &FileSystemPathLineEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
1199 connect(m_ui
->textWebUIHttpsCert
, &FileSystemPathLineEdit::selectedPathChanged
, this, &OptionsDialog::webUIHttpsCertChanged
);
1200 connect(m_ui
->textWebUIHttpsKey
, &FileSystemPathLineEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
1201 connect(m_ui
->textWebUIHttpsKey
, &FileSystemPathLineEdit::selectedPathChanged
, this, &OptionsDialog::webUIHttpsKeyChanged
);
1203 connect(m_ui
->textWebUiUsername
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1204 connect(m_ui
->textWebUiPassword
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1206 connect(m_ui
->checkBypassLocalAuth
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1207 connect(m_ui
->checkBypassAuthSubnetWhitelist
, &QAbstractButton::toggled
, this, &ThisType::enableApplyButton
);
1208 connect(m_ui
->checkBypassAuthSubnetWhitelist
, &QAbstractButton::toggled
, m_ui
->IPSubnetWhitelistButton
, &QPushButton::setEnabled
);
1209 connect(m_ui
->spinBanCounter
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1210 connect(m_ui
->spinBanDuration
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1211 connect(m_ui
->spinSessionTimeout
, qSpinBoxValueChanged
, this, &ThisType::enableApplyButton
);
1213 connect(m_ui
->groupAltWebUI
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1214 connect(m_ui
->textWebUIRootFolder
, &FileSystemPathLineEdit::selectedPathChanged
, this, &ThisType::enableApplyButton
);
1216 connect(m_ui
->checkClickjacking
, &QCheckBox::toggled
, this, &ThisType::enableApplyButton
);
1217 connect(m_ui
->checkCSRFProtection
, &QCheckBox::toggled
, this, &ThisType::enableApplyButton
);
1218 connect(m_ui
->checkWebUiHttps
, &QGroupBox::toggled
, m_ui
->checkSecureCookie
, &QWidget::setEnabled
);
1219 connect(m_ui
->checkSecureCookie
, &QCheckBox::toggled
, this, &ThisType::enableApplyButton
);
1220 connect(m_ui
->groupHostHeaderValidation
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1221 connect(m_ui
->textServerDomains
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1223 connect(m_ui
->groupWebUIAddCustomHTTPHeaders
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1224 connect(m_ui
->textWebUICustomHTTPHeaders
, &QPlainTextEdit::textChanged
, this, &OptionsDialog::enableApplyButton
);
1226 connect(m_ui
->groupEnableReverseProxySupport
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1227 connect(m_ui
->textTrustedReverseProxiesList
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1229 connect(m_ui
->checkDynDNS
, &QGroupBox::toggled
, this, &ThisType::enableApplyButton
);
1230 connect(m_ui
->comboDNSService
, qComboBoxCurrentIndexChanged
, this, &ThisType::enableApplyButton
);
1231 connect(m_ui
->domainNameTxt
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1232 connect(m_ui
->DNSUsernameTxt
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1233 connect(m_ui
->DNSPasswordTxt
, &QLineEdit::textChanged
, this, &ThisType::enableApplyButton
);
1236 void OptionsDialog::saveWebUITabOptions() const
1238 auto *pref
= Preferences::instance();
1240 pref
->setWebUiEnabled(isWebUiEnabled());
1241 pref
->setWebUiAddress(m_ui
->textWebUiAddress
->text());
1242 pref
->setWebUiPort(m_ui
->spinWebUiPort
->value());
1243 pref
->setUPnPForWebUIPort(m_ui
->checkWebUIUPnP
->isChecked());
1244 pref
->setWebUiHttpsEnabled(m_ui
->checkWebUiHttps
->isChecked());
1245 pref
->setWebUIHttpsCertificatePath(m_ui
->textWebUIHttpsCert
->selectedPath());
1246 pref
->setWebUIHttpsKeyPath(m_ui
->textWebUIHttpsKey
->selectedPath());
1247 pref
->setWebUIMaxAuthFailCount(m_ui
->spinBanCounter
->value());
1248 pref
->setWebUIBanDuration(std::chrono::seconds
{m_ui
->spinBanDuration
->value()});
1249 pref
->setWebUISessionTimeout(m_ui
->spinSessionTimeout
->value());
1251 pref
->setWebUiUsername(webUiUsername());
1252 if (!webUiPassword().isEmpty())
1253 pref
->setWebUIPassword(Utils::Password::PBKDF2::generate(webUiPassword()));
1254 pref
->setWebUiLocalAuthEnabled(!m_ui
->checkBypassLocalAuth
->isChecked());
1255 pref
->setWebUiAuthSubnetWhitelistEnabled(m_ui
->checkBypassAuthSubnetWhitelist
->isChecked());
1257 pref
->setAltWebUiEnabled(m_ui
->groupAltWebUI
->isChecked());
1258 pref
->setWebUiRootFolder(m_ui
->textWebUIRootFolder
->selectedPath());
1260 pref
->setWebUiClickjackingProtectionEnabled(m_ui
->checkClickjacking
->isChecked());
1261 pref
->setWebUiCSRFProtectionEnabled(m_ui
->checkCSRFProtection
->isChecked());
1262 pref
->setWebUiSecureCookieEnabled(m_ui
->checkSecureCookie
->isChecked());
1263 pref
->setWebUIHostHeaderValidationEnabled(m_ui
->groupHostHeaderValidation
->isChecked());
1264 pref
->setServerDomains(m_ui
->textServerDomains
->text());
1265 // Custom HTTP headers
1266 pref
->setWebUICustomHTTPHeadersEnabled(m_ui
->groupWebUIAddCustomHTTPHeaders
->isChecked());
1267 pref
->setWebUICustomHTTPHeaders(m_ui
->textWebUICustomHTTPHeaders
->toPlainText());
1269 pref
->setWebUIReverseProxySupportEnabled(m_ui
->groupEnableReverseProxySupport
->isChecked());
1270 pref
->setWebUITrustedReverseProxiesList(m_ui
->textTrustedReverseProxiesList
->text());
1272 pref
->setDynDNSEnabled(m_ui
->checkDynDNS
->isChecked());
1273 pref
->setDynDNSService(static_cast<DNS::Service
>(m_ui
->comboDNSService
->currentIndex()));
1274 pref
->setDynDomainName(m_ui
->domainNameTxt
->text());
1275 pref
->setDynDNSUsername(m_ui
->DNSUsernameTxt
->text());
1276 pref
->setDynDNSPassword(m_ui
->DNSPasswordTxt
->text());
1278 #endif // DISABLE_WEBUI
1280 void OptionsDialog::initializeLanguageCombo()
1282 // List language files
1283 const QDir
langDir(u
":/lang"_qs
);
1284 const QStringList langFiles
= langDir
.entryList(QStringList(u
"qbittorrent_*.qm"_qs
), QDir::Files
);
1285 for (const QString
&langFile
: langFiles
)
1287 const QString localeStr
= langFile
.section(u
"_"_qs
, 1, -1).section(u
"."_qs
, 0, 0); // remove "qbittorrent_" and ".qm"
1288 m_ui
->comboI18n
->addItem(/*QIcon(":/icons/flags/"+country+".svg"), */ Utils::Misc::languageToLocalizedString(localeStr
), localeStr
);
1289 qDebug() << "Supported locale:" << localeStr
;
1293 void OptionsDialog::changePage(QListWidgetItem
*current
, QListWidgetItem
*previous
)
1297 m_ui
->tabOption
->setCurrentIndex(m_ui
->tabSelection
->row(current
));
1300 void OptionsDialog::loadSplitterState()
1302 // width has been modified, use height as width reference instead
1303 const int width
= m_ui
->tabSelection
->item(TAB_UI
)->sizeHint().height() * 2;
1304 const QStringList defaultSizes
= {QString::number(width
), QString::number(m_ui
->hsplitter
->width() - width
)};
1306 QList
<int> splitterSizes
;
1307 for (const QString
&string
: asConst(m_storeHSplitterSize
.get(defaultSizes
)))
1308 splitterSizes
.append(string
.toInt());
1310 m_ui
->hsplitter
->setSizes(splitterSizes
);
1313 void OptionsDialog::showEvent(QShowEvent
*e
)
1315 QDialog::showEvent(e
);
1317 loadSplitterState();
1320 void OptionsDialog::saveOptions() const
1322 auto *pref
= Preferences::instance();
1324 saveBehaviorTabOptions();
1325 saveDownloadsTabOptions();
1326 saveConnectionTabOptions();
1327 saveSpeedTabOptions();
1328 saveBittorrentTabOptions();
1329 saveRSSTabOptions();
1330 #ifndef DISABLE_WEBUI
1331 saveWebUITabOptions();
1333 m_advancedSettings
->saveAdvancedSettings();
1335 // Assume that user changed multiple settings
1336 // so it's best to save immediately
1340 bool OptionsDialog::isIPFilteringEnabled() const
1342 return m_ui
->checkIPFilter
->isChecked();
1345 Net::ProxyType
OptionsDialog::getProxyType() const
1347 return m_ui
->comboProxyType
->currentData().value
<Net::ProxyType
>();
1350 int OptionsDialog::getPort() const
1352 return m_ui
->spinPort
->value();
1355 void OptionsDialog::on_randomButton_clicked()
1357 // Range [1024: 65535]
1358 m_ui
->spinPort
->setValue(Utils::Random::rand(1024, 65535));
1361 int OptionsDialog::getEncryptionSetting() const
1363 return m_ui
->comboEncryption
->currentIndex();
1366 int OptionsDialog::getMaxActiveDownloads() const
1368 return m_ui
->spinMaxActiveDownloads
->value();
1371 int OptionsDialog::getMaxActiveUploads() const
1373 return m_ui
->spinMaxActiveUploads
->value();
1376 int OptionsDialog::getMaxActiveTorrents() const
1378 return m_ui
->spinMaxActiveTorrents
->value();
1381 bool OptionsDialog::isQueueingSystemEnabled() const
1383 return m_ui
->checkEnableQueueing
->isChecked();
1386 bool OptionsDialog::isDHTEnabled() const
1388 return m_ui
->checkDHT
->isChecked();
1391 bool OptionsDialog::isLSDEnabled() const
1393 return m_ui
->checkLSD
->isChecked();
1396 bool OptionsDialog::isUPnPEnabled() const
1398 return m_ui
->checkUPnP
->isChecked();
1401 // Return Share ratio
1402 qreal
OptionsDialog::getMaxRatio() const
1404 if (m_ui
->checkMaxRatio
->isChecked())
1405 return m_ui
->spinMaxRatio
->value();
1409 // Return Seeding Minutes
1410 int OptionsDialog::getMaxSeedingMinutes() const
1412 if (m_ui
->checkMaxSeedingMinutes
->isChecked())
1413 return m_ui
->spinMaxSeedingMinutes
->value();
1417 // Return max connections number
1418 int OptionsDialog::getMaxConnections() const
1420 if (!m_ui
->checkMaxConnections
->isChecked())
1423 return m_ui
->spinMaxConnec
->value();
1426 int OptionsDialog::getMaxConnectionsPerTorrent() const
1428 if (!m_ui
->checkMaxConnectionsPerTorrent
->isChecked())
1431 return m_ui
->spinMaxConnecPerTorrent
->value();
1434 int OptionsDialog::getMaxUploads() const
1436 if (!m_ui
->checkMaxUploads
->isChecked())
1439 return m_ui
->spinMaxUploads
->value();
1442 int OptionsDialog::getMaxUploadsPerTorrent() const
1444 if (!m_ui
->checkMaxUploadsPerTorrent
->isChecked())
1447 return m_ui
->spinMaxUploadsPerTorrent
->value();
1450 void OptionsDialog::on_buttonBox_accepted()
1452 if (m_applyButton
->isEnabled())
1454 if (!schedTimesOk())
1456 m_ui
->tabSelection
->setCurrentRow(TAB_SPEED
);
1459 #ifndef DISABLE_WEBUI
1460 if (!webUIAuthenticationOk())
1462 m_ui
->tabSelection
->setCurrentRow(TAB_WEBUI
);
1465 if (!isAlternativeWebUIPathValid())
1467 m_ui
->tabSelection
->setCurrentRow(TAB_WEBUI
);
1472 m_applyButton
->setEnabled(false);
1479 void OptionsDialog::applySettings()
1481 if (!schedTimesOk())
1483 m_ui
->tabSelection
->setCurrentRow(TAB_SPEED
);
1486 #ifndef DISABLE_WEBUI
1487 if (!webUIAuthenticationOk())
1489 m_ui
->tabSelection
->setCurrentRow(TAB_WEBUI
);
1492 if (!isAlternativeWebUIPathValid())
1494 m_ui
->tabSelection
->setCurrentRow(TAB_WEBUI
);
1499 m_applyButton
->setEnabled(false);
1503 void OptionsDialog::on_buttonBox_rejected()
1508 bool OptionsDialog::useAdditionDialog() const
1510 return m_ui
->checkAdditionDialog
->isChecked();
1513 void OptionsDialog::enableApplyButton()
1515 m_applyButton
->setEnabled(true);
1518 void OptionsDialog::toggleComboRatioLimitAct()
1520 // Verify if the share action button must be enabled
1521 m_ui
->comboRatioLimitAct
->setEnabled(m_ui
->checkMaxRatio
->isChecked() || m_ui
->checkMaxSeedingMinutes
->isChecked());
1524 void OptionsDialog::adjustProxyOptions()
1526 const auto currentProxyType
= m_ui
->comboProxyType
->currentData().value
<Net::ProxyType
>();
1527 const bool isAuthSupported
= (currentProxyType
!= Net::ProxyType::SOCKS4
);
1529 m_ui
->checkProxyAuth
->setEnabled(isAuthSupported
);
1531 if (currentProxyType
== Net::ProxyType::SOCKS4
)
1533 m_ui
->labelProxyTypeIncompatible
->setVisible(true);
1535 m_ui
->checkProxyHostnameLookup
->setEnabled(false);
1536 m_ui
->checkProxyRSS
->setEnabled(false);
1537 m_ui
->checkProxyMisc
->setEnabled(false);
1542 m_ui
->labelProxyTypeIncompatible
->setVisible(false);
1544 m_ui
->checkProxyHostnameLookup
->setEnabled(true);
1545 m_ui
->checkProxyRSS
->setEnabled(true);
1546 m_ui
->checkProxyMisc
->setEnabled(true);
1550 bool OptionsDialog::isSplashScreenDisabled() const
1552 return !m_ui
->checkShowSplash
->isChecked();
1556 bool OptionsDialog::WinStartup() const
1558 return m_ui
->checkStartup
->isChecked();
1562 bool OptionsDialog::preAllocateAllFiles() const
1564 return m_ui
->checkPreallocateAll
->isChecked();
1567 bool OptionsDialog::addTorrentsInPause() const
1569 return m_ui
->checkStartPaused
->isChecked();
1573 bool OptionsDialog::isProxyEnabled() const
1575 return m_ui
->comboProxyType
->currentIndex();
1578 QString
OptionsDialog::getProxyIp() const
1580 return m_ui
->textProxyIP
->text().trimmed();
1583 unsigned short OptionsDialog::getProxyPort() const
1585 return m_ui
->spinProxyPort
->value();
1588 QString
OptionsDialog::getProxyUsername() const
1590 QString username
= m_ui
->textProxyUsername
->text().trimmed();
1594 QString
OptionsDialog::getProxyPassword() const
1596 QString password
= m_ui
->textProxyPassword
->text();
1597 password
= password
.trimmed();
1602 QString
OptionsDialog::getLocale() const
1604 return m_ui
->comboI18n
->itemData(m_ui
->comboI18n
->currentIndex(), Qt::UserRole
).toString();
1607 void OptionsDialog::setLocale(const QString
&localeStr
)
1610 if (localeStr
.startsWith(u
"eo", Qt::CaseInsensitive
))
1614 else if (localeStr
.startsWith(u
"ltg", Qt::CaseInsensitive
))
1620 QLocale
locale(localeStr
);
1621 if (locale
.language() == QLocale::Uzbek
)
1622 name
= u
"uz@Latn"_qs
;
1623 else if (locale
.language() == QLocale::Azerbaijani
)
1624 name
= u
"az@latin"_qs
;
1626 name
= locale
.name();
1628 // Attempt to find exact match
1629 int index
= m_ui
->comboI18n
->findData(name
, Qt::UserRole
);
1632 //Attempt to find a language match without a country
1633 int pos
= name
.indexOf(u
'_');
1636 QString lang
= name
.left(pos
);
1637 index
= m_ui
->comboI18n
->findData(lang
, Qt::UserRole
);
1642 // Unrecognized, use US English
1643 index
= m_ui
->comboI18n
->findData(u
"en"_qs
, Qt::UserRole
);
1644 Q_ASSERT(index
>= 0);
1646 m_ui
->comboI18n
->setCurrentIndex(index
);
1649 Path
OptionsDialog::getTorrentExportDir() const
1651 if (m_ui
->checkExportDir
->isChecked())
1652 return m_ui
->textExportDir
->selectedPath();
1656 Path
OptionsDialog::getFinishedTorrentExportDir() const
1658 if (m_ui
->checkExportDirFin
->isChecked())
1659 return m_ui
->textExportDirFin
->selectedPath();
1663 void OptionsDialog::on_addWatchedFolderButton_clicked()
1665 Preferences
*const pref
= Preferences::instance();
1666 const Path dir
{QFileDialog::getExistingDirectory(
1667 this, tr("Select folder to monitor"), pref
->getScanDirsLastPath().parentPath().toString())};
1671 auto dialog
= new WatchedFolderOptionsDialog({}, this);
1672 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
1673 connect(dialog
, &QDialog::accepted
, this, [this, dialog
, dir
, pref
]()
1677 auto watchedFoldersModel
= static_cast<WatchedFoldersModel
*>(m_ui
->scanFoldersView
->model());
1678 watchedFoldersModel
->addFolder(dir
, dialog
->watchedFolderOptions());
1680 pref
->setScanDirsLastPath(dir
);
1682 for (int i
= 0; i
< watchedFoldersModel
->columnCount(); ++i
)
1683 m_ui
->scanFoldersView
->resizeColumnToContents(i
);
1685 enableApplyButton();
1687 catch (const RuntimeError
&err
)
1689 QMessageBox::critical(this, tr("Adding entry failed"), err
.message());
1696 void OptionsDialog::on_editWatchedFolderButton_clicked()
1698 const QModelIndex selected
1699 = m_ui
->scanFoldersView
->selectionModel()->selectedIndexes().at(0);
1701 editWatchedFolderOptions(selected
);
1704 void OptionsDialog::on_removeWatchedFolderButton_clicked()
1706 const QModelIndexList selected
1707 = m_ui
->scanFoldersView
->selectionModel()->selectedIndexes();
1709 for (const QModelIndex
&index
: selected
)
1710 m_ui
->scanFoldersView
->model()->removeRow(index
.row());
1713 void OptionsDialog::handleWatchedFolderViewSelectionChanged()
1715 const QModelIndexList selectedIndexes
= m_ui
->scanFoldersView
->selectionModel()->selectedIndexes();
1716 m_ui
->removeWatchedFolderButton
->setEnabled(!selectedIndexes
.isEmpty());
1717 m_ui
->editWatchedFolderButton
->setEnabled(selectedIndexes
.count() == 1);
1720 void OptionsDialog::editWatchedFolderOptions(const QModelIndex
&index
)
1722 if (!index
.isValid())
1725 auto watchedFoldersModel
= static_cast<WatchedFoldersModel
*>(m_ui
->scanFoldersView
->model());
1726 auto dialog
= new WatchedFolderOptionsDialog(watchedFoldersModel
->folderOptions(index
.row()), this);
1727 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
1728 connect(dialog
, &QDialog::accepted
, this, [this, dialog
, index
, watchedFoldersModel
]()
1730 if (index
.isValid())
1732 // The index could be invalidated while the dialog was displayed,
1733 // for example, if you deleted the folder using the Web API.
1734 watchedFoldersModel
->setFolderOptions(index
.row(), dialog
->watchedFolderOptions());
1735 enableApplyButton();
1742 // Return Filter object to apply to BT session
1743 Path
OptionsDialog::getFilter() const
1745 return m_ui
->textFilterPath
->selectedPath();
1748 #ifndef DISABLE_WEBUI
1749 void OptionsDialog::webUIHttpsCertChanged(const Path
&path
)
1751 const auto isCertFileValid
= [&path
]() -> bool
1756 QFile file
{path
.data()};
1757 if (!file
.open(QIODevice::ReadOnly
))
1760 if (!Utils::Net::isSSLCertificatesValid(file
.read(Utils::Net::MAX_SSL_FILE_SIZE
)))
1766 m_ui
->textWebUIHttpsCert
->setSelectedPath(path
);
1767 m_ui
->lblSslCertStatus
->setPixmap(UIThemeManager::instance()->getScaledPixmap(
1768 (isCertFileValid() ? u
"security-high"_qs
: u
"security-low"_qs
), 24));
1771 void OptionsDialog::webUIHttpsKeyChanged(const Path
&path
)
1773 const auto isKeyFileValid
= [&path
]() -> bool
1778 QFile file
{path
.data()};
1779 if (!file
.open(QIODevice::ReadOnly
))
1782 if (!Utils::Net::isSSLKeyValid(file
.read(Utils::Net::MAX_SSL_FILE_SIZE
)))
1788 m_ui
->textWebUIHttpsKey
->setSelectedPath(path
);
1789 m_ui
->lblSslKeyStatus
->setPixmap(UIThemeManager::instance()->getScaledPixmap(
1790 (isKeyFileValid() ? u
"security-high"_qs
: u
"security-low"_qs
), 24));
1793 bool OptionsDialog::isWebUiEnabled() const
1795 return m_ui
->checkWebUi
->isChecked();
1798 QString
OptionsDialog::webUiUsername() const
1800 return m_ui
->textWebUiUsername
->text();
1803 QString
OptionsDialog::webUiPassword() const
1805 return m_ui
->textWebUiPassword
->text();
1808 bool OptionsDialog::webUIAuthenticationOk()
1810 if (webUiUsername().length() < 3)
1812 QMessageBox::warning(this, tr("Length Error"), tr("The Web UI username must be at least 3 characters long."));
1815 if (!webUiPassword().isEmpty() && (webUiPassword().length() < 6))
1817 QMessageBox::warning(this, tr("Length Error"), tr("The Web UI password must be at least 6 characters long."));
1823 bool OptionsDialog::isAlternativeWebUIPathValid()
1825 if (m_ui
->groupAltWebUI
->isChecked() && m_ui
->textWebUIRootFolder
->selectedPath().isEmpty())
1827 QMessageBox::warning(this, tr("Location Error"), tr("The alternative Web UI files location cannot be blank."));
1834 void OptionsDialog::showConnectionTab()
1836 m_ui
->tabSelection
->setCurrentRow(TAB_CONNECTION
);
1839 #ifndef DISABLE_WEBUI
1840 void OptionsDialog::on_registerDNSBtn_clicked()
1842 const auto service
= static_cast<DNS::Service
>(m_ui
->comboDNSService
->currentIndex());
1843 QDesktopServices::openUrl(Net::DNSUpdater::getRegistrationUrl(service
));
1847 void OptionsDialog::on_IpFilterRefreshBtn_clicked()
1849 if (m_refreshingIpFilter
) return;
1850 m_refreshingIpFilter
= true;
1851 // Updating program preferences
1852 BitTorrent::Session
*const session
= BitTorrent::Session::instance();
1853 session
->setIPFilteringEnabled(true);
1854 session
->setIPFilterFile({}); // forcing Session reload filter file
1855 session
->setIPFilterFile(getFilter());
1856 connect(session
, &BitTorrent::Session::IPFilterParsed
, this, &OptionsDialog::handleIPFilterParsed
);
1857 setCursor(QCursor(Qt::WaitCursor
));
1860 void OptionsDialog::handleIPFilterParsed(bool error
, int ruleCount
)
1862 setCursor(QCursor(Qt::ArrowCursor
));
1864 QMessageBox::warning(this, tr("Parsing error"), tr("Failed to parse the provided IP filter"));
1866 QMessageBox::information(this, tr("Successfully refreshed"), tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount
));
1867 m_refreshingIpFilter
= false;
1868 disconnect(BitTorrent::Session::instance(), &BitTorrent::Session::IPFilterParsed
, this, &OptionsDialog::handleIPFilterParsed
);
1871 bool OptionsDialog::schedTimesOk()
1873 if (m_ui
->timeEditScheduleFrom
->time() == m_ui
->timeEditScheduleTo
->time())
1875 QMessageBox::warning(this, tr("Time Error"), tr("The start time and the end time can't be the same."));
1881 void OptionsDialog::on_banListButton_clicked()
1883 auto dialog
= new BanListOptionsDialog(this);
1884 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
1885 connect(dialog
, &QDialog::accepted
, this, &OptionsDialog::enableApplyButton
);
1889 void OptionsDialog::on_IPSubnetWhitelistButton_clicked()
1891 auto dialog
= new IPSubnetWhitelistOptionsDialog(this);
1892 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
1893 connect(dialog
, &QDialog::accepted
, this, &OptionsDialog::enableApplyButton
);