Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Thumbs.db

# qtcreator generated files
*.pro.user*
*.user

# qtcreator shadow builds
build-SortFilterProxyModel-*
Expand Down
14 changes: 9 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.14)
project(qqmlsortfilterproxymodel)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

find_package(Qt5 REQUIRED
find_package(Qt6 REQUIRED
Core
Qml
)
Expand All @@ -12,6 +13,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) # This is to find generated *.moc and *.h file

add_library(SortFilterProxyModel OBJECT
qqmlsortfilterproxymodel.cpp
qvariantlessthan.cpp
filters/filter.cpp
filters/filtercontainer.cpp
filters/rolefilter.cpp
Expand Down Expand Up @@ -44,6 +46,8 @@ add_library(SortFilterProxyModel OBJECT

target_include_directories(SortFilterProxyModel PUBLIC
${CMAKE_CURRENT_LIST_DIR}
$<TARGET_PROPERTY:Qt5::Core,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt5::Qml,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt6::Core,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt6::Qml,INTERFACE_INCLUDE_DIRECTORIES>
)

target_compile_options(SortFilterProxyModel PRIVATE -fPIC)
4 changes: 3 additions & 1 deletion SortFilterProxyModel.pri
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
!contains( CONFIG, c\+\+1[14] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro")
!contains( CONFIG, c\+\+1[147] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro")

INCLUDEPATH += $$PWD

HEADERS += $$PWD/qqmlsortfilterproxymodel.h \
$$PWD/qvariantlessthan.h \
$$PWD/filters/filter.h \
$$PWD/filters/filtercontainer.h \
$$PWD/filters/rolefilter.h \
Expand Down Expand Up @@ -30,6 +31,7 @@ HEADERS += $$PWD/qqmlsortfilterproxymodel.h \
$$PWD/proxyroles/filterrole.h

SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \
$$PWD/qvariantlessthan.cpp \
$$PWD/filters/filter.cpp \
$$PWD/filters/filtercontainer.cpp \
$$PWD/filters/rolefilter.cpp \
Expand Down
2 changes: 1 addition & 1 deletion filters/expressionfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void ExpressionFilter::updateExpression()
return;

delete m_expression;
m_expression = new QQmlExpression(m_scriptString, m_context, 0, this);
m_expression = new QQmlExpression(m_scriptString, m_context, nullptr, this);
connect(m_expression, &QQmlExpression::valueChanged, this, &ExpressionFilter::invalidate);
m_expression->setNotifyOnValueChanged(true);
m_expression->evaluate();
Expand Down
16 changes: 10 additions & 6 deletions filters/filtercontainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#include "filter.h"
#include <QtQml>

#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
#define qmlWarning(me) qmlInfo(me)
#endif

namespace qqsfpm {

/*!
Expand Down Expand Up @@ -52,25 +56,25 @@ void FilterContainer::append_filter(QQmlListProperty<Filter>* list, Filter* filt
if (!filter)
return;

FilterContainer* that = reinterpret_cast<FilterContainer*>(list->object);
auto* that = reinterpret_cast<FilterContainer*>(list->object);
that->appendFilter(filter);
}

int FilterContainer::count_filter(QQmlListProperty<Filter>* list)
qsizetype FilterContainer::count_filter(QQmlListProperty<Filter>* list)
{
QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
auto* filters = static_cast<QList<Filter*>*>(list->data);
return filters->count();
}

Filter* FilterContainer::at_filter(QQmlListProperty<Filter>* list, int index)
Filter* FilterContainer::at_filter(QQmlListProperty<Filter>* list, qsizetype index)
{
QList<Filter*>* filters = static_cast<QList<Filter*>*>(list->data);
auto* filters = static_cast<QList<Filter*>*>(list->data);
return filters->at(index);
}

void FilterContainer::clear_filters(QQmlListProperty<Filter> *list)
{
FilterContainer* that = reinterpret_cast<FilterContainer*>(list->object);
auto* that = reinterpret_cast<FilterContainer*>(list->object);
that->clearFilters();
}

Expand Down
4 changes: 2 additions & 2 deletions filters/filtercontainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class FilterContainer {
virtual void onFiltersCleared() = 0;

static void append_filter(QQmlListProperty<Filter>* list, Filter* filter);
static int count_filter(QQmlListProperty<Filter>* list);
static Filter* at_filter(QQmlListProperty<Filter>* list, int index);
static qsizetype count_filter(QQmlListProperty<Filter>* list);
static Filter* at_filter(QQmlListProperty<Filter>* list, qsizetype index);
static void clear_filters(QQmlListProperty<Filter>* list);
};

Expand Down
7 changes: 5 additions & 2 deletions filters/rangefilter.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "rangefilter.h"
#include "qvariantlessthan.h"

namespace qqsfpm {

Expand Down Expand Up @@ -130,9 +131,11 @@ bool RangeFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilter
{
QVariant value = sourceData(sourceIndex, proxyModel);
bool lessThanMin = m_minimumValue.isValid() &&
(m_minimumInclusive ? value < m_minimumValue : value <= m_minimumValue);
(m_minimumInclusive ? qqsfpm::lessThan(value, m_minimumValue)
: !qqsfpm::lessThan(m_minimumValue, value));
bool moreThanMax = m_maximumValue.isValid() &&
(m_maximumInclusive ? value > m_maximumValue : value >= m_maximumValue);
(m_maximumInclusive ? qqsfpm::lessThan(m_maximumValue, value)
: !qqsfpm::lessThan(value, m_maximumValue));
return !(lessThanMin || moreThanMax);
}

Expand Down
97 changes: 32 additions & 65 deletions filters/regexpfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ namespace qqsfpm {
\ingroup Filters
\brief Filters rows matching a regular expression.

A RegExpFilter is a \l RoleFilter that accepts rows matching a regular rexpression.
A RegExpFilter is a \l RoleFilter that accepts rows matching a regular
rexpression.

In the following example, only rows with their \c lastName role beggining with the content of textfield the will be accepted:
\code
TextField {
id: nameTextField
In the following example, only rows with their \c lastName role beggining
with the content of textfield the will be accepted: \code TextField { id:
nameTextField
}

SortFilterProxyModel {
Expand All @@ -35,79 +35,46 @@ namespace qqsfpm {

\sa syntax
*/
QString RegExpFilter::pattern() const
{
return m_pattern;
}

void RegExpFilter::setPattern(const QString& pattern)
{
if (m_pattern == pattern)
return;

m_pattern = pattern;
m_regExp.setPattern(pattern);
Q_EMIT patternChanged();
invalidate();
}

/*!
\qmlproperty enum RegExpFilter::syntax

The pattern used to filter the contents of the source model.

Only the source model's value having their \l RoleFilter::roleName data matching this \l pattern with the specified \l syntax will be kept.
QString RegExpFilter::pattern() const { return m_pattern; }

\value RegExpFilter.RegExp A rich Perl-like pattern matching syntax. This is the default.
\value RegExpFilter.Wildcard This provides a simple pattern matching syntax similar to that used by shells (command interpreters) for "file globbing".
\value RegExpFilter.FixedString The pattern is a fixed string. This is equivalent to using the RegExp pattern on a string in which all metacharacters are escaped.
\value RegExpFilter.RegExp2 Like RegExp, but with greedy quantifiers.
\value RegExpFilter.WildcardUnix This is similar to Wildcard but with the behavior of a Unix shell. The wildcard characters can be escaped with the character "\".
\value RegExpFilter.W3CXmlSchema11 The pattern is a regular expression as defined by the W3C XML Schema 1.1 specification.
void RegExpFilter::setPattern(const QString &pattern) {
if (m_pattern == pattern)
return;

\sa pattern
*/
RegExpFilter::PatternSyntax RegExpFilter::syntax() const
{
return m_syntax;
}

void RegExpFilter::setSyntax(RegExpFilter::PatternSyntax syntax)
{
if (m_syntax == syntax)
return;

m_syntax = syntax;
m_regExp.setPatternSyntax(static_cast<QRegExp::PatternSyntax>(syntax));
Q_EMIT syntaxChanged();
invalidate();
m_pattern = pattern;
m_regularExpression.setPattern(pattern);
Q_EMIT patternChanged();
invalidate();
}

/*!
\qmlproperty Qt::CaseSensitivity RegExpFilter::caseSensitivity

This property holds the caseSensitivity of the filter.
*/
Qt::CaseSensitivity RegExpFilter::caseSensitivity() const
{
return m_caseSensitivity;
Qt::CaseSensitivity RegExpFilter::caseSensitivity() const {
return m_regularExpression.patternOptions() &
QRegularExpression::CaseInsensitiveOption
? Qt::CaseInsensitive
: Qt::CaseSensitive;
}

void RegExpFilter::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity)
{
if (m_caseSensitivity == caseSensitivity)
return;
void RegExpFilter::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) {
if (this->caseSensitivity() == caseSensitivity)
return;

m_caseSensitivity = caseSensitivity;
m_regExp.setCaseSensitivity(caseSensitivity);
Q_EMIT caseSensitivityChanged();
invalidate();
m_regularExpression.setPatternOptions(
m_regularExpression.patternOptions() ^
QRegularExpression::CaseInsensitiveOption); // toggle the option
Q_EMIT caseSensitivityChanged();
invalidate();
}

bool RegExpFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const
{
QString string = sourceData(sourceIndex, proxyModel).toString();
return m_regExp.indexIn(string) != -1;
bool RegExpFilter::filterRow(const QModelIndex &sourceIndex,
const QQmlSortFilterProxyModel &proxyModel) const {
QString string = sourceData(sourceIndex, proxyModel).toString();
QRegularExpressionMatch match = m_regularExpression.match(string);
return match.hasMatch();
}

}
} // namespace qqsfpm
48 changes: 18 additions & 30 deletions filters/regexpfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,39 @@
#define REGEXPFILTER_H

#include "rolefilter.h"
#include <QRegularExpression>

namespace qqsfpm {

class RegExpFilter : public RoleFilter {
Q_OBJECT
Q_PROPERTY(QString pattern READ pattern WRITE setPattern NOTIFY patternChanged)
Q_PROPERTY(PatternSyntax syntax READ syntax WRITE setSyntax NOTIFY syntaxChanged)
Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged)
Q_OBJECT
Q_PROPERTY(
QString pattern READ pattern WRITE setPattern NOTIFY patternChanged)
Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE
setCaseSensitivity NOTIFY caseSensitivityChanged)

public:
enum PatternSyntax {
RegExp = QRegExp::RegExp,
Wildcard = QRegExp::Wildcard,
FixedString = QRegExp::FixedString,
RegExp2 = QRegExp::RegExp2,
WildcardUnix = QRegExp::WildcardUnix,
W3CXmlSchema11 = QRegExp::W3CXmlSchema11 };
Q_ENUMS(PatternSyntax)
using RoleFilter::RoleFilter;

using RoleFilter::RoleFilter;
QString pattern() const;
void setPattern(const QString &pattern);

QString pattern() const;
void setPattern(const QString& pattern);

PatternSyntax syntax() const;
void setSyntax(PatternSyntax syntax);

Qt::CaseSensitivity caseSensitivity() const;
void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity);
Qt::CaseSensitivity caseSensitivity() const;
void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity);

protected:
bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override;
bool filterRow(const QModelIndex &sourceIndex,
const QQmlSortFilterProxyModel &proxyModel) const override;

Q_SIGNALS:
void patternChanged();
void syntaxChanged();
void caseSensitivityChanged();
void patternChanged();
void caseSensitivityChanged();

private:
QRegExp m_regExp;
Qt::CaseSensitivity m_caseSensitivity = m_regExp.caseSensitivity();
PatternSyntax m_syntax = static_cast<PatternSyntax>(m_regExp.patternSyntax());
QString m_pattern = m_regExp.pattern();
QRegularExpression m_regularExpression;
QString m_pattern{m_regularExpression.pattern()};
};

}
} // namespace qqsfpm

