Skip to content

Commit dbaa368

Browse files
Copilotsaeugetier
andcommitted
Add visual preview panel with interactive photo slots
Co-authored-by: saeugetier <1408260+saeugetier@users.noreply.github.com>
1 parent 128a003 commit dbaa368

1 file changed

Lines changed: 223 additions & 16 deletions

File tree

qml/CollageTemplateEditor.qml

Lines changed: 223 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ Item {
105105
}
106106
}
107107

108-
// Right panel: Template editor
108+
// Middle panel: Template editor
109109
ColumnLayout {
110-
Layout.fillWidth: true
110+
Layout.preferredWidth: 350
111111
Layout.fillHeight: true
112112
spacing: 10
113113

@@ -158,7 +158,10 @@ Item {
158158
Layout.fillWidth: true
159159
text: currentTemplate ? currentTemplate.icon : ""
160160
onEditingFinished: {
161-
if(currentTemplate) currentTemplate.icon = text
161+
if(currentTemplate) {
162+
currentTemplate.icon = text
163+
refreshPreview()
164+
}
162165
}
163166
}
164167

@@ -167,7 +170,10 @@ Item {
167170
id: printableCheck
168171
checked: currentTemplate ? (currentTemplate.printable !== false) : true
169172
onToggled: {
170-
if(currentTemplate) currentTemplate.printable = checked
173+
if(currentTemplate) {
174+
currentTemplate.printable = checked
175+
refreshPreview()
176+
}
171177
}
172178
}
173179
}
@@ -190,7 +196,10 @@ Item {
190196
Layout.fillWidth: true
191197
text: currentTemplate ? currentTemplate.background : ""
192198
onEditingFinished: {
193-
if(currentTemplate) currentTemplate.background = text
199+
if(currentTemplate) {
200+
currentTemplate.background = text
201+
refreshPreview()
202+
}
194203
}
195204
}
196205

@@ -200,7 +209,10 @@ Item {
200209
Layout.fillWidth: true
201210
text: currentTemplate ? currentTemplate.foreground : ""
202211
onEditingFinished: {
203-
if(currentTemplate) currentTemplate.foreground = text
212+
if(currentTemplate) {
213+
currentTemplate.foreground = text
214+
refreshPreview()
215+
}
204216
}
205217
}
206218
}
@@ -224,7 +236,10 @@ Item {
224236
to: 10000
225237
value: currentTemplate ? currentTemplate.width : 3570
226238
onValueModified: {
227-
if(currentTemplate) currentTemplate.width = value
239+
if(currentTemplate) {
240+
currentTemplate.width = value
241+
refreshPreview()
242+
}
228243
}
229244
}
230245

