From 046d6f3bc1901a0fa455649121f6c0e89b8e8647 Mon Sep 17 00:00:00 2001 From: thalieht Date: Sat, 11 Sep 2021 00:56:56 +0300 Subject: [PATCH 1/2] Move a few torrent context menu actions into "Torrent options" dialog Automatic torrent management Save path Category Download in sequential order Download first and last pieces first closes #15447, closes #14064 --- src/gui/torrentoptionsdialog.cpp | 199 ++++++++++++++++++++++++++++--- src/gui/torrentoptionsdialog.h | 11 ++ src/gui/torrentoptionsdialog.ui | 83 ++++++++++++- src/gui/transferlistwidget.cpp | 87 +------------- src/gui/transferlistwidget.h | 3 - 5 files changed, 277 insertions(+), 106 deletions(-) diff --git a/src/gui/torrentoptionsdialog.cpp b/src/gui/torrentoptionsdialog.cpp index 49ac52cf7..bd2ce39a1 100644 --- a/src/gui/torrentoptionsdialog.cpp +++ b/src/gui/torrentoptionsdialog.cpp @@ -30,6 +30,7 @@ #include "torrentoptionsdialog.h" +#include #include #include @@ -38,6 +39,7 @@ #include "base/bittorrent/torrent.h" #include "base/global.h" #include "base/unicodestrings.h" +#include "base/utils/fs.h" #include "ui_torrentoptionsdialog.h" #include "utils.h" @@ -59,13 +61,22 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorsetupUi(this); + m_ui->savePath->setMode(FileSystemPathEdit::Mode::DirectorySave); + m_ui->savePath->setDialogCaption(tr("Choose save path")); Q_ASSERT(!torrents.empty()); + const auto *session = BitTorrent::Session::instance(); bool allSameUpLimit = true, allSameDownLimit = true, allSameRatio = true, allSameSeedingTime = true - , allTorrentsArePrivate = true, allSameDHT = true, allSamePEX = true, allSameLSD = true; + , allTorrentsArePrivate = true, allSameDHT = true, allSamePEX = true, allSameLSD = true + , allSameSequential = true, allSameFirstLastPieces = true, allSameAutoTMM = true, allSameSavePath = true; + + const bool isFirstTorrentAutoTMMEnabled = torrents[0]->isAutoTMMEnabled(); + const QString firstTorrentSavePath = torrents[0]->savePath(); + const QString firstTorrentCategory = torrents[0]->category(); const int firstTorrentUpLimit = qMax(0, torrents[0]->uploadLimit()); const int firstTorrentDownLimit = qMax(0, torrents[0]->downloadLimit()); @@ -76,11 +87,29 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorisDHTDisabled(); const bool isFirstTorrentPEXDisabled = torrents[0]->isPEXDisabled(); const bool isFirstTorrentLSDDisabled = torrents[0]->isLSDDisabled(); + const bool isFirstTorrentSequentialEnabled = torrents[0]->isSequentialDownload(); + const bool isFirstTorrentFirstLastPiecesEnabled = torrents[0]->hasFirstLastPiecePriority(); m_torrentIDs.reserve(torrents.size()); for (const BitTorrent::Torrent *torrent : torrents) { m_torrentIDs << torrent->id(); + + if (allSameAutoTMM) + { + if (torrent->isAutoTMMEnabled() != isFirstTorrentAutoTMMEnabled) + allSameAutoTMM = false; + } + if (allSameSavePath) + { + if (torrent->savePath() != firstTorrentSavePath) + allSameSavePath = false; + } + if (m_allSameCategory) + { + if (torrent->category() != firstTorrentCategory) + m_allSameCategory = false; + } if (allSameUpLimit) { if (qMax(0, torrent->uploadLimit()) != firstTorrentUpLimit) @@ -109,27 +138,59 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorisDHTDisabled() != isFirstTorrentDHTDisabled) - { - m_ui->checkDisableDHT->setCheckState(Qt::PartiallyChecked); allSameDHT = false; - } } if (allSamePEX) { if (torrent->isPEXDisabled() != isFirstTorrentPEXDisabled) - { - m_ui->checkDisablePEX->setCheckState(Qt::PartiallyChecked); allSamePEX = false; - } } if (allSameLSD) { if (torrent->isLSDDisabled() != isFirstTorrentLSDDisabled) - { - m_ui->checkDisableLSD->setCheckState(Qt::PartiallyChecked); allSameLSD = false; - } } + if (allSameSequential) + { + if (torrent->isSequentialDownload() != isFirstTorrentSequentialEnabled) + allSameSequential = false; + } + if (allSameFirstLastPieces) + { + if (torrent->hasFirstLastPiecePriority() != isFirstTorrentFirstLastPiecesEnabled) + allSameFirstLastPieces = false; + } + } + + if (allSameAutoTMM) + m_ui->checkAutoTMM->setChecked(isFirstTorrentAutoTMMEnabled); + else + m_ui->checkAutoTMM->setCheckState(Qt::PartiallyChecked); + + if (allSameSavePath) + m_ui->savePath->setSelectedPath(firstTorrentSavePath); + + if (!m_allSameCategory) + { + m_ui->comboCategory->addItem(m_currentCategoriesString); + m_ui->comboCategory->clearEditText(); + m_ui->comboCategory->lineEdit()->setPlaceholderText(m_currentCategoriesString); + } + else if (!firstTorrentCategory.isEmpty()) + { + m_ui->comboCategory->setCurrentText(firstTorrentCategory); + m_ui->comboCategory->addItem(firstTorrentCategory); + } + m_ui->comboCategory->addItem(QString()); + + m_categories = session->categories().keys(); + std::sort(m_categories.begin(), m_categories.end(), Utils::Compare::NaturalLessThan()); + for (const QString &category : asConst(m_categories)) + { + if (m_allSameCategory && (category == firstTorrentCategory)) + continue; + + m_ui->comboCategory->addItem(category); } const bool isAltLimitEnabled = session->isAltGlobalSpeedLimitEnabled(); @@ -219,12 +280,20 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorcheckDisableDHT->checkState() != Qt::PartiallyChecked) + if (allSameDHT) m_ui->checkDisableDHT->setChecked(isFirstTorrentDHTDisabled); - if (m_ui->checkDisablePEX->checkState() != Qt::PartiallyChecked) + else + m_ui->checkDisableDHT->setCheckState(Qt::PartiallyChecked); + + if (allSamePEX) m_ui->checkDisablePEX->setChecked(isFirstTorrentPEXDisabled); - if (m_ui->checkDisableLSD->checkState() != Qt::PartiallyChecked) + else + m_ui->checkDisablePEX->setCheckState(Qt::PartiallyChecked); + + if (allSameLSD) m_ui->checkDisableLSD->setChecked(isFirstTorrentLSDDisabled); + else + m_ui->checkDisableLSD->setCheckState(Qt::PartiallyChecked); } else { @@ -241,17 +310,38 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorcheckDisablePEX->setToolTip(privateTorrentsTooltip); m_ui->checkDisableLSD->setToolTip(privateTorrentsTooltip); + if (allSameSequential) + m_ui->checkSequential->setChecked(isFirstTorrentSequentialEnabled); + else + m_ui->checkSequential->setCheckState(Qt::PartiallyChecked); + + if (allSameFirstLastPieces) + m_ui->checkFirstLastPieces->setChecked(isFirstTorrentFirstLastPiecesEnabled); + else + m_ui->checkFirstLastPieces->setCheckState(Qt::PartiallyChecked); + m_initialValues = { + m_ui->savePath->selectedPath(), + m_ui->comboCategory->currentText(), getRatio(), getSeedingTime(), m_ui->spinUploadLimit->value(), m_ui->spinDownloadLimit->value(), + m_ui->checkAutoTMM->checkState(), m_ui->checkDisableDHT->checkState(), m_ui->checkDisablePEX->checkState(), - m_ui->checkDisableLSD->checkState() + m_ui->checkDisableLSD->checkState(), + m_ui->checkSequential->checkState(), + m_ui->checkFirstLastPieces->checkState() }; + // Needs to be called after the initial values struct is initialized + handleTMMChanged(); + + connect(m_ui->checkAutoTMM, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleTMMChanged); + connect(m_ui->comboCategory, &QComboBox::activated, this, &TorrentOptionsDialog::handleCategoryChanged); + // Sync up/down speed limit sliders with their corresponding spinboxes connect(m_ui->sliderUploadLimit, &QSlider::valueChanged, m_ui->spinUploadLimit, &QSpinBox::setValue); connect(m_ui->sliderDownloadLimit, &QSlider::valueChanged, m_ui->spinDownloadLimit, &QSpinBox::setValue); @@ -282,12 +372,27 @@ void TorrentOptionsDialog::accept() return; } - const auto *session = BitTorrent::Session::instance(); + auto *session = BitTorrent::Session::instance(); for (const BitTorrent::TorrentID &id : asConst(m_torrentIDs)) { BitTorrent::Torrent *torrent = session->findTorrent(id); if (!torrent) continue; + const QString savePath = m_ui->savePath->selectedPath(); + if (m_initialValues.autoTMM != m_ui->checkAutoTMM->checkState()) + torrent->setAutoTMMEnabled(m_ui->checkAutoTMM->isChecked()); + if (!m_ui->checkAutoTMM->isChecked() && (m_initialValues.savePath != savePath)) + torrent->move(Utils::Fs::expandPathAbs(savePath)); + const QString category = m_ui->comboCategory->currentText(); + // index 0 is always the current category + if ((m_initialValues.category != category) || (m_ui->comboCategory->currentIndex() != 0)) + { + if (!m_categories.contains(category)) + session->addCategory(category); + + torrent->setCategory(category); + } + if (m_initialValues.upSpeedLimit != m_ui->spinUploadLimit->value()) torrent->setUploadLimit(m_ui->spinUploadLimit->value() * 1024); if (m_initialValues.downSpeedLimit != m_ui->spinDownloadLimit->value()) @@ -310,6 +415,11 @@ void TorrentOptionsDialog::accept() if (m_initialValues.disableLSD != m_ui->checkDisableLSD->checkState()) torrent->setLSDDisabled(m_ui->checkDisableLSD->isChecked()); } + + if (m_initialValues.sequential != m_ui->checkSequential->checkState()) + torrent->setSequentialDownload(m_ui->checkSequential->isChecked()); + if (m_initialValues.firstLastPieces != m_ui->checkFirstLastPieces->checkState()) + torrent->setFirstLastPiecePriority(m_ui->checkFirstLastPieces->isChecked()); } QDialog::accept(); @@ -343,6 +453,65 @@ int TorrentOptionsDialog::getSeedingTime() const return m_ui->spinTimeLimit->value(); } +void TorrentOptionsDialog::handleCategoryChanged(const int index) +{ + Q_UNUSED(index); + + if (m_ui->checkAutoTMM->checkState() == Qt::Checked) + { + if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0)) + { + m_ui->savePath->setSelectedPath(QString()); + } + else + { + const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText()); + m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath)); + } + } + + if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0)) + { + m_ui->comboCategory->clearEditText(); + m_ui->comboCategory->lineEdit()->setPlaceholderText(m_currentCategoriesString); + } + else + { + m_ui->comboCategory->lineEdit()->setPlaceholderText(QString()); + } +} + +void TorrentOptionsDialog::handleTMMChanged() +{ + if (m_ui->checkAutoTMM->checkState() == Qt::Unchecked) + { + m_ui->labelSavePath->setEnabled(true); + m_ui->savePath->setEnabled(true); + m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(m_initialValues.savePath)); + } + else + { + m_ui->labelSavePath->setEnabled(false); + m_ui->savePath->setEnabled(false); + if (m_ui->checkAutoTMM->checkState() == Qt::Checked) + { + if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0)) + { + m_ui->savePath->setSelectedPath(QString()); + } + else + { + const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText()); + m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath)); + } + } + else // partially checked + { + m_ui->savePath->setSelectedPath(QString()); + } + } +} + void TorrentOptionsDialog::handleRatioTypeChanged() { m_ui->checkMaxRatio->setEnabled(m_ui->radioTorrentLimit->isChecked()); diff --git a/src/gui/torrentoptionsdialog.h b/src/gui/torrentoptionsdialog.h index f37d63e0e..09fbe86cc 100644 --- a/src/gui/torrentoptionsdialog.h +++ b/src/gui/torrentoptionsdialog.h @@ -58,6 +58,9 @@ public slots: void accept() override; private slots: + void handleCategoryChanged(int index); + void handleTMMChanged(); + void handleUpSpeedLimitChanged(); void handleDownSpeedLimitChanged(); @@ -70,14 +73,22 @@ private: QVector m_torrentIDs; Ui::TorrentOptionsDialog *m_ui; SettingValue m_storeDialogSize; + QStringList m_categories; + QString m_currentCategoriesString; + bool m_allSameCategory = true; struct { + QString savePath; + QString category; qreal ratio; int seedingTime; int upSpeedLimit; int downSpeedLimit; + Qt::CheckState autoTMM; Qt::CheckState disableDHT; Qt::CheckState disablePEX; Qt::CheckState disableLSD; + Qt::CheckState sequential; + Qt::CheckState firstLastPieces; } m_initialValues; }; diff --git a/src/gui/torrentoptionsdialog.ui b/src/gui/torrentoptionsdialog.ui index b033d5c92..29a346856 100644 --- a/src/gui/torrentoptionsdialog.ui +++ b/src/gui/torrentoptionsdialog.ui @@ -6,14 +6,71 @@ 0 0 - 390 - 450 + 450 + 540 Torrent Options + + + + Automatic mode means that various torrent properties (e.g. save path) will be decided by the associated category + + + Automatic Torrent Management + + + + + + + + + Save path: + + + + + + + + 0 + 0 + + + + + + + + Category: + + + + + + + + 0 + 0 + + + + true + + + 2147483647 + + + QComboBox::InsertAtTop + + + + + @@ -187,6 +244,13 @@ + + + Download in sequential order + + + + Qt::Horizontal @@ -206,6 +270,13 @@ + + + + Download first and last pieces first + + + @@ -237,6 +308,14 @@ + + + FileSystemPathLineEdit + QWidget +
gui/fspathedit.h
+ 1 +
+
diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index 4592ca413..e467ba00d 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -328,21 +328,6 @@ QVector TransferListWidget::getVisibleTorrents() const return torrents; } -void TransferListWidget::setSelectedTorrentsLocation() -{ - const QVector torrents = getSelectedTorrents(); - if (torrents.isEmpty()) return; - - const QString oldLocation = torrents[0]->savePath(); - const QString newLocation = QFileDialog::getExistingDirectory(this, tr("Choose save path"), oldLocation, - QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails); - if (newLocation.isEmpty() || !QDir(newLocation).exists()) return; - - // Actually move storage - for (BitTorrent::Torrent *const torrent : torrents) - torrent->move(Utils::Fs::expandPathAbs(newLocation)); -} - void TransferListWidget::pauseAllTorrents() { for (BitTorrent::Torrent *const torrent : asConst(BitTorrent::Session::instance()->torrents())) @@ -659,18 +644,6 @@ void TransferListWidget::setSelectedTorrentsSuperSeeding(const bool enabled) con } } -void TransferListWidget::setSelectedTorrentsSequentialDownload(const bool enabled) const -{ - for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents())) - torrent->setSequentialDownload(enabled); -} - -void TransferListWidget::setSelectedFirstLastPiecePrio(const bool enabled) const -{ - for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents())) - torrent->setFirstLastPiecePriority(enabled); -} - void TransferListWidget::setSelectedAutoTMMEnabled(const bool enabled) const { for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents())) @@ -845,8 +818,6 @@ void TransferListWidget::displayListMenu(const QPoint &) connect(actionTopQueuePos, &QAction::triggered, this, &TransferListWidget::topQueuePosSelectedTorrents); auto *actionBottomQueuePos = new QAction(UIThemeManager::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), listMenu); connect(actionBottomQueuePos, &QAction::triggered, this, &TransferListWidget::bottomQueuePosSelectedTorrents); - auto *actionSetTorrentPath = new QAction(UIThemeManager::instance()->getIcon("inode-directory"), tr("Set location..."), listMenu); - connect(actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation); auto *actionForceRecheck = new QAction(UIThemeManager::instance()->getIcon("document-edit-verify"), tr("Force recheck"), listMenu); connect(actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents); auto *actionForceReannounce = new QAction(UIThemeManager::instance()->getIcon("document-edit-verify"), tr("Force reannounce"), listMenu); @@ -865,13 +836,6 @@ void TransferListWidget::displayListMenu(const QPoint &) connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSuperSeeding); auto *actionRename = new QAction(UIThemeManager::instance()->getIcon("edit-rename"), tr("Rename..."), listMenu); connect(actionRename, &QAction::triggered, this, &TransferListWidget::renameSelectedTorrent); - auto *actionSequentialDownload = new TriStateAction(tr("Download in sequential order"), listMenu); - connect(actionSequentialDownload, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsSequentialDownload); - auto *actionFirstLastPiecePrio = new TriStateAction(tr("Download first and last pieces first"), listMenu); - connect(actionFirstLastPiecePrio, &QAction::triggered, this, &TransferListWidget::setSelectedFirstLastPiecePrio); - auto *actionAutoTMM = new TriStateAction(tr("Automatic Torrent Management"), listMenu); - actionAutoTMM->setToolTip(tr("Automatic mode means that various torrent properties(eg save path) will be decided by the associated category")); - connect(actionAutoTMM, &QAction::triggered, this, &TransferListWidget::setSelectedAutoTMMEnabled); auto *actionEditTracker = new QAction(UIThemeManager::instance()->getIcon("edit-rename"), tr("Edit trackers..."), listMenu); connect(actionEditTracker, &QAction::triggered, this, &TransferListWidget::editTorrentTrackers); // End of actions @@ -884,8 +848,6 @@ void TransferListWidget::displayListMenu(const QPoint &) bool sequentialDownloadMode = false, prioritizeFirstLast = false; bool oneHasMetadata = false, oneNotSeed = false; bool allSameCategory = true; - bool allSameAutoTMM = true; - bool firstAutoTMM = false; QString firstCategory; bool first = true; TagSet tagsInAny; @@ -909,7 +871,6 @@ void TransferListWidget::displayListMenu(const QPoint &) if (first) { - firstAutoTMM = torrent->isAutoTMMEnabled(); tagsInAll = torrentTags; } else @@ -917,9 +878,6 @@ void TransferListWidget::displayListMenu(const QPoint &) tagsInAll.intersect(torrentTags); } - if (firstAutoTMM != torrent->isAutoTMMEnabled()) - allSameAutoTMM = false; - if (torrent->hasMetadata()) oneHasMetadata = true; if (!torrent->isSeed()) @@ -979,7 +937,7 @@ void TransferListWidget::displayListMenu(const QPoint &) if (oneHasMetadata && oneNotSeed && !allSameSequentialDownloadMode && !allSamePrioFirstlast && !allSameSuperSeeding && !allSameCategory - && needsStart && needsForce && needsPause && needsPreview && !allSameAutoTMM + && needsStart && needsForce && needsPause && needsPreview && hasInfohashV1 && hasInfohashV2) { break; @@ -995,36 +953,10 @@ void TransferListWidget::displayListMenu(const QPoint &) listMenu->addSeparator(); listMenu->addAction(actionDelete); listMenu->addSeparator(); - listMenu->addAction(actionSetTorrentPath); if (selectedIndexes.size() == 1) listMenu->addAction(actionRename); listMenu->addAction(actionEditTracker); - // Category Menu - QStringList categories = BitTorrent::Session::instance()->categories().keys(); - std::sort(categories.begin(), categories.end(), Utils::Compare::NaturalLessThan()); - - QMenu *categoryMenu = listMenu->addMenu(UIThemeManager::instance()->getIcon("view-categories"), tr("Category")); - - categoryMenu->addAction(UIThemeManager::instance()->getIcon("list-add"), tr("New...", "New category...") - , this, &TransferListWidget::askNewCategoryForSelection); - categoryMenu->addAction(UIThemeManager::instance()->getIcon("edit-clear"), tr("Reset", "Reset category") - , this, [this]() { setSelectionCategory(""); }); - categoryMenu->addSeparator(); - - for (const QString &category : asConst(categories)) - { - const QString escapedCategory = QString(category).replace('&', "&&"); // avoid '&' becomes accelerator key - QAction *cat = categoryMenu->addAction(UIThemeManager::instance()->getIcon("inode-directory"), escapedCategory - , this, [this, category]() { setSelectionCategory(category); }); - - if (allSameCategory && (category == firstCategory)) - { - cat->setCheckable(true); - cat->setChecked(true); - } - } - // Tag Menu QStringList tags(BitTorrent::Session::instance()->tags().values()); std::sort(tags.begin(), tags.end(), Utils::Compare::NaturalLessThan()); @@ -1063,11 +995,6 @@ void TransferListWidget::displayListMenu(const QPoint &) tagsMenu->addAction(action); } - actionAutoTMM->setCheckState(allSameAutoTMM - ? (firstAutoTMM ? Qt::Checked : Qt::Unchecked) - : Qt::PartiallyChecked); - listMenu->addAction(actionAutoTMM); - listMenu->addSeparator(); listMenu->addAction(actionTorrentOptions); if (!oneNotSeed && oneHasMetadata) @@ -1085,19 +1012,7 @@ void TransferListWidget::displayListMenu(const QPoint &) addedPreviewAction = true; } if (oneNotSeed) - { - actionSequentialDownload->setCheckState(allSameSequentialDownloadMode - ? (sequentialDownloadMode ? Qt::Checked : Qt::Unchecked) - : Qt::PartiallyChecked); - listMenu->addAction(actionSequentialDownload); - - actionFirstLastPiecePrio->setCheckState(allSamePrioFirstlast - ? (prioritizeFirstLast ? Qt::Checked : Qt::Unchecked) - : Qt::PartiallyChecked); - listMenu->addAction(actionFirstLastPiecePrio); - addedPreviewAction = true; - } if (addedPreviewAction) listMenu->addSeparator(); diff --git a/src/gui/transferlistwidget.h b/src/gui/transferlistwidget.h index 9257ea15b..22c3314bb 100644 --- a/src/gui/transferlistwidget.h +++ b/src/gui/transferlistwidget.h @@ -65,7 +65,6 @@ public slots: void addSelectionTag(const QString &tag); void removeSelectionTag(const QString &tag); void clearSelectionTags(); - void setSelectedTorrentsLocation(); void pauseAllTorrents(); void resumeAllTorrents(); void startSelectedTorrents(); @@ -109,8 +108,6 @@ private slots: void displayListMenu(const QPoint &); void currentChanged(const QModelIndex ¤t, const QModelIndex&) override; void setSelectedTorrentsSuperSeeding(bool enabled) const; - void setSelectedTorrentsSequentialDownload(bool enabled) const; - void setSelectedFirstLastPiecePrio(bool enabled) const; void setSelectedAutoTMMEnabled(bool enabled) const; void askNewCategoryForSelection(); void saveSettings(); From 16f8d6a9361f95d3fe28ad7c77692526c186c876 Mon Sep 17 00:00:00 2001 From: thalieht Date: Fri, 22 Oct 2021 13:51:28 +0300 Subject: [PATCH 2/2] Allow deselecting radio buttons in "Torrent options" for mixed torrents --- src/gui/torrentoptionsdialog.cpp | 15 ++++++++++++++- src/gui/torrentoptionsdialog.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gui/torrentoptionsdialog.cpp b/src/gui/torrentoptionsdialog.cpp index bd2ce39a1..b348e1a00 100644 --- a/src/gui/torrentoptionsdialog.cpp +++ b/src/gui/torrentoptionsdialog.cpp @@ -276,7 +276,6 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorglobalMaxSeedingMinutes(); m_ui->spinRatioLimit->setValue(maxRatio); m_ui->spinTimeLimit->setValue(maxSeedingTime); - handleRatioTypeChanged(); if (!allTorrentsArePrivate) { @@ -338,6 +337,7 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVectorcheckAutoTMM, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleTMMChanged); connect(m_ui->comboCategory, &QComboBox::activated, this, &TorrentOptionsDialog::handleCategoryChanged); @@ -514,6 +514,19 @@ void TorrentOptionsDialog::handleTMMChanged() void TorrentOptionsDialog::handleRatioTypeChanged() { + if ((m_initialValues.ratio == MIXED_SHARE_LIMITS) || (m_initialValues.seedingTime == MIXED_SHARE_LIMITS)) + { + QAbstractButton *currentRadio = m_ui->buttonGroup->checkedButton(); + if (currentRadio && (currentRadio == m_previousRadio)) + { + // Hack to deselect the currently selected radio button programatically because Qt doesn't allow it in exclusive mode + m_ui->buttonGroup->setExclusive(false); + currentRadio->setChecked(false); + m_ui->buttonGroup->setExclusive(true); + } + m_previousRadio = m_ui->buttonGroup->checkedButton(); + } + m_ui->checkMaxRatio->setEnabled(m_ui->radioTorrentLimit->isChecked()); m_ui->checkMaxTime->setEnabled(m_ui->radioTorrentLimit->isChecked()); diff --git a/src/gui/torrentoptionsdialog.h b/src/gui/torrentoptionsdialog.h index 09fbe86cc..a07eaae66 100644 --- a/src/gui/torrentoptionsdialog.h +++ b/src/gui/torrentoptionsdialog.h @@ -34,6 +34,8 @@ #include "base/settingvalue.h" +class QAbstractButton; + namespace BitTorrent { class Torrent; @@ -76,6 +78,7 @@ private: QStringList m_categories; QString m_currentCategoriesString; bool m_allSameCategory = true; + QAbstractButton *m_previousRadio = nullptr; struct { QString savePath;