299 lines
9.2 KiB
QML
299 lines
9.2 KiB
QML
|
import QtQuick 2.14
|
||
|
import QtQuick.Controls 2.14
|
||
|
import QtQuick.Layouts 1.14
|
||
|
import QtQuick.Dialogs 1.3
|
||
|
import QtQml 2.14
|
||
|
import QtGraphicalEffects 1.14
|
||
|
|
||
|
import Storybook 1.0
|
||
|
import Models 1.0
|
||
|
|
||
|
import StatusQ.Components 0.1
|
||
|
import StatusQ.Controls 0.1
|
||
|
import StatusQ.Popups 0.1
|
||
|
|
||
|
SplitView {
|
||
|
id: root
|
||
|
|
||
|
property var testControls: [ctrl1, ctrl2, ctrl3]
|
||
|
|
||
|
property bool globalStylePreferRound: true
|
||
|
property var testImageList: [ModelsData.banners.dragonereum,
|
||
|
ModelsData.banners.superRare,
|
||
|
ModelsData.banners.socks]
|
||
|
property int testImageIndex: 0
|
||
|
property int testSpacing: 0
|
||
|
property int testFrameMargins: 10
|
||
|
|
||
|
implicitWidth: mainLayout.implicitWidth
|
||
|
implicitHeight: mainLayout.implicitHeight
|
||
|
|
||
|
Logs { id: logs }
|
||
|
|
||
|
SplitView {
|
||
|
orientation: Qt.Horizontal
|
||
|
SplitView.fillWidth: true
|
||
|
SplitView.fillHeight: true
|
||
|
|
||
|
|
||
|
RowLayout {
|
||
|
id: mainLayout
|
||
|
|
||
|
anchors.fill: parent
|
||
|
spacing: root.testSpacing
|
||
|
|
||
|
ColumnLayout {
|
||
|
spacing: root.testSpacing
|
||
|
|
||
|
Layout.margins: root.testSpacing
|
||
|
Layout.fillWidth: true
|
||
|
|
||
|
Text {
|
||
|
text: `AR: ${ctrl1.aspectRatio.toFixed(2)}`
|
||
|
}
|
||
|
|
||
|
StatusImageCropPanel {
|
||
|
id: ctrl1
|
||
|
|
||
|
Layout.fillWidth: true
|
||
|
Layout.fillHeight: true
|
||
|
|
||
|
source: root.testImageList[root.testImageIndex]
|
||
|
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
|
||
|
margins: root.testFrameMargins
|
||
|
}
|
||
|
|
||
|
Text {
|
||
|
text: `AR: ${ctrl2.aspectRatio.toFixed(2)}`
|
||
|
}
|
||
|
|
||
|
StatusImageCropPanel {
|
||
|
id: ctrl2
|
||
|
|
||
|
Layout.fillWidth: true
|
||
|
Layout.fillHeight: true
|
||
|
|
||
|
source: root.testImageList[root.testImageIndex]
|
||
|
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rectangular : StatusImageCrop.WindowStyle.Rounded
|
||
|
aspectRatio: 16/9
|
||
|
enableCheckers: true
|
||
|
margins: root.testFrameMargins + 2
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ColumnLayout {
|
||
|
Layout.margins: root.testSpacing
|
||
|
Layout.fillWidth: true
|
||
|
|
||
|
Text {
|
||
|
text: `AR: ${ctrl3.aspectRatio.toFixed(2)}`
|
||
|
}
|
||
|
|
||
|
StatusImageCropPanel {
|
||
|
id: ctrl3
|
||
|
|
||
|
Layout.fillWidth: true
|
||
|
Layout.fillHeight: true
|
||
|
|
||
|
source: root.testImageList[root.testImageIndex]
|
||
|
windowStyle: globalStylePreferRound ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
|
||
|
aspectRatio: 0.8
|
||
|
|
||
|
margins: root.testFrameMargins + 5.3
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Loader {
|
||
|
id: workflowLoader
|
||
|
|
||
|
sourceComponent: workflowComponent
|
||
|
active: false
|
||
|
onStatusChanged: {
|
||
|
if(status === Loader.Ready) {
|
||
|
item.imageFileDialogTitle = qsTr("Test Title")
|
||
|
item.title = "Test popup"
|
||
|
item.acceptButtonText = "Load Custom Image"
|
||
|
item.chooseImageToCrop()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Connections {
|
||
|
target: workflowLoader.item
|
||
|
function onImageCropped(image, cropRect) {
|
||
|
ctrl1.source = image
|
||
|
ctrl2.source = image
|
||
|
ctrl3.source = image
|
||
|
}
|
||
|
function onCanceled() {
|
||
|
workflowLoader.active = false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Component {
|
||
|
id: workflowComponent
|
||
|
|
||
|
Item {
|
||
|
id: workflowItem
|
||
|
|
||
|
property alias aspectRatio: imageCropper.aspectRatio
|
||
|
property alias windowStyle: imageCropper.windowStyle
|
||
|
property string imageFileDialogTitle: ""
|
||
|
property string title: ""
|
||
|
property string acceptButtonText: ""
|
||
|
property bool roundedImage: true
|
||
|
|
||
|
signal imageCropped(var image, var cropRect)
|
||
|
signal canceled()
|
||
|
|
||
|
function chooseImageToCrop() {
|
||
|
fileDialog.open()
|
||
|
}
|
||
|
|
||
|
FileDialog {
|
||
|
id: fileDialog
|
||
|
|
||
|
title: workflowItem.imageFileDialogTitle
|
||
|
folder: workflowItem.userSelectedImage ? imageCropper.source.substr(0, imageCropper.source.lastIndexOf("/")) : shortcuts.pictures
|
||
|
nameFilters: [qsTr("Supported image formats (%1)").arg("*.jpg *.jpeg *.jfif *.webp *.png *.heif")]
|
||
|
onAccepted: {
|
||
|
if (fileDialog.fileUrls.length > 0) {
|
||
|
imageCropper.source = fileDialog.fileUrls[0]
|
||
|
imageCropperModal.open()
|
||
|
}
|
||
|
}
|
||
|
onRejected: workflowItem.canceled()
|
||
|
} // FileDialog
|
||
|
|
||
|
StatusModal {
|
||
|
id: imageCropperModal
|
||
|
|
||
|
header.title: workflowItem.title
|
||
|
|
||
|
anchors.centerIn: Overlay.overlay
|
||
|
|
||
|
width: workflowItem.roundedImage ? 480 : 580
|
||
|
|
||
|
onClosed: workflowItem.canceled()
|
||
|
|
||
|
StatusImageCropPanel {
|
||
|
id: imageCropper
|
||
|
|
||
|
implicitHeight: workflowItem.roundedImage ? 350 : 370
|
||
|
|
||
|
anchors {
|
||
|
fill: parent
|
||
|
leftMargin: 10 * 2
|
||
|
rightMargin: 10 * 2
|
||
|
topMargin: 15
|
||
|
bottomMargin: 15
|
||
|
}
|
||
|
|
||
|
margins: workflowItem.roundedImage ? 10 : 20
|
||
|
windowStyle: workflowItem.roundedImage ? StatusImageCrop.WindowStyle.Rounded : StatusImageCrop.WindowStyle.Rectangular
|
||
|
enableCheckers: true
|
||
|
}
|
||
|
|
||
|
rightButtons: [
|
||
|
StatusButton {
|
||
|
text: workflowItem.acceptButtonText
|
||
|
|
||
|
enabled: imageCropper.sourceSize.width > 0 && imageCropper.sourceSize.height > 0
|
||
|
|
||
|
onClicked: {
|
||
|
workflowItem.imageCropped(imageCropper.source, imageCropper.cropRect)
|
||
|
imageCropperModal.close()
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
} // StatusModal
|
||
|
} // Item
|
||
|
}
|
||
|
|
||
|
Shortcut {
|
||
|
sequence: StandardKey.ZoomIn
|
||
|
onActivated: {
|
||
|
for(let i in testControls) {
|
||
|
const c = testControls[i]
|
||
|
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, -0.05))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Shortcut {
|
||
|
sequence: StandardKey.ZoomOut
|
||
|
onActivated: {
|
||
|
for(let i in testControls) {
|
||
|
const c = testControls[i]
|
||
|
c.setCropRect(ctrl1.inflateRectBy(c.cropRect, 0.05))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Shortcut {
|
||
|
sequences: ["Ctrl+W"]
|
||
|
onActivated: globalStylePreferRound = !globalStylePreferRound
|
||
|
}
|
||
|
|
||
|
LogsAndControlsPanel {
|
||
|
id: logsAndControlsPanel
|
||
|
|
||
|
SplitView.minimumHeight: 100
|
||
|
SplitView.preferredHeight: 200
|
||
|
|
||
|
logsView.logText: logs.logText
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Control {
|
||
|
SplitView.minimumWidth: 300
|
||
|
SplitView.preferredWidth: 300
|
||
|
|
||
|
font.pixelSize: 13
|
||
|
|
||
|
ColumnLayout {
|
||
|
anchors.centerIn: parent
|
||
|
spacing: 16
|
||
|
|
||
|
StatusButton {
|
||
|
Layout.alignment: Qt.AlignHCenter
|
||
|
text: qsTr("Cycle image")
|
||
|
onClicked: {
|
||
|
let newIndex = root.testImageIndex
|
||
|
newIndex++
|
||
|
if(newIndex >= root.testImageList.length)
|
||
|
newIndex = 0
|
||
|
root.testImageIndex = newIndex
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StatusButton {
|
||
|
Layout.alignment: Qt.AlignHCenter
|
||
|
text: qsTr("Cycle spacing")
|
||
|
onClicked: {
|
||
|
root.testSpacing += (root.testSpacing/2) + 1
|
||
|
if(root.testSpacing > 35)
|
||
|
root.testSpacing = 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StatusButton {
|
||
|
Layout.alignment: Qt.AlignHCenter
|
||
|
text: qsTr("Cycle frame margins")
|
||
|
onClicked: {
|
||
|
root.testFrameMargins += (root.testFrameMargins/2) + 1
|
||
|
if(root.testFrameMargins > 50)
|
||
|
root.testFrameMargins = 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StatusButton {
|
||
|
Layout.alignment: Qt.AlignHCenter
|
||
|
text: qsTr("Load external image")
|
||
|
onClicked: workflowLoader.active = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|