Change default torrent list filter behaviour

See https://github.com/qbittorrent/qBittorrent/issues/21059
This commit is contained in:
wdeweijer 2024-07-14 19:04:46 +02:00
parent 3b38d0de7f
commit 9bed341543
4 changed files with 115 additions and 1 deletions

View File

@ -54,6 +54,67 @@ QString Utils::String::wildcardToRegexPattern(const QString &pattern)
return QRegularExpression::wildcardToRegularExpression(pattern, QRegularExpression::UnanchoredWildcardConversion);
}
// namespace? private?
void toLookaheadRegex(QString &name, bool isPositive) {
name = QRegularExpression::escape(name);
if(isPositive)
name.prepend(u"(?=.*").append(u")");
else
name.prepend(u"(?!.*").append(u")");
}
QString Utils::String::parseFilter(const QString &filter)
{
QString ret;
ret.reserve(256);
ret.prepend(u"\\A"); // Start matching at beginning
bool inQuotes = false;
bool excluded = false;
QString tmp;
for (const QChar c : filter)
{
if (c == u'"') // What about patterns without spaces between quotes, like `bla""bla`
{
inQuotes = !inQuotes;
continue; // Don't inlude quotes in pattern
}
else if (!inQuotes) // ` ` and `-` are left alone inside quotes
{
if (c == u' ')
{
if (!tmp.isEmpty())
{
toLookaheadRegex(tmp, !excluded);
excluded = false;
ret.append(tmp);
tmp.clear();
}
continue;
}
else if (c == u'-' && tmp.isEmpty()) // only exclude when `-` is at start of word
{
excluded = true;
continue;
}
}
tmp.append(c);
}
if (!tmp.isEmpty())
{
toLookaheadRegex(tmp, !excluded);
ret.append(tmp);
}
return ret;
}
QStringList Utils::String::splitCommand(const QString &command)
{
QStringList ret;

View File

@ -44,6 +44,7 @@
namespace Utils::String
{
QString wildcardToRegexPattern(const QString &pattern);
QString parseFilter(const QString &filter);
template <typename T>
T unquote(const T &str, const QString &quotes = u"\""_s)

View File

@ -1328,7 +1328,7 @@ void TransferListWidget::applyFilter(const QString &name, const TransferListMode
{
m_sortFilterModel->setFilterKeyColumn(type);
const QString pattern = (Preferences::instance()->getRegexAsFilteringPatternForTransferList()
? name : Utils::String::wildcardToRegexPattern(name));
? name : Utils::String::parseFilter(name));
m_sortFilterModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption));
}

View File

@ -28,6 +28,7 @@
#include <QList>
#include <QObject>
#include <QRegularExpression>
#include <QTest>
#include "base/global.h"
@ -90,6 +91,57 @@ private slots:
QCOMPARE(Utils::String::splitCommand(u" cmd.exe /d --arg2 \"arg3\" \"\" arg5 \"\"arg6 \"arg7 "_s)
, QStringList({u"cmd.exe"_s, u"/d"_s, u"--arg2"_s, u"\"arg3\""_s, u"\"\""_s, u"arg5"_s, u"\"\"arg6"_s, u"\"arg7 "_s}));
}
void testparseFilter() const
{
QRegularExpression re0(Utils::String::parseFilter(u""_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u""_s.contains(re0));
QVERIFY(u"a"_s.contains(re0));
QRegularExpression re1(Utils::String::parseFilter(u"a"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"a"_s.contains(re1));
QVERIFY(u"bab"_s.contains(re1));
QVERIFY(!u"b"_s.contains(re1));
QRegularExpression re2(Utils::String::parseFilter(u"a b"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(!u"a"_s.contains(re2));
QVERIFY(!u"b"_s.contains(re2));
QVERIFY(u"a c b"_s.contains(re2));
QVERIFY(u"b a"_s.contains(re2));
QRegularExpression re3(Utils::String::parseFilter(u"a -b"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"a"_s.contains(re3));
QVERIFY(!u"a b"_s.contains(re3));
QRegularExpression re4(Utils::String::parseFilter(uR"(a "b c")"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(!u"a c b"_s.contains(re4));
QVERIFY(u"a b c"_s.contains(re4));
QRegularExpression re5(Utils::String::parseFilter(uR"(a -"b c")"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(!u"a b c"_s.contains(re5));
QVERIFY(u"a c b"_s.contains(re5));
QRegularExpression re6(Utils::String::parseFilter(uR"(a "b -c")"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"a b -c"_s.contains(re6));
QVERIFY(!u"a b c"_s.contains(re6));
QRegularExpression re7(Utils::String::parseFilter(uR"(a-b)"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"a-b"_s.contains(re7));
QVERIFY(!u"a b"_s.contains(re7));
QVERIFY(!u"a"_s.contains(re7));
QRegularExpression re8(Utils::String::parseFilter(uR"(.)"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"."_s.contains(re8));
QVERIFY(!u"a"_s.contains(re8));
QRegularExpression re9(Utils::String::parseFilter(uR"(*)"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"*"_s.contains(re9));
QVERIFY(!u"a"_s.contains(re9));
QRegularExpression re10(Utils::String::parseFilter(u"\"a"_s), QRegularExpression::CaseInsensitiveOption);
QVERIFY(u"a"_s.contains(re10));
QVERIFY(!u"b"_s.contains(re10));
}
};
QTEST_APPLESS_MAIN(TestUtilsString)