mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-01 13:18:06 -06:00
Merge pull request #15793 from glassez/save-path
Redesign "Incomplete folder" feature
This commit is contained in:
@@ -68,6 +68,7 @@ namespace
|
||||
const QString KEY_ENABLED = QStringLiteral(SETTINGS_KEY("Enabled"));
|
||||
const QString KEY_TOPLEVEL = QStringLiteral(SETTINGS_KEY("TopLevel"));
|
||||
const QString KEY_SAVEPATHHISTORY = QStringLiteral(SETTINGS_KEY("SavePathHistory"));
|
||||
const QString KEY_DOWNLOADPATHHISTORY = QStringLiteral(SETTINGS_KEY("DownloadPathHistory"));
|
||||
const QString KEY_SAVEPATHHISTORYLENGTH = QStringLiteral(SETTINGS_KEY("SavePathHistoryLength"));
|
||||
|
||||
// just a shortcut
|
||||
@@ -120,6 +121,45 @@ namespace
|
||||
const BitTorrent::TorrentInfo &m_torrentInfo;
|
||||
QStringList &m_filePaths;
|
||||
};
|
||||
|
||||
// savePath is a folder, not an absolute file path
|
||||
int indexOfPath(const FileSystemPathComboEdit *fsPathEdit, const QString &savePath)
|
||||
{
|
||||
const QDir saveDir {savePath};
|
||||
for (int i = 0; i < fsPathEdit->count(); ++i)
|
||||
{
|
||||
if (QDir(fsPathEdit->item(i)) == saveDir)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void setPath(FileSystemPathComboEdit *fsPathEdit, const QString &newPath)
|
||||
{
|
||||
int existingIndex = indexOfPath(fsPathEdit, newPath);
|
||||
if (existingIndex < 0)
|
||||
{
|
||||
// New path, prepend to combo box
|
||||
fsPathEdit->insertItem(0, newPath);
|
||||
existingIndex = 0;
|
||||
}
|
||||
|
||||
fsPathEdit->setCurrentIndex(existingIndex);
|
||||
}
|
||||
|
||||
void updatePathHistory(const QString &settingsKey, const QString &path, const int maxLength)
|
||||
{
|
||||
// Add last used save path to the front of history
|
||||
|
||||
auto pathList = settings()->loadValue<QStringList>(settingsKey);
|
||||
const int selectedSavePathIndex = pathList.indexOf(path);
|
||||
if (selectedSavePathIndex > 0)
|
||||
pathList.removeAt(selectedSavePathIndex);
|
||||
if (selectedSavePathIndex != 0)
|
||||
pathList.prepend(path);
|
||||
|
||||
settings()->storeValue(settingsKey, QStringList(pathList.mid(0, maxLength)));
|
||||
}
|
||||
}
|
||||
|
||||
const int AddNewTorrentDialog::minPathHistoryLength;
|
||||
@@ -155,13 +195,19 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
|
||||
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
|
||||
m_ui->downloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->downloadPath->setDialogCaption(tr("Choose save path"));
|
||||
m_ui->downloadPath->setMaxVisibleItems(20);
|
||||
|
||||
m_ui->startTorrentCheckBox->setChecked(!m_torrentParams.addPaused.value_or(session->isAddTorrentPaused()));
|
||||
|
||||
m_ui->comboTTM->blockSignals(true); // the TreeView size isn't correct if the slot does it job at this point
|
||||
m_ui->comboTTM->setCurrentIndex(!session->isAutoTMMDisabledByDefault());
|
||||
m_ui->comboTTM->setCurrentIndex(session->isAutoTMMDisabledByDefault() ? 0 : 1);
|
||||
m_ui->comboTTM->blockSignals(false);
|
||||
populateSavePathComboBox();
|
||||
|
||||
connect(m_ui->savePath, &FileSystemPathEdit::selectedPathChanged, this, &AddNewTorrentDialog::onSavePathChanged);
|
||||
connect(m_ui->downloadPath, &FileSystemPathEdit::selectedPathChanged, this, &AddNewTorrentDialog::onDownloadPathChanged);
|
||||
connect(m_ui->groupBoxDownloadPath, &QGroupBox::toggled, this, &AddNewTorrentDialog::onUseDownloadPathChanged);
|
||||
|
||||
m_ui->checkBoxRememberLastSavePath->setChecked(m_storeRememberLastSavePath);
|
||||
|
||||
@@ -176,7 +222,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
|
||||
m_ui->doNotDeleteTorrentCheckBox->setVisible(TorrentFileGuard::autoDeleteMode() != TorrentFileGuard::Never);
|
||||
|
||||
// Load categories
|
||||
QStringList categories = session->categories().keys();
|
||||
QStringList categories = session->categories();
|
||||
std::sort(categories.begin(), categories.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
||||
const QString defaultCategory = m_storeDefaultCategory;
|
||||
|
||||
@@ -344,6 +390,7 @@ bool AddNewTorrentDialog::loadTorrentImpl()
|
||||
m_ui->labelInfohash2Data->setText(m_torrentInfo.infoHash().v2().isValid() ? m_torrentInfo.infoHash().v2().toString() : tr("N/A"));
|
||||
setupTreeview();
|
||||
TMMChanged(m_ui->comboTTM->currentIndex());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -409,36 +456,6 @@ void AddNewTorrentDialog::showEvent(QShowEvent *event)
|
||||
raise();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveSavePathHistory() const
|
||||
{
|
||||
// Get current history
|
||||
auto history = settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY);
|
||||
QVector<QDir> historyDirs;
|
||||
for (const QString &path : asConst(history))
|
||||
historyDirs << QDir {path};
|
||||
|
||||
const QDir selectedSavePath {m_ui->savePath->selectedPath()};
|
||||
const int selectedSavePathIndex = historyDirs.indexOf(selectedSavePath);
|
||||
if (selectedSavePathIndex > 0)
|
||||
history.removeAt(selectedSavePathIndex);
|
||||
if (selectedSavePathIndex != 0)
|
||||
// Add last used save path to the front of history
|
||||
history.push_front(selectedSavePath.absolutePath());
|
||||
|
||||
// Save history
|
||||
settings()->storeValue(KEY_SAVEPATHHISTORY, QStringList {history.mid(0, savePathHistoryLength())});
|
||||
}
|
||||
|
||||
// savePath is a folder, not an absolute file path
|
||||
int AddNewTorrentDialog::indexOfSavePath(const QString &savePath)
|
||||
{
|
||||
QDir saveDir(savePath);
|
||||
for (int i = 0; i < m_ui->savePath->count(); ++i)
|
||||
if (QDir(m_ui->savePath->item(i)) == saveDir)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateDiskSpaceLabel()
|
||||
{
|
||||
// Determine torrent size
|
||||
@@ -472,18 +489,42 @@ void AddNewTorrentDialog::onSavePathChanged(const QString &newPath)
|
||||
{
|
||||
Q_UNUSED(newPath);
|
||||
// Remember index
|
||||
m_oldIndex = m_ui->savePath->currentIndex();
|
||||
m_savePathIndex = m_ui->savePath->currentIndex();
|
||||
updateDiskSpaceLabel();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::onDownloadPathChanged(const QString &newPath)
|
||||
{
|
||||
Q_UNUSED(newPath);
|
||||
// Remember index
|
||||
const int currentPathIndex = m_ui->downloadPath->currentIndex();
|
||||
if (currentPathIndex >= 0)
|
||||
m_downloadPathIndex = m_ui->downloadPath->currentIndex();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::onUseDownloadPathChanged(const bool checked)
|
||||
{
|
||||
m_useDownloadPath = checked;
|
||||
m_ui->downloadPath->setCurrentIndex(checked ? m_downloadPathIndex : -1);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::categoryChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
||||
if (m_ui->comboTTM->currentIndex() == 1)
|
||||
{
|
||||
QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->categoryComboBox->currentText());
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
const QString categoryName = m_ui->categoryComboBox->currentText();
|
||||
|
||||
const QString savePath = btSession->categorySavePath(categoryName);
|
||||
m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
|
||||
|
||||
const QString downloadPath = btSession->categoryDownloadPath(categoryName);
|
||||
m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(downloadPath));
|
||||
|
||||
m_ui->groupBoxDownloadPath->setChecked(!m_ui->downloadPath->selectedPath().isEmpty());
|
||||
|
||||
updateDiskSpaceLabel();
|
||||
}
|
||||
}
|
||||
@@ -513,19 +554,6 @@ void AddNewTorrentDialog::contentLayoutChanged(const int index)
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setSavePath(const QString &newPath)
|
||||
{
|
||||
int existingIndex = indexOfSavePath(newPath);
|
||||
if (existingIndex < 0)
|
||||
{
|
||||
// New path, prepend to combo box
|
||||
m_ui->savePath->insertItem(0, newPath);
|
||||
existingIndex = 0;
|
||||
}
|
||||
m_ui->savePath->setCurrentIndex(existingIndex);
|
||||
onSavePathChanged(newPath);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveTorrentFile()
|
||||
{
|
||||
Q_ASSERT(hasMetadata());
|
||||
@@ -555,22 +583,78 @@ bool AddNewTorrentDialog::hasMetadata() const
|
||||
return m_torrentInfo.isValid();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::populateSavePathComboBox()
|
||||
void AddNewTorrentDialog::populateSavePaths()
|
||||
{
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
|
||||
m_ui->savePath->blockSignals(true);
|
||||
m_ui->savePath->clear();
|
||||
const auto savePathHistory = settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY);
|
||||
if (savePathHistory.size() > 0)
|
||||
{
|
||||
for (const QString &path : savePathHistory)
|
||||
m_ui->savePath->addItem(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->savePath->addItem(btSession->savePath());
|
||||
}
|
||||
|
||||
// Load save path history
|
||||
const auto savePathHistory {settings()->loadValue<QStringList>(KEY_SAVEPATHHISTORY)};
|
||||
for (const QString &savePath : savePathHistory)
|
||||
m_ui->savePath->addItem(savePath);
|
||||
if (m_savePathIndex >= 0)
|
||||
{
|
||||
m_ui->savePath->setCurrentIndex(std::min(m_savePathIndex, (m_ui->savePath->count() - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_torrentParams.savePath.isEmpty())
|
||||
setPath(m_ui->savePath, m_torrentParams.savePath);
|
||||
else if (!m_storeRememberLastSavePath)
|
||||
setPath(m_ui->savePath, btSession->savePath());
|
||||
else
|
||||
m_ui->savePath->setCurrentIndex(0);
|
||||
|
||||
const QString defSavePath {BitTorrent::Session::instance()->defaultSavePath()};
|
||||
m_savePathIndex = m_ui->savePath->currentIndex();
|
||||
}
|
||||
|
||||
if (!m_torrentParams.savePath.isEmpty())
|
||||
setSavePath(m_torrentParams.savePath);
|
||||
else if (!m_storeRememberLastSavePath)
|
||||
setSavePath(defSavePath);
|
||||
// else last used save path will be selected since it is the first in the list
|
||||
m_ui->savePath->blockSignals(false);
|
||||
|
||||
m_ui->downloadPath->blockSignals(true);
|
||||
m_ui->downloadPath->clear();
|
||||
const auto downloadPathHistory = settings()->loadValue<QStringList>(KEY_DOWNLOADPATHHISTORY);
|
||||
if (downloadPathHistory.size() > 0)
|
||||
{
|
||||
for (const QString &path : downloadPathHistory)
|
||||
m_ui->downloadPath->addItem(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->downloadPath->addItem(btSession->downloadPath());
|
||||
}
|
||||
|
||||
if (m_downloadPathIndex >= 0)
|
||||
{
|
||||
m_ui->downloadPath->setCurrentIndex(m_useDownloadPath ? std::min(m_downloadPathIndex, (m_ui->downloadPath->count() - 1)) : -1);
|
||||
m_ui->groupBoxDownloadPath->setChecked(m_useDownloadPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool useDownloadPath = m_torrentParams.useDownloadPath.value_or(btSession->isDownloadPathEnabled());
|
||||
m_ui->groupBoxDownloadPath->setChecked(useDownloadPath);
|
||||
|
||||
if (!m_torrentParams.downloadPath.isEmpty())
|
||||
setPath(m_ui->downloadPath, m_torrentParams.downloadPath);
|
||||
else if (!m_storeRememberLastSavePath)
|
||||
setPath(m_ui->downloadPath, btSession->downloadPath());
|
||||
else
|
||||
m_ui->downloadPath->setCurrentIndex(0);
|
||||
|
||||
m_downloadPathIndex = m_ui->downloadPath->currentIndex();
|
||||
if (!useDownloadPath)
|
||||
m_ui->downloadPath->setCurrentIndex(-1);
|
||||
}
|
||||
|
||||
m_ui->downloadPath->blockSignals(false);
|
||||
m_ui->groupBoxDownloadPath->blockSignals(false);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
|
||||
@@ -694,16 +778,21 @@ void AddNewTorrentDialog::accept()
|
||||
m_torrentParams.sequential = m_ui->sequentialCheckBox->isChecked();
|
||||
m_torrentParams.firstLastPiecePriority = m_ui->firstLastCheckBox->isChecked();
|
||||
|
||||
QString savePath = m_ui->savePath->selectedPath();
|
||||
if (m_ui->comboTTM->currentIndex() != 1)
|
||||
{ // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
|
||||
m_torrentParams.useAutoTMM = false;
|
||||
m_torrentParams.savePath = savePath;
|
||||
saveSavePathHistory();
|
||||
}
|
||||
else
|
||||
const bool useAutoTMM = (m_ui->comboTTM->currentIndex() == 1); // 1 is Automatic mode. Handle all non 1 values as manual mode.
|
||||
m_torrentParams.useAutoTMM = useAutoTMM;
|
||||
if (!useAutoTMM)
|
||||
{
|
||||
m_torrentParams.useAutoTMM = true;
|
||||
const QString savePath = m_ui->savePath->selectedPath();
|
||||
m_torrentParams.savePath = savePath;
|
||||
updatePathHistory(KEY_SAVEPATHHISTORY, savePath, savePathHistoryLength());
|
||||
|
||||
m_torrentParams.useDownloadPath = m_ui->groupBoxDownloadPath->isChecked();
|
||||
if (m_torrentParams.useDownloadPath)
|
||||
{
|
||||
const QString downloadPath = m_ui->downloadPath->selectedPath();
|
||||
m_torrentParams.downloadPath = downloadPath;
|
||||
updatePathHistory(KEY_DOWNLOADPATHHISTORY, downloadPath, savePathHistoryLength());
|
||||
}
|
||||
}
|
||||
|
||||
setEnabled(!m_ui->checkBoxNeverShow->isChecked());
|
||||
@@ -855,18 +944,28 @@ void AddNewTorrentDialog::TMMChanged(int index)
|
||||
{
|
||||
if (index != 1)
|
||||
{ // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
|
||||
populateSavePathComboBox();
|
||||
populateSavePaths();
|
||||
m_ui->groupBoxSavePath->setEnabled(true);
|
||||
m_ui->savePath->blockSignals(false);
|
||||
m_ui->savePath->setCurrentIndex(m_oldIndex < m_ui->savePath->count() ? m_oldIndex : m_ui->savePath->count() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
|
||||
m_ui->groupBoxSavePath->setEnabled(false);
|
||||
|
||||
m_ui->savePath->blockSignals(true);
|
||||
m_ui->savePath->clear();
|
||||
QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->categoryComboBox->currentText());
|
||||
const QString savePath = session->categorySavePath(m_ui->categoryComboBox->currentText());
|
||||
m_ui->savePath->addItem(savePath);
|
||||
|
||||
m_ui->downloadPath->blockSignals(true);
|
||||
m_ui->downloadPath->clear();
|
||||
const QString downloadPath = session->categoryDownloadPath(m_ui->categoryComboBox->currentText());
|
||||
m_ui->downloadPath->addItem(downloadPath);
|
||||
|
||||
m_ui->groupBoxDownloadPath->blockSignals(true);
|
||||
m_ui->groupBoxDownloadPath->setChecked(!downloadPath.isEmpty());
|
||||
|
||||
updateDiskSpaceLabel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,8 @@ private slots:
|
||||
void displayContentTreeMenu(const QPoint &);
|
||||
void updateDiskSpaceLabel();
|
||||
void onSavePathChanged(const QString &newPath);
|
||||
void onDownloadPathChanged(const QString &newPath);
|
||||
void onUseDownloadPathChanged(bool checked);
|
||||
void updateMetadata(const BitTorrent::TorrentInfo &metadata);
|
||||
void handleDownloadFinished(const Net::DownloadResult &downloadResult);
|
||||
void TMMChanged(int index);
|
||||
@@ -97,14 +99,11 @@ private:
|
||||
bool loadTorrentFile(const QString &torrentPath);
|
||||
bool loadTorrentImpl();
|
||||
bool loadMagnet(const BitTorrent::MagnetUri &magnetUri);
|
||||
void populateSavePathComboBox();
|
||||
void saveSavePathHistory() const;
|
||||
int indexOfSavePath(const QString &savePath);
|
||||
void populateSavePaths();
|
||||
void loadState();
|
||||
void saveState();
|
||||
void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = {});
|
||||
void setupTreeview();
|
||||
void setSavePath(const QString &newPath);
|
||||
void saveTorrentFile();
|
||||
bool hasMetadata() const;
|
||||
|
||||
@@ -115,7 +114,9 @@ private:
|
||||
PropListDelegate *m_contentDelegate = nullptr;
|
||||
BitTorrent::MagnetUri m_magnetURI;
|
||||
BitTorrent::TorrentInfo m_torrentInfo;
|
||||
int m_oldIndex = 0;
|
||||
int m_savePathIndex = -1;
|
||||
int m_downloadPathIndex = -1;
|
||||
bool m_useDownloadPath = false;
|
||||
std::unique_ptr<TorrentFileGuard> m_torrentGuard;
|
||||
BitTorrent::AddTorrentParams m_torrentParams;
|
||||
|
||||
|
||||
@@ -83,13 +83,48 @@
|
||||
<item>
|
||||
<widget class="FileSystemPathComboEdit" name="savePath" native="true"/>
|
||||
</item>
|
||||
<item alignment="Qt::AlignRight">
|
||||
<widget class="QCheckBox" name="checkBoxRememberLastSavePath">
|
||||
<property name="text">
|
||||
<string>Remember last used save path</string>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxDownloadPath">
|
||||
<property name="title">
|
||||
<string>Use another path for incomplete torrent</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="FileSystemPathComboEdit" name="downloadPath" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layoutRememberLastSavePath">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxRememberLastSavePath">
|
||||
<property name="text">
|
||||
<string>Remember last used save path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -404,40 +404,33 @@ void CategoryFilterModel::populate()
|
||||
|
||||
// Uncategorized torrents
|
||||
using Torrent = BitTorrent::Torrent;
|
||||
m_rootItem->addChild(
|
||||
UID_UNCATEGORIZED
|
||||
, new CategoryModelItem(
|
||||
nullptr, tr("Uncategorized")
|
||||
, std::count_if(torrents.begin(), torrents.end()
|
||||
, [](Torrent *torrent) { return torrent->category().isEmpty(); })));
|
||||
const int torrentsCount = std::count_if(torrents.begin(), torrents.end()
|
||||
, [](Torrent *torrent) { return torrent->category().isEmpty(); });
|
||||
m_rootItem->addChild(UID_UNCATEGORIZED, new CategoryModelItem(nullptr, tr("Uncategorized"), torrentsCount));
|
||||
|
||||
using Torrent = BitTorrent::Torrent;
|
||||
const QStringMap categories = session->categories();
|
||||
for (auto i = categories.cbegin(); i != categories.cend(); ++i)
|
||||
using BitTorrent::Torrent;
|
||||
for (const QString &categoryName : asConst(session->categories()))
|
||||
{
|
||||
const QString &category = i.key();
|
||||
if (m_isSubcategoriesEnabled)
|
||||
{
|
||||
CategoryModelItem *parent = m_rootItem;
|
||||
for (const QString &subcat : asConst(session->expandCategory(category)))
|
||||
for (const QString &subcat : asConst(session->expandCategory(categoryName)))
|
||||
{
|
||||
const QString subcatName = shortName(subcat);
|
||||
if (!parent->hasChild(subcatName))
|
||||
{
|
||||
new CategoryModelItem(
|
||||
parent, subcatName
|
||||
, std::count_if(torrents.cbegin(), torrents.cend()
|
||||
, [subcat](Torrent *torrent) { return torrent->category() == subcat; }));
|
||||
const int torrentsCount = std::count_if(torrents.cbegin(), torrents.cend()
|
||||
, [subcat](Torrent *torrent) { return torrent->category() == subcat; });
|
||||
new CategoryModelItem(parent, subcatName, torrentsCount);
|
||||
}
|
||||
parent = parent->child(subcatName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new CategoryModelItem(
|
||||
m_rootItem, category
|
||||
, std::count_if(torrents.begin(), torrents.end()
|
||||
, [category](Torrent *torrent) { return torrent->belongsToCategory(category); }));
|
||||
const int torrentsCount = std::count_if(torrents.begin(), torrents.end()
|
||||
, [categoryName](Torrent *torrent) { return torrent->belongsToCategory(categoryName); });
|
||||
new CategoryModelItem(m_rootItem, categoryName, torrentsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ void CategoryFilterWidget::removeCategory()
|
||||
void CategoryFilterWidget::removeUnusedCategories()
|
||||
{
|
||||
auto session = BitTorrent::Session::instance();
|
||||
for (const QString &category : asConst(session->categories().keys()))
|
||||
for (const QString &category : asConst(session->categories()))
|
||||
{
|
||||
if (model()->data(static_cast<CategoryFilterProxyModel *>(model())->index(category), Qt::UserRole) == 0)
|
||||
session->removeCategory(category);
|
||||
|
||||
@@ -247,6 +247,18 @@ void FileSystemPathEdit::setFileNameFilter(const QString &val)
|
||||
#endif
|
||||
}
|
||||
|
||||
QString FileSystemPathEdit::placeholder() const
|
||||
{
|
||||
Q_D(const FileSystemPathEdit);
|
||||
return d->m_editor->placeholder();
|
||||
}
|
||||
|
||||
void FileSystemPathEdit::setPlaceholder(const QString &val)
|
||||
{
|
||||
Q_D(FileSystemPathEdit);
|
||||
d->m_editor->setPlaceholder(val);
|
||||
}
|
||||
|
||||
bool FileSystemPathEdit::briefBrowseButtonCaption() const
|
||||
{
|
||||
Q_D(const FileSystemPathEdit);
|
||||
|
||||
@@ -71,6 +71,9 @@ public:
|
||||
QString fileNameFilter() const;
|
||||
void setFileNameFilter(const QString &val);
|
||||
|
||||
QString placeholder() const;
|
||||
void setPlaceholder(const QString &val);
|
||||
|
||||
/// The browse button caption is "..." if true, and "Browse" otherwise
|
||||
bool briefBrowseButtonCaption() const;
|
||||
void setBriefBrowseButtonCaption(bool brief);
|
||||
|
||||
@@ -240,6 +240,16 @@ void Private::FileLineEdit::setValidator(QValidator *validator)
|
||||
QLineEdit::setValidator(validator);
|
||||
}
|
||||
|
||||
QString Private::FileLineEdit::placeholder() const
|
||||
{
|
||||
return placeholderText();
|
||||
}
|
||||
|
||||
void Private::FileLineEdit::setPlaceholder(const QString &val)
|
||||
{
|
||||
setPlaceholderText(val);
|
||||
}
|
||||
|
||||
QWidget *Private::FileLineEdit::widget()
|
||||
{
|
||||
return this;
|
||||
@@ -346,6 +356,16 @@ void Private::FileComboEdit::setValidator(QValidator *validator)
|
||||
lineEdit()->setValidator(validator);
|
||||
}
|
||||
|
||||
QString Private::FileComboEdit::placeholder() const
|
||||
{
|
||||
return lineEdit()->placeholderText();
|
||||
}
|
||||
|
||||
void Private::FileComboEdit::setPlaceholder(const QString &val)
|
||||
{
|
||||
lineEdit()->setPlaceholderText(val);
|
||||
}
|
||||
|
||||
void Private::FileComboEdit::setFilenameFilters(const QStringList &filters)
|
||||
{
|
||||
static_cast<FileLineEdit *>(lineEdit())->setFilenameFilters(filters);
|
||||
|
||||
@@ -105,6 +105,8 @@ namespace Private
|
||||
virtual void setFilenameFilters(const QStringList &filters) = 0;
|
||||
virtual void setBrowseAction(QAction *action) = 0;
|
||||
virtual void setValidator(QValidator *validator) = 0;
|
||||
virtual QString placeholder() const = 0;
|
||||
virtual void setPlaceholder(const QString &val) = 0;
|
||||
virtual QWidget *widget() = 0;
|
||||
};
|
||||
|
||||
@@ -121,6 +123,8 @@ namespace Private
|
||||
void setFilenameFilters(const QStringList &filters) override;
|
||||
void setBrowseAction(QAction *action) override;
|
||||
void setValidator(QValidator *validator) override;
|
||||
QString placeholder() const override;
|
||||
void setPlaceholder(const QString &val) override;
|
||||
QWidget *widget() override;
|
||||
|
||||
protected:
|
||||
@@ -149,6 +153,8 @@ namespace Private
|
||||
void setFilenameFilters(const QStringList &filters) override;
|
||||
void setBrowseAction(QAction *action) override;
|
||||
void setValidator(QValidator *validator) override;
|
||||
QString placeholder() const override;
|
||||
void setPlaceholder(const QString &val) override;
|
||||
QWidget *widget() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -354,7 +354,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
connect(m_ui->comboTorrentCategoryChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->comboCategoryDefaultPathChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->comboCategoryChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->textTempPath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->textDownloadPath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkAppendqB, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkPreallocateAll, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkRecursiveDownload, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||
@@ -372,8 +372,8 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
connect(m_ui->textExportDirFin, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->actionTorrentDlOnDblClBox, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->actionTorrentFnOnDblClBox, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkTempFolder, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkTempFolder, &QAbstractButton::toggled, m_ui->textTempPath, &QWidget::setEnabled);
|
||||
connect(m_ui->checkUseDownloadPath, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->checkUseDownloadPath, &QAbstractButton::toggled, m_ui->textDownloadPath, &QWidget::setEnabled);
|
||||
connect(m_ui->addWatchedFolderButton, &QAbstractButton::clicked, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->removeWatchedFolderButton, &QAbstractButton::clicked, this, &ThisType::enableApplyButton);
|
||||
connect(m_ui->groupMailNotification, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
|
||||
@@ -559,8 +559,8 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
m_ui->textSavePath->setDialogCaption(tr("Choose a save directory"));
|
||||
m_ui->textSavePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
|
||||
m_ui->textTempPath->setDialogCaption(tr("Choose a save directory"));
|
||||
m_ui->textTempPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->textDownloadPath->setDialogCaption(tr("Choose a save directory"));
|
||||
m_ui->textDownloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
|
||||
// disable mouse wheel event on widgets to avoid mis-selection
|
||||
auto *wheelEventEater = new WheelEventEater(this);
|
||||
@@ -731,14 +731,14 @@ void OptionsDialog::saveOptions()
|
||||
auto session = BitTorrent::Session::instance();
|
||||
|
||||
// Downloads preferences
|
||||
session->setDefaultSavePath(Utils::Fs::expandPathAbs(m_ui->textSavePath->selectedPath()));
|
||||
session->setSavePath(Utils::Fs::expandPathAbs(m_ui->textSavePath->selectedPath()));
|
||||
session->setSubcategoriesEnabled(m_ui->checkUseSubcategories->isChecked());
|
||||
session->setAutoTMMDisabledByDefault(m_ui->comboSavingMode->currentIndex() == 0);
|
||||
session->setDisableAutoTMMWhenCategoryChanged(m_ui->comboTorrentCategoryChanged->currentIndex() == 1);
|
||||
session->setDisableAutoTMMWhenCategorySavePathChanged(m_ui->comboCategoryChanged->currentIndex() == 1);
|
||||
session->setDisableAutoTMMWhenDefaultSavePathChanged(m_ui->comboCategoryDefaultPathChanged->currentIndex() == 1);
|
||||
session->setTempPathEnabled(m_ui->checkTempFolder->isChecked());
|
||||
session->setTempPath(Utils::Fs::expandPathAbs(m_ui->textTempPath->selectedPath()));
|
||||
session->setDownloadPathEnabled(m_ui->checkUseDownloadPath->isChecked());
|
||||
session->setDownloadPath(Utils::Fs::expandPathAbs(m_ui->textDownloadPath->selectedPath()));
|
||||
session->setAppendExtensionEnabled(m_ui->checkAppendqB->isChecked());
|
||||
session->setPreallocationEnabled(preAllocateAllFiles());
|
||||
pref->disableRecursiveDownload(!m_ui->checkRecursiveDownload->isChecked());
|
||||
@@ -997,16 +997,16 @@ void OptionsDialog::loadOptions()
|
||||
m_ui->deleteTorrentBox->setChecked(autoDeleteMode != TorrentFileGuard::Never);
|
||||
m_ui->deleteCancelledTorrentBox->setChecked(autoDeleteMode == TorrentFileGuard::Always);
|
||||
|
||||
m_ui->textSavePath->setSelectedPath(session->defaultSavePath());
|
||||
m_ui->textSavePath->setSelectedPath(session->savePath());
|
||||
m_ui->checkUseSubcategories->setChecked(session->isSubcategoriesEnabled());
|
||||
m_ui->comboSavingMode->setCurrentIndex(!session->isAutoTMMDisabledByDefault());
|
||||
m_ui->comboTorrentCategoryChanged->setCurrentIndex(session->isDisableAutoTMMWhenCategoryChanged());
|
||||
m_ui->comboCategoryChanged->setCurrentIndex(session->isDisableAutoTMMWhenCategorySavePathChanged());
|
||||
m_ui->comboCategoryDefaultPathChanged->setCurrentIndex(session->isDisableAutoTMMWhenDefaultSavePathChanged());
|
||||
m_ui->checkTempFolder->setChecked(session->isTempPathEnabled());
|
||||
m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked());
|
||||
m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked());
|
||||
m_ui->textTempPath->setSelectedPath(Utils::Fs::toNativePath(session->tempPath()));
|
||||
m_ui->checkUseDownloadPath->setChecked(session->isDownloadPathEnabled());
|
||||
m_ui->textDownloadPath->setEnabled(m_ui->checkUseDownloadPath->isChecked());
|
||||
m_ui->textDownloadPath->setEnabled(m_ui->checkUseDownloadPath->isChecked());
|
||||
m_ui->textDownloadPath->setSelectedPath(Utils::Fs::toNativePath(session->downloadPath()));
|
||||
m_ui->checkAppendqB->setChecked(session->isAppendExtensionEnabled());
|
||||
m_ui->checkPreallocateAll->setChecked(session->isPreallocationEnabled());
|
||||
m_ui->checkRecursiveDownload->setChecked(!pref->recursiveDownloadDisabled());
|
||||
|
||||
@@ -1105,16 +1105,6 @@ Manual: Various torrent properties (e.g. save path) must be assigned manually</s
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textTempPath" native="true"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkExportDirFin">
|
||||
<property name="text">
|
||||
<string>Copy .torrent files for finished downloads to:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSavePath">
|
||||
<property name="text">
|
||||
@@ -1122,6 +1112,19 @@ Manual: Various torrent properties (e.g. save path) must be assigned manually</s
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textSavePath" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkUseDownloadPath">
|
||||
<property name="text">
|
||||
<string>Use another path for incomplete torrents:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textDownloadPath" native="true"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkExportDir">
|
||||
<property name="text">
|
||||
@@ -1129,21 +1132,18 @@ Manual: Various torrent properties (e.g. save path) must be assigned manually</s
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkTempFolder">
|
||||
<property name="text">
|
||||
<string>Keep incomplete torrents in:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="2" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textExportDir" native="true"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textExportDirFin" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textSavePath" native="true"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="textExportDir" native="true"/>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkExportDirFin">
|
||||
<property name="text">
|
||||
<string>Copy .torrent files for finished downloads to:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@@ -3490,8 +3490,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
||||
<tabstop>checkAdditionDialog</tabstop>
|
||||
<tabstop>checkAdditionDialogFront</tabstop>
|
||||
<tabstop>checkPreallocateAll</tabstop>
|
||||
<tabstop>checkTempFolder</tabstop>
|
||||
<tabstop>textTempPath</tabstop>
|
||||
<tabstop>checkUseDownloadPath</tabstop>
|
||||
<tabstop>textDownloadPath</tabstop>
|
||||
<tabstop>checkAppendqB</tabstop>
|
||||
<tabstop>scanFoldersView</tabstop>
|
||||
<tabstop>addWatchedFolderButton</tabstop>
|
||||
|
||||
@@ -581,11 +581,12 @@ void PropertiesWidget::loadUrlSeeds()
|
||||
|
||||
QString PropertiesWidget::getFullPath(const QModelIndex &index) const
|
||||
{
|
||||
const QDir saveDir {m_torrent->actualStorageLocation()};
|
||||
|
||||
if (m_propListModel->itemType(index) == TorrentContentModelItem::FileType)
|
||||
{
|
||||
const int fileIdx = m_propListModel->getFileIndex(index);
|
||||
const QString filename {m_torrent->filePath(fileIdx)};
|
||||
const QDir saveDir {m_torrent->savePath(true)};
|
||||
const QString fullPath {Utils::Fs::expandPath(saveDir.absoluteFilePath(filename))};
|
||||
return fullPath;
|
||||
}
|
||||
@@ -596,7 +597,6 @@ QString PropertiesWidget::getFullPath(const QModelIndex &index) const
|
||||
for (QModelIndex modelIdx = m_propListModel->parent(nameIndex); modelIdx.isValid(); modelIdx = modelIdx.parent())
|
||||
folderPath.prepend(modelIdx.data().toString() + '/');
|
||||
|
||||
const QDir saveDir {m_torrent->savePath(true)};
|
||||
const QString fullPath {Utils::Fs::expandPath(saveDir.absoluteFilePath(folderPath))};
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ void AutomatedRssDownloader::clearRuleDefinitionBox()
|
||||
void AutomatedRssDownloader::initCategoryCombobox()
|
||||
{
|
||||
// Load torrent categories
|
||||
QStringList categories = BitTorrent::Session::instance()->categories().keys();
|
||||
QStringList categories = BitTorrent::Session::instance()->categories();
|
||||
std::sort(categories.begin(), categories.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
||||
m_ui->comboCategory->addItem("");
|
||||
m_ui->comboCategory->addItems(categories);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2017, 2021 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QPushButton>
|
||||
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "ui_torrentcategorydialog.h"
|
||||
|
||||
TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent)
|
||||
@@ -39,15 +40,20 @@ TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent)
|
||||
, m_ui {new Ui::TorrentCategoryDialog}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->comboSavePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->comboSavePath->setDialogCaption(tr("Choose save path"));
|
||||
|
||||
m_ui->comboDownloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->comboDownloadPath->setDialogCaption(tr("Choose download path"));
|
||||
m_ui->comboDownloadPath->setEnabled(false);
|
||||
m_ui->labelDownloadPath->setEnabled(false);
|
||||
|
||||
// disable save button
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
connect(m_ui->textCategoryName, &QLineEdit::textChanged, this, [this](const QString &text)
|
||||
{
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
|
||||
});
|
||||
|
||||
connect(m_ui->textCategoryName, &QLineEdit::textChanged, this, &TorrentCategoryDialog::categoryNameChanged);
|
||||
connect(m_ui->comboUseDownloadPath, &QComboBox::currentIndexChanged, this, &TorrentCategoryDialog::useDownloadPathChanged);
|
||||
}
|
||||
|
||||
TorrentCategoryDialog::~TorrentCategoryDialog()
|
||||
@@ -57,20 +63,21 @@ TorrentCategoryDialog::~TorrentCategoryDialog()
|
||||
|
||||
QString TorrentCategoryDialog::createCategory(QWidget *parent, const QString &parentCategoryName)
|
||||
{
|
||||
using BitTorrent::CategoryOptions;
|
||||
using BitTorrent::Session;
|
||||
|
||||
QString newCategoryName {parentCategoryName};
|
||||
QString newCategoryName = parentCategoryName;
|
||||
if (!newCategoryName.isEmpty())
|
||||
newCategoryName += QLatin1Char('/');
|
||||
newCategoryName += tr("New Category");
|
||||
|
||||
TorrentCategoryDialog dialog(parent);
|
||||
TorrentCategoryDialog dialog {parent};
|
||||
dialog.setCategoryName(newCategoryName);
|
||||
while (dialog.exec() == TorrentCategoryDialog::Accepted)
|
||||
{
|
||||
newCategoryName = dialog.categoryName();
|
||||
|
||||
if (!BitTorrent::Session::isValidCategoryName(newCategoryName))
|
||||
if (!Session::isValidCategoryName(newCategoryName))
|
||||
{
|
||||
QMessageBox::critical(
|
||||
parent, tr("Invalid category name")
|
||||
@@ -78,7 +85,7 @@ QString TorrentCategoryDialog::createCategory(QWidget *parent, const QString &pa
|
||||
"Category name cannot start/end with '/'.\n"
|
||||
"Category name cannot contain '//' sequence."));
|
||||
}
|
||||
else if (BitTorrent::Session::instance()->categories().contains(newCategoryName))
|
||||
else if (Session::instance()->categories().contains(newCategoryName))
|
||||
{
|
||||
QMessageBox::critical(
|
||||
parent, tr("Category creation error")
|
||||
@@ -87,7 +94,7 @@ QString TorrentCategoryDialog::createCategory(QWidget *parent, const QString &pa
|
||||
}
|
||||
else
|
||||
{
|
||||
Session::instance()->addCategory(newCategoryName, dialog.savePath());
|
||||
Session::instance()->addCategory(newCategoryName, dialog.categoryOptions());
|
||||
return newCategoryName;
|
||||
}
|
||||
}
|
||||
@@ -105,10 +112,10 @@ void TorrentCategoryDialog::editCategory(QWidget *parent, const QString &categor
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->setCategoryNameEditable(false);
|
||||
dialog->setCategoryName(categoryName);
|
||||
dialog->setSavePath(Session::instance()->categories()[categoryName]);
|
||||
dialog->setCategoryOptions(Session::instance()->categoryOptions(categoryName));
|
||||
connect(dialog, &TorrentCategoryDialog::accepted, parent, [dialog, categoryName]()
|
||||
{
|
||||
Session::instance()->editCategory(categoryName, dialog->savePath());
|
||||
Session::instance()->editCategory(categoryName, dialog->categoryOptions());
|
||||
});
|
||||
dialog->open();
|
||||
}
|
||||
@@ -128,12 +135,59 @@ void TorrentCategoryDialog::setCategoryName(const QString &categoryName)
|
||||
m_ui->textCategoryName->setText(categoryName);
|
||||
}
|
||||
|
||||
QString TorrentCategoryDialog::savePath() const
|
||||
BitTorrent::CategoryOptions TorrentCategoryDialog::categoryOptions() const
|
||||
{
|
||||
return m_ui->comboSavePath->selectedPath();
|
||||
BitTorrent::CategoryOptions categoryOptions;
|
||||
categoryOptions.savePath = m_ui->comboSavePath->selectedPath();
|
||||
if (m_ui->comboUseDownloadPath->currentIndex() == 1)
|
||||
categoryOptions.downloadPath = {true, m_ui->comboDownloadPath->selectedPath()};
|
||||
else if (m_ui->comboUseDownloadPath->currentIndex() == 2)
|
||||
categoryOptions.downloadPath = {false};
|
||||
|
||||
return categoryOptions;
|
||||
}
|
||||
|
||||
void TorrentCategoryDialog::setSavePath(const QString &savePath)
|
||||
void TorrentCategoryDialog::setCategoryOptions(const BitTorrent::CategoryOptions &categoryOptions)
|
||||
{
|
||||
m_ui->comboSavePath->setSelectedPath(savePath);
|
||||
m_ui->comboSavePath->setSelectedPath(categoryOptions.savePath);
|
||||
if (categoryOptions.downloadPath)
|
||||
{
|
||||
m_ui->comboUseDownloadPath->setCurrentIndex(categoryOptions.downloadPath->enabled ? 1 : 2);
|
||||
m_ui->comboDownloadPath->setSelectedPath(categoryOptions.downloadPath->enabled ? categoryOptions.downloadPath->path : QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->comboUseDownloadPath->setCurrentIndex(0);
|
||||
m_ui->comboDownloadPath->setSelectedPath({});
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentCategoryDialog::categoryNameChanged(const QString &categoryName)
|
||||
{
|
||||
const QString categoryPath = Utils::Fs::toValidFileSystemName(categoryName, true);
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
m_ui->comboSavePath->setPlaceholder(Utils::Fs::resolvePath(categoryPath, btSession->savePath()));
|
||||
|
||||
const int index = m_ui->comboUseDownloadPath->currentIndex();
|
||||
const bool useDownloadPath = (index == 1) || ((index == 0) && BitTorrent::Session::instance()->isDownloadPathEnabled());
|
||||
if (useDownloadPath)
|
||||
m_ui->comboDownloadPath->setPlaceholder(Utils::Fs::resolvePath(categoryPath, btSession->downloadPath()));
|
||||
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!categoryName.isEmpty());
|
||||
}
|
||||
|
||||
void TorrentCategoryDialog::useDownloadPathChanged(const int index)
|
||||
{
|
||||
if (const QString selectedPath = m_ui->comboDownloadPath->selectedPath(); !selectedPath.isEmpty())
|
||||
m_lastEnteredDownloadPath = selectedPath;
|
||||
|
||||
m_ui->labelDownloadPath->setEnabled(index == 1);
|
||||
m_ui->comboDownloadPath->setEnabled(index == 1);
|
||||
m_ui->comboDownloadPath->setSelectedPath((index == 1) ? m_lastEnteredDownloadPath : QString());
|
||||
|
||||
const QString categoryName = m_ui->textCategoryName->text();
|
||||
const QString categoryPath = Utils::Fs::resolvePath(Utils::Fs::toValidFileSystemName(categoryName, true)
|
||||
, BitTorrent::Session::instance()->downloadPath());
|
||||
const bool useDownloadPath = (index == 1) || ((index == 0) && BitTorrent::Session::instance()->isDownloadPathEnabled());
|
||||
m_ui->comboDownloadPath->setPlaceholder(useDownloadPath ? categoryPath : QString());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2017, 2021 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,6 +30,11 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct CategoryOptions;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class TorrentCategoryDialog;
|
||||
@@ -50,9 +55,14 @@ public:
|
||||
void setCategoryNameEditable(bool editable);
|
||||
QString categoryName() const;
|
||||
void setCategoryName(const QString &categoryName);
|
||||
QString savePath() const;
|
||||
void setSavePath(const QString &savePath);
|
||||
void setCategoryOptions(const BitTorrent::CategoryOptions &categoryOptions);
|
||||
BitTorrent::CategoryOptions categoryOptions() const;
|
||||
|
||||
private slots:
|
||||
void categoryNameChanged(const QString &categoryName);
|
||||
void useDownloadPathChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::TorrentCategoryDialog *m_ui;
|
||||
QString m_lastEnteredDownloadPath;
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>100</height>
|
||||
<width>493</width>
|
||||
<height>208</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -15,7 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@@ -29,10 +29,13 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelCategoryName">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
<item row="1" column="1">
|
||||
<widget class="FileSystemPathComboEdit" name="comboSavePath" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -46,20 +49,99 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="FileSystemPathComboEdit" name="comboSavePath" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelCategoryName">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Save path for incomplete torrents:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUseDownloadPath">
|
||||
<property name="text">
|
||||
<string>Use another path for incomplete torrents:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboUseDownloadPath">
|
||||
<property name="maxVisibleItems">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Yes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>No</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDownloadPath">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FileSystemPathComboEdit" name="comboDownloadPath" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
|
||||
@@ -65,19 +65,33 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
, m_storeDialogSize {SETTINGS_KEY("Size")}
|
||||
, m_currentCategoriesString {QString::fromLatin1("--%1--").arg(tr("Currently used categories"))}
|
||||
{
|
||||
Q_ASSERT(!torrents.empty());
|
||||
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->savePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->savePath->setDialogCaption(tr("Choose save path"));
|
||||
Q_ASSERT(!torrents.empty());
|
||||
m_ui->downloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->downloadPath->setDialogCaption(tr("Choose save path"));
|
||||
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
bool allSameUpLimit = true, allSameDownLimit = true, allSameRatio = true, allSameSeedingTime = true
|
||||
, allTorrentsArePrivate = true, allSameDHT = true, allSamePEX = true, allSameLSD = true
|
||||
, allSameSequential = true, allSameFirstLastPieces = true, allSameAutoTMM = true, allSameSavePath = true;
|
||||
bool allSameUpLimit = true;
|
||||
bool allSameDownLimit = true;
|
||||
bool allSameRatio = true;
|
||||
bool allSameSeedingTime = true;
|
||||
bool allTorrentsArePrivate = true;
|
||||
bool allSameDHT = true;
|
||||
bool allSamePEX = true;
|
||||
bool allSameLSD = true;
|
||||
bool allSameSequential = true;
|
||||
bool allSameFirstLastPieces = true;
|
||||
bool allSameAutoTMM = true;
|
||||
bool allSameSavePath = true;
|
||||
bool allSameDownloadPath = true;
|
||||
|
||||
const bool isFirstTorrentAutoTMMEnabled = torrents[0]->isAutoTMMEnabled();
|
||||
const QString firstTorrentSavePath = torrents[0]->savePath();
|
||||
const QString firstTorrentDownloadPath = torrents[0]->downloadPath();
|
||||
const QString firstTorrentCategory = torrents[0]->category();
|
||||
|
||||
const int firstTorrentUpLimit = std::max(0, torrents[0]->uploadLimit());
|
||||
@@ -107,6 +121,11 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
if (torrent->savePath() != firstTorrentSavePath)
|
||||
allSameSavePath = false;
|
||||
}
|
||||
if (allSameDownloadPath)
|
||||
{
|
||||
if (torrent->downloadPath() != firstTorrentDownloadPath)
|
||||
allSameDownloadPath = false;
|
||||
}
|
||||
if (m_allSameCategory)
|
||||
{
|
||||
if (torrent->category() != firstTorrentCategory)
|
||||
@@ -172,6 +191,16 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
if (allSameSavePath)
|
||||
m_ui->savePath->setSelectedPath(firstTorrentSavePath);
|
||||
|
||||
if (allSameDownloadPath)
|
||||
{
|
||||
m_ui->downloadPath->setSelectedPath(firstTorrentDownloadPath);
|
||||
m_ui->checkUseDownloadPath->setChecked(!firstTorrentDownloadPath.isEmpty());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
|
||||
if (!m_allSameCategory)
|
||||
{
|
||||
m_ui->comboCategory->addItem(m_currentCategoriesString);
|
||||
@@ -185,7 +214,7 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
}
|
||||
m_ui->comboCategory->addItem(QString());
|
||||
|
||||
m_categories = session->categories().keys();
|
||||
m_categories = session->categories();
|
||||
std::sort(m_categories.begin(), m_categories.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
||||
for (const QString &category : asConst(m_categories))
|
||||
{
|
||||
@@ -324,12 +353,14 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
m_initialValues =
|
||||
{
|
||||
m_ui->savePath->selectedPath(),
|
||||
m_ui->downloadPath->selectedPath(),
|
||||
m_ui->comboCategory->currentText(),
|
||||
getRatio(),
|
||||
getSeedingTime(),
|
||||
m_ui->spinUploadLimit->value(),
|
||||
m_ui->spinDownloadLimit->value(),
|
||||
m_ui->checkAutoTMM->checkState(),
|
||||
m_ui->checkUseDownloadPath->checkState(),
|
||||
m_ui->checkDisableDHT->checkState(),
|
||||
m_ui->checkDisablePEX->checkState(),
|
||||
m_ui->checkDisableLSD->checkState(),
|
||||
@@ -339,9 +370,11 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
|
||||
// Needs to be called after the initial values struct is initialized
|
||||
handleTMMChanged();
|
||||
handleUseDownloadPathChanged();
|
||||
handleRatioTypeChanged();
|
||||
|
||||
connect(m_ui->checkAutoTMM, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleTMMChanged);
|
||||
connect(m_ui->checkUseDownloadPath, &QCheckBox::clicked, this, &TorrentOptionsDialog::handleUseDownloadPathChanged);
|
||||
connect(m_ui->comboCategory, &QComboBox::activated, this, &TorrentOptionsDialog::handleCategoryChanged);
|
||||
|
||||
// Sync up/down speed limit sliders with their corresponding spinboxes
|
||||
@@ -380,11 +413,28 @@ void TorrentOptionsDialog::accept()
|
||||
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));
|
||||
|
||||
if (m_ui->checkAutoTMM->checkState() == Qt::Unchecked)
|
||||
{
|
||||
const QString savePath = m_ui->savePath->selectedPath();
|
||||
if (m_initialValues.savePath != savePath)
|
||||
torrent->setSavePath(Utils::Fs::expandPathAbs(savePath));
|
||||
|
||||
const Qt::CheckState useDownloadPathState = m_ui->checkUseDownloadPath->checkState();
|
||||
if (useDownloadPathState == Qt::Checked)
|
||||
{
|
||||
const QString downloadPath = m_ui->downloadPath->selectedPath();
|
||||
if (m_initialValues.downloadPath != downloadPath)
|
||||
torrent->setDownloadPath(Utils::Fs::expandPathAbs(downloadPath));
|
||||
}
|
||||
else if (useDownloadPathState == Qt::Unchecked)
|
||||
{
|
||||
torrent->setDownloadPath(QString());
|
||||
}
|
||||
}
|
||||
|
||||
const QString category = m_ui->comboCategory->currentText();
|
||||
// index 0 is always the current category
|
||||
if ((m_initialValues.category != category) || (m_ui->comboCategory->currentIndex() != 0))
|
||||
@@ -487,33 +537,48 @@ void TorrentOptionsDialog::handleTMMChanged()
|
||||
{
|
||||
if (m_ui->checkAutoTMM->checkState() == Qt::Unchecked)
|
||||
{
|
||||
m_ui->labelSavePath->setEnabled(true);
|
||||
m_ui->savePath->setEnabled(true);
|
||||
m_ui->groupBoxSavePath->setEnabled(true);
|
||||
m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(m_initialValues.savePath));
|
||||
m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(m_initialValues.downloadPath));
|
||||
m_ui->checkUseDownloadPath->setCheckState(m_initialValues.useDownloadPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->labelSavePath->setEnabled(false);
|
||||
m_ui->savePath->setEnabled(false);
|
||||
m_ui->groupBoxSavePath->setEnabled(false);
|
||||
if (m_ui->checkAutoTMM->checkState() == Qt::Checked)
|
||||
{
|
||||
if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0))
|
||||
{
|
||||
m_ui->savePath->setSelectedPath(QString());
|
||||
m_ui->downloadPath->setSelectedPath(QString());
|
||||
m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText());
|
||||
m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
|
||||
const QString downloadPath = BitTorrent::Session::instance()->categoryDownloadPath(m_ui->comboCategory->currentText());
|
||||
m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(downloadPath));
|
||||
m_ui->checkUseDownloadPath->setChecked(!downloadPath.isEmpty());
|
||||
}
|
||||
}
|
||||
else // partially checked
|
||||
{
|
||||
m_ui->savePath->setSelectedPath(QString());
|
||||
m_ui->downloadPath->setSelectedPath(QString());
|
||||
m_ui->checkUseDownloadPath->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentOptionsDialog::handleUseDownloadPathChanged()
|
||||
{
|
||||
const bool isChecked = m_ui->checkUseDownloadPath->checkState() == Qt::Checked;
|
||||
m_ui->downloadPath->setEnabled(isChecked);
|
||||
if (isChecked && m_ui->downloadPath->selectedPath().isEmpty())
|
||||
m_ui->downloadPath->setSelectedPath(BitTorrent::Session::instance()->downloadPath());
|
||||
}
|
||||
|
||||
void TorrentOptionsDialog::handleRatioTypeChanged()
|
||||
{
|
||||
if ((m_initialValues.ratio == MIXED_SHARE_LIMITS) || (m_initialValues.seedingTime == MIXED_SHARE_LIMITS))
|
||||
|
||||
@@ -62,6 +62,7 @@ public slots:
|
||||
private slots:
|
||||
void handleCategoryChanged(int index);
|
||||
void handleTMMChanged();
|
||||
void handleUseDownloadPathChanged();
|
||||
|
||||
void handleUpSpeedLimitChanged();
|
||||
void handleDownSpeedLimitChanged();
|
||||
@@ -82,12 +83,14 @@ private:
|
||||
struct
|
||||
{
|
||||
QString savePath;
|
||||
QString downloadPath;
|
||||
QString category;
|
||||
qreal ratio;
|
||||
int seedingTime;
|
||||
int upSpeedLimit;
|
||||
int downSpeedLimit;
|
||||
Qt::CheckState autoTMM;
|
||||
Qt::CheckState useDownloadPath;
|
||||
Qt::CheckState disableDHT;
|
||||
Qt::CheckState disablePEX;
|
||||
Qt::CheckState disableLSD;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>Torrent Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkAutoTMM">
|
||||
<property name="toolTip">
|
||||
@@ -24,33 +24,35 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSavePath">
|
||||
<property name="title">
|
||||
<string>Save at</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="FileSystemPathComboEdit" name="savePath" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkUseDownloadPath">
|
||||
<property name="text">
|
||||
<string>Use another path for incomplete torrent</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FileSystemPathComboEdit" name="downloadPath" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSavePath">
|
||||
<property name="text">
|
||||
<string>Save path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="FileSystemPathLineEdit" name="savePath" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelCategory">
|
||||
<property name="text">
|
||||
<string>Category:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboCategory">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -69,6 +71,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelCategory">
|
||||
<property name="text">
|
||||
<string>Category:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -310,7 +319,7 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FileSystemPathLineEdit</class>
|
||||
<class>FileSystemPathComboEdit</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/fspathedit.h</header>
|
||||
<container>1</container>
|
||||
|
||||
@@ -106,12 +106,12 @@ namespace
|
||||
void openDestinationFolder(const BitTorrent::Torrent *const torrent)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
MacUtils::openFiles({torrent->contentPath(true)});
|
||||
MacUtils::openFiles({torrent->contentPath()});
|
||||
#else
|
||||
if (torrent->filesCount() == 1)
|
||||
Utils::Gui::openFolderSelect(torrent->contentPath(true));
|
||||
Utils::Gui::openFolderSelect(torrent->contentPath());
|
||||
else
|
||||
Utils::Gui::openPath(torrent->contentPath(true));
|
||||
Utils::Gui::openPath(torrent->contentPath());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -525,22 +525,22 @@ void TransferListWidget::openSelectedTorrentsFolder() const
|
||||
// folders prehilighted for opening, so we use a custom method.
|
||||
for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents()))
|
||||
{
|
||||
QString path = torrent->contentPath(true);
|
||||
pathsList.insert(path);
|
||||
const QString contentPath = QDir(torrent->actualStorageLocation()).absoluteFilePath(torrent->contentPath());
|
||||
pathsList.insert(contentPath);
|
||||
}
|
||||
MacUtils::openFiles(pathsList);
|
||||
#else
|
||||
for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents()))
|
||||
{
|
||||
QString path = torrent->contentPath(true);
|
||||
if (!pathsList.contains(path))
|
||||
const QString contentPath = torrent->contentPath();
|
||||
if (!pathsList.contains(contentPath))
|
||||
{
|
||||
if (torrent->filesCount() == 1)
|
||||
Utils::Gui::openFolderSelect(path);
|
||||
Utils::Gui::openFolderSelect(contentPath);
|
||||
else
|
||||
Utils::Gui::openPath(path);
|
||||
Utils::Gui::openPath(contentPath);
|
||||
}
|
||||
pathsList.insert(path);
|
||||
pathsList.insert(contentPath);
|
||||
}
|
||||
#endif // Q_OS_MACOS
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ WatchedFolderOptionsDialog::WatchedFolderOptionsDialog(
|
||||
: QDialog {parent}
|
||||
, m_ui {new Ui::WatchedFolderOptionsDialog}
|
||||
, m_savePath {watchedFolderOptions.addTorrentParams.savePath}
|
||||
, m_downloadPath {watchedFolderOptions.addTorrentParams.downloadPath}
|
||||
, m_storeDialogSize {SETTINGS_KEY("DialogSize")}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
@@ -51,13 +52,18 @@ WatchedFolderOptionsDialog::WatchedFolderOptionsDialog(
|
||||
m_ui->savePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->savePath->setDialogCaption(tr("Choose save path"));
|
||||
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
|
||||
m_ui->downloadPath->setMode(FileSystemPathEdit::Mode::DirectorySave);
|
||||
m_ui->downloadPath->setDialogCaption(tr("Choose save path"));
|
||||
m_ui->groupBoxDownloadPath->setChecked(watchedFolderOptions.addTorrentParams.useDownloadPath.value_or(session->isDownloadPathEnabled()));
|
||||
|
||||
connect(m_ui->comboTTM, qOverload<int>(&QComboBox::currentIndexChanged), this, &WatchedFolderOptionsDialog::onTMMChanged);
|
||||
connect(m_ui->categoryComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &WatchedFolderOptionsDialog::onCategoryChanged);
|
||||
|
||||
m_ui->checkBoxRecursive->setChecked(watchedFolderOptions.recursive);
|
||||
populateSavePathComboBox();
|
||||
populateSavePaths();
|
||||
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
const BitTorrent::AddTorrentParams &torrentParams = watchedFolderOptions.addTorrentParams;
|
||||
m_ui->startTorrentCheckBox->setChecked(!torrentParams.addPaused.value_or(session->isAddTorrentPaused()));
|
||||
m_ui->skipCheckingCheckBox->setChecked(torrentParams.skipChecking);
|
||||
@@ -66,7 +72,7 @@ WatchedFolderOptionsDialog::WatchedFolderOptionsDialog(
|
||||
static_cast<int>(torrentParams.contentLayout.value_or(session->torrentContentLayout())));
|
||||
|
||||
// Load categories
|
||||
QStringList categories = session->categories().keys();
|
||||
QStringList categories = session->categories();
|
||||
std::sort(categories.begin(), categories.end(), Utils::Compare::NaturalLessThan<Qt::CaseInsensitive>());
|
||||
|
||||
if (!torrentParams.category.isEmpty())
|
||||
@@ -96,10 +102,16 @@ TorrentFilesWatcher::WatchedFolderOptions WatchedFolderOptionsDialog::watchedFol
|
||||
watchedFolderOptions.recursive = m_ui->checkBoxRecursive->isChecked();
|
||||
|
||||
BitTorrent::AddTorrentParams ¶ms = watchedFolderOptions.addTorrentParams;
|
||||
params.useAutoTMM = (m_ui->comboTTM->currentIndex() == 1);
|
||||
if (!*params.useAutoTMM)
|
||||
const bool useAutoTMM = (m_ui->comboTTM->currentIndex() == 1);
|
||||
if (!useAutoTMM)
|
||||
{
|
||||
params.savePath = m_ui->savePath->selectedPath();
|
||||
params.category = m_ui->categoryComboBox->currentText();;
|
||||
params.useDownloadPath = m_ui->groupBoxDownloadPath->isChecked();
|
||||
if (params.useDownloadPath)
|
||||
params.downloadPath = m_ui->downloadPath->selectedPath();
|
||||
}
|
||||
params.useAutoTMM = useAutoTMM;
|
||||
params.category = m_ui->categoryComboBox->currentText();
|
||||
params.addPaused = !m_ui->startTorrentCheckBox->isChecked();
|
||||
params.skipChecking = m_ui->skipCheckingCheckBox->isChecked();
|
||||
params.contentLayout = static_cast<BitTorrent::TorrentContentLayout>(m_ui->contentLayoutComboBox->currentIndex());
|
||||
@@ -121,34 +133,60 @@ void WatchedFolderOptionsDialog::onCategoryChanged(const int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
||||
const QString category = m_ui->categoryComboBox->currentText();
|
||||
if (m_ui->comboTTM->currentIndex() == 1)
|
||||
{
|
||||
const QString savePath = BitTorrent::Session::instance()->categorySavePath(category);
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
const QString categoryName = m_ui->categoryComboBox->currentText();
|
||||
|
||||
const QString savePath = btSession->categorySavePath(categoryName);
|
||||
m_ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath));
|
||||
|
||||
const QString finishedSavePath = btSession->categoryDownloadPath(categoryName);
|
||||
m_ui->downloadPath->setSelectedPath(Utils::Fs::toNativePath(finishedSavePath));
|
||||
|
||||
m_ui->groupBoxDownloadPath->setChecked(!finishedSavePath.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
void WatchedFolderOptionsDialog::populateSavePathComboBox()
|
||||
void WatchedFolderOptionsDialog::populateSavePaths()
|
||||
{
|
||||
const QString defSavePath {BitTorrent::Session::instance()->defaultSavePath()};
|
||||
m_ui->savePath->setSelectedPath(!m_savePath.isEmpty() ? m_savePath : defSavePath);
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
|
||||
const QString defaultSavePath {btSession->savePath()};
|
||||
m_ui->savePath->setSelectedPath(!m_savePath.isEmpty() ? m_savePath : defaultSavePath);
|
||||
|
||||
const QString defaultFinishedSavePath {btSession->downloadPath()};
|
||||
m_ui->downloadPath->setSelectedPath(!m_downloadPath.isEmpty() ? m_downloadPath : defaultFinishedSavePath);
|
||||
|
||||
m_ui->groupBoxDownloadPath->setChecked(m_useDownloadPath);
|
||||
}
|
||||
|
||||
void WatchedFolderOptionsDialog::onTMMChanged(const int index)
|
||||
{
|
||||
if (index != 1)
|
||||
{ // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
|
||||
populateSavePathComboBox();
|
||||
populateSavePaths();
|
||||
m_ui->groupBoxSavePath->setEnabled(true);
|
||||
m_ui->savePath->blockSignals(false);
|
||||
m_ui->downloadPath->blockSignals(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->groupBoxSavePath->setEnabled(false);
|
||||
|
||||
const auto *btSession = BitTorrent::Session::instance();
|
||||
|
||||
m_ui->savePath->blockSignals(true);
|
||||
m_savePath = m_ui->savePath->selectedPath();
|
||||
const QString savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->categoryComboBox->currentText());
|
||||
const QString savePath = btSession->categorySavePath(m_ui->categoryComboBox->currentText());
|
||||
m_ui->savePath->setSelectedPath(savePath);
|
||||
|
||||
m_ui->downloadPath->blockSignals(true);
|
||||
m_downloadPath = m_ui->downloadPath->selectedPath();
|
||||
const QString finishedSavePath = btSession->categoryDownloadPath(m_ui->categoryComboBox->currentText());
|
||||
m_ui->downloadPath->setSelectedPath(finishedSavePath);
|
||||
|
||||
m_useDownloadPath = m_ui->groupBoxDownloadPath->isChecked();
|
||||
m_ui->groupBoxDownloadPath->setChecked(!finishedSavePath.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
TorrentFilesWatcher::WatchedFolderOptions watchedFolderOptions() const;
|
||||
|
||||
private:
|
||||
void populateSavePathComboBox();
|
||||
void populateSavePaths();
|
||||
void loadState();
|
||||
void saveState();
|
||||
void onTMMChanged(int index);
|
||||
@@ -58,5 +58,7 @@ private:
|
||||
|
||||
Ui::WatchedFolderOptionsDialog *m_ui;
|
||||
QString m_savePath;
|
||||
QString m_downloadPath;
|
||||
bool m_useDownloadPath = false;
|
||||
SettingValue<QSize> m_storeDialogSize;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>462</width>
|
||||
<height>325</height>
|
||||
<height>364</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -119,6 +119,24 @@
|
||||
<item>
|
||||
<widget class="FileSystemPathLineEdit" name="savePath" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxDownloadPath">
|
||||
<property name="title">
|
||||
<string>Use another path for incomplete torrents</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="FileSystemPathLineEdit" name="downloadPath" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -296,6 +314,12 @@
|
||||
<header>gui/fspathedit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>FileSystemPathLineEdit</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/fspathedit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
||||
Reference in New Issue
Block a user