From 15697f904d43f792346d95845102d8d1dd62ad62 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 27 Feb 2024 12:57:55 +0800 Subject: [PATCH] Add a small delay before processing the key input of search boxes PR #20465. Closes #20025. Closes #20235. --- src/gui/addnewtorrentdialog.cpp | 2 + src/gui/addnewtorrentdialog.h | 4 +- src/gui/lineedit.cpp | 21 ++++++++++ src/gui/lineedit.h | 8 ++++ src/gui/mainwindow.cpp | 1 + src/gui/mainwindow.h | 1 + src/gui/search/searchjobwidget.cpp | 2 +- src/webui/www/private/scripts/client.js | 20 +++++----- src/webui/www/private/scripts/contextmenu.js | 2 + src/webui/www/private/scripts/dynamicTable.js | 5 +-- src/webui/www/private/scripts/misc.js | 2 + src/webui/www/private/scripts/prop-files.js | 38 ++++++++++--------- src/webui/www/private/views/log.html | 9 ++++- src/webui/www/private/views/search.html | 22 +++++------ 14 files changed, 87 insertions(+), 50 deletions(-) diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp index a6f82288d..f9c6862de 100644 --- a/src/gui/addnewtorrentdialog.cpp +++ b/src/gui/addnewtorrentdialog.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/src/gui/addnewtorrentdialog.h b/src/gui/addnewtorrentdialog.h index 16c68eacc..112c17e40 100644 --- a/src/gui/addnewtorrentdialog.h +++ b/src/gui/addnewtorrentdialog.h @@ -38,13 +38,13 @@ #include "base/path.h" #include "base/settingvalue.h" +class LineEdit; + namespace Ui { class AddNewTorrentDialog; } -class LineEdit; - class AddNewTorrentDialog final : public QDialog { Q_OBJECT diff --git a/src/gui/lineedit.cpp b/src/gui/lineedit.cpp index f388fab60..08a5aeea5 100644 --- a/src/gui/lineedit.cpp +++ b/src/gui/lineedit.cpp @@ -29,20 +29,41 @@ #include "lineedit.h" +#include + #include #include +#include #include "base/global.h" #include "uithememanager.h" +using namespace std::chrono_literals; + +namespace +{ + const std::chrono::milliseconds FILTER_INPUT_DELAY {400}; +} + LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) + , m_delayedTextChangedTimer {new QTimer(this)} { auto *action = new QAction(UIThemeManager::instance()->getIcon(u"edit-find"_s), QString(), this); addAction(action, QLineEdit::LeadingPosition); setClearButtonEnabled(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + + m_delayedTextChangedTimer->setSingleShot(true); + connect(m_delayedTextChangedTimer, &QTimer::timeout, this, [this] + { + emit textChanged(text()); + }); + connect(this, &QLineEdit::textChanged, this, [this] + { + m_delayedTextChangedTimer->start(FILTER_INPUT_DELAY); + }); } void LineEdit::keyPressEvent(QKeyEvent *event) diff --git a/src/gui/lineedit.h b/src/gui/lineedit.h index 55ed3bd85..459740f86 100644 --- a/src/gui/lineedit.h +++ b/src/gui/lineedit.h @@ -31,6 +31,9 @@ #include +class QKeyEvent; +class QTimer; + class LineEdit final : public QLineEdit { Q_OBJECT @@ -39,6 +42,11 @@ class LineEdit final : public QLineEdit public: explicit LineEdit(QWidget *parent = nullptr); +signals: + void textChanged(const QString &text); + private: void keyPressEvent(QKeyEvent *event) override; + + QTimer *m_delayedTextChangedTimer = nullptr; }; diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index e1d6cf28c..74e46c1cf 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include "base/bittorrent/session.h" diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index d122cdbb3..c4e717899 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -42,6 +42,7 @@ class QCloseEvent; class QComboBox; class QFileSystemWatcher; class QSplitter; +class QString; class QTabWidget; class QTimer; diff --git a/src/gui/search/searchjobwidget.cpp b/src/gui/search/searchjobwidget.cpp index 99f06b6ac..d2fcc4556 100644 --- a/src/gui/search/searchjobwidget.cpp +++ b/src/gui/search/searchjobwidget.cpp @@ -126,9 +126,9 @@ SearchJobWidget::SearchJobWidget(SearchHandler *searchHandler, IGUIApplication * m_lineEditSearchResultsFilter->setPlaceholderText(tr("Filter search results...")); m_lineEditSearchResultsFilter->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_lineEditSearchResultsFilter, &QWidget::customContextMenuRequested, this, &SearchJobWidget::showFilterContextMenu); + connect(m_lineEditSearchResultsFilter, &LineEdit::textChanged, this, &SearchJobWidget::filterSearchResults); m_ui->horizontalLayout->insertWidget(0, m_lineEditSearchResultsFilter); - connect(m_lineEditSearchResultsFilter, &LineEdit::textChanged, this, &SearchJobWidget::filterSearchResults); connect(m_ui->filterMode, qOverload(&QComboBox::currentIndexChanged) , this, &SearchJobWidget::updateFilter); connect(m_ui->minSeeds, &QAbstractSpinBox::editingFinished, this, &SearchJobWidget::updateFilter); diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index d6f108678..0abe49705 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -695,6 +695,8 @@ window.addEventListener("DOMContentLoaded", function() { $('error_div').set('html', ''); if (response) { clearTimeout(torrentsFilterInputTimer); + torrentsFilterInputTimer = -1; + let torrentsTableSelectedRows; let update_categories = false; let updateTags = false; @@ -1449,18 +1451,14 @@ window.addEventListener("DOMContentLoaded", function() { $('torrentFilesFilterToolbar').addClass("invisible"); }; - let prevTorrentsFilterValue; - let torrentsFilterInputTimer = null; // listen for changes to torrentsFilterInput - $('torrentsFilterInput').addEvent('input', function() { - const value = $('torrentsFilterInput').get("value"); - if (value !== prevTorrentsFilterValue) { - prevTorrentsFilterValue = value; - clearTimeout(torrentsFilterInputTimer); - torrentsFilterInputTimer = setTimeout(function() { - torrentsTable.updateTable(false); - }, 400); - } + let torrentsFilterInputTimer = -1; + $('torrentsFilterInput').addEvent('input', () => { + clearTimeout(torrentsFilterInputTimer); + torrentsFilterInputTimer = setTimeout(() => { + torrentsFilterInputTimer = -1; + torrentsTable.updateTable(); + }, window.qBittorrent.Misc.FILTER_INPUT_DELAY); }); $('transfersTabLink').addEvent('click', showTransfersTab); diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index c03f09e4e..e716be9d9 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -175,12 +175,14 @@ window.qBittorrent.ContextMenu = (function() { const touchstartEvent = e; this.touchstartTimer = setTimeout(function() { + this.touchstartTimer = -1; this.triggerMenu(touchstartEvent, elem); }.bind(this), this.options.touchTimer); }.bind(this)); elem.addEvent('touchend', function(e) { e.preventDefault(); clearTimeout(this.touchstartTimer); + this.touchstartTimer = -1; }.bind(this)); }, diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index e6b1e18e8..ce0e7d2eb 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -701,10 +701,7 @@ window.qBittorrent.DynamicTable = (function() { return null; }, - updateTable: function(fullUpdate) { - if (fullUpdate === undefined) - fullUpdate = false; - + updateTable: function(fullUpdate = false) { const rows = this.getFilteredAndSortedRows(); for (let i = 0; i < this.selectedRows.length; ++i) diff --git a/src/webui/www/private/scripts/misc.js b/src/webui/www/private/scripts/misc.js index 659f5f1f7..61fa34406 100644 --- a/src/webui/www/private/scripts/misc.js +++ b/src/webui/www/private/scripts/misc.js @@ -47,6 +47,8 @@ window.qBittorrent.Misc = (function() { toFixedPointString: toFixedPointString, containsAllTerms: containsAllTerms, sleep: sleep, + // variables + FILTER_INPUT_DELAY: 400, MAX_ETA: 8640000 }; }; diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js index f16809d2e..09bfbfe97 100644 --- a/src/webui/www/private/scripts/prop-files.js +++ b/src/webui/www/private/scripts/prop-files.js @@ -366,6 +366,7 @@ window.qBittorrent.PropFiles = (function() { }, onSuccess: function(files) { clearTimeout(torrentFilesFilterInputTimer); + torrentFilesFilterInputTimer = -1; if (files.length === 0) { torrentFilesTable.clear(); @@ -640,26 +641,27 @@ window.qBittorrent.PropFiles = (function() { if (torrentFilesTable.getSortedColumn() === null) torrentFilesTable.setSortedColumn('name'); - let prevTorrentFilesFilterValue; - let torrentFilesFilterInputTimer = null; // listen for changes to torrentFilesFilterInput - $('torrentFilesFilterInput').addEvent('input', function() { - const value = $('torrentFilesFilterInput').get("value"); - if (value !== prevTorrentFilesFilterValue) { - prevTorrentFilesFilterValue = value; - torrentFilesTable.setFilter(value); - clearTimeout(torrentFilesFilterInputTimer); - torrentFilesFilterInputTimer = setTimeout(function() { - if (current_hash === "") - return; - torrentFilesTable.updateTable(false); + let torrentFilesFilterInputTimer = -1; + $('torrentFilesFilterInput').addEvent('input', () => { + clearTimeout(torrentFilesFilterInputTimer); - if (value.trim() === "") - collapseAllNodes(); - else - expandAllNodes(); - }, 400); - } + const value = $('torrentFilesFilterInput').get("value"); + torrentFilesTable.setFilter(value); + + torrentFilesFilterInputTimer = setTimeout(() => { + torrentFilesFilterInputTimer = -1; + + if (current_hash === "") + return; + + torrentFilesTable.updateTable(); + + if (value.trim() === "") + collapseAllNodes(); + else + expandAllNodes(); + }, window.qBittorrent.Misc.FILTER_INPUT_DELAY); }); /** diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index 3f12aeb4e..3442cf939 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -183,7 +183,7 @@ }; let customSyncLogDataInterval = null; - let logFilterTimer; + let logFilterTimer = -1; let inputtedFilterText = ""; let selectBox; let selectedLogLevels = JSON.parse(LocalPreferences.get('qbt_selected_log_levels')) || ['1', '2', '4', '8']; @@ -298,9 +298,11 @@ const logFilterChanged = () => { clearTimeout(logFilterTimer); logFilterTimer = setTimeout((curTab) => { + logFilterTimer = -1; + tableInfo[curTab].instance.updateTable(false); updateLabelCount(curTab); - }, 400, currentSelectedTab); + }, window.qBittorrent.Misc.FILTER_INPUT_DELAY, currentSelectedTab); }; const setCurrentTab = (tab) => { @@ -322,6 +324,7 @@ } clearTimeout(logFilterTimer); + logFilterTimer = -1; load(); if (tableInfo[currentSelectedTab].instance.filterText !== getFilterText()) { @@ -378,6 +381,8 @@ if (response.length > 0) { clearTimeout(logFilterTimer); + logFilterTimer = -1; + for (let i = 0; i < response.length; ++i) { let row; if (curTab === 'main') { diff --git a/src/webui/www/private/views/search.html b/src/webui/www/private/views/search.html index 2c24341e8..338274e39 100644 --- a/src/webui/www/private/views/search.html +++ b/src/webui/www/private/views/search.html @@ -230,7 +230,6 @@ max: 0.00, maxUnit: 3 }; - let prevNameFilterValue; let selectedCategory = "QBT_TR(All categories)QBT_TR[CONTEXT=SearchEngineWidget]"; let selectedPlugin = "all"; let prevSelectedPlugin; @@ -255,18 +254,17 @@ searchResultsTable.setup('searchResultsTableDiv', 'searchResultsTableFixedHeaderDiv', searchResultsTableContextMenu); getPlugins(); - let searchInNameFilterTimer = null; // listen for changes to searchInNameFilter - $('searchInNameFilter').addEvent('input', function() { - const value = $('searchInNameFilter').get("value"); - if (value !== prevNameFilterValue) { - prevNameFilterValue = value; - clearTimeout(searchInNameFilterTimer); - searchInNameFilterTimer = setTimeout(function() { - searchText.filterPattern = value; - searchFilterChanged(); - }, 400); - } + let searchInNameFilterTimer = -1; + $('searchInNameFilter').addEvent('input', () => { + clearTimeout(searchInNameFilterTimer); + searchInNameFilterTimer = setTimeout(() => { + searchInNameFilterTimer = -1; + + const value = $('searchInNameFilter').get("value"); + searchText.filterPattern = value; + searchFilterChanged(); + }, window.qBittorrent.Misc.FILTER_INPUT_DELAY); }); new Keyboard({