mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-22 02:32:29 +01:00
WIP: Replace Sidebar with bottom drawer with timeline
This commit is contained in:
parent
c1a81588d9
commit
f9cafc891b
@ -61,7 +61,7 @@ set(VCPKG_BIN_PATH "${VCPKG_INSTALLED_PATH}/bin")
|
||||
# Godot Editor
|
||||
set(GODOT_VERSION_MAJOR "4")
|
||||
set(GODOT_VERSION_MINOR "2")
|
||||
set(GODOT_VERSION_PATCH "")
|
||||
set(GODOT_VERSION_PATCH "1")
|
||||
set(GODOT_RELEASE_TYPE "stable")
|
||||
|
||||
# Use an if statement to check if GODOT_VERSION_PATCH is empty or not
|
||||
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<script>
|
||||
let body = document.getElementsByTagName('body')[0];
|
||||
body.setAttribute('style', 'margin: 0px;padding: 0px;overflow: hidden;background:black;');
|
||||
|
||||
let html = document.getElementsByTagName('html')[0];
|
||||
html.setAttribute('style', 'margin: 0px;padding: 0px;overflow: hidden;background:black;');
|
||||
|
||||
var videoElem = document.createElement('video');
|
||||
videoElem.setAttribute('width', '100%');
|
||||
videoElem.setAttribute('height', '100%');
|
||||
videoElem.setAttribute('id', 'video');
|
||||
videoElem.muted = true;
|
||||
videoElem.autoplay = true;
|
||||
videoElem.loop = true;
|
||||
document.body.appendChild(videoElem);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -13,6 +13,7 @@
|
||||
#include "monitorlistmodel.h"
|
||||
#include "profilelistmodel.h"
|
||||
#include "projectsettingslistmodel.h"
|
||||
#include "screenplayprofiles.h"
|
||||
#include "screenplaywallpaper.h"
|
||||
#include "screenplaywidget.h"
|
||||
#include "settings.h"
|
||||
@ -21,6 +22,21 @@
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
struct Wallpaper {
|
||||
QString name;
|
||||
QTime startTime;
|
||||
QTime endTime;
|
||||
QString absolutePath;
|
||||
QString previewImage;
|
||||
float playbackRate;
|
||||
float volume;
|
||||
QString file;
|
||||
QJsonObject properties;
|
||||
ContentTypes::InstalledType type;
|
||||
Video::FillMode fillMode;
|
||||
QVector<int> monitors;
|
||||
};
|
||||
|
||||
class ScreenPlayManager : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
@ -139,11 +155,14 @@ public slots:
|
||||
|
||||
private:
|
||||
bool loadProfiles();
|
||||
bool loadWidgetConfig(const QJsonObject& widget);
|
||||
bool loadWallpaperConfig(const QJsonObject& wallpaper);
|
||||
bool checkIsAnotherScreenPlayInstanceRunning();
|
||||
bool removeWallpaper(const QString& appID);
|
||||
bool removeWidget(const QString& appID);
|
||||
|
||||
private:
|
||||
ScreenPlayProfiles m_screenPlayProfiles;
|
||||
std::shared_ptr<GlobalVariables> m_globalVariables;
|
||||
std::shared_ptr<MonitorListModel> m_monitorListModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
@ -161,6 +180,6 @@ private:
|
||||
QTimer m_saveLimiter;
|
||||
|
||||
const quint16 m_webSocketPort = 16395;
|
||||
bool loadTimelineWallpaperConfig(const QJsonObject& wallpaperObj);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ TabButton {
|
||||
|
||||
ToolButton {
|
||||
icon.source: control.icon.source
|
||||
icon.color: control.checked ? Material.accentColor : Material.secondaryTextColor
|
||||
icon.color: control.checked ? Material.accentColor : "transparent"
|
||||
hoverEnabled: false
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
@ -49,6 +49,7 @@ TabButton {
|
||||
opacity: 0.6
|
||||
width: parent.width * 0.2
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_open_in_new.svg"
|
||||
icon.color: "transparent"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
onClicked: Qt.openUrlExternally(control.openLink)
|
||||
|
@ -14,7 +14,7 @@ Rectangle {
|
||||
Text {
|
||||
id: text
|
||||
color: "white"
|
||||
text: root.index
|
||||
//text: root.index
|
||||
anchors{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
|
@ -4,11 +4,11 @@ import QtQuick.Layouts
|
||||
|
||||
Control {
|
||||
id: root
|
||||
height: 220
|
||||
height: 160
|
||||
implicitWidth: 800
|
||||
topPadding: 40
|
||||
leftPadding: 40
|
||||
rightPadding: 40
|
||||
topPadding: 20
|
||||
leftPadding: 20
|
||||
rightPadding: 20
|
||||
contentItem: Item {
|
||||
id: timeLine
|
||||
|
||||
|
@ -335,7 +335,7 @@ Item {
|
||||
modalSource: root.modalSource
|
||||
anchors.centerIn: Overlay.overlay
|
||||
onAccepted: {
|
||||
root.sidebar.clear()
|
||||
root.sidebar.close()
|
||||
if (!App.installedListModel.deinstallItemAt(
|
||||
contextMenu.absoluteStoragePath)) {
|
||||
console.error("Unable to uninstall item",
|
||||
|
@ -9,11 +9,14 @@ import ScreenPlayApp
|
||||
|
||||
import ScreenPlayUtil
|
||||
import "../Monitors"
|
||||
import "../Components"
|
||||
|
||||
Item {
|
||||
Drawer {
|
||||
id: root
|
||||
|
||||
property real navHeight
|
||||
height: 500
|
||||
modal: false
|
||||
edge: Qt.BottomEdge
|
||||
property bool hasPreviewGif: false
|
||||
property var type: ContentTypes.InstalledType.QMLWallpaper
|
||||
property string contentFolderName
|
||||
|
||||
@ -29,15 +32,13 @@ Item {
|
||||
// This is used for removing wallpaper. We need to clear
|
||||
// the preview image/gif so we can release the file for deletion.
|
||||
function clear() {
|
||||
root.close()
|
||||
imagePreview.source = ""
|
||||
animatedImagePreview.source = ""
|
||||
txtHeadline.text = ""
|
||||
root.state = "inactive"
|
||||
sidebarWrapper.state = "inactive"
|
||||
}
|
||||
|
||||
width: 400
|
||||
state: "inactive"
|
||||
property bool hasPreviewGif: false
|
||||
onContentFolderNameChanged: {
|
||||
const item = App.installedListModel.get(root.contentFolderName)
|
||||
txtHeadline.text = item.m_title
|
||||
@ -64,97 +65,109 @@ Item {
|
||||
function onSetSidebarItem(folderName, type) {
|
||||
|
||||
// Toggle sidebar if clicked on the same content twice
|
||||
if (root.contentFolderName === folderName
|
||||
&& root.state !== "inactive") {
|
||||
root.state = "inactive"
|
||||
if (root.contentFolderName === folderName && root.opened) {
|
||||
root.close()
|
||||
return
|
||||
}
|
||||
root.contentFolderName = folderName
|
||||
root.type = type
|
||||
if (App.util.isWallpaper(root.type)) {
|
||||
if (type === ContentTypes.InstalledType.VideoWallpaper)
|
||||
root.state = "activeWallpaper"
|
||||
sidebarWrapper.state = "wallpaper"
|
||||
else
|
||||
root.state = "activeScene"
|
||||
sidebarWrapper.state = "scene"
|
||||
btnLaunchContent.text = qsTr("Set Wallpaper")
|
||||
} else {
|
||||
root.state = "activeWidget"
|
||||
sidebarWrapper.state = "widget"
|
||||
btnLaunchContent.text = qsTr("Set Widget")
|
||||
}
|
||||
root.open()
|
||||
}
|
||||
|
||||
target: App.util
|
||||
}
|
||||
|
||||
MouseHoverBlocker {}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Material.theme === Material.Light ? "white" : Material.background
|
||||
opacity: 0.95
|
||||
layer.enabled: true
|
||||
|
||||
layer.effect: ElevationEffect {
|
||||
elevation: 4
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
RowLayout {
|
||||
id: sidebarWrapper
|
||||
state: "inactive"
|
||||
spacing: 20
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
id: navBackground
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 10
|
||||
spacing: 5
|
||||
|
||||
height: navHeight
|
||||
ColumnLayout {
|
||||
spacing: 5
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 160
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
Text {
|
||||
Layout.leftMargin: 20
|
||||
text: qsTr("Select the duration your wallpaper should be visible")
|
||||
font.family: App.settings.font
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pointSize: 11
|
||||
color: Material.secondaryTextColor
|
||||
}
|
||||
|
||||
Timeline {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "transparent"
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.1
|
||||
color: "#AAffffff"
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.horizontalStretchFactor: 3
|
||||
spacing: 10
|
||||
|
||||
Text {
|
||||
text: qsTr("Select a Monitor to display the content")
|
||||
font.family: App.settings.font
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pointSize: 11
|
||||
color: Material.secondaryTextColor
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#ffffff"
|
||||
MonitorSelection {
|
||||
id: monitorSelection
|
||||
objectName: "monitorSelection"
|
||||
height: 200
|
||||
Layout.fillWidth: true
|
||||
availableWidth: width
|
||||
availableHeight: height
|
||||
fontSize: 11
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.horizontalStretchFactor: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sidebarBackground
|
||||
|
||||
anchors {
|
||||
top: navBackground.bottom
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.preferredWidth: 260
|
||||
Layout.fillHeight: true
|
||||
spacing: 10
|
||||
|
||||
Rectangle {
|
||||
id: imageWrapper
|
||||
|
||||
height: 237
|
||||
color: "#2b2b2b"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
Layout.preferredHeight: 180
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
// Do NOT enable async image loading!
|
||||
// Otherwhise it will still hold the file
|
||||
@ -220,62 +233,12 @@ Item {
|
||||
left: parent.left
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: button
|
||||
|
||||
height: 50
|
||||
width: 50
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.state = "inactive"
|
||||
|
||||
Image {
|
||||
id: imgBack
|
||||
|
||||
source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_arrow_right.svg"
|
||||
sourceSize: Qt.size(15, 15)
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 20
|
||||
|
||||
anchors {
|
||||
top: imageWrapper.bottom
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
margins: 30
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
id: txtHeadlineMonitor
|
||||
|
||||
height: 20
|
||||
text: qsTr("Select a Monitor to display the content")
|
||||
font.family: App.settings.font
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pointSize: 11
|
||||
color: Material.secondaryTextColor
|
||||
}
|
||||
|
||||
MonitorSelection {
|
||||
id: monitorSelection
|
||||
objectName: "monitorSelection"
|
||||
height: 180
|
||||
Layout.fillWidth: true
|
||||
availableWidth: width
|
||||
availableHeight: height
|
||||
fontSize: 11
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
LabelSlider {
|
||||
id: sliderVolume
|
||||
@ -365,14 +328,13 @@ Item {
|
||||
const absoluteStoragePath = item.m_absoluteStoragePath
|
||||
const previewImage = item.m_preview
|
||||
if (App.util.isWallpaper(root.type)) {
|
||||
if (type === ContentTypes.InstalledType.GodotWallpaper){
|
||||
if(!App.globalVariables.isBasicVersion()) {
|
||||
root.state = "inactive"
|
||||
if (type === ContentTypes.InstalledType.GodotWallpaper) {
|
||||
if (App.globalVariables.isBasicVersion()) {
|
||||
sidebarWrapper.state = "inactive"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let activeMonitors = monitorSelection.getActiveMonitors(
|
||||
)
|
||||
// TODO Alert user to choose a monitor
|
||||
@ -404,7 +366,7 @@ Item {
|
||||
1, {}, true)
|
||||
}
|
||||
})
|
||||
root.state = "inactive"
|
||||
root.close()
|
||||
return
|
||||
}
|
||||
|
||||
@ -420,230 +382,205 @@ Item {
|
||||
absoluteStoragePath,
|
||||
previewImage, {},
|
||||
true)
|
||||
root.state = "inactive"
|
||||
|
||||
root.close()
|
||||
monitorSelection.reset()
|
||||
}
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 20
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: button
|
||||
Layout.alignment: Qt.AlignTop
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_close.svg"
|
||||
icon.width: 15
|
||||
icon.height: 15
|
||||
onClicked: {
|
||||
root.close()
|
||||
sidebarWrapper.state = "inactive"
|
||||
}
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "inactive"
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 0
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 0
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "activeWidget"
|
||||
|
||||
PropertyChanges {
|
||||
target: sliderVolume
|
||||
visible: false
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: monitorSelection
|
||||
visible: false
|
||||
enabled: false
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "wallpaper"
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtComboBoxFillMode
|
||||
opacity: 1
|
||||
visible: true
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: cbVideoFillMode
|
||||
opacity: 1
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "scene"
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: sliderVolume
|
||||
opacity: 0
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
to: "inactive"
|
||||
from: "*"
|
||||
reversible: true
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 400
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "widget"
|
||||
from: "*"
|
||||
|
||||
SequentialAnimation {
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "wallpaper"
|
||||
from: "*"
|
||||
|
||||
SequentialAnimation {
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "scene"
|
||||
|
||||
SequentialAnimation {
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "inactive"
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
anchors.rightMargin: -root.width
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 0
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 0
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "activeWidget"
|
||||
|
||||
PropertyChanges {
|
||||
target: sliderVolume
|
||||
visible: false
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: monitorSelection
|
||||
visible: false
|
||||
enabled: false
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "activeWallpaper"
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtComboBoxFillMode
|
||||
opacity: 1
|
||||
visible: true
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: cbVideoFillMode
|
||||
opacity: 1
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "activeScene"
|
||||
|
||||
PropertyChanges {
|
||||
target: imagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: animatedImagePreview
|
||||
opacity: 1
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: txtHeadlineMonitor
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: sliderVolume
|
||||
opacity: 0
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
to: "inactive"
|
||||
from: "*"
|
||||
reversible: true
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 400
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
target: root
|
||||
properties: "anchors.rightMargin"
|
||||
duration: 250
|
||||
easing.type: Easing.OutQuart
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "activeWidget"
|
||||
from: "*"
|
||||
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: root
|
||||
properties: "anchors.rightMargin"
|
||||
duration: 250
|
||||
easing.type: Easing.OutQuart
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "activeWallpaper"
|
||||
from: "*"
|
||||
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: root
|
||||
properties: "anchors.rightMargin"
|
||||
duration: 250
|
||||
easing.type: Easing.OutQuart
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
to: "activeScene"
|
||||
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: root
|
||||
properties: "anchors.rightMargin"
|
||||
duration: 250
|
||||
easing.type: Easing.OutQuart
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
targets: [animatedImagePreview, imagePreview]
|
||||
property: "anchors.topMargin"
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ Item {
|
||||
"modalSource": content
|
||||
});
|
||||
nav.setNavigation(name);
|
||||
sidebar.state = "inactive";
|
||||
sidebar.close()
|
||||
}
|
||||
|
||||
Navigation.ExitPopup {
|
||||
@ -147,9 +147,9 @@ Item {
|
||||
Connections {
|
||||
function onSetSidebarActive(active) {
|
||||
if (active)
|
||||
sidebar.state = "active";
|
||||
sidebar.open()
|
||||
else
|
||||
sidebar.state = "inactive";
|
||||
sidebar.close()
|
||||
}
|
||||
|
||||
function onSetNavigationItem(pos) {
|
||||
@ -166,13 +166,7 @@ Item {
|
||||
Installed.Sidebar {
|
||||
id: sidebar
|
||||
objectName: "installedSidebar"
|
||||
navHeight: nav.height
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
width: content.width
|
||||
}
|
||||
|
||||
Navigation.Navigation {
|
||||
|
@ -69,6 +69,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
function resize() {
|
||||
print("resize")
|
||||
var absoluteDesktopSize = App.monitorListModel.absoluteDesktopSize();
|
||||
var isWidthGreaterThanHeight = false;
|
||||
var windowsDelta = 0;
|
||||
@ -161,4 +162,23 @@ Rectangle {
|
||||
snapMode: ScrollBar.SnapOnRelease
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
onClicked: App.monitorListModel.reset()
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/rotate-right-solid.svg"
|
||||
icon.width: 14
|
||||
icon.height: 14
|
||||
opacity: hovered ? 1 : .4
|
||||
hoverEnabled: true
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ GlobalVariables::GlobalVariables(QObject* parent)
|
||||
} else {
|
||||
setVersion(GlobalVariables::Version::OpenSourceStandalone);
|
||||
}
|
||||
setVersion(GlobalVariables::Version::OpenSourceUltraSteam);
|
||||
setVersion(GlobalVariables::Version::OpenSourceStandalone);
|
||||
setLocalSettingsPath(QUrl { QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) });
|
||||
}
|
||||
|
||||
|
@ -565,74 +565,22 @@ bool ScreenPlayManager::loadProfiles()
|
||||
}
|
||||
}
|
||||
|
||||
for (QJsonValueRef wallpaper : wallpaper.toObject().value("wallpaper").toArray()) {
|
||||
// for (QJsonValueRef wallpaper : wallpaper.toObject().value("wallpaper").toArray()) {
|
||||
// QJsonObject wallpaperObj = wallpaper.toObject();
|
||||
// if (!loadWallpaperConfig(wallpaperObj))
|
||||
// containsInvalidData = true;
|
||||
// }
|
||||
|
||||
for (QJsonValueRef timelineWallpaper : wallpaper.toObject().value("timelineWallpaper").toArray()) {
|
||||
QJsonObject wallpaperObj = wallpaper.toObject();
|
||||
|
||||
if (wallpaperObj.empty())
|
||||
continue;
|
||||
|
||||
QJsonArray monitorsArray = wallpaper.toObject().value("monitors").toArray();
|
||||
|
||||
QVector<int> monitors;
|
||||
for (const QJsonValueRef monitorNumber : monitorsArray) {
|
||||
int value = monitorNumber.toInt(-1);
|
||||
if (value == -1) {
|
||||
qWarning() << "Could not parse monitor number to display content at";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (monitors.contains(value)) {
|
||||
qWarning() << "The monitor: " << value << " is sharing the config multiple times. ";
|
||||
return false;
|
||||
}
|
||||
monitors.append(value);
|
||||
}
|
||||
|
||||
float volume = static_cast<float>(wallpaperObj.value("volume").toDouble(-1.0));
|
||||
|
||||
if (volume == -1.0F)
|
||||
volume = 1.0f;
|
||||
|
||||
const QString absolutePath = wallpaperObj.value("absolutePath").toString();
|
||||
const QString fillModeString = wallpaperObj.value("fillMode").toString();
|
||||
const QString previewImage = wallpaperObj.value("previewImage").toString();
|
||||
const float playbackRate = wallpaperObj.value("playbackRate").toDouble(1.0);
|
||||
const QString file = wallpaperObj.value("file").toString();
|
||||
const QString typeString = wallpaperObj.value("type").toString();
|
||||
const QJsonObject properties = wallpaperObj.value("properties").toObject();
|
||||
|
||||
const auto type = QStringToEnum<ContentTypes::InstalledType>(typeString, ContentTypes::InstalledType::VideoWallpaper);
|
||||
const auto fillMode = QStringToEnum<Video::FillMode>(fillModeString, Video::FillMode::Cover);
|
||||
|
||||
const bool success = createWallpaper(type, fillMode, absolutePath, previewImage, file, monitors, volume, playbackRate, properties, false);
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "Unable to start Wallpaper! " << type << fillMode << monitors << absolutePath;
|
||||
if (!loadTimelineWallpaperConfig(wallpaperObj))
|
||||
containsInvalidData = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const QJsonValueRef widget : wallpaper.toObject().value("widgets").toArray()) {
|
||||
QJsonObject widgetObj = widget.toObject();
|
||||
|
||||
if (widgetObj.empty())
|
||||
continue;
|
||||
|
||||
const QString absolutePath = widgetObj.value("absolutePath").toString();
|
||||
const QString previewImage = widgetObj.value("previewImage").toString();
|
||||
const QString typeString = widgetObj.value("type").toString();
|
||||
const int positionX = widgetObj.value("positionX").toInt(0);
|
||||
const int positionY = widgetObj.value("positionY").toInt(0);
|
||||
const QPoint position { positionX, positionY };
|
||||
const auto type = QStringToEnum<ContentTypes::InstalledType>(typeString, ContentTypes::InstalledType::QMLWidget);
|
||||
const QJsonObject properties = widgetObj.value("properties").toObject();
|
||||
|
||||
const bool success = createWidget(type, position, absolutePath, previewImage, properties, false);
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "Unable to start Widget! " << type << position << absolutePath;
|
||||
if (!loadWidgetConfig(widgetObj))
|
||||
containsInvalidData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -644,6 +592,87 @@ bool ScreenPlayManager::loadProfiles()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScreenPlayManager::loadTimelineWallpaperConfig(const QJsonObject& wallpaperObj)
|
||||
{
|
||||
const QString name = wallpaperObj.value("name").toString();
|
||||
const QString timeFormat = "hh:mm::ss";
|
||||
const QTime startTime = QTime::fromString(wallpaperObj.value("startTime").toString(), timeFormat);
|
||||
const QTime endTime = QTime::fromString(wallpaperObj.value("endTime").toString(), timeFormat);
|
||||
if (!loadWallpaperConfig(wallpaperObj))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScreenPlayManager::loadWallpaperConfig(const QJsonObject& wallpaperObj)
|
||||
{
|
||||
if (wallpaperObj.empty())
|
||||
return false;
|
||||
|
||||
QJsonArray monitorsArray = wallpaperObj.value("monitors").toArray();
|
||||
|
||||
QVector<int> monitors;
|
||||
for (const QJsonValueRef monitorNumber : monitorsArray) {
|
||||
int value = monitorNumber.toInt(-1);
|
||||
if (value == -1) {
|
||||
qWarning() << "Could not parse monitor number to display content at";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (monitors.contains(value)) {
|
||||
qWarning() << "The monitor: " << value << " is sharing the config multiple times. ";
|
||||
return false;
|
||||
}
|
||||
monitors.append(value);
|
||||
}
|
||||
|
||||
float volume = static_cast<float>(wallpaperObj.value("volume").toDouble(-1.0));
|
||||
|
||||
if (volume == -1.0F)
|
||||
volume = 1.0f;
|
||||
|
||||
const QString absolutePath = wallpaperObj.value("absolutePath").toString();
|
||||
const QString fillModeString = wallpaperObj.value("fillMode").toString();
|
||||
const QString previewImage = wallpaperObj.value("previewImage").toString();
|
||||
const float playbackRate = wallpaperObj.value("playbackRate").toDouble(1.0);
|
||||
const QString file = wallpaperObj.value("file").toString();
|
||||
const QString typeString = wallpaperObj.value("type").toString();
|
||||
const QJsonObject properties = wallpaperObj.value("properties").toObject();
|
||||
|
||||
const auto type = QStringToEnum<ContentTypes::InstalledType>(typeString, ContentTypes::InstalledType::VideoWallpaper);
|
||||
const auto fillMode = QStringToEnum<Video::FillMode>(fillModeString, Video::FillMode::Cover);
|
||||
|
||||
const bool success = createWallpaper(type, fillMode, absolutePath, previewImage, file, monitors, volume, playbackRate, properties, false);
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "Unable to start Wallpaper! " << type << fillMode << monitors << absolutePath;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScreenPlayManager::loadWidgetConfig(const QJsonObject& widgetObj)
|
||||
{
|
||||
if (widgetObj.empty())
|
||||
return false;
|
||||
|
||||
const QString absolutePath = widgetObj.value("absolutePath").toString();
|
||||
const QString previewImage = widgetObj.value("previewImage").toString();
|
||||
const QString typeString = widgetObj.value("type").toString();
|
||||
const int positionX = widgetObj.value("positionX").toInt(0);
|
||||
const int positionY = widgetObj.value("positionY").toInt(0);
|
||||
const QPoint position { positionX, positionY };
|
||||
const auto type = QStringToEnum<ContentTypes::InstalledType>(typeString, ContentTypes::InstalledType::QMLWidget);
|
||||
const QJsonObject properties = widgetObj.value("properties").toObject();
|
||||
|
||||
const bool success = createWidget(type, position, absolutePath, previewImage, properties, false);
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "Unable to start Widget! " << type << position << absolutePath;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_screenplaymanager.cpp"
|
||||
|
68
ScreenPlay/tests/example_config.json
Normal file
68
ScreenPlay/tests/example_config.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"appdrawer": [],
|
||||
"name": "default",
|
||||
"wallpaper": [
|
||||
{
|
||||
"name": "default",
|
||||
"absolutePath": "C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/05012024134225",
|
||||
"file": "2_15488489005711.mp4",
|
||||
"fillMode": "Contain",
|
||||
"isLooping": true,
|
||||
"monitors": [
|
||||
0
|
||||
],
|
||||
"playbackRate": 1,
|
||||
"previewImage": "previewThumbnail.jpg",
|
||||
"type": "VideoWallpaper",
|
||||
"volume": 0.6299999952316284
|
||||
}
|
||||
],
|
||||
"timelineWallpaper": [
|
||||
{
|
||||
"name": "test",
|
||||
"startTime": "00:00:00",
|
||||
"endTime": "12:00:00",
|
||||
"wallpaper": [
|
||||
{
|
||||
"absolutePath": "C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/05012024134225",
|
||||
"file": "2_15488489005711.mp4",
|
||||
"fillMode": "Contain",
|
||||
"isLooping": true,
|
||||
"monitors": [
|
||||
0
|
||||
],
|
||||
"playbackRate": 1,
|
||||
"previewImage": "previewThumbnail.jpg",
|
||||
"type": "VideoWallpaper",
|
||||
"volume": 0.6299999952316284
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"startTime": "12:01",
|
||||
"endTime": "24:00",
|
||||
"wallpaper": [
|
||||
{
|
||||
"absolutePath": "C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/05012024134225",
|
||||
"file": "2_15488489005711.mp4",
|
||||
"fillMode": "Contain",
|
||||
"isLooping": true,
|
||||
"monitors": [
|
||||
0
|
||||
],
|
||||
"playbackRate": 1,
|
||||
"previewImage": "previewThumbnail.jpg",
|
||||
"type": "VideoWallpaper",
|
||||
"volume": 0.6299999952316284
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"widgets": []
|
||||
}
|
||||
],
|
||||
"version": "1.0.0"
|
||||
}
|
@ -16,6 +16,11 @@ Rectangle {
|
||||
height: 50
|
||||
color: Material.theme === Material.Light ? "white" : Material.background
|
||||
|
||||
// Block input to underlying installed item
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
id: wrapper
|
||||
|
||||
|
@ -34,8 +34,8 @@ Item {
|
||||
Rotation {
|
||||
id: rt
|
||||
|
||||
origin.x: width * 0.5
|
||||
origin.y: height * 0.5
|
||||
origin.x: screenPlayItem.width * 0.5
|
||||
origin.y: screenPlayItem.height * 0.5
|
||||
angle: 0
|
||||
|
||||
axis {
|
||||
@ -50,15 +50,15 @@ Item {
|
||||
Scale {
|
||||
id: sc
|
||||
|
||||
origin.x: width * 0.5
|
||||
origin.y: height * 0.5
|
||||
origin.x: screenPlayItem.width * 0.5
|
||||
origin.y: screenPlayItem.height * 0.5
|
||||
}
|
||||
]
|
||||
|
||||
Timer {
|
||||
id: timerAnim
|
||||
|
||||
interval: 40 * itemIndex * Math.random()
|
||||
interval: 40 * screenPlayItem.itemIndex * Math.random()
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: showAnim.start()
|
||||
@ -151,7 +151,7 @@ Item {
|
||||
id: screenPlayItemImage
|
||||
|
||||
anchors.fill: parent
|
||||
sourceImage: Qt.resolvedUrl(screenPlayItem.absoluteStoragePath + "/" + screenPreview)
|
||||
sourceImage: Qt.resolvedUrl(screenPlayItem.absoluteStoragePath + "/" + screenPlayItem.screenPreview)
|
||||
}
|
||||
|
||||
Image {
|
||||
@ -193,17 +193,17 @@ Item {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onEntered: {
|
||||
if (!hasMenuOpen)
|
||||
if (!screenPlayItem.hasMenuOpen)
|
||||
screenPlayItem.state = "hover";
|
||||
}
|
||||
onExited: {
|
||||
if (!hasMenuOpen)
|
||||
if (!screenPlayItem.hasMenuOpen)
|
||||
screenPlayItem.state = "visible";
|
||||
}
|
||||
onClicked: {
|
||||
onClicked: function(mouse) {
|
||||
checkBox.toggle();
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
itemClicked(screenId, type, checkBox.checkState === Qt.Checked);
|
||||
itemClicked(screenPlayItem.folderName, type, checkBox.checkState === Qt.Checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,9 +213,9 @@ Item {
|
||||
|
||||
onCheckStateChanged: {
|
||||
if (checkState == Qt.Checked)
|
||||
isSelected = true;
|
||||
screenPlayItem.isSelected = true;
|
||||
else
|
||||
isSelected = false;
|
||||
screenPlayItem.isSelected = false;
|
||||
}
|
||||
|
||||
anchors {
|
||||
|
@ -179,6 +179,7 @@ Drawer {
|
||||
|
||||
Layout.fillWidth: true
|
||||
icon.source: "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_thumb_up.svg"
|
||||
icon.color: "transparent"
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Click here if you like the content")
|
||||
onClicked: {
|
||||
@ -193,6 +194,7 @@ Drawer {
|
||||
|
||||
Layout.fillWidth: true
|
||||
icon.source: "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_thumb_down.svg"
|
||||
icon.color: "transparent"
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Click here if you do not like the content")
|
||||
onClicked: {
|
||||
@ -322,6 +324,7 @@ Drawer {
|
||||
|
||||
font.pointSize: 10
|
||||
icon.source: "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_open_in_new.svg"
|
||||
icon.color: "transparent"
|
||||
height: 25
|
||||
text: qsTr("Open In Steam")
|
||||
onClicked: Qt.openUrlExternally("steam://url/CommunityFilePage/" + root.publishedFileID)
|
||||
|
@ -168,6 +168,7 @@ Item {
|
||||
ToolButton {
|
||||
onClicked: Qt.openUrlExternally("steam://url/CommunityFilePage/" + banner.bannerPublishedFileID)
|
||||
icon.source: "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_open_in_new.svg"
|
||||
icon.color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -339,6 +340,7 @@ Item {
|
||||
ToolButton {
|
||||
property bool hasContent: tiSearch.text.length > 0
|
||||
icon.source: hasContent ? "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_close.svg" : "qrc:/qml/ScreenPlayWorkshop/assets/icons/icon_search.svg"
|
||||
icon.color: "transparent"
|
||||
onClicked: {
|
||||
if (hasContent) {
|
||||
root.state = "searching";
|
||||
|
@ -36,7 +36,7 @@ VCPKG_BASE_PACKAGES = [
|
||||
]
|
||||
PYTHON_EXECUTABLE = "python" if sys.platform == "win32" else "python3"
|
||||
FFMPEG_VERSION = "6.1"
|
||||
GODOT_VERSION = "4.2"
|
||||
GODOT_VERSION = "4.2.1"
|
||||
GODOT_RELEASE_TYPE = "stable"
|
||||
GODOT_DOWNLOAD_SERVER = "https://github.com/godotengine/godot-builds/releases/download"
|
||||
if sys.platform == "win32":
|
||||
|
Loading…
Reference in New Issue
Block a user