2023-09-19 14:10:39 +03:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
|
|
|
|
import QtQuick
|
|
|
|
import HelperWidgets as HelperWidgets
|
|
|
|
import StudioControls as StudioControls
|
2024-01-16 12:30:29 +01:00
|
|
|
import StudioTheme as StudioTheme
|
2024-01-26 14:55:50 +02:00
|
|
|
import EffectComposerBackend
|
2023-09-19 14:10:39 +03:00
|
|
|
|
|
|
|
StudioControls.ComboBox {
|
|
|
|
id: root
|
|
|
|
|
|
|
|
actionIndicatorVisible: false
|
|
|
|
x: 5
|
|
|
|
width: 60
|
|
|
|
|
|
|
|
model: [selectedImage]
|
|
|
|
|
|
|
|
// hide default popup
|
|
|
|
popup.width: 0
|
|
|
|
popup.height: 0
|
|
|
|
|
|
|
|
required property Item mainRoot
|
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
property var images: [Qt.url(""),
|
|
|
|
Qt.url("images/preview0.png"),
|
|
|
|
Qt.url("images/preview1.png"),
|
|
|
|
Qt.url("images/preview2.png"),
|
|
|
|
Qt.url("images/preview3.png"),
|
|
|
|
Qt.url("images/preview4.png")]
|
|
|
|
property url selectedImage: EffectComposerBackend.effectComposerModel.currentPreviewImage != Qt.url("")
|
|
|
|
? EffectComposerBackend.effectComposerModel.currentPreviewImage
|
|
|
|
: images[1]
|
|
|
|
|
|
|
|
Component.onCompleted: EffectComposerBackend.effectComposerModel.currentPreviewImage = images[1]
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2023-11-17 13:19:00 +02:00
|
|
|
readonly property int popupHeight: Math.min(800, col.height + 2)
|
|
|
|
|
|
|
|
function calculateWindowGeometry() {
|
2024-01-26 14:55:50 +02:00
|
|
|
var globalPos = EffectComposerBackend.rootView.globalPos(mainRoot.mapFromItem(root, 0, 0))
|
|
|
|
var screenRect = EffectComposerBackend.rootView.screenRect();
|
2023-11-17 13:19:00 +02:00
|
|
|
|
|
|
|
window.width = col.width + 2 // 2: scrollView left and right 1px margins
|
|
|
|
|
|
|
|
var newX = globalPos.x + root.width - window.width
|
|
|
|
if (newX < screenRect.x)
|
|
|
|
newX = globalPos.x
|
|
|
|
|
|
|
|
var newY = Math.min(screenRect.y + screenRect.height,
|
|
|
|
Math.max(screenRect.y, globalPos.y + root.height - 1))
|
|
|
|
|
|
|
|
// Check if we have more space above or below the control, and put control on that side,
|
|
|
|
// unless we have enough room for maximum size popup under the control
|
|
|
|
var newHeight
|
|
|
|
var screenY = newY - screenRect.y
|
|
|
|
if (screenRect.height - screenY > screenY || screenRect.height - screenY > root.popupHeight) {
|
|
|
|
newHeight = Math.min(root.popupHeight, screenRect.height - screenY)
|
|
|
|
} else {
|
|
|
|
newHeight = Math.min(root.popupHeight, screenY - root.height)
|
|
|
|
newY = newY - newHeight - root.height + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
window.height = newHeight
|
|
|
|
window.x = newX
|
|
|
|
window.y = newY
|
|
|
|
}
|
|
|
|
|
2023-09-19 14:10:39 +03:00
|
|
|
Connections {
|
|
|
|
target: root.popup
|
|
|
|
|
|
|
|
function onAboutToShow() {
|
2023-11-17 13:19:00 +02:00
|
|
|
root.calculateWindowGeometry()
|
2023-09-19 14:10:39 +03:00
|
|
|
|
|
|
|
window.show()
|
|
|
|
window.requestActivate()
|
2023-11-17 13:19:00 +02:00
|
|
|
|
|
|
|
// Geometry can get corrupted by first show after screen change, so recalc it
|
|
|
|
root.calculateWindowGeometry()
|
2023-09-19 14:10:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function onAboutToHide() {
|
|
|
|
window.hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
contentItem: Item {
|
|
|
|
width: 30
|
|
|
|
height: 30
|
|
|
|
|
|
|
|
Image {
|
|
|
|
source: root.selectedImage
|
|
|
|
fillMode: Image.PreserveAspectFit
|
|
|
|
smooth: true
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.margins: 1
|
|
|
|
}
|
2023-11-20 16:35:35 +02:00
|
|
|
|
|
|
|
MouseArea {
|
|
|
|
anchors.fill: parent
|
|
|
|
enabled: true
|
|
|
|
acceptedButtons: Qt.LeftButton
|
|
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
onPressed: (mouse) => {
|
|
|
|
if (root.popup.opened)
|
|
|
|
root.popup.close()
|
|
|
|
else
|
|
|
|
root.popup.open()
|
|
|
|
mouse.accepted = true
|
|
|
|
}
|
|
|
|
}
|
2023-09-19 14:10:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Window {
|
|
|
|
id: window
|
|
|
|
|
2024-03-12 15:43:48 +02:00
|
|
|
flags: Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2023-09-20 16:49:06 +03:00
|
|
|
onActiveFocusItemChanged: {
|
2023-11-20 16:35:35 +02:00
|
|
|
if (!window.activeFocusItem && !root.hovered && root.popup.opened)
|
2023-09-19 14:10:39 +03:00
|
|
|
root.popup.close()
|
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
anchors.fill: parent
|
|
|
|
color: StudioTheme.Values.themePanelBackground
|
|
|
|
border.color: StudioTheme.Values.themeInteraction
|
|
|
|
border.width: 1
|
2023-11-20 16:35:35 +02:00
|
|
|
focus: true
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
Column {
|
2023-09-19 14:10:39 +03:00
|
|
|
anchors.fill: parent
|
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
Item {
|
|
|
|
id: setCustomItem
|
|
|
|
width: parent.width
|
2024-10-21 13:59:38 +03:00
|
|
|
height: 50
|
2024-10-17 16:15:56 +03:00
|
|
|
|
|
|
|
HelperWidgets.Button {
|
|
|
|
anchors.fill: parent
|
2024-10-21 13:59:38 +03:00
|
|
|
anchors.bottomMargin: 2
|
|
|
|
anchors.topMargin: col.padding
|
|
|
|
anchors.leftMargin: col.padding
|
|
|
|
anchors.rightMargin: col.padding
|
2024-10-17 16:15:56 +03:00
|
|
|
text: qsTr("Set Custom Image")
|
|
|
|
onClicked: {
|
|
|
|
EffectComposerBackend.effectComposerModel.chooseCustomPreviewImage()
|
|
|
|
root.popup.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-19 14:10:39 +03:00
|
|
|
|
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
HelperWidgets.ScrollView {
|
|
|
|
width: parent.width - 2
|
|
|
|
height: parent.height - setCustomItem.height
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
clip: true
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
Column {
|
|
|
|
id: col
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
padding: 10
|
|
|
|
spacing: 10
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
Repeater {
|
|
|
|
model: root.images
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
Rectangle {
|
|
|
|
required property int index
|
|
|
|
required property var modelData
|
|
|
|
|
|
|
|
color: "transparent"
|
|
|
|
border.color: root.selectedImage === modelData ? StudioTheme.Values.themeInteraction
|
|
|
|
: "transparent"
|
|
|
|
|
|
|
|
width: 200
|
|
|
|
height: 200
|
|
|
|
visible: index > 0
|
|
|
|
|| EffectComposerBackend.effectComposerModel.customPreviewImage !== Qt.url("")
|
|
|
|
|
|
|
|
Image {
|
|
|
|
source: index > 0
|
|
|
|
? parent.modelData
|
|
|
|
: EffectComposerBackend.effectComposerModel.customPreviewImage
|
|
|
|
anchors.fill: parent
|
|
|
|
fillMode: Image.PreserveAspectFit
|
|
|
|
smooth: true
|
|
|
|
anchors.margins: 1
|
|
|
|
}
|
2023-09-19 14:10:39 +03:00
|
|
|
|
2024-10-17 16:15:56 +03:00
|
|
|
MouseArea {
|
|
|
|
anchors.fill: parent
|
|
|
|
|
|
|
|
onClicked: {
|
|
|
|
if (parent.index > 0) {
|
|
|
|
EffectComposerBackend.effectComposerModel.currentPreviewImage
|
|
|
|
= root.images[index]
|
|
|
|
} else {
|
|
|
|
EffectComposerBackend.effectComposerModel.currentPreviewImage
|
|
|
|
= EffectComposerBackend.effectComposerModel.customPreviewImage
|
|
|
|
}
|
|
|
|
root.popup.close()
|
|
|
|
}
|
2023-09-19 14:10:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-20 16:35:35 +02:00
|
|
|
|
|
|
|
Keys.onPressed: function(event) {
|
|
|
|
if (event.key === Qt.Key_Escape && root.popup.opened)
|
|
|
|
root.popup.close()
|
|
|
|
}
|
2023-09-19 14:10:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|