qBittorrent
torrentoptionsdialog.cpp
Go to the documentation of this file.
1 /*
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>
6  *
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.
11  *
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.
16  *
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.
20  *
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.
29  */
30 
31 #include "torrentoptionsdialog.h"
32 
33 #include <algorithm>
34 
35 #include <QLineEdit>
36 #include <QMessageBox>
37 #include <QString>
38 
42 #include "base/global.h"
43 #include "base/unicodestrings.h"
44 #include "base/utils/fs.h"
45 #include "ui_torrentoptionsdialog.h"
46 #include "utils.h"
47 
48 #define SETTINGS_KEY(name) "TorrentOptionsDialog/" name
49 
50 namespace
51 {
52  const int MIXED_SHARE_LIMITS = -9;
53 
54  void updateSliderValue(QSlider *slider, const int value)
55  {
56  if (value > slider->maximum())
57  slider->setMaximum(value);
58  slider->setValue(value);
59  }
60 }
61 
62 TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTorrent::Torrent *> &torrents)
63  : QDialog {parent}
64  , m_ui {new Ui::TorrentOptionsDialog}
65  , m_storeDialogSize {SETTINGS_KEY("Size")}
66  , m_currentCategoriesString {QString::fromLatin1("--%1--").arg(tr("Currently used categories"))}
67 {
68  Q_ASSERT(!torrents.empty());
69 
70  m_ui->setupUi(this);
71 
73  m_ui->savePath->setDialogCaption(tr("Choose save path"));
74  m_ui->downloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
75  m_ui->downloadPath->setDialogCaption(tr("Choose save path"));
76 
77  const auto *session = BitTorrent::Session::instance();
78  bool allSameUpLimit = true;
79  bool allSameDownLimit = true;
80  bool allSameRatio = true;
81  bool allSameSeedingTime = true;
82  bool allTorrentsArePrivate = true;
83  bool allSameDHT = true;
84  bool allSamePEX = true;
85  bool allSameLSD = true;
86  bool allSameSequential = true;
87  bool allSameFirstLastPieces = true;
88  bool allSameAutoTMM = true;
89  bool allSameSavePath = true;
90  bool allSameDownloadPath = true;
91 
92  const bool isFirstTorrentAutoTMMEnabled = torrents[0]->isAutoTMMEnabled();
93  const QString firstTorrentSavePath = torrents[0]->savePath();
94  const QString firstTorrentDownloadPath = torrents[0]->downloadPath();
95  const QString firstTorrentCategory = torrents[0]->category();
96 
97  const int firstTorrentUpLimit = std::max(0, torrents[0]->uploadLimit());
98  const int firstTorrentDownLimit = std::max(0, torrents[0]->downloadLimit());
99 
100  const qreal firstTorrentRatio = torrents[0]->ratioLimit();
101  const int firstTorrentSeedingTime = torrents[0]->seedingTimeLimit();
102 
103  const bool isFirstTorrentDHTDisabled = torrents[0]->isDHTDisabled();
104  const bool isFirstTorrentPEXDisabled = torrents[0]->isPEXDisabled();
105  const bool isFirstTorrentLSDDisabled = torrents[0]->isLSDDisabled();
106  const bool isFirstTorrentSequentialEnabled = torrents[0]->isSequentialDownload();
107  const bool isFirstTorrentFirstLastPiecesEnabled = torrents[0]->hasFirstLastPiecePriority();
108 
109  m_torrentIDs.reserve(torrents.size());
110  for (const BitTorrent::Torrent *torrent : torrents)
111  {
112  m_torrentIDs << torrent->id();
113 
114  if (allSameAutoTMM)
115  {
116  if (torrent->isAutoTMMEnabled() != isFirstTorrentAutoTMMEnabled)
117  allSameAutoTMM = false;
118  }
119  if (allSameSavePath)
120  {
121  if (torrent->savePath() != firstTorrentSavePath)
122  allSameSavePath = false;
123  }
124  if (allSameDownloadPath)
125  {
126  if (torrent->downloadPath() != firstTorrentDownloadPath)
127  allSameDownloadPath = false;
128  }
129  if (m_allSameCategory)
130  {
131  if (torrent->category() != firstTorrentCategory)
132  m_allSameCategory = false;
133  }
134  if (allSameUpLimit)
135  {
136  if (std::max(0, torrent->uploadLimit()) != firstTorrentUpLimit)
137  allSameUpLimit = false;
138  }
139  if (allSameDownLimit)
140  {
141  if (std::max(0, torrent->downloadLimit()) != firstTorrentDownLimit)
142  allSameDownLimit = false;
143  }
144  if (allSameRatio)
145  {
146  if (torrent->ratioLimit() != firstTorrentRatio)
147  allSameRatio = false;
148  }
149  if (allSameSeedingTime)
150  {
151  if (torrent->seedingTimeLimit() != firstTorrentSeedingTime)
152  allSameSeedingTime = false;
153  }
154  if (allTorrentsArePrivate)
155  {
156  if (!torrent->isPrivate())
157  allTorrentsArePrivate = false;
158  }
159  if (allSameDHT)
160  {
161  if (torrent->isDHTDisabled() != isFirstTorrentDHTDisabled)
162  allSameDHT = false;
163  }
164  if (allSamePEX)
165  {
166  if (torrent->isPEXDisabled() != isFirstTorrentPEXDisabled)
167  allSamePEX = false;
168  }
169  if (allSameLSD)
170  {
171  if (torrent->isLSDDisabled() != isFirstTorrentLSDDisabled)
172  allSameLSD = false;
173  }
174  if (allSameSequential)
175  {
176  if (torrent->isSequentialDownload() != isFirstTorrentSequentialEnabled)
177  allSameSequential = false;
178  }
179  if (allSameFirstLastPieces)
180  {
181  if (torrent->hasFirstLastPiecePriority() != isFirstTorrentFirstLastPiecesEnabled)
182  allSameFirstLastPieces = false;
183  }
184  }
185 
186  if (allSameAutoTMM)
187  m_ui->checkAutoTMM->setChecked(isFirstTorrentAutoTMMEnabled);
188  else
189  m_ui->checkAutoTMM->setCheckState(Qt::PartiallyChecked);
190 
191  if (allSameSavePath)
192  m_ui->savePath->setSelectedPath(firstTorrentSavePath);
193 
194  if (allSameDownloadPath)
195  {
196  m_ui->downloadPath->setSelectedPath(firstTorrentDownloadPath);
197  m_ui->checkUseDownloadPath->setChecked(!firstTorrentDownloadPath.isEmpty());
198  }
199  else
200  {
201  m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
202  }
203 
204  if (!m_allSameCategory)
205  {
206  m_ui->comboCategory->addItem(m_currentCategoriesString);
207  m_ui->comboCategory->clearEditText();
208  m_ui->comboCategory->lineEdit()->setPlaceholderText(m_currentCategoriesString);
209  }
210  else if (!firstTorrentCategory.isEmpty())
211  {
212  m_ui->comboCategory->setCurrentText(firstTorrentCategory);
213  m_ui->comboCategory->addItem(firstTorrentCategory);
214  }
215  m_ui->comboCategory->addItem(QString());
216 
217  m_categories = session->categories();
219  for (const QString &category : asConst(m_categories))
220  {
221  if (m_allSameCategory && (category == firstTorrentCategory))
222  continue;
223 
224  m_ui->comboCategory->addItem(category);
225  }
226 
227  const bool isAltLimitEnabled = session->isAltGlobalSpeedLimitEnabled();
228  const int globalUploadLimit = isAltLimitEnabled
229  ? (session->altGlobalUploadSpeedLimit() / 1024)
230  : (session->globalUploadSpeedLimit() / 1024);
231  const int globalDownloadLimit = isAltLimitEnabled
232  ? (session->altGlobalDownloadSpeedLimit() / 1024)
233  : (session->globalDownloadSpeedLimit() / 1024);
234 
235  const int uploadVal = std::max(0, (firstTorrentUpLimit / 1024));
236  const int downloadVal = std::max(0, (firstTorrentDownLimit / 1024));
237  int maxUpload = (globalUploadLimit <= 0) ? 10000 : globalUploadLimit;
238  int maxDownload = (globalDownloadLimit <= 0) ? 10000 : globalDownloadLimit;
239 
240  // This can happen for example if global rate limit is lower than torrent rate limit.
241  if (uploadVal > maxUpload)
242  maxUpload = uploadVal;
243  if (downloadVal > maxDownload)
244  maxDownload = downloadVal;
245 
246  m_ui->sliderUploadLimit->setMaximum(maxUpload);
247  m_ui->sliderUploadLimit->setValue(allSameUpLimit ? uploadVal : (maxUpload / 2));
248  if (allSameUpLimit)
249  {
250  m_ui->spinUploadLimit->setValue(uploadVal);
251  }
252  else
253  {
254  m_ui->spinUploadLimit->setSpecialValueText(QString::fromUtf8(C_INEQUALITY));
255  m_ui->spinUploadLimit->setMinimum(-1);
256  m_ui->spinUploadLimit->setValue(-1);
257  connect(m_ui->spinUploadLimit, qOverload<int>(&QSpinBox::valueChanged)
259  }
260 
261  m_ui->sliderDownloadLimit->setMaximum(maxDownload);
262  m_ui->sliderDownloadLimit->setValue(allSameDownLimit ? downloadVal : (maxDownload / 2));
263  if (allSameDownLimit)
264  {
265  m_ui->spinDownloadLimit->setValue(downloadVal);
266  }
267  else
268  {
269  m_ui->spinDownloadLimit->setSpecialValueText(QString::fromUtf8(C_INEQUALITY));
270  m_ui->spinDownloadLimit->setMinimum(-1);
271  m_ui->spinDownloadLimit->setValue(-1);
272  connect(m_ui->spinDownloadLimit, qOverload<int>(&QSpinBox::valueChanged)
274  }
275 
276  const bool useGlobalValue = allSameRatio && allSameSeedingTime
277  && (firstTorrentRatio == BitTorrent::Torrent::USE_GLOBAL_RATIO)
278  && (firstTorrentSeedingTime == BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME);
279 
280  if (!allSameRatio || !allSameSeedingTime)
281  {
282  m_ui->radioUseGlobalShareLimits->setChecked(false);
283  m_ui->radioNoLimit->setChecked(false);
284  m_ui->radioTorrentLimit->setChecked(false);
285  }
286  else if (useGlobalValue)
287  {
288  m_ui->radioUseGlobalShareLimits->setChecked(true);
289  }
290  else if ((firstTorrentRatio == BitTorrent::Torrent::NO_RATIO_LIMIT)
291  && (firstTorrentSeedingTime == BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT))
292  {
293  m_ui->radioNoLimit->setChecked(true);
294  }
295  else
296  {
297  m_ui->radioTorrentLimit->setChecked(true);
298  if (firstTorrentRatio >= 0)
299  m_ui->checkMaxRatio->setChecked(true);
300  if (firstTorrentSeedingTime >= 0)
301  m_ui->checkMaxTime->setChecked(true);
302  }
303 
304  const qreal maxRatio = (allSameRatio && (firstTorrentRatio >= 0))
305  ? firstTorrentRatio : session->globalMaxRatio();
306  const int maxSeedingTime = (allSameSeedingTime && (firstTorrentSeedingTime >= 0))
307  ? firstTorrentSeedingTime : session->globalMaxSeedingMinutes();
308  m_ui->spinRatioLimit->setValue(maxRatio);
309  m_ui->spinTimeLimit->setValue(maxSeedingTime);
310 
311  if (!allTorrentsArePrivate)
312  {
313  if (allSameDHT)
314  m_ui->checkDisableDHT->setChecked(isFirstTorrentDHTDisabled);
315  else
316  m_ui->checkDisableDHT->setCheckState(Qt::PartiallyChecked);
317 
318  if (allSamePEX)
319  m_ui->checkDisablePEX->setChecked(isFirstTorrentPEXDisabled);
320  else
321  m_ui->checkDisablePEX->setCheckState(Qt::PartiallyChecked);
322 
323  if (allSameLSD)
324  m_ui->checkDisableLSD->setChecked(isFirstTorrentLSDDisabled);
325  else
326  m_ui->checkDisableLSD->setCheckState(Qt::PartiallyChecked);
327  }
328  else
329  {
330  m_ui->checkDisableDHT->setChecked(true);
331  m_ui->checkDisableDHT->setEnabled(false);
332  m_ui->checkDisablePEX->setChecked(true);
333  m_ui->checkDisablePEX->setEnabled(false);
334  m_ui->checkDisableLSD->setChecked(true);
335  m_ui->checkDisableLSD->setEnabled(false);
336  }
337 
338  const QString privateTorrentsTooltip = tr("Not applicable to private torrents");
339  m_ui->checkDisableDHT->setToolTip(privateTorrentsTooltip);
340  m_ui->checkDisablePEX->setToolTip(privateTorrentsTooltip);
341  m_ui->checkDisableLSD->setToolTip(privateTorrentsTooltip);
342 
343  if (allSameSequential)
344  m_ui->checkSequential->setChecked(isFirstTorrentSequentialEnabled);
345  else
346  m_ui->checkSequential->setCheckState(Qt::PartiallyChecked);
347 
348  if (allSameFirstLastPieces)
349  m_ui->checkFirstLastPieces->setChecked(isFirstTorrentFirstLastPiecesEnabled);
350  else
351  m_ui->checkFirstLastPieces->setCheckState(Qt::PartiallyChecked);
352 
354  {
355  m_ui->savePath->selectedPath(),
356  m_ui->downloadPath->selectedPath(),
357  m_ui->comboCategory->currentText(),
358  getRatio(),
359  getSeedingTime(),
360  m_ui->spinUploadLimit->value(),
361  m_ui->spinDownloadLimit->value(),
362  m_ui->checkAutoTMM->checkState(),
363  m_ui->checkUseDownloadPath->checkState(),
364  m_ui->checkDisableDHT->checkState(),
365  m_ui->checkDisablePEX->checkState(),
366  m_ui->checkDisableLSD->checkState(),
367  m_ui->checkSequential->checkState(),
368  m_ui->checkFirstLastPieces->checkState()
369  };
370 
371  // Needs to be called after the initial values struct is initialized
375 
376  connect(m_ui->checkAutoTMM, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleTMMChanged);
377  connect(m_ui->checkUseDownloadPath, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleUseDownloadPathChanged);
378  connect(m_ui->comboCategory, &QComboBox::activated, this, &TorrentOptionsDialog::handleCategoryChanged);
379 
380  // Sync up/down speed limit sliders with their corresponding spinboxes
381  connect(m_ui->sliderUploadLimit, &QSlider::valueChanged, m_ui->spinUploadLimit, &QSpinBox::setValue);
382  connect(m_ui->sliderDownloadLimit, &QSlider::valueChanged, m_ui->spinDownloadLimit, &QSpinBox::setValue);
383  connect(m_ui->spinUploadLimit, qOverload<int>(&QSpinBox::valueChanged)
384  , this, [this](const int value) { updateSliderValue(m_ui->sliderUploadLimit, value); });
385  connect(m_ui->spinDownloadLimit, qOverload<int>(&QSpinBox::valueChanged)
386  , this, [this](const int value) { updateSliderValue(m_ui->sliderDownloadLimit, value); });
387 
388  connect(m_ui->checkMaxRatio, &QCheckBox::toggled, m_ui->spinRatioLimit, &QDoubleSpinBox::setEnabled);
389  connect(m_ui->checkMaxTime, &QCheckBox::toggled, m_ui->spinTimeLimit, &QSpinBox::setEnabled);
390 
391  connect(m_ui->buttonGroup, &QButtonGroup::idClicked, this, &TorrentOptionsDialog::handleRatioTypeChanged);
392 
394 }
395 
397 {
398  m_storeDialogSize = size();
399  delete m_ui;
400 }
401 
403 {
404  if (m_ui->radioTorrentLimit->isChecked() && !m_ui->checkMaxRatio->isChecked() && !m_ui->checkMaxTime->isChecked())
405  {
406  QMessageBox::critical(this, tr("No share limit method selected"), tr("Please select a limit method first"));
407  return;
408  }
409 
410  auto *session = BitTorrent::Session::instance();
411  for (const BitTorrent::TorrentID &id : asConst(m_torrentIDs))
412  {
413  BitTorrent::Torrent *torrent = session->findTorrent(id);
414  if (!torrent) continue;
415 
416  if (m_initialValues.autoTMM != m_ui->checkAutoTMM->checkState())
417  torrent->setAutoTMMEnabled(m_ui->checkAutoTMM->isChecked());
418 
419  if (m_ui->checkAutoTMM->checkState() == Qt::Unchecked)
420  {
421  const QString savePath = m_ui->savePath->selectedPath();
422  if (m_initialValues.savePath != savePath)
424 
425  const Qt::CheckState useDownloadPathState = m_ui->checkUseDownloadPath->checkState();
426  if (useDownloadPathState == Qt::Checked)
427  {
428  const QString downloadPath = m_ui->downloadPath->selectedPath();
429  if (m_initialValues.downloadPath != downloadPath)
431  }
432  else if (useDownloadPathState == Qt::Unchecked)
433  {
434  torrent->setDownloadPath(QString());
435  }
436  }
437 
438  const QString category = m_ui->comboCategory->currentText();
439  // index 0 is always the current category
440  if ((m_initialValues.category != category) || (m_ui->comboCategory->currentIndex() != 0))
441  {
442  if (!m_categories.contains(category))
443  session->addCategory(category);
444 
445  torrent->setCategory(category);
446  }
447 
448  if (m_initialValues.upSpeedLimit != m_ui->spinUploadLimit->value())
449  torrent->setUploadLimit(m_ui->spinUploadLimit->value() * 1024);
450  if (m_initialValues.downSpeedLimit != m_ui->spinDownloadLimit->value())
451  torrent->setDownloadLimit(m_ui->spinDownloadLimit->value() * 1024);
452 
453  const qreal ratioLimit = getRatio();
454  if (m_initialValues.ratio != ratioLimit)
455  torrent->setRatioLimit(ratioLimit);
456 
457  const int seedingTimeLimit = getSeedingTime();
458  if (m_initialValues.seedingTime != seedingTimeLimit)
459  torrent->setSeedingTimeLimit(seedingTimeLimit);
460 
461  if (!torrent->isPrivate())
462  {
463  if (m_initialValues.disableDHT != m_ui->checkDisableDHT->checkState())
464  torrent->setDHTDisabled(m_ui->checkDisableDHT->isChecked());
465  if (m_initialValues.disablePEX != m_ui->checkDisablePEX->checkState())
466  torrent->setPEXDisabled(m_ui->checkDisablePEX->isChecked());
467  if (m_initialValues.disableLSD != m_ui->checkDisableLSD->checkState())
468  torrent->setLSDDisabled(m_ui->checkDisableLSD->isChecked());
469  }
470 
471  if (m_initialValues.sequential != m_ui->checkSequential->checkState())
472  torrent->setSequentialDownload(m_ui->checkSequential->isChecked());
473  if (m_initialValues.firstLastPieces != m_ui->checkFirstLastPieces->checkState())
474  torrent->setFirstLastPiecePriority(m_ui->checkFirstLastPieces->isChecked());
475  }
476 
477  QDialog::accept();
478 }
479 
481 {
482  if (m_ui->buttonGroup->checkedId() == -1) // No radio button is selected
483  return MIXED_SHARE_LIMITS;
484 
485  if (m_ui->radioUseGlobalShareLimits->isChecked())
487 
488  if (m_ui->radioNoLimit->isChecked() || !m_ui->checkMaxRatio->isChecked())
490 
491  return m_ui->spinRatioLimit->value();
492 }
493 
495 {
496  if (m_ui->buttonGroup->checkedId() == -1) // No radio button is selected
497  return MIXED_SHARE_LIMITS;
498 
499  if (m_ui->radioUseGlobalShareLimits->isChecked())
501 
502  if (m_ui->radioNoLimit->isChecked() || !m_ui->checkMaxTime->isChecked())
504 
505  return m_ui->spinTimeLimit->value();
506 }
507 
509 {
510  Q_UNUSED(index);
511 
512  if (m_ui->checkAutoTMM->checkState() == Qt::Checked)
513  {
514  if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0))
515  {
516  m_ui->savePath->setSelectedPath(QString());
517  }
518  else
519  {
520  const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText());
521  m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
522  }
523  }
524 
525  if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0))
526  {
527  m_ui->comboCategory->clearEditText();
528  m_ui->comboCategory->lineEdit()->setPlaceholderText(m_currentCategoriesString);
529  }
530  else
531  {
532  m_ui->comboCategory->lineEdit()->setPlaceholderText(QString());
533  }
534 }
535 
537 {
538  if (m_ui->checkAutoTMM->checkState() == Qt::Unchecked)
539  {
540  m_ui->groupBoxSavePath->setEnabled(true);
541  m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(m_initialValues.savePath));
542  m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(m_initialValues.downloadPath));
543  m_ui->checkUseDownloadPath->setCheckState(m_initialValues.useDownloadPath);
544  }
545  else
546  {
547  m_ui->groupBoxSavePath->setEnabled(false);
548  if (m_ui->checkAutoTMM->checkState() == Qt::Checked)
549  {
550  if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0))
551  {
552  m_ui->savePath->setSelectedPath(QString());
553  m_ui->downloadPath->setSelectedPath(QString());
554  m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
555  }
556  else
557  {
558  const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText());
559  m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
560  const QString downloadPath = BitTorrent::Session::instance()->categoryDownloadPath(m_ui->comboCategory->currentText());
561  m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(downloadPath));
562  m_ui->checkUseDownloadPath->setChecked(!downloadPath.isEmpty());
563  }
564  }
565  else // partially checked
566  {
567  m_ui->savePath->setSelectedPath(QString());
568  m_ui->downloadPath->setSelectedPath(QString());
569  m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
570  }
571  }
572 }
573 
575 {
576  const bool isChecked = m_ui->checkUseDownloadPath->checkState() == Qt::Checked;
577  m_ui->downloadPath->setEnabled(isChecked);
578  if (isChecked && m_ui->downloadPath->selectedPath().isEmpty())
579  m_ui->downloadPath->setSelectedPath(BitTorrent::Session::instance()->downloadPath());
580 }
581 
583 {
584  if ((m_initialValues.ratio == MIXED_SHARE_LIMITS) || (m_initialValues.seedingTime == MIXED_SHARE_LIMITS))
585  {
586  QAbstractButton *currentRadio = m_ui->buttonGroup->checkedButton();
587  if (currentRadio && (currentRadio == m_previousRadio))
588  {
589  // Hack to deselect the currently selected radio button programatically because Qt doesn't allow it in exclusive mode
590  m_ui->buttonGroup->setExclusive(false);
591  currentRadio->setChecked(false);
592  m_ui->buttonGroup->setExclusive(true);
593  }
594  m_previousRadio = m_ui->buttonGroup->checkedButton();
595  }
596 
597  m_ui->checkMaxRatio->setEnabled(m_ui->radioTorrentLimit->isChecked());
598  m_ui->checkMaxTime->setEnabled(m_ui->radioTorrentLimit->isChecked());
599 
600  m_ui->spinRatioLimit->setEnabled(m_ui->radioTorrentLimit->isChecked() && m_ui->checkMaxRatio->isChecked());
601  m_ui->spinTimeLimit->setEnabled(m_ui->radioTorrentLimit->isChecked() && m_ui->checkMaxTime->isChecked());
602 }
603 
605 {
606  m_ui->spinUploadLimit->setMinimum(0);
607  m_ui->spinUploadLimit->setSpecialValueText(QString::fromUtf8(C_INFINITY));
608  disconnect(m_ui->spinUploadLimit, qOverload<int>(&QSpinBox::valueChanged)
610 }
611 
613 {
614  m_ui->spinDownloadLimit->setMinimum(0);
615  m_ui->spinDownloadLimit->setSpecialValueText(QString::fromUtf8(C_INFINITY));
616  disconnect(m_ui->spinDownloadLimit, qOverload<int>(&QSpinBox::valueChanged)
618 }
static Session * instance()
Definition: session.cpp:997
QString categorySavePath(const QString &categoryName) const
Definition: session.cpp:669
QString categoryDownloadPath(const QString &categoryName) const
Definition: session.cpp:682
static const int NO_SEEDING_TIME_LIMIT
Definition: torrent.h:108
virtual void setDHTDisabled(bool disable)=0
virtual void setSequentialDownload(bool enable)=0
virtual void setAutoTMMEnabled(bool enabled)=0
virtual void setDownloadPath(const QString &downloadPath)=0
static const int USE_GLOBAL_SEEDING_TIME
Definition: torrent.h:107
virtual void setFirstLastPiecePriority(bool enabled)=0
static const qreal NO_RATIO_LIMIT
Definition: torrent.h:105
virtual void setUploadLimit(int limit)=0
virtual void setSeedingTimeLimit(int limit)=0
virtual void setSavePath(const QString &savePath)=0
virtual bool setCategory(const QString &category)=0
virtual bool isPrivate() const =0
static const qreal USE_GLOBAL_RATIO
Definition: torrent.h:104
virtual void setDownloadLimit(int limit)=0
virtual void setLSDDisabled(bool disable)=0
virtual void setPEXDisabled(bool disable)=0
virtual void setRatioLimit(qreal limit)=0
@ DirectorySave
selecting directories for saving
Ui::TorrentOptionsDialog * m_ui
QAbstractButton * m_previousRadio
struct TorrentOptionsDialog::@10 m_initialValues
SettingValue< QSize > m_storeDialogSize
void handleCategoryChanged(int index)
QVector< BitTorrent::TorrentID > m_torrentIDs
TorrentOptionsDialog(QWidget *parent, const QVector< BitTorrent::Torrent * > &torrents)
constexpr std::add_const_t< T > & asConst(T &t) noexcept
Definition: global.h:42
QString expandPathAbs(const QString &path)
Definition: fs.cpp:309
QString toNativePath(const QString &path)
Definition: fs.cpp:64
void resize(QWidget *widget, const QSize &newSize={})
Definition: utils.cpp:54
void setValue(const QString &key, const T &value)
Definition: preferences.cpp:76
T value(const QString &key, const T &defaultValue={})
Definition: preferences.cpp:64
void updateSliderValue(QSlider *slider, const int value)
#define SETTINGS_KEY(name)
const char C_INEQUALITY[]
const char C_INFINITY[]