status-desktop/storybook/pages/MovableModelWithSfpmPage.qml

482 lines
14 KiB
QML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import SortFilterProxyModel 0.2
Item {
id: root
ListModel {
id: simpleSourceModel
ListElement {
name: "entry 0"
position: 0
}
ListElement {
name: "entry 1"
position: 1
}
ListElement {
name: "entry 2"
position: 2
}
ListElement {
name: "entry 3"
position: 3
}
ListElement {
name: "entry 4"
position: 7
}
ListElement {
name: "entry 5"
position: 6
}
ListElement {
name: "entry 6"
position: 5
}
ListElement {
name: "entry 7"
position: 4
}
}
SortFilterProxyModel {
id: sorted
sorters: RoleSorter {
roleName: sortByPositionRadioButton.checked ? "position" : "name"
sortOrder: descendingCheckBox.checked ? Qt.DescendingOrder
: Qt.AscendingOrder
}
sourceModel: simpleSourceModel
}
MovableModel {
id: movableModel
sourceModel: sorted
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
spacing: 5
Item {
Layout.fillWidth: true
Layout.fillHeight: true
ColumnLayout {
id: sourceColumn
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: 20
spacing: 20
width: parent.width / 3
Label {
text: "SOURCE MODEL"
font.bold: true
font.pixelSize: 17
}
ListView {
id: sourceListView
spacing: 5
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
model: simpleSourceModel
ScrollBar.vertical: ScrollBar {}
delegate: Item {
id: sourceDelegateRoot
anchors {
left: parent ? parent.left : undefined
right: parent ? parent.right : undefined
}
height: sourceContent.implicitHeight
RowLayout {
id: sourceContent
Rectangle {
color: "lightgray"
Layout.fillHeight: true
Layout.preferredWidth: 40
Label {
anchors.centerIn: parent
text: "↕️"
}
MouseArea {
id: sourceDragArea
property bool held: false
readonly property int idx: model.index
anchors.fill: parent
drag.target: held ? sourceContent : undefined
drag.axis: Drag.YAxis
onPressed: held = true
onReleased: held = false
}
}
width: sourceDelegateRoot.width
Drag.active: sourceDragArea.held
Drag.source: sourceDragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
states: State {
when: sourceDragArea.held
ParentChange {
target: sourceContent
parent: root
}
AnchorChanges {
target: sourceContent
anchors {
horizontalCenter: undefined
verticalCenter: undefined
}
}
}
Label {
Layout.fillWidth: true
font.bold: true
text: model.name + ", position: " + model.position
}
RoundButton {
text: ""
onClicked: simpleSourceModel.remove(model.index)
}
RoundButton {
text: ""
onClicked: simpleSourceModel.setProperty(
index, "name", simpleSourceModel.get(index).name + "_")
}
}
DropArea {
anchors { fill: parent; margins: 10 }
onEntered: {
const from = drag.source.idx
const to = sourceDragArea.idx
if (from === to)
return
simpleSourceModel.move(from, to, 1)
}
}
}
}
}
ColumnLayout {
id: sfpmColumn
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: sourceColumn.right
anchors.margins: 20
spacing: 20
width: parent.width / 3
Label {
text: "SFPM MODEL"
font.bold: true
font.pixelSize: 17
}
ListView {
id: sfpmListView
spacing: 5
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
model: sorted
ScrollBar.vertical: ScrollBar {}
delegate: RowLayout {
width: ListView.view.width
Label {
Layout.fillWidth: true
font.bold: true
text: model.name + ", position: " + model.position
}
// to keep the same delegate height as in other list views
RoundButton {
enabled: false
opacity: 0
}
}
}
}
ColumnLayout {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: sfpmColumn.right
anchors.right: parent.right
anchors.margins: 20
spacing: 20
Label {
text: "MOVABLE MODEL"
font.bold: true
font.pixelSize: 17
}
ListView {
id: transformedListView
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 5
clip: true
model: movableModel
ScrollBar.vertical: ScrollBar {}
delegate: Item {
id: delegateRoot
anchors {
left: parent ? parent.left : undefined
right: parent ? parent.right : undefined
}
height: content.implicitHeight
RowLayout {
id: content
Rectangle {
color: "lightgray"
Layout.fillHeight: true
Layout.preferredWidth: 40
Label {
anchors.centerIn: parent
text: ""
}
MouseArea {
id: dragArea
property bool held: false
readonly property int idx: model.index
anchors.fill: parent
drag.target: held ? content : undefined
drag.axis: Drag.YAxis
onPressed: held = true
onReleased: held = false
}
}
width: delegateRoot.width
Drag.active: dragArea.held
Drag.source: dragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
states: State {
when: dragArea.held
ParentChange {
target: content
parent: root
}
AnchorChanges {
target: content
anchors {
horizontalCenter: undefined
verticalCenter: undefined
}
}
}
Label {
Layout.fillWidth: true
font.bold: true
text: model.name + ", position: " + model.position
}
RoundButton {
text: ""
enabled: index > 0
onClicked: movableModel.move(index, 0)
}
RoundButton {
text: ""
enabled: index < transformedListView.count - 1
onClicked: movableModel.move(
index, transformedListView.count - 1)
}
}
DropArea {
anchors { fill: parent; margins: 10 }
onEntered: {
const from = drag.source.idx
const to = dragArea.idx
if (from === to)
return
movableModel.move(from, to)
}
}
}
}
}
Rectangle {
width: 1
color: "gray"
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: sourceColumn.right
anchors.leftMargin: 10
}
Rectangle {
width: 1
color: "gray"
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: sfpmColumn.right
anchors.leftMargin: 10
}
}
Button {
Layout.alignment: Qt.AlignHCenter
text: "SAVE ORDER"
font.pixelSize: 30
onClicked: {
const count = simpleSourceModel.count
const newOrder = movableModel.order()
const newOrderInverted = []
const sourceIndexes = []
for (let i = 0; i < count; i++)
newOrderInverted[newOrder[i]] = i
for (let j = 0; j < count; j++)
sourceIndexes.push(sorted.mapToSource(j))
for (let k = 0; k < count; k++)
simpleSourceModel.setProperty(sourceIndexes[k], "position",
newOrderInverted[k])
}
}
RowLayout {
Layout.fillHeight: false
RadioButton {
text: "Sort by name"
}
RadioButton {
id: sortByPositionRadioButton
text: "Sort by position"
checked: true
}
CheckBox {
id: descendingCheckBox
text: "descending"
}
}
RowLayout {
Layout.fillHeight: false
Button {
text: "append to source model"
onClicked: simpleSourceModel.append({ name: "X" })
}
Button {
text: "desynchronize"
onClicked: movableModel.desyncOrder()
}
Button {
text: "synchronize"
onClicked: movableModel.syncOrder()
}
Label {
text: `Synchronized: <b>${movableModel.synced}</b>`
}
}
}
}
// category: Models