feat(Storybook): Utility allowing quickly visualize any model.

It makes work with model in Storybook much faster bc eliminates work
related to creating delegates and also (when needed) handling dnd logic.

Closes: #13599
This commit is contained in:
Michał Cieślak 2024-02-16 11:52:21 +01:00 committed by Michał
parent b949fb7b3b
commit 2ffb0feedd
2 changed files with 163 additions and 0 deletions

View File

@ -0,0 +1,162 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core.Utils 0.1
import utils 1.0
ListView {
id: root
// adds drag handler to every row, emits moveRequested when item is moved
property bool movable: false
// roles intended to be visualized, all roles when empty
property var roles: []
// custom delegate height, when set to 0, delegate's implicitHeight is used
property int delegateHeight: 0
// text to be displayed in a list view's header
property string label
// additional component to be instantiated within every delegate
property Component insetComponent
property int margin: 5
ScrollBar.vertical: ScrollBar {}
clip: true
spacing: 5
leftMargin: margin
rightMargin: margin
topMargin: margin
bottomMargin: margin
signal moveRequested(int from, int to)
ListModel {
id: rowModel
function initialize() {
const roleNames = roles.length ? roles
: ModelUtils.roleNames(root.model)
const modelContent = roleNames.map(roleName => ({ roleName }))
clear()
append(modelContent)
}
Component.onCompleted: initialize()
}
Rectangle {
border.color: "lightgray"
color: "transparent"
anchors.fill: parent
}
header: Label {
visible: !!text
height: visible ? undefined : 0
text: root.label
font.bold: true
font.pixelSize: 16
bottomPadding: 20
}
delegate: Item {
id: delegateRoot
width: ListView.view.width
height: root.delegateHeight || delegateRow.implicitHeight
readonly property var topModel: model
RowLayout {
id: delegateRow
Drag.active: dragArea.pressed
Drag.source: dragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
states: State {
when: dragArea.pressed
ParentChange {
target: delegateRow
parent: root
}
AnchorChanges {
target: delegateRow
anchors {
horizontalCenter: undefined
verticalCenter: undefined
}
}
}
RoundButton {
text: "↕️"
visible: root.movable
MouseArea {
id: dragArea
property bool held: pressed
readonly property int idx: model.index
anchors.fill: parent
drag.target: pressed ? delegateRow : undefined
drag.axis: Drag.YAxis
}
}
Repeater {
model: rowModel
Label {
readonly property var value:
delegateRoot.topModel[roleName]
readonly property var valueSanitized:
value === undefined ? "-" : value
readonly property bool last: index === rowModel.count - 1
readonly property string separator: last ? "" : ","
text: `${roleName}: ${valueSanitized}${separator}`
}
}
Loader {
readonly property var model: delegateRoot.topModel
sourceComponent: insetComponent
}
Item {
Layout.fillWidth: true
}
}
DropArea {
anchors { fill: parent; margins: 10 }
onEntered: {
const from = drag.source.idx
const to = dragArea.idx
if (from === to)
return
root.moveRequested(from, to)
}
}
}
}

View File

@ -4,6 +4,7 @@ FigmaLinksCache 1.0 FigmaLinksCache.qml
FigmaPreviewWindow 1.0 FigmaPreviewWindow.qml
FilteredPagesList 1.0 FilteredPagesList.qml
FlickableImage 1.0 FlickableImage.qml
GenericListView 1.0 GenericListView.qml
HotComponentFromSource 1.0 HotComponentFromSource.qml
HotLoader 1.0 HotLoader.qml
HotReloader 1.0 HotReloader.qml