Merge lp:~uriboni/unity-2d/unity-2d-exclude-filter-proxy-model into lp:unity-2d

Proposed by Ugo Riboni
Status: Merged
Approved by: Alberto Mardegan
Approved revision: 689
Merged at revision: 702
Proposed branch: lp:~uriboni/unity-2d/unity-2d-exclude-filter-proxy-model
Merge into: lp:unity-2d
Diff against target: 160 lines (+87/-2)
3 files modified
libunity-2d-private/src/qsortfilterproxymodelqml.cpp (+32/-2)
libunity-2d-private/src/qsortfilterproxymodelqml.h (+6/-0)
libunity-2d-private/tests/qsortfilterproxymodeltest.cpp (+49/-0)
To merge this branch: bzr merge lp:~uriboni/unity-2d/unity-2d-exclude-filter-proxy-model
Reviewer Review Type Date Requested Status
Alberto Mardegan (community) Approve
Review via email: mp+73836@code.launchpad.net

Commit message

Add a new proxy model class that excludes items matching the regexp instead of including them.

Description of the change

Add a new proxy model class that has all the features of QSortFilterProxyModelQML but excludes items matching the regexp instead of including them.

This is useful because generally speaking it's pretty hard to use a regular expression to exclude something. That's for example why tools like grep have the -v option to reverse the normal matching behavior.

This class is currently used only by another project but I thought having it in unity-2d would make things easier for everyone when they face a similar task.

To post a comment you must log in.
Revision history for this message
Alberto Mardegan (mardy) wrote :

The code looks fine, but I'd rather add a boolean property (invertMatch) to the existing model than add a subclass.
Hopefully most of the code you wrote for the tests can be reused.

review: Needs Fixing
688. By Ugo Riboni

Simplify the code by replacing ExcludeSortFilterProxyModel with QSortFilterProxyModel::invertMatch()

Revision history for this message
Ugo Riboni (uriboni) wrote :

I updated the MR following your suggestion.

Revision history for this message
Alberto Mardegan (mardy) wrote :

Great Ugo! Only one nitpick on the format of the comment in line 40: it starts with "//", and finishes with "*/".

689. By Ugo Riboni

FIx typo in a comment

Revision history for this message
Alberto Mardegan (mardy) wrote :

