feat: add filtering&sorting example
closes: status-im/status-desktop#6510 closes: status-im/status-desktop#6512
This commit is contained in:
parent
df60ec047a
commit
9b89e08294
|
@ -8,6 +8,11 @@ set(CMAKE_AUTORCC ON)
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# add_subdirectory(src)
|
||||
# https://doc.qt.io/qtcreator/creator-qml-modules-with-plugins.html#importing-qml-modules
|
||||
set(QML_IMPORT_PATH
|
||||
${CMAKE_SOURCE_DIR}/src;${QML_IMPORT_PATH}
|
||||
CACHE STRING "")
|
||||
|
||||
add_subdirectory(vendor/SortFilterProxyModel)
|
||||
add_subdirectory(sandbox)
|
||||
add_subdirectory(tests)
|
||||
|
|
|
@ -28,5 +28,6 @@ endif()
|
|||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE SRC_DIR="${CMAKE_CURRENT_LIST_DIR}")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick
|
||||
Qt5::QuickControls2)
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2
|
||||
SortFilterProxyModel)
|
||||
|
|
|
@ -913,8 +913,19 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
|||
notificationsCount: 0
|
||||
}
|
||||
ListElement {
|
||||
sectionId: "demoApp"
|
||||
sectionId: "examples"
|
||||
sectionType: 101
|
||||
name: "Examples"
|
||||
active: false
|
||||
image: ""
|
||||
icon: "show"
|
||||
color: ""
|
||||
hasNotification: false
|
||||
notificationsCount: 0
|
||||
}
|
||||
ListElement {
|
||||
sectionId: "demoApp"
|
||||
sectionType: 102
|
||||
name: "Demo Application"
|
||||
active: false
|
||||
image: ""
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
StatusIconTextButton {
|
||||
id: sortBtn
|
||||
|
||||
property int sortOrder: -1
|
||||
statusIcon: {
|
||||
if (sortOrder == Qt.AscendingOrder) return "chevron-down"
|
||||
if (sortOrder == Qt.DescendingOrder) return "chevron-up"
|
||||
return "remove"
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var st = sortOrder + 1
|
||||
sortOrder = st > 1 ? -1 : st
|
||||
}
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: searchInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
input.icon.name: "search"
|
||||
input.placeholderText: "nickname.."
|
||||
}
|
||||
|
||||
StatusIconTabButton {
|
||||
id: contactBtn
|
||||
|
||||
icon.name: "tiny/tiny-contact"
|
||||
identicon.icon.color: Theme.palette.primaryColor1
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusIconTabButton {
|
||||
id: verifiedBtn
|
||||
|
||||
icon.name: "tiny/tiny-checkmark"
|
||||
identicon.icon.color: Theme.palette.primaryColor1
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: contentItem.childrenRect.height
|
||||
spacing: 4
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: d.users
|
||||
sorters: StringSorter {
|
||||
enabled: sortBtn.sortOrder !== -1
|
||||
roleName: "nick"
|
||||
sortOrder: sortBtn.sortOrder
|
||||
}
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
expression: model.nick.startsWith(searchInput.text)
|
||||
},
|
||||
AllOf {
|
||||
enabled: contactBtn.highlighted || verifiedBtn.highlighted
|
||||
ValueFilter {
|
||||
enabled: contactBtn.highlighted
|
||||
roleName: "isContact"
|
||||
value: true
|
||||
}
|
||||
ValueFilter {
|
||||
enabled: verifiedBtn.highlighted
|
||||
roleName: "isVerified"
|
||||
value: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
delegate: StatusMemberListItem {
|
||||
width: parent.width
|
||||
userName: model.name
|
||||
nickName: model.nick
|
||||
isVerified: model.isVerified
|
||||
isContact: model.isContact
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property ListModel users: ListModel {
|
||||
ListElement {
|
||||
name: "Richard"
|
||||
nick: "Ricky"
|
||||
isVerified: true
|
||||
isContact: true
|
||||
}
|
||||
ListElement {
|
||||
name: "Susan"
|
||||
nick: "Sue"
|
||||
isVerified: false
|
||||
isContact: false
|
||||
}
|
||||
ListElement {
|
||||
name: "Edward"
|
||||
nick: "Ed"
|
||||
isVerified: true
|
||||
isContact: false
|
||||
}
|
||||
ListElement {
|
||||
name: "Toomas"
|
||||
nick: "Tommy"
|
||||
isVerified: false
|
||||
isContact: false
|
||||
}
|
||||
ListElement {
|
||||
name: "Elizabeth"
|
||||
nick: "Bess"
|
||||
isVerified: true
|
||||
isContact: true
|
||||
}
|
||||
ListElement {
|
||||
name: "Thomas"
|
||||
nick: "Tom"
|
||||
isVerified: false
|
||||
isContact: true
|
||||
}
|
||||
ListElement {
|
||||
name: "Fernando"
|
||||
nick: "Alonso"
|
||||
isVerified: false
|
||||
isContact: true
|
||||
}
|
||||
ListElement {
|
||||
name: "Alexander"
|
||||
nick: "Alex"
|
||||
isVerified: true
|
||||
isContact: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "sandboxapp.h"
|
||||
|
||||
#include <qqmlsortfilterproxymodeltypes.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
|
@ -12,6 +14,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
SandboxApp app(argc, argv);
|
||||
|
||||
qqsfpm::registerTypes();
|
||||
|
||||
qputenv("QT_QUICK_CONTROLS_HOVER_ENABLED", QByteArrayLiteral("1"));
|
||||
|
||||
app.setOrganizationName("Status");
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Controls 2.14
|
|||
import QtGraphicalEffects 1.13
|
||||
import QtQuick.Layouts 1.14
|
||||
import Qt.labs.settings 1.0
|
||||
import QtQml.Models 2.14
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
|
@ -14,6 +15,8 @@ import StatusQ.Components 0.1
|
|||
import StatusQ.Layout 0.1
|
||||
import StatusQ.Platform 0.1
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import "demoapp/data" 1.0
|
||||
|
||||
StatusWindow {
|
||||
|
@ -44,7 +47,8 @@ StatusWindow {
|
|||
readonly property int nodeManagement: 4
|
||||
readonly property int profileSettings: 5
|
||||
readonly property int apiDocumentation: 100
|
||||
readonly property int demoApp: 101
|
||||
readonly property int examples: 101
|
||||
readonly property int demoApp: 102
|
||||
}
|
||||
|
||||
function setActiveItem(sectionId) {
|
||||
|
@ -87,13 +91,16 @@ StatusWindow {
|
|||
if(model.sectionType === appSectionType.apiDocumentation)
|
||||
{
|
||||
stackView.push(libraryDocumentationCmp)
|
||||
rootWindow.setActiveItem(sectionId)
|
||||
}
|
||||
else if(model.sectionType === appSectionType.examples)
|
||||
{
|
||||
stackView.push(examplesCmp)
|
||||
}
|
||||
else if(model.sectionType === appSectionType.demoApp)
|
||||
{
|
||||
stackView.push(demoAppCmp)
|
||||
rootWindow.setActiveItem(model.sectionId)
|
||||
}
|
||||
rootWindow.setActiveItem(model.sectionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,6 +407,53 @@ StatusWindow {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: examplesCmp
|
||||
|
||||
StatusAppTwoPanelLayout {
|
||||
id: examplesView
|
||||
|
||||
function example(name) {
|
||||
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
|
||||
storeSettings.selectedExample = examplesLoader.source
|
||||
}
|
||||
|
||||
readonly property string defaultExampleSource: example("FilteringSorting")
|
||||
|
||||
leftPanel: StatusScrollView {
|
||||
id: examplesLeftPanel
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 48
|
||||
|
||||
ColumnLayout {
|
||||
width: examplesLeftPanel.availableWidth
|
||||
spacing: 0
|
||||
|
||||
StatusNavigationListItem {
|
||||
Layout.fillWidth: true
|
||||
title: "FilteringSorting"
|
||||
selected: examplesLoader.source.toString().includes(title)
|
||||
onClicked: examplesView.example(title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightPanel: StatusScrollView {
|
||||
id: examplesRightPanel
|
||||
anchors.fill: parent
|
||||
anchors.margins: 64
|
||||
anchors.topMargin: anchors.margins + 32
|
||||
|
||||
Loader {
|
||||
id: examplesLoader
|
||||
width: examplesRightPanel.availableWidth
|
||||
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: demoAppCmp
|
||||
|
||||
|
@ -494,6 +548,7 @@ StatusWindow {
|
|||
Settings {
|
||||
id: storeSettings
|
||||
property string selected: ""
|
||||
property string selectedExample: ""
|
||||
property bool lightTheme: true
|
||||
property bool fillPage: false
|
||||
}
|
||||
|
|
|
@ -75,5 +75,6 @@
|
|||
<file>DemoApp.qml</file>
|
||||
<file>main.qml</file>
|
||||
<file>ThemeSwitch.qml</file>
|
||||
<file>examples/FilteringSorting.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -20,7 +20,7 @@ void SandboxApp::startEngine()
|
|||
qmlRegisterType<SpellChecker>("Sandbox", 0, 1, "Spellchecker");
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
const QUrl url = QUrl::fromLocalFile(SRC_DIR + QString{"/main.qml"});
|
||||
const QUrl url = QUrl::fromLocalFile(SRC_DIR + QStringLiteral("/main.qml"));
|
||||
#else
|
||||
const QUrl url(QStringLiteral("qrc:/main.qml"));
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@ void SandboxApp::startEngine()
|
|||
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
m_engine.addImportPath(SRC_DIR + QString{"/../src"});
|
||||
m_engine.addImportPath(SRC_DIR + QStringLiteral("/../src"));
|
||||
#else
|
||||
m_engine.addImportPath(QStringLiteral(":/"));
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue