Make clipboard picker use a master/detail layout

This commit is contained in:
David Heinemeier Hansson
2026-05-17 10:49:53 +02:00
parent 32527e9201
commit 2381d015e0
@@ -30,8 +30,7 @@ Item {
property int contentSpacing: 6 property int contentSpacing: 6
property int cardWidth: 800 property int cardWidth: 800
property int cardHeight: 600 property int cardHeight: 600
property int rowHeight: 60 property int rowHeight: 50
property int cellWidth: (cardWidth - contentMargin * 2 - contentSpacing) / 2
function open(payloadJson) { function open(payloadJson) {
root.opened = true root.opened = true
@@ -211,15 +210,9 @@ Item {
if (root.filterText.length > 0) root.setFilter(root.filterText.slice(0, -1)) if (root.filterText.length > 0) root.setFilter(root.filterText.slice(0, -1))
event.accepted = true event.accepted = true
} else if (event.key === Qt.Key_Up) { } else if (event.key === Qt.Key_Up) {
root.select(-2)
event.accepted = true
} else if (event.key === Qt.Key_Down) {
root.select(2)
event.accepted = true
} else if (event.key === Qt.Key_Left) {
root.select(-1) root.select(-1)
event.accepted = true event.accepted = true
} else if (event.key === Qt.Key_Right) { } else if (event.key === Qt.Key_Down) {
root.select(1) root.select(1)
event.accepted = true event.accepted = true
} else if (event.key === Qt.Key_PageUp) { } else if (event.key === Qt.Key_PageUp) {
@@ -267,24 +260,27 @@ Item {
width: parent.width width: parent.width
height: parent.height - root.headerHeight - root.contentSpacing height: parent.height - root.headerHeight - root.contentSpacing
GridView { Row {
id: resultList
anchors.fill: parent anchors.fill: parent
spacing: root.contentSpacing
ListView {
id: resultList
width: parent.width / 2 - root.contentSpacing / 2
height: parent.height
model: displayModel model: displayModel
clip: true clip: true
cellWidth: root.cellWidth spacing: 4
cellHeight: root.rowHeight
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
delegate: Rectangle { delegate: Rectangle {
required property int index required property int index
required property string identifier required property string identifier
required property string previewText required property string previewText
required property string previewImage
required property string previewType required property string previewType
width: root.cellWidth - 4 width: ListView.view.width
height: root.rowHeight - 4 height: root.rowHeight
radius: root.cornerRadius radius: root.cornerRadius
color: index === root.selectedIndex ? root.withAlpha(root.foreground, 0.08) : root.withAlpha(root.foreground, mouseArea.containsMouse ? 0.045 : 0) color: index === root.selectedIndex ? root.withAlpha(root.foreground, 0.08) : root.withAlpha(root.foreground, mouseArea.containsMouse ? 0.045 : 0)
@@ -307,45 +303,18 @@ Item {
anchors.bottomMargin: 8 anchors.bottomMargin: 8
Text { Text {
visible: parent.parent.previewType === "text"
width: parent.width width: parent.width
height: parent.height height: parent.height
text: parent.parent.previewText text: parent.parent.previewType === "text" ? parent.parent.previewText : "Image"
color: index === root.selectedIndex ? root.accent : root.foreground color: index === root.selectedIndex ? root.accent : root.foreground
font.family: root.fontFamily font.family: root.fontFamily
font.pixelSize: 14 font.pixelSize: 14
font.italic: parent.parent.previewType === "file"
opacity: parent.parent.previewType === "file" ? 0.6 : 1.0
elide: Text.ElideRight elide: Text.ElideRight
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
Item {
visible: parent.parent.previewType === "file"
width: parent.width
height: parent.height
Image {
source: parent.parent.parent.previewImage
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height * 1.5
fillMode: Image.PreserveAspectFit
}
Text {
anchors.left: parent.children[0].right
anchors.leftMargin: 12
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "Image"
color: root.foreground
opacity: 0.6
font.family: root.fontFamily
font.pixelSize: 14
font.italic: true
}
}
} }
MouseArea { MouseArea {
@@ -361,6 +330,40 @@ Item {
} }
} }
Rectangle {
width: parent.width / 2 - root.contentSpacing / 2
height: parent.height
radius: root.cornerRadius
color: root.withAlpha(root.background, 0.5)
border.color: root.withAlpha(root.border, 0.1)
border.width: 1
clip: true
property var activeRow: displayModel.count > 0 && root.selectedIndex >= 0 && root.selectedIndex < displayModel.count ? displayModel.get(root.selectedIndex) : null
Text {
visible: parent.activeRow && parent.activeRow.previewType === "text"
anchors.fill: parent
anchors.margins: 16
text: parent.activeRow ? parent.activeRow.previewText : ""
color: root.foreground
font.family: root.fontFamily
font.pixelSize: 14
wrapMode: Text.WrapAnywhere
elide: Text.ElideRight
verticalAlignment: Text.AlignTop
}
Image {
visible: parent.activeRow && parent.activeRow.previewType === "file"
anchors.fill: parent
anchors.margins: 16
source: parent.activeRow ? parent.activeRow.previewImage : ""
fillMode: Image.PreserveAspectFit
}
}
}
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
spacing: 8 spacing: 8