Skip to content
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ build-SortFilterProxyModel-*
*.dll
*.exe

# QtCreator cmake profile
CMakeLists.txt.user
94 changes: 86 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
cmake_minimum_required(VERSION 3.1)

set(CMAKE_CXX_STANDARD 11)
project(SortFilterProxyModel LANGUAGES CXX)

find_package(Qt5 REQUIRED
Core
Qml
)

# Module version
set(SFP_MAJOR 0)
set(SFP_MINOR 2)

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON) # This is to find generated *.moc and *.h files in build dir

add_library(SortFilterProxyModel OBJECT
set(SOURCES
qqmlsortfilterproxymodel.cpp
filters/filter.cpp
filters/filtercontainer.cpp
Expand All @@ -35,15 +39,89 @@ add_library(SortFilterProxyModel OBJECT
proxyroles/joinrole.cpp
proxyroles/switchrole.cpp
proxyroles/expressionrole.cpp
proxyroles/proxyrolesqmltypes.cpp
proxyroles/singlerole.cpp
proxyroles/proxyrolesqmltypes.cpp
proxyroles/singlerole.cpp
proxyroles/regexprole.cpp
sorters/filtersorter.cpp
proxyroles/filterrole.cpp
)

target_include_directories(SortFilterProxyModel PUBLIC
${CMAKE_CURRENT_LIST_DIR}
$<TARGET_PROPERTY:Qt5::Core,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt5::Qml,INTERFACE_INCLUDE_DIRECTORIES>
# --- Object library to link directly with the application
add_library(SortFilterProxyModel OBJECT ${SOURCES})
set_target_properties(SortFilterProxyModel
PROPERTIES
CXX_STANDARD 11
EXCLUDE_FROM_ALL TRUE
)
target_link_libraries(SortFilterProxyModel PUBLIC
Qt5::Core
Qt5::Qml
)

# --- Plugin library
add_library(SortFilterProxyModelPlugin SHARED
${SOURCES}
sortfilterproxymodelplugin.cpp
)
target_link_libraries(SortFilterProxyModelPlugin PUBLIC
Qt5::Core
Qt5::Qml
)

target_compile_definitions(SortFilterProxyModelPlugin
PRIVATE
QML_PLUGIN
QML_IMPORT_MAJOR_VERSION=${SFP_MAJOR}
QML_IMPORT_MINOR_VERSION=${SFP_MINOR}
)
set_target_properties(SortFilterProxyModelPlugin
PROPERTIES
CXX_STANDARD 11
OUTPUT_NAME sortfilterproxymodel
DEBUG_POSTFIX d
EXCLUDE_FROM_ALL TRUE
)

# --- Create installed package
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
set(PACKAGE_NAME ${CMAKE_PROJECT_NAME})

set(QML_MODULE_PATH qml_module)
configure_package_config_file(
cmake/SortFilterProxyModelConfig.cmake.in
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}Config.cmake
INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME}
PATH_VARS
QML_MODULE_PATH
)

write_basic_package_version_file(
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}ConfigVersion.cmake
VERSION
"${SFP_MAJOR}.${SFP_MINOR}"
COMPATIBILITY
SameMajorVersion
)

set(SFP_INSTALL_PATH "${QML_MODULE_PATH}/QmlSortFilterProxyModel")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why QmlSortFilterProxyModel and not SortFilterProxyModel as already used?
I would prefer SortFilterProxyModel as the default and optionally changeable if you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also prefer that, however as stated in my comment, I had a namespace conflict while generating the qmltypes file. That is why I had to change the name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact qmlplugindump used for generating the *.qmltypes file is the program where I experienced the namespace conflict. Maybe after generating the types file I can change the module name back to SortFilterProxyModel.


# qml module
install(TARGETS SortFilterProxyModelPlugin
RUNTIME DESTINATION ${SFP_INSTALL_PATH}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Linux, RUNTIME installs the .so to plugins/lib/.
LIBRARY seems to produce the correct folder hierarchy. Does it work on Windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not really an ordinary plugin but a qml module. I just checked on my windows installation, Qt itself installs qml modules like this:
msvc2019_64/qml/<name_module>
I would like to change it to be the same way.

COMPONENT sortfilterproxymodel
)
install(
FILES module/qmldir module/plugins.qmltypes
DESTINATION ${SFP_INSTALL_PATH}
COMPONENT sortfilterproxymodel
)

