Use tray icon from system theme only if option is set
[qBittorrent.git] / src / gui / advancedsettings.cpp
blobfb8618f6d412481e422473432ec0c4e1ac98ab11
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2016 qBittorrent project
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 "advancedsettings.h"
31 #include <limits>
33 #include <QHeaderView>
34 #include <QHostAddress>
35 #include <QLabel>
36 #include <QNetworkInterface>
38 #include "base/bittorrent/session.h"
39 #include "base/global.h"
40 #include "base/preferences.h"
41 #include "base/unicodestrings.h"
42 #include "gui/addnewtorrentdialog.h"
43 #include "gui/desktopintegration.h"
44 #include "gui/mainwindow.h"
45 #include "interfaces/iguiapplication.h"
47 namespace
49 QString makeLink(const QStringView url, const QStringView linkLabel)
51 return u"<a href=\"%1\">%2</a>"_qs.arg(url, linkLabel);
54 enum AdvSettingsCols
56 PROPERTY,
57 VALUE,
58 COL_COUNT
61 enum AdvSettingsRows
63 // qBittorrent section
64 QBITTORRENT_HEADER,
65 RESUME_DATA_STORAGE,
66 #ifdef QBT_USES_LIBTORRENT2
67 MEMORY_WORKING_SET_LIMIT,
68 #endif
69 #if defined(Q_OS_WIN)
70 OS_MEMORY_PRIORITY,
71 #endif
72 // network interface
73 NETWORK_IFACE,
74 //Optional network address
75 NETWORK_IFACE_ADDRESS,
76 // behavior
77 SAVE_RESUME_DATA_INTERVAL,
78 CONFIRM_RECHECK_TORRENT,
79 RECHECK_COMPLETED,
80 // UI related
81 LIST_REFRESH,
82 RESOLVE_HOSTS,
83 RESOLVE_COUNTRIES,
84 PROGRAM_NOTIFICATIONS,
85 TORRENT_ADDED_NOTIFICATIONS,
86 #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) && defined(QT_DBUS_LIB)
87 NOTIFICATION_TIMEOUT,
88 #endif
89 CONFIRM_REMOVE_ALL_TAGS,
90 REANNOUNCE_WHEN_ADDRESS_CHANGED,
91 DOWNLOAD_TRACKER_FAVICON,
92 SAVE_PATH_HISTORY_LENGTH,
93 ENABLE_SPEED_WIDGET,
94 #ifndef Q_OS_MACOS
95 ENABLE_ICONS_IN_MENUS,
96 #endif
97 // embedded tracker
98 TRACKER_STATUS,
99 TRACKER_PORT,
100 TRACKER_PORT_FORWARDING,
101 // libtorrent section
102 LIBTORRENT_HEADER,
103 ASYNC_IO_THREADS,
104 #ifdef QBT_USES_LIBTORRENT2
105 HASHING_THREADS,
106 #endif
107 FILE_POOL_SIZE,
108 CHECKING_MEM_USAGE,
109 #ifndef QBT_USES_LIBTORRENT2
110 // cache
111 DISK_CACHE,
112 DISK_CACHE_TTL,
113 #endif
114 DISK_QUEUE_SIZE,
115 #ifdef QBT_USES_LIBTORRENT2
116 DISK_IO_TYPE,
117 #endif
118 DISK_IO_READ_MODE,
119 DISK_IO_WRITE_MODE,
120 #ifndef QBT_USES_LIBTORRENT2
121 COALESCE_RW,
122 #endif
123 PIECE_EXTENT_AFFINITY,
124 SUGGEST_MODE,
125 SEND_BUF_WATERMARK,
126 SEND_BUF_LOW_WATERMARK,
127 SEND_BUF_WATERMARK_FACTOR,
128 // networking & ports
129 CONNECTION_SPEED,
130 SOCKET_BACKLOG_SIZE,
131 OUTGOING_PORT_MIN,
132 OUTGOING_PORT_MAX,
133 UPNP_LEASE_DURATION,
134 PEER_TOS,
135 UTP_MIX_MODE,
136 IDN_SUPPORT,
137 MULTI_CONNECTIONS_PER_IP,
138 VALIDATE_HTTPS_TRACKER_CERTIFICATE,
139 SSRF_MITIGATION,
140 BLOCK_PEERS_ON_PRIVILEGED_PORTS,
141 // seeding
142 CHOKING_ALGORITHM,
143 SEED_CHOKING_ALGORITHM,
144 // tracker
145 ANNOUNCE_ALL_TRACKERS,
146 ANNOUNCE_ALL_TIERS,
147 ANNOUNCE_IP,
148 MAX_CONCURRENT_HTTP_ANNOUNCES,
149 STOP_TRACKER_TIMEOUT,
150 PEER_TURNOVER,
151 PEER_TURNOVER_CUTOFF,
152 PEER_TURNOVER_INTERVAL,
153 REQUEST_QUEUE_SIZE,
155 ROW_COUNT
159 AdvancedSettings::AdvancedSettings(IGUIApplication *app, QWidget *parent)
160 : QTableWidget(parent)
161 , GUIApplicationComponent(app)
163 // column
164 setColumnCount(COL_COUNT);
165 const QStringList header = {tr("Setting"), tr("Value", "Value set for this setting")};
166 setHorizontalHeaderLabels(header);
167 // row
168 setRowCount(ROW_COUNT);
169 verticalHeader()->setVisible(false);
170 // etc.
171 setAlternatingRowColors(true);
172 setSelectionMode(QAbstractItemView::NoSelection);
173 setEditTriggers(QAbstractItemView::NoEditTriggers);
174 // Load settings
175 loadAdvancedSettings();
176 resizeColumnToContents(0);
177 horizontalHeader()->setStretchLastSection(true);
180 void AdvancedSettings::saveAdvancedSettings() const
182 Preferences *const pref = Preferences::instance();
183 BitTorrent::Session *const session = BitTorrent::Session::instance();
185 session->setResumeDataStorageType(m_comboBoxResumeDataStorage.currentData().value<BitTorrent::ResumeDataStorageType>());
186 #ifdef QBT_USES_LIBTORRENT2
187 // Physical memory (RAM) usage limit
188 app()->setMemoryWorkingSetLimit(m_spinBoxMemoryWorkingSetLimit.value());
189 #endif
190 #if defined(Q_OS_WIN)
191 app()->setProcessMemoryPriority(m_comboBoxOSMemoryPriority.currentData().value<MemoryPriority>());
192 #endif
193 // Async IO threads
194 session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value());
195 #ifdef QBT_USES_LIBTORRENT2
196 // Hashing threads
197 session->setHashingThreads(m_spinBoxHashingThreads.value());
198 #endif
199 // File pool size
200 session->setFilePoolSize(m_spinBoxFilePoolSize.value());
201 // Checking Memory Usage
202 session->setCheckingMemUsage(m_spinBoxCheckingMemUsage.value());
203 #ifndef QBT_USES_LIBTORRENT2
204 // Disk write cache
205 session->setDiskCacheSize(m_spinBoxCache.value());
206 session->setDiskCacheTTL(m_spinBoxCacheTTL.value());
207 #endif
208 // Disk queue size
209 session->setDiskQueueSize(m_spinBoxDiskQueueSize.value() * 1024);
210 #ifdef QBT_USES_LIBTORRENT2
211 session->setDiskIOType(m_comboBoxDiskIOType.currentData().value<BitTorrent::DiskIOType>());
212 #endif
213 // Disk IO read mode
214 session->setDiskIOReadMode(m_comboBoxDiskIOReadMode.currentData().value<BitTorrent::DiskIOReadMode>());
215 // Disk IO write mode
216 session->setDiskIOWriteMode(m_comboBoxDiskIOWriteMode.currentData().value<BitTorrent::DiskIOWriteMode>());
217 #ifndef QBT_USES_LIBTORRENT2
218 // Coalesce reads & writes
219 session->setCoalesceReadWriteEnabled(m_checkBoxCoalesceRW.isChecked());
220 #endif
221 // Piece extent affinity
222 session->setPieceExtentAffinity(m_checkBoxPieceExtentAffinity.isChecked());
223 // Suggest mode
224 session->setSuggestMode(m_checkBoxSuggestMode.isChecked());
225 // Send buffer watermark
226 session->setSendBufferWatermark(m_spinBoxSendBufferWatermark.value());
227 session->setSendBufferLowWatermark(m_spinBoxSendBufferLowWatermark.value());
228 session->setSendBufferWatermarkFactor(m_spinBoxSendBufferWatermarkFactor.value());
229 // Outgoing connections per second
230 session->setConnectionSpeed(m_spinBoxConnectionSpeed.value());
231 // Socket listen backlog size
232 session->setSocketBacklogSize(m_spinBoxSocketBacklogSize.value());
233 // Save resume data interval
234 session->setSaveResumeDataInterval(m_spinBoxSaveResumeDataInterval.value());
235 // Outgoing ports
236 session->setOutgoingPortsMin(m_spinBoxOutgoingPortsMin.value());
237 session->setOutgoingPortsMax(m_spinBoxOutgoingPortsMax.value());
238 // UPnP lease duration
239 session->setUPnPLeaseDuration(m_spinBoxUPnPLeaseDuration.value());
240 // Type of service
241 session->setPeerToS(m_spinBoxPeerToS.value());
242 // uTP-TCP mixed mode
243 session->setUtpMixedMode(m_comboBoxUtpMixedMode.currentData().value<BitTorrent::MixedModeAlgorithm>());
244 // Support internationalized domain name (IDN)
245 session->setIDNSupportEnabled(m_checkBoxIDNSupport.isChecked());
246 // multiple connections per IP
247 session->setMultiConnectionsPerIpEnabled(m_checkBoxMultiConnectionsPerIp.isChecked());
248 // Validate HTTPS tracker certificate
249 session->setValidateHTTPSTrackerCertificate(m_checkBoxValidateHTTPSTrackerCertificate.isChecked());
250 // SSRF mitigation
251 session->setSSRFMitigationEnabled(m_checkBoxSSRFMitigation.isChecked());
252 // Disallow connection to peers on privileged ports
253 session->setBlockPeersOnPrivilegedPorts(m_checkBoxBlockPeersOnPrivilegedPorts.isChecked());
254 // Recheck torrents on completion
255 pref->recheckTorrentsOnCompletion(m_checkBoxRecheckCompleted.isChecked());
256 // Transfer list refresh interval
257 session->setRefreshInterval(m_spinBoxListRefresh.value());
258 // Peer resolution
259 pref->resolvePeerCountries(m_checkBoxResolveCountries.isChecked());
260 pref->resolvePeerHostNames(m_checkBoxResolveHosts.isChecked());
261 // Network interface
262 session->setNetworkInterface(m_comboBoxInterface.currentData().toString());
263 session->setNetworkInterfaceName((m_comboBoxInterface.currentIndex() == 0)
264 ? QString()
265 : m_comboBoxInterface.currentText());
266 // Interface address
267 // Construct a QHostAddress to filter malformed strings
268 const QHostAddress ifaceAddr {m_comboBoxInterfaceAddress.currentData().toString()};
269 session->setNetworkInterfaceAddress(ifaceAddr.toString());
270 // Announce IP
271 // Construct a QHostAddress to filter malformed strings
272 const QHostAddress addr(m_lineEditAnnounceIP.text().trimmed());
273 session->setAnnounceIP(addr.toString());
274 // Max concurrent HTTP announces
275 session->setMaxConcurrentHTTPAnnounces(m_spinBoxMaxConcurrentHTTPAnnounces.value());
276 // Stop tracker timeout
277 session->setStopTrackerTimeout(m_spinBoxStopTrackerTimeout.value());
278 // Program notification
279 app()->desktopIntegration()->setNotificationsEnabled(m_checkBoxProgramNotifications.isChecked());
280 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
281 app()->desktopIntegration()->setNotificationTimeout(m_spinBoxNotificationTimeout.value());
282 #endif
283 app()->setTorrentAddedNotificationsEnabled(m_checkBoxTorrentAddedNotifications.isChecked());
284 // Reannounce to all trackers when ip/port changed
285 session->setReannounceWhenAddressChangedEnabled(m_checkBoxReannounceWhenAddressChanged.isChecked());
286 // Misc GUI properties
287 app()->mainWindow()->setDownloadTrackerFavicon(m_checkBoxTrackerFavicon.isChecked());
288 AddNewTorrentDialog::setSavePathHistoryLength(m_spinBoxSavePathHistoryLength.value());
289 pref->setSpeedWidgetEnabled(m_checkBoxSpeedWidgetEnabled.isChecked());
290 #ifndef Q_OS_MACOS
291 pref->setIconsInMenusEnabled(m_checkBoxIconsInMenusEnabled.isChecked());
292 #endif
294 // Tracker
295 pref->setTrackerPort(m_spinBoxTrackerPort.value());
296 pref->setTrackerPortForwardingEnabled(m_checkBoxTrackerPortForwarding.isChecked());
297 session->setTrackerEnabled(m_checkBoxTrackerStatus.isChecked());
299 // Choking algorithm
300 session->setChokingAlgorithm(m_comboBoxChokingAlgorithm.currentData().value<BitTorrent::ChokingAlgorithm>());
301 // Seed choking algorithm
302 session->setSeedChokingAlgorithm(m_comboBoxSeedChokingAlgorithm.currentData().value<BitTorrent::SeedChokingAlgorithm>());
304 pref->setConfirmTorrentRecheck(m_checkBoxConfirmTorrentRecheck.isChecked());
306 pref->setConfirmRemoveAllTags(m_checkBoxConfirmRemoveAllTags.isChecked());
308 session->setAnnounceToAllTrackers(m_checkBoxAnnounceAllTrackers.isChecked());
309 session->setAnnounceToAllTiers(m_checkBoxAnnounceAllTiers.isChecked());
311 session->setPeerTurnover(m_spinBoxPeerTurnover.value());
312 session->setPeerTurnoverCutoff(m_spinBoxPeerTurnoverCutoff.value());
313 session->setPeerTurnoverInterval(m_spinBoxPeerTurnoverInterval.value());
314 // Maximum outstanding requests to a single peer
315 session->setRequestQueueSize(m_spinBoxRequestQueueSize.value());
318 #ifndef QBT_USES_LIBTORRENT2
319 void AdvancedSettings::updateCacheSpinSuffix(const int value)
321 if (value == 0)
322 m_spinBoxCache.setSuffix(tr(" (disabled)"));
323 else if (value < 0)
324 m_spinBoxCache.setSuffix(tr(" (auto)"));
325 else
326 m_spinBoxCache.setSuffix(tr(" MiB"));
328 #endif
330 void AdvancedSettings::updateSaveResumeDataIntervalSuffix(const int value)
332 if (value > 0)
333 m_spinBoxSaveResumeDataInterval.setSuffix(tr(" min", " minutes"));
334 else
335 m_spinBoxSaveResumeDataInterval.setSuffix(tr(" (disabled)"));
338 void AdvancedSettings::updateInterfaceAddressCombo()
340 const auto toString = [](const QHostAddress &address) -> QString
342 switch (address.protocol()) {
343 case QAbstractSocket::IPv4Protocol:
344 return address.toString();
345 case QAbstractSocket::IPv6Protocol:
346 return Utils::Net::canonicalIPv6Addr(address).toString();
347 default:
348 Q_ASSERT(false);
349 break;
351 return {};
354 // Clear all items and reinsert them
355 m_comboBoxInterfaceAddress.clear();
356 m_comboBoxInterfaceAddress.addItem(tr("All addresses"), QString());
357 m_comboBoxInterfaceAddress.addItem(tr("All IPv4 addresses"), QHostAddress(QHostAddress::AnyIPv4).toString());
358 m_comboBoxInterfaceAddress.addItem(tr("All IPv6 addresses"), QHostAddress(QHostAddress::AnyIPv6).toString());
360 const QString currentIface = m_comboBoxInterface.currentData().toString();
361 if (currentIface.isEmpty()) // `any` interface
363 for (const QHostAddress &address : asConst(QNetworkInterface::allAddresses()))
365 const QString addressString = toString(address);
366 m_comboBoxInterfaceAddress.addItem(addressString, addressString);
369 else
371 const QList<QNetworkAddressEntry> addresses = QNetworkInterface::interfaceFromName(currentIface).addressEntries();
372 for (const QNetworkAddressEntry &entry : addresses)
374 const QString addressString = toString(entry.ip());
375 m_comboBoxInterfaceAddress.addItem(addressString, addressString);
379 const QString currentAddress = BitTorrent::Session::instance()->networkInterfaceAddress();
380 const int index = m_comboBoxInterfaceAddress.findData(currentAddress);
381 if (index > -1)
383 m_comboBoxInterfaceAddress.setCurrentIndex(index);
385 else
387 // not found, for the sake of UI consistency, add such entry
388 m_comboBoxInterfaceAddress.addItem(currentAddress, currentAddress);
389 m_comboBoxInterfaceAddress.setCurrentIndex(m_comboBoxInterfaceAddress.count() - 1);
393 void AdvancedSettings::loadAdvancedSettings()
395 const Preferences *const pref = Preferences::instance();
396 const BitTorrent::Session *const session = BitTorrent::Session::instance();
398 // add section headers
399 auto *labelQbtLink = new QLabel(
400 makeLink(u"https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced"
401 , tr("Open documentation"))
402 , this);
403 labelQbtLink->setOpenExternalLinks(true);
404 addRow(QBITTORRENT_HEADER, u"<b>%1</b>"_qs.arg(tr("qBittorrent Section")), labelQbtLink);
405 static_cast<QLabel *>(cellWidget(QBITTORRENT_HEADER, PROPERTY))->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
407 auto *labelLibtorrentLink = new QLabel(
408 makeLink(u"https://www.libtorrent.org/reference-Settings.html"
409 , tr("Open documentation"))
410 , this);
411 labelLibtorrentLink->setOpenExternalLinks(true);
412 addRow(LIBTORRENT_HEADER, u"<b>%1</b>"_qs.arg(tr("libtorrent Section")), labelLibtorrentLink);
413 static_cast<QLabel *>(cellWidget(LIBTORRENT_HEADER, PROPERTY))->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
415 m_comboBoxResumeDataStorage.addItem(tr("Fastresume files"), QVariant::fromValue(BitTorrent::ResumeDataStorageType::Legacy));
416 m_comboBoxResumeDataStorage.addItem(tr("SQLite database (experimental)"), QVariant::fromValue(BitTorrent::ResumeDataStorageType::SQLite));
417 m_comboBoxResumeDataStorage.setCurrentIndex(m_comboBoxResumeDataStorage.findData(QVariant::fromValue(session->resumeDataStorageType())));
418 addRow(RESUME_DATA_STORAGE, tr("Resume data storage type (requires restart)"), &m_comboBoxResumeDataStorage);
420 #ifdef QBT_USES_LIBTORRENT2
421 // Physical memory (RAM) usage limit
422 m_spinBoxMemoryWorkingSetLimit.setMinimum(1);
423 m_spinBoxMemoryWorkingSetLimit.setMaximum(std::numeric_limits<int>::max());
424 m_spinBoxMemoryWorkingSetLimit.setSuffix(tr(" MiB"));
425 m_spinBoxMemoryWorkingSetLimit.setToolTip(tr("This option is less effective on Linux"));
426 m_spinBoxMemoryWorkingSetLimit.setValue(app()->memoryWorkingSetLimit());
427 addRow(MEMORY_WORKING_SET_LIMIT, (tr("Physical memory (RAM) usage limit") + u' ' + makeLink(u"https://wikipedia.org/wiki/Working_set", u"(?)"))
428 , &m_spinBoxMemoryWorkingSetLimit);
429 #endif
430 #if defined(Q_OS_WIN)
431 m_comboBoxOSMemoryPriority.addItem(tr("Normal"), QVariant::fromValue(MemoryPriority::Normal));
432 m_comboBoxOSMemoryPriority.addItem(tr("Below normal"), QVariant::fromValue(MemoryPriority::BelowNormal));
433 m_comboBoxOSMemoryPriority.addItem(tr("Medium"), QVariant::fromValue(MemoryPriority::Medium));
434 m_comboBoxOSMemoryPriority.addItem(tr("Low"), QVariant::fromValue(MemoryPriority::Low));
435 m_comboBoxOSMemoryPriority.addItem(tr("Very low"), QVariant::fromValue(MemoryPriority::VeryLow));
436 m_comboBoxOSMemoryPriority.setCurrentIndex(m_comboBoxOSMemoryPriority.findData(QVariant::fromValue(app()->processMemoryPriority())));
437 addRow(OS_MEMORY_PRIORITY, (tr("Process memory priority (Windows >= 8 only)")
438 + u' ' + makeLink(u"https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-memory_priority_information", u"(?)"))
439 , &m_comboBoxOSMemoryPriority);
440 #endif
441 // Async IO threads
442 m_spinBoxAsyncIOThreads.setMinimum(1);
443 m_spinBoxAsyncIOThreads.setMaximum(1024);
444 m_spinBoxAsyncIOThreads.setValue(session->asyncIOThreads());
445 addRow(ASYNC_IO_THREADS, (tr("Asynchronous I/O threads") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#aio_threads", u"(?)"))
446 , &m_spinBoxAsyncIOThreads);
448 #ifdef QBT_USES_LIBTORRENT2
449 // Hashing threads
450 m_spinBoxHashingThreads.setMinimum(1);
451 m_spinBoxHashingThreads.setMaximum(1024);
452 m_spinBoxHashingThreads.setValue(session->hashingThreads());
453 addRow(HASHING_THREADS, (tr("Hashing threads") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#hashing_threads", u"(?)"))
454 , &m_spinBoxHashingThreads);
455 #endif
457 // File pool size
458 m_spinBoxFilePoolSize.setMinimum(1);
459 m_spinBoxFilePoolSize.setMaximum(std::numeric_limits<int>::max());
460 m_spinBoxFilePoolSize.setValue(session->filePoolSize());
461 addRow(FILE_POOL_SIZE, (tr("File pool size") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#file_pool_size", u"(?)"))
462 , &m_spinBoxFilePoolSize);
464 // Checking Memory Usage
465 m_spinBoxCheckingMemUsage.setMinimum(1);
466 // When build as 32bit binary, set the maximum value lower to prevent crashes.
467 #ifdef QBT_APP_64BIT
468 m_spinBoxCheckingMemUsage.setMaximum(1024);
469 #else
470 // Allocate at most 128MiB out of the remaining 512MiB (see the cache part below)
471 m_spinBoxCheckingMemUsage.setMaximum(128);
472 #endif
473 m_spinBoxCheckingMemUsage.setValue(session->checkingMemUsage());
474 m_spinBoxCheckingMemUsage.setSuffix(tr(" MiB"));
475 addRow(CHECKING_MEM_USAGE, (tr("Outstanding memory when checking torrents") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#checking_mem_usage", u"(?)"))
476 , &m_spinBoxCheckingMemUsage);
477 #ifndef QBT_USES_LIBTORRENT2
478 // Disk write cache
479 m_spinBoxCache.setMinimum(-1);
480 // When build as 32bit binary, set the maximum at less than 2GB to prevent crashes.
481 #ifdef QBT_APP_64BIT
482 m_spinBoxCache.setMaximum(33554431); // 32768GiB
483 #else
484 // allocate 1536MiB and leave 512MiB to the rest of program data in RAM
485 m_spinBoxCache.setMaximum(1536);
486 #endif
487 m_spinBoxCache.setValue(session->diskCacheSize());
488 updateCacheSpinSuffix(m_spinBoxCache.value());
489 connect(&m_spinBoxCache, qOverload<int>(&QSpinBox::valueChanged)
490 , this, &AdvancedSettings::updateCacheSpinSuffix);
491 addRow(DISK_CACHE, (tr("Disk cache") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#cache_size", u"(?)"))
492 , &m_spinBoxCache);
493 // Disk cache expiry
494 m_spinBoxCacheTTL.setMinimum(1);
495 m_spinBoxCacheTTL.setMaximum(std::numeric_limits<int>::max());
496 m_spinBoxCacheTTL.setValue(session->diskCacheTTL());
497 m_spinBoxCacheTTL.setSuffix(tr(" s", " seconds"));
498 addRow(DISK_CACHE_TTL, (tr("Disk cache expiry interval") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#cache_expiry", u"(?)"))
499 , &m_spinBoxCacheTTL);
500 #endif
501 // Disk queue size
502 m_spinBoxDiskQueueSize.setMinimum(1);
503 m_spinBoxDiskQueueSize.setMaximum(std::numeric_limits<int>::max());
504 m_spinBoxDiskQueueSize.setValue(session->diskQueueSize() / 1024);
505 m_spinBoxDiskQueueSize.setSuffix(tr(" KiB"));
506 addRow(DISK_QUEUE_SIZE, (tr("Disk queue size") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#max_queued_disk_bytes", u"(?)"))
507 , &m_spinBoxDiskQueueSize);
508 #ifdef QBT_USES_LIBTORRENT2
509 // Disk IO type
510 m_comboBoxDiskIOType.addItem(tr("Default"), QVariant::fromValue(BitTorrent::DiskIOType::Default));
511 m_comboBoxDiskIOType.addItem(tr("Memory mapped files"), QVariant::fromValue(BitTorrent::DiskIOType::MMap));
512 m_comboBoxDiskIOType.addItem(tr("POSIX-compliant"), QVariant::fromValue(BitTorrent::DiskIOType::Posix));
513 m_comboBoxDiskIOType.setCurrentIndex(m_comboBoxDiskIOType.findData(QVariant::fromValue(session->diskIOType())));
514 addRow(DISK_IO_TYPE, tr("Disk IO type (requires restart)") + u' ' + makeLink(u"https://www.libtorrent.org/single-page-ref.html#default-disk-io-constructor", u"(?)")
515 , &m_comboBoxDiskIOType);
516 #endif
517 // Disk IO read mode
518 m_comboBoxDiskIOReadMode.addItem(tr("Disable OS cache"), QVariant::fromValue(BitTorrent::DiskIOReadMode::DisableOSCache));
519 m_comboBoxDiskIOReadMode.addItem(tr("Enable OS cache"), QVariant::fromValue(BitTorrent::DiskIOReadMode::EnableOSCache));
520 m_comboBoxDiskIOReadMode.setCurrentIndex(m_comboBoxDiskIOReadMode.findData(QVariant::fromValue(session->diskIOReadMode())));
521 addRow(DISK_IO_READ_MODE, (tr("Disk IO read mode") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#disk_io_read_mode", u"(?)"))
522 , &m_comboBoxDiskIOReadMode);
523 // Disk IO write mode
524 m_comboBoxDiskIOWriteMode.addItem(tr("Disable OS cache"), QVariant::fromValue(BitTorrent::DiskIOWriteMode::DisableOSCache));
525 m_comboBoxDiskIOWriteMode.addItem(tr("Enable OS cache"), QVariant::fromValue(BitTorrent::DiskIOWriteMode::EnableOSCache));
526 #ifdef QBT_USES_LIBTORRENT2
527 m_comboBoxDiskIOWriteMode.addItem(tr("Write-through"), QVariant::fromValue(BitTorrent::DiskIOWriteMode::WriteThrough));
528 #endif
529 m_comboBoxDiskIOWriteMode.setCurrentIndex(m_comboBoxDiskIOWriteMode.findData(QVariant::fromValue(session->diskIOWriteMode())));
530 addRow(DISK_IO_WRITE_MODE, (tr("Disk IO write mode") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#disk_io_write_mode", u"(?)"))
531 , &m_comboBoxDiskIOWriteMode);
532 #ifndef QBT_USES_LIBTORRENT2
533 // Coalesce reads & writes
534 m_checkBoxCoalesceRW.setChecked(session->isCoalesceReadWriteEnabled());
535 addRow(COALESCE_RW, (tr("Coalesce reads & writes") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#coalesce_reads", u"(?)"))
536 , &m_checkBoxCoalesceRW);
537 #endif
538 // Piece extent affinity
539 m_checkBoxPieceExtentAffinity.setChecked(session->usePieceExtentAffinity());
540 addRow(PIECE_EXTENT_AFFINITY, (tr("Use piece extent affinity") + u' ' + makeLink(u"https://libtorrent.org/single-page-ref.html#piece_extent_affinity", u"(?)")), &m_checkBoxPieceExtentAffinity);
541 // Suggest mode
542 m_checkBoxSuggestMode.setChecked(session->isSuggestModeEnabled());
543 addRow(SUGGEST_MODE, (tr("Send upload piece suggestions") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#suggest_mode", u"(?)"))
544 , &m_checkBoxSuggestMode);
545 // Send buffer watermark
546 m_spinBoxSendBufferWatermark.setMinimum(1);
547 m_spinBoxSendBufferWatermark.setMaximum(std::numeric_limits<int>::max());
548 m_spinBoxSendBufferWatermark.setSuffix(tr(" KiB"));
549 m_spinBoxSendBufferWatermark.setValue(session->sendBufferWatermark());
550 addRow(SEND_BUF_WATERMARK, (tr("Send buffer watermark") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#send_buffer_watermark", u"(?)"))
551 , &m_spinBoxSendBufferWatermark);
552 m_spinBoxSendBufferLowWatermark.setMinimum(1);
553 m_spinBoxSendBufferLowWatermark.setMaximum(std::numeric_limits<int>::max());
554 m_spinBoxSendBufferLowWatermark.setSuffix(tr(" KiB"));
555 m_spinBoxSendBufferLowWatermark.setValue(session->sendBufferLowWatermark());
556 addRow(SEND_BUF_LOW_WATERMARK, (tr("Send buffer low watermark") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#send_buffer_low_watermark", u"(?)"))
557 , &m_spinBoxSendBufferLowWatermark);
558 m_spinBoxSendBufferWatermarkFactor.setMinimum(1);
559 m_spinBoxSendBufferWatermarkFactor.setMaximum(std::numeric_limits<int>::max());
560 m_spinBoxSendBufferWatermarkFactor.setSuffix(u" %"_qs);
561 m_spinBoxSendBufferWatermarkFactor.setValue(session->sendBufferWatermarkFactor());
562 addRow(SEND_BUF_WATERMARK_FACTOR, (tr("Send buffer watermark factor") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#send_buffer_watermark_factor", u"(?)"))
563 , &m_spinBoxSendBufferWatermarkFactor);
564 // Outgoing connections per second
565 m_spinBoxConnectionSpeed.setMinimum(0);
566 m_spinBoxConnectionSpeed.setMaximum(std::numeric_limits<int>::max());
567 m_spinBoxConnectionSpeed.setValue(session->connectionSpeed());
568 addRow(CONNECTION_SPEED, (tr("Outgoing connections per second") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#connection_speed", u"(?)"))
569 , &m_spinBoxConnectionSpeed);
570 // Socket listen backlog size
571 m_spinBoxSocketBacklogSize.setMinimum(1);
572 m_spinBoxSocketBacklogSize.setMaximum(std::numeric_limits<int>::max());
573 m_spinBoxSocketBacklogSize.setValue(session->socketBacklogSize());
574 addRow(SOCKET_BACKLOG_SIZE, (tr("Socket backlog size") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#listen_queue_size", u"(?)"))
575 , &m_spinBoxSocketBacklogSize);
576 // Save resume data interval
577 m_spinBoxSaveResumeDataInterval.setMinimum(0);
578 m_spinBoxSaveResumeDataInterval.setMaximum(std::numeric_limits<int>::max());
579 m_spinBoxSaveResumeDataInterval.setValue(session->saveResumeDataInterval());
580 connect(&m_spinBoxSaveResumeDataInterval, qOverload<int>(&QSpinBox::valueChanged)
581 , this, &AdvancedSettings::updateSaveResumeDataIntervalSuffix);
582 updateSaveResumeDataIntervalSuffix(m_spinBoxSaveResumeDataInterval.value());
583 addRow(SAVE_RESUME_DATA_INTERVAL, tr("Save resume data interval", "How often the fastresume file is saved."), &m_spinBoxSaveResumeDataInterval);
584 // Outgoing port Min
585 m_spinBoxOutgoingPortsMin.setMinimum(0);
586 m_spinBoxOutgoingPortsMin.setMaximum(65535);
587 m_spinBoxOutgoingPortsMin.setValue(session->outgoingPortsMin());
588 addRow(OUTGOING_PORT_MIN, (tr("Outgoing ports (Min) [0: Disabled]")
589 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#outgoing_port", u"(?)"))
590 , &m_spinBoxOutgoingPortsMin);
591 // Outgoing port Min
592 m_spinBoxOutgoingPortsMax.setMinimum(0);
593 m_spinBoxOutgoingPortsMax.setMaximum(65535);
594 m_spinBoxOutgoingPortsMax.setValue(session->outgoingPortsMax());
595 addRow(OUTGOING_PORT_MAX, (tr("Outgoing ports (Max) [0: Disabled]")
596 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#outgoing_port", u"(?)"))
597 , &m_spinBoxOutgoingPortsMax);
598 // UPnP lease duration
599 m_spinBoxUPnPLeaseDuration.setMinimum(0);
600 m_spinBoxUPnPLeaseDuration.setMaximum(std::numeric_limits<int>::max());
601 m_spinBoxUPnPLeaseDuration.setValue(session->UPnPLeaseDuration());
602 m_spinBoxUPnPLeaseDuration.setSuffix(tr(" s", " seconds"));
603 addRow(UPNP_LEASE_DURATION, (tr("UPnP lease duration [0: Permanent lease]") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#upnp_lease_duration", u"(?)"))
604 , &m_spinBoxUPnPLeaseDuration);
605 // Type of service
606 m_spinBoxPeerToS.setMinimum(0);
607 m_spinBoxPeerToS.setMaximum(255);
608 m_spinBoxPeerToS.setValue(session->peerToS());
609 addRow(PEER_TOS, (tr("Type of service (ToS) for connections to peers") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#peer_tos", u"(?)"))
610 , &m_spinBoxPeerToS);
611 // uTP-TCP mixed mode
612 m_comboBoxUtpMixedMode.addItem(tr("Prefer TCP"), QVariant::fromValue(BitTorrent::MixedModeAlgorithm::TCP));
613 m_comboBoxUtpMixedMode.addItem(tr("Peer proportional (throttles TCP)"), QVariant::fromValue(BitTorrent::MixedModeAlgorithm::Proportional));
614 m_comboBoxUtpMixedMode.setCurrentIndex(m_comboBoxUtpMixedMode.findData(QVariant::fromValue(session->utpMixedMode())));
615 addRow(UTP_MIX_MODE, (tr("%1-TCP mixed mode algorithm", "uTP-TCP mixed mode algorithm").arg(C_UTP)
616 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#mixed_mode_algorithm", u"(?)"))
617 , &m_comboBoxUtpMixedMode);
618 // Support internationalized domain name (IDN)
619 m_checkBoxIDNSupport.setChecked(session->isIDNSupportEnabled());
620 addRow(IDN_SUPPORT, (tr("Support internationalized domain name (IDN)")
621 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#allow_idna", u"(?)"))
622 , &m_checkBoxIDNSupport);
623 // multiple connections per IP
624 m_checkBoxMultiConnectionsPerIp.setChecked(session->multiConnectionsPerIpEnabled());
625 addRow(MULTI_CONNECTIONS_PER_IP, (tr("Allow multiple connections from the same IP address")
626 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#allow_multiple_connections_per_ip", u"(?)"))
627 , &m_checkBoxMultiConnectionsPerIp);
628 // Validate HTTPS tracker certificate
629 m_checkBoxValidateHTTPSTrackerCertificate.setChecked(session->validateHTTPSTrackerCertificate());
630 addRow(VALIDATE_HTTPS_TRACKER_CERTIFICATE, (tr("Validate HTTPS tracker certificates")
631 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#validate_https_trackers", u"(?)"))
632 , &m_checkBoxValidateHTTPSTrackerCertificate);
633 // SSRF mitigation
634 m_checkBoxSSRFMitigation.setChecked(session->isSSRFMitigationEnabled());
635 addRow(SSRF_MITIGATION, (tr("Server-side request forgery (SSRF) mitigation")
636 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#ssrf_mitigation", u"(?)"))
637 , &m_checkBoxSSRFMitigation);
638 // Disallow connection to peers on privileged ports
639 m_checkBoxBlockPeersOnPrivilegedPorts.setChecked(session->blockPeersOnPrivilegedPorts());
640 addRow(BLOCK_PEERS_ON_PRIVILEGED_PORTS, (tr("Disallow connection to peers on privileged ports") + u' ' + makeLink(u"https://libtorrent.org/single-page-ref.html#no_connect_privileged_ports", u"(?)")), &m_checkBoxBlockPeersOnPrivilegedPorts);
641 // Recheck completed torrents
642 m_checkBoxRecheckCompleted.setChecked(pref->recheckTorrentsOnCompletion());
643 addRow(RECHECK_COMPLETED, tr("Recheck torrents on completion"), &m_checkBoxRecheckCompleted);
644 // Refresh interval
645 m_spinBoxListRefresh.setMinimum(30);
646 m_spinBoxListRefresh.setMaximum(99999);
647 m_spinBoxListRefresh.setValue(session->refreshInterval());
648 m_spinBoxListRefresh.setSuffix(tr(" ms", " milliseconds"));
649 m_spinBoxListRefresh.setToolTip(tr("It controls the internal state update interval which in turn will affect UI updates"));
650 addRow(LIST_REFRESH, tr("Refresh interval"), &m_spinBoxListRefresh);
651 // Resolve Peer countries
652 m_checkBoxResolveCountries.setChecked(pref->resolvePeerCountries());
653 addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries"), &m_checkBoxResolveCountries);
654 // Resolve peer hosts
655 m_checkBoxResolveHosts.setChecked(pref->resolvePeerHostNames());
656 addRow(RESOLVE_HOSTS, tr("Resolve peer host names"), &m_checkBoxResolveHosts);
657 // Network interface
658 m_comboBoxInterface.addItem(tr("Any interface", "i.e. Any network interface"), QString());
659 for (const QNetworkInterface &iface : asConst(QNetworkInterface::allInterfaces()))
660 m_comboBoxInterface.addItem(iface.humanReadableName(), iface.name());
662 const QString currentInterface = session->networkInterface();
663 const int ifaceIndex = m_comboBoxInterface.findData(currentInterface);
664 if (ifaceIndex > -1)
666 m_comboBoxInterface.setCurrentIndex(ifaceIndex);
668 else
670 // Saved interface does not exist, show it
671 m_comboBoxInterface.addItem(session->networkInterfaceName(), currentInterface);
672 m_comboBoxInterface.setCurrentIndex(m_comboBoxInterface.count() - 1);
675 connect(&m_comboBoxInterface, qOverload<int>(&QComboBox::currentIndexChanged)
676 , this, &AdvancedSettings::updateInterfaceAddressCombo);
677 addRow(NETWORK_IFACE, tr("Network interface"), &m_comboBoxInterface);
678 // Network interface address
679 updateInterfaceAddressCombo();
680 addRow(NETWORK_IFACE_ADDRESS, tr("Optional IP address to bind to"), &m_comboBoxInterfaceAddress);
681 // Announce IP
682 m_lineEditAnnounceIP.setText(session->announceIP());
683 addRow(ANNOUNCE_IP, (tr("IP address reported to trackers (requires restart)")
684 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#announce_ip", u"(?)"))
685 , &m_lineEditAnnounceIP);
686 // Max concurrent HTTP announces
687 m_spinBoxMaxConcurrentHTTPAnnounces.setMaximum(std::numeric_limits<int>::max());
688 m_spinBoxMaxConcurrentHTTPAnnounces.setValue(session->maxConcurrentHTTPAnnounces());
689 addRow(MAX_CONCURRENT_HTTP_ANNOUNCES, (tr("Max concurrent HTTP announces") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#max_concurrent_http_announces", u"(?)"))
690 , &m_spinBoxMaxConcurrentHTTPAnnounces);
691 // Stop tracker timeout
692 m_spinBoxStopTrackerTimeout.setValue(session->stopTrackerTimeout());
693 m_spinBoxStopTrackerTimeout.setSuffix(tr(" s", " seconds"));
694 addRow(STOP_TRACKER_TIMEOUT, (tr("Stop tracker timeout") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#stop_tracker_timeout", u"(?)"))
695 , &m_spinBoxStopTrackerTimeout);
697 // Program notifications
698 m_checkBoxProgramNotifications.setChecked(app()->desktopIntegration()->isNotificationsEnabled());
699 addRow(PROGRAM_NOTIFICATIONS, tr("Display notifications"), &m_checkBoxProgramNotifications);
700 // Torrent added notifications
701 m_checkBoxTorrentAddedNotifications.setChecked(app()->isTorrentAddedNotificationsEnabled());
702 addRow(TORRENT_ADDED_NOTIFICATIONS, tr("Display notifications for added torrents"), &m_checkBoxTorrentAddedNotifications);
703 #ifdef QBT_USES_CUSTOMDBUSNOTIFICATIONS
704 // Notification timeout
705 m_spinBoxNotificationTimeout.setMinimum(-1);
706 m_spinBoxNotificationTimeout.setMaximum(std::numeric_limits<int>::max());
707 m_spinBoxNotificationTimeout.setValue(app()->desktopIntegration()->notificationTimeout());
708 m_spinBoxNotificationTimeout.setSpecialValueText(tr("System default"));
709 m_spinBoxNotificationTimeout.setSuffix(tr(" ms", " milliseconds"));
710 addRow(NOTIFICATION_TIMEOUT, tr("Notification timeout [0: infinite]"), &m_spinBoxNotificationTimeout);
711 #endif
712 // Reannounce to all trackers when ip/port changed
713 m_checkBoxReannounceWhenAddressChanged.setChecked(session->isReannounceWhenAddressChangedEnabled());
714 addRow(REANNOUNCE_WHEN_ADDRESS_CHANGED, tr("Reannounce to all trackers when IP or port changed"), &m_checkBoxReannounceWhenAddressChanged);
715 // Download tracker's favicon
716 m_checkBoxTrackerFavicon.setChecked(app()->mainWindow()->isDownloadTrackerFavicon());
717 addRow(DOWNLOAD_TRACKER_FAVICON, tr("Download tracker's favicon"), &m_checkBoxTrackerFavicon);
718 // Save path history length
719 m_spinBoxSavePathHistoryLength.setRange(AddNewTorrentDialog::minPathHistoryLength, AddNewTorrentDialog::maxPathHistoryLength);
720 m_spinBoxSavePathHistoryLength.setValue(AddNewTorrentDialog::savePathHistoryLength());
721 addRow(SAVE_PATH_HISTORY_LENGTH, tr("Save path history length"), &m_spinBoxSavePathHistoryLength);
722 // Enable speed graphs
723 m_checkBoxSpeedWidgetEnabled.setChecked(pref->isSpeedWidgetEnabled());
724 addRow(ENABLE_SPEED_WIDGET, tr("Enable speed graphs"), &m_checkBoxSpeedWidgetEnabled);
725 #ifndef Q_OS_MACOS
726 // Enable icons in menus
727 m_checkBoxIconsInMenusEnabled.setChecked(pref->iconsInMenusEnabled());
728 addRow(ENABLE_ICONS_IN_MENUS, tr("Enable icons in menus"), &m_checkBoxIconsInMenusEnabled);
729 #endif
730 // Tracker State
731 m_checkBoxTrackerStatus.setChecked(session->isTrackerEnabled());
732 addRow(TRACKER_STATUS, tr("Enable embedded tracker"), &m_checkBoxTrackerStatus);
733 // Tracker port
734 m_spinBoxTrackerPort.setMinimum(1);
735 m_spinBoxTrackerPort.setMaximum(65535);
736 m_spinBoxTrackerPort.setValue(pref->getTrackerPort());
737 addRow(TRACKER_PORT, tr("Embedded tracker port"), &m_spinBoxTrackerPort);
738 // Tracker port forwarding
739 m_checkBoxTrackerPortForwarding.setChecked(pref->isTrackerPortForwardingEnabled());
740 addRow(TRACKER_PORT_FORWARDING, tr("Enable port forwarding for embedded tracker"), &m_checkBoxTrackerPortForwarding);
741 // Choking algorithm
742 m_comboBoxChokingAlgorithm.addItem(tr("Fixed slots"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::FixedSlots));
743 m_comboBoxChokingAlgorithm.addItem(tr("Upload rate based"), QVariant::fromValue(BitTorrent::ChokingAlgorithm::RateBased));
744 m_comboBoxChokingAlgorithm.setCurrentIndex(m_comboBoxChokingAlgorithm.findData(QVariant::fromValue(session->chokingAlgorithm())));
745 addRow(CHOKING_ALGORITHM, (tr("Upload slots behavior") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#choking_algorithm", u"(?)"))
746 , &m_comboBoxChokingAlgorithm);
747 // Seed choking algorithm
748 m_comboBoxSeedChokingAlgorithm.addItem(tr("Round-robin"), QVariant::fromValue(BitTorrent::SeedChokingAlgorithm::RoundRobin));
749 m_comboBoxSeedChokingAlgorithm.addItem(tr("Fastest upload"), QVariant::fromValue(BitTorrent::SeedChokingAlgorithm::FastestUpload));
750 m_comboBoxSeedChokingAlgorithm.addItem(tr("Anti-leech"), QVariant::fromValue(BitTorrent::SeedChokingAlgorithm::AntiLeech));
751 m_comboBoxSeedChokingAlgorithm.setCurrentIndex(m_comboBoxSeedChokingAlgorithm.findData(QVariant::fromValue(session->seedChokingAlgorithm())));
752 addRow(SEED_CHOKING_ALGORITHM, (tr("Upload choking algorithm") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#seed_choking_algorithm", u"(?)"))
753 , &m_comboBoxSeedChokingAlgorithm);
755 // Torrent recheck confirmation
756 m_checkBoxConfirmTorrentRecheck.setChecked(pref->confirmTorrentRecheck());
757 addRow(CONFIRM_RECHECK_TORRENT, tr("Confirm torrent recheck"), &m_checkBoxConfirmTorrentRecheck);
759 // Remove all tags confirmation
760 m_checkBoxConfirmRemoveAllTags.setChecked(pref->confirmRemoveAllTags());
761 addRow(CONFIRM_REMOVE_ALL_TAGS, tr("Confirm removal of all tags"), &m_checkBoxConfirmRemoveAllTags);
763 // Announce to all trackers in a tier
764 m_checkBoxAnnounceAllTrackers.setChecked(session->announceToAllTrackers());
765 addRow(ANNOUNCE_ALL_TRACKERS, (tr("Always announce to all trackers in a tier")
766 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#announce_to_all_trackers", u"(?)"))
767 , &m_checkBoxAnnounceAllTrackers);
769 // Announce to all tiers
770 m_checkBoxAnnounceAllTiers.setChecked(session->announceToAllTiers());
771 addRow(ANNOUNCE_ALL_TIERS, (tr("Always announce to all tiers")
772 + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#announce_to_all_tiers", u"(?)"))
773 , &m_checkBoxAnnounceAllTiers);
775 m_spinBoxPeerTurnover.setMinimum(0);
776 m_spinBoxPeerTurnover.setMaximum(100);
777 m_spinBoxPeerTurnover.setValue(session->peerTurnover());
778 m_spinBoxPeerTurnover.setSuffix(u" %"_qs);
779 addRow(PEER_TURNOVER, (tr("Peer turnover disconnect percentage") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#peer_turnover", u"(?)"))
780 , &m_spinBoxPeerTurnover);
781 m_spinBoxPeerTurnoverCutoff.setMinimum(0);
782 m_spinBoxPeerTurnoverCutoff.setMaximum(100);
783 m_spinBoxPeerTurnoverCutoff.setSuffix(u" %"_qs);
784 m_spinBoxPeerTurnoverCutoff.setValue(session->peerTurnoverCutoff());
785 addRow(PEER_TURNOVER_CUTOFF, (tr("Peer turnover threshold percentage") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#peer_turnover", u"(?)"))
786 , &m_spinBoxPeerTurnoverCutoff);
787 m_spinBoxPeerTurnoverInterval.setMinimum(30);
788 m_spinBoxPeerTurnoverInterval.setMaximum(3600);
789 m_spinBoxPeerTurnoverInterval.setSuffix(tr(" s", " seconds"));
790 m_spinBoxPeerTurnoverInterval.setValue(session->peerTurnoverInterval());
791 addRow(PEER_TURNOVER_INTERVAL, (tr("Peer turnover disconnect interval") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#peer_turnover", u"(?)"))
792 , &m_spinBoxPeerTurnoverInterval);
793 // Maximum outstanding requests to a single peer
794 m_spinBoxRequestQueueSize.setMinimum(1);
795 m_spinBoxRequestQueueSize.setMaximum(std::numeric_limits<int>::max());
796 m_spinBoxRequestQueueSize.setValue(session->requestQueueSize());
797 addRow(REQUEST_QUEUE_SIZE, (tr("Maximum outstanding requests to a single peer") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#max_out_request_queue", u"(?)"))
798 , &m_spinBoxRequestQueueSize);
801 template <typename T>
802 void AdvancedSettings::addRow(const int row, const QString &text, T *widget)
804 auto label = new QLabel(text);
805 label->setOpenExternalLinks(true);
807 setCellWidget(row, PROPERTY, label);
808 setCellWidget(row, VALUE, widget);
810 if constexpr (std::is_same_v<T, QCheckBox>)
811 connect(widget, &QCheckBox::stateChanged, this, &AdvancedSettings::settingsChanged);
812 else if constexpr (std::is_same_v<T, QSpinBox>)
813 connect(widget, qOverload<int>(&QSpinBox::valueChanged), this, &AdvancedSettings::settingsChanged);
814 else if constexpr (std::is_same_v<T, QComboBox>)
815 connect(widget, qOverload<int>(&QComboBox::currentIndexChanged), this, &AdvancedSettings::settingsChanged);
816 else if constexpr (std::is_same_v<T, QLineEdit>)
817 connect(widget, &QLineEdit::textChanged, this, &AdvancedSettings::settingsChanged);