Skip to content

Commit

Permalink
QAbstractItemModel: implement QRegularExpression support for match
Browse files Browse the repository at this point in the history
This is part of the migration of qtbase from QRexExp to
QRegularExpression.

[ChangeLog][QtCore][QAbstractItemModel] The match() method now
supports the new Qt::RegularExpression match flag value. This
will allow users to use either a string or a fully configured
QRegularExpression when doing searches. In the second case,
the case sensitivity flag will be ignored if passed.

Task-number: QTBUG-72587
Change-Id: I07c8d72a661c48b7f4fcf13ef8e95980bcdcb998
Reviewed-by: Giuseppe D'Angelo <[email protected]>
  • Loading branch information
sgaist committed Oct 16, 2019
1 parent 85ed676 commit c222a92
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 17 deletions.
5 changes: 4 additions & 1 deletion src/corelib/global/qnamespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1575,9 +1575,12 @@ Qt {
MatchContains = 1,
MatchStartsWith = 2,
MatchEndsWith = 3,
MatchRegExp = 4,
#if QT_DEPRECATED_SINCE(5, 15)
MatchRegExp Q_DECL_ENUMERATOR_DEPRECATED_X("MatchRegExp is deprecated. Use MatchRegularExpression instead") = 4,
#endif
MatchWildcard = 5,
MatchFixedString = 8,
MatchRegularExpression = 9,
MatchCaseSensitive = 16,
MatchWrap = 32,
MatchRecursive = 64
Expand Down
32 changes: 20 additions & 12 deletions src/corelib/global/qnamespace.qdoc
Original file line number Diff line number Diff line change
Expand Up @@ -2840,24 +2840,32 @@
This enum describes the type of matches that can be used when searching
for items in a model.

\value MatchExactly Performs QVariant-based matching.
\value MatchFixedString Performs string-based matching.
\value MatchExactly Performs QVariant-based matching.
\value MatchFixedString Performs string-based matching.
String-based comparisons are case-insensitive unless the
\c MatchCaseSensitive flag is also specified.
\value MatchContains The search term is contained in the item.
\value MatchStartsWith The search term matches the start of the item.
\value MatchEndsWith The search term matches the end of the item.
\value MatchCaseSensitive The search is case sensitive.
\value MatchRegExp Performs string-based matching using a regular
expression as the search term.
\value MatchWildcard Performs string-based matching using a string with
\value MatchContains The search term is contained in the item.
\value MatchStartsWith The search term matches the start of the item.
\value MatchEndsWith The search term matches the end of the item.
\value MatchCaseSensitive The search is case sensitive.
\value MatchRegExp Performs string-based matching using a regular
expression as the search term. Uses the deprecated QRegExp class.
\e{This enum value is deprecated since Qt 5.15.}
\value MatchRegularExpression Performs string-based matching using a regular
expression as the search term. Uses QRegularExpression.
When using this flag, a QRegularExpression object can be passed as
parameter and will directly be used to perform the search. The case
sensitivity flag will be ignored as the QRegularExpression object is
expected to be fully configured.
This enum value was added in Qt 5.15.
\value MatchWildcard Performs string-based matching using a string with
wildcards as the search term.
\value MatchWrap Perform a search that wraps around, so that when
\value MatchWrap Perform a search that wraps around, so that when
the search reaches the last item in the model, it begins again at
the first item and continues until all items have been examined.
\value MatchRecursive Searches the entire hierarchy.
\value MatchRecursive Searches the entire hierarchy.

\sa QString::compare(), QRegExp
\sa QString::compare(), QRegExp, QRegularExpression
*/

/*!
Expand Down
32 changes: 28 additions & 4 deletions src/corelib/itemmodels/qabstractitemmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <qdebug.h>
#include <qvector.h>
#include <qregexp.h>
#include <qregularexpression.h>
#include <qstack.h>
#include <qbitarray.h>
#include <qdatetime.h>
Expand Down Expand Up @@ -2358,6 +2359,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
bool wrap = flags & Qt::MatchWrap;
bool allHits = (hits == -1);
QString text; // only convert to a string if it is needed
QRegularExpression rx; // only create it if needed
const int column = start.column();
QModelIndex p = parent(start);
int from = start.row();
Expand All @@ -2374,17 +2376,39 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
if (matchType == Qt::MatchExactly) {
if (value == v)
result.append(idx);
} else { // QString based matching
if (text.isEmpty()) // lazy conversion
text = value.toString();
} else { // QString or regular expression based matching
if (matchType == Qt::MatchRegularExpression) {
if (rx.pattern().isEmpty()) {
if (value.type() == QVariant::RegularExpression) {
rx = value.toRegularExpression();
} else {
rx.setPattern(value.toString());
if (cs == Qt::CaseInsensitive)
rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
}
}
} else if (matchType == Qt::MatchWildcard) {
if (rx.pattern().isEmpty())
rx.setPattern(QRegularExpression::wildcardToRegularExpression(value.toString()));
if (cs == Qt::CaseInsensitive)
rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
} else {
if (text.isEmpty()) // lazy conversion
text = value.toString();
}

QString t = v.toString();
switch (matchType) {
#if QT_DEPRECATED_SINCE(5, 15)
case Qt::MatchRegExp:
if (QRegExp(text, cs).exactMatch(t))
result.append(idx);
break;
#endif
case Qt::MatchRegularExpression:
Q_FALLTHROUGH();
case Qt::MatchWildcard:
if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
if (t.contains(rx))
result.append(idx);
break;
case Qt::MatchStartsWith:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,34 @@ void tst_QAbstractItemModel::match()
res = model.match(start, Qt::DisplayRole, QVariant("bat"), -1,
Qt::MatchFixedString | Qt::MatchCaseSensitive);
QCOMPARE(res.count(), 1);

res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1,
Qt::MatchRegularExpression);
QCOMPARE(res.count(), 2);
res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1,
Qt::MatchRegularExpression | Qt::MatchCaseSensitive);
QCOMPARE(res.count(), 0);

res = model.match(start, Qt::DisplayRole, QVariant(QRegularExpression(".*O.*")),
-1, Qt::MatchRegularExpression);
QCOMPARE(res.count(), 0);
res = model.match(start,
Qt::DisplayRole,
QVariant(QRegularExpression(".*O.*",
QRegularExpression::CaseInsensitiveOption)),
-1,
Qt::MatchRegularExpression);
QCOMPARE(res.count(), 2);

// Ensure that the case sensitivity is properly ignored when passing a
// QRegularExpression object.
res = model.match(start,
Qt::DisplayRole,
QVariant(QRegularExpression(".*O.*",
QRegularExpression::CaseInsensitiveOption)),
-1,
Qt::MatchRegularExpression | Qt::MatchCaseSensitive);
QCOMPARE(res.count(), 2);
}

typedef QPair<int, int> Position;
Expand Down

0 comments on commit c222a92

Please sign in to comment.