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 FigmaPreviewWindow 1.0 FigmaPreviewWindow.qml
FilteredPagesList 1.0 FilteredPagesList.qml FilteredPagesList 1.0 FilteredPagesList.qml
FlickableImage 1.0 FlickableImage.qml FlickableImage 1.0 FlickableImage.qml
GenericListView 1.0 GenericListView.qml
HotComponentFromSource 1.0 HotComponentFromSource.qml HotComponentFromSource 1.0 HotComponentFromSource.qml
HotLoader 1.0 HotLoader.qml HotLoader 1.0 HotLoader.qml
HotReloader 1.0 HotReloader.qml HotReloader 1.0 HotReloader.qml