2022-05-04 09:25:01 +00:00
|
|
|
import QtQuick 2.14
|
|
|
|
import QtQuick.Layouts 1.14
|
|
|
|
import QtQuick.Controls 2.14
|
|
|
|
import QtQuick.Dialogs 1.3
|
|
|
|
|
|
|
|
import utils 1.0
|
|
|
|
import shared.panels 1.0
|
|
|
|
import shared.popups 1.0
|
|
|
|
|
|
|
|
import StatusQ.Core 0.1
|
|
|
|
import StatusQ.Core.Theme 0.1
|
|
|
|
import StatusQ.Layout 0.1
|
|
|
|
import StatusQ.Components 0.1
|
|
|
|
import StatusQ.Controls 0.1
|
|
|
|
import StatusQ.Controls.Validators 0.1
|
|
|
|
import StatusQ.Popups 0.1
|
|
|
|
|
|
|
|
Item {
|
|
|
|
id: root
|
|
|
|
|
2022-06-01 14:00:57 +00:00
|
|
|
property alias source: croppedPreview.source
|
|
|
|
property alias cropRect: croppedPreview.cropRect
|
|
|
|
/*required*/ property alias aspectRatio: imageCropWorkflow.aspectRatio
|
2022-05-04 09:25:01 +00:00
|
|
|
|
2022-06-01 14:00:57 +00:00
|
|
|
property alias roundedImage: imageCropWorkflow.roundedImage
|
2022-05-04 09:25:01 +00:00
|
|
|
|
2022-06-01 14:00:57 +00:00
|
|
|
/*required*/ property alias imageFileDialogTitle: imageCropWorkflow.imageFileDialogTitle
|
|
|
|
/*required*/ property alias title: imageCropWorkflow.title
|
|
|
|
/*required*/ property alias acceptButtonText: imageCropWorkflow.acceptButtonText
|
2023-05-16 15:07:21 +00:00
|
|
|
property alias editButtonVisible: editButton.visible
|
2022-05-04 09:25:01 +00:00
|
|
|
|
|
|
|
property string dataImage: ""
|
|
|
|
|
2022-07-12 08:27:35 +00:00
|
|
|
property Component backgroundComponent
|
|
|
|
|
2022-05-04 09:25:01 +00:00
|
|
|
property bool userSelectedImage: false
|
|
|
|
readonly property bool nothingToShow: state === d.noImageState
|
|
|
|
|
2022-09-01 07:53:22 +00:00
|
|
|
readonly property alias cropWorkflow : imageCropWorkflow
|
|
|
|
|
2023-05-16 15:07:21 +00:00
|
|
|
function cropImage(file) {
|
|
|
|
imageCropWorkflow.cropImage(file);
|
|
|
|
}
|
2023-05-08 12:00:26 +00:00
|
|
|
|
2022-07-12 08:27:35 +00:00
|
|
|
function chooseImageToCrop() {
|
|
|
|
imageCropWorkflow.chooseImageToCrop()
|
|
|
|
}
|
|
|
|
|
2022-05-04 09:25:01 +00:00
|
|
|
implicitWidth: mainLayout.implicitWidth
|
|
|
|
implicitHeight: mainLayout.implicitHeight
|
|
|
|
|
|
|
|
|
|
|
|
states: [
|
|
|
|
State {
|
|
|
|
name: d.dataImageState
|
|
|
|
when: root.dataImage.length > 0 && !userSelectedImage
|
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: d.noImageState
|
2022-07-12 08:27:35 +00:00
|
|
|
when: root.dataImage.length === 0 && !userSelectedImage && !backgroundComponent
|
2022-05-04 09:25:01 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: d.imageSelectedState
|
|
|
|
when: userSelectedImage
|
2022-07-12 08:27:35 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: d.backgroundComponentState
|
|
|
|
when: root.dataImage.length === 0 && !userSelectedImage && backgroundComponent
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
QtObject {
|
|
|
|
id: d
|
|
|
|
|
|
|
|
readonly property string dataImageState: "dataImage"
|
|
|
|
readonly property string noImageState: "noImage"
|
|
|
|
readonly property string imageSelectedState: "imageSelected"
|
2022-07-12 08:27:35 +00:00
|
|
|
readonly property string backgroundComponentState: "backgroundComponent"
|
2022-05-23 18:53:31 +00:00
|
|
|
readonly property int buttonsInsideOffset: 5
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: mainLayout
|
|
|
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
|
|
|
Item {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
|
2022-07-12 08:27:35 +00:00
|
|
|
visible: !imageCropEditor.visible && (root.state !== d.backgroundComponentState)
|
2022-05-04 09:25:01 +00:00
|
|
|
|
|
|
|
StatusRoundedImage {
|
|
|
|
anchors.fill: parent
|
|
|
|
|
|
|
|
visible: root.state === d.dataImageState
|
|
|
|
|
|
|
|
image.source: root.dataImage
|
|
|
|
showLoadingIndicator: true
|
|
|
|
border.width: 1
|
|
|
|
border.color: Style.current.border
|
2022-06-01 14:00:57 +00:00
|
|
|
radius: root.roundedImage ? width/2 : croppedPreview.radius
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
|
2022-05-23 18:53:31 +00:00
|
|
|
StatusImageCrop {
|
2022-06-01 14:00:57 +00:00
|
|
|
id: croppedPreview
|
2022-05-04 09:25:01 +00:00
|
|
|
anchors.fill: parent
|
|
|
|
|
|
|
|
visible: root.state === d.imageSelectedState
|
2022-06-01 14:00:57 +00:00
|
|
|
windowStyle: imageCropWorkflow.windowStyle
|
2022-05-04 09:25:01 +00:00
|
|
|
wallColor: Theme.palette.statusAppLayout.backgroundColor
|
|
|
|
wallTransparency: 1
|
2022-05-23 18:53:31 +00:00
|
|
|
clip:true
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StatusRoundButton {
|
|
|
|
id: editButton
|
|
|
|
|
2023-04-25 09:40:00 +00:00
|
|
|
icon.name: "edit_pencil"
|
2022-05-04 09:25:01 +00:00
|
|
|
|
2023-04-25 09:40:00 +00:00
|
|
|
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
2022-05-23 18:53:31 +00:00
|
|
|
transform: [
|
|
|
|
Translate {
|
|
|
|
x: -editButton.width/2 - d.buttonsInsideOffset
|
2023-04-25 09:40:00 +00:00
|
|
|
y: -editButton.height/2 + d.buttonsInsideOffset
|
2022-05-23 18:53:31 +00:00
|
|
|
},
|
|
|
|
Rotation { angle: -editRotationTransform.angle },
|
|
|
|
Rotation {
|
|
|
|
id: editRotationTransform
|
2023-04-25 09:40:00 +00:00
|
|
|
angle: 135
|
2022-05-23 18:53:31 +00:00
|
|
|
origin.x: editButton.rotationRadius
|
|
|
|
},
|
|
|
|
Translate {
|
|
|
|
x: root.roundedImage ? 0 : editButton.parent.width - 2 * editButton.rotationRadius
|
2023-04-25 09:40:00 +00:00
|
|
|
y: editButton.rotationRadius
|
2022-05-23 18:53:31 +00:00
|
|
|
}
|
|
|
|
]
|
2022-05-04 09:25:01 +00:00
|
|
|
type: StatusRoundButton.Type.Secondary
|
|
|
|
|
2023-04-25 09:40:00 +00:00
|
|
|
onClicked: chooseImageToCrop()
|
|
|
|
// TODO uncomment when status-go supports deleting images:
|
|
|
|
// onClicked: imageEditMenu.popup(this, mouse.x, mouse.y)
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
2022-06-01 14:00:57 +00:00
|
|
|
id: imageCropEditor
|
2022-05-04 09:25:01 +00:00
|
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
|
|
|
|
visible: root.state === d.noImageState
|
2022-06-01 14:00:57 +00:00
|
|
|
radius: roundedImage ? Math.max(width, height)/2 : croppedPreview.radius
|
2022-05-04 09:25:01 +00:00
|
|
|
color: Style.current.inputBackground
|
|
|
|
|
|
|
|
StatusRoundButton {
|
|
|
|
id: addButton
|
|
|
|
|
|
|
|
icon.name: "add"
|
2022-06-01 14:00:57 +00:00
|
|
|
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
2022-07-12 08:27:35 +00:00
|
|
|
|
2022-05-23 18:53:31 +00:00
|
|
|
transform: [
|
|
|
|
Translate {
|
|
|
|
x: -addButton.width/2 - d.buttonsInsideOffset
|
|
|
|
y: -addButton.height/2 + d.buttonsInsideOffset
|
|
|
|
},
|
|
|
|
Rotation { angle: -addRotationTransform.angle },
|
|
|
|
Rotation {
|
|
|
|
id: addRotationTransform
|
|
|
|
angle: 135
|
|
|
|
origin.x: addButton.rotationRadius
|
|
|
|
},
|
|
|
|
Translate {
|
|
|
|
x: root.roundedImage ? 0 : addButton.parent.width - 2 * addButton.rotationRadius
|
|
|
|
y: addButton.rotationRadius
|
|
|
|
}
|
|
|
|
]
|
2022-05-04 09:25:01 +00:00
|
|
|
|
|
|
|
type: StatusRoundButton.Type.Secondary
|
|
|
|
|
2023-04-25 09:40:00 +00:00
|
|
|
onClicked: chooseImageToCrop()
|
2022-06-01 14:00:57 +00:00
|
|
|
z: imageCropEditor.z + 1
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
|
2022-06-01 14:00:57 +00:00
|
|
|
ImageCropWorkflow {
|
|
|
|
id: imageCropWorkflow
|
2022-05-31 09:07:45 +00:00
|
|
|
|
2022-05-23 11:29:58 +00:00
|
|
|
onImageCropped: {
|
2022-06-01 14:00:57 +00:00
|
|
|
croppedPreview.source = image
|
|
|
|
croppedPreview.setCropRect(cropRect)
|
2022-05-23 11:29:58 +00:00
|
|
|
root.userSelectedImage = true
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-12 08:27:35 +00:00
|
|
|
|
|
|
|
Loader {
|
|
|
|
id: backgroundLoader
|
|
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
|
|
|
|
visible: root.state == d.backgroundComponentState
|
|
|
|
|
|
|
|
sourceComponent: root.backgroundComponent
|
|
|
|
}
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|
2023-04-25 09:40:00 +00:00
|
|
|
|
|
|
|
StatusMenu {
|
|
|
|
id: imageEditMenu
|
|
|
|
|
|
|
|
StatusAction {
|
|
|
|
text: qsTr("Select different image")
|
|
|
|
assetSettings.name: "image"
|
|
|
|
onTriggered: chooseImageToCrop()
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusAction {
|
|
|
|
text: qsTr("Remove image")
|
|
|
|
type: StatusAction.Danger
|
|
|
|
assetSettings.name: "delete"
|
|
|
|
onTriggered: {
|
|
|
|
root.userSelectedImage = false
|
|
|
|
root.dataImage = ""
|
|
|
|
root.source = ""
|
|
|
|
croppedPreview.setCropRect(Qt.rect(0, 0, 0, 0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-04 09:25:01 +00:00
|
|
|
}
|