Files
pay/guis/mobile/TokensTab.qml
tomFlowee 18adf5f63f Add all wallets option to the RepeatPaymentsModel
And the planned payments tab on mobile uses it to filter on the selected
wallet. Or show for all wallets.
2026-03-15 19:44:56 +01:00

232 lines
9.0 KiB
QML

import QtQuick
Item {
property bool hideQRScanButton: true
property bool combineWallets: allWalletsEntrySelected
onCombineWalletsChanged: {
tokens.combineWallets = combineWallets
}
Flickable {
id: canvas
anchors.fill: parent
boundsBehavior: Flickable.StopAtBounds
property bool editable: false
property real cellWidth: parent.width / tokensLayout.screenColumnCount
property real cellHeight: parent.height / tokensLayout.screenRowCount
contentWidth: cellWidth * tokensLayout.screenColumnCount
contentHeight: cellHeight * tokensLayout.rowCount
Repeater {
model: canvas.editable ? tokensLayout.screenColumnCount + 1 : 0
delegate: Rectangle {
x: index * (parent.width / tokensLayout.screenColumnCount)
width: 1
height: parent.height
color: palette.alternateBase
}
}
Repeater {
model: canvas.editable ? tokensLayout.rowCount + 1 : 0
delegate: Rectangle {
y: index * (parent.height / tokensLayout.rowCount)
width: parent.width
height: 1
color: palette.alternateBase
}
}
// Interactive widgets
Repeater {
model: tokensLayout.widgets
delegate: Item {
id: container
z: dragArea.pressed || resizeArea.pressed ? 100 : 1
property real cellWidth: canvas.cellWidth
property real cellHeight: canvas.cellHeight
x: modelData.col * cellWidth
y: modelData.row * cellHeight
width: modelData.colSpan * cellWidth
height: modelData.rowSpan * cellHeight
// Visual border (highlight when interacting)
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: (dragArea.pressed || resizeArea.pressed) ? "blue" : "gray"
border.width: 2
radius: 8
visible: canvas.editable
}
Loader {
anchors.fill: parent
anchors.margins: 8
source: modelData.source
clip: true
}
// Drag the widget
MouseArea {
id: dragArea
anchors.fill: parent
enabled: canvas.editable
cursorShape: pressed ? Qt.ClosedHandCursor : Qt.OpenHandCursor
property point grabOffset: Qt.point(0, 0)
onPressed: (mouse) => {
var pressGlobal = dragArea.mapToItem(container.parent, mouse.x, mouse.y)
grabOffset = Qt.point(pressGlobal.x - container.x, pressGlobal.y - container.y)
canvas.interactive = false
}
onPositionChanged: (mouse) => {
if (pressed) {
var currentGlobal = dragArea.mapToItem(container.parent, mouse.x, mouse.y)
// Desired position if no snap (grabbed point follows cursor exactly)
var desiredX = currentGlobal.x - grabOffset.x
var desiredY = currentGlobal.y - grabOffset.y
// Live snap to grid
var candidateCol = Math.round(desiredX / cellWidth)
var candidateRow = Math.round(desiredY / cellHeight)
// Clamp to keep widget fully inside grid
candidateCol = Math.max(0, Math.min(candidateCol,
tokensLayout.screenColumnCount - modelData.colSpan))
candidateRow = Math.max(0, Math.min(candidateRow,
tokensLayout.rowCount - modelData.rowSpan))
container.x = candidateCol * cellWidth
container.y = candidateRow * cellHeight
}
}
onReleased: {
// Update backend to final snapped position
var finalCol = Math.round(container.x / cellWidth)
var finalRow = Math.round(container.y / cellHeight)
modelData.col = finalCol
modelData.row = finalRow
canvas.interactive = true
}
}
// Resize handle
Rectangle {
id: resizeHandle
width: 24
height: 24
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: -8
color: "#80ffffff"
radius: 4
border.color: "#666666"
border.width: 1
visible: canvas.editable
// Grip visual
Repeater {
model: 3
Rectangle {
width: 4
height: 4
color: "#666666"
x: 4 + index * 5
y: 4 + index * 5
}
}
MouseArea {
id: resizeArea
anchors.fill: parent
cursorShape: Qt.SizeFDiagCursor
enabled: canvas.editable
property real startWidth: 0
property real startHeight: 0
property point pressMousePos: Qt.point(0, 0)
onPressed: (mouse) => {
startWidth = container.width
startHeight = container.height
pressMousePos = resizeArea.mapToItem(container.parent, mouse.x, mouse.y)
canvas.interactive = false
}
onPositionChanged: (mouse) => {
if (pressed) {
var currentMousePos = resizeArea.mapToItem(container.parent, mouse.x, mouse.y)
var deltaX = currentMousePos.x - pressMousePos.x
var deltaY = currentMousePos.y - pressMousePos.y
var newPixelWidth = startWidth + deltaX
var newPixelHeight = startHeight + deltaY
// Enforce minimum before snapping
newPixelWidth = Math.max(newPixelWidth, model.minimumWidth * cellWidth)
newPixelHeight = Math.max(newPixelHeight, model.minimumHeight * cellHeight)
// Live snap to grid units
var candColSpan = Math.round(newPixelWidth / cellWidth)
var candRowSpan = Math.round(newPixelHeight / cellHeight)
// Clamp to grid bounds
candColSpan = Math.min(candColSpan, tokensLayout.screenColumnCount - model.col)
candRowSpan = Math.min(candRowSpan, tokensLayout.rowCount - model.row)
container.width = candColSpan * cellWidth
container.height = candRowSpan * cellHeight
}
}
onReleased: {
var finalColSpan = container.width / cellWidth
var finalRowSpan = container.height / cellHeight
model.colSpan = finalColSpan
model.rowSpan = finalRowSpan
canvas.interactive = true
}
}
}
}
}
}
Rectangle {
width: 50
height: 20
anchors.right: parent.right
color: "blue"
visible: false // disable configurability for now.
MouseArea {
anchors.fill: parent
onClicked: {
canvas.editable = !canvas.editable
activityTabs.interactive = !activityTabs.interactive
if (canvas.editable)
tokensLayout.rowCount += 12
else
tokensLayout.trimRows()
}
}
}
Keys.onPressed: (event)=> {
if (event.key === Qt.Key_Escape || event.key === Qt.Key_Back) {
if (canvas.editable) {
event.accepted = true
canvas.editable = false
activityTabs.interactive = true
}
}
}
}