#endif // REGEXPFILTER_H
2 changes: 1 addition & 1 deletion proxyroles/proxyrole.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ProxyRole : public QObject

public:
using QObject::QObject;
virtual ~ProxyRole() = default;
~ProxyRole() override = default;

QVariant roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel, const QString& name);
virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel);
Expand Down
12 changes: 6 additions & 6 deletions proxyroles/proxyrolecontainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,25 @@ void ProxyRoleContainer::append_proxyRole(QQmlListProperty<ProxyRole>* list, Pro
if (!proxyRole)
return;

ProxyRoleContainer* that = reinterpret_cast<ProxyRoleContainer*>(list->object);
auto* that = reinterpret_cast<ProxyRoleContainer*>(list->object);
that->appendProxyRole(proxyRole);
}

int ProxyRoleContainer::count_proxyRole(QQmlListProperty<ProxyRole>* list)
qsizetype ProxyRoleContainer::count_proxyRole(QQmlListProperty<ProxyRole>* list)
{
QList<ProxyRole*>* ProxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
auto* ProxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
return ProxyRoles->count();
}

ProxyRole* ProxyRoleContainer::at_proxyRole(QQmlListProperty<ProxyRole>* list, int index)
ProxyRole* ProxyRoleContainer::at_proxyRole(QQmlListProperty<ProxyRole>* list, qsizetype index)
{
QList<ProxyRole*>* ProxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
auto* ProxyRoles = static_cast<QList<ProxyRole*>*>(list->data);
return ProxyRoles->at(index);
}

