Sync translations from Transifex and run lupdate
[qBittorrent.git] / src / gui / torrentoptionsdialog.cpp
blob49ac52cf7688b5f6e0d5e0da60e510d8366eb610
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>
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>
34 #include <QString>
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"
42 #include "utils.h"
44 #define SETTINGS_KEY(name) "TorrentOptionsDialog/" name
46 namespace
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)
59 : QDialog {parent}
60 , m_ui {new Ui::TorrentOptionsDialog}
61 , m_storeDialogSize {SETTINGS_KEY("Size")}
63 m_ui->setupUi(this);
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();
84 if (allSameUpLimit)
86 if (qMax(0, torrent->uploadLimit()) != firstTorrentUpLimit)
87 allSameUpLimit = false;
89 if (allSameDownLimit)
91 if (qMax(0, torrent->downloadLimit()) != firstTorrentDownLimit)
92 allSameDownLimit = false;
94 if (allSameRatio)
96 if (torrent->ratioLimit() != firstTorrentRatio)
97 allSameRatio = false;
99 if (allSameSeedingTime)
101 if (torrent->seedingTimeLimit() != firstTorrentSeedingTime)
102 allSameSeedingTime = false;
104 if (allTorrentsArePrivate)
106 if (!torrent->isPrivate())
107 allTorrentsArePrivate = false;
109 if (allSameDHT)
111 if (torrent->isDHTDisabled() != isFirstTorrentDHTDisabled)
113 m_ui->checkDisableDHT->setCheckState(Qt::PartiallyChecked);
114 allSameDHT = false;
117 if (allSamePEX)
119 if (torrent->isPEXDisabled() != isFirstTorrentPEXDisabled)
121 m_ui->checkDisablePEX->setCheckState(Qt::PartiallyChecked);
122 allSamePEX = false;
125 if (allSameLSD)
127 if (torrent->isLSDDisabled() != isFirstTorrentLSDDisabled)
129 m_ui->checkDisableLSD->setCheckState(Qt::PartiallyChecked);
130 allSameLSD = false;
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));
156 if (allSameUpLimit)
158 m_ui->spinUploadLimit->setValue(uploadVal);
160 else
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);
175 else
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);
203 else
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);
229 else
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);
244 m_initialValues =
246 getRatio(),
247 getSeedingTime(),
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();
274 delete m_ui;
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"));
282 return;
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());
315 QDialog::accept();
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);