mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 13:23:34 -07:00
feat: Add functionality to Desktop/App too.
* Add preference flag that is turned **OFF** by default * Exposes the `Type` in `TorrentFilter` so that we can know on which status we are. * Maintains a `QHash` object with the `Status` as `key` and the pair of `column` + `sort order` as `value`. * This sorting is maintained for the session being, we do not save between shutdowns of QBT
This commit is contained in:
parent
f51d07cc94
commit
e13139a264
12 changed files with 69 additions and 2 deletions
|
@ -425,6 +425,19 @@ void Preferences::setPreventFromSuspendWhenSeeding(const bool b)
|
||||||
setValue(u"Preferences/General/PreventFromSuspendWhenSeeding"_s, b);
|
setValue(u"Preferences/General/PreventFromSuspendWhenSeeding"_s, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::usePerStatusSortOrder() const
|
||||||
|
{
|
||||||
|
return value(u"Preferences/General/UsePerStatusSortOrder"_s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setUsePerStatusSortOrder(const bool use)
|
||||||
|
{
|
||||||
|
if (use == usePerStatusSortOrder())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setValue(u"Preferences/General/UsePerStatusSortOrder"_s, use);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
bool Preferences::WinStartup() const
|
bool Preferences::WinStartup() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,6 +162,9 @@ public:
|
||||||
int getActionOnDblClOnTorrentFn() const;
|
int getActionOnDblClOnTorrentFn() const;
|
||||||
void setActionOnDblClOnTorrentFn(int act);
|
void setActionOnDblClOnTorrentFn(int act);
|
||||||
|
|
||||||
|
bool usePerStatusSortOrder() const;
|
||||||
|
void setUsePerStatusSortOrder(bool use);
|
||||||
|
|
||||||
// Connection options
|
// Connection options
|
||||||
QTime getSchedulerStartTime() const;
|
QTime getSchedulerStartTime() const;
|
||||||
void setSchedulerStartTime(const QTime &time);
|
void setSchedulerStartTime(const QTime &time);
|
||||||
|
|
|
@ -100,6 +100,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
bool setType(Type type);
|
bool setType(Type type);
|
||||||
|
Type getType() const { return m_type; }
|
||||||
bool setTypeByName(const QString &filter);
|
bool setTypeByName(const QString &filter);
|
||||||
bool setTorrentIDSet(const std::optional<TorrentIDSet> &idSet);
|
bool setTorrentIDSet(const std::optional<TorrentIDSet> &idSet);
|
||||||
bool setCategory(const std::optional<QString> &category);
|
bool setCategory(const std::optional<QString> &category);
|
||||||
|
|
|
@ -358,6 +358,7 @@ void OptionsDialog::loadBehaviorTabOptions()
|
||||||
m_ui->checkBoxFreeDiskSpaceStatusBar->setChecked(pref->isStatusbarFreeDiskSpaceDisplayed());
|
m_ui->checkBoxFreeDiskSpaceStatusBar->setChecked(pref->isStatusbarFreeDiskSpaceDisplayed());
|
||||||
m_ui->checkBoxExternalIPStatusBar->setChecked(pref->isStatusbarExternalIPDisplayed());
|
m_ui->checkBoxExternalIPStatusBar->setChecked(pref->isStatusbarExternalIPDisplayed());
|
||||||
m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled());
|
m_ui->checkBoxPerformanceWarning->setChecked(session->isPerformanceWarningEnabled());
|
||||||
|
m_ui->checkBoxPerFilterSorting->setChecked(pref->usePerStatusSortOrder());
|
||||||
|
|
||||||
connect(m_ui->comboLanguage, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->comboLanguage, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
|
||||||
|
|
||||||
|
@ -447,6 +448,7 @@ void OptionsDialog::loadBehaviorTabOptions()
|
||||||
connect(m_ui->checkBoxFreeDiskSpaceStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBoxFreeDiskSpaceStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->checkBoxExternalIPStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBoxExternalIPStatusBar, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->checkBoxPerformanceWarning, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBoxPerformanceWarning, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
|
connect(m_ui->checkBoxPerFilterSorting, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsDialog::saveBehaviorTabOptions() const
|
void OptionsDialog::saveBehaviorTabOptions() const
|
||||||
|
@ -540,6 +542,7 @@ void OptionsDialog::saveBehaviorTabOptions() const
|
||||||
|
|
||||||
pref->setStatusbarFreeDiskSpaceDisplayed(m_ui->checkBoxFreeDiskSpaceStatusBar->isChecked());
|
pref->setStatusbarFreeDiskSpaceDisplayed(m_ui->checkBoxFreeDiskSpaceStatusBar->isChecked());
|
||||||
pref->setStatusbarExternalIPDisplayed(m_ui->checkBoxExternalIPStatusBar->isChecked());
|
pref->setStatusbarExternalIPDisplayed(m_ui->checkBoxExternalIPStatusBar->isChecked());
|
||||||
|
pref->setUsePerStatusSortOrder(m_ui->checkBoxPerFilterSorting->isChecked());
|
||||||
session->setPerformanceWarningEnabled(m_ui->checkBoxPerformanceWarning->isChecked());
|
session->setPerformanceWarningEnabled(m_ui->checkBoxPerformanceWarning->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -840,6 +840,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBoxPerFilterSorting">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use Per-Status Sorting</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_4">
|
<spacer name="verticalSpacer_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -123,6 +123,11 @@ void TransferListSortModel::sort(const int column, const Qt::SortOrder order)
|
||||||
QSortFilterProxyModel::sort(column, order);
|
QSortFilterProxyModel::sort(column, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TorrentFilter::Type TransferListSortModel::getType() const
|
||||||
|
{
|
||||||
|
return m_filter.getType();
|
||||||
|
}
|
||||||
|
|
||||||
void TransferListSortModel::setStatusFilter(const TorrentFilter::Type filter)
|
void TransferListSortModel::setStatusFilter(const TorrentFilter::Type filter)
|
||||||
{
|
{
|
||||||
if (m_filter.setType(filter))
|
if (m_filter.setType(filter))
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void disableTagFilter();
|
void disableTagFilter();
|
||||||
void setTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs);
|
void setTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs);
|
||||||
void disableTrackerFilter();
|
void disableTrackerFilter();
|
||||||
|
TorrentFilter::Type getType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int compare(const QModelIndex &left, const QModelIndex &right) const;
|
int compare(const QModelIndex &left, const QModelIndex &right) const;
|
||||||
|
|
|
@ -1336,7 +1336,26 @@ void TransferListWidget::applyFilter(const QString &name, const TransferListMode
|
||||||
void TransferListWidget::applyStatusFilter(const int filterIndex)
|
void TransferListWidget::applyStatusFilter(const int filterIndex)
|
||||||
{
|
{
|
||||||
const auto filterType = static_cast<TorrentFilter::Type>(filterIndex);
|
const auto filterType = static_cast<TorrentFilter::Type>(filterIndex);
|
||||||
|
//Save sort order for old filter
|
||||||
|
const bool usePerFilterSort = Preferences::instance()->usePerStatusSortOrder();
|
||||||
|
const TorrentFilter::Type filter = m_sortFilterModel->getType();
|
||||||
|
const int column = m_sortFilterModel->sortColumn();
|
||||||
|
if (column != -1 && usePerFilterSort)
|
||||||
|
{
|
||||||
|
m_statusSortPairs.insert_or_assign(filter, qMakePair(column, m_sortFilterModel->sortOrder()));
|
||||||
|
}
|
||||||
|
|
||||||
m_sortFilterModel->setStatusFilter(((filterType >= TorrentFilter::All) && (filterType < TorrentFilter::_Count)) ? filterType : TorrentFilter::All);
|
m_sortFilterModel->setStatusFilter(((filterType >= TorrentFilter::All) && (filterType < TorrentFilter::_Count)) ? filterType : TorrentFilter::All);
|
||||||
|
|
||||||
|
// Load sort for new status filter
|
||||||
|
if (m_statusSortPairs.contains(filterType) && usePerFilterSort)
|
||||||
|
{
|
||||||
|
const QPair<int, Qt::SortOrder> sortPair = m_statusSortPairs.value(filterType);
|
||||||
|
m_sortFilterModel->sort(sortPair.first, sortPair.second);
|
||||||
|
// Rows are sorted correctly, but header state does not reflect actual sort setting
|
||||||
|
header()->setSortIndicator(sortPair.first, sortPair.second);
|
||||||
|
}
|
||||||
|
|
||||||
// Select first item if nothing is selected
|
// Select first item if nothing is selected
|
||||||
if (selectionModel()->selectedRows(0).empty() && (m_sortFilterModel->rowCount() > 0))
|
if (selectionModel()->selectedRows(0).empty() && (m_sortFilterModel->rowCount() > 0))
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
|
||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
|
#include "base/torrentfilter.h"
|
||||||
#include "guiapplicationcomponent.h"
|
#include "guiapplicationcomponent.h"
|
||||||
#include "transferlistmodel.h"
|
#include "transferlistmodel.h"
|
||||||
|
|
||||||
|
@ -137,6 +138,7 @@ private:
|
||||||
void applyToSelectedTorrents(const std::function<void (BitTorrent::Torrent *const)> &fn);
|
void applyToSelectedTorrents(const std::function<void (BitTorrent::Torrent *const)> &fn);
|
||||||
QList<BitTorrent::Torrent *> getVisibleTorrents() const;
|
QList<BitTorrent::Torrent *> getVisibleTorrents() const;
|
||||||
int visibleColumnsCount() const;
|
int visibleColumnsCount() const;
|
||||||
|
QHash<TorrentFilter::Type, QPair<int, Qt::SortOrder>> m_statusSortPairs;
|
||||||
|
|
||||||
TransferListModel *m_listModel = nullptr;
|
TransferListModel *m_listModel = nullptr;
|
||||||
TransferListSortModel *m_sortFilterModel = nullptr;
|
TransferListSortModel *m_sortFilterModel = nullptr;
|
||||||
|
|
|
@ -137,6 +137,7 @@ void AppController::preferencesAction()
|
||||||
data[u"locale"_s] = pref->getLocale();
|
data[u"locale"_s] = pref->getLocale();
|
||||||
data[u"performance_warning"_s] = session->isPerformanceWarningEnabled();
|
data[u"performance_warning"_s] = session->isPerformanceWarningEnabled();
|
||||||
data[u"status_bar_external_ip"_s] = pref->isStatusbarExternalIPDisplayed();
|
data[u"status_bar_external_ip"_s] = pref->isStatusbarExternalIPDisplayed();
|
||||||
|
data[u"per_status_sorting"_s] = pref->usePerStatusSortOrder();
|
||||||
// Transfer List
|
// Transfer List
|
||||||
data[u"confirm_torrent_deletion"_s] = pref->confirmTorrentDeletion();
|
data[u"confirm_torrent_deletion"_s] = pref->confirmTorrentDeletion();
|
||||||
// Log file
|
// Log file
|
||||||
|
@ -530,6 +531,8 @@ void AppController::setPreferencesAction()
|
||||||
pref->setStatusbarExternalIPDisplayed(it.value().toBool());
|
pref->setStatusbarExternalIPDisplayed(it.value().toBool());
|
||||||
if (hasKey(u"performance_warning"_s))
|
if (hasKey(u"performance_warning"_s))
|
||||||
session->setPerformanceWarningEnabled(it.value().toBool());
|
session->setPerformanceWarningEnabled(it.value().toBool());
|
||||||
|
if (hasKey(u"per_status_sorting"_s))
|
||||||
|
pref->setUsePerStatusSortOrder(it.value().toBool());
|
||||||
// Transfer List
|
// Transfer List
|
||||||
if (hasKey(u"confirm_torrent_deletion"_s))
|
if (hasKey(u"confirm_torrent_deletion"_s))
|
||||||
pref->setConfirmTorrentDeletion(it.value().toBool());
|
pref->setConfirmTorrentDeletion(it.value().toBool());
|
||||||
|
|
|
@ -267,21 +267,24 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
|
||||||
setStatusFilter = (name) => {
|
setStatusFilter = (name) => {
|
||||||
const currentHash = torrentsTable.getCurrentTorrentID();
|
const currentHash = torrentsTable.getCurrentTorrentID();
|
||||||
|
const usePerFilterSorting = window.qBittorrent.Cache.preferences.get().per_status_sorting;
|
||||||
|
|
||||||
// Save current sorting for this filter.
|
// Save current sorting for this filter.
|
||||||
if (torrentsTable.getSortedColumn()) {
|
if ((torrentsTable.getSortedColumn()) && usePerFilterSorting) {
|
||||||
LocalPreferences.set(`selected_filter_sort_${selectedStatus}`, torrentsTable.getSortedColumn());
|
LocalPreferences.set(`selected_filter_sort_${selectedStatus}`, torrentsTable.getSortedColumn());
|
||||||
LocalPreferences.set(`selected_filter_sort_reverse_${selectedStatus}`, (torrentsTable.reverseSort ?? "0"));
|
LocalPreferences.set(`selected_filter_sort_reverse_${selectedStatus}`, (torrentsTable.reverseSort ?? "0"));
|
||||||
}
|
}
|
||||||
LocalPreferences.set("selected_filter", name);
|
LocalPreferences.set("selected_filter", name);
|
||||||
|
|
||||||
// If there is a saved sorting column, load it.
|
// If there is a saved sorting column, load it.
|
||||||
const sortColumn = LocalPreferences.get(`selected_filter_sort_${name}`);
|
const sortColumn = LocalPreferences.get(`selected_filter_sort_${name}`);
|
||||||
if (sortColumn !== null) {
|
if ((sortColumn !== null) && usePerFilterSorting) {
|
||||||
torrentsTable.setSortedColumn(
|
torrentsTable.setSortedColumn(
|
||||||
sortColumn,
|
sortColumn,
|
||||||
LocalPreferences.get(`selected_filter_sort_reverse_${name}`, "0")
|
LocalPreferences.get(`selected_filter_sort_reverse_${name}`, "0")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedStatus = name;
|
selectedStatus = name;
|
||||||
highlightSelectedStatus();
|
highlightSelectedStatus();
|
||||||
updateMainData();
|
updateMainData();
|
||||||
|
|
|
@ -100,6 +100,11 @@
|
||||||
<label for="performanceWarning">QBT_TR(Log performance warnings)QBT_TR[CONTEXT=OptionsDialog]</label>
|
<label for="performanceWarning">QBT_TR(Log performance warnings)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="formRow" style="margin-bottom: 5px;">
|
||||||
|
<input type="checkbox" id="perStatusSorting">
|
||||||
|
<label for="perStatusSorting">QBT_TR(Use Per-Status Sorting)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<fieldset class="settings">
|
<fieldset class="settings">
|
||||||
<legend title="QBT_TR(Following settings are WebUI only)QBT_TR[CONTEXT=OptionsDialog]">QBT_TR(Custom WebUI settings)QBT_TR[CONTEXT=OptionsDialog]</legend>
|
<legend title="QBT_TR(Following settings are WebUI only)QBT_TR[CONTEXT=OptionsDialog]">QBT_TR(Custom WebUI settings)QBT_TR[CONTEXT=OptionsDialog]</legend>
|
||||||
<div class="formRow" style="margin-bottom: 3px;">
|
<div class="formRow" style="margin-bottom: 3px;">
|
||||||
|
@ -2224,6 +2229,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
updateColoSchemeSelect();
|
updateColoSchemeSelect();
|
||||||
document.getElementById("statusBarExternalIP").checked = pref.status_bar_external_ip;
|
document.getElementById("statusBarExternalIP").checked = pref.status_bar_external_ip;
|
||||||
document.getElementById("performanceWarning").checked = pref.performance_warning;
|
document.getElementById("performanceWarning").checked = pref.performance_warning;
|
||||||
|
document.getElementById("perStatusSorting").checked = pref.per_status_sorting;
|
||||||
document.getElementById("displayFullURLTrackerColumn").checked = (LocalPreferences.get("full_url_tracker_column", "false") === "true");
|
document.getElementById("displayFullURLTrackerColumn").checked = (LocalPreferences.get("full_url_tracker_column", "false") === "true");
|
||||||
document.getElementById("useVirtualList").checked = (LocalPreferences.get("use_virtual_list", "false") === "true");
|
document.getElementById("useVirtualList").checked = (LocalPreferences.get("use_virtual_list", "false") === "true");
|
||||||
document.getElementById("hideZeroFiltersCheckbox").checked = (LocalPreferences.get("hide_zero_status_filters", "false") === "true");
|
document.getElementById("hideZeroFiltersCheckbox").checked = (LocalPreferences.get("hide_zero_status_filters", "false") === "true");
|
||||||
|
@ -2657,6 +2663,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
LocalPreferences.set("color_scheme", "dark");
|
LocalPreferences.set("color_scheme", "dark");
|
||||||
settings["status_bar_external_ip"] = document.getElementById("statusBarExternalIP").checked;
|
settings["status_bar_external_ip"] = document.getElementById("statusBarExternalIP").checked;
|
||||||
settings["performance_warning"] = document.getElementById("performanceWarning").checked;
|
settings["performance_warning"] = document.getElementById("performanceWarning").checked;
|
||||||
|
settings["per_status_sorting"] = document.getElementById("perStatusSorting").checked;
|
||||||
LocalPreferences.set("full_url_tracker_column", document.getElementById("displayFullURLTrackerColumn").checked.toString());
|
LocalPreferences.set("full_url_tracker_column", document.getElementById("displayFullURLTrackerColumn").checked.toString());
|
||||||
LocalPreferences.set("use_virtual_list", document.getElementById("useVirtualList").checked.toString());
|
LocalPreferences.set("use_virtual_list", document.getElementById("useVirtualList").checked.toString());
|
||||||
LocalPreferences.set("hide_zero_status_filters", document.getElementById("hideZeroFiltersCheckbox").checked.toString());
|
LocalPreferences.set("hide_zero_status_filters", document.getElementById("hideZeroFiltersCheckbox").checked.toString());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue