import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 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.Popups 0.1 Item { id: root property alias source: croppedPreview.source property alias cropRect: croppedPreview.cropRect /*required*/ property alias aspectRatio: imageCropWorkflow.aspectRatio property alias roundedImage: imageCropWorkflow.roundedImage /*required*/ property alias imageFileDialogTitle: imageCropWorkflow.imageFileDialogTitle /*required*/ property alias title: imageCropWorkflow.title /*required*/ property alias acceptButtonText: imageCropWorkflow.acceptButtonText property alias editButtonVisible: editButton.visible property string dataImage: "" property Component backgroundComponent property bool userSelectedImage: false readonly property bool nothingToShow: state === d.noImageState property bool isError readonly property alias cropWorkflow : imageCropWorkflow function cropImage(file) { imageCropWorkflow.cropImage(file); } function chooseImageToCrop() { imageCropWorkflow.chooseImageToCrop() } implicitWidth: mainLayout.implicitWidth implicitHeight: mainLayout.implicitHeight objectName: "editCroppedImageItem_" + root.title states: [ State { name: d.dataImageState when: root.dataImage.length > 0 && !userSelectedImage }, State { name: d.noImageState when: root.dataImage.length === 0 && !userSelectedImage && !backgroundComponent }, State { name: d.imageSelectedState when: userSelectedImage }, State { name: d.backgroundComponentState when: root.dataImage.length === 0 && !userSelectedImage && backgroundComponent } ] QtObject { id: d readonly property string dataImageState: "dataImage" readonly property string noImageState: "noImage" readonly property string imageSelectedState: "imageSelected" readonly property string backgroundComponentState: "backgroundComponent" readonly property int buttonsInsideOffset: 5 } ColumnLayout { id: mainLayout anchors.fill: parent Item { Layout.fillWidth: true Layout.fillHeight: true visible: !imageCropEditor.visible && (root.state !== d.backgroundComponentState) StatusRoundedImage { anchors.fill: parent visible: root.state === d.dataImageState image.source: root.dataImage showLoadingIndicator: true border.width: 1 border.color: Theme.palette.border radius: root.roundedImage ? width/2 : croppedPreview.radius } StatusImageCrop { id: croppedPreview anchors.fill: parent visible: root.state === d.imageSelectedState windowStyle: imageCropWorkflow.windowStyle wallColor: Theme.palette.statusAppLayout.backgroundColor wallTransparency: 1 clip:true } StatusRoundButton { id: editButton icon.name: "edit_pencil" width: 40 height: 40 readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius transform: [ Translate { x: -editButton.width/2 - d.buttonsInsideOffset y: -editButton.height/2 + d.buttonsInsideOffset }, Rotation { angle: -editRotationTransform.angle }, Rotation { id: editRotationTransform angle: 135 origin.x: editButton.rotationRadius }, Translate { x: root.roundedImage ? 0 : editButton.parent.width - 2 * editButton.rotationRadius y: editButton.rotationRadius } ] type: StatusRoundButton.Type.Secondary onClicked: chooseImageToCrop() // TODO uncomment when status-go supports deleting images: // onClicked: imageEditMenu.popup(this, mouse.x, mouse.y) } } Rectangle { id: imageCropEditor Layout.fillWidth: true Layout.fillHeight: true visible: root.state === d.noImageState radius: roundedImage ? Math.max(width, height)/2 : croppedPreview.radius color: Theme.palette.baseColor2 border.color: Theme.palette.dangerColor1 border.width: root.isError ? 1 : 0 StatusRoundButton { id: addButton icon.name: "add" width: 40 height: 40 readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius 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 } ] type: StatusRoundButton.Type.Secondary onClicked: chooseImageToCrop() z: imageCropEditor.z + 1 } ImageCropWorkflow { id: imageCropWorkflow onImageCropped: { croppedPreview.source = image croppedPreview.setCropRect(cropRect) root.userSelectedImage = true } } } Loader { id: backgroundLoader Layout.fillWidth: true Layout.fillHeight: true visible: root.state == d.backgroundComponentState sourceComponent: root.backgroundComponent } } 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)) } } } }