diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index a28222d0..13a2ff2b 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -9,10 +9,9 @@ set(CMAKE_AUTOMOC ON) include(GenerateCMakeVariableHeader) set(SOURCES - # cmake-format: sort - src/applicationengine.cpp src/app.cpp + src/applicationengine.cpp src/create.cpp src/createimportvideo.cpp src/globalvariables.cpp @@ -29,7 +28,6 @@ set(SOURCES src/wizards.cpp) set(HEADER - # cmake-format: sort inc/public/ScreenPlay/app.h inc/public/ScreenPlay/applicationengine.h @@ -51,9 +49,14 @@ set(HEADER inc/public/ScreenPlay/wizards.h) set(QML - # cmake-format: sort main.qml + qml/Components/TrayIcon.qml + qml/Components/LineHandle.qml + qml/Components/LineIndicator.qml + qml/Components/ScreenPlayProPopup.qml + qml/Components/Section.qml + qml/Components/Timeline.qml qml/Community/CommunityNavItem.qml qml/Community/CommunityView.qml qml/Community/XMLNewsfeed.qml @@ -68,8 +71,8 @@ set(QML qml/Create/Wizards/HTMLWidget.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperFileSelect.qml - qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml + qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperSettings.qml qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml qml/Create/Wizards/QMLWallpaper.qml qml/Create/Wizards/QMLWidget.qml @@ -81,12 +84,14 @@ set(QML qml/Installed/ScreenPlayItem.qml qml/Installed/ScreenPlayItemImage.qml qml/Installed/Sidebar.qml + qml/MainApp.qml qml/Monitors/DefaultVideoControls.qml qml/Monitors/MonitorSelection.qml qml/Monitors/MonitorSelectionItem.qml qml/Monitors/MonitorsProjectSettingItem.qml qml/Monitors/MonitorsView.qml qml/Monitors/SaveNotification.qml + qml/Monitors/WallpaperTimeline.qml qml/Navigation/ExitPopup.qml qml/Navigation/Navigation.qml qml/Settings/SettingBool.qml @@ -97,12 +102,9 @@ set(QML qml/Settings/SettingsHorizontalSeperator.qml qml/Settings/SettingsPage.qml qml/Settings/SettingsView.qml - qml/TrayIcon.qml - qml/Base.qml qml/Workshop/WorkshopView.qml) set(TS_FILES - # cmake-format: sort translations/ScreenPlay_.ts translations/ScreenPlay_de_DE.ts @@ -119,7 +121,6 @@ set(TS_FILES translations/ScreenPlay_zh_CN.ts) set(RESOURCES - # cmake-format: sort "legal/Font Awesome Free License.txt" "legal/Qt LGPLv3.txt" @@ -130,9 +131,11 @@ set(RESOURCES assets/icons/brand_twitch.svg assets/icons/brand_twitter.svg assets/icons/exclamation-triangle-solid.svg + assets/icons/font-awsome/lock-solid.svg assets/icons/font-awsome/close.svg assets/icons/font-awsome/frown-o.svg assets/icons/font-awsome/patreon-brands.svg + assets/icons/font-awsome/rotate-right-solid.svg assets/icons/icon_arrow_left.svg assets/icons/icon_arrow_right.svg assets/icons/icon_build.svg @@ -187,7 +190,8 @@ set(RESOURCES assets/icons/item_banner_new.svg assets/icons/monitor_setup.svg assets/icons/steam_default_avatar.png - assets/images/Early_Access.png + assets/images/rocket_3d.png + assets/images/pro_version.png assets/images/Intro.png assets/images/Intro_PC.png assets/images/Intro_shine.png @@ -266,15 +270,15 @@ endif() find_package( Qt6 COMPONENTS Core - Quick - QuickControls2 - Gui - Widgets - WebSockets - Svg - Xml - LinguistTools - Test) + Quick + QuickControls2 + Gui + Widgets + WebSockets + Svg + Xml + LinguistTools + Test) add_library(ScreenPlayApp STATIC) @@ -309,21 +313,20 @@ qt_add_qml_module( target_link_libraries( ScreenPlayApp PUBLIC ScreenPlaySDK - LibArchive::LibArchive - ScreenPlayUtil - ScreenPlayUtilplugin - QArchive - Plausibleplugin - Threads::Threads - QCoro6::Qml - Qt6::Quick - Qt6::Gui - Qt6::Widgets - Qt6::Core - Qt6::WebSockets - Qt6::Svg - Qt6::QuickControls2 - Qt6::Xml) + LibArchive::LibArchive + ScreenPlayUtil + ScreenPlayUtilplugin + QArchive + Threads::Threads + QCoro6::Qml + Qt6::Quick + Qt6::Gui + Qt6::Widgets + Qt6::Core + Qt6::WebSockets + Qt6::Svg + Qt6::QuickControls2 + Qt6::Xml) if(${SCREENPLAY_STEAM}) target_link_libraries(ScreenPlayApp PUBLIC ScreenPlayWorkshopplugin ScreenPlayWorkshop) @@ -347,8 +350,8 @@ if(${SCREENPLAY_TESTS}) endif() if(WIN32 - OR UNIX - AND NOT APPLE) + OR UNIX + AND NOT APPLE) include(CopyRecursive) set(FONTS_OUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets/fonts) file(MAKE_DIRECTORY ${FONTS_OUT_DIR}) @@ -406,26 +409,26 @@ if(APPLE) set_target_properties( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME} - MACOSX_BUNDLE TRUE - MACOSX_RPATH TRUE - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - MACOSX_FRAMEWORK_IDENTIFIER app.screenplay - XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@loader_path/Libraries" - RESOURCE "${RESOURCE_FILES};${APP_ICON_MACOSX}" # Include the icon in the resources - XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE - XCODE_ATTRIBUTE_EXECUTABLE_NAME ${PROJECT_NAME}) + MACOSX_BUNDLE TRUE + MACOSX_RPATH TRUE + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + MACOSX_FRAMEWORK_IDENTIFIER app.screenplay + XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@loader_path/Libraries" + RESOURCE "${RESOURCE_FILES};${APP_ICON_MACOSX}" # Include the icon in the resources + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE + XCODE_ATTRIBUTE_EXECUTABLE_NAME ${PROJECT_NAME}) add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/ffmpeg/ffmpeg" - "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/ffmpeg/ffprobe" - "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") # fonts include(CopyRecursive) diff --git a/ScreenPlay/assets/icons/font-awsome/lock-solid.svg b/ScreenPlay/assets/icons/font-awsome/lock-solid.svg new file mode 100644 index 00000000..c805eee5 --- /dev/null +++ b/ScreenPlay/assets/icons/font-awsome/lock-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/font-awsome/rotate-right-solid.svg b/ScreenPlay/assets/icons/font-awsome/rotate-right-solid.svg new file mode 100644 index 00000000..aef72c84 --- /dev/null +++ b/ScreenPlay/assets/icons/font-awsome/rotate-right-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/images/285663_database_icon.svg b/ScreenPlay/assets/images/285663_database_icon.svg new file mode 100644 index 00000000..9d171a75 --- /dev/null +++ b/ScreenPlay/assets/images/285663_database_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/images/4180404_squircle_steam_icon.svg b/ScreenPlay/assets/images/4180404_squircle_steam_icon.svg new file mode 100644 index 00000000..bfe8fecb --- /dev/null +++ b/ScreenPlay/assets/images/4180404_squircle_steam_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/images/Intro.png b/ScreenPlay/assets/images/Intro.png index e4e51600..f8e971d6 100644 Binary files a/ScreenPlay/assets/images/Intro.png and b/ScreenPlay/assets/images/Intro.png differ diff --git a/ScreenPlay/assets/images/Intro_shine.png b/ScreenPlay/assets/images/Intro_shine.png index b40bbd06..f4f02386 100644 Binary files a/ScreenPlay/assets/images/Intro_shine.png and b/ScreenPlay/assets/images/Intro_shine.png differ diff --git a/ScreenPlay/assets/images/pro_version.png b/ScreenPlay/assets/images/pro_version.png new file mode 100644 index 00000000..f7263f80 Binary files /dev/null and b/ScreenPlay/assets/images/pro_version.png differ diff --git a/ScreenPlay/assets/images/rocket_3d.png b/ScreenPlay/assets/images/rocket_3d.png new file mode 100644 index 00000000..57e14707 Binary files /dev/null and b/ScreenPlay/assets/images/rocket_3d.png differ diff --git a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h index 89087934..a6b34164 100644 --- a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h +++ b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h @@ -31,14 +31,21 @@ public: explicit GlobalVariables(QObject* parent = nullptr); enum class Version { - OpenSource, + OpenSourceStandalone, OpenSourceSteam, - OpenSourcePlus, - OpenSourcePlusSteam + OpenSourceProStandalone, + OpenSourceProSteam, + OpenSourceUltraStandalone, + OpenSourceUltraSteam }; Q_ENUM(Version) + Q_INVOKABLE bool isBasicVersion() const; + Q_INVOKABLE bool isStandaloneVersion() const; + Q_INVOKABLE bool isSteamVersion() const; + Q_INVOKABLE bool isProVersion() const; + Q_INVOKABLE bool isUltraVersion() const; - Version version() const { return m_version; } + ScreenPlay::GlobalVariables::Version version() const { return m_version; } QUrl localStoragePath() const { return m_localStoragePath; } QUrl localSettingsPath() const { return m_localSettingsPath; } QUrl wallpaperExecutablePath() const { return m_wallpaperExecutablePath; } @@ -78,6 +85,6 @@ private: QUrl m_widgetExecutablePath; QUrl m_godotWallpaperExecutablePath; QUrl m_godotEditorExecutablePath; - Version m_version = Version::OpenSource; + Version m_version = Version::OpenSourceStandalone; }; } diff --git a/ScreenPlay/inc/public/ScreenPlay/settings.h b/ScreenPlay/inc/public/ScreenPlay/settings.h index e0888e37..3f9d98a7 100644 --- a/ScreenPlay/inc/public/ScreenPlay/settings.h +++ b/ScreenPlay/inc/public/ScreenPlay/settings.h @@ -53,8 +53,6 @@ class Settings : public QObject { Q_PROPERTY(bool autostart READ autostart WRITE setAutostart NOTIFY autostartChanged) Q_PROPERTY(bool highPriorityStart READ highPriorityStart WRITE setHighPriorityStart NOTIFY highPriorityStartChanged) Q_PROPERTY(bool checkWallpaperVisible READ checkWallpaperVisible WRITE setCheckWallpaperVisible NOTIFY checkWallpaperVisibleChanged) - Q_PROPERTY(bool offlineMode READ offlineMode WRITE setOfflineMode NOTIFY offlineModeChanged) - Q_PROPERTY(bool steamVersion READ steamVersion WRITE setSteamVersion NOTIFY steamVersionChanged) Q_PROPERTY(ScreenPlay::Video::FillMode videoFillMode READ videoFillMode WRITE setVideoFillMode NOTIFY videoFillModeChanged) Q_PROPERTY(ScreenPlay::Settings::DesktopEnvironment desktopEnvironment READ desktopEnvironment WRITE setDesktopEnvironment NOTIFY desktopEnvironmentChanged) @@ -111,8 +109,6 @@ public: }; Q_ENUM(Theme) - bool offlineMode() const { return m_offlineMode; } - bool getOfflineMode() const { return m_offlineMode; } bool autostart() const { return m_autostart; } bool highPriorityStart() const { return m_highPriorityStart; } QString decoder() const { return m_decoder; } @@ -123,7 +119,6 @@ public: ScreenPlay::Settings::Language language() const { return m_language; } QString font() const { return m_font; } ScreenPlay::Settings::Theme theme() const { return m_theme; } - bool steamVersion() const { return m_steamVersion; } ScreenPlay::Settings::DesktopEnvironment desktopEnvironment() const { return m_desktopEnvironment; } const QString& buildInfos() const { return m_buildInfos; } bool showDefaultContent() const { return m_showDefaultContent; } @@ -161,7 +156,6 @@ public slots: void setHighPriorityStart(bool highPriorityStart); void setLocalStoragePath(QUrl localStoragePath); void setDecoder(QString decoder); - void setOfflineMode(bool offlineMode); void setSilentStart(bool silentStart); void setAnonymousTelemetry(bool anonymousTelemetry); void setCheckWallpaperVisible(bool checkWallpaperVisible); @@ -169,7 +163,6 @@ public slots: void setLanguage(ScreenPlay::Settings::Language language); void setFont(QString font); void setTheme(ScreenPlay::Settings::Theme theme); - void setSteamVersion(bool steamVersion); void setDesktopEnvironment(ScreenPlay::Settings::DesktopEnvironment desktopEnvironment); void setBuildInfos(const QString& buildInfos); @@ -187,7 +180,6 @@ private: bool m_autostart { true }; bool m_highPriorityStart { false }; - bool m_offlineMode { true }; bool m_checkWallpaperVisible { false }; bool m_silentStart { false }; bool m_anonymousTelemetry { true }; @@ -199,7 +191,6 @@ private: ScreenPlay::Settings::DesktopEnvironment m_desktopEnvironment { DesktopEnvironment::Unknown }; QString m_font { "Roboto" }; QString m_decoder; - bool m_steamVersion { false }; QString m_buildInfos; }; } diff --git a/ScreenPlay/main.cpp b/ScreenPlay/main.cpp index b4851838..1d104c0b 100644 --- a/ScreenPlay/main.cpp +++ b/ScreenPlay/main.cpp @@ -21,7 +21,6 @@ Q_IMPORT_QML_PLUGIN(ScreenPlayWorkshopPlugin) #include Q_IMPORT_QML_PLUGIN(ScreenPlayAppPlugin) Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) -Q_IMPORT_QML_PLUGIN(PlausiblePlugin) int main(int argc, char* argv[]) { diff --git a/ScreenPlay/main.qml b/ScreenPlay/main.qml index 50981a2a..d6b99171 100644 --- a/ScreenPlay/main.qml +++ b/ScreenPlay/main.qml @@ -3,7 +3,6 @@ import QtQuick import QtQuick.Window import QtQuick.Controls import QtQuick.Controls.Material -import Plausible 1.0 import ScreenPlayApp 1.0 import QtCore as QCore @@ -15,7 +14,8 @@ ApplicationWindow { visible: false width: 1400 height: 810 - title: "ScreenPlay - v" + App.version() + + minimumHeight: 450 minimumWidth: 1050 Component.onCompleted: { @@ -24,14 +24,30 @@ ApplicationWindow { // and do _not_ access any other properties before we called init. App.init() + setTheme(App.settings.theme) if (!App.settings.silentStart) { App.showDockIcon(true) root.show() } - baseLoader.setSource("qrc:/qml/ScreenPlayApp/qml/Base.qml") + baseLoader.setSource("qrc:/qml/ScreenPlayApp/qml/MainApp.qml") + + const isSteamVersion = App.globalVariables.isSteamVersion() + let platform = "" + if (isSteamVersion) + platform = qsTr("Steam") + const isProVersion = App.globalVariables.isProVersion() + let featureLevel = "" + if (isProVersion) + featureLevel = qsTr("Pro") + const isUltraVersion = App.globalVariables.isUltraVersion() + if (isUltraVersion) + featureLevel = qsTr("Ultra") + + root.title = "ScreenPlay - v" + App.version() + " " + featureLevel + " " + platform } + Connections { target: App function onRequestExit(){ @@ -84,14 +100,6 @@ ApplicationWindow { exitDialog.open() } - Plausible { - id: plausible - screenSize: Qt.size(root.width, root.height) - domain: "app.screen-play.app" - debug: false - enabled: false - } - Loader { id: baseLoader asynchronous: true diff --git a/ScreenPlay/qml/Components/LineHandle.qml b/ScreenPlay/qml/Components/LineHandle.qml new file mode 100644 index 00000000..703b6517 --- /dev/null +++ b/ScreenPlay/qml/Components/LineHandle.qml @@ -0,0 +1,51 @@ +import QtQuick +import QtQuick.Controls + +Item { + id: root + property real lineWidth: 100 + property real linePosition: (root.x / lineWidth).toFixed(2) + property real lineMinimum: .5 + property real lineMaximum: .5 + property bool isLast: false + property alias dragHandler: dragHandler + + signal handleMoved(var handle) + signal removeHandle(var handle) + signal updateNeighbors(var handle) + width: 20 + height: width + Rectangle { + visible: !root.isLast + radius: width + color: dragHandler.active ? "orange" : "white" + anchors.fill: parent + } + + Text { + id: txt + text: root.linePosition + "-"+ (root.linePosition * root.lineWidth).toFixed(2) + "\n" + Math.floor( dragHandler.xAxis.minimum) + " - "+ Math.floor(dragHandler.xAxis.maximum) + color: "white" + visible: false + anchors{ + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: -20 + } + } + + DragHandler { + id: dragHandler + enabled: !root.isLast + target: root + yAxis.enabled: false + xAxis { + enabled: true + minimum: root.lineMinimum + maximum: root.lineMaximum + onActiveValueChanged: delta => { + root.handleMoved(root) + } + } + } +} diff --git a/ScreenPlay/qml/Components/LineIndicator.qml b/ScreenPlay/qml/Components/LineIndicator.qml new file mode 100644 index 00000000..8a1d3120 --- /dev/null +++ b/ScreenPlay/qml/Components/LineIndicator.qml @@ -0,0 +1,82 @@ +import QtQuick +import QtQuick.Controls + +Rectangle { + id: root + property int index: 0 + property bool selected: false + property bool isLast: false + property alias text: text.text + + signal remove(var index) + signal lineSelected(var index) + + border.width: root.selected ? 2 : 0 + border.color: "gold" + Behavior on color { + id: colorBehavior + ColorAnimation { + duration: 400 + } + } + Text { + id: text + color: "white" + text: root.index + anchors{ + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 10 + } + } + + Rectangle { + id: indicatorLineVertical + width: 5 + height: 30 + color: parent.color + border.width: root.selected ? 2 : 0 + border.color: "gold" + anchors{ + horizontalCenter: parent.horizontalCenter + top: parent.bottom + topMargin: 0 + } + } + + Rectangle { + id: background + width: 70 + height: 48 + radius: 5 + border.width: root.selected ? 2 : 0 + border.color: "gold" + color: parent.color + anchors{ + horizontalCenter: parent.horizontalCenter + top: indicatorLineVertical.bottom + topMargin: -1 + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onClicked:{ + root.lineSelected(root.index) + } + } + } + ToolButton { + text:"❌" + visible: !root.isLast + enabled: visible + onClicked: root.remove(root.index) + font.pointSize: 10 + + + anchors{ + left: background.right + bottom: background.top + margins: - 20 + } + } +} diff --git a/ScreenPlay/qml/Components/ScreenPlayProPopup.qml b/ScreenPlay/qml/Components/ScreenPlayProPopup.qml new file mode 100644 index 00000000..57bd4617 --- /dev/null +++ b/ScreenPlay/qml/Components/ScreenPlayProPopup.qml @@ -0,0 +1,314 @@ +import QtQuick +import QtQuick.Controls +import ScreenPlayUtil +import ScreenPlayApp + +Dialog { + id: dialog + width: 1200 + height: 700 + dim: true + anchors.centerIn: Overlay.overlay + modal: true + focus: true + + property alias message: messageText.text + Text { + id: messageText + color: Material.primaryTextColor + } + onOpened: wrapper.state = "in" + onClosed: wrapper.state = "out" + Rectangle { + id: wrapper + state: "out" + color: Material.backgroundColor + + anchors { + fill: parent + } + clip: true + + Image { + id: imgBg + source: "qrc:/qml/ScreenPlayApp/assets/images/Intro.png" + anchors.fill: parent + } + + Item { + height: parent.height + anchors { + top: parent.top + topMargin: parent.height * 0.5 + 50 + right: parent.right + left: parent.left + } + + Image { + id: imgShine + + source: "qrc:/qml/ScreenPlayApp/assets/images/Intro_shine.png" + height: 1753 + width: 1753 + opacity: 0 + anchors.centerIn: parent + + RotationAnimator { + target: imgShine + from: 0 + to: 360 + duration: 1000000 + running: true + loops: Animation.Infinite + } + } + } + + Image { + id: imgLogo + + source: "qrc:/qml/ScreenPlayApp/assets/images/pro_version.png" + width: 539 + height: 148 + sourceSize: Qt.size(width, height) + + anchors { + top: parent.top + topMargin: -200 + horizontalCenter: parent.horizontalCenter + } + } + + Text { + id: txtHeadline + + y: 80 + text: qsTr("✅ 3D Wallpaper\n✅ Wallpaper Timeline") + font.family: App.settings.font + font.capitalization: Font.Capitalize + wrapMode: Text.WordWrap + color: "white" + font.pointSize: 21 + horizontalAlignment: Text.AlignHCenter + + anchors { + right: parent.right + left: parent.left + top: parent.top + } + } + + Image { + id: imgPC + + source: "qrc:/qml/ScreenPlayApp/assets/images/Intro_PC.png" + width: 500 * 0.8 + height: 500 * 0.8 + sourceSize: Qt.size(width, height) + + anchors { + top: parent.top + topMargin: 50 + horizontalCenter: parent.horizontalCenter + } + } + + Button { + id: btnWorkshop + + text: qsTr("Get ScreenPlay Pro") + Material.background: Material.color(Material.Orange) + Material.foreground: "white" + font.pointSize: 16 + width: implicitWidth + 20 + height: implicitHeight + 10 + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_community.svg" + icon.width: 18 + icon.height: 18 + onClicked: { + if (App.globalVariables.isSteamVersion()) { + Qt.openUrlExternally("https://forum.screen-play.app/") + } else { + Qt.openUrlExternally("https://forum.screen-play.app/") + } + } + + anchors { + bottom: parent.bottom + bottomMargin: -100 + horizontalCenter: parent.horizontalCenter + } + } + + ToolButton { + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_close.svg" + icon.color: "transparent" + onClicked: dialog.close() + anchors { + top: parent.top + right: parent.right + } + } + + states: [ + State { + name: "out" + + PropertyChanges { + target: imgBg + opacity: 0 + } + + PropertyChanges { + target: imgShine + opacity: 0 + } + + PropertyChanges { + target: imgPC + opacity: 0 + anchors.topMargin: -500 + } + + PropertyChanges { + target: imgLogo + opacity: 1 + anchors.topMargin: -500 + } + + PropertyChanges { + target: txtHeadline + opacity: 0 + anchors.topMargin: 0 + } + + PropertyChanges { + target: btnWorkshop + anchors.bottomMargin: -100 + } + }, + State { + name: "in" + + PropertyChanges { + target: imgBg + opacity: 1 + } + + PropertyChanges { + target: imgShine + opacity: 0.5 + } + + PropertyChanges { + target: imgPC + opacity: 1 + anchors.topMargin: 250 + } + + PropertyChanges { + target: imgLogo + opacity: 1 + anchors.topMargin: 50 + } + + PropertyChanges { + target: txtHeadline + color: "#ffffff" + opacity: 1 + anchors.topMargin: 250 + } + + PropertyChanges { + target: btnWorkshop + anchors.bottomMargin: 50 + } + } + ] + transitions: [ + Transition { + from: "out" + to: "in" + reversible: true + + ParallelAnimation { + PropertyAnimation { + targets: imgBg + property: "opacity" + duration: 400 + } + + PropertyAnimation { + targets: imgShine + property: "opacity" + duration: 600 + } + } + + SequentialAnimation { + PauseAnimation { + duration: 200 + } + + PropertyAnimation { + targets: imgPC + property: "topMargin" + duration: 700 + easing.type: Easing.OutBack + } + + PropertyAnimation { + targets: imgPC + property: "opacity" + duration: 600 + easing.type: Easing.OutBack + } + } + + ParallelAnimation { + + PropertyAnimation { + targets: imgLogo + property: "opacity" + duration: 600 + easing.type: Easing.InOutExpo + } + + PropertyAnimation { + targets: imgLogo + property: "topMargin" + duration: 1000 + easing.type: Easing.InOutExpo + } + } + + SequentialAnimation { + PauseAnimation { + duration: 400 + } + + PropertyAnimation { + targets: txtHeadline + properties: "topMargin, opacity" + duration: 1100 + easing.type: Easing.InOutExpo + } + } + + SequentialAnimation { + PauseAnimation { + duration: 600 + } + + PropertyAnimation { + targets: btnWorkshop + properties: "bottomMargin" + duration: 1500 + easing.type: Easing.OutBack + } + + } + } + ] + } +} diff --git a/ScreenPlay/qml/Components/Section.qml b/ScreenPlay/qml/Components/Section.qml new file mode 100644 index 00000000..b9386b4d --- /dev/null +++ b/ScreenPlay/qml/Components/Section.qml @@ -0,0 +1,8 @@ +import QtQuick + +Item { + property int index: 0 + property real relativeLinePosition: 0 + property LineHandle lineHandle + property LineIndicator lineIndicator +} diff --git a/ScreenPlay/qml/Components/Timeline.qml b/ScreenPlay/qml/Components/Timeline.qml new file mode 100644 index 00000000..1c42fdd8 --- /dev/null +++ b/ScreenPlay/qml/Components/Timeline.qml @@ -0,0 +1,277 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Control { + id: root + height: 250 + implicitWidth: 800 + topPadding: 40 + leftPadding: 40 + rightPadding: 40 + contentItem: Item { + id: timeLine + + property var sectionsList: [] + property var lineColors: ["#E53935", "#D81B60", "#8E24AA", "#5E35B1", "#3949AB", "#1E88E5", "#00897B", "#43A047", "#C0CA33", "#FFB300", "#FB8C00", "#F4511E"] + onWidthChanged: timeLine.updatePositions() + + Component.onCompleted: { + const initialStopPositions = [1] + createAllSections(initialStopPositions) + } + + function createAllSections(initialStopPositions) { + for (let index in initialStopPositions) { + addSection(initialStopPositions[Number(index)]) + } + } + + function addSection(stopPosition) { + print("stopPosition", stopPosition) + //if (!isFloat(stopPosition)) + // console.error(typeof (stopPosition), stopPosition) + // Make sure to limit float precision + const fixedStopPosition = stopPosition + print("addSection at: ", fixedStopPosition) + if (stopPosition < 0 || fixedStopPosition > 1) { + console.error("Invalid position:", fixedStopPosition) + return + } + + let sectionComponent = Qt.createComponent("Section.qml") + if (sectionComponent.status === Component.Error) { + console.error(sectionComponent.errorString()) + return + } + let sectionObject = sectionComponent.createObject(timeLine, { + "relativeLinePosition": fixedStopPosition + }) + timeLine.sectionsList.push(sectionObject) + + timeLine.sectionsList.sort(function (a, b) { + return a.relativeLinePosition - b.relativeLinePosition + }) + const index = timeLine.sectionsList.indexOf(sectionObject) + console.log("Addsection:", index) + createSection(index, fixedStopPosition, sectionObject) + + updatePositions() + } + + function createSection(index, stopPosition, section) { + console.log("Adding at:", index, stopPosition) + //console.assert(isFloat(stopPosition)) + + let haComponent = Qt.createComponent("LineHandle.qml") + if (haComponent.status === Component.Error) { + console.assert(haComponent.errorString()) + return + } + + section.lineHandle = haComponent.createObject(handleWrapper) + section.lineHandle.lineWidth = timeLine.width + section.lineHandle.x = Math.round( + handleWrapper.width * timeLine.sectionsList[index].relativeLinePosition) + section.lineHandle.y = -section.lineHandle.height / 2 + // Will be set later + section.lineHandle.lineMinimum = timeLine.x + section.lineHandle.lineMaximum = timeLine.x + section.lineHandle.handleMoved.connect(timeLine.updatePositions) + + let liComponent = Qt.createComponent("LineIndicator.qml") + if (liComponent.status === Component.Error) { + console.assert(liComponent.errorString()) + return + } + + // Set color initially so we do not have a weird color animation at start + const lineIndicatorProperties = { + "color": getColorAtIndex(index) + } + section.lineIndicator = liComponent.createObject( + lineIndicatorWrapper, lineIndicatorProperties) + section.lineIndicator.height = lineIndicatorWrapper.height + section.lineIndicator.index = index + section.lineIndicator.color = getColorAtIndex(index) + section.lineIndicator.remove.connect(timeLine.removeSection) + section.lineIndicator.lineSelected.connect( + timeLine.lineIndicatorSelected) + } + + function lineIndicatorSelected(selectedIndicatorindex) { + for (var i = 0; i < timeLine.sectionsList.length; i++) { + if (i === selectedIndicatorindex) { + timeLine.sectionsList[i].lineIndicator.selected = true + continue + } + timeLine.sectionsList[i].lineIndicator.selected = false + } + } + + // We must update all indexes when removing/adding an element + function updateIndicatorIndexes() { + for (var i = 0; i < timeLine.sectionsList.length; i++) { + timeLine.sectionsList[i].index = i + timeLine.sectionsList[i].lineIndicator.index = i + } + } + + function removeSection(index) { + print(timeLine.stopPositionList) + print(timeLine.sectionList) + + const isLast = index === timeLine.sectionsList.length - 1 + if (isLast) + return + // ORDER is important here! First destory the object + // and then remove i f + let section = timeLine.sectionsList[index] + section.lineHandle.destroy() + section.lineIndicator.destroy() + section.destroy() + timeLine.sectionsList.splice(index, 1) + + updatePositions() + } + + function updatePositions() { + // Iterate through each handle in the 'sectionList' array + for (var i = 0; i < timeLine.sectionsList.length; i++) { + let handle = timeLine.sectionsList[i].lineHandle + + // Determine the minimum position for the current handle + let prevPos + if (i === 0) { + // If it's the first handle, its minimum is 0 + prevPos = 0 + } else { + // Otherwise, it's directly the position of the previous handle + prevPos = timeLine.sectionsList[i - 1].lineHandle.x + } + + // Determine the maximum position for the current handle + let nextPos + if (i === timeLine.sectionsList.length - 1) { + // If it's the last handle, its maximum is the width of the line + nextPos = timeLine.width + } else { + // Otherwise, it's directly the position of the next handle + nextPos = timeLine.sectionsList[i + 1].lineHandle.x + } + + // Set the determined minimum and maximum positions for the current handle + handle.lineMinimum = prevPos + handle.lineMaximum = nextPos + } + updateIndicatorIndexes() + updateIndicatorPositions() + updateLastHandle() + updateIndicatorColor() + } + + function getColorAtIndex(index) { + let i = index + // Start from the beginnging again + if (index >= timeLine.lineColors.length) { + i = index % timeLine.lineColors.length + } + return timeLine.lineColors[i] + } + + function updateIndicatorColor() { + for (var i = 0; i < timeLine.sectionsList.length; i++) { + let lineIndicator = timeLine.sectionsList[i].lineIndicator + lineIndicator.color = getColorAtIndex(i) + } + } + + function updateLastHandle() { + for (var i = 0; i < timeLine.sectionsList.length; i++) { + timeLine.sectionsList[i].lineHandle.isLast = i === timeLine.sectionsList.length - 1 + timeLine.sectionsList[i].lineIndicator.isLast = i + === timeLine.sectionsList.length - 1 + } + } + + function updateIndicatorPositions() { + for (var i = 0; i < timeLine.sectionsList.length; i++) { + const lineIndicator = timeLine.sectionsList[i].lineIndicator + print(i, lineIndicator.x, lineIndicator.width) + const handle = timeLine.sectionsList[i].lineHandle + lineIndicator.x = handle.dragHandler.xAxis.minimum + lineIndicator.width = (handle.linePosition * handle.lineWidth).toFixed( + 2) - lineIndicator.x + } + } + + // https://stackoverflow.com/a/3885844 + function isFloat(n) { + return n === +n && n !== (n | 0) + } + + Rectangle { + id: addHandleWrapper + color: Material.color(Material.Grey, Material.Shade900) + height: 30 + anchors { + left: parent.left + right: parent.right + top: parent.top + } + HoverHandler { + id: hoverHandler + enabled: true + } + + ToolButton { + text: "➕" + onClicked: { + const p = this.x / timeLine.width + const position = p.toFixed(2) + timeLine.addSection(position) + } + + x: hoverHandler.point.position.x - width * .5 + anchors.verticalCenter: parent.verticalCenter + } + } + Item { + id: lineIndicatorWrapper + height: 5 + anchors { + left: parent.left + right: parent.right + top: addHandleWrapper.bottom + } + } + Item { + id: handleWrapper + height: 5 + anchors { + left: parent.left + right: parent.right + top: addHandleWrapper.bottom + } + } + Item { + height: 18 + width: 5 + anchors { + right: parent.left + top: addHandleWrapper.bottom + topMargin: -9 + } + } + Rectangle { + height: 18 + width: 5 + color: "#757575" + anchors { + right: parent.right + top: addHandleWrapper.bottom + topMargin: -9 + } + } + } +} diff --git a/ScreenPlay/qml/TrayIcon.qml b/ScreenPlay/qml/Components/TrayIcon.qml similarity index 100% rename from ScreenPlay/qml/TrayIcon.qml rename to ScreenPlay/qml/Components/TrayIcon.qml diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index 3417ab0a..e94bf7b5 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -5,8 +5,8 @@ import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp - import ScreenPlayUtil +import "../Components" Rectangle { id: root @@ -36,13 +36,13 @@ Rectangle { id: loaderConnections function onWizardStarted() { - root.expanded = false; + root.expanded = false } function onWizardExited() { - root.expanded = true; - App.util.setNavigation("Installed"); - App.util.setNavigationActive(true); + root.expanded = true + App.util.setNavigation("Installed") + App.util.setNavigationActive(true) } ignoreUnknownSignals: true @@ -53,6 +53,7 @@ Rectangle { headline: qsTr("Tools Overview") source: "qrc:/qml/ScreenPlayApp/qml/Create/StartInfo.qml" category: "Home" + proFeature: false } ListElement { @@ -60,48 +61,56 @@ Rectangle { source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml" category: "Video Wallpaper" objectName: "videoImportConvert" + proFeature: false } ListElement { headline: qsTr("GIF Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/GifWallpaper.qml" category: "Video Wallpaper" + proFeature: false } ListElement { headline: qsTr("3D Engine Wallpaper (Godot 4.2)") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/GodotWallpaper.qml" category: "3D Engine & \nCode Wallpaper" + proFeature: true } ListElement { headline: qsTr("QML Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/QMLWallpaper.qml" category: "3D Engine & \nCode Wallpaper" + proFeature: false } ListElement { headline: qsTr("HTML5 Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/HTMLWallpaper.qml" category: "3D Engine & \nCode Wallpaper" + proFeature: false } ListElement { headline: qsTr("Website Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/WebsiteWallpaper.qml" category: "3D Engine & \nCode Wallpaper" + proFeature: false } ListElement { headline: qsTr("QML Widget") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/QMLWidget.qml" category: "Widgets" + proFeature: false } ListElement { headline: qsTr("HTML Widget") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/HTMLWidget.qml" category: "Widgets" + proFeature: false } } @@ -114,7 +123,7 @@ Rectangle { height: headline.contentHeight + 20 Text { - id:headline + id: headline font.pointSize: 18 color: Material.primaryTextColor text: section @@ -135,13 +144,32 @@ Rectangle { highlighted: ListView.isCurrentItem text: headline onClicked: { - listView.currentIndex = index; - const item = stackView.push(source); - loaderConnections.target = item; + if (proFeature && App.globalVariables.isBasicVersion()) + return screenPlayProView.open() + + listView.currentIndex = index + const item = stackView.push(source) + loaderConnections.target = item + } + ToolButton { + enabled: false + visible: proFeature && App.globalVariables.isBasicVersion() + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/lock-solid.svg" + icon.width: 10 + icon.height: 10 + icon.color: "gold" + anchors { + top: listItem.top + topMargin: -10 + right: listItem.right + rightMargin: -10 + } } } } - + ScreenPlayProPopup { + id: screenPlayProView + } layer.effect: ElevationEffect { elevation: 6 } diff --git a/ScreenPlay/qml/Installed/InstalledNavigation.qml b/ScreenPlay/qml/Installed/InstalledNavigation.qml index 3cd789bd..9ddb736d 100644 --- a/ScreenPlay/qml/Installed/InstalledNavigation.qml +++ b/ScreenPlay/qml/Installed/InstalledNavigation.qml @@ -125,7 +125,6 @@ Item { implicitWidth: height icon.width: height icon.height: height - icon.color: Material.iconColor } } diff --git a/ScreenPlay/qml/Installed/InstalledView.qml b/ScreenPlay/qml/Installed/InstalledView.qml index 0efdcf77..fa32a78c 100644 --- a/ScreenPlay/qml/Installed/InstalledView.qml +++ b/ScreenPlay/qml/Installed/InstalledView.qml @@ -7,8 +7,8 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import QtCore as QCore import ScreenPlayApp - import ScreenPlayUtil as Util +import "../Components" Item { id: root @@ -23,23 +23,21 @@ Item { function checkIsContentInstalled() { if (App.installedListModel.count === 0) { - loaderHelp.active = true; - gridView.footerItem.isVisible = true; - gridView.visible = false; - navWrapper.visible = false; + gridView.footerItem.isVisible = true + gridView.visible = false + navWrapper.visible = false } else { - loaderHelp.active = false; - gridView.footerItem.isVisible = false; - refresh = false; - gridView.contentY = -82; - gridView.visible = true; - navWrapper.visible = true; + gridView.footerItem.isVisible = false + refresh = false + gridView.contentY = -82 + gridView.visible = true + navWrapper.visible = true } } StackView.onActivated: { - navWrapper.state = "in"; - checkIsContentInstalled(); + navWrapper.state = "in" + checkIsContentInstalled() } Action { @@ -49,27 +47,24 @@ Item { Connections { function onInstalledLoadingFinished() { - checkIsContentInstalled(); + checkIsContentInstalled() } function onCountChanged(count) { if (count === 0) - checkIsContentInstalled(); + checkIsContentInstalled() } target: App.installedListModel } - Loader { - id: loaderHelp - active: false - anchors.fill: parent - source: "qrc:/qml/ScreenPlayApp/qml/Installed/InstalledWelcomeScreen.qml" + ScreenPlayProPopup { + id: screenPlayProView } Connections { function onSortChanged() { - gridView.positionViewAtBeginning(); + gridView.positionViewAtBeginning() } target: App.installedListFilter @@ -122,12 +117,12 @@ Item { } onContentYChanged: { if (contentY <= -180) - gridView.headerItem.isVisible = true; + gridView.headerItem.isVisible = true else - gridView.headerItem.isVisible = false; + gridView.headerItem.isVisible = false //Pull to refresh if (contentY <= -180 && !refresh && !isDragging) - App.installedListModel.reset(); + App.installedListModel.reset() } anchors { @@ -144,11 +139,11 @@ Item { opacity: 0 onIsVisibleChanged: { if (isVisible) { - txtHeader.color = Material.accent; - txtHeader.text = qsTr("Refreshing!"); + txtHeader.color = Material.accent + txtHeader.text = qsTr("Refreshing!") } else { - txtHeader.color = "gray"; - txtHeader.text = qsTr("Pull to refresh!"); + txtHeader.color = "gray" + txtHeader.text = qsTr("Pull to refresh!") } } @@ -156,7 +151,7 @@ Item { interval: 150 running: true onTriggered: { - animFadeIn.start(); + animFadeIn.start() } } @@ -200,7 +195,7 @@ Item { interval: 400 running: true onTriggered: { - animFadeInTxtFooter.start(); + animFadeInTxtFooter.start() } } @@ -228,25 +223,30 @@ Item { publishedFileID: m_publishedFileID itemIndex: index isScrolling: gridView.isScrolling + onOpenOpenLicensePopup: function () { + screenPlayProView.open() + } + onOpenContextMenu: function (position) { // Set the menu to the current item informations - contextMenu.publishedFileID = delegate.publishedFileID; - contextMenu.absoluteStoragePath = delegate.absoluteStoragePath; - contextMenu.fileName = delegate.customTitle; - contextMenu.type = delegate.type; - print(delegate.publishedFileID); + contextMenu.publishedFileID = delegate.publishedFileID + contextMenu.absoluteStoragePath = delegate.absoluteStoragePath + contextMenu.fileName = delegate.customTitle + contextMenu.type = delegate.type + print(delegate.publishedFileID) if (contextMenu.godotItem) - contextMenu.godotItem.destroy(); - const pos = delegate.mapToItem(root, position.x, position.y); + contextMenu.godotItem.destroy() + const pos = delegate.mapToItem(root, position.x, position.y) // Disable duplicate opening. The can happen if we // call popup when we are in the closing animtion. if (contextMenu.visible || contextMenu.opened) - return; + return if (delegate.type === Util.ContentTypes.InstalledType.GodotWallpaper) { - contextMenu.godotItem = editGodotWallpaperComp.createObject(); - contextMenu.insertItem(0, contextMenu.godotItem); + contextMenu.godotItem = editGodotWallpaperComp.createObject( + ) + contextMenu.insertItem(0, contextMenu.godotItem) } - contextMenu.popup(pos.x, pos.y); + contextMenu.popup(pos.x, pos.y) } } @@ -263,7 +263,9 @@ Item { enabled: contextMenu.type === Util.ContentTypes.InstalledType.GodotWallpaper icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_edit.svg" onClicked: { - App.util.openGodotEditor(contextMenu.absoluteStoragePath, App.globalVariables.godotEditorExecutablePath); + App.util.openGodotEditor( + contextMenu.absoluteStoragePath, + App.globalVariables.godotEditorExecutablePath) } } } @@ -284,7 +286,7 @@ Item { objectName: "openFolder" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_folder_open.svg" onClicked: { - App.util.openFolderInExplorer(contextMenu.absoluteStoragePath); + App.util.openFolderInExplorer(contextMenu.absoluteStoragePath) } } @@ -293,10 +295,12 @@ Item { objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_import_export_.svg" onClicked: { - exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath; - let urlFileName = QCore.StandardPaths.writableLocation(QCore.StandardPaths.DesktopLocation) + "/" + contextMenu.fileName + ".screenplay"; - exportFileDialog.currentFile = urlFileName; - exportFileDialog.open(); + exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath + let urlFileName = QCore.StandardPaths.writableLocation( + QCore.StandardPaths.DesktopLocation) + "/" + + contextMenu.fileName + ".screenplay" + exportFileDialog.currentFile = urlFileName + exportFileDialog.open() } } @@ -304,18 +308,21 @@ Item { text: enabled ? qsTr("Remove Item") : qsTr("Remove via Workshop") objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_delete.svg" - enabled: contextMenu.publishedFileID === 0 || !App.settings.steamVersion + enabled: contextMenu.publishedFileID === 0 + || !App.globalVariables.isSteamVersion() onClicked: { - deleteDialog.open(); + deleteDialog.open() } } MenuItem { text: qsTr("Open Workshop Page") - enabled: contextMenu.publishedFileID !== 0 && App.settings.steamVersion + enabled: contextMenu.publishedFileID !== 0 + && App.globalVariables.isSteamVersion() icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" onClicked: { - Qt.openUrlExternally("steam://url/CommunityFilePage/" + contextMenu.publishedFileID); + Qt.openUrlExternally( + "steam://url/CommunityFilePage/" + contextMenu.publishedFileID) } } } @@ -328,9 +335,11 @@ Item { modalSource: root.modalSource anchors.centerIn: Overlay.overlay onAccepted: { - root.sidebar.clear(); - if (!App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath)) { - console.error("Unable to uninstall item", contextMenu.absoluteStoragePath); + root.sidebar.clear() + if (!App.installedListModel.deinstallItemAt( + contextMenu.absoluteStoragePath)) { + console.error("Unable to uninstall item", + contextMenu.absoluteStoragePath) } } } @@ -340,7 +349,7 @@ Item { fileMode: FileDialog.SaveFile property string absoluteStoragePath onAccepted: { - exportFileProgressDialog.open(); + exportFileProgressDialog.open() } } @@ -353,10 +362,11 @@ Item { modalSource: root.modalSource closePolicy: Popup.NoAutoClose onOpened: { - const success = archive.exportProject(exportFileDialog.absoluteStoragePath, exportFileDialog.currentFile); + const success = archive.exportProject( + exportFileDialog.absoluteStoragePath, + exportFileDialog.currentFile) } - onClosed: exportProgressBar.value = 0 ColumnLayout { width: parent.width @@ -380,10 +390,10 @@ Item { id: exportConnections target: archive function onCompressionProgressChanged(file, proc, total, br, bt) { - exportProgressBar.value = (br * 100 / bt); + exportProgressBar.value = (br * 100 / bt) } function onCompressionFinished() { - exportFileProgressDialog.close(); + exportFileProgressDialog.close() } } } @@ -399,7 +409,7 @@ Item { } Util.Archive { - id:archive + id: archive } DropArea { @@ -407,29 +417,31 @@ Item { anchors.fill: parent property string filePath onEntered: function (drag) { - dropPopup.open(); + dropPopup.open() } onDropped: function (drop) { - dropPopup.close(); - dropArea.enabled = false; + dropPopup.close() + dropArea.enabled = false if (drop.urls.length > 1) { - importProjectErrorDialog.title = qsTr("We only support adding one item at once."); - importProjectErrorDialog.open(); - return; + importProjectErrorDialog.title = qsTr( + "We only support adding one item at once.") + importProjectErrorDialog.open() + return } - var file = ""; + var file = "" // Convert url to string - file = "" + drop.urls[0]; + file = "" + drop.urls[0] if (!file.endsWith('.screenplay')) { - importProjectErrorDialog.title = qsTr("File type not supported. We only support '.screenplay' files."); - importProjectErrorDialog.open(); - return; + importProjectErrorDialog.title = qsTr( + "File type not supported. We only support '.screenplay' files.") + importProjectErrorDialog.open() + return } - importDialog.open(); - dropArea.filePath = file; + importDialog.open() + dropArea.filePath = file } onExited: { - dropPopup.close(); + dropPopup.close() } Util.Dialog { @@ -450,9 +462,11 @@ Item { closePolicy: Popup.NoAutoClose onClosed: importProgressBar.value = 0 onOpened: { - const success = archive.importProject(dropArea.filePath, App.globalVariables.localStoragePath); - print("finished", success); - dropArea.filePath = ""; + const success = archive.importProject( + dropArea.filePath, + App.globalVariables.localStoragePath) + print("finished", success) + dropArea.filePath = "" } ColumnLayout { width: parent.width @@ -474,10 +488,10 @@ Item { id: importConnections target: archive function onExtractionProgressChanged(file, proc, total, br, bt) { - importProgressBar.value = (br * 100 / bt); + importProgressBar.value = (br * 100 / bt) } function onExtractionFinished() { - importDialog.close(); + importDialog.close() } } } @@ -493,8 +507,8 @@ Item { modal: true onOpened: fileDropAnimation.state = "fileDrop" onClosed: { - fileDropAnimation.state = ""; - dropArea.enabled = true; + fileDropAnimation.state = "" + dropArea.enabled = true } Util.FileDropAnimation { diff --git a/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml b/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml index b731ddc4..e51b0c87 100644 --- a/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml +++ b/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material import ScreenPlayApp - import ScreenPlayUtil Item { @@ -70,7 +69,7 @@ Item { id: txtHeadline y: 80 - text: App.settings.steamVersion ? qsTr("Get free Widgets and Wallpaper via the Steam Workshop") : qsTr("Get content via our forum") + text: App.globalVariables.isSteamVersion() ? qsTr("Get free Widgets and Wallpaper via the Steam Workshop") : qsTr("Get content via our forum") font.family: App.settings.font font.capitalization: Font.Capitalize wrapMode: Text.WordWrap @@ -104,7 +103,7 @@ Item { id: btnWorkshop text: { - if (App.settings.steamVersion) { + if (App.globalVariables.isSteamVersion()) { return qsTr("Browse the Steam Workshop"); } else { return qsTr("Open the ScreenPlay forum"); @@ -116,7 +115,7 @@ Item { width: implicitWidth + 20 height: implicitHeight + 10 icon.source: { - if (App.settings.steamVersion) { + if (App.globalVariables.isSteamVersion()) { return "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg"; } else { return "qrc:/qml/ScreenPlayApp/assets/icons/icon_community.svg"; @@ -125,7 +124,7 @@ Item { icon.width: 18 icon.height: 18 onClicked: { - if (App.settings.steamVersion) { + if (App.globalVariables.isSteamVersion()) { App.util.setNavigation("Workshop"); } else { Qt.openUrlExternally("https://forum.screen-play.app/"); diff --git a/ScreenPlay/qml/Installed/ScreenPlayItem.qml b/ScreenPlay/qml/Installed/ScreenPlayItem.qml index 03a94e55..3d78931f 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItem.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItem.qml @@ -3,7 +3,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls import QtQuick.Controls.Material import ScreenPlayApp - import ScreenPlayUtil as Util Item { @@ -12,15 +11,25 @@ Item { property string customTitle property string screenId property url absoluteStoragePath - property int type: ContentTypes.InstalledType.Unknown + property int type: Util.ContentTypes.InstalledType.Unknown // Must be var to make it work wit 64bit ints property var publishedFileID: 0 property int itemIndex property bool isScrolling: false property bool isNew: false property bool containsAudio: false + property int version: App.globalVariables.version + property bool hasLicense: { + if ((root.version === GlobalVariables.OpenSourceStandalone + || root.version === GlobalVariables.OpenSourceSteam) + && root.type === Util.ContentTypes.InstalledType.GodotWallpaper) { + return false + } + return true + } signal openContextMenu(point position) + signal openOpenLicensePopup width: 320 height: 180 @@ -140,7 +149,7 @@ Item { text: root.customTitle font.family: App.settings.font font.pointSize: 16 - visible: !screenPlayItemImage.visible + visible: !screenPlayItemImage.visible && root.hasLicense color: Material.primaryTextColor anchors.centerIn: parent horizontalAlignment: Text.AlignHCenter @@ -148,7 +157,7 @@ Item { ScreenPlayItemImage { id: screenPlayItemImage - + opacity: root.hasLicense ? 1 : 0.3 anchors.fill: parent enabled: visible visible: m_preview !== "" || m_previewGIF !== "" @@ -219,6 +228,20 @@ Item { anchors.centerIn: parent } } + + ToolButton { + enabled: false + visible: !root.hasLicense + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/lock-solid.svg" + icon.height: 14 + icon.width: 11 + icon.color: "gold" + opacity: .5 + anchors { + top: parent.top + right: parent.right + } + } } OpacityMask { @@ -232,6 +255,8 @@ Item { cursorShape: Qt.PointingHandCursor acceptedButtons: Qt.LeftButton | Qt.RightButton onEntered: { + if (!root.hasLicense) + return root.state = "hover" screenPlayItemImage.state = "hover" screenPlayItemImage.enter() @@ -242,6 +267,11 @@ Item { screenPlayItemImage.exit() } onClicked: function (mouse) { + if (!root.hasLicense) { + root.openOpenLicensePopup() + return + } + if (mouse.button === Qt.LeftButton) App.util.setSidebarItem(root.screenId, root.type) else if (mouse.button === Qt.RightButton) @@ -250,7 +280,6 @@ Item { } } } - transitions: [ Transition { from: "" diff --git a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml index 213afce4..e1982346 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml @@ -1,4 +1,5 @@ import QtQuick +import ScreenPlayUtil as Util Item { id: root @@ -6,7 +7,7 @@ Item { property string absoluteStoragePath property string sourceImage property string sourceImageGIF - property var type: ContentTypes.InstalledType.Unknown + property var type: Util.ContentTypes.InstalledType.Unknown function enter() { if (root.sourceImageGIF != "") diff --git a/ScreenPlay/qml/Installed/Sidebar.qml b/ScreenPlay/qml/Installed/Sidebar.qml index 97bd3ceb..58a16771 100644 --- a/ScreenPlay/qml/Installed/Sidebar.qml +++ b/ScreenPlay/qml/Installed/Sidebar.qml @@ -365,6 +365,14 @@ 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" + return + } + } + + let activeMonitors = monitorSelection.getActiveMonitors( ) // TODO Alert user to choose a monitor diff --git a/ScreenPlay/qml/Base.qml b/ScreenPlay/qml/MainApp.qml similarity index 93% rename from ScreenPlay/qml/Base.qml rename to ScreenPlay/qml/MainApp.qml index 5e2de724..6e12018b 100644 --- a/ScreenPlay/qml/Base.qml +++ b/ScreenPlay/qml/MainApp.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import ScreenPlayUtil as Util import ScreenPlayApp 1.0 - import "Monitors" as Monitors import "Installed" as Installed import "Navigation" as Navigation @@ -96,15 +95,6 @@ Item { App.showDockIcon(true); root.show(); } - - function onActiveWidgetsCounterChanged() { - plausible.pageView("widget/count/" + App.screenPlayManager.activeWidgetsCounter); - } - - function onActiveWallpaperCounterChanged() { - plausible.pageView("wallpaper/count/" + App.screenPlayManager.activeWallpaperCounter); - } - target: App.screenPlayManager } diff --git a/ScreenPlay/qml/Monitors/MonitorsView.qml b/ScreenPlay/qml/Monitors/MonitorsView.qml index 7f0e4b72..2ea74621 100644 --- a/ScreenPlay/qml/Monitors/MonitorsView.qml +++ b/ScreenPlay/qml/Monitors/MonitorsView.qml @@ -5,8 +5,8 @@ import QtQuick.Controls.Material import QtQuick.Layouts import QtQuick.Controls.Material.impl import ScreenPlayApp - import ScreenPlayUtil as Util +import "../Components" Util.Popup { id: root @@ -14,249 +14,11 @@ Util.Popup { property string activeMonitorName: "" property int activeMonitorIndex - width: 1000 - height: 500 + width: 1366 + height: 768 onOpened: { - monitorSelection.selectMonitorAt(0); + monitorSelection.selectMonitorAt(0) } - - Connections { - function onRequestToggleWallpaperConfiguration() { - root.open(); - } - - target: App.util - } - - Item { - id: monitorsSettingsWrapper - - clip: true - - anchors { - fill: parent - margins: 10 - } - - Item { - id: itmLeftWrapper - - width: parent.width * 0.5 - - anchors { - top: parent.top - left: parent.left - bottom: parent.bottom - margins: 10 - } - - Text { - id: txtHeadline - - text: qsTr("Wallpaper Configuration") - font.pointSize: 21 - color: Material.primaryTextColor - font.family: App.settings.font - font.weight: Font.Light - width: 400 - - anchors { - top: parent.top - topMargin: 10 - left: parent.left - leftMargin: 20 - } - } - - MonitorSelection { - id: monitorSelection - - bgRadius: 3 - height: 200 - width: parent.width * 0.9 - multipleMonitorsSelectable: false - monitorWithoutContentSelectable: false - availableWidth: width - 20 - availableHeight: 150 - onRequestProjectSettings: function (index, installedType, appID) { - if (installedType === Util.ContentTypes.InstalledType.VideoWallpaper) { - videoControlWrapper.state = "visible"; - customPropertiesGridView.visible = false; - const wallpaper = App.screenPlayManager.getWallpaperByAppID(appID); - videoControlWrapper.wallpaper = wallpaper; - } else { - videoControlWrapper.state = "hidden"; - customPropertiesGridView.visible = true; - if (!App.screenPlayManager.requestProjectSettingsAtMonitorIndex(index)) { - console.warn("Unable to get requested settings from index: ", index); - } - } - activeMonitorIndex = index; - } - - anchors { - top: txtHeadline.bottom - topMargin: 20 - left: parent.left - leftMargin: 20 - } - - Connections { - function onProjectSettingsListModelResult(listModel) { - customPropertiesGridView.projectSettingsListmodelRef = listModel; - } - - target: App.screenPlayManager - } - } - - ColumnLayout { - spacing: 5 - - anchors { - top: monitorSelection.bottom - right: parent.right - left: parent.left - margins: 20 - } - - Button { - id: btnRemoveSelectedWallpaper - Material.background: Material.accent - highlighted: true - text: qsTr("Remove selected") - font.family: App.settings.font - enabled: monitorSelection.activeMonitors.length == 1 && App.screenPlayManager.activeWallpaperCounter > 0 - onClicked: { - if (!App.screenPlayManager.removeWallpaperAt(monitorSelection.activeMonitors[0])) - print("Unable to close singel wallpaper"); - } - } - - Button { - id: btnRemoveAllWallpape - - text: qsTr("Remove all ") + App.screenPlayManager.activeWallpaperCounter + " " + qsTr("Wallpapers") - Material.background: Material.accent - highlighted: true - font.family: App.settings.font - enabled: App.screenPlayManager.activeWallpaperCounter > 0 - onClicked: { - if (!App.screenPlayManager.removeAllWallpapers(true)) - print("Unable to close all wallpaper!"); - root.close(); - } - } - - Button { - id: btnRemoveAllWidgets - - text: qsTr("Remove all ") + App.screenPlayManager.activeWidgetsCounter + " " + qsTr("Widgets") - Material.background: Material.accent - Material.foreground: Material.primaryTextColor - highlighted: true - font.family: App.settings.font - enabled: App.screenPlayManager.activeWidgetsCounter > 0 - onClicked: { - if (!App.screenPlayManager.removeAllWidgets()) - print("Unable to close all widgets!"); - root.close(); - } - } - } - } - - Rectangle { - color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) - radius: 3 - clip: true - - anchors { - top: parent.top - topMargin: 75 - right: parent.right - rightMargin: 40 - bottom: parent.bottom - bottomMargin: 30 - left: itmLeftWrapper.right - } - - DefaultVideoControls { - id: videoControlWrapper - - activeMonitorIndex: root.activeMonitorIndex - state: "hidden" - anchors.fill: parent - anchors.margins: 10 - } - - GridView { - id: customPropertiesGridView - - property var projectSettingsListmodelRef - - boundsBehavior: Flickable.DragOverBounds - maximumFlickVelocity: 7000 - flickDeceleration: 5000 - cellWidth: 340 - cellHeight: 50 - cacheBuffer: 10000 - clip: true - anchors.fill: parent - anchors.margins: 10 - visible: false - model: customPropertiesGridView.projectSettingsListmodelRef - - delegate: MonitorsProjectSettingItem { - id: delegate - - width: parent.width - 40 - selectedMonitor: activeMonitorIndex - name: m_name - isHeadline: m_isHeadline - value: m_value - itemIndex: index - projectSettingsListmodelRef: customPropertiesGridView.projectSettingsListmodelRef - } - - ScrollBar.vertical: ScrollBar { - snapMode: ScrollBar.SnapOnRelease - policy: ScrollBar.AlwaysOn - } - } - } - - ToolButton { - width: 32 - height: width - icon.width: 16 - icon.height: 16 - icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/close.svg" - icon.color: Material.iconColor - onClicked: root.close() - - anchors { - top: parent.top - right: parent.right - } - } - - SaveNotification { - id: saveNotification - - width: parent.width - 40 - - Connections { - function onProfilesSaved() { - if (root.opened) - saveNotification.open(); - } - - target: App.screenPlayManager - } - } - } - background: Rectangle { anchors.fill: parent radius: 4 @@ -267,4 +29,290 @@ Util.Popup { elevation: 6 } } + Connections { + function onRequestToggleWallpaperConfiguration() { + root.open() + } + + target: App.util + } + ColumnLayout { + + anchors { + fill: parent + margins: 10 + } + + Rectangle { + id: timelineWrapper + color: Material.theme === Material.Light ? Material.background : "#242424" + border.color: "#44FFD700" + border.width: 1 + radius: 3 + Layout.fillWidth: true + Layout.preferredHeight: 280 + + ColumnLayout { + spacing: 20 + + anchors { + fill: parent + margins: 40 + } + + Text { + text: qsTr("Timeline") + font.pointSize: 21 + color: Material.primaryTextColor + font.family: App.settings.font + font.weight: Font.Light + width: 400 + Layout.fillWidth: true + Layout.preferredHeight: 30 + } + + Timeline { + Layout.fillWidth: true + Layout.fillHeight: true + + } + } + } + + Item { + id: monitorsSettingsWrapper + + clip: true + Layout.fillWidth: true + Layout.fillHeight: true + + Item { + id: itmLeftWrapper + + width: parent.width * 0.5 + + anchors { + top: parent.top + left: parent.left + bottom: parent.bottom + margins: 10 + } + + Text { + id: txtHeadline + + text: qsTr("Wallpaper Configuration") + font.pointSize: 21 + color: Material.primaryTextColor + font.family: App.settings.font + font.weight: Font.Light + width: 400 + + anchors { + top: parent.top + topMargin: 10 + left: parent.left + leftMargin: 20 + } + } + + MonitorSelection { + id: monitorSelection + + bgRadius: 3 + height: 200 + width: parent.width * 0.9 + multipleMonitorsSelectable: false + monitorWithoutContentSelectable: false + availableWidth: width - 20 + availableHeight: 150 + onRequestProjectSettings: function (index, installedType, appID) { + if (installedType === Util.ContentTypes.InstalledType.VideoWallpaper) { + videoControlWrapper.state = "visible" + customPropertiesGridView.visible = false + const wallpaper = App.screenPlayManager.getWallpaperByAppID( + appID) + videoControlWrapper.wallpaper = wallpaper + } else { + videoControlWrapper.state = "hidden" + customPropertiesGridView.visible = true + if (!App.screenPlayManager.requestProjectSettingsAtMonitorIndex( + index)) { + console.warn("Unable to get requested settings from index: ", + index) + } + } + activeMonitorIndex = index + } + + anchors { + top: txtHeadline.bottom + topMargin: 20 + left: parent.left + leftMargin: 20 + } + + Connections { + function onProjectSettingsListModelResult(listModel) { + customPropertiesGridView.projectSettingsListmodelRef = listModel + } + + target: App.screenPlayManager + } + } + + ColumnLayout { + spacing: 5 + + anchors { + top: monitorSelection.bottom + right: parent.right + left: parent.left + margins: 20 + } + + Button { + id: btnRemoveSelectedWallpaper + Material.background: Material.accent + highlighted: true + text: qsTr("Remove selected") + font.family: App.settings.font + enabled: monitorSelection.activeMonitors.length == 1 + && App.screenPlayManager.activeWallpaperCounter > 0 + onClicked: { + if (!App.screenPlayManager.removeWallpaperAt( + monitorSelection.activeMonitors[0])) + print("Unable to close singel wallpaper") + } + } + + Button { + id: btnRemoveAllWallpape + + text: qsTr("Remove all ") + + App.screenPlayManager.activeWallpaperCounter + " " + qsTr( + "Wallpapers") + Material.background: Material.accent + highlighted: true + font.family: App.settings.font + enabled: App.screenPlayManager.activeWallpaperCounter > 0 + onClicked: { + if (!App.screenPlayManager.removeAllWallpapers( + true)) + print("Unable to close all wallpaper!") + root.close() + } + } + + Button { + id: btnRemoveAllWidgets + + text: qsTr("Remove all ") + + App.screenPlayManager.activeWidgetsCounter + " " + qsTr( + "Widgets") + Material.background: Material.accent + Material.foreground: Material.primaryTextColor + highlighted: true + font.family: App.settings.font + enabled: App.screenPlayManager.activeWidgetsCounter > 0 + onClicked: { + if (!App.screenPlayManager.removeAllWidgets()) + print("Unable to close all widgets!") + root.close() + } + } + } + } + + Rectangle { + color: Material.theme === Material.Light ? Material.background : Qt.darker( + Material.background) + radius: 3 + clip: true + + anchors { + top: parent.top + topMargin: 75 + right: parent.right + rightMargin: 40 + bottom: parent.bottom + bottomMargin: 30 + left: itmLeftWrapper.right + } + + DefaultVideoControls { + id: videoControlWrapper + + activeMonitorIndex: root.activeMonitorIndex + state: "hidden" + anchors.fill: parent + anchors.margins: 10 + } + + GridView { + id: customPropertiesGridView + + property var projectSettingsListmodelRef + + boundsBehavior: Flickable.DragOverBounds + maximumFlickVelocity: 7000 + flickDeceleration: 5000 + cellWidth: 340 + cellHeight: 50 + cacheBuffer: 10000 + clip: true + anchors.fill: parent + anchors.margins: 10 + visible: false + model: customPropertiesGridView.projectSettingsListmodelRef + + delegate: MonitorsProjectSettingItem { + id: delegate + + width: parent.width - 40 + selectedMonitor: activeMonitorIndex + name: m_name + isHeadline: m_isHeadline + value: m_value + itemIndex: index + projectSettingsListmodelRef: customPropertiesGridView.projectSettingsListmodelRef + } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + policy: ScrollBar.AlwaysOn + } + } + } + + SaveNotification { + id: saveNotification + + width: parent.width - 40 + + Connections { + function onProfilesSaved() { + if (root.opened) + saveNotification.open() + } + + target: App.screenPlayManager + } + } + } + } + ToolButton { + width: 32 + height: width + icon.width: 16 + icon.height: 16 + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/close.svg" + icon.color: Material.iconColor + onClicked: root.close() + + anchors { + top: parent.top + right: parent.right + } + } } diff --git a/ScreenPlay/qml/Monitors/WallpaperTimeline.qml b/ScreenPlay/qml/Monitors/WallpaperTimeline.qml new file mode 100644 index 00000000..90b2015f --- /dev/null +++ b/ScreenPlay/qml/Monitors/WallpaperTimeline.qml @@ -0,0 +1,74 @@ +import QtQuick +import QtQuick.Controls + +Pane { + id: root + + Component.onCompleted: { + // Add the second handle at 100% after the component is fully created + sliderHandles.append({"position": sliderLine.width}); + } + + ListModel { + id: sliderHandles + ListElement { position: 0 } // Initial handle at 0% + } + + Rectangle { + id: sliderLine + width: parent.width + height: 10 + anchors.centerIn: parent + color: "grey" + + MouseArea { + anchors.fill: parent + onClicked: { + var newHandlePosition = Math.max(0, Math.min(mouseX, sliderLine.width)); + sliderHandles.append({"position": newHandlePosition}); + // Sort handles after adding a new one + sortHandles(); + } + } + } + + Repeater { + model: sliderHandles + delegate: Rectangle { + id: handle + width: 10 + height: 20 + x: model.position - width / 2 + y: sliderLine.y - height / 2 + sliderLine.height / 2 + color: "blue" + + MouseArea { + id: dragArea + anchors.fill: parent + drag.target: handle + drag.axis: Drag.XAxis + drag.minimumX: getMinimumX(index) + drag.maximumX: getMaximumX(index) + + onReleased: { + sliderHandles.set(index, {"position": handle.x + width / 2}); + } + } + } + } + + function getMinimumX(index) { + return index > 0 ? sliderHandles.get(index - 1).position : 0; + } + + function getMaximumX(index) { + return index < sliderHandles.count - 1 ? sliderHandles.get(index + 1).position - handle.width : sliderLine.width; + } + + function sortHandles() { + sliderHandles.sort(function(a, b) { + return a.position - b.position; + }); + } + +} diff --git a/ScreenPlay/qml/Navigation/Navigation.qml b/ScreenPlay/qml/Navigation/Navigation.qml index ceafd615..a1efd5b5 100644 --- a/ScreenPlay/qml/Navigation/Navigation.qml +++ b/ScreenPlay/qml/Navigation/Navigation.qml @@ -6,8 +6,8 @@ import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp - import ScreenPlayUtil +import "../Components" Rectangle { id: root @@ -22,29 +22,29 @@ Rectangle { signal changePage(string name) function setActive(active) { - navActive = active; + navActive = active if (active) - root.state = "enabled"; + root.state = "enabled" else - root.state = "disabled"; + root.state = "disabled" } function setNavigation(name) { for (var i = 0; i < navArray.length; i++) { if (navArray[i].objectName === name) { - navArray[i].state = "active"; - root.currentNavigationName = name; - tabBar.currentIndex = navArray[i].index; + navArray[i].state = "active" + root.currentNavigationName = name + tabBar.currentIndex = navArray[i].index } else { - navArray[i].state = "inactive"; + navArray[i].state = "inactive" } } } function onPageChanged(name) { if (!navActive) - return; - root.changePage(name); - setNavigation(name); + return + root.changePage(name) + setNavigation(name) } implicitWidth: 1366 @@ -58,11 +58,11 @@ Rectangle { Connections { function onRequestNavigationActive(isActive) { - setActive(isActive); + setActive(isActive) } function onRequestNavigation(nav) { - onPageChanged(nav); + onPageChanged(nav) } target: App.util @@ -90,19 +90,19 @@ Rectangle { objectName: "Create" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_plus.svg" onClicked: { - root.onPageChanged("Create"); + root.onPageChanged("Create") } } CustomTabButton { id: navWorkshop index: 1 - enabled: App.settings.steamVersion + enabled: App.globalVariables.isSteamVersion() text: qsTr("Workshop") objectName: "Workshop" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" onClicked: { - root.onPageChanged("Workshop"); + root.onPageChanged("Workshop") } } @@ -113,7 +113,7 @@ Rectangle { objectName: "Installed" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_installed.svg" onClicked: { - root.onPageChanged("Installed"); + root.onPageChanged("Installed") } } @@ -124,7 +124,7 @@ Rectangle { objectName: "Community" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_community.svg" onClicked: { - root.onPageChanged("Community"); + root.onPageChanged("Community") } } @@ -135,7 +135,7 @@ Rectangle { objectName: "Settings" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_settings.svg" onClicked: { - root.onPageChanged("Settings"); + root.onPageChanged("Settings") } } } @@ -147,37 +147,74 @@ Rectangle { height: parent.height width: implicitWidth property int index: 0 - background: Item { - } + background: Item {} font.capitalization: Font.MixedCase } + Rectangle { + id: premiumBackground + anchors.centerIn: premium + width: premium.width + height: premium.height + color: Material.theme === Material.Light ? Material.background : "#242424" + border.color: "#44FFD700" + border.width: 1 + radius: 3 + } + + SwipeView { + id:premium + clip: true + anchors { + top: parent.top + topMargin: 5 + right: quickActionRow.left + rightMargin: 20 + bottom: parent.bottom + bottomMargin: 5 + } + interactive: false + + currentIndex: { + if (App.globalVariables.isBasicVersion()) + return 0 + if (App.globalVariables.isProVersion()) + return 1 + if (App.globalVariables.isUltraVersion()) + return 2 + return 0 + } + + ScreenPlayProPopup { + id:screenPlayProView + } + + ToolButton { + icon.source: "qrc:/qml/ScreenPlayApp/assets/images/rocket_3d.png" + icon.color: "transparent" + text: qsTr("Get ScreenPlay Pro 3D Wallpaper and Timelines!") + onClicked: screenPlayProView.open() + } + ToolButton { + text: qsTr("ScreenPlay Pro Active") + + } + ToolButton { + text: qsTr("ScreenPlay ULTRA Active") + } + } + Rectangle { id: quickActionRowBackground anchors.centerIn: quickActionRow width: quickActionRow.width + 5 height: quickActionRow.height - 16 color: Material.theme === Material.Light ? Material.background : "#242424" - border.color: Material.theme === Material.Light ? Material.iconDisabledColor : Qt.darker(Material.background) + border.color: Material.theme === Material.Light ? Material.iconDisabledColor : Qt.darker( + Material.background) border.width: 1 radius: 3 } - - RowLayout { - anchors { - top: parent.top - right: quickActionRow.left - rightMargin: 20 - bottom: parent.bottom - } - - ToolButton { - icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/font-awsome/patreon-brands.svg" - text: qsTr("Support me on Patreon!") - onClicked: Qt.openUrlExternally("https://www.patreon.com/ScreenPlayApp") - } - } - RowLayout { id: quickActionRow anchors { @@ -187,12 +224,13 @@ Rectangle { bottom: parent.bottom } - property bool contentActive: App.screenPlayManager.activeWallpaperCounter > 0 || App.screenPlayManager.activeWidgetsCounter > 0 + property bool contentActive: App.screenPlayManager.activeWallpaperCounter > 0 + || App.screenPlayManager.activeWidgetsCounter > 0 onContentActiveChanged: { if (!contentActive) { - miMuteAll.soundEnabled = true; - miStopAll.isPlaying = true; + miMuteAll.soundEnabled = true + miStopAll.isPlaying = true } } @@ -208,11 +246,12 @@ Rectangle { property bool soundEnabled: true onSoundEnabledChanged: { if (miMuteAll.soundEnabled) { - miMuteAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume.svg"; - App.screenPlayManager.setAllWallpaperValue("muted", "false"); + miMuteAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume.svg" + App.screenPlayManager.setAllWallpaperValue("muted", "false") } else { - miMuteAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume_mute.svg"; - App.screenPlayManager.setAllWallpaperValue("muted", "true"); + miMuteAll.icon.source + = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume_mute.svg" + App.screenPlayManager.setAllWallpaperValue("muted", "true") } } @@ -231,18 +270,19 @@ Rectangle { property bool isPlaying: true onIsPlayingChanged: { if (miStopAll.isPlaying) { - miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_pause.svg"; - App.screenPlayManager.setAllWallpaperValue("isPlaying", "true"); + miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_pause.svg" + App.screenPlayManager.setAllWallpaperValue("isPlaying", + "true") } else { - miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_play.svg"; - App.screenPlayManager.setAllWallpaperValue("isPlaying", "false"); + miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_play.svg" + App.screenPlayManager.setAllWallpaperValue("isPlaying", + "false") } } hoverEnabled: true ToolTip.text: qsTr("Pause/Play all Wallpaper") ToolTip.visible: hovered } - ToolButton { id: miCloseAll enabled: quickActionRow.contentActive @@ -251,19 +291,19 @@ Rectangle { icon.width: root.iconWidth icon.height: root.iconHeight onClicked: { - App.screenPlayManager.removeAllWallpapers(); - App.screenPlayManager.removeAllWidgets(); - miStopAll.isPlaying = true; - miMuteAll.soundEnabled = true; + App.screenPlayManager.removeAllWallpapers(true) + App.screenPlayManager.removeAllWidgets(true) + miStopAll.isPlaying = true + miMuteAll.soundEnabled = true } hoverEnabled: true ToolTip.text: qsTr("Close All Content") ToolTip.visible: hovered } - ToolButton { id: miConfig + enabled: quickActionRow.contentActive Layout.alignment: Qt.AlignVCenter icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_video_settings.svg" icon.width: root.iconWidth diff --git a/ScreenPlay/qml/Workshop/WorkshopView.qml b/ScreenPlay/qml/Workshop/WorkshopView.qml index 511c9b00..fe899a6d 100644 --- a/ScreenPlay/qml/Workshop/WorkshopView.qml +++ b/ScreenPlay/qml/Workshop/WorkshopView.qml @@ -3,8 +3,7 @@ import QtQuick.Controls import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts - -import ScreenPlayWorkshop +import ScreenPlayApp Item { id: root @@ -12,7 +11,7 @@ Item { property Item modalSource Component.onCompleted: { - if (App.settings.steamVersion) { + if (App.globalVariables.isSteamVersion()) { workshopLoader.setSource("qrc:/qml/ScreenPlayWorkshop/qml/SteamWorkshop.qml", { "modalSource": modalSource }); diff --git a/ScreenPlay/src/globalvariables.cpp b/ScreenPlay/src/globalvariables.cpp index d1da46b0..3dc45845 100644 --- a/ScreenPlay/src/globalvariables.cpp +++ b/ScreenPlay/src/globalvariables.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/globalvariables.h" +#include "ScreenPlay/CMakeVariables.h" namespace ScreenPlay { @@ -16,9 +17,47 @@ namespace ScreenPlay { GlobalVariables::GlobalVariables(QObject* parent) : QObject(parent) { + if (SCREENPLAY_STEAM_VERSION) { + setVersion(GlobalVariables::Version::OpenSourceSteam); + } else { + setVersion(GlobalVariables::Version::OpenSourceStandalone); + } + setVersion(GlobalVariables::Version::OpenSourceUltraSteam); setLocalSettingsPath(QUrl { QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) }); } +bool GlobalVariables::isBasicVersion() const +{ + return (m_version == Version::OpenSourceSteam + || m_version == Version::OpenSourceStandalone); +} + +bool GlobalVariables::isSteamVersion() const +{ + return (m_version == Version::OpenSourceSteam + || m_version == Version::OpenSourceProSteam + || m_version == Version::OpenSourceUltraSteam); +} + +bool GlobalVariables::isStandaloneVersion() const +{ + return (m_version == Version::OpenSourceStandalone + || m_version == Version::OpenSourceProStandalone + || m_version == Version::OpenSourceUltraStandalone); +} + +bool GlobalVariables::isProVersion() const +{ + return (m_version == Version::OpenSourceProStandalone + || m_version == Version::OpenSourceProSteam); +} + +bool GlobalVariables::isUltraVersion() const +{ + return (m_version == Version::OpenSourceUltraStandalone + || m_version == Version::OpenSourceUltraSteam); +} + void GlobalVariables::setLocalStoragePath(QUrl localStoragePath) { if (m_localStoragePath == localStoragePath) diff --git a/ScreenPlay/src/settings.cpp b/ScreenPlay/src/settings.cpp index 921c5924..079939b7 100644 --- a/ScreenPlay/src/settings.cpp +++ b/ScreenPlay/src/settings.cpp @@ -55,8 +55,6 @@ Settings::Settings(const std::shared_ptr& globalVariables, const QString isSteamVersion = QString("Is steam version: %1").arg((SCREENPLAY_STEAM_VERSION ? QString("✅ Yes") : QString("❌ No"))); setBuildInfos(qtVersion + buildType + buildDate + commitHash + isDeployVersion + isSteamVersion); - setSteamVersion(SCREENPLAY_STEAM_VERSION); - #ifdef Q_OS_WIN setDesktopEnvironment(DesktopEnvironment::Windows); #endif @@ -212,7 +210,9 @@ void Settings::initInstalledPath() const QString contentPath = m_qSettings.value("ScreenPlayContentPath", "").toString(); // Steamless - if (!steamVersion() && contentPath.isEmpty()) { + const GlobalVariables::Version version = m_globalVariables->version(); + const bool steamVersion = version == GlobalVariables::Version::OpenSourceSteam || version == GlobalVariables::Version::OpenSourceProSteam; + if (!steamVersion && contentPath.isEmpty()) { const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); m_qSettings.setValue("ScreenPlayContentPath", QUrl::fromUserInput(path)); m_qSettings.sync(); @@ -312,7 +312,8 @@ bool Settings::retranslateUI() guiAppInst->installTranslator(&m_translator); emit requestRetranslation(); - if (language() == Settings::Language::Ko_KR) { + const Language lang = language(); + if (lang == Settings::Language::Ko_KR) { setFont("Noto Sans CJK KR Regular"); } else { setFont("Roboto"); @@ -516,14 +517,6 @@ void Settings::setDecoder(QString decoder) emit decoderChanged(m_decoder); } -void Settings::setOfflineMode(bool offlineMode) -{ - if (m_offlineMode == offlineMode) - return; - - m_offlineMode = offlineMode; - emit offlineModeChanged(m_offlineMode); -} void Settings::setSilentStart(bool silentStart) { @@ -598,14 +591,6 @@ void Settings::setTheme(ScreenPlay::Settings::Theme theme) emit themeChanged(m_theme); } -void Settings::setSteamVersion(bool steamVersion) -{ - if (m_steamVersion == steamVersion) - return; - - m_steamVersion = steamVersion; - emit steamVersionChanged(m_steamVersion); -} void Settings::setDesktopEnvironment(DesktopEnvironment desktopEnvironment) { diff --git a/ScreenPlaySDK/CMakeLists.txt b/ScreenPlaySDK/CMakeLists.txt index df45410b..e6df8e55 100644 --- a/ScreenPlaySDK/CMakeLists.txt +++ b/ScreenPlaySDK/CMakeLists.txt @@ -21,7 +21,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC inc/public/) target_link_libraries( ${PROJECT_NAME} PUBLIC Qt6::Core - Qt6::Quick - Qt6::Gui - Qt6::Network - ScreenPlayUtil) + Qt6::Quick + Qt6::Gui + Qt6::Network + ScreenPlayUtil) diff --git a/ScreenPlayUtil/CMakeLists.txt b/ScreenPlayUtil/CMakeLists.txt index c91601d0..9f1695fc 100644 --- a/ScreenPlayUtil/CMakeLists.txt +++ b/ScreenPlayUtil/CMakeLists.txt @@ -16,7 +16,6 @@ find_package( REQUIRED) set(QML - # cmake-format: sort qml/CloseIcon.qml qml/ColorImage.qml @@ -31,37 +30,37 @@ set(QML qml/Headline.qml qml/HeadlineSection.qml qml/ImageSelector.qml + qml/LabelSlider.qml qml/LicenseSelector.qml qml/ModalBackgroundBlur.qml qml/MouseHoverBlocker.qml qml/Popup.qml qml/RippleEffect.qml qml/Shake.qml - qml/LabelSlider.qml qml/Tag.qml qml/TagSelector.qml qml/TextField.qml) set(SOURCES # cmake-format: sort - src/processmanager.cpp src/archive.cpp src/contenttypes.cpp src/exitcodes.cpp src/logginghandler.cpp + src/processmanager.cpp src/projectfile.cpp src/steamenumsgenerated.cpp src/util.cpp) set(HEADER # cmake-format: sort - inc/public/ScreenPlayUtil/processmanager.h inc/public/ScreenPlayUtil/archive.h inc/public/ScreenPlayUtil/contenttypes.h inc/public/ScreenPlayUtil/exitcodes.h inc/public/ScreenPlayUtil/HelpersCommon.h inc/public/ScreenPlayUtil/ListPropertyHelper.h inc/public/ScreenPlayUtil/logginghandler.h + inc/public/ScreenPlayUtil/processmanager.h inc/public/ScreenPlayUtil/projectfile.h inc/public/ScreenPlayUtil/PropertyHelpers.h inc/public/ScreenPlayUtil/steamenumsgenerated.h @@ -73,7 +72,7 @@ if(APPLE) endif() set(RESOURCES # cmake-format: sort - assets/icons/attach_file.svg assets/icons/description.svg assets/icons/folder.svg) + assets/icons/attach_file.svg assets/icons/description.svg assets/icons/folder.svg) qt_add_library( ${PROJECT_NAME} @@ -107,15 +106,14 @@ target_include_directories(${PROJECT_NAME}plugin PUBLIC inc/public/ScreenPlayUti target_link_libraries( ${PROJECT_NAME} - PUBLIC - Qt6::Core - Qt6::Quick - Qt6::Gui - QCoro6::Core - QCoro6::Qml - fmt::fmt-header-only - LibArchive::LibArchive - QArchive) + PUBLIC Qt6::Core + Qt6::Quick + Qt6::Gui + QCoro6::Core + QCoro6::Qml + fmt::fmt-header-only + LibArchive::LibArchive + QArchive) if(WIN32) # Used for query windows monitor data diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json b/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json index 2f925072..1bbe9fbf 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json @@ -84,4 +84,4 @@ "configurePreset": "osx-debug" } ] -} +} \ No newline at end of file diff --git a/ScreenPlayWorkshop/CMakeLists.txt b/ScreenPlayWorkshop/CMakeLists.txt index 0317e549..c85abed0 100644 --- a/ScreenPlayWorkshop/CMakeLists.txt +++ b/ScreenPlayWorkshop/CMakeLists.txt @@ -15,7 +15,6 @@ find_package( REQUIRED) set(QML - # cmake-format: sort qml/Background.qml qml/Forum.qml @@ -37,7 +36,6 @@ set(QML qml/WorkshopItem.qml) set(SOURCES - # cmake-format: sort src/installedlistmodel.cpp src/screenplayworkshop.cpp @@ -49,7 +47,6 @@ set(SOURCES src/steamworkshoplistmodel.cpp) set(HEADER - # cmake-format: sort src/installedlistmodel.h src/screenplayworkshop.h @@ -63,7 +60,6 @@ set(HEADER src/workshopitem.h) set(RESOURCES - # cmake-format: sort assets/icons/icon_account_circle.svg assets/icons/icon_arrow_left.svg @@ -103,10 +99,10 @@ target_include_directories(${PROJECT_NAME} PUBLIC src/) target_link_libraries( ${PROJECT_NAME} PUBLIC Qt6::Core - Qt6::Quick - ${STEAM_LIB} - ScreenPlayUtil - SteamSDK) + Qt6::Quick + ${STEAM_LIB} + ScreenPlayUtil + SteamSDK) qt_add_qml_module( ${PROJECT_NAME} @@ -142,14 +138,14 @@ if(${SCREENPLAY_STEAM}) target_link_libraries( tst_ScreenPlayWorkshop PRIVATE Qt6::Quick - Qt6::QuickControls2 - ${PROJECT_NAME}plugin - ScreenPlayUtilplugin - SteamSDK) + Qt6::QuickControls2 + ${PROJECT_NAME}plugin + ScreenPlayUtilplugin + SteamSDK) if(APPLE) set_target_properties(tst_ScreenPlayWorkshop PROPERTIES RUNTIME_OUTPUT_DIRECTORY - "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") endif() endif() endif() diff --git a/ScreenPlayWorkshop/qml/PopupOffline.qml b/ScreenPlayWorkshop/qml/PopupOffline.qml index 7844d38a..1553aad2 100644 --- a/ScreenPlayWorkshop/qml/PopupOffline.qml +++ b/ScreenPlayWorkshop/qml/PopupOffline.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import ScreenPlayWorkshop import ScreenPlayUtil - import ScreenPlayApp Popup { diff --git a/ScreenPlayWorkshop/qml/Workshop.qml b/ScreenPlayWorkshop/qml/Workshop.qml index 99ed515c..c6a1ee79 100644 --- a/ScreenPlayWorkshop/qml/Workshop.qml +++ b/ScreenPlayWorkshop/qml/Workshop.qml @@ -3,6 +3,7 @@ import QtQuick.Controls import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts +import ScreenPlayApp Item { @@ -11,7 +12,7 @@ Item { property Item modalSource Component.onCompleted: { - if (App.settings.steamVersion) { + if (App.globalVariables.isSteamVersion()) { workshopLoader.setSource("qrc:/qml/ScreenPlayApp/qml/Workshop/SteamWorkshop.qml", { "modalSource": modalSource }); diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index 5c29559e..a0b9a9fa 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -4,30 +4,19 @@ FetchContent_Populate( QArchive GIT_REPOSITORY https://github.com/antony-jr/QArchive.git GIT_TAG e587f30507c0e6d92f79a2dc1a6aa7ebb1f8e679 - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder # https://bugreports.qt.io/browse/QTCREATORBUG-27083 SOURCE_DIR ${THIRD_PARTY_PATH}/QArchive) -FetchContent_Populate( - qml-plausible - GIT_REPOSITORY https://gitlab.com/kelteseth/qml-plausible.git - GIT_TAG 322d8e17cab77b496f0d7fafb19f6dcda4193ed7 - - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder - # https://bugreports.qt.io/browse/QTCREATORBUG-27083 - SOURCE_DIR ${THIRD_PARTY_PATH}/qml-plausible) FetchContent_Populate( qcoro GIT_REPOSITORY https://github.com/danvratil/qcoro.git GIT_TAG 12c052e - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder # https://bugreports.qt.io/browse/QTCREATORBUG-27083 SOURCE_DIR ${THIRD_PARTY_PATH}/qqcoro) -add_subdirectory(qml-plausible) add_subdirectory(QArchive) add_subdirectory(qqcoro) @@ -38,7 +27,6 @@ if(UNIX AND NOT APPLE) qt-layer-shell GIT_REPOSITORY https://github.com/KDE/layer-shell-qt.git GIT_TAG 721c0ae334554eb2396a2d4d3358f896b8c77412 - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder # https://bugreports.qt.io/browse/QTCREATORBUG-27083 SOURCE_DIR ${THIRD_PARTY_PATH}/qt-layer-shell)