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"
33 #include <QMessageBox>
36 #include "base/bittorrent/infohash.h"
37 #include "base/bittorrent/session.h"
38 #include "base/bittorrent/torrent.h"
39 #include "base/global.h"
40 #include "base/unicodestrings.h"
41 #include "ui_torrentoptionsdialog.h"
44 #define SETTINGS_KEY(name) "TorrentOptionsDialog/" name
48 const int MIXED_SHARE_LIMITS
= -9;
50 void updateSliderValue(QSlider
*slider
, const int value
)
52 if (value
> slider
->maximum())
53 slider
->setMaximum(value
);
54 slider
->setValue(value
);
58 TorrentOptionsDialog::TorrentOptionsDialog(QWidget
*parent
, const QVector
<BitTorrent::Torrent
*> &torrents
)
60 , m_ui
{new Ui::TorrentOptionsDialog
}
61 , m_storeDialogSize
{SETTINGS_KEY("Size")}
65 Q_ASSERT(!torrents
.empty());
66 const auto *session
= BitTorrent::Session::instance();
67 bool allSameUpLimit
= true, allSameDownLimit
= true, allSameRatio
= true, allSameSeedingTime
= true
68 , allTorrentsArePrivate
= true, allSameDHT
= true, allSamePEX
= true, allSameLSD
= true;
70 const int firstTorrentUpLimit
= qMax(0, torrents
[0]->uploadLimit());
71 const int firstTorrentDownLimit
= qMax(0, torrents
[0]->downloadLimit());
73 const qreal firstTorrentRatio
= torrents
[0]->ratioLimit();
74 const int firstTorrentSeedingTime
= torrents
[0]->seedingTimeLimit();
76 const bool isFirstTorrentDHTDisabled
= torrents
[0]->isDHTDisabled();
77 const bool isFirstTorrentPEXDisabled
= torrents
[0]->isPEXDisabled();
78 const bool isFirstTorrentLSDDisabled
= torrents
[0]->isLSDDisabled();
80 m_torrentIDs
.reserve(torrents
.size());
81 for (const BitTorrent::Torrent
*torrent
: torrents
)
83 m_torrentIDs
<< torrent
->id();
86 if (qMax(0, torrent
->uploadLimit()) != firstTorrentUpLimit
)
87 allSameUpLimit
= false;
91 if (qMax(0, torrent
->downloadLimit()) != firstTorrentDownLimit
)
92 allSameDownLimit
= false;
96 if (torrent
->ratioLimit() != firstTorrentRatio
)
99 if (allSameSeedingTime
)
101 if (torrent
->seedingTimeLimit() != firstTorrentSeedingTime
)
102 allSameSeedingTime
= false;
104 if (allTorrentsArePrivate
)
106 if (!torrent
->isPrivate())
107 allTorrentsArePrivate
= false;
111 if (torrent
->isDHTDisabled() != isFirstTorrentDHTDisabled
)
113 m_ui
->checkDisableDHT
->setCheckState(Qt::PartiallyChecked
);
119 if (torrent
->isPEXDisabled() != isFirstTorrentPEXDisabled
)
121 m_ui
->checkDisablePEX
->setCheckState(Qt::PartiallyChecked
);
127 if (torrent
->isLSDDisabled() != isFirstTorrentLSDDisabled
)
129 m_ui
->checkDisableLSD
->setCheckState(Qt::PartiallyChecked
);
135 const bool isAltLimitEnabled
= session
->isAltGlobalSpeedLimitEnabled();
136 const int globalUploadLimit
= isAltLimitEnabled
137 ? (session
->altGlobalUploadSpeedLimit() / 1024)
138 : (session
->globalUploadSpeedLimit() / 1024);
139 const int globalDownloadLimit
= isAltLimitEnabled
140 ? (session
->altGlobalDownloadSpeedLimit() / 1024)
141 : (session
->globalDownloadSpeedLimit() / 1024);
143 const int uploadVal
= qMax(0, (firstTorrentUpLimit
/ 1024));
144 const int downloadVal
= qMax(0, (firstTorrentDownLimit
/ 1024));
145 int maxUpload
= (globalUploadLimit
<= 0) ? 10000 : globalUploadLimit
;
146 int maxDownload
= (globalDownloadLimit
<= 0) ? 10000 : globalDownloadLimit
;
148 // This can happen for example if global rate limit is lower than torrent rate limit.
149 if (uploadVal
> maxUpload
)
150 maxUpload
= uploadVal
;
151 if (downloadVal
> maxDownload
)
152 maxDownload
= downloadVal
;
154 m_ui
->sliderUploadLimit
->setMaximum(maxUpload
);
155 m_ui
->sliderUploadLimit
->setValue(allSameUpLimit
? uploadVal
: (maxUpload
/ 2));
158 m_ui
->spinUploadLimit
->setValue(uploadVal
);
162 m_ui
->spinUploadLimit
->setSpecialValueText(QString::fromUtf8(C_INEQUALITY
));
163 m_ui
->spinUploadLimit
->setMinimum(-1);
164 m_ui
->spinUploadLimit
->setValue(-1);
165 connect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
166 , this, &TorrentOptionsDialog::handleUpSpeedLimitChanged
);
169 m_ui
->sliderDownloadLimit
->setMaximum(maxDownload
);
170 m_ui
->sliderDownloadLimit
->setValue(allSameDownLimit
? downloadVal
: (maxDownload
/ 2));
171 if (allSameDownLimit
)
173 m_ui
->spinDownloadLimit
->setValue(downloadVal
);
177 m_ui
->spinDownloadLimit
->setSpecialValueText(QString::fromUtf8(C_INEQUALITY
));
178 m_ui
->spinDownloadLimit
->setMinimum(-1);
179 m_ui
->spinDownloadLimit
->setValue(-1);
180 connect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
181 , this, &TorrentOptionsDialog::handleDownSpeedLimitChanged
);
184 const bool useGlobalValue
= allSameRatio
&& allSameSeedingTime
185 && (firstTorrentRatio
== BitTorrent::Torrent::USE_GLOBAL_RATIO
)
186 && (firstTorrentSeedingTime
== BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME
);
188 if (!allSameRatio
|| !allSameSeedingTime
)
190 m_ui
->radioUseGlobalShareLimits
->setChecked(false);
191 m_ui
->radioNoLimit
->setChecked(false);
192 m_ui
->radioTorrentLimit
->setChecked(false);
194 else if (useGlobalValue
)
196 m_ui
->radioUseGlobalShareLimits
->setChecked(true);
198 else if ((firstTorrentRatio
== BitTorrent::Torrent::NO_RATIO_LIMIT
)
199 && (firstTorrentSeedingTime
== BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT
))
201 m_ui
->radioNoLimit
->setChecked(true);
205 m_ui
->radioTorrentLimit
->setChecked(true);
206 if (firstTorrentRatio
>= 0)
207 m_ui
->checkMaxRatio
->setChecked(true);
208 if (firstTorrentSeedingTime
>= 0)
209 m_ui
->checkMaxTime
->setChecked(true);
212 const qreal maxRatio
= (allSameRatio
&& (firstTorrentRatio
>= 0))
213 ? firstTorrentRatio
: session
->globalMaxRatio();
214 const int maxSeedingTime
= (allSameSeedingTime
&& (firstTorrentSeedingTime
>= 0))
215 ? firstTorrentSeedingTime
: session
->globalMaxSeedingMinutes();
216 m_ui
->spinRatioLimit
->setValue(maxRatio
);
217 m_ui
->spinTimeLimit
->setValue(maxSeedingTime
);
218 handleRatioTypeChanged();
220 if (!allTorrentsArePrivate
)
222 if (m_ui
->checkDisableDHT
->checkState() != Qt::PartiallyChecked
)
223 m_ui
->checkDisableDHT
->setChecked(isFirstTorrentDHTDisabled
);
224 if (m_ui
->checkDisablePEX
->checkState() != Qt::PartiallyChecked
)
225 m_ui
->checkDisablePEX
->setChecked(isFirstTorrentPEXDisabled
);
226 if (m_ui
->checkDisableLSD
->checkState() != Qt::PartiallyChecked
)
227 m_ui
->checkDisableLSD
->setChecked(isFirstTorrentLSDDisabled
);
231 m_ui
->checkDisableDHT
->setChecked(true);
232 m_ui
->checkDisableDHT
->setEnabled(false);
233 m_ui
->checkDisablePEX
->setChecked(true);
234 m_ui
->checkDisablePEX
->setEnabled(false);
235 m_ui
->checkDisableLSD
->setChecked(true);
236 m_ui
->checkDisableLSD
->setEnabled(false);
239 const QString privateTorrentsTooltip
= tr("Not applicable to private torrents");
240 m_ui
->checkDisableDHT
->setToolTip(privateTorrentsTooltip
);
241 m_ui
->checkDisablePEX
->setToolTip(privateTorrentsTooltip
);
242 m_ui
->checkDisableLSD
->setToolTip(privateTorrentsTooltip
);
248 m_ui
->spinUploadLimit
->value(),
249 m_ui
->spinDownloadLimit
->value(),
250 m_ui
->checkDisableDHT
->checkState(),
251 m_ui
->checkDisablePEX
->checkState(),
252 m_ui
->checkDisableLSD
->checkState()
255 // Sync up/down speed limit sliders with their corresponding spinboxes
256 connect(m_ui
->sliderUploadLimit
, &QSlider::valueChanged
, m_ui
->spinUploadLimit
, &QSpinBox::setValue
);
257 connect(m_ui
->sliderDownloadLimit
, &QSlider::valueChanged
, m_ui
->spinDownloadLimit
, &QSpinBox::setValue
);
258 connect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
259 , this, [this](const int value
) { updateSliderValue(m_ui
->sliderUploadLimit
, value
); });
260 connect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
261 , this, [this](const int value
) { updateSliderValue(m_ui
->sliderDownloadLimit
, value
); });
263 connect(m_ui
->checkMaxRatio
, &QCheckBox::toggled
, m_ui
->spinRatioLimit
, &QDoubleSpinBox::setEnabled
);
264 connect(m_ui
->checkMaxTime
, &QCheckBox::toggled
, m_ui
->spinTimeLimit
, &QSpinBox::setEnabled
);
266 connect(m_ui
->buttonGroup
, &QButtonGroup::idClicked
, this, &TorrentOptionsDialog::handleRatioTypeChanged
);
268 Utils::Gui::resize(this, m_storeDialogSize
);
271 TorrentOptionsDialog::~TorrentOptionsDialog()
273 m_storeDialogSize
= size();
277 void TorrentOptionsDialog::accept()
279 if (m_ui
->radioTorrentLimit
->isChecked() && !m_ui
->checkMaxRatio
->isChecked() && !m_ui
->checkMaxTime
->isChecked())
281 QMessageBox::critical(this, tr("No share limit method selected"), tr("Please select a limit method first"));
285 const auto *session
= BitTorrent::Session::instance();
286 for (const BitTorrent::TorrentID
&id
: asConst(m_torrentIDs
))
288 BitTorrent::Torrent
*torrent
= session
->findTorrent(id
);
289 if (!torrent
) continue;
291 if (m_initialValues
.upSpeedLimit
!= m_ui
->spinUploadLimit
->value())
292 torrent
->setUploadLimit(m_ui
->spinUploadLimit
->value() * 1024);
293 if (m_initialValues
.downSpeedLimit
!= m_ui
->spinDownloadLimit
->value())
294 torrent
->setDownloadLimit(m_ui
->spinDownloadLimit
->value() * 1024);
296 const qreal ratioLimit
= getRatio();
297 if (m_initialValues
.ratio
!= ratioLimit
)
298 torrent
->setRatioLimit(ratioLimit
);
300 const int seedingTimeLimit
= getSeedingTime();
301 if (m_initialValues
.seedingTime
!= seedingTimeLimit
)
302 torrent
->setSeedingTimeLimit(seedingTimeLimit
);
304 if (!torrent
->isPrivate())
306 if (m_initialValues
.disableDHT
!= m_ui
->checkDisableDHT
->checkState())
307 torrent
->setDHTDisabled(m_ui
->checkDisableDHT
->isChecked());
308 if (m_initialValues
.disablePEX
!= m_ui
->checkDisablePEX
->checkState())
309 torrent
->setPEXDisabled(m_ui
->checkDisablePEX
->isChecked());
310 if (m_initialValues
.disableLSD
!= m_ui
->checkDisableLSD
->checkState())
311 torrent
->setLSDDisabled(m_ui
->checkDisableLSD
->isChecked());
318 qreal
TorrentOptionsDialog::getRatio() const
320 if (m_ui
->buttonGroup
->checkedId() == -1) // No radio button is selected
321 return MIXED_SHARE_LIMITS
;
323 if (m_ui
->radioUseGlobalShareLimits
->isChecked())
324 return BitTorrent::Torrent::USE_GLOBAL_RATIO
;
326 if (m_ui
->radioNoLimit
->isChecked() || !m_ui
->checkMaxRatio
->isChecked())
327 return BitTorrent::Torrent::NO_RATIO_LIMIT
;
329 return m_ui
->spinRatioLimit
->value();
332 int TorrentOptionsDialog::getSeedingTime() const
334 if (m_ui
->buttonGroup
->checkedId() == -1) // No radio button is selected
335 return MIXED_SHARE_LIMITS
;
337 if (m_ui
->radioUseGlobalShareLimits
->isChecked())
338 return BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME
;
340 if (m_ui
->radioNoLimit
->isChecked() || !m_ui
->checkMaxTime
->isChecked())
341 return BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT
;
343 return m_ui
->spinTimeLimit
->value();
346 void TorrentOptionsDialog::handleRatioTypeChanged()
348 m_ui
->checkMaxRatio
->setEnabled(m_ui
->radioTorrentLimit
->isChecked());
349 m_ui
->checkMaxTime
->setEnabled(m_ui
->radioTorrentLimit
->isChecked());
351 m_ui
->spinRatioLimit
->setEnabled(m_ui
->radioTorrentLimit
->isChecked() && m_ui
->checkMaxRatio
->isChecked());
352 m_ui
->spinTimeLimit
->setEnabled(m_ui
->radioTorrentLimit
->isChecked() && m_ui
->checkMaxTime
->isChecked());
355 void TorrentOptionsDialog::handleUpSpeedLimitChanged()
357 m_ui
->spinUploadLimit
->setMinimum(0);
358 m_ui
->spinUploadLimit
->setSpecialValueText(QString::fromUtf8(C_INFINITY
));
359 disconnect(m_ui
->spinUploadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
360 , this, &TorrentOptionsDialog::handleUpSpeedLimitChanged
);
363 void TorrentOptionsDialog::handleDownSpeedLimitChanged()
365 m_ui
->spinDownloadLimit
->setMinimum(0);
366 m_ui
->spinDownloadLimit
->setSpecialValueText(QString::fromUtf8(C_INFINITY
));
367 disconnect(m_ui
->spinDownloadLimit
, qOverload
<int>(&QSpinBox::valueChanged
)
368 , this, &TorrentOptionsDialog::handleDownSpeedLimitChanged
);