@@ -235,7 +250,10 @@ Item {
235250
to: 10000
236251
value: currentTemplate ? currentTemplate.height : 2380
237252
onValueModified: {
238-
if(currentTemplate) currentTemplate.height = value
253+
if(currentTemplate) {
254+
currentTemplate.height = value
255+
refreshPreview()
256+
}
239257
}
240258
}
241259
}
@@ -304,6 +322,162 @@ Item {
304322
}
305323
}
306324
}
325+
326+
// Right panel: Preview
327+
ColumnLayout {
328+
Layout.fillWidth: true
329+
Layout.fillHeight: true
330+
spacing: 10
331+
visible: currentTemplate !== null
332+
333+
Label {
334+
text: qsTr("Preview")
335+
font.pixelSize: 16
336+
font.bold: true
337+
}
338+
339+
Rectangle {
340+
Layout.fillWidth: true
341+
Layout.fillHeight: true
342+
color: "#f0f0f0"
343+
border.color: "#cccccc"
344+
border.width: 1
345+
346+
Item {
347+
id: previewArea
348+
anchors.fill: parent
349+
anchors.margins: 20
350+
351+
Rectangle {
352+
id: previewCanvas
353+
anchors.centerIn: parent
354+
width: {
355+
if(!currentTemplate) return 400
356+
var aspect = currentTemplate.width / currentTemplate.height
357+
var maxWidth = previewArea.width
358+
var maxHeight = previewArea.height
359+
if(maxWidth / aspect <= maxHeight) {
360+
return maxWidth
361+
} else {
362+
return maxHeight * aspect
363+
}
364+
}
365+
height: width / (currentTemplate ? (currentTemplate.width / currentTemplate.height) : 1.5)
366+
color: "#ffffff"
367+
border.color: "#333333"
368+
border.width: 2
369+
370+
// Background indicator
371+
Label {
372+
anchors.top: parent.top
373+
anchors.left: parent.left
374+
anchors.margins: 5
375+
text: currentTemplate ? "BG: " + currentTemplate.background : ""
376+
font.pixelSize: 10
377+
color: "#666666"
378+
}
379+
380+
// Photo slots
381+
Repeater {
382+
model: currentTemplate ? currentTemplate.images.length : 0
383+
384+
Rectangle {
385+
property var slot: currentTemplate.images[index]
386+
x: slot.x * previewCanvas.width
387+
y: slot.y * previewCanvas.height
388+
width: slot.width * previewCanvas.width
389+
height: slot.height * previewCanvas.height
390+
color: Qt.rgba(0.3, 0.5, 0.8, 0.3)
391+
border.color: "#2196F3"
392+
border.width: 2
393+
rotation: slot.rotation || 0
394+
transformOrigin: Item.TopLeft
395+
396+
Label {
397+
anchors.centerIn: parent
398+
text: (index + 1).toString()
399+
font.pixelSize: 20
400+
font.bold: true
401+
color: "#2196F3"
402+
}
403+
404+
// Border indicator
405+
Rectangle {
406+
anchors.fill: parent
407+
anchors.margins: 3
408+
color: "transparent"
409+
border.color: "#FF5722"
410+
border.width: slot.border && slot.border.file ? 3 : 0
411+
}
412+
413+
MouseArea {
414+
anchors.fill: parent
415+
onClicked: {
416+
photoSlotEditor.currentSlotIndex = index
417+
photoSlotEditor.visible = true
418+
}
419+
cursorShape: Qt.PointingHandCursor
420+
}
421+
}
422+
}
423+
424+
// Foreground indicator
425+
Label {
426+
anchors.bottom: parent.bottom
427+
anchors.right: parent.right
428+
anchors.margins: 5
429+
text: currentTemplate && currentTemplate.foreground ? "FG: " + currentTemplate.foreground : ""
430+
font.pixelSize: 10
431+
color: "#666666"
432+
}
433+
}
434+
}
435+
436+
// Legend
437+
Column {
438+
anchors.right: parent.right
439+
anchors.bottom: parent.bottom
440+
anchors.margins: 10
441+
spacing: 5
442+
443+
Row {
444+
spacing: 5
445+
Rectangle {
446+
width: 20
447+
height: 20
448+
color: Qt.rgba(0.3, 0.5, 0.8, 0.3)
449+
border.color: "#2196F3"
450+
border.width: 2
451+
}
452+
Label {
453+
text: qsTr("Photo slot")
454+
font.pixelSize: 10
455+
}
456+
}
457+
458+
Row {
459+
spacing: 5
460+
Rectangle {
461+
width: 20
462+
height: 20
463+
color: "transparent"
464+
border.color: "#FF5722"
465+
border.width: 3
466+
}
467+
Label {
468+
text: qsTr("Has border")
469+
font.pixelSize: 10
470+
}
471+
}
472+
}
473+
}
474+
475+
Label {
476+
text: currentTemplate ? qsTr("Size: %1 x %2 px").arg(currentTemplate.width).arg(currentTemplate.height) : ""
477+
font.pixelSize: 12
478+
Layout.alignment: Qt.AlignHCenter
479+
}
480+
}
307481
}
308482

309483
// Photo slot editor dialog
@@ -332,7 +506,10 @@ Item {
332506
from: 0
333507
to: 100
334508
value: getSlotValue("x", 0) * 100
335-
onValueModified: setSlotValue("x", value / 100.0)
509+
onValueModified: {
510+
setSlotValue("x", value / 100.0)
511+
collageTemplateEditor.refreshPreview()
512+
}
336513
}
337514