# cmake package config
install(
FILES
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}Config.cmake
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME}
)
104 changes: 81 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,80 @@
SortFilterProxyModel
====================
# SortFilterProxyModel

SortFilterProxyModel is an implementation of `QSortFilterProxyModel` conveniently exposed for QML.

Install
-------
##### With [qpm](https://qpm.io) :
## Install

### With [qpm](https://qpm.io)

1. `qpm install fr.grecko.sortfilterproxymodel`
2. add `include(vendor/vendor.pri)` in your .pro if it is not already done
3. `import SortFilterProxyModel 0.2` to use this library in your QML files

##### Without qpm :
1. clone or download this repository
2. * `qmake` add `include (<path/to/SortFilterProxyModel>/SortFilterProxyModel.pri)` in your `.pro`
* `CMake` add $<TARGET_OBJECTS:SortFilterProxyModel> to the sources of your executable target in your cmake project
### Without qpm

1. Clone or download this repository
2. Project integration
* `qmake`
* Add `include (<path/to/SortFilterProxyModel>/SortFilterProxyModel.pri)` in your `.pro`
* `CMake`
* Add `add_subdirectory(<path/to/SortFilterProxyModel>/SortFilterProxyModel)`
* Append `$<TARGET_OBJECTS:SortFilterProxyModel>` to the sources of your executable target in your cmake project
3. `import SortFilterProxyModel 0.2` to use this library in your QML files

Sample Usage
------------
### Plugin

1. Clone or download this repository
2. Build and install the plugin target, example with msvc2019 and Ninja generator:

```powershell
PS $Env:QTDIR='C:/Qt/5.15.2/msvc2019_64'
PS cd SortFilterProxyModel
PS md release_build
PS cmake -S . -B release_build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$Env:QTDIR" -DCMAKE_INSTALL_PREFIX='plugins'
PS cmake --build release_build --target SortFilterProxyModelPlugin
PS cmake --build release_build --target install
```

To create a debug plugin, repeat the steps above, but create a different
build directory and set -DCMAKE_BUILD_TYPE=Debug. This will install the
project as a qml module:

```text
plugins/
├── qml_module/
│ └── QmlSortFilterProxyModel/
│ ├── plugins.qmltypes
│ ├── qmldir
│ ├── sortfilterproxymodel.dll
│ └── sortfilterproxymodeld.dll
└── lib/
└── cmake/
└── SortFilterProxyModel/
├── SortFilterProxyModelConfig.cmake
└── SortFilterProxyModelConfigVersion.cmake
```

Even though the plugin is build with cmake, it is enough to add the
`plugins` path to the import paths of your qml application. To module
name has changed to QmlSortFilterProxyModel due to a namespace conflict.
To import the module in qml code use:

```qml
import QmlSortFilterProxyModel 0.2
```

The cmake package that is generated is optional and just for convenience.
It can be used in a cmake project to get the module name and path:

```cmake
find_package(SortFilterProxyModel 0.2 REQUIRED)
set(QML_IMPORT_PATH "${SortFilterProxyModel_QML_MODULE_PATH};${OTHER_IMPORT_PATHS}" CACHE STRING "Extra qml import paths" FORCE)
```

## Sample Usage

* You can do simple filtering and sorting with SortFilterProxyModel:

- You can do simple filtering and sorting with SortFilterProxyModel:
```qml
import QtQuick 2.2
import QtQuick.Controls 1.2
Expand Down Expand Up @@ -64,9 +119,11 @@ ApplicationWindow {
}
}
```

Here the `ListView` will only show elements that contains the content of the `TextField` in their `lastName` role.

- But you can also achieve more complex filtering or sorting with multiple `filters` and `sorters`:
* But you can also achieve more complex filtering or sorting with multiple `filters` and `sorters`:

