2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2020 thalieht
4 * Copyright (C) 2011 Christian Kandeler
5 * Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * In addition, as a special exception, the copyright holders give permission to
22 * link this program with the OpenSSL project's "OpenSSL" library (or with
23 * modified versions of it that use the same license as the "OpenSSL" library),
24 * and distribute the linked executables. You must obey the GNU General Public
25 * License in all respects for all of the code used other than "OpenSSL". If you
26 * modify file(s), you may extend this exception to your version of the file(s),
27 * but you are not obligated to do so. If you do not wish to do so, delete this
28 * exception statement from your version.
31 #include "torrentoptionsdialog.h"
36 #include <QMessageBox>
39 #include "base/bittorrent/infohash.h"
40 #include "base/bittorrent/session.h"
41 #include "base/bittorrent/torrent.h"
42 #include "base/global.h"
43 #include "base/unicodestrings.h"
44 #include "base/utils/fs.h"
45 #include "ui_torrentoptionsdialog.h"
48 #define SETTINGS_KEY(name) u"TorrentOptionsDialog/" name
52 const int MIXED_SHARE_LIMITS
= -9;
54 void updateSliderValue(QSlider
*slider
, const int value
)
56 if (value
> slider
->maximum())
57 slider
->setMaximum(value
);
58 slider
->setValue(value
);
62 TorrentOptionsDialog::TorrentOptionsDialog(QWidget
*parent
, const QVector
<BitTorrent::Torrent
*> &torrents
)
64 , m_ui
{new Ui::TorrentOptionsDialog
}
65 , m_storeDialogSize
{SETTINGS_KEY(u
"Size"_s
)}
66 , m_currentCategoriesString
{u
"--%1--"_s
.arg(tr("Currently used categories"))}
68 Q_ASSERT(!torrents
.empty());
72 connect(m_ui
->buttonBox
, &QDialogButtonBox::accepted
, this, &QDialog::accept
);
73 connect(m_ui
->buttonBox
, &QDialogButtonBox::rejected
, this, &QDialog::reject
);
75 m_ui
->savePath
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
76 m_ui
->savePath
->setDialogCaption(tr("Choose save path"));
77 m_ui
->downloadPath
->setMode(FileSystemPathEdit::Mode::DirectorySave
);
78 m_ui
->downloadPath
->setDialogCaption(tr("Choose save path"));
80 const auto *session
= BitTorrent::Session::instance();
81 bool allSameUpLimit
= true;
82 bool allSameDownLimit
= true;
83 bool allSameRatio
= true;
84 bool allSameSeedingTime
= true;
85 bool allSameInactiveSeedingTime
= true;
86 bool allTorrentsArePrivate
= true;
87 bool allSameDHT
= true;
88 bool allSamePEX
= true;
89 bool allSameLSD
= true;
90 bool allSameSequential
= true;
91 bool allSameFirstLastPieces
= true;
92 bool allSameAutoTMM
= true;
93 bool allSameSavePath
= true;
94 bool allSameDownloadPath
= true;
96 const bool isFirstTorrentAutoTMMEnabled
= torrents
[0]->isAutoTMMEnabled();
97 const Path firstTorrentSavePath
= torrents
[0]->savePath();
98 const Path firstTorrentDownloadPath
= torrents
[0]->downloadPath();
99 const QString firstTorrentCategory
= torrents
[0]->category();
101 const int firstTorrentUpLimit
= std::max(0, torrents
[0]->uploadLimit());
102 const int firstTorrentDownLimit
= std::max(0, torrents
[0]->downloadLimit());
104 const qreal firstTorrentRatio
= torrents
[0]->ratioLimit();
105 const int firstTorrentSeedingTime
= torrents
[0]->seedingTimeLimit();
106 const int firstTorrentInactiveSeedingTime
= torrents
[0]->inactiveSeedingTimeLimit();
108 const bool isFirstTorrentDHTDisabled
= torrents
[0]->isDHTDisabled();
109 const bool isFirstTorrentPEXDisabled
= torrents
[0]->isPEXDisabled();
110 const bool isFirstTorrentLSDDisabled
= torrents
[0]->isLSDDisabled();
111 const bool isFirstTorrentSequentialEnabled
= torrents
[0]->isSequentialDownload();
112 const bool isFirstTorrentFirstLastPiecesEnabled
= torrents
[0]->hasFirstLastPiecePriority();
114 m_torrentIDs
.reserve(torrents
.size());
115 for (const BitTorrent::Torrent
*torrent
: torrents
)
117 m_torrentIDs
<< torrent
->id();
121 if (torrent
->isAutoTMMEnabled() != isFirstTorrentAutoTMMEnabled
)
122 allSameAutoTMM
= false;
126 if (torrent
->savePath() != firstTorrentSavePath
)
127 allSameSavePath
= false;
129 if (allSameDownloadPath
)
131 if (torrent
->downloadPath() != firstTorrentDownloadPath
)
132 allSameDownloadPath
= false;
134 if (m_allSameCategory
)
136 if (torrent
->category() != firstTorrentCategory
)
137 m_allSameCategory
= false;
141 if (std::max(0, torrent
->uploadLimit()) != firstTorrentUpLimit
)
142 allSameUpLimit
= false;
144 if (allSameDownLimit
)
146 if (std::max(0, torrent
->downloadLimit()) != firstTorrentDownLimit
)
147 allSameDownLimit
= false;
151 if (torrent
->ratioLimit() != firstTorrentRatio
)
152 allSameRatio
= false;
154 if (allSameSeedingTime
)
156 if (torrent
->seedingTimeLimit() != firstTorrentSeedingTime
)
157 allSameSeedingTime
= false;
159 if (allSameInactiveSeedingTime
)
161 if (torrent
->inactiveSeedingTimeLimit() != firstTorrentInactiveSeedingTime
)
162 allSameInactiveSeedingTime
= false;
164 if (allTorrentsArePrivate
)
166 if (!torrent
->isPrivate())
167 allTorrentsArePrivate
= false;
171 if (torrent
->isDHTDisabled() != isFirstTorrentDHTDisabled
)
176 if (torrent
->isPEXDisabled() != isFirstTorrentPEXDisabled
)
181 if (torrent
->isLSDDisabled() != isFirstTorrentLSDDisabled
)
184 if (allSameSequential
)
186 if (torrent
->isSequentialDownload() != isFirstTorrentSequentialEnabled
)
187 allSameSequential
= false;
189 if (allSameFirstLastPieces
)
191 if (torrent
->hasFirstLastPiecePriority() != isFirstTorrentFirstLastPiecesEnabled
)
192 allSameFirstLastPieces
= false;
197 m_ui
->checkAutoTMM
->setChecked(isFirstTorrentAutoTMMEnabled
);
199 m_ui
->checkAutoTMM
->setCheckState(Qt::PartiallyChecked
);
202 m_ui
->savePath
->setSelectedPath(firstTorrentSavePath
);
204 if (allSameDownloadPath
)
206 m_ui
->downloadPath
->setSelectedPath(firstTorrentDownloadPath
);
207 m_ui
->checkUseDownloadPath
->setChecked(!firstTorrentDownloadPath
.isEmpty());
211 m_ui
->checkUseDownloadPath
->setCheckState(Qt::PartiallyChecked
);
214 if (!m_allSameCategory
)
216 m_ui
->comboCategory
->addItem(m_currentCategoriesString
);
217 m_ui
->comboCategory
->clearEditText();
218 m_ui
->comboCategory
->lineEdit()->setPlaceholderText(m_currentCategoriesString
);
220 else if (!firstTorrentCategory
.isEmpty())
222 m_ui
->comboCategory
->setCurrentText(firstTorrentCategory
);
223 m_ui
->comboCategory
->addItem(firstTorrentCategory
);
225 m_ui
->comboCategory
->addItem(QString());
227 m_categories
= session
->categories();
228 std::sort(m_categories
.begin(), m_categories
.end(), Utils::Compare::NaturalLessThan
<Qt::CaseInsensitive
>());
229 for (const QString
&category
: asConst(m_categories
))
231 if (m_allSameCategory
&& (category
== firstTorrentCategory
))
234 m_ui
->comboCategory
->addItem(category
);
237 const bool isAltLimitEnabled
= session
->isAltGlobalSpeedLimitEnabled();
238 const int globalUploadLimit
= isAltLimitEnabled
239 ? (session
->altGlobalUploadSpeedLimit() / 1024)
240 : (session
->globalUploadSpeedLimit() / 1024);
241 const int globalDownloadLimit
= isAltLimitEnabled
242 ? (session
->altGlobalDownloadSpeedLimit() / 1024)
243 : (session
->globalDownloadSpeedLimit() / 1024);
245 const int uploadVal
= std::max(0, (firstTorrentUpLimit
/ 1024));
246 const int downloadVal
= std::max(0, (firstTorrentDownLimit
/ 1024));
247 int maxUpload
= (globalUploadLimit
<= 0) ? 10000 : globalUploadLimit
;
248 int maxDownload
= (globalDownloadLimit
<= 0) ? 10000 : globalDownloadLimit
;
250 // This can happen for example if global rate limit is lower than torrent rate limit.
251 if (uploadVal
> maxUpload
)
252 maxUpload
= uploadVal
;
253 if (downloadVal
> maxDownload
)
254 maxDownload
= downloadVal
;
256 m_ui
->sliderUploadLimit
->setMaximum(maxUpload
);
257 m_ui
->sliderUploadLimit
->setValue(allSameUpLimit
? uploadVal
: (maxUpload
/ 2));
260 m_ui
->spinUploadLimit
->setValue(uploadVal
);
264 m_ui
->spinUploadLimit
->setSpecialValueText(C_INEQUALITY
);
265 m_ui
->spinUploadLimit
->setMinimum(-1);
266 m_ui
->spinUploadLimit
->setValue(-1);
267 connect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
268 , this, &TorrentOptionsDialog::handleUpSpeedLimitChanged
);
271 m_ui
->sliderDownloadLimit
->setMaximum(maxDownload
);
272 m_ui
->sliderDownloadLimit
->setValue(allSameDownLimit
? downloadVal
: (maxDownload
/ 2));
273 if (allSameDownLimit
)
275 m_ui
->spinDownloadLimit
->setValue(downloadVal
);
279 m_ui
->spinDownloadLimit
->setSpecialValueText(C_INEQUALITY
);
280 m_ui
->spinDownloadLimit
->setMinimum(-1);
281 m_ui
->spinDownloadLimit
->setValue(-1);
282 connect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
283 , this, &TorrentOptionsDialog::handleDownSpeedLimitChanged
);
286 const bool useGlobalValue
= allSameRatio
&& allSameSeedingTime
287 && (firstTorrentRatio
== BitTorrent::Torrent::USE_GLOBAL_RATIO
)
288 && (firstTorrentSeedingTime
== BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME
)
289 && (firstTorrentInactiveSeedingTime
== BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME
);
291 if (!allSameRatio
|| !allSameSeedingTime
|| !allSameInactiveSeedingTime
)
293 m_ui
->radioUseGlobalShareLimits
->setChecked(false);
294 m_ui
->radioNoLimit
->setChecked(false);
295 m_ui
->radioTorrentLimit
->setChecked(false);
297 else if (useGlobalValue
)
299 m_ui
->radioUseGlobalShareLimits
->setChecked(true);
301 else if ((firstTorrentRatio
== BitTorrent::Torrent::NO_RATIO_LIMIT
)
302 && (firstTorrentSeedingTime
== BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT
)
303 && (firstTorrentInactiveSeedingTime
== BitTorrent::Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT
))
305 m_ui
->radioNoLimit
->setChecked(true);
309 m_ui
->radioTorrentLimit
->setChecked(true);
310 if (firstTorrentRatio
>= 0)
311 m_ui
->checkMaxRatio
->setChecked(true);
312 if (firstTorrentSeedingTime
>= 0)
313 m_ui
->checkMaxTime
->setChecked(true);
314 if (firstTorrentInactiveSeedingTime
>= 0)
315 m_ui
->checkMaxInactiveTime
->setChecked(true);
318 const qreal maxRatio
= (allSameRatio
&& (firstTorrentRatio
>= 0))
319 ? firstTorrentRatio
: session
->globalMaxRatio();
320 const int maxSeedingTime
= (allSameSeedingTime
&& (firstTorrentSeedingTime
>= 0))
321 ? firstTorrentSeedingTime
: session
->globalMaxSeedingMinutes();
322 const int maxInactiveSeedingTime
= (allSameInactiveSeedingTime
&& (firstTorrentInactiveSeedingTime
>= 0))
323 ? firstTorrentInactiveSeedingTime
: session
->globalMaxInactiveSeedingMinutes();
324 m_ui
->spinRatioLimit
->setValue(maxRatio
);
325 m_ui
->spinTimeLimit
->setValue(maxSeedingTime
);
326 m_ui
->spinInactiveTimeLimit
->setValue(maxInactiveSeedingTime
);
328 if (!allTorrentsArePrivate
)
331 m_ui
->checkDisableDHT
->setChecked(isFirstTorrentDHTDisabled
);
333 m_ui
->checkDisableDHT
->setCheckState(Qt::PartiallyChecked
);
336 m_ui
->checkDisablePEX
->setChecked(isFirstTorrentPEXDisabled
);
338 m_ui
->checkDisablePEX
->setCheckState(Qt::PartiallyChecked
);
341 m_ui
->checkDisableLSD
->setChecked(isFirstTorrentLSDDisabled
);
343 m_ui
->checkDisableLSD
->setCheckState(Qt::PartiallyChecked
);
347 m_ui
->checkDisableDHT
->setChecked(true);
348 m_ui
->checkDisableDHT
->setEnabled(false);
349 m_ui
->checkDisablePEX
->setChecked(true);
350 m_ui
->checkDisablePEX
->setEnabled(false);
351 m_ui
->checkDisableLSD
->setChecked(true);
352 m_ui
->checkDisableLSD
->setEnabled(false);
355 const QString privateTorrentsTooltip
= tr("Not applicable to private torrents");
356 m_ui
->checkDisableDHT
->setToolTip(privateTorrentsTooltip
);
357 m_ui
->checkDisablePEX
->setToolTip(privateTorrentsTooltip
);
358 m_ui
->checkDisableLSD
->setToolTip(privateTorrentsTooltip
);
360 if (allSameSequential
)
361 m_ui
->checkSequential
->setChecked(isFirstTorrentSequentialEnabled
);
363 m_ui
->checkSequential
->setCheckState(Qt::PartiallyChecked
);
365 if (allSameFirstLastPieces
)
366 m_ui
->checkFirstLastPieces
->setChecked(isFirstTorrentFirstLastPiecesEnabled
);
368 m_ui
->checkFirstLastPieces
->setCheckState(Qt::PartiallyChecked
);
372 m_ui
->savePath
->selectedPath(),
373 m_ui
->downloadPath
->selectedPath(),
374 m_ui
->comboCategory
->currentText(),
377 getInactiveSeedingTime(),
378 m_ui
->spinUploadLimit
->value(),
379 m_ui
->spinDownloadLimit
->value(),
380 m_ui
->checkAutoTMM
->checkState(),
381 m_ui
->checkUseDownloadPath
->checkState(),
382 m_ui
->checkDisableDHT
->checkState(),
383 m_ui
->checkDisablePEX
->checkState(),
384 m_ui
->checkDisableLSD
->checkState(),
385 m_ui
->checkSequential
->checkState(),
386 m_ui
->checkFirstLastPieces
->checkState()
389 // Needs to be called after the initial values struct is initialized
391 handleUseDownloadPathChanged();
392 handleRatioTypeChanged();
394 connect(m_ui
->checkAutoTMM
, &QCheckBox::clicked
, this, &TorrentOptionsDialog::handleTMMChanged
);
395 connect(m_ui
->checkUseDownloadPath
, &QCheckBox::clicked
, this, &TorrentOptionsDialog::handleUseDownloadPathChanged
);
396 connect(m_ui
->comboCategory
, &QComboBox::activated
, this, &TorrentOptionsDialog::handleCategoryChanged
);
398 // Sync up/down speed limit sliders with their corresponding spinboxes
399 connect(m_ui
->sliderUploadLimit
, &QSlider::valueChanged
, m_ui
->spinUploadLimit
, &QSpinBox::setValue
);
400 connect(m_ui
->sliderDownloadLimit
, &QSlider::valueChanged
, m_ui
->spinDownloadLimit
, &QSpinBox::setValue
);
401 connect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
402 , this, [this](const int value
) { updateSliderValue(m_ui
->sliderUploadLimit
, value
); });
403 connect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
404 , this, [this](const int value
) { updateSliderValue(m_ui
->sliderDownloadLimit
, value
); });
406 connect(m_ui
->checkMaxRatio
, &QCheckBox::toggled
, m_ui
->spinRatioLimit
, &QWidget::setEnabled
);
407 connect(m_ui
->checkMaxTime
, &QCheckBox::toggled
, m_ui
->spinTimeLimit
, &QWidget::setEnabled
);
408 connect(m_ui
->checkMaxInactiveTime
, &QCheckBox::toggled
, m_ui
->spinInactiveTimeLimit
, &QSpinBox::setEnabled
);
410 connect(m_ui
->buttonGroup
, &QButtonGroup::idClicked
, this, &TorrentOptionsDialog::handleRatioTypeChanged
);
412 if (const QSize dialogSize
= m_storeDialogSize
; dialogSize
.isValid())
416 TorrentOptionsDialog::~TorrentOptionsDialog()
418 m_storeDialogSize
= size();
422 void TorrentOptionsDialog::accept()
424 if (m_ui
->radioTorrentLimit
->isChecked() && !m_ui
->checkMaxRatio
->isChecked()
425 && !m_ui
->checkMaxTime
->isChecked() && !m_ui
->checkMaxInactiveTime
->isChecked())
427 QMessageBox::critical(this, tr("No share limit method selected"), tr("Please select a limit method first"));
431 auto *session
= BitTorrent::Session::instance();
432 for (const BitTorrent::TorrentID
&id
: asConst(m_torrentIDs
))
434 BitTorrent::Torrent
*torrent
= session
->getTorrent(id
);
435 if (!torrent
) continue;
437 if (m_initialValues
.autoTMM
!= m_ui
->checkAutoTMM
->checkState())
438 torrent
->setAutoTMMEnabled(m_ui
->checkAutoTMM
->isChecked());
440 if (m_ui
->checkAutoTMM
->checkState() == Qt::Unchecked
)
442 const Path savePath
= m_ui
->savePath
->selectedPath();
443 if (m_initialValues
.savePath
!= savePath
)
444 torrent
->setSavePath(savePath
);
446 const Qt::CheckState useDownloadPathState
= m_ui
->checkUseDownloadPath
->checkState();
447 if (useDownloadPathState
== Qt::Checked
)
449 const Path downloadPath
= m_ui
->downloadPath
->selectedPath();
450 if (m_initialValues
.downloadPath
!= downloadPath
)
451 torrent
->setDownloadPath(downloadPath
);
453 else if (useDownloadPathState
== Qt::Unchecked
)
455 torrent
->setDownloadPath({});
459 const QString category
= m_ui
->comboCategory
->currentText();
460 // index 0 is always the current category
461 if ((m_initialValues
.category
!= category
) || (m_ui
->comboCategory
->currentIndex() != 0))
463 if (!m_categories
.contains(category
))
464 session
->addCategory(category
);
466 torrent
->setCategory(category
);
469 if (m_initialValues
.upSpeedLimit
!= m_ui
->spinUploadLimit
->value())
470 torrent
->setUploadLimit(m_ui
->spinUploadLimit
->value() * 1024);
471 if (m_initialValues
.downSpeedLimit
!= m_ui
->spinDownloadLimit
->value())
472 torrent
->setDownloadLimit(m_ui
->spinDownloadLimit
->value() * 1024);
474 const qreal ratioLimit
= getRatio();
475 if (m_initialValues
.ratio
!= ratioLimit
)
476 torrent
->setRatioLimit(ratioLimit
);
478 const int seedingTimeLimit
= getSeedingTime();
479 if (m_initialValues
.seedingTime
!= seedingTimeLimit
)
480 torrent
->setSeedingTimeLimit(seedingTimeLimit
);
482 const int inactiveSeedingTimeLimit
= getInactiveSeedingTime();
483 if (m_initialValues
.inactiveSeedingTime
!= inactiveSeedingTimeLimit
)
484 torrent
->setInactiveSeedingTimeLimit(inactiveSeedingTimeLimit
);
486 if (!torrent
->isPrivate())
488 if (m_initialValues
.disableDHT
!= m_ui
->checkDisableDHT
->checkState())
489 torrent
->setDHTDisabled(m_ui
->checkDisableDHT
->isChecked());
490 if (m_initialValues
.disablePEX
!= m_ui
->checkDisablePEX
->checkState())
491 torrent
->setPEXDisabled(m_ui
->checkDisablePEX
->isChecked());
492 if (m_initialValues
.disableLSD
!= m_ui
->checkDisableLSD
->checkState())
493 torrent
->setLSDDisabled(m_ui
->checkDisableLSD
->isChecked());
496 if (m_initialValues
.sequential
!= m_ui
->checkSequential
->checkState())
497 torrent
->setSequentialDownload(m_ui
->checkSequential
->isChecked());
498 if (m_initialValues
.firstLastPieces
!= m_ui
->checkFirstLastPieces
->checkState())
499 torrent
->setFirstLastPiecePriority(m_ui
->checkFirstLastPieces
->isChecked());
505 qreal
TorrentOptionsDialog::getRatio() const
507 if (m_ui
->buttonGroup
->checkedId() == -1) // No radio button is selected
508 return MIXED_SHARE_LIMITS
;
510 if (m_ui
->radioUseGlobalShareLimits
->isChecked())
511 return BitTorrent::Torrent::USE_GLOBAL_RATIO
;
513 if (m_ui
->radioNoLimit
->isChecked() || !m_ui
->checkMaxRatio
->isChecked())
514 return BitTorrent::Torrent::NO_RATIO_LIMIT
;
516 return m_ui
->spinRatioLimit
->value();
519 int TorrentOptionsDialog::getSeedingTime() const
521 if (m_ui
->buttonGroup
->checkedId() == -1) // No radio button is selected
522 return MIXED_SHARE_LIMITS
;
524 if (m_ui
->radioUseGlobalShareLimits
->isChecked())
525 return BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME
;
527 if (m_ui
->radioNoLimit
->isChecked() || !m_ui
->checkMaxTime
->isChecked())
528 return BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT
;
530 return m_ui
->spinTimeLimit
->value();
533 int TorrentOptionsDialog::getInactiveSeedingTime() const
535 if (m_ui
->buttonGroup
->checkedId() == -1) // No radio button is selected
536 return MIXED_SHARE_LIMITS
;
538 if (m_ui
->radioUseGlobalShareLimits
->isChecked())
539 return BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME
;
541 if (m_ui
->radioNoLimit
->isChecked() || !m_ui
->checkMaxInactiveTime
->isChecked())
542 return BitTorrent::Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT
;
544 return m_ui
->spinInactiveTimeLimit
->value();
547 void TorrentOptionsDialog::handleCategoryChanged(const int index
)
551 if (m_ui
->checkAutoTMM
->checkState() == Qt::Checked
)
553 if (!m_allSameCategory
&& (m_ui
->comboCategory
->currentIndex() == 0))
555 m_ui
->savePath
->setSelectedPath({});
559 const Path savePath
= BitTorrent::Session::instance()->categorySavePath(m_ui
->comboCategory
->currentText());
560 m_ui
->savePath
->setSelectedPath(savePath
);
561 const Path downloadPath
= BitTorrent::Session::instance()->categoryDownloadPath(m_ui
->comboCategory
->currentText());
562 m_ui
->downloadPath
->setSelectedPath(downloadPath
);
563 m_ui
->checkUseDownloadPath
->setChecked(!downloadPath
.isEmpty());
567 if (!m_allSameCategory
&& (m_ui
->comboCategory
->currentIndex() == 0))
569 m_ui
->comboCategory
->clearEditText();
570 m_ui
->comboCategory
->lineEdit()->setPlaceholderText(m_currentCategoriesString
);
574 m_ui
->comboCategory
->lineEdit()->setPlaceholderText(QString());
578 void TorrentOptionsDialog::handleTMMChanged()
580 if (m_ui
->checkAutoTMM
->checkState() == Qt::Unchecked
)
582 m_ui
->groupBoxSavePath
->setEnabled(true);
583 m_ui
->savePath
->setSelectedPath(m_initialValues
.savePath
);
584 m_ui
->downloadPath
->setSelectedPath(m_initialValues
.downloadPath
);
585 m_ui
->checkUseDownloadPath
->setCheckState(m_initialValues
.useDownloadPath
);
589 m_ui
->groupBoxSavePath
->setEnabled(false);
590 if (m_ui
->checkAutoTMM
->checkState() == Qt::Checked
)
592 if (!m_allSameCategory
&& (m_ui
->comboCategory
->currentIndex() == 0))
594 m_ui
->savePath
->setSelectedPath({});
595 m_ui
->downloadPath
->setSelectedPath({});
596 m_ui
->checkUseDownloadPath
->setCheckState(Qt::PartiallyChecked
);
600 const Path savePath
= BitTorrent::Session::instance()->categorySavePath(m_ui
->comboCategory
->currentText());
601 m_ui
->savePath
->setSelectedPath(savePath
);
602 const Path downloadPath
= BitTorrent::Session::instance()->categoryDownloadPath(m_ui
->comboCategory
->currentText());
603 m_ui
->downloadPath
->setSelectedPath(downloadPath
);
604 m_ui
->checkUseDownloadPath
->setChecked(!downloadPath
.isEmpty());
607 else // partially checked
609 m_ui
->savePath
->setSelectedPath({});
610 m_ui
->downloadPath
->setSelectedPath({});
611 m_ui
->checkUseDownloadPath
->setCheckState(Qt::PartiallyChecked
);
616 void TorrentOptionsDialog::handleUseDownloadPathChanged()
618 const bool isChecked
= m_ui
->checkUseDownloadPath
->checkState() == Qt::Checked
;
619 m_ui
->downloadPath
->setEnabled(isChecked
);
620 if (isChecked
&& m_ui
->downloadPath
->selectedPath().isEmpty())
621 m_ui
->downloadPath
->setSelectedPath(BitTorrent::Session::instance()->downloadPath());
624 void TorrentOptionsDialog::handleRatioTypeChanged()
626 if ((m_initialValues
.ratio
== MIXED_SHARE_LIMITS
) || (m_initialValues
.seedingTime
== MIXED_SHARE_LIMITS
)
627 || (m_initialValues
.inactiveSeedingTime
== MIXED_SHARE_LIMITS
))
629 QAbstractButton
*currentRadio
= m_ui
->buttonGroup
->checkedButton();
630 if (currentRadio
&& (currentRadio
== m_previousRadio
))
632 // Hack to deselect the currently selected radio button programmatically because Qt doesn't allow it in exclusive mode
633 m_ui
->buttonGroup
->setExclusive(false);
634 currentRadio
->setChecked(false);
635 m_ui
->buttonGroup
->setExclusive(true);
637 m_previousRadio
= m_ui
->buttonGroup
->checkedButton();
640 m_ui
->checkMaxRatio
->setEnabled(m_ui
->radioTorrentLimit
->isChecked());
641 m_ui
->checkMaxTime
->setEnabled(m_ui
->radioTorrentLimit
->isChecked());
642 m_ui
->checkMaxInactiveTime
->setEnabled(m_ui
->radioTorrentLimit
->isChecked());
644 m_ui
->spinRatioLimit
->setEnabled(m_ui
->radioTorrentLimit
->isChecked() && m_ui
->checkMaxRatio
->isChecked());
645 m_ui
->spinTimeLimit
->setEnabled(m_ui
->radioTorrentLimit
->isChecked() && m_ui
->checkMaxTime
->isChecked());
646 m_ui
->spinInactiveTimeLimit
->setEnabled(m_ui
->radioTorrentLimit
->isChecked() && m_ui
->checkMaxInactiveTime
->isChecked());
649 void TorrentOptionsDialog::handleUpSpeedLimitChanged()
651 m_ui
->spinUploadLimit
->setMinimum(0);
652 m_ui
->spinUploadLimit
->setSpecialValueText(C_INFINITY
);
653 disconnect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
654 , this, &TorrentOptionsDialog::handleUpSpeedLimitChanged
);
657 void TorrentOptionsDialog::handleDownSpeedLimitChanged()
659 m_ui
->spinDownloadLimit
->setMinimum(0);
660 m_ui
->spinDownloadLimit
->setSpecialValueText(C_INFINITY
);
661 disconnect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
662 , this, &TorrentOptionsDialog::handleDownSpeedLimitChanged
);