338515
Label { text: qsTr("Position Y (0-1):") }
@@ -341,7 +518,10 @@ Item {
341518
from: 0
342519
to: 100
343520
value: getSlotValue("y", 0) * 100
344-
onValueModified: setSlotValue("y", value / 100.0)
521+
onValueModified: {
522+
setSlotValue("y", value / 100.0)
523+
collageTemplateEditor.refreshPreview()
524+
}
345525
}
346526

347527
Label { text: qsTr("Width (0-1):") }
@@ -350,7 +530,10 @@ Item {
350530
from: 1
351531
to: 100
352532
value: getSlotValue("width", 100) * 100
353-
onValueModified: setSlotValue("width", value / 100.0)
533+
onValueModified: {
534+
setSlotValue("width", value / 100.0)
535+
collageTemplateEditor.refreshPreview()
536+
}
354537
}
355538

356539
Label { text: qsTr("Height (0-1):") }
@@ -359,7 +542,10 @@ Item {
359542
from: 1
360543
to: 100
361544
value: getSlotValue("height", 100) * 100
362-
onValueModified: setSlotValue("height", value / 100.0)
545+
onValueModified: {
546+
setSlotValue("height", value / 100.0)
547+
collageTemplateEditor.refreshPreview()
548+
}
363549
}
364550

365551
Label { text: qsTr("Rotation (degrees):") }
@@ -368,30 +554,42 @@ Item {
368554
from: -180
369555
to: 180
370556
value: getSlotValue("rotation", 0)
371-
onValueModified: setSlotValue("rotation", value)
557+
onValueModified: {
558+
setSlotValue("rotation", value)
559+
collageTemplateEditor.refreshPreview()
560+
}
372561
}
373562

374563
Label { text: qsTr("Border Image:") }
375564
TextField {
376565
id: borderField
377566
Layout.fillWidth: true
378567
text: getSlotBorderValue("file", "")
379-
onEditingFinished: setSlotBorderValue("file", text)
568+
onEditingFinished: {
569+
setSlotBorderValue("file", text)
570+
collageTemplateEditor.refreshPreview()
571+
}
380572
}
381573

382574
Label { text: qsTr("Effect Preset:") }
383575
TextField {
384576
id: effectPresetField
385577
Layout.fillWidth: true
386578
text: getSlotValue("effectPreset", "")
387-
onEditingFinished: setSlotValue("effectPreset", text)
579+
onEditingFinished: {
580+
setSlotValue("effectPreset", text)
581+
collageTemplateEditor.refreshPreview()
582+
}
388583
}
389584

390585
Label { text: qsTr("Effect Selectable:") }
391586
CheckBox {
392587
id: effectSelectableCheck
393588
checked: getSlotValue("effectSelectable", true)
394-
onToggled: setSlotValue("effectSelectable", checked)
589+
onToggled: {
590+
setSlotValue("effectSelectable", checked)
591+
collageTemplateEditor.refreshPreview()
592+
}
395593
}
396594
}
397595

@@ -648,6 +846,7 @@ Item {
648846
rotation: 0
649847
})
650848
photoSlotsView.model = currentTemplate.images.length
849+
refreshPreview()
651850
showStatus(qsTr("Added photo slot"), "#4CAF50")
652851
}
653852

@@ -656,9 +855,17 @@ Item {
656855

657856
currentTemplate.images.pop()
658857
photoSlotsView.model = currentTemplate.images.length
858+
refreshPreview()
659859
showStatus(qsTr("Removed photo slot"), "#4CAF50")
660860
}
661861

862+
function refreshPreview() {
863+
// Trigger preview update by modifying a property
864+
var temp = currentTemplate
865+
currentTemplate = null
866+
currentTemplate = temp
867+
}
868+
662869
function showStatus(text, color) {
663870
statusLabel.text = text
664871
statusLabel.color = color

0 commit comments

Comments
 (0)