```qml
SortFilterProxyModel {
id: personProxyModel
Expand Down Expand Up @@ -101,26 +158,27 @@ Here the `ListView` will only show elements that contains the content of the `Te
id:onlyShowFavoritesCheckbox
}
```

This will show in the corresponding `ListView` only the elements where the `firstName` or the `lastName` match the text entered in the `textField`, and if the `onlyShowFavoritesCheckbox` is checked it will aditionnally filter the elements where `favorite` is `true`.
The favorited elements will be shown first and all the elements are sorted by `firstName` and then `lastName`.

Showcase Application
--------------------
You can find an application showcasing this library here: https://github.com/oKcerG/SFPMShowcase
## Showcase Application

You can find an application showcasing this library here: [showcase](https://github.com/oKcerG/SFPMShowcase).

## License

License
-------
This library is licensed under the MIT License.

Documentation
-------------
## Documentation

This component is a subclass of [`QSortFilterProxyModel`](http://doc.qt.io/qt-5/qsortfilterproxymodel.html), to use it, you need to set the `sourceModel` property to a [`QAbstractItemModel*`](http://doc.qt.io/qt-5/qabstractitemmodel.html) with correct role names.
This means you can use it with custom c++ models or `ListModel`, but not with JavaScript models like arrays, integers or object instances.

The complete documentation reference is available here: https://okcerg.github.io/SortFilterProxyModel/
The complete documentation reference is available here: [documentation](https://okcerg.github.io/SortFilterProxyModel/)

## Contributing

Contributing
------------
Don't hesitate to open an issue about a suggestion, a bug, a lack of clarity in the documentation, etc.

Pull requests are also welcome, if it's a important change you should open an issue first though.
7 changes: 7 additions & 0 deletions cmake/SortFilterProxyModelConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@PACKAGE_INIT@

set_and_check(${CMAKE_FIND_PACKAGE_NAME}_QML_MODULE_PATH "@PACKAGE_QML_MODULE_PATH@")

set(${CMAKE_FIND_PACKAGE_NAME}_QML_MODULE_NAME QmlSortFilterProxyModel)

check_required_components(SortFilterProxyModel)
28 changes: 17 additions & 11 deletions filters/filtersqmltypes.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "filtersqmltypes.h"
#include "filter.h"
#include "valuefilter.h"
#include "indexfilter.h"
Expand All @@ -11,18 +12,23 @@

namespace qqsfpm {

void registerFiltersTypes() {
qmlRegisterUncreatableType<Filter>("SortFilterProxyModel", 0, 2, "Filter", "Filter is an abstract class");
qmlRegisterType<ValueFilter>("SortFilterProxyModel", 0, 2, "ValueFilter");
qmlRegisterType<IndexFilter>("SortFilterProxyModel", 0, 2, "IndexFilter");
qmlRegisterType<RegExpFilter>("SortFilterProxyModel", 0, 2, "RegExpFilter");
qmlRegisterType<RangeFilter>("SortFilterProxyModel", 0, 2, "RangeFilter");
qmlRegisterType<ExpressionFilter>("SortFilterProxyModel", 0, 2, "ExpressionFilter");
qmlRegisterType<AnyOfFilter>("SortFilterProxyModel", 0, 2, "AnyOf");
qmlRegisterType<AllOfFilter>("SortFilterProxyModel", 0, 2, "AllOf");
qmlRegisterUncreatableType<FilterContainerAttached>("SortFilterProxyModel", 0, 2, "FilterContainer", "FilterContainer can only be used as an attaching type");
void registerFiltersTypes(const char *uri, int major, int minor) {
qmlRegisterUncreatableType<Filter>(uri, major, minor, "Filter", "Filter is an abstract class");
qmlRegisterType<ValueFilter>(uri, major, minor, "ValueFilter");
qmlRegisterType<IndexFilter>(uri, major, minor, "IndexFilter");
qmlRegisterType<RegExpFilter>(uri, major, minor, "RegExpFilter");
qmlRegisterType<RangeFilter>(uri, major, minor, "RangeFilter");
qmlRegisterType<ExpressionFilter>(uri, major, minor, "ExpressionFilter");
qmlRegisterType<AnyOfFilter>(uri, major, minor, "AnyOf");
qmlRegisterType<AllOfFilter>(uri, major, minor, "AllOf");
qmlRegisterUncreatableType<FilterContainerAttached>(uri, major, minor, "FilterContainer", "FilterContainer can only be used as an attaching type");
}

#ifndef QML_PLUGIN
void registerFiltersTypes() {
registerFiltersTypes("SortFilterProxyModel", 0, 2);
}
Q_COREAPP_STARTUP_FUNCTION(registerFiltersTypes)
#endif

}
} // namespace qqsfpm
10 changes: 10 additions & 0 deletions filters/filtersqmltypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef FILTERSQMLTYPES_H
#define FILTERSQMLTYPES_H

namespace qqsfpm {

void registerFiltersTypes(const char *uri, int major, int minor);

} // namespace qqsfpm

#endif // FILTERSQMLTYPES_H
Loading