Thanks a lot! :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libunity-2d-private/src/qsortfilterproxymodelqml.cpp'
--- libunity-2d-private/src/qsortfilterproxymodelqml.cpp 2011-07-29 13:49:34 +0000
+++ libunity-2d-private/src/qsortfilterproxymodelqml.cpp 2011-09-07 13:37:35 +0000
@@ -17,8 +17,10 @@
17#include "qsortfilterproxymodelqml.h"17#include "qsortfilterproxymodelqml.h"
18#include <debug_p.h>18#include <debug_p.h>
1919
20QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent) :20QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent)
21 QSortFilterProxyModel(parent), m_limit(-1)21 : QSortFilterProxyModel(parent)
22 , m_limit(-1)
23 , m_invertMatch(false)
22{24{
23 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));25 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
24 connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));26 connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
@@ -189,4 +191,32 @@
189 }191 }
190}192}
191193
194bool
195QSortFilterProxyModelQML::invertMatch() const
196{
197 return m_invertMatch;
198}
199
200void
201QSortFilterProxyModelQML::setInvertMatch(bool invertMatch)
202{
203 if (invertMatch != m_invertMatch) {
204 m_invertMatch = invertMatch;
205 Q_EMIT invertMatchChanged(invertMatch);
206 }
207}
208
209bool
210QSortFilterProxyModelQML::filterAcceptsRow(int sourceRow,
211 const QModelIndex &sourceParent) const
212{
213 // If there's no regexp set, always accept all rows indepenently of the invertMatch setting
214 if (filterRegExp().isEmpty()) {
215 return true;
216 }
217
218 bool result = QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
219 return (m_invertMatch) ? !result : result;
220}
221
192#include "qsortfilterproxymodelqml.moc"222#include "qsortfilterproxymodelqml.moc"
193223
=== modified file 'libunity-2d-private/src/qsortfilterproxymodelqml.h'
--- libunity-2d-private/src/qsortfilterproxymodelqml.h 2011-07-29 13:49:34 +0000
+++ libunity-2d-private/src/qsortfilterproxymodelqml.h 2011-09-07 13:37:35 +0000
@@ -27,6 +27,7 @@
27 Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged)27 Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged)
28 Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged)28 Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged)
29 Q_PROPERTY(int count READ count NOTIFY countChanged)29 Q_PROPERTY(int count READ count NOTIFY countChanged)
30 Q_PROPERTY(bool invertMatch READ invertMatch WRITE setInvertMatch NOTIFY invertMatchChanged)
3031
31public:32public:
32 explicit QSortFilterProxyModelQML(QObject *parent = 0);33 explicit QSortFilterProxyModelQML(QObject *parent = 0);
@@ -34,15 +35,18 @@
34 Q_INVOKABLE QVariantMap get(int row);35 Q_INVOKABLE QVariantMap get(int row);
35 Q_INVOKABLE int count();36 Q_INVOKABLE int count();
36 int rowCount(const QModelIndex &parent = QModelIndex()) const;37 int rowCount(const QModelIndex &parent = QModelIndex()) const;
38 virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
3739
38 /* getters */40 /* getters */
39 QObject* sourceModelQObject() const;41 QObject* sourceModelQObject() const;
40 int limit() const;42 int limit() const;
41 int totalCount() const;43 int totalCount() const;
44 bool invertMatch() const;
4245
43 /* setters */46 /* setters */
44 void setSourceModelQObject(QObject *model);47 void setSourceModelQObject(QObject *model);
45 void setLimit(int limit);48 void setLimit(int limit);
49 void setInvertMatch(bool invertMatch);
4650
47 Q_SLOT void setRoleNames(const QHash<int,QByteArray> &roleNames);51 Q_SLOT void setRoleNames(const QHash<int,QByteArray> &roleNames);
4852
@@ -50,10 +54,12 @@
50 void limitChanged();54 void limitChanged();
51 void totalCountChanged();55 void totalCountChanged();
52 void countChanged();56 void countChanged();
57 void invertMatchChanged(bool);
53 void roleNamesChanged(const QHash<int,QByteArray> &);58 void roleNamesChanged(const QHash<int,QByteArray> &);
5459
55private:60private:
56 int m_limit;61 int m_limit;
62 bool m_invertMatch;
57};63};
5864
59#endif // QSORTFILTERPROXYMODELQML_H65#endif // QSORTFILTERPROXYMODELQML_H
6066
=== modified file 'libunity-2d-private/tests/qsortfilterproxymodeltest.cpp'
--- libunity-2d-private/tests/qsortfilterproxymodeltest.cpp 2011-07-26 16:50:34 +0000
+++ libunity-2d-private/tests/qsortfilterproxymodeltest.cpp 2011-09-07 13:37:35 +0000
@@ -67,6 +67,13 @@
67 return true;67 return true;
68 }68 }
6969
70 bool appendRows(QStringList &rows, const QModelIndex &parent=QModelIndex()) {
71 beginInsertRows(parent, rowCount(), rowCount() + rows.count() - 1);
72 m_list.append(rows);
73 endInsertRows();
74 return true;
75 }
76
70 bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) {77 bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) {
71 beginRemoveRows(parent, row, row+count-1);78 beginRemoveRows(parent, row, row+count-1);
72 for (int i=0; i<count; i++) {79 for (int i=0; i<count; i++) {
@@ -376,6 +383,48 @@
376 //QCOMPARE(spyOnRowsInserted.count(), 0);383 //QCOMPARE(spyOnRowsInserted.count(), 0);
377 //QCOMPARE(spyOnCountChanged.count(), 0);384 //QCOMPARE(spyOnCountChanged.count(), 0);
378 }385 }
386
387 void testInvertMatch() {
388 QSortFilterProxyModelQML proxy;
389 MockListModel model;
390
391 proxy.setSourceModelQObject(&model);
392 proxy.setDynamicSortFilter(true);
393
394 QStringList rows;
395 rows << "a/foobar/b" << "foobar" << "foobarbaz" << "hello";
396 model.appendRows(rows);
397
398 // Check that without a filterRegExp all rows are accepted regardless of invertMatch
399 QCOMPARE(model.rowCount(), rows.count());
400 QCOMPARE(proxy.rowCount(), rows.count());
401 for (int i=0; i<rows.count(); i++) {
402 QCOMPARE(proxy.index(i, 0).data().toString(), model.index(i, 0).data().toString());
403 }
404 proxy.setInvertMatch(true);
405 QCOMPARE(model.rowCount(), rows.count());
406 QCOMPARE(proxy.rowCount(), rows.count());
407 for (int i=0; i<rows.count(); i++) {
408 QCOMPARE(proxy.index(i, 0).data().toString(), model.index(i, 0).data().toString());
409 }
410
411
412 // Test non-anchored regexp with invertMatch active
413 proxy.setFilterRegExp("foobar");
414 QCOMPARE(proxy.rowCount(), 1);
415 QCOMPARE(proxy.index(0, 0).data().toString(), rows.last());
416
417 // Test anchored regexp with invertMatch active
418 proxy.setFilterRegExp("^foobar$");
419 QCOMPARE(proxy.rowCount(), 3);
420 QCOMPARE(proxy.index(0, 0).data().toString(), rows.at(0));
421 QCOMPARE(proxy.index(1, 0).data().toString(), rows.at(2));
422 QCOMPARE(proxy.index(2, 0).data().toString(), rows.at(3));
423
424 // Test regexp with OR and invertMatch active
425 proxy.setFilterRegExp("foobar|hello");
426 QCOMPARE(proxy.count(), 0);
427 }
379};428};
380429
381QTEST_MAIN(QSortFilterProxyModelTest)430QTEST_MAIN(QSortFilterProxyModelTest)

Subscribers

People subscribed via source and target branches