Skip to content

Commit

Permalink
Change default torrent list filter behaviour
Browse files Browse the repository at this point in the history
See #21059
  • Loading branch information
wdeweijer committed Jul 20, 2024
1 parent 3b38d0d commit 9bed341
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 1 deletion.
61 changes: 61 additions & 0 deletions src/base/utils/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/base/utils/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/gui/transferlistwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down
52 changes: 52 additions & 0 deletions test/testutilsstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <QList>
#include <QObject>
#include <QRegularExpression>
#include <QTest>

#include "base/global.h"
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 9bed341

Please sign in to comment.