void ProxyRoleContainer::clear_proxyRoles(QQmlListProperty<ProxyRole> *list)
{
ProxyRoleContainer* that = reinterpret_cast<ProxyRoleContainer*>(list->object);
auto* that = reinterpret_cast<ProxyRoleContainer*>(list->object);
that->clearProxyRoles();
}

Expand Down
4 changes: 2 additions & 2 deletions proxyroles/proxyrolecontainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class ProxyRoleContainer {
virtual void onProxyRolesCleared() = 0;

static void append_proxyRole(QQmlListProperty<ProxyRole>* list, ProxyRole* proxyRole);
static int count_proxyRole(QQmlListProperty<ProxyRole>* list);
static ProxyRole* at_proxyRole(QQmlListProperty<ProxyRole>* list, int index);
static qsizetype count_proxyRole(QQmlListProperty<ProxyRole>* list);
static ProxyRole* at_proxyRole(QQmlListProperty<ProxyRole>* list, qsizetype index);
static void clear_proxyRoles(QQmlListProperty<ProxyRole>* list);
};

Expand Down
2 changes: 1 addition & 1 deletion proxyroles/switchrole.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SwitchRoleAttached : public QObject
Q_OBJECT
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
public:
SwitchRoleAttached(QObject* parent);
explicit SwitchRoleAttached(QObject* parent);

QVariant value() const;
void setValue(QVariant value);
Expand Down
Loading