diff --git a/ScreenPlay/main.qml b/ScreenPlay/main.qml index c2e3cdf4..d6597b38 100644 --- a/ScreenPlay/main.qml +++ b/ScreenPlay/main.qml @@ -4,10 +4,8 @@ import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.12 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 - import ScreenPlay 1.0 import Settings 1.0 - import "qml/Monitors" as Monitors import "qml/Common" as Common import "qml/Common/Dialogs" as Dialogs @@ -18,112 +16,113 @@ import "qml/Community" as Community ApplicationWindow { id: window - color: Material.theme === Material.Dark ? Qt.darker( - Material.background) : Material.background - // Set visible if the -silent parameter was not set (see app.cpp end of constructor). - visible: false - width: 1400 - height: 788 - title: "ScreenPlay Alpha - " + ScreenPlay.version(); - minimumHeight: 450 - minimumWidth: 1050 - onVisibilityChanged: { - if (window.visibility === 2) { - ScreenPlay.installedListModel.reset() - } - } - - // Partial workaround for - // https://bugreports.qt.io/browse/QTBUG-86047 - Material.accent: Material.color(Material.Orange) - - Component.onCompleted: { - setTheme(ScreenPlay.settings.theme) - switchPage("Installed") - - if (!ScreenPlay.settings.silentStart) { - window.show() - } - } - - Connections { - target: ScreenPlay.settings - function onThemeChanged(theme) { - setTheme(theme) - } - } - - Connections { - target: ScreenPlay.util - function onRequestNavigation(nav) { - switchPage(nav) - } - } - - Connections { - target: ScreenPlay.screenPlayManager - function onRequestRaise() { - window.show() - } - } function setTheme(theme) { switch (theme) { case Settings.System: - window.Material.theme = Material.System - break + window.Material.theme = Material.System; + break; case Settings.Dark: - window.Material.theme = Material.Dark - break + window.Material.theme = Material.Dark; + break; case Settings.Light: - window.Material.theme = Material.Light - break + window.Material.theme = Material.Light; + break; } } function switchPage(name) { - const unloadSteamPlugin = nav.currentNavigationName === "Workshop" - + const unloadSteamPlugin = nav.currentNavigationName === "Workshop"; if (nav.currentNavigationName === name) { if (name === "Installed") - ScreenPlay.installedListModel.reset() - return - } + ScreenPlay.installedListModel.reset(); + return ; + } if (name === "Workshop") { if (!ScreenPlay.settings.steamVersion) { - const steamAvialable = ScreenPlay.loadSteamPlugin() + const steamAvialable = ScreenPlay.loadSteamPlugin(); if (!steamAvialable) { - dialogSteam.open() - switchPage("Installed") - return + dialogSteam.open(); + switchPage("Installed"); + return ; } } } + stackView.replace("qrc:/qml/" + name + "/" + name + ".qml"); + if (unloadSteamPlugin) + ScreenPlay.unloadSteamPlugin(); - stackView.replace("qrc:/qml/" + name + "/" + name + ".qml") + sidebar.state = "inactive"; + } - if (unloadSteamPlugin) { - ScreenPlay.unloadSteamPlugin() + color: Material.theme === Material.Dark ? Qt.darker(Material.background) : Material.background + // Set visible if the -silent parameter was not set (see app.cpp end of constructor). + visible: false + width: 1400 + height: 788 + title: "ScreenPlay Alpha - " + ScreenPlay.version() + minimumHeight: 450 + minimumWidth: 1050 + // Partial workaround for + // https://bugreports.qt.io/browse/QTBUG-86047 + Material.accent: Material.color(Material.Orange) + onVisibilityChanged: { + if (window.visibility === 2) + ScreenPlay.installedListModel.reset(); + + } + Component.onCompleted: { + setTheme(ScreenPlay.settings.theme); + switchPage("Installed"); + if (!ScreenPlay.settings.silentStart) + window.show(); + + } + + Connections { + function onThemeChanged(theme) { + setTheme(theme); } - sidebar.state = "inactive" + target: ScreenPlay.settings + } + + Connections { + function onRequestNavigation(nav) { + switchPage(nav); + } + + target: ScreenPlay.util + } + + Connections { + function onRequestRaise() { + window.show(); + } + + target: ScreenPlay.screenPlayManager } Dialogs.SteamNotAvailable { id: dialogSteam } - Dialogs.MonitorConfiguration {} + Dialogs.MonitorConfiguration { + } Dialogs.CriticalError { mainWindow: window } - Common.TrayIcon {} + Common.TrayIcon { + } StackView { id: stackView + + property int duration: 300 + anchors { top: nav.bottom right: parent.right @@ -131,8 +130,6 @@ ApplicationWindow { left: parent.left } - property int duration: 300 - replaceEnter: Transition { OpacityAnimator { from: 0 @@ -140,13 +137,16 @@ ApplicationWindow { duration: stackView.duration easing.type: Easing.InOutQuart } + ScaleAnimator { from: 0.8 to: 1 duration: stackView.duration easing.type: Easing.InOutQuart } + } + replaceExit: Transition { OpacityAnimator { from: 1 @@ -154,61 +154,68 @@ ApplicationWindow { duration: stackView.duration easing.type: Easing.InOutQuart } + ScaleAnimator { from: 1 to: 0.8 duration: stackView.duration easing.type: Easing.InOutQuart } + } + } Connections { - target: stackView.currentItem - ignoreUnknownSignals: true - function onSetSidebarActive(active) { - if (active) { - sidebar.state = "active" - } else { - sidebar.state = "inactive" - } + if (active) + sidebar.state = "active"; + else + sidebar.state = "inactive"; } function onSetNavigationItem(pos) { - if (pos === 0) { - nav.onPageChanged("Create") - } else { - nav.onPageChanged("Workshop") - } + if (pos === 0) + nav.onPageChanged("Create"); + else + nav.onPageChanged("Workshop"); } + + target: stackView.currentItem + ignoreUnknownSignals: true } Installed.Sidebar { id: sidebar navHeight: nav.height + anchors { top: parent.top right: parent.right bottom: parent.bottom } + } Navigation.Navigation { id: nav + + onChangePage: { + monitors.close(); + switchPage(name); + } + anchors { top: parent.top right: parent.right left: parent.left } - onChangePage: { - monitors.close() - switchPage(name) - } + } Monitors.Monitors { id: monitors } + } diff --git a/ScreenPlay/qml/Common/Background.qml b/ScreenPlay/qml/Common/Background.qml index 1b8e5a2a..70b5527f 100644 --- a/ScreenPlay/qml/Common/Background.qml +++ b/ScreenPlay/qml/Common/Background.qml @@ -5,17 +5,20 @@ import QtQuick.Particles 2.0 Rectangle { id: element + anchors.fill: parent - color: Material.theme === Material.Light ? "white" : Qt.darker( - Material.background) + color: Material.theme === Material.Light ? "white" : Qt.darker(Material.background) state: "init" Rectangle { id: bgCommunity + anchors.fill: parent } + Rectangle { id: bgWorkshop + color: "#161C1D" anchors.fill: parent } @@ -23,52 +26,62 @@ Rectangle { states: [ State { name: "init" + PropertyChanges { target: bgCommunity opacity: 0 } + PropertyChanges { target: bgWorkshop opacity: 0 } + }, State { name: "create" + PropertyChanges { target: bgCommunity opacity: 0 } + PropertyChanges { target: bgWorkshop opacity: 0 } + }, State { name: "community" + PropertyChanges { target: bgCommunity opacity: 1 } + PropertyChanges { target: bgWorkshop opacity: 0 } + }, State { name: "workshop" + PropertyChanges { target: bgCommunity opacity: 0 } + PropertyChanges { target: bgWorkshop opacity: 1 } + } ] - transitions: [ - Transition { from: "*" to: "*" @@ -79,6 +92,7 @@ Rectangle { duration: 400 easing.type: Easing.InOutQuart } + } ] } diff --git a/ScreenPlay/qml/Common/CloseIcon.qml b/ScreenPlay/qml/Common/CloseIcon.qml index 6a65ecfe..91f70e17 100644 --- a/ScreenPlay/qml/Common/CloseIcon.qml +++ b/ScreenPlay/qml/Common/CloseIcon.qml @@ -9,19 +9,6 @@ import QtQuick.Controls.Material 2.3 */ MouseArea { id: root - width: 32 - height: width - cursorShape: Qt.PointingHandCursor - - onEntered: root.state = "hover" - onExited: root.state = "" - hoverEnabled: true - anchors { - top: parent.top - right: parent.right - margins: 10 - } - /*! \qmlproperty color BackButtonIcon::color @@ -29,8 +16,6 @@ MouseArea { Color if the icon. */ property color color: Material.iconColor - - /*! \qmlproperty string BackButtonIcon::icon @@ -38,8 +23,22 @@ MouseArea { */ property string icon: "qrc:/assets/icons/icon_close.svg" + width: 32 + height: width + cursorShape: Qt.PointingHandCursor + onEntered: root.state = "hover" + onExited: root.state = "" + hoverEnabled: true + + anchors { + top: parent.top + right: parent.right + margins: 10 + } + Image { id: imgClose + source: root.icon visible: false width: 14 @@ -51,10 +50,12 @@ MouseArea { ColorOverlay { id: iconColorOverlay + anchors.fill: imgClose source: imgClose color: root.color } + states: [ State { name: "hover" @@ -63,9 +64,9 @@ MouseArea { target: iconColorOverlay color: Material.color(Material.Orange) } + } ] - transitions: [ Transition { from: "" @@ -77,6 +78,7 @@ MouseArea { duration: 200 easing.type: Easing.InOutQuad } + } ] } diff --git a/ScreenPlay/qml/Common/ColorPicker.qml b/ScreenPlay/qml/Common/ColorPicker.qml index fabe5177..0fcbdc6e 100644 --- a/ScreenPlay/qml/Common/ColorPicker.qml +++ b/ScreenPlay/qml/Common/ColorPicker.qml @@ -30,22 +30,122 @@ import QtQuick.Controls 2.12 import QtQuick.Shapes 1.12 Pane { - width: 500 - height: 300 - property color hueColor: "blue" property int colorHandleRadius: 10 property int marginsValue: 10 property int chekerSide: 5 - property color currentColor: "black" - property var commonColors: ['#FFFFFF', '#C0C0C0', '#808080', '#000000', '#FF0000', '#800000', '#FFFF00', '#808000', '#00FF00', '#008000', '#00FFFF', '#008080', '#0000FF', '#000080', '#FF00FF', '#800080'] property bool updatingControls: false function initColor(acolor) { - initColorRGB(acolor.r * 255, acolor.g * 255, acolor.b * 255, - acolor.a * 255) + initColorRGB(acolor.r * 255, acolor.g * 255, acolor.b * 255, acolor.a * 255); + } + + function setHueColor(hueValue) { + var v = 1 - hueValue; + if (0 <= v && v < 0.16) { + return Qt.rgba(1, 0, v / 0.16, 1); + } else if (0.16 <= v && v < 0.33) { + return Qt.rgba(1 - (v - 0.16) / 0.17, 0, 1, 1); + } else if (0.33 <= v && v < 0.5) { + return Qt.rgba(0, ((v - 0.33) / 0.17), 1, 1); + } else if (0.5 <= v && v < 0.76) { + return Qt.rgba(0, 1, 1 - (v - 0.5) / 0.26, 1); + } else if (0.76 <= v && v < 0.85) { + return Qt.rgba((v - 0.76) / 0.09, 1, 0, 1); + } else if (0.85 <= v && v <= 1) { + return Qt.rgba(1, 1 - (v - 0.85) / 0.15, 0, 1); + } else { + console.log("Invalid hueValue [0, 1]", hueValue); + return "white"; + } + } + + function hexToRgb(hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + "r": parseInt(result[1], 16), + "g": parseInt(result[2], 16), + "b": parseInt(result[3], 16) + } : null; + } + + function rgbToHex(r, g, b) { + return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); + } + + function drawChecker(ctx, width, height) { + ctx.lineWidth = 0; + //ctx.strokeStyle = 'blue' + var numRows = Math.ceil(height / chekerSide); + var numCols = Math.ceil(width / chekerSide); + var lastWhite = false; + var lastColWhite = false; + for (var icol = 0; icol < numCols; icol++) { + lastColWhite = lastWhite; + for (var irow = 0; irow < numRows; irow++) { + if (lastWhite) + ctx.fillStyle = 'gray'; + else + ctx.fillStyle = 'white'; + ctx.fillRect(icol * chekerSide, irow * chekerSide, chekerSide, chekerSide); + lastWhite = !lastWhite; + } + lastWhite = !lastColWhite; + } + } + + function handleMouseVertSlider(mouse, ctrlCursor, ctrlHeight) { + if (mouse.buttons & Qt.LeftButton) { + ctrlCursor.y = Math.max(0, Math.min(ctrlHeight, mouse.y)); + setCurrentColor(); + } + } + + function setCurrentColor() { + var alphaFactor = 1 - (shpAlpha.y / shpAlpha.parent.height); + if (optHsv.checked) { + var hueFactor = 1 - (shpHue.y / shpHue.parent.height); + hueColor = setHueColor(hueFactor); + var saturation = (pickerCursor.x + colorHandleRadius) / pickerCursor.parent.width; + var colorValue = 1 - ((pickerCursor.y + colorHandleRadius) / pickerCursor.parent.height); + currentColor = Qt.hsva(hueFactor, saturation, colorValue, alphaFactor); + } else { + currentColor = Qt.rgba(sliderRed.value / 255, sliderGreen.value / 255, sliderBlue.value / 255, alphaFactor); + } + hexColor.text = rgbToHex(currentColor.r * 255, currentColor.g * 255, currentColor.b * 255); + optHsv.focus = true; + } + + function initColorRGB(ared, agreen, ablue, aalpha) { + updatingControls = true; + var acolor = Qt.rgba(ared / 255, agreen / 255, ablue / 255, aalpha / 255); + var valHue = acolor.hsvHue; + if (valHue < 0) + valHue = 0; + + //console.log("toset", acolor.r * 255, acolor.g * 255, acolor.b * 255, acolor.a * 255) + shpHue.y = ((1 - valHue) * shpHue.parent.height); + shpAlpha.y = ((1 - acolor.a) * shpAlpha.parent.height); + pickerCursor.x = (acolor.hsvSaturation * pickerCursor.parent.width) - colorHandleRadius; + pickerCursor.y = ((1 - acolor.hsvValue) * pickerCursor.parent.height) - colorHandleRadius; + sliderRed.value = ared; + sliderGreen.value = agreen; + sliderBlue.value = ablue; + setCurrentColor(); + updatingControls = false; + } + + width: 500 + height: 300 + Component.onCompleted: { + initColorRGB(255, 0, 0, 255); } RowLayout { @@ -74,19 +174,23 @@ Pane { y: 0 width: parent.width height: parent.height - visible: true + gradient: Gradient { orientation: Gradient.Horizontal + GradientStop { - position: 0.0 + position: 0 color: "#FFFFFF" } + GradientStop { - position: 1.0 + position: 1 color: hueColor } + } + } Rectangle { @@ -95,28 +199,33 @@ Pane { width: parent.width height: parent.height border.color: BppMetrics.accentColor - visible: true + gradient: Gradient { GradientStop { - position: 1.0 + position: 1 color: "#FF000000" } + GradientStop { - position: 0.0 + position: 0 color: "#00000000" } + } + } Rectangle { id: pickerCursor + width: colorHandleRadius * 2 height: colorHandleRadius * 2 radius: colorHandleRadius border.color: BppMetrics.windowBackground border.width: 2 color: "transparent" + Rectangle { anchors.fill: parent anchors.margins: 2 @@ -125,66 +234,33 @@ Pane { radius: width / 2 color: "transparent" } + } MouseArea { - anchors.fill: parent function handleMouse(mouse) { if (mouse.buttons & Qt.LeftButton) { - pickerCursor.x = Math.max( - -colorHandleRadius, Math.min( - width, - mouse.x) - colorHandleRadius) - pickerCursor.y = Math.max( - -colorHandleRadius, Math.min( - height, - mouse.y) - colorHandleRadius) - setCurrentColor() + pickerCursor.x = Math.max(-colorHandleRadius, Math.min(width, mouse.x) - colorHandleRadius); + pickerCursor.y = Math.max(-colorHandleRadius, Math.min(height, mouse.y) - colorHandleRadius); + setCurrentColor(); } } + + anchors.fill: parent onPositionChanged: handleMouse(mouse) onPressed: handleMouse(mouse) } + } Rectangle { Layout.fillHeight: true Layout.preferredWidth: 30 - border.color: BppMetrics.accentColor - gradient: Gradient { - GradientStop { - position: 1.0 - color: "#FF0000" - } - GradientStop { - position: 0.85 - color: "#FFFF00" - } - GradientStop { - position: 0.76 - color: "#00FF00" - } - GradientStop { - position: 0.5 - color: "#00FFFF" - } - GradientStop { - position: 0.33 - color: "#0000FF" - } - GradientStop { - position: 0.16 - color: "#FF00FF" - } - GradientStop { - position: 0.0 - color: "#FF0000" - } - } Shape { id: shpHue + anchors.left: parent.left anchors.margins: 0 y: 90 @@ -192,27 +268,72 @@ Pane { ShapePath { strokeWidth: 1 strokeColor: "black" + PathSvg { path: "M0,0 L30,0" } + } + ShapePath { strokeWidth: 2 strokeColor: BppMetrics.accentColor fillColor: "transparent" + PathSvg { path: "M0,-5 L30,-5 L30,4 L0,4z" } + } + } MouseArea { anchors.fill: parent - onPositionChanged: handleMouseVertSlider(mouse, - shpHue, height) + onPositionChanged: handleMouseVertSlider(mouse, shpHue, height) onPressed: handleMouseVertSlider(mouse, shpHue, height) } + + gradient: Gradient { + GradientStop { + position: 1 + color: "#FF0000" + } + + GradientStop { + position: 0.85 + color: "#FFFF00" + } + + GradientStop { + position: 0.76 + color: "#00FF00" + } + + GradientStop { + position: 0.5 + color: "#00FFFF" + } + + GradientStop { + position: 0.33 + color: "#0000FF" + } + + GradientStop { + position: 0.16 + color: "#FF00FF" + } + + GradientStop { + position: 0 + color: "#FF0000" + } + + } + } + } ColumnLayout { @@ -224,50 +345,63 @@ Pane { text: qsTr("Red") color: BppMetrics.textColor } + Slider { id: sliderRed + Layout.fillWidth: true from: 0 to: 255 value: 0 onValueChanged: { if (!updatingControls) - setCurrentColor() + setCurrentColor(); + } } + Label { text: qsTr("Green") color: BppMetrics.textColor } + Slider { id: sliderGreen + Layout.fillWidth: true from: 0 to: 255 value: 0 onValueChanged: { if (!updatingControls) - setCurrentColor() + setCurrentColor(); + } } + Label { text: qsTr("Blue") color: BppMetrics.textColor } + Slider { id: sliderBlue + Layout.fillWidth: true from: 0 to: 255 value: 0 onValueChanged: { if (!updatingControls) - setCurrentColor() + setCurrentColor(); + } } + Item { Layout.fillHeight: true } + } Rectangle { @@ -283,65 +417,58 @@ Pane { Repeater { model: commonColors + Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: modelData border.color: "gray" border.width: 0 + MouseArea { anchors.fill: parent hoverEnabled: true onPressed: { - initColorRGB(parent.color.r * 255, - parent.color.g * 255, - parent.color.b * 255, 255) + initColorRGB(parent.color.r * 255, parent.color.g * 255, parent.color.b * 255, 255); } onEntered: { - border.width = 1 - var compColor = Qt.rgba(1, 1, 1, 1) + border.width = 1; + var compColor = Qt.rgba(1, 1, 1, 1); if (color.hsvValue > 0.5) - compColor = Qt.rgba(0, 0, 0, 1) - border.color = compColor + compColor = Qt.rgba(0, 0, 0, 1); + + border.color = compColor; } onExited: { - border.width = 0 + border.width = 0; } } + } + } + } + } + } Canvas { Layout.fillHeight: true Layout.preferredWidth: 30 - onPaint: { - var ctx = getContext('2d') - drawChecker(ctx, width, height) + var ctx = getContext('2d'); + drawChecker(ctx, width, height); } Rectangle { anchors.fill: parent border.color: BppMetrics.accentColor - gradient: Gradient { - //GradientStop { position: 0.0; color: "#FF000000" } - GradientStop { - position: 0.0 - color: Qt.rgba(currentColor.r, currentColor.g, - currentColor.b, 1) - } - GradientStop { - position: 1.0 - color: "#00000000" - } - } - Shape { id: shpAlpha + anchors.left: parent.left anchors.margins: 0 y: 90 @@ -349,27 +476,48 @@ Pane { ShapePath { strokeWidth: 1 strokeColor: "black" + PathSvg { path: "M0,0 L30,0" } + } + ShapePath { strokeWidth: 2 strokeColor: BppMetrics.accentColor fillColor: "transparent" + PathSvg { path: "M0,-5 L30,-5 L30,4 L0,4z" } + } + } MouseArea { anchors.fill: parent - onPositionChanged: handleMouseVertSlider(mouse, - shpAlpha, height) + onPositionChanged: handleMouseVertSlider(mouse, shpAlpha, height) onPressed: handleMouseVertSlider(mouse, shpAlpha, height) } + + gradient: Gradient { + //GradientStop { position: 0.0; color: "#FF000000" } + GradientStop { + position: 0 + color: Qt.rgba(currentColor.r, currentColor.g, currentColor.b, 1) + } + + GradientStop { + position: 1 + color: "#00000000" + } + + } + } + } ColumnLayout { @@ -381,41 +529,50 @@ Pane { Canvas { Layout.fillWidth: true height: 35 - onPaint: { - var ctx = getContext('2d') - drawChecker(ctx, width, height) + var ctx = getContext('2d'); + drawChecker(ctx, width, height); } + Rectangle { border.color: BppMetrics.accentColor color: "transparent" anchors.fill: parent + RowLayout { anchors.fill: parent anchors.margins: 1 spacing: 0 + Rectangle { Layout.fillWidth: true Layout.fillHeight: true - color: Qt.rgba(currentColor.r, currentColor.g, - currentColor.b, 1) + color: Qt.rgba(currentColor.r, currentColor.g, currentColor.b, 1) } + Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: currentColor } + } + } + } ColumnLayout { spacing: 0 + RadioButton { id: optRgb + padding: 0 text: qsTr("RGB") Layout.alignment: Qt.AlignLeft + onCheckedChanged: initColorRGB(currentColor.r * 255, currentColor.g * 255, currentColor.b * 255, currentColor.a * 255) + contentItem: Text { text: optRgb.text color: BppMetrics.textColor @@ -423,18 +580,19 @@ Pane { leftPadding: optRgb.indicator.width + optRgb.spacing verticalAlignment: Text.AlignVCenter } - onCheckedChanged: initColorRGB(currentColor.r * 255, - currentColor.g * 255, - currentColor.b * 255, - currentColor.a * 255) + } + RadioButton { id: optHsv + padding: 0 text: qsTr("HSV") Layout.alignment: Qt.AlignLeft checked: true focus: true + onCheckedChanged: initColorRGB(currentColor.r * 255, currentColor.g * 255, currentColor.b * 255, currentColor.a * 255) + contentItem: Text { text: optHsv.text color: BppMetrics.textColor @@ -442,11 +600,9 @@ Pane { leftPadding: optHsv.indicator.width + optHsv.spacing verticalAlignment: Text.AlignVCenter } - onCheckedChanged: initColorRGB(currentColor.r * 255, - currentColor.g * 255, - currentColor.b * 255, - currentColor.a * 255) + } + } Item { @@ -456,82 +612,105 @@ Pane { RowLayout { visible: optRgb.checked Layout.fillWidth: true + Label { text: qsTr("R:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.r * 255) Layout.fillWidth: true color: BppMetrics.textColor } + } + RowLayout { visible: optRgb.checked Layout.fillWidth: true + Label { text: qsTr("G:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.g * 255) Layout.fillWidth: true color: BppMetrics.textColor } + } + RowLayout { visible: optRgb.checked Layout.fillWidth: true + Label { text: qsTr("B:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.b * 255) Layout.fillWidth: true color: BppMetrics.textColor } + } RowLayout { visible: optHsv.checked Layout.fillWidth: true + Label { text: qsTr("H:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.hsvHue * 360) Layout.fillWidth: true color: BppMetrics.textColor } + } + RowLayout { visible: optHsv.checked Layout.fillWidth: true + Label { text: qsTr("S:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.hsvSaturation * 100) Layout.fillWidth: true color: BppMetrics.textColor } + } + RowLayout { visible: optHsv.checked Layout.fillWidth: true + Label { text: qsTr("V:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.hsvValue * 100) Layout.fillWidth: true color: BppMetrics.textColor } + } + Item { Layout.fillHeight: true } @@ -539,170 +718,56 @@ Pane { //Label { text: qsTr("Alpha"); color: BppMetrics.textColor; font.bold: true; Layout.alignment: Qt.AlignLeft } RowLayout { Layout.fillWidth: true + Label { text: qsTr("Alpha:") color: BppMetrics.textColor } + Label { text: Math.floor(currentColor.a * 255) Layout.fillWidth: true color: BppMetrics.textColor } + } + RowLayout { Layout.fillWidth: true spacing: 0 + Label { text: qsTr("#") color: BppMetrics.textColor } + TextInput { id: hexColor + Layout.fillWidth: true text: "FF0099" inputMask: "HHHHHH" selectByMouse: true color: BppMetrics.textColor - onTextChanged: { - if (!hexColor.focus) { - return - } + if (!hexColor.focus) + return ; if (!updatingControls && acceptableInput) { - var rgbColor = hexToRgb(text) - if (rgbColor && rgbColor.r !== Math.floor( - currentColor.r * 255) - && rgbColor.g !== Math.floor( - currentColor.g * 255) - && rgbColor.b !== Math.floor( - currentColor.b * 255)) { - //console.log('updating', rgbColor.r, currentColor.r * 255, rgbColor.g, currentColor.g * 255, rgbColor.b, currentColor.b * 255) - initColorRGB(rgbColor.r, rgbColor.g, - rgbColor.b, currentColor.a * 255) - } + //console.log('updating', rgbColor.r, currentColor.r * 255, rgbColor.g, currentColor.g * 255, rgbColor.b, currentColor.b * 255) + + var rgbColor = hexToRgb(text); + if (rgbColor && rgbColor.r !== Math.floor(currentColor.r * 255) && rgbColor.g !== Math.floor(currentColor.g * 255) && rgbColor.b !== Math.floor(currentColor.b * 255)) + initColorRGB(rgbColor.r, rgbColor.g, rgbColor.b, currentColor.a * 255); + } } } + } - } - } - function setHueColor(hueValue) { - var v = 1.0 - hueValue - if (0.0 <= v && v < 0.16) { - return Qt.rgba(1.0, 0.0, v / 0.16, 1.0) - } else if (0.16 <= v && v < 0.33) { - return Qt.rgba(1.0 - (v - 0.16) / 0.17, 0.0, 1.0, 1.0) - } else if (0.33 <= v && v < 0.5) { - return Qt.rgba(0.0, ((v - 0.33) / 0.17), 1.0, 1.0) - } else if (0.5 <= v && v < 0.76) { - return Qt.rgba(0.0, 1.0, 1.0 - (v - 0.5) / 0.26, 1.0) - } else if (0.76 <= v && v < 0.85) { - return Qt.rgba((v - 0.76) / 0.09, 1.0, 0.0, 1.0) - } else if (0.85 <= v && v <= 1.0) { - return Qt.rgba(1.0, 1.0 - (v - 0.85) / 0.15, 0.0, 1.0) - } else { - console.log("Invalid hueValue [0, 1]", hueValue) - return "white" - } - } - - function hexToRgb(hex) { - // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i - hex = hex.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b - }) - - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) - return result ? { - "r": parseInt(result[1], 16), - "g": parseInt(result[2], 16), - "b": parseInt(result[3], 16) - } : null - } - - function rgbToHex(r, g, b) { - return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1) - } - - function drawChecker(ctx, width, height) { - ctx.lineWidth = 0 - - //ctx.strokeStyle = 'blue' - var numRows = Math.ceil(height / chekerSide) - var numCols = Math.ceil(width / chekerSide) - - var lastWhite = false - var lastColWhite = false - for (var icol = 0; icol < numCols; icol++) { - lastColWhite = lastWhite - for (var irow = 0; irow < numRows; irow++) { - if (lastWhite) - ctx.fillStyle = 'gray' - else - ctx.fillStyle = 'white' - - ctx.fillRect(icol * chekerSide, irow * chekerSide, chekerSide, - chekerSide) - lastWhite = !lastWhite - } - lastWhite = !lastColWhite - } - } - - function handleMouseVertSlider(mouse, ctrlCursor, ctrlHeight) { - if (mouse.buttons & Qt.LeftButton) { - ctrlCursor.y = Math.max(0, Math.min(ctrlHeight, mouse.y)) - setCurrentColor() - } - } - - function setCurrentColor() { - var alphaFactor = 1.0 - (shpAlpha.y / shpAlpha.parent.height) - if (optHsv.checked) { - var hueFactor = 1.0 - (shpHue.y / shpHue.parent.height) - hueColor = setHueColor(hueFactor) - var saturation = (pickerCursor.x + colorHandleRadius) / pickerCursor.parent.width - var colorValue = 1 - ((pickerCursor.y + colorHandleRadius) / pickerCursor.parent.height) - currentColor = Qt.hsva(hueFactor, saturation, colorValue, - alphaFactor) - } else { - currentColor = Qt.rgba(sliderRed.value / 255.0, - sliderGreen.value / 255.0, - sliderBlue.value / 255.0, alphaFactor) } - hexColor.text = rgbToHex(currentColor.r * 255, currentColor.g * 255, - currentColor.b * 255) - optHsv.focus = true } - function initColorRGB(ared, agreen, ablue, aalpha) { - updatingControls = true - - var acolor = Qt.rgba(ared / 255.0, agreen / 255.0, ablue / 255.0, - aalpha / 255.0) - var valHue = acolor.hsvHue - if (valHue < 0) - valHue = 0 - //console.log("toset", acolor.r * 255, acolor.g * 255, acolor.b * 255, acolor.a * 255) - shpHue.y = ((1.0 - valHue) * shpHue.parent.height) - shpAlpha.y = ((1.0 - acolor.a) * shpAlpha.parent.height) - - pickerCursor.x = (acolor.hsvSaturation * pickerCursor.parent.width) - colorHandleRadius - pickerCursor.y = ((1 - acolor.hsvValue) * pickerCursor.parent.height) - colorHandleRadius - - sliderRed.value = ared - sliderGreen.value = agreen - sliderBlue.value = ablue - - setCurrentColor() - updatingControls = false - } - - Component.onCompleted: { - initColorRGB(255, 0, 0, 255) - } } diff --git a/ScreenPlay/qml/Common/Dialogs/CriticalError.qml b/ScreenPlay/qml/Common/Dialogs/CriticalError.qml index 57a22dad..abfa7826 100644 --- a/ScreenPlay/qml/Common/Dialogs/CriticalError.qml +++ b/ScreenPlay/qml/Common/Dialogs/CriticalError.qml @@ -8,31 +8,32 @@ import ScreenPlay 1.0 Dialog { id: root - modal: true - anchors.centerIn: Overlay.overlay - standardButtons: Dialog.Ok | Dialog.Help - onHelpRequested: { - Qt.openUrlExternally( - "https://forum.screen-play.app/category/7/troubleshooting") - } property Window mainWindow property string message + modal: true + anchors.centerIn: Overlay.overlay + standardButtons: Dialog.Ok | Dialog.Help + onHelpRequested: { + Qt.openUrlExternally("https://forum.screen-play.app/category/7/troubleshooting"); + } + Connections { - target: ScreenPlay.screenPlayManager function onDisplayErrorPopup(msg) { - root.message = msg - root.mainWindow.show() - root.open() + root.message = msg; + root.mainWindow.show(); + root.open(); } + + target: ScreenPlay.screenPlayManager } contentItem: Item { width: 600 height: 400 - ColumnLayout { + ColumnLayout { anchors.margins: 20 anchors.fill: parent spacing: 20 @@ -46,10 +47,13 @@ Dialog { layer { enabled: true + effect: ColorOverlay { color: Material.color(Material.DeepOrange) } + } + } Text { @@ -63,6 +67,9 @@ Dialog { font.pointSize: 16 color: Material.primaryTextColor } + } + } + } diff --git a/ScreenPlay/qml/Common/Dialogs/MonitorConfiguration.qml b/ScreenPlay/qml/Common/Dialogs/MonitorConfiguration.qml index 4dce81a6..47a1c37b 100644 --- a/ScreenPlay/qml/Common/Dialogs/MonitorConfiguration.qml +++ b/ScreenPlay/qml/Common/Dialogs/MonitorConfiguration.qml @@ -2,19 +2,26 @@ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.12 - import ScreenPlay 1.0 Dialog { id: dialogMonitorConfigurationChanged + modal: true anchors.centerIn: Overlay.overlay standardButtons: Dialog.Ok contentHeight: 250 + Connections { + function onMonitorConfigurationChanged() { + dialogMonitorConfigurationChanged.open(); + } + + target: ScreenPlay.monitorListModel + } + contentItem: Item { ColumnLayout { - anchors.margins: 20 anchors.fill: parent spacing: 20 @@ -37,12 +44,9 @@ Dialog { font.pointSize: 16 color: Material.primaryTextColor } + } + } - Connections { - target: ScreenPlay.monitorListModel - function onMonitorConfigurationChanged() { - dialogMonitorConfigurationChanged.open() - } - } + } diff --git a/ScreenPlay/qml/Common/Dialogs/SteamNotAvailable.qml b/ScreenPlay/qml/Common/Dialogs/SteamNotAvailable.qml index faa8932d..164c86c2 100644 --- a/ScreenPlay/qml/Common/Dialogs/SteamNotAvailable.qml +++ b/ScreenPlay/qml/Common/Dialogs/SteamNotAvailable.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts 1.3 Dialog { id: dialogSteam + modal: true anchors.centerIn: Overlay.overlay standardButtons: Dialog.Ok diff --git a/ScreenPlay/qml/Common/FileSelector.qml b/ScreenPlay/qml/Common/FileSelector.qml index 466c814e..fb2eb635 100644 --- a/ScreenPlay/qml/Common/FileSelector.qml +++ b/ScreenPlay/qml/Common/FileSelector.qml @@ -4,7 +4,6 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Dialogs 1.2 import ScreenPlay 1.0 - /*! \qmltype Image Selector \brief A image selector with popup preview. @@ -26,29 +25,30 @@ import ScreenPlay 1.0 */ Item { id: root - height: 70 - implicitWidth: 300 - state: "nothingSelected" property string file property alias placeHolderText: txtPlaceholder.text property alias fileDialog: fileDialog + height: 70 + implicitWidth: 300 + state: "nothingSelected" onFileChanged: { if (file === "") { - txtName.text = "" - root.state = "nothingSelected" + txtName.text = ""; + root.state = "nothingSelected"; } else { - root.state = "imageSelected" + root.state = "imageSelected"; } } Rectangle { id: rectangle - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) + + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) radius: 3 clip: true + anchors { fill: parent margins: 3 @@ -56,6 +56,7 @@ Item { Text { id: txtPlaceholder + clip: true font.pointSize: 12 font.capitalization: Font.Capitalize @@ -64,6 +65,7 @@ Item { color: Material.secondaryTextColor verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft + anchors { top: parent.top left: parent.left @@ -71,10 +73,12 @@ Item { bottom: parent.bottom margins: 10 } + } Text { id: txtName + clip: true font.pointSize: 12 font.family: ScreenPlay.settings.font @@ -82,6 +86,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft color: Material.secondaryTextColor + anchors { top: parent.top left: parent.left @@ -89,16 +94,19 @@ Item { bottom: parent.bottom margins: 10 } + } Button { id: btnClear + text: qsTr("Clear") - Material.background: Material.theme - === Material.Light ? Qt.lighter( - Material.accent) : Qt.darker( - Material.accent) + Material.background: Material.theme === Material.Light ? Qt.lighter(Material.accent) : Qt.darker(Material.accent) Material.foreground: "white" + onClicked: { + root.file = ""; + fileDialog.file = ""; + } anchors { top: parent.top @@ -106,18 +114,18 @@ Item { bottom: parent.bottom margins: 5 } - onClicked: { - root.file = "" - fileDialog.file = "" - } + } Button { id: btnOpen + text: qsTr("Select File") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font + onClicked: fileDialog.open() + anchors { top: parent.top right: parent.right @@ -125,58 +133,68 @@ Item { bottom: parent.bottom margins: 5 } - onClicked: fileDialog.open() + } + FileDialog { id: fileDialog + title: qsTr("Please choose a file") onAccepted: { - root.file = fileDialog.file - txtName.text = fileDialog.file.toString() + root.file = fileDialog.file; + txtName.text = fileDialog.file.toString(); } } + } states: [ State { name: "imageSelected" + PropertyChanges { target: btnClear opacity: 1 anchors.topMargin: 5 } + PropertyChanges { target: txtPlaceholder opacity: 0 } + }, State { name: "nothingSelected" + PropertyChanges { target: btnClear opacity: 0 anchors.topMargin: -40 } + } ] - transitions: [ Transition { from: "imageSelected" to: "nothingSelected" reversible: true + PropertyAnimation { target: btnClear properties: "opacity, anchors.topMargin" duration: 300 easing.type: Easing.OutQuart } + PropertyAnimation { target: txtPlaceholder property: "opacity" duration: 300 easing.type: Easing.OutQuart } + } ] } diff --git a/ScreenPlay/qml/Common/Grow.qml b/ScreenPlay/qml/Common/Grow.qml index 917370fd..e04290e0 100644 --- a/ScreenPlay/qml/Common/Grow.qml +++ b/ScreenPlay/qml/Common/Grow.qml @@ -3,22 +3,23 @@ import QtQuick 2.12 Scale { id: root - function start(offset = 0, loopOffset = 1000, scale = 1.5,loops = 1) { - root.offset = offset - root.loopOffset = loopOffset - root.loops = loops - root.cScale = scale - grow.restart() - } - property int offset: 0 property int loopOffset: 1000 property int loops: 1 property real cScale: 1.5 property alias centerX: root.origin.x property alias centerY: root.origin.y + property SequentialAnimation grow - property SequentialAnimation grow: SequentialAnimation { + function start(offset = 0, loopOffset = 1000, scale = 1.5, loops = 1) { + root.offset = offset; + root.loopOffset = loopOffset; + root.loops = loops; + root.cScale = scale; + grow.restart(); + } + + grow: SequentialAnimation { loops: root.loops alwaysRunToEnd: true @@ -34,6 +35,7 @@ Scale { to: root.cScale duration: 200 } + PropertyAnimation { target: root properties: "xScale,yScale" @@ -41,10 +43,13 @@ Scale { to: 1 duration: 300 } + } PauseAnimation { duration: root.loopOffset } + } + } diff --git a/ScreenPlay/qml/Common/GrowIconLink.qml b/ScreenPlay/qml/Common/GrowIconLink.qml index 318120db..484a8631 100644 --- a/ScreenPlay/qml/Common/GrowIconLink.qml +++ b/ScreenPlay/qml/Common/GrowIconLink.qml @@ -4,18 +4,19 @@ import QtQuick.Controls.Material 2.12 Rectangle { id: root - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) - width: 42 - height: width - radius: width property alias iconSource: icon.source property string url property alias color: overlay.color + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) + width: 42 + height: width + radius: width + Image { id: icon + sourceSize: Qt.size(28, 28) anchors.centerIn: parent visible: false @@ -25,6 +26,7 @@ Rectangle { ColorOverlay { id: overlay + anchors.fill: icon source: icon color: Material.accent @@ -42,26 +44,29 @@ Rectangle { states: [ State { name: "hover" + PropertyChanges { target: icon width: 34 height: 34 - sourceSize: Qt.size(34,34) + sourceSize: Qt.size(34, 34) } + } ] - transitions: [ Transition { from: "" to: "hover" reversible: true + PropertyAnimation { target: icon properties: "width,height,sourceSize" duration: 200 easing.type: Easing.InOutQuart } + } ] } diff --git a/ScreenPlay/qml/Common/Headline.qml b/ScreenPlay/qml/Common/Headline.qml index cc8709e6..fc43da7b 100644 --- a/ScreenPlay/qml/Common/Headline.qml +++ b/ScreenPlay/qml/Common/Headline.qml @@ -3,13 +3,15 @@ import QtQuick.Controls.Material 2.12 import ScreenPlay 1.0 Item { - id:root - height: 40 + id: root property alias text: txtHeadline.text + height: 40 + Text { id: txtHeadline + font.pointSize: 18 color: Material.primaryTextColor text: qsTr("Headline") @@ -21,10 +23,13 @@ Item { height: 2 width: parent.width color: Material.secondaryTextColor + anchors { - right:parent.right - left:parent.left + right: parent.right + left: parent.left bottom: parent.bottom } + } + } diff --git a/ScreenPlay/qml/Common/ImageSelector.qml b/ScreenPlay/qml/Common/ImageSelector.qml index 2781a849..083e7d1a 100644 --- a/ScreenPlay/qml/Common/ImageSelector.qml +++ b/ScreenPlay/qml/Common/ImageSelector.qml @@ -4,7 +4,6 @@ import QtQuick.Controls.Material 2.12 import Qt.labs.platform 1.1 import ScreenPlay 1.0 - /*! \qmltype Image Selector \brief A image selector with popup preview. @@ -26,30 +25,31 @@ import ScreenPlay 1.0 */ Item { id: root - height: 70 - width: parent.width - state: "nothingSelected" property string imageSource property alias placeHolderText: txtPlaceholder.text + height: 70 + width: parent.width + state: "nothingSelected" onImageSourceChanged: { if (imageSource === "") { - img.source = "" - txtName.text = "" - root.state = "nothingSelected" + img.source = ""; + txtName.text = ""; + root.state = "nothingSelected"; } else { - img.source = imageSource - root.state = "imageSelected" + img.source = imageSource; + root.state = "imageSelected"; } } Rectangle { id: rectangle - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) + + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) radius: 3 clip: true + anchors { fill: parent margins: 3 @@ -57,10 +57,12 @@ Item { Rectangle { id: imgWrapper + width: 70 radius: 3 clip: true color: Material.color(Material.Grey, Material.Shade700) + anchors { top: parent.top left: parent.left @@ -70,6 +72,7 @@ Item { Image { id: img + anchors.fill: parent } @@ -77,32 +80,38 @@ Item { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - if (imageSource !== "") { - popup.open() - } + if (imageSource !== "") + popup.open(); + } } + } Popup { id: popup + width: 902 modal: true anchors.centerIn: Overlay.overlay height: 507 + Image { source: imageSource anchors.fill: parent } + MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: popup.close() } + } Text { id: txtPlaceholder + clip: true font.pointSize: 12 font.capitalization: Font.Capitalize @@ -112,6 +121,7 @@ Item { color: Material.secondaryTextColor verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft + anchors { top: parent.top left: imgWrapper.right @@ -119,10 +129,12 @@ Item { bottom: parent.bottom margins: 10 } + } Text { id: txtName + clip: true font.pointSize: 12 font.family: ScreenPlay.settings.font @@ -130,6 +142,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft color: Material.secondaryTextColor + anchors { top: parent.top left: imgWrapper.right @@ -137,16 +150,16 @@ Item { bottom: parent.bottom margins: 10 } + } Button { id: btnClear + text: qsTr("Clear") - Material.background: Material.theme - === Material.Light ? Qt.lighter( - Material.accent) : Qt.darker( - Material.accent) + Material.background: Material.theme === Material.Light ? Qt.lighter(Material.accent) : Qt.darker(Material.accent) Material.foreground: "white" + onClicked: imageSource = "" anchors { top: parent.top @@ -154,15 +167,18 @@ Item { bottom: parent.bottom margins: 5 } - onClicked: imageSource = "" + } Button { id: btnOpen + text: qsTr("Select Preview Image") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font + onClicked: fileDialog.open() + anchors { top: parent.top right: parent.right @@ -170,61 +186,70 @@ Item { bottom: parent.bottom margins: 5 } - onClicked: fileDialog.open() + } + FileDialog { id: fileDialog + title: "Please choose a file" fileMode: FileDialog.OpenFile nameFilters: ["Images (*.png *.jpg)"] onAccepted: { - imageSource = fileDialog.file - txtName.text = fileDialog.file.toString().replace(/^.*[\\\/]/, - '') + imageSource = fileDialog.file; + txtName.text = fileDialog.file.toString().replace(/^.*[\\\/]/, ''); } } + } states: [ State { name: "imageSelected" + PropertyChanges { target: btnClear opacity: 1 anchors.topMargin: 5 } + PropertyChanges { target: txtPlaceholder opacity: 0 } + }, State { name: "nothingSelected" + PropertyChanges { target: btnClear opacity: 0 anchors.topMargin: -40 } + } ] - transitions: [ Transition { from: "imageSelected" to: "nothingSelected" reversible: true + PropertyAnimation { target: btnClear properties: "opacity, anchors.topMargin" duration: 300 easing.type: Easing.OutQuart } + PropertyAnimation { target: txtPlaceholder property: "opacity" duration: 300 easing.type: Easing.OutQuart } + } ] } diff --git a/ScreenPlay/qml/Common/LicenseSelector.qml b/ScreenPlay/qml/Common/LicenseSelector.qml index 3d6ed54c..762928f8 100644 --- a/ScreenPlay/qml/Common/LicenseSelector.qml +++ b/ScreenPlay/qml/Common/LicenseSelector.qml @@ -2,16 +2,16 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Controls.Material 2.12 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 ColumnLayout { id: root - Layout.preferredWidth: 250 property string name: licenseModel.get(cb.currentIndex).name property string licenseFile: licenseModel.get(cb.currentIndex).licenseFile + Layout.preferredWidth: 250 + HeadlineSection { Layout.fillWidth: true text: qsTr("License") @@ -24,52 +24,63 @@ ColumnLayout { ComboBox { id: cb + Layout.fillWidth: true textRole: "name" + model: ListModel { id: licenseModel + ListElement { name: "Creative Commons - Attribution-ShareAlike 4.0" description: qsTr("Share — copy and redistribute the material in any medium or format. Adapt — remix, transform, and build upon the material for any purpose, even commercially.") tldrlegal: "https://tldrlegal.com/license/creative-commons-attribution-sharealike-4.0-international-(cc-by-sa-4.0)" licenseFile: "License_CC_Attribution-ShareAlike_4.0.txt" } + ListElement { name: "Creative Commons - Attribution 4.0" description: qsTr("You grant other to remix your work and change the license to their linking.") tldrlegal: "https://tldrlegal.com/license/creative-commons-attribution-4.0-international-(cc-by-4)" licenseFile: "License_CC_Attribution_4.0.txt" } + ListElement { name: "Creative Commons - Attribution-NonCommercial-ShareAlike 4.0" description: qsTr("Share — copy and redistribute the material in any medium or format. Adapt — remix, transform, and build upon the material. You are not allowed to use it commercially! ") tldrlegal: "https://tldrlegal.com/license/creative-commons-attribution-noncommercial-sharealike-4.0-international-(cc-by-nc-sa-4.0)" licenseFile: "License_CC_Attribution-NonCommercial-ShareAlike_4.0.txt" } + ListElement { name: "Creative Commons - CC0 1.0 Universal Public Domain" description: qsTr("You allow everyone to do anything with your work.") tldrlegal: "https://tldrlegal.com/license/creative-commons-cc0-1.0-universal" licenseFile: "License_CC0_1.0.txt" } + ListElement { name: "Open Source - Apache License 2.0" description: qsTr("You grant other to remix your work and change the license to their linking.") tldrlegal: "https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)" licenseFile: "License_Apache_2.0.txt" } + ListElement { name: "Open Source - General Public License 3.0" description: qsTr("You grant other to remix your work but it must remain under the GPLv3. We recommend this license for all code wallpaper!") tldrlegal: "https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)" licenseFile: "License_GPL_3.0.txt" } + ListElement { name: "All rights reserved" description: qsTr("You do not share any rights and nobody is allowed to use or remix it (Not recommended). Can also used to credit work others.") tldrlegal: "License_All_Rights_Reserved_1.0.txt" } + } + } ToolButton { @@ -81,13 +92,15 @@ ColumnLayout { ToolButton { icon.source: "qrc:/assets/icons/icon_open_in_new.svg" icon.color: Material.iconColor - onClicked: Qt.openUrlExternally(licenseModel.get( - cb.currentIndex).tldrlegal) + onClicked: Qt.openUrlExternally(licenseModel.get(cb.currentIndex).tldrlegal) } ToolTip { id: toolTip + text: licenseModel.get(cb.currentIndex).description } + } + } diff --git a/ScreenPlay/qml/Common/RippleEffect.qml b/ScreenPlay/qml/Common/RippleEffect.qml index f447075f..95c7833f 100644 --- a/ScreenPlay/qml/Common/RippleEffect.qml +++ b/ScreenPlay/qml/Common/RippleEffect.qml @@ -10,25 +10,33 @@ import QtQuick.Controls.Material 2.12 Item { id: root - anchors.fill: parent property alias radius: mask.radius - property color color: Material.accent + property color color: Material.accent property var target property int duration: 600 function trigger() { var wave = ripple.createObject(container, { - "startX": root.width * .5, - "startY": root.height * .5, - "maxRadius": furthestDistance( - root.width * .5, - root.height * .5) - }) + "startX": root.width * 0.5, + "startY": root.height * 0.5, + "maxRadius": furthestDistance(root.width * 0.5, root.height * 0.5) + }); } + function distance(x1, y1, x2, y2) { + return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); + } + + function furthestDistance(x, y) { + return Math.max(distance(x, y, 0, 0), distance(x, y, width, height), distance(x, y, 0, height), distance(x, y, width, 0)); + } + + anchors.fill: parent + Rectangle { id: mask + anchors.fill: parent color: "black" visible: false @@ -36,6 +44,7 @@ Item { Item { id: container + anchors.fill: parent visible: false } @@ -51,20 +60,34 @@ Item { Rectangle { id: ink - radius: 0 - opacity: 0.25 - color: root.color + property int startX property int startY property int maxRadius: 150 + function fadeIfApplicable() { + if (!fadeAnimation.running) + fadeAnimation.start(); + + } + + radius: 0 + opacity: 0.25 + color: root.color x: startX - radius y: startY - radius width: radius * 2 height: radius * 2 + Component.onCompleted: { + growAnimation.start(); + if (!fadeAnimation.running) + fadeAnimation.start(); + + } NumberAnimation { id: growAnimation + target: ink property: "radius" from: 0 @@ -75,6 +98,7 @@ Item { SequentialAnimation { id: fadeAnimation + NumberAnimation { target: ink property: "opacity" @@ -82,31 +106,15 @@ Item { to: 0 duration: root.duration } + ScriptAction { script: ink.destroy() } + } - Component.onCompleted: { - growAnimation.start() - if (!fadeAnimation.running) - fadeAnimation.start() - } - - function fadeIfApplicable() { - if (!fadeAnimation.running) - fadeAnimation.start() - } } + } - - function distance(x1,y1,x2,y2) { - return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) - } - - function furthestDistance(x,y) { - return Math.max(distance(x, y, 0, 0), distance(x, y, width, height), - distance(x, y, 0, height), distance(x, y, width, 0)) - } } diff --git a/ScreenPlay/qml/Common/Search.qml b/ScreenPlay/qml/Common/Search.qml index d3f82dba..1374a3a6 100644 --- a/ScreenPlay/qml/Common/Search.qml +++ b/ScreenPlay/qml/Common/Search.qml @@ -1,43 +1,50 @@ import QtQuick 2.0 import QtQuick.Controls 2.0 import QtQuick.Controls.Material 2.0 - import ScreenPlay 1.0 Item { - id:root + id: root + width: 300 ToolButton { id: icnSearch + icon.source: "qrc:/assets/icons/icon_search.svg" height: 30 width: 30 icon.width: 30 icon.height: 30 icon.color: Material.iconColor + anchors { right: parent.right verticalCenter: parent.verticalCenter } + } + TextField { id: txtSearch + width: 250 height: 40 + placeholderText: qsTr("Search for Wallpaper & Widgets") + onTextChanged: { + if (txtSearch.text.length === 0) + ScreenPlay.installedListFilter.resetFilter(); + else + ScreenPlay.installedListFilter.sortByName(txtSearch.text); + } + anchors { right: icnSearch.left rightMargin: 10 top: parent.top topMargin: 10 } - onTextChanged: { - if (txtSearch.text.length === 0) { - ScreenPlay.installedListFilter.resetFilter() - } else { - ScreenPlay.installedListFilter.sortByName(txtSearch.text) - } - } - placeholderText: qsTr("Search for Wallpaper & Widgets") + } + } diff --git a/ScreenPlay/qml/Common/Shake.qml b/ScreenPlay/qml/Common/Shake.qml index c94036d5..f17d0ee0 100644 --- a/ScreenPlay/qml/Common/Shake.qml +++ b/ScreenPlay/qml/Common/Shake.qml @@ -2,19 +2,20 @@ import QtQuick 2.12 Translate { id: root - function start(offset = 0, loopOffset = 1000, loops = 1) { - root.offset = offset - root.loopOffset = loopOffset - root.loops = loops - shake.restart() - } property int offset: 0 property int loops: 3 property int loopOffset: 1000 + property SequentialAnimation shake - property SequentialAnimation shake: SequentialAnimation { + function start(offset = 0, loopOffset = 1000, loops = 1) { + root.offset = offset; + root.loopOffset = loopOffset; + root.loops = loops; + shake.restart(); + } + shake: SequentialAnimation { loops: root.loops alwaysRunToEnd: true @@ -23,15 +24,15 @@ Translate { } SequentialAnimation { - PropertyAnimation { target: root property: "x" from: 0 to: 10 - duration: 50 + duration: 50 easing.type: Easing.InOutBounce } + PropertyAnimation { target: root property: "x" @@ -40,12 +41,13 @@ Translate { duration: 100 easing.type: Easing.InOutBounce } + PropertyAnimation { target: root property: "x" from: -10 to: 0 - duration: 50 + duration: 50 } PropertyAnimation { @@ -53,9 +55,10 @@ Translate { property: "x" from: 0 to: 10 - duration:50 + duration: 50 easing.type: Easing.InOutBounce } + PropertyAnimation { target: root property: "x" @@ -64,16 +67,21 @@ Translate { duration: 100 easing.type: Easing.InOutBounce } + PropertyAnimation { target: root property: "x" from: -10 to: 0 - duration: 50 + duration: 50 } + } + PauseAnimation { duration: root.loopOffset } + } + } diff --git a/ScreenPlay/qml/Common/Slider.qml b/ScreenPlay/qml/Common/Slider.qml index de0ed887..01cf17b7 100644 --- a/ScreenPlay/qml/Common/Slider.qml +++ b/ScreenPlay/qml/Common/Slider.qml @@ -6,14 +6,16 @@ import ScreenPlay 1.0 Item { id: root - height: 70 property string headline: "dummyHeandline" property string iconSource: "qrc:/assets/icons/icon_volume.svg" property alias slider: slider + height: 70 + Text { id: txtHeadline + text: headline height: 20 font.pointSize: 14 @@ -25,13 +27,14 @@ Item { right: parent.right left: parent.left } + } RowLayout { spacing: 30 + anchors { top: txtHeadline.bottom - right: parent.right bottom: parent.bottom left: parent.left @@ -39,6 +42,7 @@ Item { Image { id: imgIcon + width: 20 height: 20 source: iconSource @@ -48,6 +52,7 @@ Item { QQC.Slider { id: slider + stepSize: 0.01 from: 0 value: 1 @@ -58,6 +63,7 @@ Item { Text { id: txtValue + color: QQCM.Material.secondaryTextColor text: Math.round(slider.value * 100) / 100 Layout.alignment: Qt.AlignVCenter @@ -65,5 +71,7 @@ Item { font.italic: true verticalAlignment: Text.AlignVCenter } + } + } diff --git a/ScreenPlay/qml/Common/Tag.qml b/ScreenPlay/qml/Common/Tag.qml index 88e9cfcf..86379791 100644 --- a/ScreenPlay/qml/Common/Tag.qml +++ b/ScreenPlay/qml/Common/Tag.qml @@ -5,22 +5,25 @@ import ScreenPlay 1.0 Item { id: tag - width: textMetrics.width + 20 - height: 45 property int itemIndex property alias text: txt.text + signal removeThis(var index) + width: textMetrics.width + 20 + height: 45 + Rectangle { id: rectangle + anchors.fill: parent radius: 3 - color: Material.theme === Material.Light ? Qt.lighter( - Material.background) : Material.background + color: Material.theme === Material.Light ? Qt.lighter(Material.background) : Material.background Text { id: txt + text: _name color: Material.primaryTextColor verticalAlignment: Text.AlignVCenter @@ -31,6 +34,7 @@ Item { TextField { id: textField + enabled: false opacity: 0 anchors.fill: parent @@ -41,30 +45,37 @@ Item { TextMetrics { id: textMetrics + text: txt.text font.pointSize: 14 font.family: ScreenPlay.settings.font } + } + MouseArea { id: ma + width: 10 height: width cursorShape: Qt.PointingHandCursor + onClicked: { + tag.removeThis(itemIndex); + } + anchors { top: parent.top right: parent.right margins: 5 } - onClicked: { - tag.removeThis(itemIndex) - } Image { id: name + anchors.fill: parent source: "qrc:/assets/icons/icon_close.svg" } + } states: [ @@ -81,13 +92,7 @@ Item { opacity: 1 enabled: true } + } ] } - -/*##^## -Designer { - D{i:0;height:50;width:100} -} -##^##*/ - diff --git a/ScreenPlay/qml/Common/TagSelector.qml b/ScreenPlay/qml/Common/TagSelector.qml index 2be52ee9..4411e79f 100644 --- a/ScreenPlay/qml/Common/TagSelector.qml +++ b/ScreenPlay/qml/Common/TagSelector.qml @@ -2,36 +2,37 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.12 - import ScreenPlay 1.0 Item { id: root + + function getTags() { + var array = []; + for (var i = 0; i < listModel.count; i++) { + array.push(listModel.get(i)._name); + } + return array; + } + height: 70 implicitWidth: 200 onStateChanged: { if (root.state === "add") { - btnAdd.text = qsTr("Save") - textField.focus = true + btnAdd.text = qsTr("Save"); + textField.focus = true; } else { - btnAdd.text = qsTr("Add tag") + btnAdd.text = qsTr("Add tag"); } } - function getTags() { - var array = [] - for (var i = 0; i < listModel.count; i++) { - array.push(listModel.get(i)._name) - } - return array - } - Rectangle { id: rectangle - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) + + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) radius: 3 clip: true + anchors { fill: parent margins: 3 @@ -41,6 +42,7 @@ Item { orientation: ListView.Horizontal model: listModel spacing: 10 + anchors { top: parent.top right: btnAdd.left @@ -51,33 +53,37 @@ Item { delegate: Tag { id: delegate + text: _name itemIndex: index Connections { - target: delegate function onRemoveThis() { - listModel.remove(itemIndex) + listModel.remove(itemIndex); } + + target: delegate } + } + } ListModel { id: listModel + onCountChanged: getTags() } Rectangle { id: textFieldWrapper + opacity: 0 enabled: false radius: 3 height: parent.height - 20 width: 200 - color: Material.theme - === Material.Light ? Qt.lighter( - Material.background) : Material.background + color: Material.theme === Material.Light ? Qt.lighter(Material.background) : Material.background anchors { top: parent.top @@ -85,37 +91,44 @@ Item { right: btnCancel.left margins: 10 } + Gradient { GradientStop { - position: 0.0 + position: 0 color: "#00000000" } + GradientStop { - position: 1.0 + position: 1 color: "#FF000000" } + } TextField { id: textField + font.family: ScreenPlay.settings.font color: Material.primaryTextColor + onTextChanged: { + if (textField.length >= 10) + textField.text = textField.text; + + } + anchors { fill: parent rightMargin: 15 leftMargin: 15 } - onTextChanged: { - if (textField.length >= 10) { - textField.text = textField.text - } - } } + } Button { id: btnCancel + text: qsTr("Cancel") opacity: 0 height: parent.height - 20 @@ -123,46 +136,50 @@ Item { Material.background: Material.Red Material.foreground: "white" font.family: ScreenPlay.settings.font + onClicked: { + root.state = ""; + textField.clear(); + } + anchors { right: btnAdd.left rightMargin: 10 verticalCenter: parent.verticalCenter } - onClicked: { - root.state = "" - textField.clear() - } } + Button { id: btnAdd + text: qsTr("Add Tag") height: parent.height - 20 Material.background: Material.LightGreen Material.foreground: "white" font.family: ScreenPlay.settings.font + onClicked: { + if (root.state === "add") { + listModel.append({ + "_name": textField.text + }); + textField.clear(); + root.state = ""; + } else { + root.state = "add"; + } + } + anchors { right: parent.right rightMargin: 10 verticalCenter: parent.verticalCenter } - onClicked: { - if (root.state === "add") { - listModel.append({ - "_name": textField.text - }) - textField.clear() - root.state = "" - } else { - root.state = "add" - } - } } + } states: [ - State { name: "add" @@ -178,6 +195,7 @@ Item { opacity: 1 enabled: true } + } ] transitions: [ @@ -185,11 +203,13 @@ Item { from: "" to: "add" reversible: true + NumberAnimation { properties: "anchors.topMargin, opacity" duration: 200 easing.type: Easing.OutQuart } + } ] } diff --git a/ScreenPlay/qml/Common/TextField.qml b/ScreenPlay/qml/Common/TextField.qml index f72dc9d3..ff916f4e 100644 --- a/ScreenPlay/qml/Common/TextField.qml +++ b/ScreenPlay/qml/Common/TextField.qml @@ -8,132 +8,143 @@ import ScreenPlay 1.0 Item { id: root - height: 55 - width: 150 - - state: { - if (textField.text.length > 0) { - return "containsTextEditingFinished" - } else { - return "" - } - } - - signal editingFinished - onEditingFinished: { - if (!root.required) - return - } property bool required: false property bool dirty: false property alias text: textField.text property alias placeholderText: txtPlaceholder.text + signal editingFinished() + + height: 55 + width: 150 + state: { + if (textField.text.length > 0) + return "containsTextEditingFinished"; + else + return ""; + } + onEditingFinished: { + if (!root.required) + return ; + + } + Text { id: txtPlaceholder + text: qsTr("Label") font.family: ScreenPlay.settings.font color: Material.primaryTextColor - opacity: .4 + opacity: 0.4 font.pointSize: 11 font.weight: Font.Medium + anchors { top: parent.top topMargin: 15 left: parent.left leftMargin: 10 } + } Timer { id: timerSaveDelay + interval: 1000 onTriggered: root.editingFinished() } QQC.TextField { id: textField + + function resetState() { + if (textField.text.length === 0) + root.state = ""; + + textField.focus = false; + } + font.family: ScreenPlay.settings.font color: Material.secondaryTextColor width: parent.width Keys.onEscapePressed: resetState() onTextEdited: { - timerSaveDelay.start() - root.dirty = true + timerSaveDelay.start(); + root.dirty = true; } + onEditingFinished: { + resetState(); + if (textField.text.length > 0) + root.state = "containsTextEditingFinished"; + + } + onPressed: { + root.state = "containsText"; + } + anchors { left: parent.left right: parent.right bottom: parent.bottom } - onEditingFinished: { - resetState() - if (textField.text.length > 0) { - root.state = "containsTextEditingFinished" - } - } - - function resetState() { - if (textField.text.length === 0) { - root.state = "" - } - textField.focus = false - } - - onPressed: { - root.state = "containsText" - } } Text { id: requiredText + text: qsTr("*Required") visible: root.required font.family: ScreenPlay.settings.font color: Material.secondaryTextColor + anchors { top: textField.bottom right: textField.right } + } states: [ State { name: "" + PropertyChanges { target: txtPlaceholder font.pointSize: 11 color: Material.secondaryTextColor - anchors.topMargin: 15 anchors.leftMargin: 10 } + }, State { name: "containsText" + PropertyChanges { target: txtPlaceholder font.pointSize: 8 opacity: 1 color: Material.accentColor - anchors.topMargin: 0 anchors.leftMargin: 0 } + }, State { name: "containsTextEditingFinished" + PropertyChanges { target: txtPlaceholder font.pointSize: 8 color: Material.secondaryTextColor opacity: 0.4 - anchors.topMargin: 0 anchors.leftMargin: 0 } + } ] transitions: [ @@ -141,23 +152,27 @@ Item { from: "" to: "containsText" reversible: true + PropertyAnimation { target: txtPlaceholder duration: 150 easing.type: Easing.InOutQuart properties: "font.pointSize,anchors.topMargin,anchors.leftMargin,opacity,color" } + }, Transition { from: "containsText" to: "containsTextEditingFinished" reversible: true + PropertyAnimation { target: txtPlaceholder duration: 150 easing.type: Easing.OutSine properties: "color,opacity" } + } ] } diff --git a/ScreenPlay/qml/Common/TrayIcon.qml b/ScreenPlay/qml/Common/TrayIcon.qml index a7eb721e..b3f3d16b 100644 --- a/ScreenPlay/qml/Common/TrayIcon.qml +++ b/ScreenPlay/qml/Common/TrayIcon.qml @@ -4,22 +4,23 @@ import ScreenPlay 1.0 SystemTrayIcon { id: root + visible: true iconSource: "qrc:/assets/icons/app.ico" tooltip: qsTr("ScreenPlay - Double click to change you settings.") onActivated: { switch (reason) { case SystemTrayIcon.Unknown: - break + break; case SystemTrayIcon.Context: - break + break; case SystemTrayIcon.DoubleClick: - window.show() - break + window.show(); + break; case SystemTrayIcon.Trigger: - break + break; case SystemTrayIcon.MiddleClick: - break + break; } } @@ -27,48 +28,53 @@ SystemTrayIcon { MenuItem { text: qsTr("Open ScreenPlay") onTriggered: { - window.show() + window.show(); } } + MenuItem { id: miMuteAll + property bool isMuted: true + text: qsTr("Mute all") onTriggered: { if (miMuteAll.isMuted) { - isMuted = false - miMuteAll.text = qsTr("Mute all") - ScreenPlay.screenPlayManager.setAllWallpaperValue( - "muted", "true") + isMuted = false; + miMuteAll.text = qsTr("Mute all"); + ScreenPlay.screenPlayManager.setAllWallpaperValue("muted", "true"); } else { - isMuted = true - miMuteAll.text = qsTr("Unmute all") - ScreenPlay.screenPlayManager.setAllWallpaperValue( - "muted", "false") + isMuted = true; + miMuteAll.text = qsTr("Unmute all"); + ScreenPlay.screenPlayManager.setAllWallpaperValue("muted", "false"); } } } + MenuItem { id: miStopAll + property bool isPlaying: false + text: qsTr("Pause all") onTriggered: { if (miStopAll.isPlaying) { - isPlaying = false - miStopAll.text = qsTr("Pause all") - ScreenPlay.screenPlayManager.setAllWallpaperValue( - "isPlaying", "true") + isPlaying = false; + miStopAll.text = qsTr("Pause all"); + ScreenPlay.screenPlayManager.setAllWallpaperValue("isPlaying", "true"); } else { - isPlaying = true - miStopAll.text = qsTr("Play all") - ScreenPlay.screenPlayManager.setAllWallpaperValue( - "isPlaying", "false") + isPlaying = true; + miStopAll.text = qsTr("Play all"); + ScreenPlay.screenPlayManager.setAllWallpaperValue("isPlaying", "false"); } } } + MenuItem { text: qsTr("Quit") onTriggered: ScreenPlay.exit() } + } + } diff --git a/ScreenPlay/qml/Community/Community.qml b/ScreenPlay/qml/Community/Community.qml index fdbb5dde..fa1dd970 100644 --- a/ScreenPlay/qml/Community/Community.qml +++ b/ScreenPlay/qml/Community/Community.qml @@ -11,18 +11,22 @@ Item { Rectangle { id: navWrapper + color: Material.theme === Material.Light ? "white" : Material.background height: 50 + anchors { top: parent.top right: parent.right left: parent.left } + TabBar { id: nav + height: parent.height currentIndex: 0 - background: Item {} + anchors { top: parent.top left: parent.left @@ -47,108 +51,138 @@ Item { openLink: "https://forum.screen-play.app/" icon.source: "qrc:/assets/icons/icon_forum.svg" } + CommunityNavItem { text: qsTr("Issue List") openLink: "https://gitlab.com/kelteseth/ScreenPlay/-/issues" icon.source: "qrc:/assets/icons/icon_report_problem.svg" } + CommunityNavItem { text: qsTr("Contribute") openLink: "https://gitlab.com/kelteseth/ScreenPlay#general-contributing" icon.source: "qrc:/assets/icons/icon_supervisor_account.svg" } + CommunityNavItem { text: qsTr("Steam Workshop") openLink: "steam://url/GameHub/672870" icon.source: "qrc:/assets/icons/icon_steam.svg" } + + background: Item { + } + } + } LinearGradient { height: 6 z: 99 + start: Qt.point(0, 0) + end: Qt.point(0, 6) + anchors { top: navWrapper.bottom left: parent.left right: parent.right } - start: Qt.point(0, 0) - end: Qt.point(0, 6) gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#33333333" } + GradientStop { - position: 1.0 + position: 1 color: "transparent" } + } + } SwipeView { id: swipeView + currentIndex: nav.currentIndex + anchors { top: navWrapper.bottom right: parent.right bottom: parent.bottom left: parent.left } - XMLNewsfeed { + XMLNewsfeed { } Repeater { id: repeater - model: ListModel { - id: webModel - ListElement { - url: "https://screen-play.app/blog/" - } - ListElement { - url: "https://kelteseth.gitlab.io/ScreenPlayDocs/" - } - ListElement { - url: "https://forum.screen-play.app/" - } - ListElement { - url: "https://gitlab.com/kelteseth/ScreenPlay/-/issues" - } - ListElement { - url: "https://gitlab.com/kelteseth/ScreenPlay#general-contributing" - } - ListElement { - url: "https://steamcommunity.com/app/672870/workshop/" - } - } Loader { - active: SwipeView.isCurrentItem || SwipeView.isNextItem - || SwipeView.isPreviousItem + active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem asynchronous: true + sourceComponent: Item { Component.onCompleted: timer.start() + Timer { id: timer + interval: 200 - onTriggered: webView.url = webModel.get(index +1).url + onTriggered: webView.url = webModel.get(index + 1).url } WebEngineView { id: webView + anchors.fill: parent } + } + } + + model: ListModel { + id: webModel + + ListElement { + url: "https://screen-play.app/blog/" + } + + ListElement { + url: "https://kelteseth.gitlab.io/ScreenPlayDocs/" + } + + ListElement { + url: "https://forum.screen-play.app/" + } + + ListElement { + url: "https://gitlab.com/kelteseth/ScreenPlay/-/issues" + } + + ListElement { + url: "https://gitlab.com/kelteseth/ScreenPlay#general-contributing" + } + + ListElement { + url: "https://steamcommunity.com/app/672870/workshop/" + } + + } + } + } - Binding{ + Binding { target: nav property: "currentIndex" value: swipeView.currentIndex } + } diff --git a/ScreenPlay/qml/Community/CommunityNavItem.qml b/ScreenPlay/qml/Community/CommunityNavItem.qml index ec451730..0de84736 100644 --- a/ScreenPlay/qml/Community/CommunityNavItem.qml +++ b/ScreenPlay/qml/Community/CommunityNavItem.qml @@ -5,30 +5,35 @@ import ScreenPlay 1.0 TabButton { id: control - height: parent.height + property url openLink + height: parent.height + contentItem: Item { anchors.fill: parent ToolButton { icon.source: control.icon.source - anchors { - right: txt.left - verticalCenter: txt.verticalCenter - } icon.color: control.checked ? Material.accentColor : Material.secondaryTextColor hoverEnabled: false icon.width: 16 icon.height: 16 enabled: false + + anchors { + right: txt.left + verticalCenter: txt.verticalCenter + } + } Text { id: txt + text: control.text font.family: ScreenPlay.settings.font - opacity: enabled ? 1.0 : 0.3 + opacity: enabled ? 1 : 0.3 color: control.checked ? Material.accentColor : Material.primaryTextColor horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight @@ -40,32 +45,28 @@ TabButton { } ToolButton { + opacity: 0.6 + width: parent.width * 0.2 + icon.source: "qrc:/assets/icons/icon_open_in_new.svg" + icon.width: 16 + icon.height: 16 + onClicked: Qt.openUrlExternally(control.openLink) + ToolTip.delay: 500 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + ToolTip.text: qsTr("Open in browser") + anchors { top: parent.top topMargin: 15 right: parent.right } - opacity: 0.6 - width: parent.width * .2 - icon.source: "qrc:/assets/icons/icon_open_in_new.svg" - icon.width: 16 - icon.height: 16 - onClicked: Qt.openUrlExternally(control.openLink) - - ToolTip.delay: 500 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - ToolTip.text: qsTr("Open in browser") } + } - background: Item {} -} + background: Item { + } -/*##^## -Designer { - D{i:0;height:60;width:300} } -##^##*/ - diff --git a/ScreenPlay/qml/Community/XMLNewsfeed.qml b/ScreenPlay/qml/Community/XMLNewsfeed.qml index 1a19a152..05f42e4b 100644 --- a/ScreenPlay/qml/Community/XMLNewsfeed.qml +++ b/ScreenPlay/qml/Community/XMLNewsfeed.qml @@ -11,14 +11,15 @@ Item { GridView { id: changelogFlickableWrapper + flickableDirection: Flickable.VerticalFlick maximumFlickVelocity: 5000 flickDeceleration: 5000 cellHeight: 250 cellWidth: 450 clip: true - model: feedModel + anchors { top: parent.top right: parent.right @@ -29,28 +30,35 @@ Item { XmlListModel { id: feedModel + source: "https://screen-play.app/blog/index.xml" query: "/rss/channel/item" + XmlRole { name: "title" query: "title/string()" } + XmlRole { name: "image" query: "image/string()" } + XmlRole { name: "pubDate" query: "pubDate/string()" } + XmlRole { name: "link" query: "link/string()" } + XmlRole { name: "description" query: "description/string()" } + } header: Item { @@ -59,10 +67,10 @@ Item { Text { id: name + text: qsTr("News & Patchnotes") wrapMode: Text.WordWrap color: Material.primaryTextColor - verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.pointSize: 32 @@ -74,11 +82,14 @@ Item { topMargin: 30 horizontalCenter: parent.horizontalCenter } + } + } delegate: Item { id: delegate + width: changelogFlickableWrapper.cellWidth - 20 height: changelogFlickableWrapper.cellHeight - 20 @@ -90,38 +101,51 @@ Item { Image { id: img + asynchronous: true anchors.fill: parent fillMode: Image.PreserveAspectCrop source: image opacity: status === Image.Ready ? 1 : 0 + Behavior on opacity { PropertyAnimation { duration: 250 } + } + } LinearGradient { anchors.fill: parent - start: Qt.point(0, 0) end: Qt.point(0, parent.height) + gradient: Gradient { GradientStop { - position: 1.0 + position: 1 color: "#ee111111" } + GradientStop { - position: 0.0 + position: 0 color: "transparent" } + } + } Text { id: txtTitle + text: title + color: Material.primaryTextColor + font.family: ScreenPlay.settings.font + font.weight: Font.Normal + font.pointSize: 14 + wrapMode: Text.WordWrap anchors { right: parent.right @@ -129,16 +153,18 @@ Item { left: parent.left margins: 20 } - color: Material.primaryTextColor - font.family: ScreenPlay.settings.font - font.weight: Font.Normal - font.pointSize: 14 - wrapMode: Text.WordWrap + } Text { id: txtPubDate + text: pubDate + color: Material.primaryTextColor + font.family: ScreenPlay.settings.font + font.pointSize: 8 + wrapMode: Text.WordWrap + anchors { right: parent.right rightMargin: 20 @@ -147,11 +173,7 @@ Item { left: parent.left leftMargin: 20 } - color: Material.primaryTextColor - font.family: ScreenPlay.settings.font - font.pointSize: 8 - wrapMode: Text.WordWrap } MouseArea { @@ -162,7 +184,9 @@ Item { onEntered: delegate.state = "hover" onExited: delegate.state = "" } + } + transitions: [ Transition { from: "" @@ -174,6 +198,7 @@ Item { from: 1 to: 1.05 } + }, Transition { from: "hover" @@ -185,6 +210,7 @@ Item { from: 1.05 to: 1 } + } ] } @@ -193,5 +219,7 @@ Item { snapMode: ScrollBar.SnapOnRelease policy: ScrollBar.AlwaysOn } + } + } diff --git a/ScreenPlay/qml/Create/Create.qml b/ScreenPlay/qml/Create/Create.qml index 2c68704f..28d34e07 100644 --- a/ScreenPlay/qml/Create/Create.qml +++ b/ScreenPlay/qml/Create/Create.qml @@ -4,9 +4,7 @@ import QtQuick.Layouts 1.12 import QtQuick.Controls.Material 2.12 import QtQuick.Particles 2.0 import QtGraphicalEffects 1.0 - import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 import ScreenPlay.QMLUtilities 1.0 @@ -15,25 +13,30 @@ Item { id: root Component.onCompleted: { - wizardContentWrapper.state = "in" - stackView.push("qrc:/qml/Create/StartInfo.qml") + wizardContentWrapper.state = "in"; + stackView.push("qrc:/qml/Create/StartInfo.qml"); } Sidebar { id: sidebar + stackView: stackView + anchors { top: parent.top left: parent.left bottom: parent.bottom } + } Item { id: wizardContentWrapper + width: parent.width - (sidebar.width + (anchors.margins * 2)) height: parent.height - (anchors.margins * 2) opacity: 0 + anchors { margins: 10 top: parent.top @@ -44,10 +47,8 @@ Item { Rectangle { radius: 4 layer.enabled: true - layer.effect: ElevationEffect { - elevation: 6 - } color: Material.theme === Material.Light ? "white" : Material.background + anchors { fill: parent margins: 10 @@ -55,6 +56,12 @@ Item { StackView { id: stackView + + anchors { + fill: parent + margins: 20 + } + pushEnter: Transition { PropertyAnimation { property: "opacity" @@ -63,6 +70,7 @@ Item { duration: 400 easing.type: Easing.InOutQuart } + PropertyAnimation { property: "scale" from: 0.8 @@ -70,6 +78,7 @@ Item { duration: 400 easing.type: Easing.InOutQuart } + } pushExit: Transition { @@ -84,27 +93,31 @@ Item { PropertyAnimation { property: "scale" from: 1 - to: .8 + to: 0.8 duration: 400 easing.type: Easing.InOutQuart } + } - anchors { - fill: parent - margins: 20 - } } + + layer.effect: ElevationEffect { + elevation: 6 + } + } states: [ State { name: "in" + PropertyChanges { target: wizardContentWrapper anchors.topMargin: wizardContentWrapper.anchors.margins opacity: 1 } + } ] transitions: [ @@ -112,8 +125,8 @@ Item { from: "" to: "in" reversible: true - SequentialAnimation { + SequentialAnimation { PropertyAnimation { target: wizardContentWrapper duration: 400 @@ -123,17 +136,14 @@ Item { ScriptAction { script: { - wizardContentWrapper.anchors.left = sidebar.right + wizardContentWrapper.anchors.left = sidebar.right; } } + } + } ] } -} -/*##^## Designer { - D{i:0;autoSize:true;height:768;width:1366} } - ##^##*/ - diff --git a/ScreenPlay/qml/Create/Sidebar.qml b/ScreenPlay/qml/Create/Sidebar.qml index acfe233f..1cd64fb1 100644 --- a/ScreenPlay/qml/Create/Sidebar.qml +++ b/ScreenPlay/qml/Create/Sidebar.qml @@ -4,92 +4,27 @@ import QtQuick.Layouts 1.12 import QtQuick.Controls.Material 2.12 import QtQuick.Particles 2.0 import QtGraphicalEffects 1.0 - import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 import ScreenPlay.QMLUtilities 1.0 Rectangle { id: root - width: 350 - state: expanded ? "" : "inactive" - layer.enabled: true - layer.effect: ElevationEffect { - elevation: 6 - } - property bool expanded: false - Component.onCompleted: expanded = true - color: Material.background + property bool expanded: false property alias listView: listView property alias model: listView.model property StackView stackView + width: 350 + state: expanded ? "" : "inactive" + layer.enabled: true + Component.onCompleted: expanded = true + color: Material.background + ListView { - id: listView - anchors.fill: parent - anchors.margins: 20 - spacing: 5 - model: ListModel { - - ListElement { - headline: qsTr("Tools Overview") - source: "qrc:/qml/Create/StartInfo.qml" - category: "Home" - } - - ListElement { - headline: "Video import and convert (all types)" - source: "qrc:/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml" - category: "Video Wallpaper" - } - - ListElement { - headline: qsTr("Video Import (.webm)") - source: "qrc:/qml/Create/Wizards/ImportWebm/ImportWebm.qml" - category: "Video Wallpaper" - } - - ListElement { - headline: qsTr("GIF Wallpaper") - source: "qrc:/qml/Create/Wizards/GifWallpaper.qml" - category: "Video Wallpaper" - } - - ListElement { - headline: qsTr("QML Wallpaper") - source: "qrc:/qml/Create/Wizards/QMLWallpaper.qml" - category: "Code Wallpaper" - } - - ListElement { - headline: qsTr("HTML5 Wallpaper") - source: "qrc:/qml/Create/Wizards/HTMLWallpaper.qml" - category: "Code Wallpaper" - } - - ListElement { - headline: qsTr("Website Wallpaper") - source: "qrc:/qml/Create/Wizards/WebsiteWallpaper.qml" - category: "Code Wallpaper" - } - - ListElement { - headline: qsTr("QML Widget") - source: "qrc:/qml/Create/Wizards/QMLWidget.qml" - category: "Code Widgets" - } - - ListElement { - headline: qsTr("HTML Widget") - source: "qrc:/qml/Create/Wizards/HTMLWidget.qml" - category: "Code Widgets" - } - - - /* + /* ListElement { headline: qsTr("QML Particle Wallpaper") source: "" @@ -150,75 +85,152 @@ Rectangle { category: "Example Widget" } */ + + id: listView + + anchors.fill: parent + anchors.margins: 20 + spacing: 5 + section.property: "category" + + Connections { + id: loaderConnections + + function onWizardStarted() { + root.expanded = false; + } + + function onWizardExited() { + root.expanded = true; + stackView.clear(StackView.PushTransition); + stackView.push("qrc:/qml/Create/StartInfo.qml"); + listView.currentIndex = 0; + ScreenPlay.util.setNavigationActive(true); + } + + ignoreUnknownSignals: true + } + + model: ListModel { + ListElement { + headline: qsTr("Tools Overview") + source: "qrc:/qml/Create/StartInfo.qml" + category: "Home" + } + + ListElement { + headline: "Video import and convert (all types)" + source: "qrc:/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml" + category: "Video Wallpaper" + } + + ListElement { + headline: qsTr("Video Import (.webm)") + source: "qrc:/qml/Create/Wizards/ImportWebm/ImportWebm.qml" + category: "Video Wallpaper" + } + + ListElement { + headline: qsTr("GIF Wallpaper") + source: "qrc:/qml/Create/Wizards/GifWallpaper.qml" + category: "Video Wallpaper" + } + + ListElement { + headline: qsTr("QML Wallpaper") + source: "qrc:/qml/Create/Wizards/QMLWallpaper.qml" + category: "Code Wallpaper" + } + + ListElement { + headline: qsTr("HTML5 Wallpaper") + source: "qrc:/qml/Create/Wizards/HTMLWallpaper.qml" + category: "Code Wallpaper" + } + + ListElement { + headline: qsTr("Website Wallpaper") + source: "qrc:/qml/Create/Wizards/WebsiteWallpaper.qml" + category: "Code Wallpaper" + } + + ListElement { + headline: qsTr("QML Widget") + source: "qrc:/qml/Create/Wizards/QMLWidget.qml" + category: "Code Widgets" + } + + ListElement { + headline: qsTr("HTML Widget") + source: "qrc:/qml/Create/Wizards/HTMLWidget.qml" + category: "Code Widgets" + } + } ScrollBar.vertical: ScrollBar { snapMode: ScrollBar.SnapOnRelease policy: ScrollBar.AsNeeded } - section.property: "category" + section.delegate: Item { height: 60 + Text { + font.pointSize: 18 + color: Material.primaryTextColor + text: section + anchors { bottom: parent.bottom left: parent.left bottomMargin: 10 } - font.pointSize: 18 - color: Material.primaryTextColor - text: section } - } - Connections { - id: loaderConnections - ignoreUnknownSignals: true - function onWizardStarted() { - root.expanded = false - } - function onWizardExited() { - root.expanded = true - - stackView.clear(StackView.PushTransition) - stackView.push("qrc:/qml/Create/StartInfo.qml") - listView.currentIndex = 0 - - ScreenPlay.util.setNavigationActive(true) - } } delegate: Button { id: listItem + width: listView.width - 40 height: 45 highlighted: ListView.isCurrentItem - onClicked: { - listView.currentIndex = index - const item = stackView.push(source) - loaderConnections.target = item - } text: headline + onClicked: { + listView.currentIndex = index; + const item = stackView.push(source); + loaderConnections.target = item; + } } + + } + + layer.effect: ElevationEffect { + elevation: 6 } states: [ State { name: "" + PropertyChanges { target: root anchors.leftMargin: 0 opacity: 1 } + }, State { name: "inactive" + PropertyChanges { target: root opacity: 0 anchors.leftMargin: -root.width } + } ] transitions: [ @@ -226,17 +238,20 @@ Rectangle { from: "" to: "inactive" reversible: true - SequentialAnimation { + SequentialAnimation { PauseAnimation { duration: 100 } + PropertyAnimation { properties: "anchors.leftMargin,opacity" duration: 300 easing.type: Easing.OutCubic } + } + } ] } diff --git a/ScreenPlay/qml/Create/StartInfo.qml b/ScreenPlay/qml/Create/StartInfo.qml index 0aa2173f..6b14d0d8 100644 --- a/ScreenPlay/qml/Create/StartInfo.qml +++ b/ScreenPlay/qml/Create/StartInfo.qml @@ -5,11 +5,9 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Particles 2.0 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 import ScreenPlay.QMLUtilities 1.0 - import "../Common" as Common Item { @@ -17,31 +15,45 @@ Item { Common.Headline { id: headline + text: qsTr("Free Tools to create wallpaper") + anchors { top: parent.top right: parent.right left: parent.left margins: 20 } + } Text { id: introText + color: Material.primaryTextColor + font.pointSize: 12 + font.family: ScreenPlay.settings.font + text: qsTr("Below you can find tools to create wallaper beyond the tools that ScreenPlay provides for you!") + anchors { top: headline.bottom right: parent.right left: parent.left margins: 20 } - font.pointSize: 12 - font.family: ScreenPlay.settings.font - text: qsTr("Below you can find tools to create wallaper beyond the tools that ScreenPlay provides for you!") + } GridView { id: gridView + + boundsBehavior: Flickable.DragOverBounds + maximumFlickVelocity: 2500 + flickDeceleration: 500 + clip: true + cellWidth: 186 + cellHeight: 280 + anchors { top: introText.bottom right: parent.right @@ -49,15 +61,11 @@ Item { left: parent.left margins: 20 } - boundsBehavior: Flickable.DragOverBounds - maximumFlickVelocity: 2500 - flickDeceleration: 500 - clip: true - cellWidth: 186 - cellHeight: 280 + ScrollBar.vertical: ScrollBar { snapMode: ScrollBar.SnapOnRelease } + model: ListModel { ListElement { text: "Subreddit" @@ -66,6 +74,7 @@ Item { description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." category: "Community" } + ListElement { text: "Forums" image: "qrc:/assets/startinfo/forums.png" @@ -73,6 +82,7 @@ Item { description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." category: "Community" } + ListElement { text: "QML Online Editor" image: "qrc:/assets/startinfo/qml_online.png" @@ -80,6 +90,7 @@ Item { description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." category: "Tools" } + ListElement { text: "Godot" image: "qrc:/assets/startinfo/godot.png" @@ -87,6 +98,7 @@ Item { description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." category: "Tools" } + ListElement { text: "Handbreak" image: "qrc:/assets/startinfo/handbreak.png" @@ -94,6 +106,7 @@ Item { description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cum sociis natoque penatibus et magnis dis parturient montes," category: "Tools" } + ListElement { text: "Blender" image: "qrc:/assets/startinfo/blender.png" @@ -101,6 +114,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "OBS Studio" image: "qrc:/assets/startinfo/obs.png" @@ -108,6 +122,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Krita" image: "qrc:/assets/startinfo/krita.png" @@ -115,6 +130,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Gimp" image: "qrc:/assets/startinfo/gimp.png" @@ -122,6 +138,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Inscape" image: "qrc:/assets/startinfo/inkscape.png" @@ -129,6 +146,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Kdenlive" image: "qrc:/assets/startinfo/kdeenlive.png" @@ -136,6 +154,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "ShareX" image: "qrc:/assets/startinfo/sharex.png" @@ -143,6 +162,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "GitLab" image: "qrc:/assets/startinfo/gitlab.png" @@ -150,6 +170,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Git Extensions - Git UI for Windows" image: "qrc:/assets/startinfo/git_extentions.png" @@ -157,6 +178,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Visual Studio Code" image: "qrc:/assets/startinfo/vscode.png" @@ -164,6 +186,7 @@ Item { description: "" category: "Tools" } + ListElement { text: "Shadertoy" image: "qrc:/assets/startinfo/shadertoy.png" @@ -171,6 +194,7 @@ Item { description: "" category: "Resources" } + ListElement { text: "Flaticon" image: "qrc:/assets/startinfo/flaticon.png" @@ -178,6 +202,7 @@ Item { description: "" category: "Resources" } + ListElement { text: "Unsplash" image: "qrc:/assets/startinfo/unsplash.png" @@ -185,6 +210,7 @@ Item { description: "" category: "Resources" } + ListElement { text: "FreeSound" image: "qrc:/assets/startinfo/freesound.png" @@ -192,10 +218,12 @@ Item { description: "" category: "Resources" } + } delegate: StartInfoLinkImage { id: delegate + image: model.image category: model.category + ":" description: model.description @@ -204,5 +232,7 @@ Item { width: gridView.cellWidth height: gridView.cellHeight } + } + } diff --git a/ScreenPlay/qml/Create/StartInfoLinkImage.qml b/ScreenPlay/qml/Create/StartInfoLinkImage.qml index 7dd210c3..43bc3185 100644 --- a/ScreenPlay/qml/Create/StartInfoLinkImage.qml +++ b/ScreenPlay/qml/Create/StartInfoLinkImage.qml @@ -5,11 +5,9 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Particles 2.0 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 import ScreenPlay.QMLUtilities 1.0 - import "../Common" as Common Item { @@ -23,16 +21,15 @@ Item { Rectangle { id: img + anchors.fill: parent anchors.margins: 5 clip: true layer.enabled: true - layer.effect: ElevationEffect { - elevation: 4 - } Image { id: image + anchors.fill: parent fillMode: Image.PreserveAspectCrop } @@ -40,23 +37,30 @@ Item { LinearGradient { anchors.fill: parent end: Qt.point(0, 0) - start: Qt.point(0, parent.height * .66) + start: Qt.point(0, parent.height * 0.66) + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#DD000000" } + GradientStop { - position: 1.0 + position: 1 color: "#00000000" } + } + } + Text { id: txtCategory + font.pointSize: 10 font.family: ScreenPlay.settings.font color: "white" + anchors { left: parent.left right: parent.right @@ -64,9 +68,12 @@ Item { margins: 15 bottomMargin: 5 } + } + Text { id: txtText + font.pointSize: 16 font.family: ScreenPlay.settings.font color: "white" @@ -78,10 +85,12 @@ Item { bottom: parent.bottom margins: 15 } + } Rectangle { color: Material.backgroundDimColor + anchors { top: img.bottom right: parent.right @@ -91,15 +100,20 @@ Item { Text { id: description + font.pointSize: 14 font.family: ScreenPlay.settings.font color: Material.primaryTextColor + anchors { fill: parent margins: 5 } + } + } + MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor @@ -107,8 +121,12 @@ Item { onClicked: Qt.openUrlExternally(delegate.link) onEntered: delegate.state = "hover" onExited: delegate.state = "" - } + + layer.effect: ElevationEffect { + elevation: 4 + } + } transitions: [ @@ -122,6 +140,7 @@ Item { from: 1 to: 1.05 } + }, Transition { from: "hover" @@ -133,6 +152,7 @@ Item { from: 1.05 to: 1 } + } ] } diff --git a/ScreenPlay/qml/Create/Wizard.qml b/ScreenPlay/qml/Create/Wizard.qml index a87e9739..d3f9bd55 100644 --- a/ScreenPlay/qml/Create/Wizard.qml +++ b/ScreenPlay/qml/Create/Wizard.qml @@ -1,25 +1,23 @@ -import QtQuick 2.12 +import QtQuick 2.12 import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.3 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../Common" Item { id: root - anchors.fill: parent - state: "out" function setSource(path, arguments) { - loader_wrapperContent.setSource(path, arguments) - - root.state = "in" + loader_wrapperContent.setSource(path, arguments); + root.state = "in"; } + anchors.fill: parent + state: "out" + //Blocks some MouseArea from create page MouseArea { anchors.fill: parent @@ -27,12 +25,6 @@ Item { RectangularGlow { id: effect - anchors { - top: wrapper.top - left: wrapper.left - right: wrapper.right - topMargin: 3 - } height: wrapper.height width: wrapper.width @@ -42,21 +34,31 @@ Item { color: "black" opacity: 0.4 cornerRadius: 15 + + anchors { + top: wrapper.top + left: wrapper.left + right: wrapper.right + topMargin: 3 + } + } Rectangle { id: wrapper - color: Material.theme === Material.Light ? "white" : Material.background - width: { - if (parent.width < 1200) { - return parent.width - 20 // Add small margin left and right - } else { - return 1200 - } - } + color: Material.theme === Material.Light ? "white" : Material.background height: 580 radius: 4 + width: { + // Add small margin left and right + + if (parent.width < 1200) + return parent.width - 20; + else + return 1200; + } + anchors { horizontalCenter: parent.horizontalCenter top: parent.top @@ -65,165 +67,192 @@ Item { Loader { id: loader_wrapperContent + anchors.fill: parent } CloseIcon { onClicked: { - timerBack.start() + timerBack.start(); } + Timer { id: timerBack + interval: 400 onTriggered: { - ScreenPlay.util.setNavigationActive(true) - ScreenPlay.util.setNavigation("Create") + ScreenPlay.util.setNavigationActive(true); + ScreenPlay.util.setNavigation("Create"); } } + } + } states: [ State { name: "out" + PropertyChanges { target: wrapper anchors.topMargin: 800 opacity: 0 } + PropertyChanges { target: effect opacity: 0 } + }, State { name: "in" + PropertyChanges { target: wrapper - anchors.topMargin: { - if (root.height < 650) { - return 20 - } else { - return 70 - } - } - opacity: 1 + anchors.topMargin: { + if (root.height < 650) + return 20; + else + return 70; + } } + PropertyChanges { target: effect - opacity: .4 + opacity: 0.4 } + }, State { name: "error" + PropertyChanges { target: wrapper anchors.topMargin: 100 opacity: 1 } + PropertyChanges { target: effect - opacity: .4 + opacity: 0.4 } + PropertyChanges { target: loader_wrapperContent opacity: 1 z: 1 } + }, State { name: "success" + PropertyChanges { target: wrapper anchors.topMargin: 100 opacity: 1 } + PropertyChanges { target: effect - opacity: .4 + opacity: 0.4 } + PropertyChanges { target: loader_wrapperContent opacity: 0 z: 0 } + } ] - transitions: [ Transition { from: "out" to: "in" - SequentialAnimation { + SequentialAnimation { PauseAnimation { duration: 400 } - ParallelAnimation { + ParallelAnimation { PropertyAnimation { target: wrapper duration: 600 property: "anchors.topMargin" easing.type: Easing.OutQuart } + PropertyAnimation { target: wrapper duration: 600 property: "opacity" easing.type: Easing.OutQuart } - SequentialAnimation { + SequentialAnimation { PauseAnimation { duration: 1000 } + PropertyAnimation { target: effect duration: 300 property: "opacity" easing.type: Easing.OutQuart } + } + } + } + }, Transition { from: "in" to: "out" ParallelAnimation { - PropertyAnimation { target: wrapper duration: 600 property: "anchors.topMargin" easing.type: Easing.OutQuart } + PropertyAnimation { target: wrapper duration: 600 property: "opacity" easing.type: Easing.OutQuart } - SequentialAnimation { + SequentialAnimation { PauseAnimation { duration: 500 } + PropertyAnimation { target: effect duration: 300 property: "opacity" easing.type: Easing.OutQuart } + } + } + }, Transition { from: "in" to: "error" + SequentialAnimation { PropertyAnimation { target: loader_wrapperContent @@ -231,10 +260,13 @@ Item { property: "opacity" easing.type: Easing.OutQuart } + PauseAnimation { duration: 50 } + } + } ] } diff --git a/ScreenPlay/qml/Create/Wizards/GifWallpaper.qml b/ScreenPlay/qml/Create/Wizards/GifWallpaper.qml index cbf14946..268c60e4 100644 --- a/ScreenPlay/qml/Create/Wizards/GifWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/GifWallpaper.qml @@ -3,29 +3,26 @@ import QtQuick.Controls.Material 2.14 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import QtQuick.Dialogs 1.2 - import ScreenPlay 1.0 - import "../../Common" as Common WizardPage { id: root property url file + sourceComponent: ColumnLayout { + property bool ready: tfTitle.text.length >= 1 && root.file.length !== "" function create() { - ScreenPlay.wizards.createGifWallpaper(tfTitle.text, cbLicense.name, - cbLicense.licenseFile, - tfCreatedBy.text, root.file, - tagSelector.getTags()) + ScreenPlay.wizards.createGifWallpaper(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, root.file, tagSelector.getTags()); } - property bool ready: tfTitle.text.length >= 1 && root.file.length !== "" onReadyChanged: root.ready = ready Common.Headline { id: txtHeadline + text: qsTr("Import a Gif Wallpaper") Layout.fillWidth: true } @@ -41,41 +38,40 @@ WizardPage { Layout.fillWidth: true ColumnLayout { - Layout.preferredHeight: root.width * .5 - Layout.preferredWidth: root.width * .5 + Layout.preferredHeight: root.width * 0.5 + Layout.preferredWidth: root.width * 0.5 Rectangle { id: leftWrapper + color: Qt.darker(Material.backgroundColor) radius: 3 Layout.fillHeight: true Layout.fillWidth: true + DropArea { id: dropArea + anchors.fill: parent onDropped: { - root.file = drop.urls[0] - leftWrapper.color = Qt.darker( - Qt.darker(Material.backgroundColor)) + root.file = drop.urls[0]; + leftWrapper.color = Qt.darker(Qt.darker(Material.backgroundColor)); } - onExited: { - leftWrapper.color = Qt.darker( - Material.backgroundColor) + leftWrapper.color = Qt.darker(Material.backgroundColor); } - onEntered: { - leftWrapper.color = Qt.darker( - Qt.darker(Material.backgroundColor)) - drag.accept(Qt.LinkAction) + leftWrapper.color = Qt.darker(Qt.darker(Material.backgroundColor)); + drag.accept(Qt.LinkAction); } } Image { id: bgPattern + anchors.fill: parent fillMode: Image.Tile - opacity: .2 + opacity: 0.2 source: "qrc:/assets/images/noisy-texture-3.png" } @@ -89,10 +85,12 @@ WizardPage { AnimatedImage { id: imgPreview + anchors.fill: parent fillMode: Image.PreserveAspectCrop source: root.file } + } Item { @@ -102,18 +100,21 @@ WizardPage { Common.FileSelector { id: fileSelector + Layout.fillWidth: true placeHolderText: qsTr("Select your gif") fileDialog.nameFilters: ["Gif (*.gif)"] onFileChanged: root.file = file } + } ColumnLayout { id: rightWrapper + spacing: 20 Layout.fillHeight: true - Layout.preferredWidth: root.width * .5 + Layout.preferredWidth: root.width * 0.5 Common.HeadlineSection { text: qsTr("General") @@ -121,6 +122,7 @@ WizardPage { Common.TextField { id: tfTitle + Layout.fillWidth: true placeholderText: qsTr("Wallpaper name") required: true @@ -128,12 +130,14 @@ WizardPage { Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created By") } Common.LicenseSelector { id: cbLicense + Layout.fillWidth: true } @@ -143,6 +147,7 @@ WizardPage { Common.TagSelector { id: tagSelector + Layout.fillWidth: true } @@ -150,14 +155,11 @@ WizardPage { Layout.fillHeight: true Layout.fillWidth: true } + } + } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:580;width:1200} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml b/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml index 3dd101e0..91126059 100644 --- a/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml @@ -3,10 +3,8 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../Common" as Common WizardPage { @@ -14,22 +12,19 @@ WizardPage { sourceComponent: ColumnLayout { id: rightWrapper + + function create() { + ScreenPlay.wizards.createHTMLWallpaper(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, previewSelector.imageSource, tagSelector.getTags()); + } + spacing: 10 + anchors { top: parent.top right: parent.right left: parent.left } - function create() { - ScreenPlay.wizards.createHTMLWallpaper(tfTitle.text, - cbLicense.name, - cbLicense.licenseFile, - tfCreatedBy.text, - previewSelector.imageSource, - tagSelector.getTags()) - } - Common.Headline { text: qsTr("Create a HTML Wallpaper") Layout.fillWidth: true @@ -38,24 +33,31 @@ WizardPage { Common.HeadlineSection { text: qsTr("General") } + RowLayout { spacing: 20 Common.TextField { id: tfTitle + Layout.fillWidth: true placeholderText: qsTr("Wallpaper name") required: true onTextChanged: root.ready = text.length >= 1 } + Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created By") } + } + Common.TextField { id: tfDescription + Layout.fillWidth: true placeholderText: qsTr("Description") } @@ -77,8 +79,10 @@ WizardPage { Common.TagSelector { id: tagSelector + Layout.fillWidth: true } + } Item { @@ -91,14 +95,10 @@ WizardPage { Common.ImageSelector { id: previewSelector + Layout.fillWidth: true } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/HTMLWidget.qml b/ScreenPlay/qml/Create/Wizards/HTMLWidget.qml index d10e54a8..28d2772e 100644 --- a/ScreenPlay/qml/Create/Wizards/HTMLWidget.qml +++ b/ScreenPlay/qml/Create/Wizards/HTMLWidget.qml @@ -4,24 +4,19 @@ import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import QtQuick.Dialogs 1.2 import ScreenPlay 1.0 - import "../../Common" as Common WizardPage { id: root sourceComponent: ColumnLayout { - function create() { - ScreenPlay.wizards.createHTMLWidget(tfTitle.text, cbLicense.name, - cbLicense.licenseFile, - tfCreatedBy.text, - previewSelector.imageSource, - tagSelector.getTags()) + ScreenPlay.wizards.createHTMLWidget(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, previewSelector.imageSource, tagSelector.getTags()); } Common.Headline { id: txtHeadline + text: qsTr("Create a HTML widget") Layout.fillWidth: true } @@ -37,12 +32,13 @@ WizardPage { Layout.fillWidth: true ColumnLayout { - Layout.preferredHeight: root.width * .5 - Layout.preferredWidth: root.width * .5 + Layout.preferredHeight: root.width * 0.5 + Layout.preferredWidth: root.width * 0.5 spacing: 20 Rectangle { id: leftWrapper + color: "#333333" radius: 3 Layout.fillHeight: true @@ -50,37 +46,46 @@ WizardPage { Image { id: imgPreview + source: "qrc:/assets/wizards/example_html.png" anchors.fill: parent fillMode: Image.PreserveAspectCrop } + } Common.ImageSelector { id: previewSelector + Layout.fillWidth: true } + } ColumnLayout { id: rightWrapper + spacing: 20 Layout.fillHeight: true - Layout.preferredWidth: root.width * .5 + Layout.preferredWidth: root.width * 0.5 Layout.alignment: Qt.AlignTop Common.HeadlineSection { text: qsTr("General") } + Common.TextField { id: tfTitle + Layout.fillWidth: true required: true placeholderText: qsTr("Widget name") onTextChanged: root.ready = text.length >= 1 } + Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created by") } @@ -88,22 +93,21 @@ WizardPage { Common.LicenseSelector { id: cbLicense } + Common.HeadlineSection { text: qsTr("Tags") } Common.TagSelector { id: tagSelector + Layout.fillWidth: true } + } + } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:580;width:1200} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml index 8d10842c..42a25037 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml @@ -3,36 +3,42 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 Item { id: root - signal wizardStarted - signal wizardExited - signal next + signal wizardStarted() + signal wizardExited() + signal next() SwipeView { id: swipeView + anchors.fill: parent interactive: false clip: true CreateWallpaperInit { onNext: { - root.wizardStarted() - swipeView.currentIndex = 1 - createWallpaperVideoImportConvert.codec = codec - createWallpaperVideoImportConvert.filePath = filePath - ScreenPlay.create.createWallpaperStart(filePath, codec, quality) + root.wizardStarted(); + swipeView.currentIndex = 1; + createWallpaperVideoImportConvert.codec = codec; + createWallpaperVideoImportConvert.filePath = filePath; + ScreenPlay.create.createWallpaperStart(filePath, codec, quality); } } + CreateWallpaperVideoImportConvert { id: createWallpaperVideoImportConvert + onAbort: root.wizardExited() } - CreateWallpaperResult {} + + CreateWallpaperResult { + } + } + } diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml index 1dc24b3e..00dda2ca 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml @@ -4,17 +4,17 @@ import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 import QtQuick.Dialogs 1.3 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../../Common" as Common Item { id: root - signal next(var filePath, var codec) property int quality: sliderQuality.slider.value + + signal next(var filePath, var codec) + ColumnLayout { spacing: 40 @@ -33,6 +33,7 @@ Item { Text { id: txtDescription + text: qsTr("Depending on your PC configuration it is better to convert your wallpaper to a specific video codec. If both have bad performance you can also try a QML wallpaper! Supported video formats are: \n *.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv") color: Material.primaryTextColor @@ -41,55 +42,70 @@ Item { wrapMode: Text.WrapAtWordBoundaryOrAnywhere font.family: ScreenPlay.settings.font } + ColumnLayout { spacing: 20 + Text { id: txtComboboxHeadline + text: qsTr("Set your preffered video codec:") color: Material.primaryTextColor width: parent.width font.pointSize: 14 font.family: ScreenPlay.settings.font } + ComboBox { + // ListElement { + // text: "AV1 (NVidia 3000, AMD 6000 or newer). ULTRA SLOW ENCODING!" + // value: Create.AV1 + // } + id: comboBoxCodec + Layout.preferredWidth: 400 textRole: "text" valueRole: "value" currentIndex: 1 font.family: ScreenPlay.settings.font + model: ListModel { id: model + ListElement { text: "VP8 (Better for older hardware)" value: Create.VP9 } + ListElement { text: "VP9 (Better for newer hardware 2018+)" value: Create.VP8 } - // Import works but the QWebEngine cannot display AV1 :( - // ListElement { - // text: "AV1 (NVidia 3000, AMD 6000 or newer). ULTRA SLOW ENCODING!" - // value: Create.AV1 - // } - } - } - } + // Import works but the QWebEngine cannot display AV1 :( + } + + } + + } Common.Slider { id: sliderQuality + iconSource: "qrc:/assets/icons/icon_settings.svg" headline: qsTr("Quality slider. Lower value means better quality.") + Layout.preferredWidth: 400 + slider { from: 63 value: 22 to: 0 stepSize: 1 } - Layout.preferredWidth: 400 + } + } Button { @@ -101,12 +117,13 @@ Item { icon.width: 16 icon.height: 16 font.family: ScreenPlay.settings.font - onClicked: Qt.openUrlExternally( - "https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + onClicked: Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + anchors { bottom: parent.bottom margins: 20 } + } Button { @@ -114,16 +131,15 @@ Item { highlighted: true font.family: ScreenPlay.settings.font onClicked: { - fileDialogImportVideo.open() + fileDialogImportVideo.open(); } FileDialog { id: fileDialogImportVideo - nameFilters: ["Video files (*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv)"] + nameFilters: ["Video files (*.mp4 *.mpg *.mp2 *.mpeg *.ogv *.avi *.wmv *.m4v *.3gp *.flv)"] onAccepted: { - root.next(fileDialogImportVideo.fileUrl, - model.get(comboBoxCodec.currentIndex).value) + root.next(fileDialogImportVideo.fileUrl, model.get(comboBoxCodec.currentIndex).value); } } @@ -132,12 +148,7 @@ Item { bottom: parent.bottom margins: 20 } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:768;width:1366} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml index 9f1e2a37..bd78042a 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml @@ -4,35 +4,38 @@ import QtQuick.Controls.Material 2.14 import QtQuick.Layouts 1.14 import QtQuick.Dialogs 1.2 import QtGraphicalEffects 1.0 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 Item { id: wrapperError - property alias error:txtFFMPEGDebug.text + property alias error: txtFFMPEGDebug.text Text { id: txtErrorHeadline + text: qsTr("An error occurred!") + height: 40 + font.family: ScreenPlay.settings.font + font.weight: Font.Light + color: Material.color(Material.DeepOrange) + font.pointSize: 32 anchors { top: parent.top topMargin: 30 horizontalCenter: parent.horizontalCenter } - height: 40 - font.family: ScreenPlay.settings.font - font.weight: Font.Light - color: Material.color(Material.DeepOrange) - font.pointSize: 32 + } Rectangle { id: rectangle1 + color: "#eeeeee" radius: 3 + anchors { top: txtErrorHeadline.bottom right: parent.right @@ -46,59 +49,73 @@ Item { anchors.fill: parent clip: true contentHeight: txtFFMPEGDebug.paintedHeight + 100 - ScrollBar.vertical: ScrollBar { - snapMode: ScrollBar.SnapOnRelease - policy: ScrollBar.AlwaysOn - } + Text { id: txtFFMPEGDebug + + font.family: ScreenPlay.settings.font + wrapMode: Text.WordWrap + color: "#626262" + text: ScreenPlay.create.ffmpegOutput + height: txtFFMPEGDebug.paintedHeight + anchors { top: parent.top right: parent.right left: parent.left margins: 20 } - font.family: ScreenPlay.settings.font - wrapMode: Text.WordWrap - color: "#626262" - text: ScreenPlay.create.ffmpegOutput - height: txtFFMPEGDebug.paintedHeight + } + MouseArea { anchors.fill: parent propagateComposedEvents: true acceptedButtons: Qt.RightButton onClicked: contextMenu.popup() } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + policy: ScrollBar.AlwaysOn + } + } + } + Menu { id: contextMenu + MenuItem { text: qsTr("Copy text to clipboard") onClicked: { - ScreenPlay.util.copyToClipboard(txtFFMPEGDebug.text) + ScreenPlay.util.copyToClipboard(txtFFMPEGDebug.text); } } - } + } Button { id: btnBack + text: qsTr("Back to create and send an error report!") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font + onClicked: { + ScreenPlay.util.setNavigationActive(true); + ScreenPlay.util.setNavigation("Create"); + } + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 10 } - onClicked: { - ScreenPlay.util.setNavigationActive(true) - ScreenPlay.util.setNavigation("Create") - } + } + states: [ State { name: "error" @@ -107,6 +124,7 @@ Item { target: txtFFMPEGDebug text: "Error!" } + }, State { name: "success" @@ -115,11 +133,7 @@ Item { target: txtFFMPEGDebug text: "Success!" } + } ] } - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml index 41d4b017..63a0701d 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml @@ -3,11 +3,9 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - -import "../../../Common" as Common +import "../../../Common" as Common Item { id: root @@ -16,116 +14,116 @@ Item { property bool canSave: false property var codec: Create.VP8 property string filePath - signal abort - onFilePathChanged: { - textFieldName.text = basename(filePath) - } + signal abort() + signal save() function cleanup() { - ScreenPlay.create.abortAndCleanup() + ScreenPlay.create.abortAndCleanup(); } function basename(str) { - let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)) - let filename = filenameWithExtentions.split('.').slice(0, -1).join('.') - return filename + let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)); + let filename = filenameWithExtentions.split('.').slice(0, -1).join('.'); + return filename; + } + + function checkCanSave() { + if (canSave && conversionFinishedSuccessful) + btnSave.enabled = true; + else + btnSave.enabled = false; } onCanSaveChanged: root.checkCanSave() - signal save - - function checkCanSave() { - if (canSave && conversionFinishedSuccessful) { - btnSave.enabled = true - } else { - btnSave.enabled = false - } + onFilePathChanged: { + textFieldName.text = basename(filePath); } Connections { - target: ScreenPlay.create - function onCreateWallpaperStateChanged(state) { switch (state) { case CreateImportVideo.ConvertingPreviewImage: - txtConvert.text = qsTr("Generating preview image...") - break + txtConvert.text = qsTr("Generating preview image..."); + break; case CreateImportVideo.ConvertingPreviewThumbnailImage: - txtConvert.text = qsTr("Generating preview thumbnail image...") - break + txtConvert.text = qsTr("Generating preview thumbnail image..."); + break; case CreateImportVideo.ConvertingPreviewImageFinished: - imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg" - imgPreview.visible = true - break + imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg"; + imgPreview.visible = true; + break; case CreateImportVideo.ConvertingPreviewVideo: - txtConvert.text = qsTr("Generating 5 second preview video...") - break + txtConvert.text = qsTr("Generating 5 second preview video..."); + break; case CreateImportVideo.ConvertingPreviewGif: - txtConvert.text = qsTr("Generating preview gif...") - break + txtConvert.text = qsTr("Generating preview gif..."); + break; case CreateImportVideo.ConvertingPreviewGifFinished: - gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif" - imgPreview.visible = false - gifPreview.visible = true - gifPreview.playing = true - break + gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif"; + imgPreview.visible = false; + gifPreview.visible = true; + gifPreview.playing = true; + break; case CreateImportVideo.ConvertingAudio: - txtConvert.text = qsTr("Converting Audio...") - break + txtConvert.text = qsTr("Converting Audio..."); + break; case CreateImportVideo.ConvertingVideo: - txtConvert.text = qsTr( - "Converting Video... This can take some time!") - break + txtConvert.text = qsTr("Converting Video... This can take some time!"); + break; case CreateImportVideo.ConvertingVideoError: - txtConvert.text = qsTr("Converting Video ERROR!") - break + txtConvert.text = qsTr("Converting Video ERROR!"); + break; case CreateImportVideo.AnalyseVideoError: - txtConvert.text = qsTr("Analyse Video ERROR!") - break + txtConvert.text = qsTr("Analyse Video ERROR!"); + break; case CreateImportVideo.Finished: - txtConvert.text = "" - conversionFinishedSuccessful = true - busyIndicator.running = false - root.checkCanSave() - - break + txtConvert.text = ""; + conversionFinishedSuccessful = true; + busyIndicator.running = false; + root.checkCanSave(); + break; } } + function onProgressChanged(progress) { - var percentage = Math.floor(progress * 100) - + var percentage = Math.floor(progress * 100); if (percentage > 100 || progress > 0.95) - percentage = 100 + percentage = 100; - if (percentage === NaN) { - print(progress, percentage) - } + if (percentage === NaN) + print(progress, percentage); - txtConvertNumber.text = percentage + "%" + txtConvertNumber.text = percentage + "%"; } + + target: ScreenPlay.create } Text { id: txtHeadline + text: qsTr("Convert a video to a wallpaper") height: 40 font.family: ScreenPlay.settings.font font.weight: Font.Light color: Material.primaryTextColor - font.pointSize: 23 + anchors { top: parent.top left: parent.left margins: 40 bottomMargin: 0 } + } Item { id: wrapperLeft - width: parent.width * .66 + + width: parent.width * 0.66 + anchors { left: parent.left top: txtHeadline.bottom @@ -135,6 +133,9 @@ Item { Rectangle { id: imgWrapper + + color: Material.color(Material.Grey) + anchors { top: parent.top right: parent.right @@ -144,11 +145,10 @@ Item { left: parent.left } - color: Material.color(Material.Grey) - Image { - fillMode: Image.PreserveAspectCrop id: imgPreview + + fillMode: Image.PreserveAspectCrop asynchronous: true visible: false anchors.fill: parent @@ -156,6 +156,7 @@ Item { AnimatedImage { id: gifPreview + fillMode: Image.PreserveAspectCrop asynchronous: true playing: true @@ -165,70 +166,93 @@ Item { LinearGradient { id: shadow + cached: true anchors.fill: parent start: Qt.point(0, height) end: Qt.point(0, 0) + gradient: Gradient { GradientStop { id: gradientStop0 - position: 0.0 + + position: 0 color: "#DD000000" } + GradientStop { id: gradientStop1 - position: 1.0 + + position: 1 color: "#00000000" } + } + } BusyIndicator { id: busyIndicator + anchors.centerIn: parent running: true } Text { id: txtConvertNumber + color: "white" text: qsTr("") font.pointSize: 21 font.family: ScreenPlay.settings.font + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 40 } + } Text { id: txtConvert + color: Material.secondaryTextColor text: qsTr("Generating preview video...") font.pointSize: 14 font.family: ScreenPlay.settings.font + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 20 } + } + } + Common.ImageSelector { id: previewSelector + height: 80 + anchors { right: parent.right rightMargin: 20 left: parent.left bottom: parent.bottom } + } + } + Item { id: wrapperRight - width: parent.width * .33 + + width: parent.width * 0.33 + anchors { top: txtHeadline.bottom topMargin: 30 @@ -238,7 +262,9 @@ Item { ColumnLayout { id: column + spacing: 0 + anchors { right: parent.right left: parent.left @@ -251,20 +277,21 @@ Item { Common.TextField { id: textFieldName + placeholderText: qsTr("Name (required!)") width: parent.width Layout.fillWidth: true onTextChanged: { - if (textFieldName.text.length >= 3) { - canSave = true - } else { - canSave = false - } + if (textFieldName.text.length >= 3) + canSave = true; + else + canSave = false; } } Common.TextField { id: textFieldDescription + placeholderText: qsTr("Description") width: parent.width Layout.fillWidth: true @@ -272,6 +299,7 @@ Item { Common.TextField { id: textFieldYoutubeURL + placeholderText: qsTr("Youtube URL") width: parent.width Layout.fillWidth: true @@ -279,16 +307,20 @@ Item { Common.TagSelector { id: textFieldTags + width: parent.width Layout.fillWidth: true } + } Row { id: column1 + height: 80 width: childrenRect.width spacing: 10 + anchors { right: parent.right rightMargin: 30 @@ -298,42 +330,42 @@ Item { Button { id: btnExit + text: qsTr("Abort") Material.background: Material.Red Material.foreground: "white" font.family: ScreenPlay.settings.font onClicked: { - root.abort() - ScreenPlay.create.abortAndCleanup() + root.abort(); + ScreenPlay.create.abortAndCleanup(); } } Button { id: btnSave + text: qsTr("Save") enabled: false Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font - onClicked: { if (conversionFinishedSuccessful) { - btnSave.enabled = false - ScreenPlay.create.saveWallpaper( - textFieldName.text, - textFieldDescription.text, root.filePath, - previewSelector.imageSource, - textFieldYoutubeURL.text, codec, - textFieldTags.getTags()) - savePopup.open() - ScreenPlay.installedListModel.reset() + btnSave.enabled = false; + ScreenPlay.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, codec, textFieldTags.getTags()); + savePopup.open(); + ScreenPlay.installedListModel.reset(); } } } + } + } + Popup { id: savePopup + modal: true focus: true width: 250 @@ -345,6 +377,7 @@ Item { anchors.centerIn: parent running: true } + Text { text: qsTr("Save Wallpaper...") color: Material.primaryTextColor @@ -356,19 +389,15 @@ Item { Timer { id: timerSave + interval: 1000 + Math.random() * 1000 onTriggered: { - savePopup.close() - ScreenPlay.util.setNavigationActive(true) - ScreenPlay.util.setNavigation("Installed") + savePopup.close(); + ScreenPlay.util.setNavigationActive(true); + ScreenPlay.util.setNavigation("Installed"); } } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:580;width:1200} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml index d9e894db..aee8a7b9 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml @@ -3,35 +3,39 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 Item { id: root - signal wizardStarted - signal wizardExited - signal next + signal wizardStarted() + signal wizardExited() + signal next() SwipeView { id: swipeView + anchors.fill: parent interactive: false clip: true ImportWebmInit { onNext: { - root.wizardStarted() - swipeView.currentIndex = 1 - createWallpaperVideoImportConvert.filePath = filePath - ScreenPlay.util.setNavigationActive(false) - ScreenPlay.create.createWallpaperStart(filePath, Create.VP9) + root.wizardStarted(); + swipeView.currentIndex = 1; + createWallpaperVideoImportConvert.filePath = filePath; + ScreenPlay.util.setNavigationActive(false); + ScreenPlay.create.createWallpaperStart(filePath, Create.VP9); } } + ImportWebmConvert { id: createWallpaperVideoImportConvert + onExit: root.wizardExited() } + } + } diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml index 89560d2a..0d15579b 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml @@ -3,122 +3,120 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../../Common" as Common - Item { id: root property bool conversionFinishedSuccessful: false property bool canSave: false property string filePath - signal exit - onFilePathChanged: { - textFieldName.text = basename(filePath) - } + signal exit() + signal save() function basename(str) { - let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)) - let filename = filenameWithExtentions.split('.').slice(0, -1).join('.') - return filename + let filenameWithExtentions = (str.slice(str.lastIndexOf("/") + 1)); + let filename = filenameWithExtentions.split('.').slice(0, -1).join('.'); + return filename; + } + + function checkCanSave() { + if (canSave && conversionFinishedSuccessful) + btnSave.enabled = true; + else + btnSave.enabled = false; } onCanSaveChanged: root.checkCanSave() - signal save - - function checkCanSave() { - if (canSave && conversionFinishedSuccessful) { - btnSave.enabled = true - } else { - btnSave.enabled = false - } + onFilePathChanged: { + textFieldName.text = basename(filePath); } Connections { - target: ScreenPlay.create - function onCreateWallpaperStateChanged(state) { switch (state) { case CreateImportVideo.AnalyseVideo: - txtConvert.text = qsTr("AnalyseVideo...") - break + txtConvert.text = qsTr("AnalyseVideo..."); + break; case CreateImportVideo.ConvertingPreviewImage: - txtConvert.text = qsTr("Generating preview image...") - break + txtConvert.text = qsTr("Generating preview image..."); + break; case CreateImportVideo.ConvertingPreviewThumbnailImage: - txtConvert.text = qsTr("Generating preview thumbnail image...") - break + txtConvert.text = qsTr("Generating preview thumbnail image..."); + break; case CreateImportVideo.ConvertingPreviewImageFinished: - imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg" - imgPreview.visible = true - break + imgPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.jpg"; + imgPreview.visible = true; + break; case CreateImportVideo.ConvertingPreviewVideo: - txtConvert.text = qsTr("Generating 5 second preview video...") - break + txtConvert.text = qsTr("Generating 5 second preview video..."); + break; case CreateImportVideo.ConvertingPreviewGif: - txtConvert.text = qsTr("Generating preview gif...") - break + txtConvert.text = qsTr("Generating preview gif..."); + break; case CreateImportVideo.ConvertingPreviewGifFinished: - gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif" - imgPreview.visible = false - gifPreview.visible = true - gifPreview.playing = true - break + gifPreview.source = "file:///" + ScreenPlay.create.workingDir + "/preview.gif"; + imgPreview.visible = false; + gifPreview.visible = true; + gifPreview.playing = true; + break; case CreateImportVideo.ConvertingAudio: - txtConvert.text = qsTr("Converting Audio...") - break + txtConvert.text = qsTr("Converting Audio..."); + break; case CreateImportVideo.ConvertingVideo: - txtConvert.text = qsTr( - "Converting Video... This can take some time!") - break + txtConvert.text = qsTr("Converting Video... This can take some time!"); + break; case CreateImportVideo.ConvertingVideoError: - txtConvert.text = qsTr("Converting Video ERROR!") - break + txtConvert.text = qsTr("Converting Video ERROR!"); + break; case CreateImportVideo.AnalyseVideoError: - txtConvert.text = qsTr("Analyse Video ERROR!") - break + txtConvert.text = qsTr("Analyse Video ERROR!"); + break; case CreateImportVideo.Finished: - txtConvert.text = "" - conversionFinishedSuccessful = true - busyIndicator.running = false - root.checkCanSave() - - break + txtConvert.text = ""; + conversionFinishedSuccessful = true; + busyIndicator.running = false; + root.checkCanSave(); + break; } } + function onProgressChanged(progress) { - var percentage = Math.floor(progress * 100) - + var percentage = Math.floor(progress * 100); if (percentage > 100 || progress > 0.95) - percentage = 100 + percentage = 100; - if (percentage === NaN) { - print(progress, percentage) - } + if (percentage === NaN) + print(progress, percentage); - txtConvertNumber.text = percentage + "%" + txtConvertNumber.text = percentage + "%"; } + + target: ScreenPlay.create } Common.Headline { id: txtHeadline + text: qsTr("Import a video to a wallpaper") + anchors { top: parent.top left: parent.left margins: 40 bottomMargin: 0 } + } Item { id: wrapperLeft - width: parent.width * .66 + + width: parent.width * 0.66 + anchors { left: parent.left top: txtHeadline.bottom @@ -128,6 +126,9 @@ Item { Rectangle { id: imgWrapper + + color: Material.color(Material.Grey) + anchors { top: parent.top right: parent.right @@ -137,11 +138,10 @@ Item { left: parent.left } - color: Material.color(Material.Grey) - Image { - fillMode: Image.PreserveAspectCrop id: imgPreview + + fillMode: Image.PreserveAspectCrop asynchronous: true visible: false anchors.fill: parent @@ -149,6 +149,7 @@ Item { AnimatedImage { id: gifPreview + fillMode: Image.PreserveAspectCrop asynchronous: true playing: true @@ -158,70 +159,93 @@ Item { LinearGradient { id: shadow + cached: true anchors.fill: parent start: Qt.point(0, height) end: Qt.point(0, 0) + gradient: Gradient { GradientStop { id: gradientStop0 - position: 0.0 + + position: 0 color: "#DD000000" } + GradientStop { id: gradientStop1 - position: 1.0 + + position: 1 color: "#00000000" } + } + } BusyIndicator { id: busyIndicator + anchors.centerIn: parent running: true } Text { id: txtConvertNumber + color: "white" text: qsTr("") font.pointSize: 21 font.family: ScreenPlay.settings.font + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 40 } + } Text { id: txtConvert + color: Material.secondaryTextColor text: qsTr("Generating preview video...") font.pointSize: 14 font.family: ScreenPlay.settings.font + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 20 } + } + } + Common.ImageSelector { id: previewSelector + height: 80 + anchors { right: parent.right rightMargin: 20 left: parent.left bottom: parent.bottom } + } + } + Item { id: wrapperRight - width: parent.width * .33 + + width: parent.width * 0.33 + anchors { top: txtHeadline.bottom topMargin: 30 @@ -231,7 +255,9 @@ Item { ColumnLayout { id: column + spacing: 0 + anchors { right: parent.right left: parent.left @@ -244,20 +270,21 @@ Item { Common.TextField { id: textFieldName + placeholderText: qsTr("Name (required!)") width: parent.width Layout.fillWidth: true onTextChanged: { - if (textFieldName.text.length >= 3) { - canSave = true - } else { - canSave = false - } + if (textFieldName.text.length >= 3) + canSave = true; + else + canSave = false; } } Common.TextField { id: textFieldDescription + placeholderText: qsTr("Description") width: parent.width Layout.fillWidth: true @@ -265,6 +292,7 @@ Item { Common.TextField { id: textFieldYoutubeURL + placeholderText: qsTr("Youtube URL") width: parent.width Layout.fillWidth: true @@ -272,16 +300,20 @@ Item { Common.TagSelector { id: textFieldTags + width: parent.width Layout.fillWidth: true } + } Row { id: column1 + height: 80 width: childrenRect.width spacing: 10 + anchors { right: parent.right rightMargin: 30 @@ -291,42 +323,42 @@ Item { Button { id: btnExit + text: qsTr("Abort") Material.background: Material.Red Material.foreground: "white" font.family: ScreenPlay.settings.font onClicked: { - root.exit() - ScreenPlay.create.abortAndCleanup() + root.exit(); + ScreenPlay.create.abortAndCleanup(); } } Button { id: btnSave + text: qsTr("Save") enabled: false Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font - onClicked: { if (conversionFinishedSuccessful) { - btnSave.enabled = false - ScreenPlay.create.saveWallpaper( - textFieldName.text, - textFieldDescription.text, root.filePath, - previewSelector.imageSource, - textFieldYoutubeURL.text, Create.VP9, - textFieldTags.getTags()) - savePopup.open() - ScreenPlay.installedListModel.reset() + btnSave.enabled = false; + ScreenPlay.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Create.VP9, textFieldTags.getTags()); + savePopup.open(); + ScreenPlay.installedListModel.reset(); } } } + } + } + Popup { id: savePopup + modal: true focus: true width: 250 @@ -338,6 +370,7 @@ Item { anchors.centerIn: parent running: true } + Text { text: qsTr("Save Wallpaper...") color: Material.primaryTextColor @@ -349,19 +382,15 @@ Item { Timer { id: timerSave + interval: 1000 + Math.random() * 1000 onTriggered: { - savePopup.close() - ScreenPlay.util.setNavigationActive(true) - root.exit() + savePopup.close(); + ScreenPlay.util.setNavigationActive(true); + root.exit(); } } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:580;width:1200} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml index 799d1f34..c1e1fe6c 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml @@ -4,19 +4,19 @@ import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 import QtQuick.Dialogs 1.3 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../../Common" as Common import "../../" Item { id: root + signal next(var filePath) ColumnLayout { id: wrapper + spacing: 40 anchors { @@ -36,12 +36,15 @@ Item { Layout.fillHeight: true Layout.fillWidth: true spacing: 40 + ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true spacing: 40 + Text { id: txtDescription + text: qsTr("When importing webm we can skip the long conversion. When you get unsatisfying results with the ScreenPlay importer from 'ideo import and convert (all types)' you can also convert via the free and open source HandBrake!") color: Material.primaryTextColor Layout.fillWidth: true @@ -52,11 +55,28 @@ Item { DropArea { id: dropArea + Layout.fillHeight: true Layout.fillWidth: true + onExited: { + bg.color = Qt.darker(Material.backgroundColor); + } + onEntered: { + bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); + drag.accept(Qt.LinkAction); + } + onDropped: { + let file = ScreenPlay.util.toLocal(drop.urls[0]); + bg.color = Qt.darker(Qt.darker(Material.backgroundColor)); + if (file.endsWith(".webm")) + root.next(drop.urls[0]); + else + txtFile.text = qsTr("Invalid file type. Must be valid VP8 or VP9 (*.webm)!"); + } Rectangle { id: bg + anchors.fill: parent radius: 3 color: Qt.darker(Material.backgroundColor) @@ -64,50 +84,38 @@ Item { Image { id: bgPattern + anchors.fill: parent fillMode: Image.Tile - opacity: .2 + opacity: 0.2 source: "qrc:/assets/images/noisy-texture-3.png" } - onExited: { - bg.color = Qt.darker(Material.backgroundColor) - } - onEntered: { - bg.color = Qt.darker(Qt.darker( - Material.backgroundColor)) - drag.accept(Qt.LinkAction) - } - onDropped: { - let file = ScreenPlay.util.toLocal(drop.urls[0]) - bg.color = Qt.darker(Qt.darker( - Material.backgroundColor)) - if (file.endsWith(".webm")) { - root.next(drop.urls[0]) - } else { - txtFile.text = qsTr( - "Invalid file type. Must be valid VP8 or VP9 (*.webm)!") - } - } Text { id: txtFile + text: qsTr("Drop a *.webm file here or use 'Select file' below.") - anchors { - fill: parent - margins: 40 - } wrapMode: Text.WrapAtWordBoundaryOrAnywhere color: Material.primaryTextColor font.pointSize: 13 horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter font.family: ScreenPlay.settings.font + + anchors { + fill: parent + margins: 40 + } + } + } + } + Item { Layout.fillHeight: true - Layout.preferredWidth: wrapper.width * .33 + Layout.preferredWidth: wrapper.width * 0.33 StartInfoLinkImage { text: "Handbreak" @@ -119,12 +127,16 @@ Item { height: parent.height anchors.centerIn: parent } + } + } + } Button { id: btnOpenDocs + text: qsTr("Open Documentation") Material.background: Material.LightGreen Material.foreground: "white" @@ -133,28 +145,30 @@ Item { icon.width: 16 icon.height: 16 font.family: ScreenPlay.settings.font - onClicked: Qt.openUrlExternally( - "https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + onClicked: Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/wallpaper/wallpaper/#performance") + anchors { bottom: parent.bottom left: parent.left margins: 20 } + } + Button { text: qsTr("Select file") highlighted: true font.family: ScreenPlay.settings.font onClicked: { - fileDialogImportVideo.open() + fileDialogImportVideo.open(); } FileDialog { id: fileDialogImportVideo - nameFilters: ["Video files (*.webm)"] + nameFilters: ["Video files (*.webm)"] onAccepted: { - root.next(fileDialogImportVideo.fileUrl) + root.next(fileDialogImportVideo.fileUrl); } } @@ -163,12 +177,7 @@ Item { bottom: parent.bottom margins: 20 } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:768;width:1366} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml b/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml index a7322249..94f8fd5a 100644 --- a/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml @@ -3,10 +3,8 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../Common" as Common WizardPage { @@ -14,22 +12,19 @@ WizardPage { sourceComponent: ColumnLayout { id: rightWrapper + + function create() { + ScreenPlay.wizards.createQMLWallpaper(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, previewSelector.imageSource, tagSelector.getTags()); + } + spacing: 10 + anchors { top: parent.top right: parent.right left: parent.left } - function create() { - ScreenPlay.wizards.createQMLWallpaper(tfTitle.text, - cbLicense.name, - cbLicense.licenseFile, - tfCreatedBy.text, - previewSelector.imageSource, - tagSelector.getTags()) - } - Common.Headline { text: qsTr("Create a QML Wallpaper") Layout.fillWidth: true @@ -38,24 +33,31 @@ WizardPage { Common.HeadlineSection { text: qsTr("General") } + RowLayout { spacing: 20 Common.TextField { id: tfTitle + Layout.fillWidth: true placeholderText: qsTr("Wallpaper name") required: true onTextChanged: root.ready = text.length >= 1 } + Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created By") } + } + Common.TextField { id: tfDescription + Layout.fillWidth: true placeholderText: qsTr("Description") } @@ -71,15 +73,16 @@ WizardPage { RowLayout { spacing: 20 - Common.LicenseSelector { id: cbLicense } Common.TagSelector { id: tagSelector + Layout.fillWidth: true } + } Item { @@ -92,15 +95,10 @@ WizardPage { Common.ImageSelector { id: previewSelector + Layout.fillWidth: true } } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/QMLWidget.qml b/ScreenPlay/qml/Create/Wizards/QMLWidget.qml index 94a61d9d..4b74f622 100644 --- a/ScreenPlay/qml/Create/Wizards/QMLWidget.qml +++ b/ScreenPlay/qml/Create/Wizards/QMLWidget.qml @@ -4,24 +4,19 @@ import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import QtQuick.Dialogs 1.2 import ScreenPlay 1.0 - import "../../Common" as Common WizardPage { id: root sourceComponent: ColumnLayout { - function create() { - ScreenPlay.wizards.createQMLWidget(tfTitle.text, cbLicense.name, - cbLicense.licenseFile, - tfCreatedBy.text, - previewSelector.imageSource, - tagSelector.getTags()) + ScreenPlay.wizards.createQMLWidget(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, previewSelector.imageSource, tagSelector.getTags()); } Common.Headline { id: txtHeadline + text: qsTr("Create a QML widget") Layout.fillWidth: true } @@ -37,12 +32,13 @@ WizardPage { Layout.fillWidth: true ColumnLayout { - Layout.preferredHeight: root.width * .5 - Layout.preferredWidth: root.width * .5 + Layout.preferredHeight: root.width * 0.5 + Layout.preferredWidth: root.width * 0.5 spacing: 20 Rectangle { id: leftWrapper + color: "#333333" radius: 3 Layout.fillHeight: true @@ -50,37 +46,46 @@ WizardPage { Image { id: imgPreview + source: "qrc:/assets/wizards/example_qml.png" anchors.fill: parent fillMode: Image.PreserveAspectCrop } + } Common.ImageSelector { id: previewSelector + Layout.fillWidth: true } + } ColumnLayout { id: rightWrapper + spacing: 20 Layout.fillHeight: true - Layout.preferredWidth: root.width * .5 + Layout.preferredWidth: root.width * 0.5 Layout.alignment: Qt.AlignTop Common.HeadlineSection { text: qsTr("General") } + Common.TextField { id: tfTitle + Layout.fillWidth: true required: true placeholderText: qsTr("Widget name") onTextChanged: root.ready = text.length >= 1 } + Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created by") } @@ -88,22 +93,21 @@ WizardPage { Common.LicenseSelector { id: cbLicense } + Common.HeadlineSection { text: qsTr("Tags") } Common.TagSelector { id: tagSelector + Layout.fillWidth: true } + } + } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:580;width:1200} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml b/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml index 19cddfd4..090a90ee 100644 --- a/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml @@ -3,32 +3,29 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 - import "../../Common" as Common WizardPage { id: root sourceComponent: ColumnLayout { + property bool ready: tfTitle.text.length >= 1 && tfUrl.text.length > 1 + + function create() { + ScreenPlay.wizards.createWebsiteWallpaper(tfTitle.text, previewSelector.imageSource, tfUrl.text, tagSelector.getTags()); + } + spacing: 10 + onReadyChanged: root.ready = ready + anchors { top: parent.top right: parent.right left: parent.left } - function create() { - ScreenPlay.wizards.createWebsiteWallpaper( - tfTitle.text, previewSelector.imageSource, tfUrl.text, - tagSelector.getTags()) - } - - property bool ready: tfTitle.text.length >= 1 && tfUrl.text.length > 1 - onReadyChanged: root.ready = ready - Common.Headline { text: qsTr("Create a Website Wallpaper") Layout.fillWidth: true @@ -43,25 +40,32 @@ WizardPage { Common.TextField { id: tfTitle + Layout.fillWidth: true placeholderText: qsTr("Wallpaper name") required: true onTextChanged: root.ready = text.length >= 1 } + Common.TextField { id: tfCreatedBy + Layout.fillWidth: true placeholderText: qsTr("Created By") } + } + Common.TextField { id: tfDescription + Layout.fillWidth: true placeholderText: qsTr("Description") } Common.TextField { id: tfUrl + Layout.fillWidth: true required: true text: "https://" @@ -77,6 +81,7 @@ WizardPage { Common.TagSelector { id: tagSelector + Layout.fillWidth: true } @@ -90,14 +95,10 @@ WizardPage { Common.ImageSelector { id: previewSelector + Layout.fillWidth: true } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} } -##^##*/ - diff --git a/ScreenPlay/qml/Create/Wizards/WizardPage.qml b/ScreenPlay/qml/Create/Wizards/WizardPage.qml index 726faa57..c1439d80 100644 --- a/ScreenPlay/qml/Create/Wizards/WizardPage.qml +++ b/ScreenPlay/qml/Create/Wizards/WizardPage.qml @@ -4,25 +4,26 @@ import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.3 import QtQuick.Layouts 1.12 import QtQuick.Window 2.12 - import ScreenPlay 1.0 import ScreenPlay.Create 1.0 FocusScope { id: root - signal wizardStarted - signal wizardExited - signal saveClicked - signal saveFinished - signal cancelClicked - - property Component sourceComponent property alias savePopup: savePopup property bool ready: false + signal wizardStarted() + signal wizardExited() + signal saveClicked() + signal saveFinished() + signal cancelClicked() + ScrollView { + contentWidth: width + contentHeight: loader.height + anchors { margins: 20 top: parent.top @@ -31,24 +32,26 @@ FocusScope { left: parent.left } - contentWidth: width - contentHeight: loader.height - Loader { id: loader + width: parent.width Component.onCompleted: height = item.childrenRect.height clip: true sourceComponent: root.sourceComponent + anchors { top: parent.top horizontalCenter: parent.horizontalCenter } + } + } RowLayout { id: footer + anchors { right: parent.right bottom: parent.bottom @@ -62,6 +65,7 @@ FocusScope { Button { id: btnSave + text: qsTr("Save") enabled: root.ready Material.background: Material.accent @@ -69,16 +73,18 @@ FocusScope { Layout.alignment: Qt.AlignRight font.family: ScreenPlay.settings.font onClicked: { - btnSave.enabled = false - root.saveClicked() - loader.item.create() - savePopup.open() + btnSave.enabled = false; + root.saveClicked(); + loader.item.create(); + savePopup.open(); } } + } Popup { id: savePopup + modal: true focus: true width: 250 @@ -95,20 +101,25 @@ FocusScope { text: qsTr("Saving...") color: Material.primaryHighlightedTextColor font.family: ScreenPlay.settings.font + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 30 } + } Timer { id: timerSave + interval: 1000 + Math.random() * 1000 onTriggered: { - savePopup.close() - root.wizardExited() + savePopup.close(); + root.wizardExited(); } } + } + } diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml index f4fe69d9..8aa27ab4 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/Installed.qml @@ -4,7 +4,6 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Enums.InstalledType 1.0 import ScreenPlay.Enums.SearchType 1.0 @@ -12,16 +11,32 @@ import ScreenPlay.Enums.SearchType 1.0 Item { id: root - signal setNavigationItem(var pos) - signal setSidebarActive(var active) - property bool refresh: false property bool enabled: true + signal setNavigationItem(var pos) + signal setSidebarActive(var active) + + function checkIsContentInstalled() { + if (ScreenPlay.installedListModel.count === 0) { + loaderHelp.active = true; + 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; + } + } + Component.onCompleted: { - navWrapper.state = "in" - ScreenPlay.installedListFilter.sortBySearchType(SearchType.All) - checkIsContentInstalled() + navWrapper.state = "in"; + ScreenPlay.installedListFilter.sortBySearchType(SearchType.All); + checkIsContentInstalled(); } Action { @@ -30,42 +45,30 @@ Item { } Connections { - target: loaderHelp.item function onHelperButtonPressed(pos) { - setNavigationItem(pos) + setNavigationItem(pos); } + + target: loaderHelp.item } Connections { - target: ScreenPlay.installedListModel function onInstalledLoadingFinished() { - checkIsContentInstalled() + checkIsContentInstalled(); } - function onCountChanged(count) { - if (count === 0) { - checkIsContentInstalled() - } - } - } - function checkIsContentInstalled() { - if (ScreenPlay.installedListModel.count === 0) { - loaderHelp.active = true - 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 + function onCountChanged(count) { + if (count === 0) + checkIsContentInstalled(); + } + + target: ScreenPlay.installedListModel } Loader { id: loaderHelp + active: false z: 99 anchors.fill: parent @@ -73,14 +76,19 @@ Item { } Connections { - target: ScreenPlay.installedListFilter function onSortChanged() { - gridView.positionViewAtBeginning() + gridView.positionViewAtBeginning(); } + + target: ScreenPlay.installedListFilter } GridView { id: gridView + + property bool isDragging: false + property bool isScrolling: gridView.verticalVelocity != 0 + boundsBehavior: Flickable.DragOverBounds maximumFlickVelocity: 2500 flickDeceleration: 500 @@ -90,23 +98,39 @@ Item { cacheBuffer: 160 interactive: root.enabled snapMode: GridView.SnapToRow + onDragStarted: isDragging = true + onDragEnded: isDragging = false + model: ScreenPlay.installedListFilter + onContentYChanged: { + if (contentY <= -180) + gridView.headerItem.isVisible = true; + else + gridView.headerItem.isVisible = false; + //Pull to refresh + if (contentY <= -180 && !refresh && !isDragging) + ScreenPlay.installedListModel.reset(); + + } + anchors { topMargin: 0 rightMargin: 0 leftMargin: 30 } + header: Item { + property bool isVisible: false + height: 82 width: parent.width - gridView.leftMargin - property bool isVisible: false 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!"); } } @@ -114,29 +138,34 @@ Item { interval: 150 running: true onTriggered: { - animFadeIn.start() + animFadeIn.start(); } } - PropertyAnimation on opacity { - id: animFadeIn - from: 0 - to: 1 - running: false - duration: 1000 - } - Text { id: txtHeader + text: qsTr("Pull to refresh!") font.family: ScreenPlay.settings.font anchors.centerIn: parent color: "gray" font.pointSize: 18 } + + PropertyAnimation on opacity { + id: animFadeIn + + from: 0 + to: 1 + running: false + duration: 1000 + } + } + footer: Item { property bool isVisible: true + height: 100 opacity: 0 visible: isVisible @@ -144,6 +173,7 @@ Item { Text { id: txtFooter + font.family: ScreenPlay.settings.font text: qsTr("Get more Wallpaper & Widgets via the Steam workshop!") anchors.centerIn: parent @@ -153,40 +183,26 @@ Item { interval: 400 running: true onTriggered: { - animFadeInTxtFooter.start() + animFadeInTxtFooter.start(); } } PropertyAnimation on opacity { id: animFadeInTxtFooter + from: 0 to: 1 running: false duration: 1000 } - } - } - property bool isDragging: false - property bool isScrolling: gridView.verticalVelocity != 0 - onDragStarted: isDragging = true - onDragEnded: isDragging = false - onContentYChanged: { - if (contentY <= -180) { - gridView.headerItem.isVisible = true - } else { - gridView.headerItem.isVisible = false + } - //Pull to refresh - if (contentY <= -180 && !refresh && !isDragging) { - ScreenPlay.installedListModel.reset() - } } - model: ScreenPlay.installedListFilter - delegate: ScreenPlayItem { id: delegate + focus: true customTitle: m_title type: m_type @@ -197,28 +213,28 @@ Item { isScrolling: gridView.isScrolling onOpenContextMenu: { // Set the menu to the current item informations - contextMenu.publishedFileID = delegate.publishedFileID - contextMenu.absoluteStoragePath = delegate.absoluteStoragePath - - deleteDialog.currentItemIndex = itemIndex - - const pos = delegate.mapToItem(root, position.x, position.y) - + contextMenu.publishedFileID = delegate.publishedFileID; + contextMenu.absoluteStoragePath = delegate.absoluteStoragePath; + deleteDialog.currentItemIndex = itemIndex; + 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 ; - contextMenu.popup(pos.x, pos.y) + contextMenu.popup(pos.x, pos.y); } } + ScrollBar.vertical: ScrollBar { snapMode: ScrollBar.SnapOnRelease } + } Menu { id: contextMenu + property var publishedFileID: 0 property url absoluteStoragePath @@ -226,49 +242,54 @@ Item { text: qsTr("Open containing folder") icon.source: "qrc:/assets/icons/icon_folder_open.svg" onClicked: { - ScreenPlay.util.openFolderInExplorer( - contextMenu.absoluteStoragePath) + ScreenPlay.util.openFolderInExplorer(contextMenu.absoluteStoragePath); } } + MenuItem { text: qsTr("Deinstall Item") icon.source: "qrc:/assets/icons/icon_delete.svg" enabled: contextMenu.publishedFileID === 0 onClicked: { - deleteDialog.open() + deleteDialog.open(); } } + MenuItem { id: miWorkshop + text: qsTr("Open workshop Page") enabled: contextMenu.publishedFileID !== 0 icon.source: "qrc:/assets/icons/icon_steam.svg" onClicked: { - Qt.openUrlExternally( - "steam://url/CommunityFilePage/" + publishedFileID) + Qt.openUrlExternally("steam://url/CommunityFilePage/" + publishedFileID); } } + } Dialog { id: deleteDialog + + property int currentItemIndex: 0 + title: qsTr("Are you sure you want to delete this item?") standardButtons: Dialog.Ok | Dialog.Cancel modal: true dim: true anchors.centerIn: Overlay.overlay - property int currentItemIndex: 0 - - onAccepted: ScreenPlay.installedListModel.deinstallItemAt( - currentItemIndex) + onAccepted: ScreenPlay.installedListModel.deinstallItemAt(currentItemIndex) } Navigation { id: navWrapper + anchors { top: parent.top right: parent.right left: parent.left } + } + } diff --git a/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml b/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml index 96dce934..acf9be02 100644 --- a/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml +++ b/ScreenPlay/qml/Installed/InstalledWelcomeScreen.qml @@ -7,36 +7,42 @@ import "../Common" Item { id: installedUserHelper + signal helperButtonPressed(var pos) - anchors { - fill: parent - } state: "out" Component.onCompleted: state = "in" + anchors { + fill: parent + } + Image { id: imgBg + source: "qrc:/assets/images/Intro.png" anchors.fill: parent } Item { height: parent.height + anchors { top: parent.top - topMargin: parent.height * .5 + 50 + topMargin: parent.height * 0.5 + 50 right: parent.right left: parent.left } Image { id: imgShine + source: "qrc:/assets/images/Intro_shine.png" height: 1753 width: 1753 opacity: 0 anchors.centerIn: parent + RotationAnimator { target: imgShine from: 0 @@ -45,24 +51,30 @@ Item { running: true loops: Animation.Infinite } + } + } Image { id: imgLogo + source: "qrc:/assets/images/Early_Access.png" + width: 539 + height: 148 + sourceSize: Qt.size(width, height) + anchors { top: parent.top topMargin: -200 horizontalCenter: parent.horizontalCenter } - width: 539 - height: 148 - sourceSize: Qt.size(width, height) + } Text { id: txtHeadline + y: 80 text: qsTr("Get free Widgets and Wallpaper via the Steam Workshop") font.family: ScreenPlay.settings.font @@ -72,28 +84,34 @@ Item { font.weight: Font.Thin font.pointSize: 28 horizontalAlignment: Text.AlignHCenter + anchors { right: parent.right left: parent.left top: parent.top } + } Image { id: imgPC + source: "qrc:/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 } - width: 500 * .8 - height: 500 * .8 - sourceSize: Qt.size(width, height) + } Button { id: btnWorkshop + text: qsTr("Browse the Steam Workshop") Material.background: Material.color(Material.Orange) Material.foreground: "white" @@ -104,23 +122,26 @@ Item { icon.source: "qrc:/assets/icons/icon_steam.svg" icon.width: 18 icon.height: 18 + onClicked: helperButtonPressed(1) transform: [ Shake { id: animShake }, Grow { id: animGrow - centerX: btnWorkshop.width * .5 - centerY: btnWorkshop.height * .5 + + centerX: btnWorkshop.width * 0.5 + centerY: btnWorkshop.height * 0.5 loops: -1 } ] + anchors { bottom: parent.bottom bottomMargin: -100 horizontalCenter: parent.horizontalCenter } - onClicked: helperButtonPressed(1) + } states: [ @@ -136,6 +157,7 @@ Item { target: imgShine opacity: 0 } + PropertyChanges { target: imgPC opacity: 0 @@ -153,10 +175,12 @@ Item { opacity: 0 anchors.topMargin: -300 } + PropertyChanges { target: btnWorkshop anchors.bottomMargin: -100 } + }, State { name: "in" @@ -168,8 +192,9 @@ Item { PropertyChanges { target: imgShine - opacity: .5 + opacity: 0.5 } + PropertyChanges { target: imgPC opacity: 1 @@ -188,13 +213,14 @@ Item { opacity: 1 anchors.topMargin: 250 } + PropertyChanges { target: btnWorkshop anchors.bottomMargin: 50 } + } ] - transitions: [ Transition { from: "out" @@ -207,14 +233,16 @@ Item { property: "opacity" duration: 400 } + PropertyAnimation { targets: imgShine property: "opacity" duration: 600 } - } - SequentialAnimation { + } + + SequentialAnimation { PauseAnimation { duration: 500 } @@ -232,10 +260,10 @@ Item { duration: 600 easing.type: Easing.OutBack } + } SequentialAnimation { - PropertyAnimation { targets: imgLogo property: "opacity" @@ -249,44 +277,43 @@ Item { duration: 500 easing.type: Easing.InOutExpo } + } SequentialAnimation { - PauseAnimation { duration: 200 } + PropertyAnimation { targets: txtHeadline properties: "topMargin, opacity" duration: 1100 easing.type: Easing.InOutExpo } + } SequentialAnimation { - PauseAnimation { duration: 600 } + PropertyAnimation { targets: btnWorkshop properties: "bottomMargin" duration: 400 easing.type: Easing.OutBack } + ScriptAction { script: { - animShake.start(2000, 1000, -1) + animShake.start(2000, 1000, -1); } } + } + } ] } - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ - diff --git a/ScreenPlay/qml/Installed/Navigation.qml b/ScreenPlay/qml/Installed/Navigation.qml index 24843207..8ea2472c 100644 --- a/ScreenPlay/qml/Installed/Navigation.qml +++ b/ScreenPlay/qml/Installed/Navigation.qml @@ -2,40 +2,44 @@ import QtQuick 2.0 import QtQuick.Controls 2.14 import QtQuick.Controls.Material 2.12 import QtQuick.Controls.Styles 1.4 - import QtGraphicalEffects 1.0 import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Enums.InstalledType 1.0 import ScreenPlay.Enums.SearchType 1.0 - import "../Common" as Common Item { id: navWrapper + state: "out" height: 52 Rectangle { id: nav + color: Material.theme === Material.Light ? "white" : Material.background height: 50 + layer.enabled: true + anchors { top: parent.top right: parent.right left: parent.left } - layer.enabled: true + layer.effect: ElevationEffect { elevation: 2 } + } - Common.MouseHoverBlocker {} + Common.MouseHoverBlocker { + } Item { height: nav.height + anchors { top: parent.top left: parent.left @@ -44,7 +48,7 @@ Item { TabBar { height: parent.height - background: Item {} + anchors { top: parent.top topMargin: 5 @@ -60,15 +64,18 @@ Item { icon.width: 16 height: parent.height width: implicitWidth - background: Item {} font.weight: Font.Thin icon.source: "qrc:/assets/icons/icon_installed.svg" onClicked: { - setSidebarActive(false) - ScreenPlay.installedListFilter.sortBySearchType( - SearchType.All) + setSidebarActive(false); + ScreenPlay.installedListFilter.sortBySearchType(SearchType.All); } + + background: Item { + } + } + TabButton { text: qsTr("Scenes") icon.height: 16 @@ -76,15 +83,18 @@ Item { font.family: ScreenPlay.settings.font width: implicitWidth height: parent.height - background: Item {} font.weight: Font.Thin icon.source: "qrc:/assets/icons/icon_code.svg" onClicked: { - setSidebarActive(false) - ScreenPlay.installedListFilter.sortBySearchType( - SearchType.Scene) + setSidebarActive(false); + ScreenPlay.installedListFilter.sortBySearchType(SearchType.Scene); } + + background: Item { + } + } + TabButton { text: qsTr("Videos") icon.height: 16 @@ -92,15 +102,18 @@ Item { font.family: ScreenPlay.settings.font height: parent.height width: implicitWidth - background: Item {} font.weight: Font.Thin icon.source: "qrc:/assets/icons/icon_movie.svg" onClicked: { - setSidebarActive(false) - ScreenPlay.installedListFilter.sortBySearchType( - SearchType.Wallpaper) + setSidebarActive(false); + ScreenPlay.installedListFilter.sortBySearchType(SearchType.Wallpaper); } + + background: Item { + } + } + TabButton { text: qsTr("Widgets") icon.height: 16 @@ -108,71 +121,83 @@ Item { font.family: ScreenPlay.settings.font height: parent.height width: implicitWidth - background: Item {} font.weight: Font.Thin icon.source: "qrc:/assets/icons/icon_widgets.svg" onClicked: { - setSidebarActive(false) - ScreenPlay.installedListFilter.sortBySearchType( - SearchType.Widget) + setSidebarActive(false); + ScreenPlay.installedListFilter.sortBySearchType(SearchType.Widget); } + + background: Item { + } + } + + background: Item { + } + } Common.Search { height: parent.height + anchors { right: btnSortOrder.left rightMargin: 10 top: parent.top } + } ToolButton { id: btnSortOrder + property int sortOrder: Qt.DescendingOrder - onClicked: { - sortOrder = (sortOrder - === Qt.DescendingOrder) ? Qt.AscendingOrder : Qt.DescendingOrder - ScreenPlay.installedListFilter.setSortOrder(sortOrder) - } icon.source: (sortOrder === Qt.AscendingOrder) ? "qrc:/assets/icons/icon_sort-down-solid.svg" : "qrc:/assets/icons/icon_sort-up-solid.svg" icon.width: 12 icon.height: 12 + hoverEnabled: true + ToolTip.delay: 100 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + ToolTip.text: (sortOrder === Qt.AscendingOrder) ? qsTr("Install Date Ascending") : qsTr("Install Date Descending") + onClicked: { + sortOrder = (sortOrder === Qt.DescendingOrder) ? Qt.AscendingOrder : Qt.DescendingOrder; + ScreenPlay.installedListFilter.setSortOrder(sortOrder); + } + anchors { right: parent.right rightMargin: 10 top: parent.top verticalCenter: parent.verticalCenter } - hoverEnabled: true - ToolTip.delay: 100 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - ToolTip.text: (sortOrder === Qt.AscendingOrder) ? qsTr("Install Date Ascending") : qsTr( - "Install Date Descending") } + } states: [ State { name: "out" + PropertyChanges { target: navWrapper anchors.topMargin: -115 } + }, State { name: "in" + PropertyChanges { target: navWrapper anchors.topMargin: 0 } + } ] - transitions: [ Transition { from: "out" @@ -184,6 +209,7 @@ Item { duration: 400 easing.type: Easing.InOutQuart } + } ] } diff --git a/ScreenPlay/qml/Installed/ScreenPlayItem.qml b/ScreenPlay/qml/Installed/ScreenPlayItem.qml index 168cfb0d..34ba94dc 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItem.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItem.qml @@ -5,13 +5,10 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Controls.Styles 1.4 import ScreenPlay 1.0 import ScreenPlay.Enums.InstalledType 1.0 - import "../Common/Util.js" as JSUtil Item { id: root - width: 320 - height: 180 property string customTitle property string screenId @@ -23,37 +20,40 @@ Item { signal openContextMenu(point position) + width: 320 + height: 180 onTypeChanged: { if (JSUtil.isWidget(type)) { - icnType.source = "qrc:/assets/icons/icon_widgets.svg" - return + icnType.source = "qrc:/assets/icons/icon_widgets.svg"; + return ; } if (JSUtil.isScene(type)) { - icnType.source = "qrc:/assets/icons/icon_code.svg" - return + icnType.source = "qrc:/assets/icons/icon_code.svg"; + return ; } if (JSUtil.isVideo(type)) { - icnType.source = "qrc:/assets/icons/icon_movie.svg" - return + icnType.source = "qrc:/assets/icons/icon_movie.svg"; + return ; } } Timer { - interval: { - var itemIndexMax = itemIndex - if (itemIndex > 30) - itemIndexMax = 3 - - 5 * itemIndexMax * Math.random() - } - running: true onTriggered: showAnim.start() + interval: { + var itemIndexMax = itemIndex; + if (itemIndex > 30) + itemIndexMax = 3; + + 5 * itemIndexMax * Math.random(); + } } SequentialAnimation { id: showAnim + running: false + ParallelAnimation { OpacityAnimator { target: screenPlayItemWrapper @@ -62,6 +62,7 @@ Item { duration: 600 easing.type: Easing.OutCirc } + YAnimator { target: screenPlayItemWrapper from: 80 @@ -69,13 +70,15 @@ Item { duration: 500 easing.type: Easing.OutCirc } + ScaleAnimator { target: screenPlayItemWrapper - from: .5 + from: 0.5 to: 1 duration: 200 easing.type: Easing.OutCirc } + } OpacityAnimator { @@ -85,14 +88,11 @@ Item { duration: 800 easing.type: Easing.OutCirc } + } RectangularGlow { id: effect - anchors { - top: parent.top - topMargin: 3 - } height: parent.height width: parent.width @@ -102,16 +102,24 @@ Item { color: "black" opacity: 0 cornerRadius: 15 + + anchors { + top: parent.top + topMargin: 3 + } + } Item { id: screenPlayItemWrapper + width: 320 height: 180 opacity: 0 Image { id: mask + source: "qrc:/assets/images/Window.svg" sourceSize: Qt.size(root.width, root.height) visible: false @@ -121,6 +129,7 @@ Item { Item { id: itemWrapper + visible: false anchors.fill: parent @@ -141,6 +150,7 @@ Item { ScreenPlayItemImage { id: screenPlayItemImage + anchors.fill: parent enabled: visible visible: m_preview !== "" || m_previewGIF !== "" @@ -152,28 +162,34 @@ Item { Image { id: icnType + width: 20 height: 20 opacity: 0.25 source: "qrc:/assets/icons/icon_movie.svg" sourceSize: Qt.size(20, 20) + anchors { top: parent.top left: parent.left margins: 10 } + } Rectangle { color: "#AAffffff" height: 30 visible: false + anchors { right: parent.right left: parent.left bottom: parent.bottom } + } + } OpacityMask { @@ -187,25 +203,25 @@ Item { cursorShape: Qt.PointingHandCursor acceptedButtons: Qt.LeftButton | Qt.RightButton onEntered: { - root.state = "hover" - screenPlayItemImage.state = "hover" - screenPlayItemImage.enter() + root.state = "hover"; + screenPlayItemImage.state = "hover"; + screenPlayItemImage.enter(); } onExited: { - root.state = "" - screenPlayItemImage.state = "loaded" - screenPlayItemImage.exit() + root.state = ""; + screenPlayItemImage.state = "loaded"; + screenPlayItemImage.exit(); } - onClicked: { - if (mouse.button === Qt.LeftButton) { - ScreenPlay.util.setSidebarItem(root.screenId, root.type) - } else if (mouse.button === Qt.RightButton) { - root.openContextMenu(Qt.point(mouseX, mouseY)) - } + if (mouse.button === Qt.LeftButton) + ScreenPlay.util.setSidebarItem(root.screenId, root.type); + else if (mouse.button === Qt.RightButton) + root.openContextMenu(Qt.point(mouseX, mouseY)); } } + } + } transitions: [ @@ -219,24 +235,28 @@ Item { from: 1 to: 1.05 } + ScaleAnimator { target: effect duration: 80 from: 1 to: 1.05 } + OpacityAnimator { target: icnType duration: 80 from: 0.25 - to: .8 + to: 0.8 } + OpacityAnimator { target: effect duration: 80 from: 0.6 to: 1 } + }, Transition { from: "hover" @@ -248,24 +268,28 @@ Item { from: 1.05 to: 1 } + ScaleAnimator { target: effect duration: 80 from: 1.05 to: 1 } + OpacityAnimator { target: icnType duration: 80 - from: .8 + from: 0.8 to: 0.25 } + OpacityAnimator { target: effect duration: 80 from: 1 to: 0.5 } + } ] } diff --git a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml index 417ab52a..9145fa3b 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml @@ -2,9 +2,6 @@ import QtQuick 2.12 Item { id: root - width: 320 - height: 121 - state: "loading" property string absoluteStoragePath property string sourceImage @@ -12,54 +9,60 @@ Item { property var type: InstalledType.Unknown function enter() { - if (root.sourceImageGIF != "") { - loader_imgGIFPreview.sourceComponent = component_imgGIFPreview - } + if (root.sourceImageGIF != "") + loader_imgGIFPreview.sourceComponent = component_imgGIFPreview; + } function exit() { - root.state = "loaded" - loader_imgGIFPreview.sourceComponent = null + root.state = "loaded"; + loader_imgGIFPreview.sourceComponent = null; } + width: 320 + height: 121 + state: "loading" + Image { id: image + anchors.fill: parent asynchronous: true cache: true fillMode: Image.PreserveAspectCrop source: { if (root.sourceImage === "") - return "qrc:/assets/images/missingPreview.png" + return "qrc:/assets/images/missingPreview.png"; - return root.screenPreview === "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl( - absoluteStoragePath + "/" + root.sourceImage) + return root.screenPreview === "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(absoluteStoragePath + "/" + root.sourceImage); } - onStatusChanged: { if (image.status === Image.Ready) { - root.state = "loaded" + root.state = "loaded"; } else if (image.status === Image.Error) { - source = "qrc:/assets/images/missingPreview.png" - root.state = "loaded" + source = "qrc:/assets/images/missingPreview.png"; + root.state = "loaded"; } } } Component { id: component_imgGIFPreview + AnimatedImage { id: imgGIFPreview + asynchronous: true playing: true - source: root.sourceImageGIF - === "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl( - absoluteStoragePath + "/" + root.sourceImageGIF) + source: root.sourceImageGIF === "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(absoluteStoragePath + "/" + root.sourceImageGIF) fillMode: Image.PreserveAspectCrop } + } + Loader { id: loader_imgGIFPreview + anchors.fill: parent opacity: 0 } @@ -76,6 +79,7 @@ Item { to: 1 easing.type: Easing.OutQuart } + }, Transition { from: "hover" @@ -88,6 +92,7 @@ Item { to: 0 easing.type: Easing.OutQuart } + }, Transition { from: "loaded" @@ -101,6 +106,7 @@ Item { to: 1 easing.type: Easing.OutQuart } + } ] } diff --git a/ScreenPlay/qml/Installed/Sidebar.qml b/ScreenPlay/qml/Installed/Sidebar.qml index 4bd6e54f..77ba257e 100644 --- a/ScreenPlay/qml/Installed/Sidebar.qml +++ b/ScreenPlay/qml/Installed/Sidebar.qml @@ -5,112 +5,98 @@ import QtQuick.Extras 1.4 import QtQuick.Layouts 1.12 import QtQuick.Controls.Material 2.12 import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 import ScreenPlay.Enums.FillMode 1.0 import ScreenPlay.Enums.InstalledType 1.0 - import "../Monitors" import "../Common" as Common import "../Common/Util.js" as JSUtil Item { id: root - width: 400 - state: "inactive" property real navHeight property var type: InstalledType.QMLWallpaper property string contentFolderName - onContentFolderNameChanged: { - txtHeadline.text = ScreenPlay.installedListModel.get( - root.contentFolderName).m_title + function indexOfValue(model, value) { + for (var i = 0; i < model.length; i++) { + let ourValue = model[i].value; + if (value === ourValue) + return i; - const hasPreviewGif = ScreenPlay.installedListModel.get( - root.contentFolderName).m_previewGIF !== undefined - if (!hasPreviewGif) { - image.source = Qt.resolvedUrl( - ScreenPlay.globalVariables.localStoragePath + "/" - + root.contentFolderName + "/" + ScreenPlay.installedListModel.get( - root.contentFolderName).m_preview) - image.playing = false - } else { - - image.source = Qt.resolvedUrl( - ScreenPlay.globalVariables.localStoragePath + "/" - + root.contentFolderName + "/" + ScreenPlay.installedListModel.get( - root.contentFolderName).m_previewGIF) - image.playing = true } - - if (JSUtil.isWidget(root.type) - || (monitorSelection.activeMonitors.length > 0)) { - btnSetWallpaper.enabled = true - return - } - - btnSetWallpaper.enabled = false + return -1; } - function indexOfValue(model, value) { - - for (var i = 0; i < model.length; i++) { - let ourValue = model[i].value - if (value === ourValue) - return i + width: 400 + state: "inactive" + onContentFolderNameChanged: { + txtHeadline.text = ScreenPlay.installedListModel.get(root.contentFolderName).m_title; + const hasPreviewGif = ScreenPlay.installedListModel.get(root.contentFolderName).m_previewGIF !== undefined; + if (!hasPreviewGif) { + image.source = Qt.resolvedUrl(ScreenPlay.globalVariables.localStoragePath + "/" + root.contentFolderName + "/" + ScreenPlay.installedListModel.get(root.contentFolderName).m_preview); + image.playing = false; + } else { + image.source = Qt.resolvedUrl(ScreenPlay.globalVariables.localStoragePath + "/" + root.contentFolderName + "/" + ScreenPlay.installedListModel.get(root.contentFolderName).m_previewGIF); + image.playing = true; } - return -1 + if (JSUtil.isWidget(root.type) || (monitorSelection.activeMonitors.length > 0)) { + btnSetWallpaper.enabled = true; + return ; + } + btnSetWallpaper.enabled = false; } Connections { - target: ScreenPlay.util - function onSetSidebarItem(folderName, type) { - // Toggle sidebar if clicked on the same content twice - if (root.contentFolderName === folderName - && root.state !== "inactive") { - root.state = "inactive" - return + if (root.contentFolderName === folderName && root.state !== "inactive") { + root.state = "inactive"; + return ; } - - root.contentFolderName = folderName - root.type = type - + root.contentFolderName = folderName; + root.type = type; if (JSUtil.isWallpaper(root.type)) { - if (type === InstalledType.VideoWallpaper) { - root.state = "activeWallpaper" - } else { - root.state = "activeScene" - } - btnSetWallpaper.text = qsTr("Set Wallpaper") + if (type === InstalledType.VideoWallpaper) + root.state = "activeWallpaper"; + else + root.state = "activeScene"; + btnSetWallpaper.text = qsTr("Set Wallpaper"); } else { - root.state = "activeWidget" - btnSetWallpaper.text = qsTr("Set Widget") + root.state = "activeWidget"; + btnSetWallpaper.text = qsTr("Set Widget"); } } + + target: ScreenPlay.util } - Common.MouseHoverBlocker {} + Common.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 { id: sidebarWrapper + anchors.fill: parent Item { id: navBackground + height: navHeight + anchors { top: parent.top right: parent.right @@ -121,21 +107,27 @@ Item { anchors.fill: parent start: Qt.point(0, 0) end: Qt.point(400, 0) + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "transparent" } + GradientStop { position: 0.1 color: "#AAffffff" } + GradientStop { - position: 1.0 + position: 1 color: "#ffffff" } + } + } + } Item { @@ -150,6 +142,7 @@ Item { Rectangle { id: imageWrapper + height: 237 color: "#2b2b2b" anchors.right: parent.right @@ -159,42 +152,50 @@ Item { AnimatedImage { id: image + playing: true fillMode: Image.PreserveAspectCrop asynchronous: true anchors.fill: parent onStatusChanged: { - if (image.status === Image.Error) { - source = "qrc:/assets/images/missingPreview.png" - } + if (image.status === Image.Error) + source = "qrc:/assets/images/missingPreview.png"; + } } + LinearGradient { id: tabShadow + height: 50 cached: true + start: Qt.point(0, 50) + end: Qt.point(0, 0) anchors { bottom: parent.bottom right: parent.right left: parent.left } - start: Qt.point(0, 50) - end: Qt.point(0, 0) + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#EE000000" } + GradientStop { - position: 1.0 + position: 1 color: "#00000000" } + } + } Text { id: txtHeadline + text: qsTr("Headline") font.family: ScreenPlay.settings.font font.weight: Font.Thin @@ -203,16 +204,19 @@ Item { color: "white" wrapMode: Text.WordWrap height: 50 + anchors { bottom: parent.bottom right: parent.right margins: 20 left: parent.left } + } MouseArea { id: button + height: 50 width: 50 anchors.top: parent.top @@ -222,12 +226,15 @@ Item { Image { id: imgBack + source: "qrc:/assets/icons/icon_arrow_right.svg" sourceSize: Qt.size(15, 15) fillMode: Image.PreserveAspectFit anchors.centerIn: parent } + } + } ColumnLayout { @@ -245,6 +252,7 @@ Item { Text { id: txtHeadlineMonitor + height: 20 text: qsTr("Select a Monitor to display the content") font.family: ScreenPlay.settings.font @@ -255,6 +263,7 @@ Item { MonitorSelection { id: monitorSelection + height: 180 Layout.fillWidth: true availableWidth: width @@ -262,17 +271,21 @@ Item { fontSize: 11 onActiveMonitorsChanged: { if (JSUtil.isWidget(root.type)) { - btnSetWallpaper.enabled = true - return + btnSetWallpaper.enabled = true; + return ; } - - btnSetWallpaper.enabled = activeMonitors.length > 0 + btnSetWallpaper.enabled = activeMonitors.length > 0; } } + } Common.Slider { id: sliderVolume + + Layout.fillWidth: true + headline: qsTr("Set Volume") + slider { stepSize: 0.01 from: 0 @@ -280,8 +293,6 @@ Item { to: 1 } - Layout.fillWidth: true - headline: qsTr("Set Volume") } ColumnLayout { @@ -290,9 +301,9 @@ Item { Text { id: txtComboBoxFillMode + visible: false text: qsTr("Fill Mode") - font.family: ScreenPlay.settings.font verticalAlignment: Text.AlignVCenter font.pointSize: 10 @@ -300,40 +311,43 @@ Item { wrapMode: Text.WrapAnywhere Layout.fillWidth: true } + ComboBox { id: cbVideoFillMode + visible: false Layout.fillWidth: true textRole: "text" valueRole: "value" font.family: ScreenPlay.settings.font - Component.onCompleted: { - cbVideoFillMode.currentIndex = root.indexOfValue( - cbVideoFillMode.model, - ScreenPlay.settings.videoFillMode) - } model: [{ - "value": FillMode.Stretch, - "text": qsTr("Stretch") - }, { - "value": FillMode.Fill, - "text": qsTr("Fill") - }, { - "value": FillMode.Contain, - "text": qsTr("Contain") - }, { - "value": FillMode.Cover, - "text": qsTr("Cover") - }, { - "value": FillMode.Scale_Down, - "text": qsTr("Scale-Down") - }] + "value": FillMode.Stretch, + "text": qsTr("Stretch") + }, { + "value": FillMode.Fill, + "text": qsTr("Fill") + }, { + "value": FillMode.Contain, + "text": qsTr("Contain") + }, { + "value": FillMode.Cover, + "text": qsTr("Cover") + }, { + "value": FillMode.Scale_Down, + "text": qsTr("Scale-Down") + }] + Component.onCompleted: { + cbVideoFillMode.currentIndex = root.indexOfValue(cbVideoFillMode.model, ScreenPlay.settings.videoFillMode); + } } + } + } Button { id: btnSetWallpaper + Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font @@ -341,6 +355,29 @@ Item { icon.color: "white" icon.width: 16 icon.height: 16 + onClicked: { + const absoluteStoragePath = ScreenPlay.globalVariables.localStoragePath + "/" + root.contentFolderName; + const previewImage = ScreenPlay.installedListModel.get(root.contentFolderName).m_preview; + if (JSUtil.isWallpaper(root.type)) { + let activeMonitors = monitorSelection.getActiveMonitors(); + // TODO Alert user to choose a monitor + if (activeMonitors.length === 0) + return ; + + // We only have sliderVolume if it is a VideoWallpaper + let volume = 0; + if (type === InstalledType.VideoWallpaper) + volume = Math.round(sliderVolume.slider.value * 100) / 100; + + const screenFile = ScreenPlay.installedListModel.get(root.contentFolderName).m_file; + ScreenPlay.screenPlayManager.createWallpaper(root.type, cbVideoFillMode.currentValue, absoluteStoragePath, previewImage, screenFile, activeMonitors, volume, 1, {}, true); + } + if (JSUtil.isWidget(root.type)) + ScreenPlay.screenPlayManager.createWidget(type, Qt.point(0, 0), absoluteStoragePath, previewImage, {}, true); + + root.state = "inactive"; + monitorSelection.reset(); + } anchors { bottom: parent.bottom @@ -348,47 +385,10 @@ Item { horizontalCenter: parent.horizontalCenter } - onClicked: { - const absoluteStoragePath = ScreenPlay.globalVariables.localStoragePath - + "/" + root.contentFolderName - const previewImage = ScreenPlay.installedListModel.get( - root.contentFolderName).m_preview - if (JSUtil.isWallpaper(root.type)) { - let activeMonitors = monitorSelection.getActiveMonitors( - ) - - // TODO Alert user to choose a monitor - if (activeMonitors.length === 0) - return - - // We only have sliderVolume if it is a VideoWallpaper - let volume = 0.0 - if (type === InstalledType.VideoWallpaper) { - volume = Math.round( - sliderVolume.slider.value * 100) / 100 - } - - const screenFile = ScreenPlay.installedListModel.get( - root.contentFolderName).m_file - - ScreenPlay.screenPlayManager.createWallpaper( - root.type, cbVideoFillMode.currentValue, - absoluteStoragePath, previewImage, - screenFile, activeMonitors, volume, - 1.0, {}, true) - } - - if (JSUtil.isWidget(root.type)) { - ScreenPlay.screenPlayManager.createWidget( - type, Qt.point(0, 0), absoluteStoragePath, - previewImage, {}, true) - } - - root.state = "inactive" - monitorSelection.reset() - } } + } + } states: [ @@ -399,11 +399,13 @@ Item { target: root anchors.rightMargin: -root.width } + PropertyChanges { target: image opacity: 0 anchors.topMargin: 20 } + }, State { name: "activeWidget" @@ -424,10 +426,12 @@ Item { opacity: 1 anchors.topMargin: 0 } + PropertyChanges { target: txtHeadlineMonitor opacity: 0 } + }, State { name: "activeWallpaper" @@ -437,6 +441,7 @@ Item { opacity: 1 anchors.topMargin: 0 } + PropertyChanges { target: txtHeadlineMonitor opacity: 1 @@ -453,6 +458,7 @@ Item { opacity: 1 visible: true } + }, State { name: "activeScene" @@ -462,28 +468,32 @@ Item { 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 { target: image property: "opacity" duration: 200 } + NumberAnimation { target: image property: "anchors.topMargin" @@ -496,6 +506,7 @@ Item { duration: 250 easing.type: Easing.OutQuart } + }, Transition { to: "activeWidget" @@ -515,17 +526,22 @@ Item { property: "opacity" duration: 200 } + NumberAnimation { target: image property: "anchors.topMargin" duration: 100 } + } + } + }, Transition { to: "activeWallpaper" from: "*" + SequentialAnimation { NumberAnimation { target: root @@ -540,16 +556,21 @@ Item { property: "opacity" duration: 200 } + NumberAnimation { target: image property: "anchors.topMargin" duration: 100 } + } + } + }, Transition { to: "activeScene" + SequentialAnimation { NumberAnimation { target: root @@ -564,13 +585,17 @@ Item { property: "opacity" duration: 200 } + NumberAnimation { target: image property: "anchors.topMargin" duration: 100 } + } + } + } ] } diff --git a/ScreenPlay/qml/Monitors/DefaultVideoControls.qml b/ScreenPlay/qml/Monitors/DefaultVideoControls.qml index e7fe7a20..cb885fe5 100644 --- a/ScreenPlay/qml/Monitors/DefaultVideoControls.qml +++ b/ScreenPlay/qml/Monitors/DefaultVideoControls.qml @@ -3,71 +3,68 @@ import QtQuick.Controls 2.3 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.2 import QtQuick.Layouts 1.3 - import ScreenPlay 1.0 import ScreenPlay.Enums.FillMode 1.0 - import "../Common/" as SP ColumnLayout { id: root - spacing: 10 - state: "hidden" - clip: true property int activeMonitorIndex property ScreenPlayWallpaper wallpaper - onWallpaperChanged: { - if (!wallpaper) { - slPlaybackRate.slider.value = 1 - return - } - slVolume.slider.value = wallpaper.volume - slPlaybackRate.slider.value = wallpaper.playbackRate - } function indexOfValue(model, value) { - for (var i = 0; i < model.length; i++) { - let ourValue = model[i].value + let ourValue = model[i].value; if (value === ourValue) - return i + return i; + } - return -1 + return -1; + } + + spacing: 10 + state: "hidden" + clip: true + onWallpaperChanged: { + if (!wallpaper) { + slPlaybackRate.slider.value = 1; + return ; + } + slVolume.slider.value = wallpaper.volume; + slPlaybackRate.slider.value = wallpaper.playbackRate; } SP.Slider { id: slVolume + headline: qsTr("Volume") slider.stepSize: 0.1 - slider.onValueChanged: { - ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - activeMonitorIndex, "volume", - (Math.round(slVolume.slider.value * 100) / 100)) - } - Layout.fillWidth: true Layout.leftMargin: 10 Layout.rightMargin: 10 + slider.onValueChanged: { + ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(activeMonitorIndex, "volume", (Math.round(slVolume.slider.value * 100) / 100)); + } } + SP.Slider { id: slPlaybackRate + headline: qsTr("Playback rate") - slider.onValueChanged: ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - activeMonitorIndex, "playbackRate", - (Math.round(slPlaybackRate.slider.value * 100) / 100)) + slider.onValueChanged: ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(activeMonitorIndex, "playbackRate", (Math.round(slPlaybackRate.slider.value * 100) / 100)) Layout.fillWidth: true slider.stepSize: 0.1 slider.to: 1 Layout.leftMargin: 10 Layout.rightMargin: 10 } + SP.Slider { id: slCurrentVideoTime + headline: qsTr("Current Video Time") - slider.onValueChanged: ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - activeMonitorIndex, "currentTime", - (Math.round(slCurrentVideoTime.slider.value * 100) / 100)) + slider.onValueChanged: ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(activeMonitorIndex, "currentTime", (Math.round(slCurrentVideoTime.slider.value * 100) / 100)) Layout.fillWidth: true slider.stepSize: 0.1 Layout.leftMargin: 10 @@ -82,6 +79,7 @@ ColumnLayout { Text { id: txtComboBoxFillMode + text: qsTr("Fill Mode") font.family: ScreenPlay.settings.font verticalAlignment: Text.AlignVCenter @@ -90,70 +88,73 @@ ColumnLayout { wrapMode: Text.WrapAnywhere Layout.fillWidth: true } + ComboBox { id: settingsComboBox + Layout.fillWidth: true Layout.leftMargin: 10 - onActivated: { - ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - activeMonitorIndex, "fillmode", - settingsComboBox.currentText) - } - textRole: "text" valueRole: "value" - currentIndex: root.indexOfValue(settingsComboBox.model, - ScreenPlay.settings.videoFillMode) - + currentIndex: root.indexOfValue(settingsComboBox.model, ScreenPlay.settings.videoFillMode) model: [{ - "value": FillMode.Stretch, - "text": qsTr("Stretch") - }, { - "value": FillMode.Fill, - "text": qsTr("Fill") - }, { - "value": FillMode.Contain, - "text": qsTr("Contain") - }, { - "value": FillMode.Cover, - "text": qsTr("Cover") - }, { - "value": FillMode.Scale_Down, - "text": qsTr("Scale_Down") - }] + "value": FillMode.Stretch, + "text": qsTr("Stretch") + }, { + "value": FillMode.Fill, + "text": qsTr("Fill") + }, { + "value": FillMode.Contain, + "text": qsTr("Contain") + }, { + "value": FillMode.Cover, + "text": qsTr("Cover") + }, { + "value": FillMode.Scale_Down, + "text": qsTr("Scale_Down") + }] + onActivated: { + ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(activeMonitorIndex, "fillmode", settingsComboBox.currentText); + } } + } states: [ State { name: "visible" + PropertyChanges { target: root opacity: 1 anchors.topMargin: 20 } + }, State { name: "hidden" + PropertyChanges { target: root opacity: 0 anchors.topMargin: -50 } + } ] - transitions: [ Transition { from: "visible" to: "hidden" reversible: true + PropertyAnimation { target: root duration: 300 easing.type: Easing.InOutQuart properties: "anchors.topMargin, opacity" } + } ] } diff --git a/ScreenPlay/qml/Monitors/MonitorSelection.qml b/ScreenPlay/qml/Monitors/MonitorSelection.qml index 58908f18..967b0225 100644 --- a/ScreenPlay/qml/Monitors/MonitorSelection.qml +++ b/ScreenPlay/qml/Monitors/MonitorSelection.qml @@ -7,166 +7,135 @@ import ScreenPlay 1.0 Rectangle { id: root - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) - height: availableHeight - width: parent.width - clip: true - layer.enabled: true - layer.effect: InnerShadow { - cached: true - fast: true - smooth: true - radius: 32 - spread: .8 - verticalOffset: 3 - color: "#55000000" - } - // Width of the Sidebar or Space that should be used property real availableWidth: 0 property real availableHeight: 0 property int fontSize: 12 - property bool monitorWithoutContentSelectable: true property bool multipleMonitorsSelectable: false - // We preselect the main monitor property var activeMonitors: [0] - property alias background: root.color property alias radius: root.radius signal requestProjectSettings(int index, var installedType, string appID) - Component.onCompleted: { - resize() - } - - Connections { - target: ScreenPlay.monitorListModel - function onMonitorReloadCompleted() { - resize() - } - } - function selectOnly(index) { for (var i = 0; i < rp.count; i++) { - if (i === index) { - rp.itemAt(i).isSelected = true - continue + rp.itemAt(i).isSelected = true; + continue; } - rp.itemAt(i).isSelected = false + rp.itemAt(i).isSelected = false; } } function reset() { for (var i = 0; i < rp.count; i++) { - rp.itemAt(i).isSelected = false + rp.itemAt(i).isSelected = false; } - rp.itemAt(0).isSelected = true - getActiveMonitors() + rp.itemAt(0).isSelected = true; + getActiveMonitors(); } function getActiveMonitors() { - root.activeMonitors = [] + root.activeMonitors = []; for (var i = 0; i < rp.count; i++) { - if (rp.itemAt(i).isSelected) { - root.activeMonitors.push(rp.itemAt(i).index) - } + if (rp.itemAt(i).isSelected) + root.activeMonitors.push(rp.itemAt(i).index); + } // Must be called manually. When QML properties are getting altered in js the // property binding breaks - root.activeMonitorsChanged() - return root.activeMonitors + root.activeMonitorsChanged(); + return root.activeMonitors; } function selectMonitorAt(index) { - if (!multipleMonitorsSelectable) { - selectOnly(index) - } else { - rp.itemAt(index).isSelected = !rp.itemAt(index).isSelected - } - - getActiveMonitors() - + if (!multipleMonitorsSelectable) + selectOnly(index); + else + rp.itemAt(index).isSelected = !rp.itemAt(index).isSelected; + getActiveMonitors(); if (rp.itemAt(index).hasContent) - root.requestProjectSettings(index, rp.itemAt(index).installedType, - rp.itemAt(index).appID) + root.requestProjectSettings(index, rp.itemAt(index).installedType, rp.itemAt(index).appID); + } function resize() { - - var absoluteDesktopSize = ScreenPlay.monitorListModel.getAbsoluteDesktopSize() - var isWidthGreaterThanHeight = false - var windowsDelta = 0 - + var absoluteDesktopSize = ScreenPlay.monitorListModel.getAbsoluteDesktopSize(); + var isWidthGreaterThanHeight = false; + var windowsDelta = 0; if (absoluteDesktopSize.width < absoluteDesktopSize.height) { - windowsDelta = absoluteDesktopSize.width / absoluteDesktopSize.height - isWidthGreaterThanHeight = false + windowsDelta = absoluteDesktopSize.width / absoluteDesktopSize.height; + isWidthGreaterThanHeight = false; } else { - windowsDelta = absoluteDesktopSize.height / absoluteDesktopSize.width - isWidthGreaterThanHeight = true + windowsDelta = absoluteDesktopSize.height / absoluteDesktopSize.width; + isWidthGreaterThanHeight = true; } + if (rp.count === 1) + availableWidth = availableWidth * 0.66; - if (rp.count === 1) { - availableWidth = availableWidth * .66 - } - - var dynamicHeight = availableWidth * windowsDelta - var dynamicWidth = availableHeight * windowsDelta - + var dynamicHeight = availableWidth * windowsDelta; + var dynamicWidth = availableHeight * windowsDelta; // Delta (height/width) - var monitorHeightRationDelta = 0 - var monitorWidthRationDelta = 0 - + var monitorHeightRationDelta = 0; + var monitorWidthRationDelta = 0; if (isWidthGreaterThanHeight) { - monitorHeightRationDelta = dynamicHeight / absoluteDesktopSize.height - monitorWidthRationDelta = availableWidth / absoluteDesktopSize.width + monitorHeightRationDelta = dynamicHeight / absoluteDesktopSize.height; + monitorWidthRationDelta = availableWidth / absoluteDesktopSize.width; } else { - monitorHeightRationDelta = availableHeight / absoluteDesktopSize.height - monitorWidthRationDelta = dynamicWidth / absoluteDesktopSize.width + monitorHeightRationDelta = availableHeight / absoluteDesktopSize.height; + monitorWidthRationDelta = dynamicWidth / absoluteDesktopSize.width; } - for (var i = 0; i < rp.count; i++) { - rp.itemAt(i).index = i - rp.itemAt(i).height = rp.itemAt(i).height * monitorHeightRationDelta - rp.itemAt(i).width = rp.itemAt(i).width * monitorWidthRationDelta - rp.itemAt(i).x = rp.itemAt(i).x * monitorWidthRationDelta - rp.itemAt(i).y = rp.itemAt(i).y * monitorHeightRationDelta - - rp.contentWidth += rp.itemAt(i).width - rp.contentHeight += rp.itemAt(i).height + rp.itemAt(i).index = i; + rp.itemAt(i).height = rp.itemAt(i).height * monitorHeightRationDelta; + rp.itemAt(i).width = rp.itemAt(i).width * monitorWidthRationDelta; + rp.itemAt(i).x = rp.itemAt(i).x * monitorWidthRationDelta; + rp.itemAt(i).y = rp.itemAt(i).y * monitorHeightRationDelta; + rp.contentWidth += rp.itemAt(i).width; + rp.contentHeight += rp.itemAt(i).height; } - rp.contentWidth += 200 - rp.contentHeight += 200 + rp.contentWidth += 200; + rp.contentHeight += 200; + } + + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) + height: availableHeight + width: parent.width + clip: true + layer.enabled: true + Component.onCompleted: { + resize(); + } + + Connections { + function onMonitorReloadCompleted() { + resize(); + } + + target: ScreenPlay.monitorListModel } Flickable { id: flickable - anchors.fill: parent + anchors.fill: parent contentWidth: rp.contentWidth contentHeight: rp.contentHeight - ScrollBar.vertical: ScrollBar { - policy: ScrollBar.AlwaysOff - - snapMode: ScrollBar.SnapOnRelease - } - ScrollBar.horizontal: ScrollBar { - policy: ScrollBar.AlwaysOff - - snapMode: ScrollBar.SnapOnRelease - } Repeater { id: rp - model: ScreenPlay.monitorListModel + property int contentWidth property int contentHeight + + model: ScreenPlay.monitorListModel + delegate: MonitorSelectionItem { id: delegate + monitorID: m_monitorID monitorName: m_name appID: m_appID @@ -184,6 +153,30 @@ Rectangle { monitorWithoutContentSelectable: root.monitorWithoutContentSelectable onMonitorSelected: root.selectMonitorAt(delegate.index) } + } + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOff + snapMode: ScrollBar.SnapOnRelease + } + + ScrollBar.horizontal: ScrollBar { + policy: ScrollBar.AlwaysOff + snapMode: ScrollBar.SnapOnRelease + } + } + + layer.effect: InnerShadow { + cached: true + fast: true + smooth: true + radius: 32 + spread: 0.8 + verticalOffset: 3 + color: "#55000000" + } + // Width of the Sidebar or Space that should be used + } diff --git a/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml b/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml index fde261cb..33f8ceb0 100644 --- a/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml +++ b/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml @@ -1,7 +1,6 @@ import QtQuick 2.12 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.12 - import ScreenPlay 1.0 import ScreenPlay.Enums.InstalledType 1.0 @@ -18,41 +17,42 @@ Item { property var installedType: InstalledType.QMLWallpaper property bool monitorWithoutContentSelectable: true property bool hasContent: appID !== "" - - onPreviewImageChanged: { - if (previewImage === "") { - imgPreview.opacity = 0 - } else { - imgPreview.source = Qt.resolvedUrl("file:///" + previewImage) - imgPreview.opacity = 1 - } - } - property int fontSize: 10 property int index property bool isSelected: false - onIsSelectedChanged: root.state = isSelected ? "selected" : "default" signal monitorSelected(var index) + onIsSelectedChanged: root.state = isSelected ? "selected" : "default" + onPreviewImageChanged: { + if (previewImage === "") { + imgPreview.opacity = 0; + } else { + imgPreview.source = Qt.resolvedUrl("file:///" + previewImage); + imgPreview.opacity = 1; + } + } + Text { text: monitorSize.width + "x" + monitorSize.height - anchors { - horizontalCenter: parent.horizontalCenter - top: wrapper.bottom - topMargin: 5 - } color: Material.foreground - horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.pointSize: root.fontSize font.family: ScreenPlay.settings.font wrapMode: Text.WrapAnywhere + + anchors { + horizontalCenter: parent.horizontalCenter + top: wrapper.bottom + topMargin: 5 + } + } Rectangle { id: wrapper + color: "#828282" anchors.fill: parent anchors.margins: 10 @@ -63,6 +63,7 @@ Item { Image { id: imgPreview + sourceSize: Qt.size(parent.width, parent.height) anchors.margins: 3 opacity: 0 @@ -84,30 +85,35 @@ Item { cursorShape: Qt.PointingHandCursor onClicked: { if (monitorWithoutContentSelectable) { - monitorSelected(index) - return + monitorSelected(index); + return ; } - if (root.hasContent && !root.monitorWithoutContentSelectable) - monitorSelected(index) + monitorSelected(index); + } } + } states: [ State { name: "default" + PropertyChanges { target: wrapper border.color: "#373737" } + }, State { name: "selected" + PropertyChanges { target: wrapper border.color: "#F28E0D" } + } ] transitions: [ @@ -115,12 +121,14 @@ Item { from: "default" to: "selected" reversible: true + PropertyAnimation { target: wrapper duration: 200 easing.type: Easing.InOutQuart property: "border.color" } + } ] } diff --git a/ScreenPlay/qml/Monitors/Monitors.qml b/ScreenPlay/qml/Monitors/Monitors.qml index 091dc56c..f0a998d2 100644 --- a/ScreenPlay/qml/Monitors/Monitors.qml +++ b/ScreenPlay/qml/Monitors/Monitors.qml @@ -3,51 +3,40 @@ import QtQuick.Controls 2.3 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.2 import QtQuick.Layouts 1.3 - import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay 1.0 - import ScreenPlay.Enums.InstalledType 1.0 import "../Common/" as SP Popup { id: monitors - width: 1000 - height: 500 - dim: true - anchors.centerIn: Overlay.overlay - - modal: true - focus: true - background: Rectangle { - anchors.fill: parent - radius: 4 - layer.enabled: true - layer.effect: ElevationEffect { - elevation: 6 - } - color: Material.theme === Material.Light ? "white" : Material.background - } property string activeMonitorName: "" property int activeMonitorIndex - Connections { - target: ScreenPlay.util - function onRequestToggleWallpaperConfiguration() { - monitors.open() - } + width: 1000 + height: 500 + dim: true + anchors.centerIn: Overlay.overlay + modal: true + focus: true + onOpened: { + monitorSelection.selectMonitorAt(0); } - onOpened: { - monitorSelection.selectMonitorAt(0) + Connections { + function onRequestToggleWallpaperConfiguration() { + monitors.open(); + } + + target: ScreenPlay.util } Item { id: monitorsSettingsWrapper clip: true + anchors { fill: parent margins: 10 @@ -55,129 +44,139 @@ Popup { Item { id: itmLeftWrapper - width: parent.width * .5 + + 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: ScreenPlay.settings.font font.weight: Font.Light width: 400 + anchors { top: parent.top topMargin: 10 left: parent.left leftMargin: 20 } + } + MonitorSelection { id: monitorSelection + radius: 3 height: 200 - width: parent.width * .9 + width: parent.width * 0.9 multipleMonitorsSelectable: false monitorWithoutContentSelectable: false + availableWidth: width - 20 + availableHeight: 150 + onRequestProjectSettings: { + if (installedType === InstalledType.VideoWallpaper) { + videoControlWrapper.state = "visible"; + customPropertiesGridView.visible = false; + const wallpaper = ScreenPlay.screenPlayManager.getWallpaperByAppID(appID); + videoControlWrapper.wallpaper = wallpaper; + } else { + videoControlWrapper.state = "hidden"; + customPropertiesGridView.visible = true; + ScreenPlay.screenPlayManager.requestProjectSettingsAtMonitorIndex(index); + } + activeMonitorIndex = index; + } + anchors { top: txtHeadline.bottom topMargin: 20 left: parent.left leftMargin: 20 } - availableWidth: width - 20 - availableHeight: 150 - - onRequestProjectSettings: { - - if (installedType === InstalledType.VideoWallpaper) { - videoControlWrapper.state = "visible" - customPropertiesGridView.visible = false - const wallpaper = ScreenPlay.screenPlayManager.getWallpaperByAppID(appID) - videoControlWrapper.wallpaper = wallpaper - } else { - videoControlWrapper.state = "hidden" - customPropertiesGridView.visible = true - ScreenPlay.screenPlayManager.requestProjectSettingsAtMonitorIndex(index) - } - - activeMonitorIndex = index - } Connections { - target: ScreenPlay.screenPlayManager function onProjectSettingsListModelResult(listModel) { - customPropertiesGridView.projectSettingsListmodelRef = listModel + customPropertiesGridView.projectSettingsListmodelRef = listModel; } + + target: ScreenPlay.screenPlayManager } + } ColumnLayout { + spacing: 5 + anchors { top: monitorSelection.bottom right: parent.right left: parent.left margins: 20 } - spacing: 5 + Button { id: btnRemoveSelectedWallpaper + text: qsTr("Remove selected") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font enabled: monitorSelection.activeMonitors.length == 1 onClicked: { - if (!ScreenPlay.screenPlayManager.removeWallpaperAt( - monitorSelection.activeMonitors[0])) { - print("Unable to close singel wallpaper") - } + if (!ScreenPlay.screenPlayManager.removeWallpaperAt(monitorSelection.activeMonitors[0])) + print("Unable to close singel wallpaper"); + } } + Button { id: btnRemoveAllWallpape - text: qsTr("Remove ") - + ScreenPlay.screenPlayManager.activeWallpaperCounter + " " + qsTr( - "Wallpapers") + + text: qsTr("Remove ") + ScreenPlay.screenPlayManager.activeWallpaperCounter + " " + qsTr("Wallpapers") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font enabled: ScreenPlay.screenPlayManager.activeWallpaperCounter > 0 onClicked: { - if (!ScreenPlay.screenPlayManager.removeAllWallpapers()) { - print("Unable to close all wallpaper!") - } + if (!ScreenPlay.screenPlayManager.removeAllWallpapers()) + print("Unable to close all wallpaper!"); - monitors.close() + monitors.close(); } } + Button { id: btnRemoveAllWidgets - text: qsTr("Remove ") - + ScreenPlay.screenPlayManager.activeWidgetsCounter + " " + qsTr("Widgets") + + text: qsTr("Remove ") + ScreenPlay.screenPlayManager.activeWidgetsCounter + " " + qsTr("Widgets") Material.background: Material.accent Material.foreground: "white" font.family: ScreenPlay.settings.font enabled: ScreenPlay.screenPlayManager.activeWidgetsCounter > 0 onClicked: { - if (!ScreenPlay.screenPlayManager.removeAllWidgets()) { - print("Unable to close all widgets!") - } + if (!ScreenPlay.screenPlayManager.removeAllWidgets()) + print("Unable to close all widgets!"); - monitors.close() + monitors.close(); } } + } + } Rectangle { - color: Material.theme === Material.Light ? Material.background : Qt.darker( - Material.background) + color: Material.theme === Material.Light ? Material.background : Qt.darker(Material.background) radius: 3 clip: true @@ -193,6 +192,7 @@ Popup { DefaultVideoControls { id: videoControlWrapper + activeMonitorIndex: monitors.activeMonitorIndex state: "hidden" anchors.fill: parent @@ -201,6 +201,9 @@ Popup { GridView { id: customPropertiesGridView + + property var projectSettingsListmodelRef + boundsBehavior: Flickable.DragOverBounds maximumFlickVelocity: 7000 flickDeceleration: 5000 @@ -212,10 +215,10 @@ Popup { anchors.margins: 10 visible: false model: customPropertiesGridView.projectSettingsListmodelRef - property var projectSettingsListmodelRef delegate: MonitorsProjectSettingItem { id: delegate + width: parent.width - 40 selectedMonitor: activeMonitorIndex name: m_name @@ -229,14 +232,12 @@ Popup { snapMode: ScrollBar.SnapOnRelease policy: ScrollBar.AlwaysOn } + } + } ToolButton { - anchors { - top: parent.top - right: parent.right - } width: 32 height: width icon.width: 16 @@ -244,18 +245,43 @@ Popup { icon.source: "qrc:/assets/icons/font-awsome/close.svg" icon.color: Material.iconColor onClicked: monitors.close() + + anchors { + top: parent.top + right: parent.right + } + } SaveNotification { id: saveNotification + width: parent.width - 40 + Connections { - target: ScreenPlay.screenPlayManager function onProfilesSaved() { if (monitors.opened) - saveNotification.open() + saveNotification.open(); + } + + target: ScreenPlay.screenPlayManager } + } + } + + background: Rectangle { + anchors.fill: parent + radius: 4 + layer.enabled: true + color: Material.theme === Material.Light ? "white" : Material.background + + layer.effect: ElevationEffect { + elevation: 6 + } + + } + } diff --git a/ScreenPlay/qml/Monitors/MonitorsProjectSettingItem.qml b/ScreenPlay/qml/Monitors/MonitorsProjectSettingItem.qml index 1c850195..ef65acd6 100644 --- a/ScreenPlay/qml/Monitors/MonitorsProjectSettingItem.qml +++ b/ScreenPlay/qml/Monitors/MonitorsProjectSettingItem.qml @@ -4,13 +4,11 @@ import QtGraphicalEffects 1.0 import QtQuick.Dialogs 1.2 import QtQuick.Controls.Material 2.2 import QtQuick.Layouts 1.3 - import ScreenPlay 1.0 Item { id: root - focus: true - height: isHeadline ? 50 : 30 + property int selectedMonitor property string name property var value @@ -18,26 +16,56 @@ Item { property int itemIndex property var projectSettingsListmodelRef + focus: true + height: isHeadline ? 50 : 30 + Text { id: txtDescription + text: root.name width: 100 font.pointSize: root.isHeadline ? 18 : 12 anchors.verticalCenter: parent.verticalCenter font.family: ScreenPlay.settings.font font.weight: Font.Normal - color: root.isHeadline ? Qt.darker( - Material.foreground) : Material.foreground + color: root.isHeadline ? Qt.darker(Material.foreground) : Material.foreground anchors { left: parent.left leftMargin: root.isHeadline ? 0 : 25 } + } Item { height: parent.height visible: !root.isHeadline + Component.onCompleted: { + if (root.isHeadline) + return ; + + switch (root.value["type"]) { + case "slider": + loader.sourceComponent = compSlider; + loader.item.from = root.value["from"]; + loader.item.to = root.value["to"]; + loader.item.value = root.value["value"]; + loader.item.stepSize = root.value["stepSize"]; + break; + case "bool": + loader.sourceComponent = compCheckbox; + loader.item.value = root.value["value"]; + break; + case "color": + loader.sourceComponent = compColorpicker; + loader.item.value = root.value["value"]; + break; + } + if (root.value["text"]) + txtDescription.text = root.value["text"]; + + } + anchors { left: txtDescription.right leftMargin: 20 @@ -46,43 +74,18 @@ Item { Loader { id: loader + anchors.fill: parent anchors.rightMargin: 10 Connections { - target: loader.item function onSave(value) { - projectSettingsListmodelRef.setValueAtIndex(root.itemIndex, - name, value) + projectSettingsListmodelRef.setValueAtIndex(root.itemIndex, name, value); } - } - } - Component.onCompleted: { - if (root.isHeadline) - return - - switch (root.value["type"]) { - case "slider": - loader.sourceComponent = compSlider - loader.item.from = root.value["from"] - loader.item.to = root.value["to"] - loader.item.value = root.value["value"] - loader.item.stepSize = root.value["stepSize"] - break - case "bool": - loader.sourceComponent = compCheckbox - loader.item.value = root.value["value"] - break - case "color": - loader.sourceComponent = compColorpicker - loader.item.value = root.value["value"] - break + target: loader.item } - if (root.value["text"]) { - txtDescription.text = root.value["text"] - } } Component { @@ -90,31 +93,36 @@ Item { Item { id: root - anchors.fill: parent + property bool value + signal save(var value) + anchors.fill: parent + CheckBox { id: checkbox + checkable: true checked: root.value - anchors { - right: parent.right - verticalCenter: parent.verticalCenter - } onCheckedChanged: { let obj = { "value": checkbox.checked, "type": "checkBox" - } - - root.save(obj) - - ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - selectedMonitor, name, checkbox.checked) + }; + root.save(obj); + ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(selectedMonitor, name, checkbox.checked); } + + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + } + } + } Component { @@ -122,53 +130,62 @@ Item { Item { id: root - anchors.fill: parent + property color value signal save(var value) + anchors.fill: parent + Button { id: btnSetColor + text: qsTr("Set color") onClicked: colorDialog.open() + anchors { right: parent.right verticalCenter: parent.verticalCenter } + } + Rectangle { id: rctPreviewColor + radius: 3 color: root.value border.width: 1 border.color: "gray" width: parent.height height: parent.height + anchors { right: btnSetColor.left rightMargin: 20 verticalCenter: parent.verticalCenter } + } + ColorDialog { id: colorDialog + title: qsTr("Please choose a color") onAccepted: { - rctPreviewColor.color = colorDialog.color - let tmpColor = "'" + colorDialog.color.toString() + "'" - + rctPreviewColor.color = colorDialog.color; + let tmpColor = "'" + colorDialog.color.toString() + "'"; let obj = { "value": colorDialog.color, "type": "color" - } - - root.save(obj) - - ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - selectedMonitor, name, tmpColor) + }; + root.save(obj); + ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(selectedMonitor, name, tmpColor); } } + } + } Component { @@ -176,7 +193,7 @@ Item { Item { id: root - anchors.fill: parent + property int from property int to property int value @@ -184,13 +201,29 @@ Item { signal save(var value) + anchors.fill: parent + Slider { id: slider + from: root.from to: root.to value: root.value stepSize: root.stepSize live: false + onValueChanged: { + const value = Math.trunc(slider.value * 100) / 100; + txtSliderValue.text = value; + let obj = { + "from": root.from, + "to": root.to, + "value": value, + "type": "slider", + "stepSize": root.stepSize + }; + root.save(obj); + ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex(selectedMonitor, name, value); + } anchors { verticalCenter: parent.verticalCenter @@ -200,42 +233,26 @@ Item { leftMargin: 20 } - onValueChanged: { - const value = Math.trunc(slider.value * 100) / 100 - txtSliderValue.text = value - - let obj = { - "from": root.from, - "to": root.to, - "value": value, - "type": "slider", - "stepSize": root.stepSize - } - - root.save(obj) - - ScreenPlay.screenPlayManager.setWallpaperValueAtMonitorIndex( - selectedMonitor, name, value) - } } + Text { id: txtSliderValue + color: Material.foreground horizontalAlignment: Text.AlignRight font.family: ScreenPlay.settings.font + anchors { right: parent.right verticalCenter: parent.verticalCenter } + } + } + } + } -} -/*##^## -Designer { - D{i:0;height:50;width:400} } -##^##*/ - diff --git a/ScreenPlay/qml/Monitors/SaveNotification.qml b/ScreenPlay/qml/Monitors/SaveNotification.qml index 71c431e9..cd5f7fb8 100644 --- a/ScreenPlay/qml/Monitors/SaveNotification.qml +++ b/ScreenPlay/qml/Monitors/SaveNotification.qml @@ -1,37 +1,36 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Controls.Material 2.14 - import QtQuick.Controls.Material.impl 2.12 import ScreenPlay 1.0 Rectangle { id: root + + function open() { + root.state = "in"; + closeTimer.start(); + } + + function close() { + root.state = ""; + } + height: 40 opacity: 0 + radius: 4 + color: Material.color(Material.LightGreen) + layer.enabled: true + anchors { horizontalCenter: parent.horizontalCenter bottomMargin: -root.height bottom: parent.bottom } - radius: 4 - color: Material.color(Material.LightGreen) - layer.enabled: true - layer.effect: ElevationEffect { - elevation: 6 - } - - function open() { - root.state = "in" - closeTimer.start() - } - function close() { - root.state = "" - } - Timer { id: closeTimer + interval: 1500 onTriggered: root.close() } @@ -42,6 +41,7 @@ Rectangle { font.family: ScreenPlay.settings.font font.pointSize: 14 verticalAlignment: Qt.AlignVCenter + anchors { top: parent.top topMargin: 5 @@ -50,18 +50,26 @@ Rectangle { bottom: parent.bottom bottomMargin: 5 } + } + + layer.effect: ElevationEffect { + elevation: 6 + } + transitions: [ Transition { from: "" to: "in" reversible: true + PropertyAnimation { target: root properties: "opacity,anchors.bottomMargin" duration: 250 easing.type: Easing.InOutQuart } + } ] states: [ @@ -73,6 +81,7 @@ Rectangle { anchors.bottomMargin: 10 opacity: 1 } + } ] } diff --git a/ScreenPlay/qml/Navigation/Navigation.qml b/ScreenPlay/qml/Navigation/Navigation.qml index c6db95dc..274b25dd 100644 --- a/ScreenPlay/qml/Navigation/Navigation.qml +++ b/ScreenPlay/qml/Navigation/Navigation.qml @@ -2,74 +2,72 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Controls.Material 2.12 import QtGraphicalEffects 1.0 - import QtQuick.Controls.Material.impl 2.12 import ScreenPlay 1.0 - import "../Workshop" import "../Common" Rectangle { id: root - height: 60 - clip: true - width: 1366 - color: Material.theme === Material.Light ? "white" : Material.background - layer.enabled: true - layer.effect: ElevationEffect { - elevation: 2 - } - - MouseHoverBlocker {} - - signal changePage(string name) property string currentNavigationName: "" property var navArray: [navCreate, navWorkshop, navInstalled, navSettings, navCommunity] property bool navActive: true - Connections { - target: ScreenPlay.util - function onRequestNavigationActive(isActive) { - setActive(isActive) - } - function onRequestNavigation(nav) { - onPageChanged(nav) - } - } + signal changePage(string name) function setActive(active) { - navActive = active - if (active) { - root.state = "enabled" - } else { - root.state = "disabled" - } + navActive = active; + if (active) + root.state = "enabled"; + else + root.state = "disabled"; } function setNavigation(name) { - var i = 0 + var i = 0; for (; i < navArray.length; i++) { if (navArray[i].name === name) { - navArray[i].state = "active" - root.currentNavigationName = name + navArray[i].state = "active"; + root.currentNavigationName = name; } else { - navArray[i].state = "inactive" + navArray[i].state = "inactive"; } } } function onPageChanged(name) { - if (!navActive) - return + return ; - root.changePage(name) - setNavigation(name) + root.changePage(name); + setNavigation(name); + } + + height: 60 + clip: true + width: 1366 + color: Material.theme === Material.Light ? "white" : Material.background + layer.enabled: true + + MouseHoverBlocker { + } + + Connections { + function onRequestNavigationActive(isActive) { + setActive(isActive); + } + + function onRequestNavigation(nav) { + onPageChanged(nav); + } + + target: ScreenPlay.util } Row { id: row + anchors.fill: parent anchors.left: parent.left anchors.leftMargin: 20 @@ -77,15 +75,16 @@ Rectangle { NavigationItem { id: navCreate + state: "inactive" name: "Create" - iconSource: "qrc:/assets/icons/icon_plus.svg" onPageClicked: root.onPageChanged(name) } NavigationItem { id: navWorkshop + state: "inactive" name: "Workshop" iconSource: "qrc:/assets/icons/icon_steam.svg" @@ -94,6 +93,7 @@ Rectangle { NavigationItem { id: navInstalled + state: "active" name: "Installed" amount: ScreenPlay.installedListModel.count @@ -103,21 +103,30 @@ Rectangle { NavigationItem { id: navCommunity + state: "inactive" name: "Community" iconSource: "qrc:/assets/icons/icon_community.svg" onPageClicked: root.onPageChanged(name) } + NavigationItem { id: navSettings + state: "inactive" name: "Settings" iconSource: "qrc:/assets/icons/icon_settings.svg" onPageClicked: root.onPageChanged(name) } + } - NavigationWallpaperConfiguration {} + NavigationWallpaperConfiguration { + } + + layer.effect: ElevationEffect { + elevation: 2 + } states: [ State { @@ -130,16 +139,19 @@ Rectangle { target: row opacity: 0.3 } + } ] transitions: [ Transition { from: "*" to: "*" + PropertyAnimation { target: row duration: 300 } + } ] } diff --git a/ScreenPlay/qml/Navigation/NavigationItem.qml b/ScreenPlay/qml/Navigation/NavigationItem.qml index fe30d6a7..69aa3ace 100644 --- a/ScreenPlay/qml/Navigation/NavigationItem.qml +++ b/ScreenPlay/qml/Navigation/NavigationItem.qml @@ -5,49 +5,44 @@ import ScreenPlay 1.0 Item { id: navigationItem - width: txtAmount.paintedWidth + txt.paintedWidth + icon.paintedWidth + 40 - Behavior on width { - PropertyAnimation { - duration: 50 - } - } - height: 60 - state: "inactive" - clip: true property string iconSource: "qrc:/assets/icons/icon_installed.svg" property alias name: txt.text property alias amount: txtAmount.text - property bool enabled: true - onEnabledChanged: { - if (!enabled) { - navigationItem.width = 0 - navigationItem.opacity = 0 - } - } signal pageClicked(string name) function setActive(isActive) { - if (isActive) { - navigationItem.state = "active" - } else { - navigationItem.state = "inactive" + if (isActive) + navigationItem.state = "active"; + else + navigationItem.state = "inactive"; + } + + width: txtAmount.paintedWidth + txt.paintedWidth + icon.paintedWidth + 40 + height: 60 + state: "inactive" + clip: true + onEnabledChanged: { + if (!enabled) { + navigationItem.width = 0; + navigationItem.opacity = 0; } } MouseArea { id: mouseArea - anchors.fill: parent + anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - navigationItem.pageClicked(navigationItem.name) + navigationItem.pageClicked(navigationItem.name); } Image { id: icon + source: iconSource width: 16 height: 16 @@ -61,6 +56,7 @@ Item { Text { id: txtAmount + anchors.left: icon.right anchors.leftMargin: 10 font.pointSize: 14 @@ -73,6 +69,7 @@ Item { Text { id: txt + anchors.left: txtAmount.right anchors.leftMargin: navigationItem.amount == "" ? 0 : 5 text: "name" @@ -85,6 +82,7 @@ Item { ColorOverlay { id: iconColorOverlay + anchors.fill: icon source: icon color: Material.accentColor @@ -92,6 +90,7 @@ Item { Rectangle { id: navIndicator + y: 83 height: 3 color: Material.accent @@ -100,6 +99,14 @@ Item { anchors.bottom: parent.bottom anchors.bottomMargin: 0 } + + } + + Behavior on width { + PropertyAnimation { + duration: 50 + } + } states: [ @@ -115,6 +122,7 @@ Item { target: iconColorOverlay color: Material.accent } + }, State { name: "disabled" @@ -128,6 +136,7 @@ Item { target: iconColorOverlay color: "#00000000" } + }, State { name: "inactive" @@ -141,9 +150,9 @@ Item { target: iconColorOverlay color: "#00000000" } + } ] - transitions: [ Transition { from: "*" @@ -154,6 +163,7 @@ Item { duration: 200 easing.type: Easing.OutQuart } + }, Transition { from: "*" @@ -164,6 +174,7 @@ Item { duration: 200 easing.type: Easing.OutQuart } + }, Transition { from: "*" @@ -174,6 +185,7 @@ Item { duration: 100 easing.type: Easing.OutQuart } + } ] } diff --git a/ScreenPlay/qml/Navigation/NavigationWallpaperConfiguration.qml b/ScreenPlay/qml/Navigation/NavigationWallpaperConfiguration.qml index 832f2912..92ac31a4 100644 --- a/ScreenPlay/qml/Navigation/NavigationWallpaperConfiguration.qml +++ b/ScreenPlay/qml/Navigation/NavigationWallpaperConfiguration.qml @@ -2,14 +2,15 @@ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.12 import QtGraphicalEffects 1.0 - import ScreenPlay 1.0 - import "../Common" Item { id: navigationWallpaperConfiguration + width: 450 + states: [] + transitions: [] anchors { top: parent.top @@ -18,34 +19,36 @@ Item { } RippleEffect { - id:rippleEffect - target: navigationWallpaperConfiguration + id: rippleEffect + target: navigationWallpaperConfiguration } Connections { - target: ScreenPlay.screenPlayManager function onActiveWallpaperCounterChanged() { - rippleEffect.trigger() + rippleEffect.trigger(); } - } + target: ScreenPlay.screenPlayManager + } Image { id: image + width: 24 height: 24 + source: "qrc:/assets/icons/icon_monitor.svg" + anchors { rightMargin: 30 right: parent.right verticalCenter: parent.verticalCenter } - source: "qrc:/assets/icons/icon_monitor.svg" Text { id: txtAmountActiveWallpapers - text: ScreenPlay.screenPlayManager.activeWallpaperCounter - + ScreenPlay.screenPlayManager.activeWidgetsCounter + + text: ScreenPlay.screenPlayManager.activeWallpaperCounter + ScreenPlay.screenPlayManager.activeWidgetsCounter horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: Material.accent @@ -58,17 +61,23 @@ Item { top: parent.top topMargin: 1 } + } + } Text { id: activeMonitorName + + horizontalAlignment: Text.AlignRight + color: Material.foreground + font.pointSize: 12 + font.family: ScreenPlay.settings.font text: { - if (ScreenPlay.screenPlayManager.activeWallpaperCounter > 0) { - return qsTr("Configurate active Wallpaper or Widgets") - } else { - return qsTr("No active Wallpaper or Widgets") - } + if (ScreenPlay.screenPlayManager.activeWallpaperCounter > 0) + return qsTr("Configurate active Wallpaper or Widgets"); + else + return qsTr("No active Wallpaper or Widgets"); } anchors { @@ -76,21 +85,17 @@ Item { rightMargin: 30 verticalCenter: parent.verticalCenter } - horizontalAlignment: Text.AlignRight - color: Material.foreground - font.pointSize: 12 - font.family: ScreenPlay.settings.font + } + MouseArea { id: ma + anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - ScreenPlay.util.setToggleWallpaperConfiguration() + ScreenPlay.util.setToggleWallpaperConfiguration(); } } - states: [] - - transitions: [] } diff --git a/ScreenPlay/qml/Settings/SettingBool.qml b/ScreenPlay/qml/Settings/SettingBool.qml index 5c6567d6..b05205f9 100644 --- a/ScreenPlay/qml/Settings/SettingBool.qml +++ b/ScreenPlay/qml/Settings/SettingBool.qml @@ -6,27 +6,29 @@ import ScreenPlay 1.0 Item { id: settingsBool + property string headline: "Headline" property string description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." property bool isChecked: false property bool available: true + signal checkboxChanged(bool checked) + height: txtHeadline.paintedHeight + txtDescription.paintedHeight + 20 width: parent.width - onAvailableChanged: { if (!available) { - settingsBool.opacity = .5 - radioButton.enabled = false + settingsBool.opacity = 0.5; + radioButton.enabled = false; } else { - settingsButton.opacity = 1 - radioButton.enabled = true + settingsButton.opacity = 1; + radioButton.enabled = true; } } - signal checkboxChanged(bool checked) Text { id: txtHeadline + color: Material.foreground text: settingsBool.headline font.family: ScreenPlay.settings.font @@ -34,6 +36,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft wrapMode: Text.WrapAtWordBoundaryOrAnywhere + anchors { top: parent.top topMargin: 6 @@ -42,15 +45,15 @@ Item { right: parent.right rightMargin: 20 } + } + Text { id: txtDescription + text: settingsBool.description wrapMode: Text.WordWrap - color: Material.theme === Material.Light ? Qt.lighter( - Material.foreground) : Qt.darker( - Material.foreground) - + color: Material.theme === Material.Light ? Qt.lighter(Material.foreground) : Qt.darker(Material.foreground) font.family: ScreenPlay.settings.font verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft @@ -64,23 +67,26 @@ Item { right: radioButton.left rightMargin: 20 } + } CheckBox { id: radioButton + + checked: settingsBool.isChecked + onCheckedChanged: { + if (radioButton.checkState === Qt.Checked) + checkboxChanged(true); + else + checkboxChanged(false); + } + anchors { right: parent.right rightMargin: 20 verticalCenter: parent.verticalCenter } - checked: settingsBool.isChecked - onCheckedChanged: { - if (radioButton.checkState === Qt.Checked) { - checkboxChanged(true) - } else { - checkboxChanged(false) - } - } } + } diff --git a/ScreenPlay/qml/Settings/Settings.qml b/ScreenPlay/qml/Settings/Settings.qml index f263b116..fdf8254e 100644 --- a/ScreenPlay/qml/Settings/Settings.qml +++ b/ScreenPlay/qml/Settings/Settings.qml @@ -4,28 +4,27 @@ import QtQuick.Controls.Material 2.12 import QtQuick.Dialogs 1.3 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 - import ScreenPlay 1.0 import ScreenPlay.Enums.FillMode 1.0 import Settings 1.0 - import "../Common" Item { id: root function indexOfValue(model, value) { - for (var i = 0; i < model.length; i++) { - let ourValue = model[i].value + let ourValue = model[i].value; if (value === ourValue) - return i + return i; + } - return -1 + return -1; } Flickable { id: flickableWrapper + width: 800 height: parent.height contentHeight: columnWrapper.childrenRect.height @@ -40,12 +39,9 @@ Item { horizontalCenter: parent.horizontalCenter } - ScrollBar.vertical: ScrollBar { - snapMode: ScrollBar.SnapOnRelease - } - Column { id: columnWrapper + width: parent.width - 40 spacing: 30 @@ -54,12 +50,15 @@ Item { header: SettingsHeader { id: headerGeneral + text: qsTr("General") } contentItem: Column { id: columnGeneral + spacing: 20 + anchors { top: headerGeneral.bottom topMargin: 20 @@ -68,168 +67,188 @@ Item { leftMargin: 20 rightMargin: 20 } + SettingBool { headline: qsTr("Autostart") description: qsTr("ScreenPlay will start with Windows and will setup your Desktop every time for you.") isChecked: ScreenPlay.settings.autostart onCheckboxChanged: { - ScreenPlay.settings.setAutostart(checked) + ScreenPlay.settings.setAutostart(checked); } } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } + SettingBool { headline: qsTr("High priority Autostart") available: false - description: qsTr("This options grants ScreenPlay a higher autostart priority than other apps.") isChecked: ScreenPlay.settings.highPriorityStart onCheckboxChanged: { - ScreenPlay.settings.setHighPriorityStart(checked) + ScreenPlay.settings.setHighPriorityStart(checked); } } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } + SettingBool { height: 70 headline: qsTr("Send anonymous crash reports and statistics") description: qsTr("Help us make ScreenPlay faster and more stable. All collected data is purely anonymous and only used for development purposes!") isChecked: ScreenPlay.settings.anonymousTelemetry onCheckboxChanged: { - ScreenPlay.settings.setAnonymousTelemetry(checked) + ScreenPlay.settings.setAnonymousTelemetry(checked); } } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } SettingsButton { headline: qsTr("Set save location") + buttonText: qsTr("Set location") description: { // Remove file:/// so the used does not get confused - let path = ScreenPlay.globalVariables.localStoragePath + "" - if (path.length === 0) { - return qsTr("Your storage path is empty!") - } else { - return path.replace('file:///', '') - } + let path = ScreenPlay.globalVariables.localStoragePath + ""; + if (path.length === 0) + return qsTr("Your storage path is empty!"); + else + return path.replace('file:///', ''); + } + onButtonPressed: { + folderDialogSaveLocation.open(); } - buttonText: qsTr("Set location") - onButtonPressed: { - folderDialogSaveLocation.open() - } FileDialog { id: folderDialogSaveLocation + selectFolder: true folder: ScreenPlay.globalVariables.localStoragePath onAccepted: { - ScreenPlay.settings.setLocalStoragePath( - folderDialogSaveLocation.fileUrls[0]) + ScreenPlay.settings.setLocalStoragePath(folderDialogSaveLocation.fileUrls[0]); } } + } + Text { id: txtDirChangesInfo + text: qsTr("Important: Changing this directory has no effect on the workshop download path. ScreenPlay only supports having one content folder!") color: Qt.darker(Material.foreground) wrapMode: Text.WrapAtWordBoundaryOrAnywhere font.pointSize: 10 font.family: ScreenPlay.settings.font height: 30 + anchors { right: parent.right rightMargin: 10 left: parent.left leftMargin: 20 } + } - SettingsHorizontalSeperator {} + SettingsHorizontalSeperator { + } SettingsComboBox { id: settingsLanguage + headline: qsTr("Language") description: qsTr("Set the ScreenPlay UI Language") Component.onCompleted: { - settingsLanguage.comboBox.currentIndex = root.indexOfValue( - settingsLanguage.comboBox.model, - ScreenPlay.settings.language) + settingsLanguage.comboBox.currentIndex = root.indexOfValue(settingsLanguage.comboBox.model, ScreenPlay.settings.language); } comboBox { - onActivated: { - ScreenPlay.settings.setLanguage( - settingsLanguage.comboBox.currentValue) - ScreenPlay.settings.retranslateUI() - } model: [{ - "value": Settings.En, - "text": qsTr("English") - }, { - "value": Settings.De, - "text": qsTr("German") - }, { - "value": Settings.Zh_CN, - "text": qsTr("Chinese - Simplified") - }, { - "value": Settings.Ru, - "text": qsTr("Russian") - }, { - "value": Settings.Fr, - "text": qsTr("French") - }, { - "value": Settings.Es, - "text": qsTr("Spanish") - }, { - "value": Settings.Ko, - "text": qsTr("Korean") - }, { - "value": Settings.Vi, - "text": qsTr("Vietnamese") - }, { - "value": Settings.Pt_BR, - "text": qsTr("Portuguese (Brazil)") - }] + "value": Settings.En, + "text": qsTr("English") + }, { + "value": Settings.De, + "text": qsTr("German") + }, { + "value": Settings.Zh_CN, + "text": qsTr("Chinese - Simplified") + }, { + "value": Settings.Ru, + "text": qsTr("Russian") + }, { + "value": Settings.Fr, + "text": qsTr("French") + }, { + "value": Settings.Es, + "text": qsTr("Spanish") + }, { + "value": Settings.Ko, + "text": qsTr("Korean") + }, { + "value": Settings.Vi, + "text": qsTr("Vietnamese") + }, { + "value": Settings.Pt_BR, + "text": qsTr("Portuguese (Brazil)") + }] + onActivated: { + ScreenPlay.settings.setLanguage(settingsLanguage.comboBox.currentValue); + ScreenPlay.settings.retranslateUI(); + } } + + } + + SettingsHorizontalSeperator { } - SettingsHorizontalSeperator {} SettingsComboBox { id: settingsTheme + headline: qsTr("Theme") description: qsTr("Switch dark/light theme") Component.onCompleted: { - settingsTheme.comboBox.currentIndex = root.indexOfValue( - settingsTheme.comboBox.model, - ScreenPlay.settings.theme) + settingsTheme.comboBox.currentIndex = root.indexOfValue(settingsTheme.comboBox.model, ScreenPlay.settings.theme); } comboBox { - onActivated: { - ScreenPlay.settings.setTheme( - settingsTheme.comboBox.currentValue) - } model: [{ - "value": Settings.System, - "text": qsTr("System Default") - }, { - "value": Settings.Dark, - "text": qsTr("Dark") - }, { - "value": Settings.Light, - "text": qsTr("Light") - }] + "value": Settings.System, + "text": qsTr("System Default") + }, { + "value": Settings.Dark, + "text": qsTr("Dark") + }, { + "value": Settings.Light, + "text": qsTr("Light") + }] + onActivated: { + ScreenPlay.settings.setTheme(settingsTheme.comboBox.currentValue); + } } + } + } + } SettingsPage { + header: SettingsHeader { id: headerPerformance + text: qsTr("Performance") image: "qrc:/assets/icons/icon_build.svg" } + contentItem: Column { id: perfomanceWrapper + spacing: 20 + anchors { top: headerPerformance.bottom topMargin: 20 @@ -238,60 +257,68 @@ Item { leftMargin: 20 rightMargin: 20 } + SettingBool { headline: qsTr("Pause wallpaper video rendering while another app is in the foreground") description: qsTr("We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required!") isChecked: ScreenPlay.settings.checkWallpaperVisible onCheckboxChanged: { - ScreenPlay.settings.setCheckWallpaperVisible( - checked) + ScreenPlay.settings.setCheckWallpaperVisible(checked); } } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } + SettingsComboBox { id: cbVideoFillMode + headline: qsTr("Default Fill Mode") description: qsTr("Set this property to define how the video is scaled to fit the target area.") Component.onCompleted: { - cbVideoFillMode.comboBox.currentIndex = root.indexOfValue( - cbVideoFillMode.comboBox.model, - ScreenPlay.settings.videoFillMode) + cbVideoFillMode.comboBox.currentIndex = root.indexOfValue(cbVideoFillMode.comboBox.model, ScreenPlay.settings.videoFillMode); } - comboBox { - onActivated: ScreenPlay.settings.setVideoFillMode( - cbVideoFillMode.comboBox.currentValue) + comboBox { + onActivated: ScreenPlay.settings.setVideoFillMode(cbVideoFillMode.comboBox.currentValue) model: [{ - "value": FillMode.Stretch, - "text": qsTr("Stretch") - }, { - "value": FillMode.Fill, - "text": qsTr("Fill") - }, { - "value": FillMode.Contain, - "text": qsTr("Contain") - }, { - "value": FillMode.Cover, - "text": qsTr("Cover") - }, { - "value": FillMode.Scale_Down, - "text": qsTr("Scale-Down") - }] + "value": FillMode.Stretch, + "text": qsTr("Stretch") + }, { + "value": FillMode.Fill, + "text": qsTr("Fill") + }, { + "value": FillMode.Contain, + "text": qsTr("Contain") + }, { + "value": FillMode.Cover, + "text": qsTr("Cover") + }, { + "value": FillMode.Scale_Down, + "text": qsTr("Scale-Down") + }] } + } + } + } SettingsPage { + header: SettingsHeader { id: headerAbout + text: qsTr("About") image: "qrc:/assets/icons/icon_cake.svg" } contentItem: Column { id: aboutWrapper + spacing: 20 + anchors { top: headerAbout.bottom topMargin: 20 @@ -303,40 +330,45 @@ Item { Column { id: settingsAboutrapperWrapper + width: parent.width spacing: 10 Item { width: parent.width - height: txtHeadline.paintedHeight + txtDescriptionAbout.paintedHeight - + wrapperLinks.childrenRect.height + 80 + height: txtHeadline.paintedHeight + txtDescriptionAbout.paintedHeight + wrapperLinks.childrenRect.height + 80 + Text { id: txtHeadline + color: Material.foreground text: qsTr("Thank you for using ScreenPlay") - verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.pointSize: 16 font.family: ScreenPlay.settings.font + anchors { top: parent.top topMargin: 6 left: parent.left leftMargin: 20 } + } + Text { id: txtDescriptionAbout + text: qsTr("Hi, I'm Elias Steurer also known as Kelteseth and I'm the developer of ScreenPlay. Thank you for using my software. You can follow me to receive updates about ScreenPlay here:") color: Qt.darker(Material.foreground) - wrapMode: Text.WordWrap verticalAlignment: Text.AlignTop horizontalAlignment: Text.AlignLeft font.pointSize: 11 font.family: ScreenPlay.settings.font - width: parent.width * .6 + width: parent.width * 0.6 + anchors { top: txtHeadline.bottom topMargin: 15 @@ -345,61 +377,73 @@ Item { right: imgLogoHead.left rightMargin: 60 } + } RowLayout { id: wrapperLinks + + spacing: 20 + anchors { left: parent.left margins: 20 bottom: parent.bottom } - spacing: 20 GrowIconLink { iconSource: "qrc:/assets/icons/brand_github.svg" url: "https://github.com/kelteseth" color: "#333333" } + GrowIconLink { iconSource: "qrc:/assets/icons/brand_gitlab.svg" url: "https://gitlab.com/kelteseth" color: "#FC6D26" } + GrowIconLink { iconSource: "qrc:/assets/icons/brand_twitter.svg" url: "https://twitter.com/Kelteseth" color: "#1DA1F2" } + GrowIconLink { iconSource: "qrc:/assets/icons/brand_twitch.svg" url: "https://www.twitch.tv/kelteseth/" color: "#6441A5" } + GrowIconLink { iconSource: "qrc:/assets/icons/brand_reddit.svg" url: "https://www.reddit.com/r/ScreenPlayApp/" color: "#FF4500" } + } Image { id: imgLogoHead - source: "https://assets.gitlab-static.net/uploads/-/system/user/avatar/64172/avatar.png" + source: "https://assets.gitlab-static.net/uploads/-/system/user/avatar/64172/avatar.png" width: 120 height: 120 visible: false + sourceSize: Qt.size(width, height) + anchors { top: txtHeadline.bottom topMargin: 0 right: parent.right rightMargin: 20 } - sourceSize: Qt.size(width, height) + } + Image { id: mask + source: "qrc:/assets/images/mask_round.svg" sourceSize: Qt.size(width, height) smooth: true @@ -410,88 +454,108 @@ Item { OpacityMask { id: opacityMask + anchors.fill: imgLogoHead source: imgLogoHead maskSource: mask smooth: true } + } + } - SettingsHorizontalSeperator {} + SettingsHorizontalSeperator { + } SettingsButton { icon.source: "qrc:/assets/icons/icon_launch.svg" headline: qsTr("Version") - description: qsTr("ScreenPlay Build Version ") - + ScreenPlay.settings.gitBuildHash + description: qsTr("ScreenPlay Build Version ") + ScreenPlay.settings.gitBuildHash buttonText: qsTr("Open Changelog") - onButtonPressed: Qt.openUrlExternally( - "https://gitlab.com/kelteseth/ScreenPlay/-/releases") + onButtonPressed: Qt.openUrlExternally("https://gitlab.com/kelteseth/ScreenPlay/-/releases") + } + + SettingsHorizontalSeperator { } - SettingsHorizontalSeperator {} SettingsButton { headline: qsTr("Third Party Software") description: qsTr("ScreenPlay would not be possible without the work of others. A big thank you to: ") buttonText: qsTr("Licenses") onButtonPressed: { - ScreenPlay.util.requestAllLicenses() - expanderCopyright.toggle() + ScreenPlay.util.requestAllLicenses(); + expanderCopyright.toggle(); } } + SettingsExpander { id: expanderCopyright Connections { - target: ScreenPlay.util function onAllLicenseLoaded(licensesText) { - expanderCopyright.text = licensesText + expanderCopyright.text = licensesText; } + + target: ScreenPlay.util } + } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } + SettingsButton { headline: qsTr("Logs") description: qsTr("If your ScreenPlay missbehaves this is a good way to look for answers. This shows all logs and warning during runtime.") buttonText: qsTr("Show Logs") onButtonPressed: { - expanderDebug.toggle() + expanderDebug.toggle(); } } + SettingsExpander { id: expanderDebug + text: ScreenPlay.util.debugMessages } - SettingsHorizontalSeperator {} + + SettingsHorizontalSeperator { + } + SettingsButton { headline: qsTr("Data Protection") description: qsTr("We use you data very carefully to improve ScreenPlay. We do not sell or share this (anonymous) information with others!") buttonText: qsTr("Privacy") onButtonPressed: { - ScreenPlay.util.requestDataProtection() - expanderDataProtection.toggle() + ScreenPlay.util.requestDataProtection(); + expanderDataProtection.toggle(); } } + SettingsExpander { id: expanderDataProtection Connections { - target: ScreenPlay.util function onAllDataProtectionLoaded(dataProtectionText) { - expanderDataProtection.text = dataProtectionText + expanderDataProtection.text = dataProtectionText; } + + target: ScreenPlay.util } + } + } + } + } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + } + } -} -/*##^## -Designer { - D{i:0;autoSize:true;height:2000;width:1000} } -##^##*/ - diff --git a/ScreenPlay/qml/Settings/SettingsButton.qml b/ScreenPlay/qml/Settings/SettingsButton.qml index 29673429..6e8afa2c 100644 --- a/ScreenPlay/qml/Settings/SettingsButton.qml +++ b/ScreenPlay/qml/Settings/SettingsButton.qml @@ -15,26 +15,30 @@ Item { property bool enabled: true property bool available: true + signal buttonPressed() + height: txtHeadline.paintedHeight + txtDescription.paintedHeight + 20 width: parent.width onAvailableChanged: { if (!available) { - settingsButton.opacity = .5 - btnSettings.enabled = false + settingsButton.opacity = 0.5; + btnSettings.enabled = false; } else { - settingsButton.opacity = 1 - btnSettings.enabled = true + settingsButton.opacity = 1; + btnSettings.enabled = true; } } - signal buttonPressed - Text { id: txtHeadline + color: Material.foreground text: settingsButton.headline verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + font.family: ScreenPlay.settings.font + anchors { top: parent.top topMargin: 6 @@ -42,22 +46,19 @@ Item { leftMargin: 20 } - font.pointSize: 12 - font.family: ScreenPlay.settings.font } Text { id: txtDescription - text: settingsButton.description - color: Material.theme === Material.Light ? Qt.lighter( - Material.foreground) : Qt.darker( - Material.foreground) + text: settingsButton.description + color: Material.theme === Material.Light ? Qt.lighter(Material.foreground) : Qt.darker(Material.foreground) verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap horizontalAlignment: Text.AlignLeft font.pointSize: 10 font.family: ScreenPlay.settings.font + anchors { top: txtHeadline.bottom topMargin: 6 @@ -66,21 +67,26 @@ Item { right: btnSettings.left rightMargin: 20 } + } Button { id: btnSettings + text: settingsButton.buttonText icon.width: 20 icon.height: 20 font.family: ScreenPlay.settings.font Material.background: Material.accent Material.foreground: "white" + onPressed: buttonPressed() + anchors { right: parent.right rightMargin: 20 verticalCenter: parent.verticalCenter } - onPressed: buttonPressed() + } + } diff --git a/ScreenPlay/qml/Settings/SettingsComboBox.qml b/ScreenPlay/qml/Settings/SettingsComboBox.qml index c7e9c5f1..b634ab77 100644 --- a/ScreenPlay/qml/Settings/SettingsComboBox.qml +++ b/ScreenPlay/qml/Settings/SettingsComboBox.qml @@ -6,20 +6,25 @@ import ScreenPlay 1.0 Control { id: settingsComboBox + property string headline: "Headline" property string description: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." property bool enabled: true property alias comboBox: comboBox width: parent.width - height: txtHeadline.paintedHeight + txtDescription.paintedHeight +20 + height: txtHeadline.paintedHeight + txtDescription.paintedHeight + 20 Text { id: txtHeadline + color: Material.foreground text: settingsComboBox.headline verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft + font.pointSize: 12 + font.family: ScreenPlay.settings.font + anchors { top: parent.top topMargin: 6 @@ -27,20 +32,19 @@ Control { leftMargin: 20 } - font.pointSize: 12 - font.family: ScreenPlay.settings.font } Text { id: txtDescription + text: settingsComboBox.description color: Qt.darker(Material.foreground) - verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft wrapMode: Text.WordWrap font.pointSize: 10 font.family: ScreenPlay.settings.font + anchors { top: txtHeadline.bottom topMargin: 6 @@ -49,18 +53,23 @@ Control { right: comboBox.left rightMargin: 20 } + } ComboBox { id: comboBox + implicitWidth: 200 textRole: "text" valueRole: "value" font.family: ScreenPlay.settings.font + anchors { right: parent.right rightMargin: 20 verticalCenter: parent.verticalCenter } + } + } diff --git a/ScreenPlay/qml/Settings/SettingsExpander.qml b/ScreenPlay/qml/Settings/SettingsExpander.qml index c1a97b94..5fb33ad6 100644 --- a/ScreenPlay/qml/Settings/SettingsExpander.qml +++ b/ScreenPlay/qml/Settings/SettingsExpander.qml @@ -7,56 +7,67 @@ import ScreenPlay 1.0 Item { id: root + + property alias text: txtExpander.text + + function toggle() { + root.state = root.state == "on" ? "off" : "on"; + } + state: "off" clip: true width: parent.width implicitHeight: 50 - property alias text: txtExpander.text - Flickable { anchors.fill: parent contentHeight: txtExpander.paintedHeight z: 999 focus: true contentWidth: parent.width - ScrollBar.vertical: ScrollBar { - snapMode: ScrollBar.SnapOnRelease - policy: ScrollBar.AlwaysOn - } + Text { id: txtExpander + + color: Material.theme === Material.Light ? Qt.lighter(Material.foreground) : Qt.darker(Material.foreground) + lineHeight: 1.2 + height: txtExpander.paintedHeight + wrapMode: Text.WordWrap + font.family: ScreenPlay.settings.font + anchors { top: parent.top right: parent.right left: parent.left margins: 20 } - color: Material.theme === Material.Light ? Qt.lighter(Material.foreground) : Qt.darker(Material.foreground) - lineHeight: 1.2 - height: txtExpander.paintedHeight - wrapMode: Text.WordWrap - font.family: ScreenPlay.settings.font + } + MouseArea { anchors.fill: parent propagateComposedEvents: true acceptedButtons: Qt.RightButton onClicked: contextMenu.popup() } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + policy: ScrollBar.AlwaysOn + } + } + Menu { id: contextMenu + MenuItem { text: qsTr("Copy text to clipboard") onClicked: { - ScreenPlay.util.copyToClipboard(txtExpander.text) + ScreenPlay.util.copyToClipboard(txtExpander.text); } } - } - function toggle() { - root.state = root.state == "on" ? "off" : "on" } states: [ @@ -67,13 +78,16 @@ Item { target: root height: 500 } + }, State { name: "off" + PropertyChanges { target: root height: 0 } + } ] transitions: [ @@ -81,11 +95,13 @@ Item { from: "off" to: "on" reversible: true + PropertyAnimation { target: root property: "height" duration: 250 } + } ] } diff --git a/ScreenPlay/qml/Settings/SettingsHeader.qml b/ScreenPlay/qml/Settings/SettingsHeader.qml index 3d3c04a0..9e1437e2 100644 --- a/ScreenPlay/qml/Settings/SettingsHeader.qml +++ b/ScreenPlay/qml/Settings/SettingsHeader.qml @@ -5,29 +5,35 @@ import ScreenPlay 1.0 Item { id: settingsHeader - state: "out" - Component.onCompleted: state = "in" + property color background: "#FFAB00" property string text: "HEADLINE" property url image: "qrc:/assets/icons/icon_settings.svg" + + state: "out" + Component.onCompleted: state = "in" width: parent.width height: 70 Rectangle { id: radiusWorkaround + height: 5 radius: 4 color: settingsHeader.background + anchors { top: parent.top right: parent.right left: parent.left } + } Rectangle { color: settingsHeader.background height: 47 + anchors { top: radiusWorkaround.bottom topMargin: -2 @@ -44,39 +50,51 @@ Item { Image { id: imgIcon + source: settingsHeader.image height: 20 width: 20 sourceSize: Qt.size(20, 20) + anchors { top: parent.top topMargin: 3 left: parent.left leftMargin: 0 } + } + ColorOverlay { id: iconColorOverlay + anchors.fill: imgIcon source: imgIcon color: "#ffffff" } + Text { id: txtHeadline + text: settingsHeader.text font.pointSize: 12 color: "white" verticalAlignment: Text.AlignTop font.family: ScreenPlay.settings.font + anchors { top: parent.top topMargin: 0 left: parent.left leftMargin: 30 } + } + } + } + states: [ State { name: "out" @@ -92,9 +110,11 @@ Item { anchors.topMargin: 10 opacity: 0 } + }, State { name: "in" + PropertyChanges { target: imgIcon anchors.leftMargin: 3 @@ -106,6 +126,7 @@ Item { anchors.topMargin: 2 opacity: 1 } + } ] transitions: [ @@ -120,6 +141,7 @@ Item { duration: 400 easing.type: Easing.InOutQuart } + } ] } diff --git a/ScreenPlay/qml/Settings/SettingsHorizontalSeperator.qml b/ScreenPlay/qml/Settings/SettingsHorizontalSeperator.qml index 63c7ac87..fa7f1b95 100644 --- a/ScreenPlay/qml/Settings/SettingsHorizontalSeperator.qml +++ b/ScreenPlay/qml/Settings/SettingsHorizontalSeperator.qml @@ -14,6 +14,7 @@ Item { height: customHeight width: customWidth color: customColor + anchors { right: parent.right rightMargin: customMargin @@ -21,5 +22,7 @@ Item { leftMargin: customMargin verticalCenter: parent.verticalCenter } + } + } diff --git a/ScreenPlay/qml/Settings/SettingsPage.qml b/ScreenPlay/qml/Settings/SettingsPage.qml index 6ee535a2..c2567a21 100644 --- a/ScreenPlay/qml/Settings/SettingsPage.qml +++ b/ScreenPlay/qml/Settings/SettingsPage.qml @@ -10,13 +10,17 @@ Page { width: parent.width height: contentHeight + header.height + 30 * 3 Material.elevation: 4 + background: Rectangle { anchors.fill: parent radius: 3 layer.enabled: true + color: Material.theme === Material.Light ? "white" : Material.background + layer.effect: ElevationEffect { elevation: 4 } - color: Material.theme === Material.Light ? "white" : Material.background + } + } diff --git a/ScreenPlay/qml/Workshop/Background.qml b/ScreenPlay/qml/Workshop/Background.qml index 7da13923..12beaafb 100644 --- a/ScreenPlay/qml/Workshop/Background.qml +++ b/ScreenPlay/qml/Workshop/Background.qml @@ -4,35 +4,42 @@ import ScreenPlay.Workshop 1.0 Rectangle { id: root - color: "#161C1D" + property string backgroundImage: "" property int imageOffsetTop: 0 + + color: "#161C1D" onImageOffsetTopChanged: { if ((imageOffsetTop * -1) >= 200) { - root.state = "backgroundColor" + root.state = "backgroundColor"; } else { - if (root.state !== "backgroundImage") { - root.state = "backgroundImage" - } + if (root.state !== "backgroundImage") + root.state = "backgroundImage"; + } } onBackgroundImageChanged: { - if (backgroundImage === "") { - root.state = "" - } else { - root.state = "backgroundImage" - } + if (backgroundImage === "") + root.state = ""; + else + root.state = "backgroundImage"; } Image { id: maskSource + visible: false source: "qrc:/assets/images/mask_workshop.png" } Image { id: bgImage + height: bgImage.sourceSize.height + fillMode: Image.PreserveAspectCrop + opacity: 0 + source: root.backgroundImage + anchors { topMargin: root.imageOffsetTop top: parent.top @@ -40,33 +47,37 @@ Rectangle { left: parent.left } - fillMode: Image.PreserveAspectCrop - opacity: 0 - source: root.backgroundImage - LinearGradient { id: gradient + anchors.fill: parent z: 4 + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#00ffffff" } + GradientStop { position: 0.6 color: "#00ffffff" } + GradientStop { position: 1 color: "#161C1D" } + } + } + } MaskedBlur { id: blur + anchors.fill: bgImage source: bgImage maskSource: maskSource @@ -78,6 +89,7 @@ Rectangle { Rectangle { id: bgColor + color: "#161C1D" opacity: 0 anchors.fill: parent @@ -86,6 +98,7 @@ Rectangle { states: [ State { name: "" + PropertyChanges { target: bgImage opacity: 0 @@ -95,13 +108,16 @@ Rectangle { target: bgColor opacity: 0 } + PropertyChanges { target: blur opacity: 0 } + }, State { name: "backgroundImage" + PropertyChanges { target: bgImage opacity: 1 @@ -111,13 +127,16 @@ Rectangle { target: bgColor opacity: 0 } + PropertyChanges { target: blur opacity: 0 } + }, State { name: "backgroundColor" + PropertyChanges { target: bgImage opacity: 1 @@ -127,10 +146,12 @@ Rectangle { target: bgColor opacity: 0.8 } + PropertyChanges { target: blur opacity: 1 } + } ] transitions: [ @@ -138,23 +159,27 @@ Rectangle { from: "" to: "backgroundImage" reversible: true + PropertyAnimation { targets: [bgImage, bgColor, blur] duration: 500 easing.type: Easing.InOutQuart property: "opacity" } + }, Transition { from: "backgroundImage" to: "backgroundColor" reversible: true + PropertyAnimation { targets: [bgImage, bgColor, blur] duration: 200 easing.type: Easing.InOutQuart property: "opacity" } + } ] } diff --git a/ScreenPlay/qml/Workshop/Navigation.qml b/ScreenPlay/qml/Workshop/Navigation.qml index d3c3695b..e1925bda 100644 --- a/ScreenPlay/qml/Workshop/Navigation.qml +++ b/ScreenPlay/qml/Workshop/Navigation.qml @@ -2,26 +2,27 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 import QtQuick.Controls.Material 2.13 import QtGraphicalEffects 1.0 - import QtQuick.Controls.Material.impl 2.12 - import ScreenPlay.Workshop 1.0 import SteamQMLImageProvider 1.0 import ScreenPlay 1.0 Rectangle { id: root - implicitWidth: 800 - height: 50 property SteamWorkshop steamWorkshop - signal uploadPressed + signal uploadPressed() + + implicitWidth: 800 + height: 50 color: Material.theme === Material.Light ? "white" : Material.background Item { id: wrapper + height: 50 + anchors { verticalCenter: parent.verticalCenter right: parent.right @@ -30,11 +31,6 @@ Rectangle { Text { id: name - text: { - return steamWorkshop.steamAccount.username + qsTr( - " Subscribed items: ") - + steamWorkshop.steamAccount.amountSubscribedItems - } font.pointSize: 14 color: Material.primaryTextColor @@ -42,6 +38,10 @@ Rectangle { font.weight: Font.Thin verticalAlignment: Qt.AlignVCenter wrapMode: Text.WrapAtWordBoundaryOrAnywhere + text: { + return steamWorkshop.steamAccount.username + qsTr(" Subscribed items: ") + steamWorkshop.steamAccount.amountSubscribedItems; + } + anchors { top: parent.top left: avatar.right @@ -50,58 +50,72 @@ Rectangle { right: btnUplaod.left rightMargin: 10 } + } SteamImage { id: avatar + width: 30 height: 30 + Component.onCompleted: { + steamWorkshop.steamAccount.loadAvatar(); + } + anchors { left: parent.left leftMargin: 10 verticalCenter: parent.verticalCenter } - Component.onCompleted: { - steamWorkshop.steamAccount.loadAvatar() - } + Connections { - target: steamWorkshop.steamAccount function onAvatarChanged(_avatar) { - avatar.setImage(_avatar) + avatar.setImage(_avatar); } + + target: steamWorkshop.steamAccount } + } Button { id: btnUplaod + text: qsTr("Upload to the Steam Workshop") icon.source: "qrc:/assets/icons/icon_plus.svg" icon.color: "white" icon.width: 16 icon.height: 16 onClicked: uploadPressed() + anchors { verticalCenter: parent.verticalCenter right: parent.right rightMargin: 10 } + } + } states: [ State { name: "base" + PropertyChanges { target: bg radius: 3 } + }, State { name: "scrolling" + PropertyChanges { target: bg radius: 0 } + } ] } diff --git a/ScreenPlay/qml/Workshop/PopupOffline.qml b/ScreenPlay/qml/Workshop/PopupOffline.qml index 3014637a..899c73fe 100644 --- a/ScreenPlay/qml/Workshop/PopupOffline.qml +++ b/ScreenPlay/qml/Workshop/PopupOffline.qml @@ -2,12 +2,12 @@ import QtQuick 2.0 import QtQuick.Controls 2.13 import QtQuick.Controls.Material 2.13 import QtGraphicalEffects 1.0 - import ScreenPlay.Workshop 1.0 import ScreenPlay 1.0 Popup { id: popupOffline + width: 1100 height: 600 modal: true @@ -15,12 +15,9 @@ Popup { anchors.centerIn: Overlay.overlay dim: true - background: Rectangle { - color: Material.theme === Material.Light ? "white" : Material.background - } - Text { id: txtOffline + anchors.centerIn: parent font.family: ScreenPlay.settings.font font.pointSize: 21 @@ -29,15 +26,22 @@ Popup { } Button { + highlighted: true + text: qsTr("Back") + onClicked: { + ScreenPlay.util.setNavigation("Installed"); + popupOffline.close(); + } + anchors { horizontalCenter: parent.horizontalCenter top: txtOffline.bottom } - highlighted: true - text: qsTr("Back") - onClicked: { - ScreenPlay.util.setNavigation("Installed") - popupOffline.close() - } + } + + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Material.background + } + } diff --git a/ScreenPlay/qml/Workshop/ScreenPlayItem.qml b/ScreenPlay/qml/Workshop/ScreenPlayItem.qml index 9f95cd97..09108085 100644 --- a/ScreenPlay/qml/Workshop/ScreenPlayItem.qml +++ b/ScreenPlay/qml/Workshop/ScreenPlayItem.qml @@ -5,12 +5,8 @@ import QtQuick.Controls.Styles 1.4 Item { id: screenPlayItem - width: 320 - height: 180 - property alias checkBox: checkBox - state: "invisible" - opacity: 0 + property alias checkBox: checkBox property string preview: screenPreview property bool isSelected: false property string customTitle: "name here" @@ -20,52 +16,62 @@ Item { property var publishedFileID: 0 property int itemIndex property string screenId: "" + signal itemClicked(var screenId, var type, var isActive) + width: 320 + height: 180 + state: "invisible" + opacity: 0 onTypeChanged: { - if (type === "widget") { - icnType.source = "icons/icon_widgets.svg" - } else if (type === "qmlScene") { - icnType.source = "icons/icon_code.svg" - } + if (type === "widget") + icnType.source = "icons/icon_widgets.svg"; + else if (type === "qmlScene") + icnType.source = "icons/icon_code.svg"; } - Component.onCompleted: { - screenPlayItem.state = "visible" + screenPlayItem.state = "visible"; } - - Timer { - id: timerAnim - interval: 40 * itemIndex * Math.random() - running: true - repeat: false - onTriggered: showAnim.start() - } - transform: [ Rotation { id: rt - origin.x: width * .5 - origin.y: height * .5 + + origin.x: width * 0.5 + origin.y: height * 0.5 + angle: 0 + axis { - x: -.5 + x: -0.5 y: 0 z: 0 } - angle: 0 + }, Translate { id: tr }, Scale { id: sc - origin.x: width * .5 - origin.y: height * .5 + + origin.x: width * 0.5 + origin.y: height * 0.5 } ] + + Timer { + id: timerAnim + + interval: 40 * itemIndex * Math.random() + running: true + repeat: false + onTriggered: showAnim.start() + } + ParallelAnimation { id: showAnim + running: false + RotationAnimation { target: rt from: 90 @@ -74,6 +80,7 @@ Item { easing.type: Easing.OutQuint property: "angle" } + PropertyAnimation { target: screenPlayItem from: 0 @@ -82,6 +89,7 @@ Item { easing.type: Easing.OutQuint property: "opacity" } + PropertyAnimation { target: tr from: 80 @@ -90,22 +98,20 @@ Item { easing.type: Easing.OutQuint property: "y" } + PropertyAnimation { target: sc - from: .8 + from: 0.8 to: 1 duration: 500 easing.type: Easing.OutQuint properties: "xScale,yScale" } + } RectangularGlow { id: effect - anchors { - top: parent.top - topMargin: 3 - } height: parent.height width: parent.width @@ -115,16 +121,24 @@ Item { color: "black" opacity: 0.4 cornerRadius: 15 + + anchors { + top: parent.top + topMargin: 3 + } + } Item { id: screenPlayItemWrapper + anchors.centerIn: parent height: 180 width: 320 Image { id: mask + source: "qrc:/assets/images/window.svg" sourceSize: Qt.size(screenPlayItem.width, screenPlayItem.height) visible: false @@ -134,41 +148,46 @@ Item { Item { id: itemWrapper + anchors.fill: parent visible: false ScreenPlayItemImage { id: screenPlayItemImage + anchors.fill: parent - sourceImage: Qt.resolvedUrl( - screenPlayItem.absoluteStoragePath + "/" + screenPreview) - - + sourceImage: Qt.resolvedUrl(screenPlayItem.absoluteStoragePath + "/" + screenPreview) } Image { id: icnType + width: 20 height: 20 opacity: 0 sourceSize: Qt.size(20, 20) + anchors { top: parent.top left: parent.left margins: 10 } + } Rectangle { color: "#AAffffff" height: 30 visible: false + anchors { right: parent.right left: parent.left bottom: parent.bottom } + } + } OpacityMask { @@ -182,33 +201,33 @@ Item { cursorShape: Qt.PointingHandCursor acceptedButtons: Qt.LeftButton | Qt.RightButton onEntered: { - if (!hasMenuOpen) { - screenPlayItem.state = "hover" - } + if (!hasMenuOpen) + screenPlayItem.state = "hover"; + } onExited: { - if (!hasMenuOpen) { - screenPlayItem.state = "visible" - } - } + if (!hasMenuOpen) + screenPlayItem.state = "visible"; + } onClicked: { - checkBox.toggle() - if (mouse.button === Qt.LeftButton) { - itemClicked(screenId, type, checkBox.checkState === Qt.Checked) - } + checkBox.toggle(); + if (mouse.button === Qt.LeftButton) + itemClicked(screenId, type, checkBox.checkState === Qt.Checked); + } } + } CheckBox { id: checkBox + onCheckStateChanged: { - if(checkState == Qt.Checked){ - isSelected = true - } else { - isSelected = false - } + if (checkState == Qt.Checked) + isSelected = true; + else + isSelected = false; } anchors { @@ -216,8 +235,10 @@ Item { right: parent.right margins: 10 } + } - } + + } states: [ State { @@ -228,31 +249,38 @@ Item { y: -10 opacity: 0 } + PropertyChanges { target: effect opacity: 0 } + }, State { name: "visible" + PropertyChanges { target: effect opacity: 0.4 } + PropertyChanges { target: screenPlayItemWrapper y: 0 opacity: 1 } + PropertyChanges { target: screenPlayItem width: 320 height: 180 } + PropertyChanges { target: icnType opacity: 0 } + }, State { name: "selected" @@ -262,10 +290,12 @@ Item { y: 0 opacity: 1 } + PropertyChanges { target: icnType - opacity: .5 + opacity: 0.5 } + } ] transitions: [ @@ -283,6 +313,7 @@ Item { property: "opacity" duration: 80 } + } ] } diff --git a/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml b/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml index b68e472e..b79451a7 100644 --- a/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml +++ b/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml @@ -2,24 +2,26 @@ import QtQuick 2.12 Item { id: screenPlayItemImage - width: 320 - height: 121 - state: "loading" property string sourceImage property string sourceImageGIF + width: 320 + height: 121 + state: "loading" + Image { id: image + anchors.fill: parent fillMode: Image.PreserveAspectCrop source: screenPlayItemImage.sourceImage.trim() onStatusChanged: { if (image.status === Image.Ready) { - screenPlayItemImage.state = "loaded" + screenPlayItemImage.state = "loaded"; } else if (image.status === Image.Error) { - source = "images/missingPreview.png" - screenPlayItemImage.state = "loaded" + source = "images/missingPreview.png"; + screenPlayItemImage.state = "loaded"; } } } @@ -32,6 +34,7 @@ Item { target: image opacity: 0 } + }, State { name: "loaded" @@ -40,9 +43,9 @@ Item { target: image opacity: 1 } + } ] - transitions: [ Transition { from: "loading" @@ -54,6 +57,7 @@ Item { duration: 300 easing.type: Easing.InOutQuad } + } ] } diff --git a/ScreenPlay/qml/Workshop/Sidebar.qml b/ScreenPlay/qml/Workshop/Sidebar.qml index d1404901..596990e6 100644 --- a/ScreenPlay/qml/Workshop/Sidebar.qml +++ b/ScreenPlay/qml/Workshop/Sidebar.qml @@ -4,51 +4,13 @@ import QtQuick.Controls 2.3 import QtQuick.Layouts 1.11 import QtWebEngine 1.8 import QtQuick.Controls.Material 2.2 - import ScreenPlay.Workshop 1.0 import ScreenPlay 1.0 Drawer { id: root - edge: Qt.RightEdge - height: parent.height - 60 - dim: false - modal: false - width: 400 - interactive: false + property SteamWorkshop steamWorkshop - - signal tagClicked(var tag) - - background: Rectangle { - color: Material.theme === Material.Light ? "white" : Qt.darker( - Material.background) - opacity: .95 - } - enter: Transition { - SmoothedAnimation { - velocity: 10 - easing.type: Easing.InOutQuart - } - } - exit: Transition { - SmoothedAnimation { - velocity: 10 - easing.type: Easing.InOutQuart - } - } - - Component.onCompleted: { - WebEngine.settings.localContentCanAccessFileUrls = true - WebEngine.settings.localContentCanAccessRemoteUrls = true - WebEngine.settings.allowRunningInsecureContent = true - WebEngine.settings.accelerated2dCanvasEnabled = true - WebEngine.settings.javascriptCanOpenWindows = false - WebEngine.settings.showScrollBars = false - WebEngine.settings.playbackRequiresUserGesture = false - WebEngine.settings.focusOnNavigationEnabled = true - } - property url videoPreview property alias imgUrl: img.source property string name @@ -57,84 +19,119 @@ Drawer { property int subscriptionCount property bool subscribed: false + signal tagClicked(var tag) + function setWorkshopItem(publishedFileID, imgUrl, videoPreview, subscriptionCount) { - if (root.publishedFileID === publishedFileID) { - if (!root.visible) { - root.open() - } else { - root.close() - } - return + if (!root.visible) + root.open(); + else + root.close(); + return ; } - webView.opacity = 0 - root.publishedFileID = publishedFileID - root.imgUrl = imgUrl - root.subscriptionCount = subscriptionCount - root.videoPreview = videoPreview - root.subscribed = false - txtVotesUp.highlighted = false - txtVotesDown.highlighted = false + webView.opacity = 0; + root.publishedFileID = publishedFileID; + root.imgUrl = imgUrl; + root.subscriptionCount = subscriptionCount; + root.videoPreview = videoPreview; + root.subscribed = false; + txtVotesUp.highlighted = false; + txtVotesDown.highlighted = false; + if (!root.visible) + root.open(); - if (!root.visible) { - root.open() - } + steamWorkshop.requestWorkshopItemDetails(publishedFileID); + webView.setVideo(); + } - steamWorkshop.requestWorkshopItemDetails(publishedFileID) - - webView.setVideo() + edge: Qt.RightEdge + height: parent.height - 60 + dim: false + modal: false + width: 400 + interactive: false + Component.onCompleted: { + WebEngine.settings.localContentCanAccessFileUrls = true; + WebEngine.settings.localContentCanAccessRemoteUrls = true; + WebEngine.settings.allowRunningInsecureContent = true; + WebEngine.settings.accelerated2dCanvasEnabled = true; + WebEngine.settings.javascriptCanOpenWindows = false; + WebEngine.settings.showScrollBars = false; + WebEngine.settings.playbackRequiresUserGesture = false; + WebEngine.settings.focusOnNavigationEnabled = true; } Connections { - target: steamWorkshop function onRequestItemDetailReturned(title, tags, steamIDOwner, description, votesUp, votesDown, url, fileSize, publishedFileId) { - - tagListModel.clear() - + tagListModel.clear(); // Even if the tags array is empty it still contains // one empty string, resulting in an empty button if (tags.length > 1) { for (var i in tags) { tagListModel.append({ - "name": tags[i] - }) + "name": tags[i] + }); } - rpTagList.model = tagListModel + rpTagList.model = tagListModel; } else { - rpTagList.model = null + rpTagList.model = null; } + txtTitle.text = title; + const size = Math.floor((1000 * ((fileSize / 1024) / 1000)) / 1000); + txtFileSize.text = qsTr("Size: ") + size + qsTr(" MB"); + pbVotes.to = votesDown + votesUp; + pbVotes.value = votesUp; + txtVotesDown.text = votesDown; + txtVotesUp.text = votesUp; + if (description === "") + description = qsTr("No description..."); - txtTitle.text = title - const size = Math.floor((1000 * ((fileSize / 1024) / 1000)) / 1000) - txtFileSize.text = qsTr("Size: ") + size + qsTr(" MB") - pbVotes.to = votesDown + votesUp - pbVotes.value = votesUp - txtVotesDown.text = votesDown - txtVotesUp.text = votesUp - if (description === "") { - description = qsTr("No description...") - } - - txtDescription.text = description - pbVotes.hoverText = votesUp + " / " + votesDown + txtDescription.text = description; + pbVotes.hoverText = votesUp + " / " + votesDown; } + + target: steamWorkshop } Item { id: imgWrapper + width: parent.width height: 220 + Image { id: img + fillMode: Image.PreserveAspectCrop anchors.fill: parent } + WebEngineView { id: webView - anchors.fill: parent - opacity: 0 property bool ready: false + + function getUpdateVideoCommand() { + let src = ""; + src += "var video = document.getElementById('video');\n"; + src += "video.src = '" + root.videoPreview + "';\n"; + // Incase a workshop item has no gif preview + src += "video.poster = '" + root.videoPreview + "';\n"; + src += "video.play();\n"; + return src; + } + + function setVideo() { + if (!root.videoPreview.toString().startsWith("https")) + return ; + + webView.runJavaScript(getUpdateVideoCommand(), function(result) { + webView.opacity = 1; + }); + } + + anchors.fill: parent + opacity: 0 url: "qrc:/assets/WorkshopPreview.html" onUrlChanged: print(url) @@ -142,55 +139,41 @@ Drawer { NumberAnimation { duration: 200 } + } - function getUpdateVideoCommand() { - let src = "" - src += "var video = document.getElementById('video');\n" - src += "video.src = '" + root.videoPreview + "';\n" - // Incase a workshop item has no gif preview - src += "video.poster = '" + root.videoPreview + "';\n" - src += "video.play();\n" - - return src - } - - function setVideo() { - if (!root.videoPreview.toString().startsWith("https")) - return - - webView.runJavaScript(getUpdateVideoCommand(), - function (result) { - webView.opacity = 1 - }) - } } LinearGradient { height: 50 cached: true + start: Qt.point(0, 50) + end: Qt.point(0, 0) anchors { bottom: parent.bottom right: parent.right left: parent.left } - start: Qt.point(0, 50) - end: Qt.point(0, 0) + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#EE000000" } + GradientStop { - position: 1.0 + position: 1 color: "#00000000" } + } + } Text { id: txtTitle + font.family: ScreenPlay.settings.font font.weight: Font.Thin verticalAlignment: Text.AlignBottom @@ -199,16 +182,19 @@ Drawer { wrapMode: Text.WordWrap elide: Text.ElideRight height: 50 + anchors { bottom: parent.bottom right: parent.right margins: 20 left: parent.left } + } MouseArea { id: button + height: 50 width: 50 anchors.top: parent.top @@ -218,15 +204,20 @@ Drawer { Image { id: imgBack + source: "qrc:/assets/icons/icon_arrow_right.svg" sourceSize: Qt.size(15, 15) fillMode: Image.PreserveAspectFit anchors.centerIn: parent } + } + } ColumnLayout { + spacing: 20 + anchors { top: imgWrapper.bottom right: parent.right @@ -235,8 +226,6 @@ Drawer { margins: 20 } - spacing: 20 - ColumnLayout { Layout.fillHeight: true Layout.fillWidth: true @@ -252,40 +241,47 @@ Drawer { ToolButton { id: txtVotesUp + Layout.fillWidth: true icon.source: "qrc:/assets/icons/icon_thumb_up.svg" font.family: ScreenPlay.settings.font ToolTip.visible: hovered ToolTip.text: qsTr("Click here if you like the content") onClicked: { - steamWorkshop.vote(root.publishedFileID, true) - txtVotesUp.highlighted = true - txtVotesDown.highlighted = false + steamWorkshop.vote(root.publishedFileID, true); + txtVotesUp.highlighted = true; + txtVotesDown.highlighted = false; } } + ToolButton { id: txtVotesDown + Layout.fillWidth: true icon.source: "qrc:/assets/icons/icon_thumb_down.svg" font.family: ScreenPlay.settings.font ToolTip.visible: hovered ToolTip.text: qsTr("Click here if you do not like the content") onClicked: { - steamWorkshop.vote(root.publishedFileID, false) - txtVotesUp.highlighted = false - txtVotesDown.highlighted = true + steamWorkshop.vote(root.publishedFileID, false); + txtVotesUp.highlighted = false; + txtVotesDown.highlighted = true; } } + } ProgressBar { id: pbVotes + property string hoverText + Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true ToolTip.visible: hovered ToolTip.text: hoverText } + } Flickable { @@ -294,50 +290,64 @@ Drawer { Layout.fillWidth: true clip: true contentWidth: rowTagList.width + rpTagList.count * rowTagList.spacing + ListModel { id: tagListModel } + Row { id: rowTagList + width: parent.width spacing: 10 + Repeater { id: rpTagList delegate: Button { id: txtTags + property string tags + text: name font.pointSize: 8 font.family: ScreenPlay.settings.font onClicked: root.tagClicked(txtTags.text) } + } + } + } RowLayout { Layout.fillWidth: true spacing: 20 + Text { id: txtSubscriptionCount + color: Material.secondaryTextColor font.family: ScreenPlay.settings.font font.pointSize: 11 text: qsTr("Subscribtions: ") + root.subscriptionCount wrapMode: Text.WrapAtWordBoundaryOrAnywhere } + Item { Layout.fillWidth: true } Text { id: txtFileSize + color: Material.secondaryTextColor font.family: ScreenPlay.settings.font font.pointSize: 11 wrapMode: Text.WrapAtWordBoundaryOrAnywhere } + } Rectangle { @@ -346,6 +356,7 @@ Drawer { Layout.fillHeight: true //txtDescription.paintedHeight > 100 color: Material.backgroundColor radius: 3 + ScrollView { anchors.fill: parent anchors.margins: 20 @@ -355,33 +366,43 @@ Drawer { Text { id: txtDescription + width: parent.width color: Material.primaryTextColor font.family: ScreenPlay.settings.font font.pointSize: 12 wrapMode: Text.WrapAtWordBoundaryOrAnywhere } + } + } + } + } + RowLayout { id: rlBottomButtons + + spacing: 20 + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 20 } - spacing: 20 + ToolButton { id: btnOpenInSteam + font.pointSize: 10 icon.source: "qrc:/assets/icons/icon_open_in_new.svg" height: 25 text: qsTr("Open In Steam") - onClicked: Qt.openUrlExternally( - "steam://url/CommunityFilePage/" + root.publishedFileID) + onClicked: Qt.openUrlExternally("steam://url/CommunityFilePage/" + root.publishedFileID) } + Button { id: btnSubscribe @@ -390,16 +411,32 @@ Drawer { icon.source: "qrc:/assets/icons/icon_download.svg" text: root.subscribed ? qsTr("Subscribed!") : qsTr("Subscribe") onClicked: { - root.subscribed = true - root.steamWorkshop.subscribeItem(root.publishedFileID) + root.subscribed = true; + root.steamWorkshop.subscribeItem(root.publishedFileID); } } + } -} -/*##^## -Designer { - D{i:0;formeditorZoom:0.75;height:800;width:300} -} -##^##*/ + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Qt.darker(Material.background) + opacity: 0.95 + } + enter: Transition { + SmoothedAnimation { + velocity: 10 + easing.type: Easing.InOutQuart + } + + } + + exit: Transition { + SmoothedAnimation { + velocity: 10 + easing.type: Easing.InOutQuart + } + + } + +} diff --git a/ScreenPlay/qml/Workshop/Workshop.qml b/ScreenPlay/qml/Workshop/Workshop.qml index 62d25106..ee644c08 100644 --- a/ScreenPlay/qml/Workshop/Workshop.qml +++ b/ScreenPlay/qml/Workshop/Workshop.qml @@ -3,24 +3,29 @@ import QtQuick.Controls 2.13 import QtQuick.Controls.Material 2.13 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.12 - import ScreenPlay.Workshop 1.0 import ScreenPlay.Workshop.SteamEnums 1.0 import ScreenPlay 1.0 - import "upload/" - import "../Common" as Common Item { id: root + + property alias steamWorkshop: screenPlayWorkshop.steamWorkshop + state: "base" onVisibleChanged: { if (!visible) - sidebar.close() - } + sidebar.close(); - property alias steamWorkshop: screenPlayWorkshop.steamWorkshop + } + Component.onCompleted: { + if (steamWorkshop.online) + steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); + else + popupOffline.open(); + } MouseArea { enabled: gridView.count === 0 @@ -36,28 +41,20 @@ Item { id: screenPlayWorkshop } - Component.onCompleted: { - if (steamWorkshop.online) { - steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend) - } else { - popupOffline.open() - } - } - Connections { - target: steamWorkshop function onWorkshopSearched() { - bannerTxt.text = steamWorkshop.workshopListModel.getBannerText() - background.backgroundImage = steamWorkshop.workshopListModel.getBannerUrl() - banner.bannerPublishedFileID = steamWorkshop.workshopListModel.getBannerID() - bannerTxtUnderline.numberSubscriber - = steamWorkshop.workshopListModel.getBannerAmountSubscriber( - ) + bannerTxt.text = steamWorkshop.workshopListModel.getBannerText(); + background.backgroundImage = steamWorkshop.workshopListModel.getBannerUrl(); + banner.bannerPublishedFileID = steamWorkshop.workshopListModel.getBannerID(); + bannerTxtUnderline.numberSubscriber = steamWorkshop.workshopListModel.getBannerAmountSubscriber(); } + + target: steamWorkshop } Background { id: background + anchors.fill: parent } @@ -67,6 +64,7 @@ Item { UploadProject { id: popupUploadProject + steamWorkshop: root.steamWorkshop workshop: screenPlayWorkshop } @@ -76,60 +74,51 @@ Item { } Connections { - target: steamWorkshop.uploadListModel function onUserNeedsToAcceptWorkshopLegalAgreement() { - popupSteamWorkshopAgreement.open() + popupSteamWorkshopAgreement.open(); } + + target: steamWorkshop.uploadListModel } Navigation { id: nav + steamWorkshop: root.steamWorkshop z: 3 + onUploadPressed: popupUploadProject.open() + anchors { top: parent.top right: parent.right left: parent.left } - onUploadPressed: popupUploadProject.open() } Flickable { id: scrollView + anchors.fill: parent contentWidth: parent.width contentHeight: gridView.height + header.height + 150 - - Behavior on contentHeight { - PropertyAnimation { - duration: 400 - property: "contentHeight" - easing.type: Easing.InOutQuart - } - } - onContentYChanged: { // Calculate parallax scrolling - if (contentY >= 0) { - background.imageOffsetTop = (contentY * -.4) - } else { - background.imageOffsetTop = 0 - } - if (contentY >= (header.height)) { - root.state = "scrolling" - } else { - root.state = "base" - } - } - - ScrollBar.vertical: ScrollBar { - snapMode: ScrollBar.SnapOnRelease + if (contentY >= 0) + background.imageOffsetTop = (contentY * -0.4); + else + background.imageOffsetTop = 0; + if (contentY >= (header.height)) + root.state = "scrolling"; + else + root.state = "base"; } Item { id: header + height: 350 + anchors { top: parent.top topMargin: nav.height @@ -139,23 +128,29 @@ Item { Item { id: banner - height: 350 + property var bannerPublishedFileID + + height: 350 + anchors { top: parent.top right: parent.right left: parent.left } + Image { id: bannerImg2 + + asynchronous: true + fillMode: Image.PreserveAspectCrop + anchors { right: parent.right left: parent.left bottom: parent.bottom } - asynchronous: true - fillMode: Image.PreserveAspectCrop } ColumnLayout { @@ -169,7 +164,9 @@ Item { Text { id: bannerTxtUnderline + property int numberSubscriber: 0 + text: numberSubscriber + " SUBSCRIBED TO:" font.pointSize: 12 color: "white" @@ -179,6 +176,7 @@ Item { Text { id: bannerTxt + text: qsTr("Loading") font.pointSize: 42 color: "white" @@ -189,18 +187,18 @@ Item { RowLayout { spacing: 10 + Button { text: qsTr("Download now!") Material.background: Material.accent Material.foreground: "white" icon.source: "qrc:/assets/icons/icon_download.svg" onClicked: { - text = qsTr("Downloading...") - steamWorkshop.subscribeItem( - steamWorkshop.workshopListModel.getBannerID( - )) + text = qsTr("Downloading..."); + steamWorkshop.subscribeItem(steamWorkshop.workshopListModel.getBannerID()); } } + Button { text: qsTr("Details") Material.background: Material.accent @@ -208,24 +206,22 @@ Item { icon.source: "qrc:/assets/icons/icon_info.svg" visible: false onClicked: { - sidebar.setWorkshopItem(publishedFileID, - imgUrl, - additionalPreviewUrl, - subscriptionCount) + sidebar.setWorkshopItem(publishedFileID, imgUrl, additionalPreviewUrl, subscriptionCount); } } + } MouseArea { - onClicked: Qt.openUrlExternally( - "steam://url/CommunityFilePage/" - + banner.bannerPublishedFileID) + onClicked: Qt.openUrlExternally("steam://url/CommunityFilePage/" + banner.bannerPublishedFileID) height: 30 width: bannerTxtOpenInSteam.paintedWidth cursorShape: Qt.PointingHandCursor + Text { id: bannerTxtOpenInSteam - opacity: .7 + + opacity: 0.7 text: qsTr("Open In Steam") font.pointSize: 10 color: "white" @@ -233,21 +229,27 @@ Item { font.family: ScreenPlay.settings.font font.weight: Font.Thin } + } + } + } + } GridView { id: gridView + maximumFlickVelocity: 7000 flickDeceleration: 5000 cellWidth: 330 cellHeight: 190 height: contentHeight interactive: false - model: steamWorkshop.workshopListModel + boundsBehavior: Flickable.StopAtBounds + anchors { top: header.bottom topMargin: 100 @@ -257,9 +259,10 @@ Item { } header: Item { + property alias searchField: tiSearch + height: 80 width: gridView.width - gridView.anchors.leftMargin - property alias searchField: tiSearch Rectangle { color: Material.backgroundColor @@ -270,8 +273,10 @@ Item { Item { id: searchWrapper + width: 400 height: 50 + anchors { verticalCenter: parent.verticalCenter left: parent.left @@ -280,6 +285,12 @@ Item { TextField { id: tiSearch + + leftPadding: 25 + selectByMouse: true + placeholderText: qsTr("Search for Wallpaper and Widgets...") + onTextChanged: timerSearch.restart() + anchors { top: parent.top right: parent.right @@ -287,16 +298,14 @@ Item { left: parent.left leftMargin: 10 } - leftPadding: 25 - selectByMouse: true - placeholderText: qsTr("Search for Wallpaper and Widgets...") - onTextChanged: timerSearch.restart() + Timer { id: timerSearch + interval: 500 - onTriggered: steamWorkshop.searchWorkshopByText( - tiSearch.text) + onTriggered: steamWorkshop.searchWorkshopByText(tiSearch.text) } + } Image { @@ -304,30 +313,36 @@ Item { width: 14 height: width sourceSize: Qt.size(width, width) + anchors { left: parent.left leftMargin: 15 bottom: parent.bottom bottomMargin: 22 } + } ToolButton { id: tb + enabled: tiSearch.text !== "" + icon.source: "qrc:/assets/icons/font-awsome/close.svg" + onClicked: tiSearch.text = "" + anchors { right: parent.right bottom: parent.bottom bottomMargin: 10 } - icon.source: "qrc:/assets/icons/font-awsome/close.svg" - onClicked: tiSearch.text = "" } + } RowLayout { spacing: 20 + anchors { left: searchWrapper.right leftMargin: 20 @@ -335,89 +350,92 @@ Item { rightMargin: 20 verticalCenter: parent.verticalCenter } + Item { Layout.fillWidth: true Layout.fillHeight: true } + Button { text: qsTr("Open Workshop in Steam") font.capitalization: Font.Capitalize font.family: ScreenPlay.settings.font - onClicked: Qt.openUrlExternally( - "steam://url/SteamWorkshopPage/672870") + onClicked: Qt.openUrlExternally("steam://url/SteamWorkshopPage/672870") icon.source: "qrc:/assets/icons/icon_steam.svg" icon.width: 18 icon.height: 18 height: cbQuerySort.height } + Button { text: qsTr("Open GameHub in Steam") font.capitalization: Font.Capitalize font.family: ScreenPlay.settings.font - onClicked: Qt.openUrlExternally( - "steam://url/GameHub/672870") + onClicked: Qt.openUrlExternally("steam://url/GameHub/672870") icon.source: "qrc:/assets/icons/icon_steam.svg" icon.width: 18 icon.height: 18 height: cbQuerySort.height } + } ComboBox { id: cbQuerySort + width: 250 height: searchWrapper.height + textRole: "text" + valueRole: "value" + currentIndex: 2 + Layout.preferredHeight: searchWrapper.height + font.family: ScreenPlay.settings.font + model: [{ + "value": SteamEnums.k_EUGCQuery_RankedByVote, + "text": qsTr("Ranked By Vote") + }, { + "value": SteamEnums.K_EUGCQuery_RankedByPublicationDate, + "text": qsTr("Publication Date") + }, { + "value": SteamEnums.K_EUGCQuery_RankedByTrend, + "text": qsTr("Ranked By Trend") + }, { + "value": SteamEnums.K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate, + "text": qsTr("Favorited By Friends") + }, { + "value": SteamEnums.K_EUGCQuery_CreatedByFriendsRankedByPublicationDate, + "text": qsTr("Created By Friends") + }, { + "value": SteamEnums.K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate, + "text": qsTr("Created By Followed Users") + }, { + "value": SteamEnums.K_EUGCQuery_NotYetRated, + "text": qsTr("Not Yet Rated") + }, { + "value": SteamEnums.K_EUGCQuery_RankedByTotalVotesAsc, + "text": qsTr("Total VotesAsc") + }, { + "value": SteamEnums.K_EUGCQuery_RankedByVotesUp, + "text": qsTr("Votes Up") + }, { + "value": SteamEnums.K_EUGCQuery_RankedByTotalUniqueSubscriptions, + "text": qsTr("Total Unique Subscriptions") + }] + onActivated: { + steamWorkshop.searchWorkshop(cbQuerySort.currentValue); + } + anchors { verticalCenter: parent.verticalCenter right: parent.right rightMargin: 10 } - textRole: "text" - valueRole: "value" - currentIndex: 2 - Layout.preferredHeight: searchWrapper.height - font.family: ScreenPlay.settings.font - onActivated: { - steamWorkshop.searchWorkshop( - cbQuerySort.currentValue) - } - model: [{ - "value": SteamEnums.k_EUGCQuery_RankedByVote, - "text": qsTr("Ranked By Vote") - }, { - "value": SteamEnums.K_EUGCQuery_RankedByPublicationDate, - "text": qsTr("Publication Date") - }, { - "value": SteamEnums.K_EUGCQuery_RankedByTrend, - "text": qsTr("Ranked By Trend") - }, { - "value": SteamEnums.K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate, - "text": qsTr("Favorited By Friends") - }, { - "value": SteamEnums.K_EUGCQuery_CreatedByFriendsRankedByPublicationDate, - "text": qsTr("Created By Friends") - }, { - "value": SteamEnums.K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate, - "text": qsTr("Created By Followed Users") - }, { - "value": SteamEnums.K_EUGCQuery_NotYetRated, - "text": qsTr("Not Yet Rated") - }, { - "value": SteamEnums.K_EUGCQuery_RankedByTotalVotesAsc, - "text": qsTr("Total VotesAsc") - }, { - "value": SteamEnums.K_EUGCQuery_RankedByVotesUp, - "text": qsTr("Votes Up") - }, { - "value": SteamEnums.K_EUGCQuery_RankedByTotalUniqueSubscriptions, - "text": qsTr("Total Unique Subscriptions") - }] } - } - } - boundsBehavior: Flickable.StopAtBounds + } + + } delegate: WorkshopItem { imgUrl: m_workshopPreview @@ -428,14 +446,13 @@ Item { itemIndex: index steamWorkshop: root.steamWorkshop onClicked: { - sidebar.setWorkshopItem(publishedFileID, imgUrl, - additionalPreviewUrl, - subscriptionCount) + sidebar.setWorkshopItem(publishedFileID, imgUrl, additionalPreviewUrl, subscriptionCount); } } ScrollBar.vertical: ScrollBar { id: workshopScrollBar + snapMode: ScrollBar.SnapOnRelease } @@ -443,62 +460,76 @@ Item { height: 150 width: parent.width spacing: 10 + Item { Layout.fillWidth: true } + Button { id: btnBack + Layout.alignment: Qt.AlignVCenter text: qsTr("Back") enabled: steamWorkshop.workshopListModel.currentPage > 1 onClicked: { - steamWorkshop.workshopListModel.setCurrentPage( - steamWorkshop.workshopListModel.currentPage - 1) - steamWorkshop.searchWorkshop( - SteamEnums.K_EUGCQuery_RankedByTrend) + steamWorkshop.workshopListModel.setCurrentPage(steamWorkshop.workshopListModel.currentPage - 1); + steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); } } + Text { id: txtPage + Layout.alignment: Qt.AlignVCenter - text: steamWorkshop.workshopListModel.currentPage + "/" - + steamWorkshop.workshopListModel.pages + text: steamWorkshop.workshopListModel.currentPage + "/" + steamWorkshop.workshopListModel.pages font.family: ScreenPlay.settings.font color: Material.primaryTextColor } + Button { id: btnForward + Layout.alignment: Qt.AlignVCenter text: qsTr("Forward") - enabled: steamWorkshop.workshopListModel.currentPage - <= steamWorkshop.workshopListModel.pages - 1 + enabled: steamWorkshop.workshopListModel.currentPage <= steamWorkshop.workshopListModel.pages - 1 onClicked: { - steamWorkshop.workshopListModel.setCurrentPage( - steamWorkshop.workshopListModel.currentPage + 1) - steamWorkshop.searchWorkshop( - SteamEnums.K_EUGCQuery_RankedByTrend) + steamWorkshop.workshopListModel.setCurrentPage(steamWorkshop.workshopListModel.currentPage + 1); + steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); } } + Item { Layout.fillWidth: true } + } + } + + Behavior on contentHeight { + PropertyAnimation { + duration: 400 + property: "contentHeight" + easing.type: Easing.InOutQuart + } + + } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + } + } Sidebar { id: sidebar + topMargin: 60 steamWorkshop: root.steamWorkshop onTagClicked: { - gridView.headerItem.searchField.text = tag - sidebar.close() + gridView.headerItem.searchField.text = tag; + sidebar.close(); } } -} -/*##^## Designer { - D{i:0;autoSize:true;height:800;width:1366} } - ##^##*/ - diff --git a/ScreenPlay/qml/Workshop/WorkshopInstalled.qml b/ScreenPlay/qml/Workshop/WorkshopInstalled.qml index 334df2cc..0354a435 100644 --- a/ScreenPlay/qml/Workshop/WorkshopInstalled.qml +++ b/ScreenPlay/qml/Workshop/WorkshopInstalled.qml @@ -6,29 +6,32 @@ import ScreenPlay.Workshop 1.0 as SP Item { id: pageInstalled - state: "out" - clip: true + + property bool refresh: false + property bool enabled: true signal setSidebaractiveItem(var screenId, var type) signal setNavigationItem(var pos) signal setSidebarActive(var active) - property bool refresh: false - property bool enabled: true - + state: "out" + clip: true + states: [] Component.onCompleted: { - pageInstalled.state = "in" + pageInstalled.state = "in"; } Connections { - target: loaderHelp.item function onHelperButtonPressed(pos) { - setNavigationItem(pos) + setNavigationItem(pos); } + + target: loaderHelp.item } Loader { id: loaderHelp + asynchronous: true active: false z: 99 @@ -36,10 +39,6 @@ Item { source: "qrc:/qml/Installed/InstalledUserHelper.qml" } - - - states: [] - transitions: [ Transition { from: "out" diff --git a/ScreenPlay/qml/Workshop/WorkshopItem.qml b/ScreenPlay/qml/Workshop/WorkshopItem.qml index 2ea104b3..183ec942 100644 --- a/ScreenPlay/qml/Workshop/WorkshopItem.qml +++ b/ScreenPlay/qml/Workshop/WorkshopItem.qml @@ -3,13 +3,10 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.2 import ScreenPlay.Workshop 1.0 - import ScreenPlay 1.0 Item { id: root - width: 320 - height: 180 property url imgUrl property url additionalPreviewUrl @@ -22,12 +19,36 @@ Item { signal clicked(var publishedFileID, url imgUrl) + width: 320 + height: 180 + transform: [ + Rotation { + id: rt + + origin.x: width * 0.5 + origin.y: height * 0.5 + angle: 0 + + axis { + x: -0.5 + y: 0 + z: 0 + } + + }, + Translate { + id: tr + }, + Scale { + id: sc + + origin.x: width * 0.5 + origin.y: height * 0.5 + } + ] + RectangularGlow { id: effect - anchors { - top: parent.top - topMargin: 3 - } height: parent.height width: parent.width @@ -37,39 +58,28 @@ Item { color: "black" opacity: 0.4 cornerRadius: 15 + + anchors { + top: parent.top + topMargin: 3 + } + } + Timer { id: timerAnim + interval: 40 * itemIndex * Math.random() running: true repeat: false onTriggered: showAnim.start() } - transform: [ - Rotation { - id: rt - origin.x: width * .5 - origin.y: height * .5 - axis { - x: -.5 - y: 0 - z: 0 - } - angle: 0 - }, - Translate { - id: tr - }, - Scale { - id: sc - origin.x: width * .5 - origin.y: height * .5 - } - ] ParallelAnimation { id: showAnim + running: false + RotationAnimation { target: rt from: 90 @@ -78,6 +88,7 @@ Item { easing.type: Easing.OutQuint property: "angle" } + PropertyAnimation { target: root from: 0 @@ -86,6 +97,7 @@ Item { easing.type: Easing.OutQuint property: "opacity" } + PropertyAnimation { target: tr from: 80 @@ -94,24 +106,28 @@ Item { easing.type: Easing.OutQuint property: "y" } + PropertyAnimation { target: sc - from: .8 + from: 0.8 to: 1 duration: 500 easing.type: Easing.OutQuint properties: "xScale,yScale" } + } Item { id: screenPlay + anchors.centerIn: parent height: 180 width: 320 Image { id: mask + source: "qrc:/assets/images/Window.svg" sourceSize: Qt.size(screenPlay.width, screenPlay.height) visible: false @@ -121,7 +137,9 @@ Item { Item { id: itemWrapper + visible: false + anchors { fill: parent margins: 5 @@ -129,6 +147,7 @@ Item { ScreenPlayItemImage { id: screenPlayItemImage + anchors.fill: parent sourceImage: root.imgUrl sourceImageGIF: root.additionalPreviewUrl @@ -136,29 +155,37 @@ Item { LinearGradient { id: shadow + height: 80 opacity: 0 cached: true + start: Qt.point(0, 80) + end: Qt.point(0, 0) + anchors { bottom: parent.bottom right: parent.right left: parent.left } - start: Qt.point(0, 80) - end: Qt.point(0, 0) + gradient: Gradient { GradientStop { - position: 0.0 + position: 0 color: "#CC000000" } + GradientStop { - position: 1.0 + position: 1 color: "#00000000" } + } + } + Text { id: txtTitle + text: root.name opacity: 0 height: 30 @@ -168,6 +195,7 @@ Item { font.pointSize: 14 wrapMode: Text.WrapAtWordBoundaryOrAnywhere font.family: ScreenPlay.settings.font + anchors { bottom: parent.bottom right: parent.right @@ -176,25 +204,31 @@ Item { leftMargin: 20 bottomMargin: -50 } + } Item { id: openInWorkshop + height: 20 width: 20 z: 99 opacity: 0 + anchors { margins: 10 top: parent.top right: parent.right } + Image { source: "qrc:/assets/icons/icon_open_in_new.svg" sourceSize: Qt.size(parent.width, parent.height) fillMode: Image.PreserveAspectFit } + } + } OpacityMask { @@ -208,34 +242,38 @@ Item { cursorShape: Qt.PointingHandCursor onContainsMouseChanged: { if (!isDownloading) { - if (containsMouse) { - root.state = "hover" - } else { - root.state = "" - } + if (containsMouse) + root.state = "hover"; + else + root.state = ""; } } onClicked: { - root.clicked(root.publishedFileID, root.imgUrl) + root.clicked(root.publishedFileID, root.imgUrl); } } + MouseArea { height: 20 width: 20 cursorShape: Qt.PointingHandCursor + onClicked: { + Qt.openUrlExternally("steam://url/CommunityFilePage/" + root.publishedFileID); + } + anchors { margins: 10 top: parent.top right: parent.right } - onClicked: { - Qt.openUrlExternally( - "steam://url/CommunityFilePage/" + root.publishedFileID) - } + } + } + FastBlur { id: effBlur + anchors.fill: itemWrapper source: itemWrapper radius: 0 @@ -243,7 +281,9 @@ Item { Item { id: itmDownloading + opacity: 0 + anchors { top: parent.top topMargin: 50 @@ -254,12 +294,14 @@ Item { Text { id: txtDownloading + text: qsTr("Successfully subscribed to Workshop Item!") color: "white" font.pointSize: 18 wrapMode: Text.WordWrap font.family: ScreenPlay.settings.font horizontalAlignment: Qt.AlignHCenter + anchors { verticalCenter: parent.verticalCenter right: parent.right @@ -267,8 +309,11 @@ Item { left: parent.left leftMargin: 20 } + } + } + } states: [ @@ -277,7 +322,7 @@ Item { PropertyChanges { target: openInWorkshop - opacity: .75 + opacity: 0.75 } PropertyChanges { @@ -290,10 +335,12 @@ Item { target: shadow opacity: 1 } + PropertyChanges { target: effBlur radius: 0 } + }, State { name: "downloading" @@ -323,6 +370,7 @@ Item { opacity: 1 anchors.topMargin: 0 } + }, State { name: "installed" @@ -347,10 +395,12 @@ Item { opacity: 1 anchors.topMargin: 0 } + PropertyChanges { target: txtDownloading text: qsTr("Download complete!") } + } ] transitions: [ @@ -364,16 +414,19 @@ Item { duration: 100 properties: "opacity" } + PropertyAnimation { target: txtTitle duration: 100 properties: "opacity, anchors.bottomMargin" } + PropertyAnimation { target: shadow duration: 100 properties: "opacity" } + }, Transition { from: "*" @@ -385,23 +438,28 @@ Item { duration: 100 properties: "opacity" } + PropertyAnimation { target: shadow duration: 100 properties: "opacity" } + SequentialAnimation { PropertyAnimation { target: effBlur duration: 500 properties: "radius" } + PropertyAnimation { target: txtTitle duration: 200 properties: "opacity, anchors.topMargin" } + } + } ] } diff --git a/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml b/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml index 66f56b52..6759d1ab 100644 --- a/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml +++ b/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml @@ -2,22 +2,19 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Controls.Material 2.12 import QtQuick.Layouts 1.12 - import ScreenPlay.Workshop 1.0 as SP import ScreenPlay 1.0 - import "../../Common" Popup { id: root + dim: true width: 800 height: 400 closePolicy: Popup.NoAutoClose anchors.centerIn: Overlay.overlay - background: Rectangle { - color: Material.theme === Material.Light ? "white" : Material.background - } + ColumnLayout { anchors { fill: parent @@ -31,6 +28,7 @@ Popup { Text { id: name + text: qsTr("REQUIRES INTERNET CONNECTION AND FREE STEAM ACCOUNT TO ACTIVATE. Notice: Product offered subject to your acceptance of the Steam Subscriber Agreement (SSA). You must activate this product via the Internet by registering for a Steam account and accepting the SSA. Please see https://store.steampowered.com/subscriber_agreement/ to view the SSA prior to purchase. If you do not agree with the provisions of the SSA, you should return this game unopened to your retailer in accordance with their return policy.") font: ScreenPlay.settings.font color: Material.primaryTextColor @@ -40,28 +38,37 @@ Popup { RowLayout { Layout.fillWidth: true + Item { Layout.fillWidth: true } + Button { id: btnAbort + text: qsTr("View The Steam Subscriber Agreement") - onClicked: Qt.openUrlExternally( - "https://store.steampowered.com/subscriber_agreement/") + onClicked: Qt.openUrlExternally("https://store.steampowered.com/subscriber_agreement/") } Button { id: btnAgree + text: qsTr("Accept Steam Workshop Agreement") highlighted: true Material.background: Material.accent Material.foreground: "white" onClicked: { - Qt.openUrlExternally( - "https://steamcommunity.com/sharedfiles/workshoplegalagreement") - root.close() + Qt.openUrlExternally("https://steamcommunity.com/sharedfiles/workshoplegalagreement"); + root.close(); } } + } + } + + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Material.background + } + } diff --git a/ScreenPlay/qml/Workshop/upload/UploadProject.qml b/ScreenPlay/qml/Workshop/upload/UploadProject.qml index 5b2f239a..2593c64c 100644 --- a/ScreenPlay/qml/Workshop/upload/UploadProject.qml +++ b/ScreenPlay/qml/Workshop/upload/UploadProject.qml @@ -2,12 +2,15 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Controls.Material 2.12 import QtQuick.Layouts 1.12 - import ScreenPlay.Workshop 1.0 import ScreenPlay 1.0 Popup { id: root + + property SteamWorkshop steamWorkshop + property ScreenPlayWorkshop workshop + width: 1200 height: 700 modal: true @@ -16,33 +19,34 @@ Popup { closePolicy: Popup.NoAutoClose onAboutToShow: uploadLoader.sourceComponent = com onAboutToHide: uploadLoader.sourceComponent = undefined - property SteamWorkshop steamWorkshop - property ScreenPlayWorkshop workshop - background: Rectangle { - color: Material.theme === Material.Light ? "white" : Material.background - } Loader { id: uploadLoader + anchors.fill: parent } Connections { - target: uploadLoader.item function onRequestClosePopup() { - root.close() + root.close(); } + + target: uploadLoader.item } Component { id: com + Item { id: wrapper - signal requestClosePopup + + signal requestClosePopup() Item { id: headerWrapper + height: 50 + anchors { top: parent.top right: parent.right @@ -52,6 +56,7 @@ Popup { Text { id: txtHeadline + text: qsTr("Upload Wallpaper/Widgets to Steam") color: Material.foreground font.pointSize: 21 @@ -62,13 +67,18 @@ Popup { top: parent.top horizontalCenter: parent.horizontalCenter } + } + } SwipeView { id: view + clip: true currentIndex: 0 + interactive: false + anchors { top: headerWrapper.bottom right: parent.right @@ -76,13 +86,13 @@ Popup { left: parent.left margins: 10 } - interactive: false Item { id: firstPage GridView { id: gridView + boundsBehavior: Flickable.DragOverBounds maximumFlickVelocity: 7000 flickDeceleration: 5000 @@ -90,6 +100,7 @@ Popup { cellHeight: 250 clip: true model: workshop.installedListModel + anchors { top: parent.top right: parent.right @@ -97,8 +108,10 @@ Popup { left: parent.left margins: 10 } + delegate: UploadProjectBigItem { id: delegate + focus: true width: gridView.cellWidth - 30 customTitle: m_title @@ -111,11 +124,11 @@ Popup { onItemClicked: { for (let childItem in gridView.contentItem.children) { if (gridView.contentItem.children[childItem].isSelected) { - btnUploadProjects.enabled = true - return + btnUploadProjects.enabled = true; + return ; } } - btnUploadProjects.enabled = false + btnUploadProjects.enabled = false; } } @@ -123,12 +136,15 @@ Popup { snapMode: ScrollBar.SnapOnRelease policy: ScrollBar.AlwaysOn } + } + Button { id: btnAbort + text: qsTr("Abort") onClicked: { - wrapper.requestClosePopup() + wrapper.requestClosePopup(); } anchors { @@ -136,38 +152,42 @@ Popup { bottom: parent.bottom margins: 10 } + } Button { id: btnUploadProjects + text: qsTr("Upload Selected Projects") highlighted: true enabled: false + onClicked: { + var uploadListArray = []; + for (let childItem in gridView.contentItem.children) { + if (gridView.contentItem.children[childItem].isSelected) + uploadListArray.push(gridView.contentItem.children[childItem].absoluteStoragePath); + + } + view.currentIndex = 1; + steamWorkshop.bulkUploadToWorkshop(uploadListArray); + } + anchors { right: parent.right bottom: parent.bottom margins: 10 } - onClicked: { - var uploadListArray = [] - for (let childItem in gridView.contentItem.children) { - if (gridView.contentItem.children[childItem].isSelected) { - - uploadListArray.push( - gridView.contentItem.children[childItem].absoluteStoragePath) - } - } - view.currentIndex = 1 - steamWorkshop.bulkUploadToWorkshop(uploadListArray) - } } + } + Item { id: secondPage ListView { id: listView + boundsBehavior: Flickable.DragOverBounds maximumFlickVelocity: 7000 flickDeceleration: 5000 @@ -176,6 +196,7 @@ Popup { model: steamWorkshop.uploadListModel width: parent.width - 50 spacing: 25 + anchors { top: parent.top horizontalCenter: parent.horizontalCenter @@ -184,7 +205,6 @@ Popup { } delegate: UploadProjectItem { - previewImagePath: m_absolutePreviewImagePath progress: m_uploadProgress name: m_name @@ -194,29 +214,37 @@ Popup { ScrollBar.vertical: ScrollBar { snapMode: ScrollBar.SnapOnRelease } + } Button { id: btnFinish + text: qsTr("Finish") - onClicked: { - root.close() - } highlighted: true enabled: false + onClicked: { + root.close(); + } + anchors { right: parent.right bottom: parent.bottom margins: 10 } + Connections { - target: steamWorkshop.uploadListModel function onUploadCompleted() { - btnFinish.enabled = true + btnFinish.enabled = true; } + + target: steamWorkshop.uploadListModel } + } + } + } PageIndicator { @@ -224,10 +252,16 @@ Popup { count: view.count currentIndex: view.currentIndex - anchors.bottom: view.bottom anchors.horizontalCenter: parent.horizontalCenter } + } + } + + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Material.background + } + } diff --git a/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml b/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml index 7cfdd881..736dc107 100644 --- a/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml +++ b/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml @@ -3,18 +3,14 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.12 import QtQuick.Layouts 1.12 - import QtQuick.Controls.Material.impl 2.12 import ScreenPlay 1.0 - import "../" Item { id: root - height: 250 property bool isProjectValid: false - property alias checkBox: checkBox property bool isSelected: false property string customTitle: "name here" @@ -25,24 +21,17 @@ Item { property bool hasMenuOpen: false property var publishedFileID: 0 property int itemIndex + signal itemClicked(var screenId, var type, var isActive) + height: 250 onTypeChanged: { - if (type === "widget") { - icnType.source = "icons/icon_widgets.svg" - } else if (type === "qmlScene") { - icnType.source = "icons/icon_code.svg" - } + if (type === "widget") + icnType.source = "icons/icon_widgets.svg"; + else if (type === "qmlScene") + icnType.source = "icons/icon_code.svg"; } - // Component.onCompleted: { - // print("root.preview",root.preview) - // if (root.preview == undefined) { - // print("invalid") - // } else { - // root.isProjectValid = true - // } - // if (!isProjectValid) { // root.state = "invalid" // } @@ -51,58 +40,69 @@ Item { anchors.fill: screenPlayItemWrapper radius: 4 layer.enabled: true + color: Material.theme === Material.Light ? "white" : Material.background + layer.effect: ElevationEffect { elevation: 6 } - color: Material.theme === Material.Light ? "white" : Material.background + } Item { id: screenPlayItemWrapper + anchors.fill: parent anchors.margins: 20 Item { id: itemWrapper + width: parent.width height: parent.height clip: true Image { id: screenPlayItemImage + width: 400 + source: Qt.resolvedUrl(root.absoluteStoragePath + "/" + root.preview) + anchors { top: parent.top left: parent.left bottom: parent.bottom } - source: Qt.resolvedUrl( - root.absoluteStoragePath + "/" + root.preview) + } Image { id: icnType + width: 20 height: 20 sourceSize: Qt.size(20, 20) + anchors { top: parent.top left: parent.left margins: 10 } + } ColumnLayout { + spacing: 10 + anchors { top: parent.top right: parent.right left: screenPlayItemImage.right margins: 20 } - spacing: 10 Text { id: name + text: m_title color: Material.foreground font.pointSize: 18 @@ -115,22 +115,24 @@ Item { color: Material.foreground font.family: ScreenPlay.settings.font } + } Button { text: qsTr("Open Folder") - onClicked: ScreenPlay.util.openFolderInExplorer( - m_absoluteStoragePath) + onClicked: ScreenPlay.util.openFolderInExplorer(m_absoluteStoragePath) + anchors { right: parent.right bottom: parent.bottom margins: 20 } - } + } Text { id: txtInvalidError + text: qsTr("Invalid Project!") color: Material.color(Material.Red) anchors.fill: screenPlayItemImage @@ -139,17 +141,18 @@ Item { font.weight: Font.Thin opacity: 0 } + } CheckBox { id: checkBox + onCheckStateChanged: { - if (checkState == Qt.Checked) { - isSelected = true - } else { - isSelected = false - } - itemClicked(screenId, type, isSelected) + if (checkState == Qt.Checked) + isSelected = true; + else + isSelected = false; + itemClicked(screenId, type, isSelected); } anchors { @@ -157,7 +160,9 @@ Item { right: parent.right margins: 10 } + } + } states: [ @@ -169,10 +174,12 @@ Item { y: 0 opacity: 1 } + PropertyChanges { target: icnType - opacity: .5 + opacity: 0.5 } + }, State { name: "invalid" @@ -181,6 +188,7 @@ Item { target: checkBox enabled: false } + PropertyChanges { target: txtInvalidError opacity: 1 @@ -192,18 +200,13 @@ Item { Transition { from: "*" to: "invalid" + PropertyAnimation { property: opacity target: txtInvalidError duration: 250 } + } ] } - -/*##^## -Designer { - D{i:0;formeditorZoom:0.6600000262260437;height:250;width:600} -} -##^##*/ - diff --git a/ScreenPlay/qml/Workshop/upload/UploadProjectItem.qml b/ScreenPlay/qml/Workshop/upload/UploadProjectItem.qml index 74c3d0b5..cdfb53f3 100644 --- a/ScreenPlay/qml/Workshop/upload/UploadProjectItem.qml +++ b/ScreenPlay/qml/Workshop/upload/UploadProjectItem.qml @@ -1,392 +1,392 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 - import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.12 - import ScreenPlay.Workshop.SteamEnums 1.0 import QtQuick.Layouts 1.12 - import QtQuick.Controls.Material.impl 2.12 Page { + // Everyting that is not OK is a fail. See steam_qt_enums_generated.h + id: root + + property string previewImagePath + property real progress: 0.5 + property string name: "Headline" + property var steamStatus + width: 800 height: 240 anchors.centerIn: parent + padding: 20 + onPreviewImagePathChanged: img.source = Qt.resolvedUrl("file:///" + previewImagePath) + onSteamStatusChanged: { + let errorText; + switch (steamStatus) { + case SteamEnums.K_EResultNone: + root.contentItem.state = "uploadComplete"; + return ; + case SteamEnums.K_EResultOK: + root.contentItem.state = "uploadComplete"; + return ; + case SteamEnums.K_EResultFail: + errorText = qsTr("Fail"); + break; + case SteamEnums.K_EResultNoConnection: + errorText = qsTr("No Connection"); + break; + case SteamEnums.K_EResultInvalidPassword: + errorText = qsTr("Invalid Password"); + break; + case SteamEnums.K_EResultLoggedInElsewhere: + errorText = qsTr("Logged In Elsewhere"); + break; + case SteamEnums.K_EResultInvalidProtocolVer: + errorText = qsTr("Invalid Protocol Version"); + break; + case SteamEnums.K_EResultInvalidParam: + errorText = qsTr("Invalid Param"); + break; + case SteamEnums.K_EResultFileNotFound: + errorText = qsTr("File Not Found"); + break; + case SteamEnums.K_EResultBusy: + errorText = qsTr("Busy"); + break; + case SteamEnums.K_EResultInvalidState: + errorText = qsTr("Invalid State"); + break; + case SteamEnums.K_EResultInvalidName: + errorText = qsTr("Invalid Name"); + break; + case SteamEnums.K_EResultInvalidEmail: + errorText = qsTr("Invalid Email"); + break; + case SteamEnums.K_EResultDuplicateName: + errorText = qsTr("Duplicate Name"); + break; + case SteamEnums.K_EResultAccessDenied: + errorText = qsTr("Access Denied"); + break; + case SteamEnums.K_EResultTimeout: + errorText = qsTr("Timeout"); + break; + case SteamEnums.K_EResultBanned: + errorText = qsTr("Banned"); + break; + case SteamEnums.K_EResultAccountNotFound: + errorText = qsTr("Account Not Found"); + break; + case SteamEnums.K_EResultInvalidSteamID: + errorText = qsTr("Invalid SteamID"); + break; + case SteamEnums.K_EResultServiceUnavailable: + errorText = qsTr("Service Unavailable"); + break; + case SteamEnums.K_EResultNotLoggedOn: + errorText = qsTr("Not Logged On"); + break; + case SteamEnums.K_EResultPending: + errorText = qsTr("Pending"); + break; + case SteamEnums.K_EResultEncryptionFailure: + errorText = qsTr("Encryption Failure"); + break; + case SteamEnums.K_EResultInsufficientPrivilege: + errorText = qsTr("Insufficient Privilege"); + break; + case SteamEnums.K_EResultLimitExceeded: + errorText = qsTr("Limit Exceeded"); + break; + case SteamEnums.K_EResultRevoked: + errorText = qsTr("Revoked"); + break; + case SteamEnums.K_EResultExpired: + errorText = qsTr("Expired"); + break; + case SteamEnums.K_EResultAlreadyRedeemed: + errorText = qsTr("Already Redeemed"); + break; + case SteamEnums.K_EResultDuplicateRequest: + errorText = qsTr("Duplicate Request"); + break; + case SteamEnums.K_EResultAlreadyOwned: + errorText = qsTr("Already Owned"); + break; + case SteamEnums.K_EResultIPNotFound: + errorText = qsTr("IP Not Found"); + break; + case SteamEnums.K_EResultPersistFailed: + errorText = qsTr("Persist Failed"); + break; + case SteamEnums.K_EResultLockingFailed: + errorText = qsTr("Locking Failed"); + break; + case SteamEnums.K_EResultLogonSessionReplaced: + errorText = qsTr("Logon Session Replaced"); + break; + case SteamEnums.K_EResultConnectFailed: + errorText = qsTr("Connect Failed"); + break; + case SteamEnums.K_EResultHandshakeFailed: + errorText = qsTr("Handshake Failed"); + break; + case SteamEnums.K_EResultIOFailure: + errorText = qsTr("IO Failure"); + break; + case SteamEnums.K_EResultRemoteDisconnect: + errorText = qsTr("Remote Disconnect"); + break; + case SteamEnums.K_EResultShoppingCartNotFound: + errorText = qsTr("Shopping Cart Not Found"); + break; + case SteamEnums.K_EResultBlocked: + errorText = qsTr("Blocked"); + break; + case SteamEnums.K_EResultIgnored: + errorText = qsTr("Ignored"); + break; + case SteamEnums.K_EResultNoMatch: + errorText = qsTr("No Match"); + break; + case SteamEnums.K_EResultAccountDisabled: + errorText = qsTr("Account Disabled"); + break; + case SteamEnums.K_EResultServiceReadOnly: + errorText = qsTr("Service ReadOnly"); + break; + case SteamEnums.K_EResultAccountNotFeatured: + errorText = qsTr("Account Not Featured"); + break; + case SteamEnums.K_EResultAdministratorOK: + errorText = qsTr("Administrator OK"); + break; + case SteamEnums.K_EResultContentVersion: + errorText = qsTr("Content Version"); + break; + case SteamEnums.K_EResultTryAnotherCM: + errorText = qsTr("Try Another CM"); + break; + case SteamEnums.K_EResultPasswordRequiredToKickSession: + errorText = qsTr("Password Required T oKick Session"); + break; + case SteamEnums.K_EResultAlreadyLoggedInElsewhere: + errorText = qsTr("Already Logged In Elsewhere"); + break; + case SteamEnums.K_EResultSuspended: + errorText = qsTr("Suspended"); + break; + case SteamEnums.K_EResultCancelled: + errorText = qsTr("Cancelled"); + break; + case SteamEnums.K_EResultDataCorruption: + errorText = qsTr("Data Corruption"); + break; + case SteamEnums.K_EResultDiskFull: + errorText = qsTr("Disk Full"); + break; + case SteamEnums.K_EResultRemoteCallFailed: + errorText = qsTr("Remote Call Failed"); + break; + case SteamEnums.K_EResultPasswordUnset: + errorText = qsTr("Password Unset"); + break; + case SteamEnums.K_EResultExternalAccountUnlinked: + errorText = qsTr("External Account Unlinked"); + break; + case SteamEnums.K_EResultPSNTicketInvalid: + errorText = qsTr("PSN Ticket Invalid"); + break; + case SteamEnums.K_EResultExternalAccountAlreadyLinked: + errorText = qsTr("External Account Already Linked"); + break; + case SteamEnums.K_EResultRemoteFileConflict: + errorText = qsTr("Remote File Conflict"); + break; + case SteamEnums.K_EResultIllegalPassword: + errorText = qsTr("Illegal Password"); + break; + case SteamEnums.K_EResultSameAsPreviousValue: + errorText = qsTr("Same As Previous Value"); + break; + case SteamEnums.K_EResultAccountLogonDenied: + errorText = qsTr("Account Logon Denied"); + break; + case SteamEnums.K_EResultCannotUseOldPassword: + errorText = qsTr("Cannot Use Old Password"); + break; + case SteamEnums.K_EResultInvalidLoginAuthCode: + errorText = qsTr("Invalid Login AuthCode"); + break; + case SteamEnums.K_EResultAccountLogonDeniedNoMail: + errorText = qsTr("Account Logon Denied No Mail"); + break; + case SteamEnums.K_EResultHardwareNotCapableOfIPT: + errorText = qsTr("Hardware Not Capable Of IPT"); + break; + case SteamEnums.K_EResultIPTInitError: + errorText = qsTr("IPT Init Error"); + break; + case SteamEnums.K_EResultParentalControlRestricted: + errorText = qsTr("Parental Control Restricted"); + break; + case SteamEnums.K_EResultFacebookQueryError: + errorText = qsTr("Facebook Query Error"); + break; + case SteamEnums.K_EResultExpiredLoginAuthCode: + errorText = qsTr("Expired Login Auth Code"); + break; + case SteamEnums.K_EResultIPLoginRestrictionFailed: + errorText = qsTr("IP Login Restriction Failed"); + break; + case SteamEnums.K_EResultAccountLockedDown: + errorText = qsTr("Account Locked Down"); + break; + case SteamEnums.K_EResultAccountLogonDeniedVerifiedEmailRequired: + errorText = qsTr("Account Logon Denied Verified Email Required"); + break; + case SteamEnums.K_EResultNoMatchingURL: + errorText = qsTr("No MatchingURL"); + break; + case SteamEnums.K_EResultBadResponse: + errorText = qsTr("Bad Response"); + break; + case SteamEnums.K_EResultRequirePasswordReEntry: + errorText = qsTr("Require Password ReEntry"); + break; + case SteamEnums.K_EResultValueOutOfRange: + errorText = qsTr("Value Out Of Range"); + break; + case SteamEnums.K_EResultUnexpectedError: + errorText = qsTr("Unexpecte Error"); + break; + case SteamEnums.K_EResultDisabled: + errorText = qsTr("Disabled"); + break; + case SteamEnums.K_EResultInvalidCEGSubmission: + errorText = qsTr("Invalid CEG Submission"); + break; + case SteamEnums.K_EResultRestrictedDevice: + errorText = qsTr("Restricted Device"); + break; + case SteamEnums.K_EResultRegionLocked: + errorText = qsTr("Region Locked"); + break; + case SteamEnums.K_EResultRateLimitExceeded: + errorText = qsTr("Rate Limit Exceeded"); + break; + case SteamEnums.K_EResultAccountLoginDeniedNeedTwoFactor: + errorText = qsTr("Account Login Denied Need Two Factor"); + break; + case SteamEnums.K_EResultItemDeleted: + errorText = qsTr("Item Deleted"); + break; + case SteamEnums.K_EResultAccountLoginDeniedThrottle: + errorText = qsTr("Account Login Denied Throttle"); + break; + case SteamEnums.K_EResultTwoFactorCodeMismatch: + errorText = qsTr("Two Factor Code Mismatch"); + break; + case SteamEnums.K_EResultTwoFactorActivationCodeMismatch: + errorText = qsTr("Two Factor Activation Code Mismatch"); + break; + case SteamEnums.K_EResultAccountAssociatedToMultiplePartners: + errorText = qsTr("Account Associated To Multiple Partners"); + break; + case SteamEnums.K_EResultNotModified: + errorText = qsTr("Not Modified"); + break; + case SteamEnums.K_EResultNoMobileDevice: + errorText = qsTr("No Mobile Device"); + break; + case SteamEnums.K_EResultTimeNotSynced: + errorText = qsTr("Time Not Synced"); + break; + case SteamEnums.K_EResultSmsCodeFailed: + errorText = qsTr("Sms Code Failed"); + break; + case SteamEnums.K_EResultAccountLimitExceeded: + errorText = qsTr("Account Limit Exceeded"); + break; + case SteamEnums.K_EResultAccountActivityLimitExceeded: + errorText = qsTr("Account Activity Limit Exceeded"); + break; + case SteamEnums.K_EResultPhoneActivityLimitExceeded: + errorText = qsTr("Phone Activity Limit Exceeded"); + break; + case SteamEnums.K_EResultRefundToWallet: + errorText = qsTr("Refund To Wallet"); + break; + case SteamEnums.K_EResultEmailSendFailure: + errorText = qsTr("Email Send Failure"); + break; + case SteamEnums.K_EResultNotSettled: + errorText = qsTr("Not Settled"); + break; + case SteamEnums.K_EResultNeedCaptcha: + errorText = qsTr("Need Captcha"); + break; + case SteamEnums.K_EResultGSLTDenied: + errorText = qsTr("GSLT Denied"); + break; + case SteamEnums.K_EResultGSOwnerDenied: + errorText = qsTr("GS Owner Denied"); + break; + case SteamEnums.K_EResultInvalidItemType: + errorText = qsTr("Invalid Item Type"); + break; + case SteamEnums.K_EResultIPBanned: + errorText = qsTr("IP Banned"); + break; + case SteamEnums.K_EResultGSLTExpired: + errorText = qsTr("GSLT Expired"); + break; + case SteamEnums.K_EResultInsufficientFunds: + errorText = qsTr("Insufficient Funds"); + break; + case SteamEnums.K_EResultTooManyPending: + errorText = qsTr("Too Many Pending"); + break; + case SteamEnums.K_EResultNoSiteLicensesFound: + errorText = qsTr("No Site Licenses Found"); + break; + case SteamEnums.K_EResultWGNetworkSendExceeded: + errorText = qsTr("WG Network Send Exceeded"); + break; + case SteamEnums.K_EResultAccountNotFriends: + errorText = qsTr("Account Not Friends"); + break; + case SteamEnums.K_EResultLimitedUserAccount: + errorText = qsTr("Limited User Account"); + break; + case SteamEnums.K_EResultCantRemoveItem: + errorText = qsTr("Cant Remove Item"); + break; + case SteamEnums.K_EResultAccountDeleted: + errorText = qsTr("Account Deleted"); + break; + case SteamEnums.K_EResultExistingUserCancelledLicense: + errorText = qsTr("Existing User Cancelled License"); + break; + case SteamEnums.K_EResultCommunityCooldown: + errorText = qsTr("Community Cooldown"); + break; + } + root.contentItem.txtStatus.statusText = errorText; + root.contentItem.state = "error"; + } + background: Rectangle { radius: 4 anchors.fill: parent layer.enabled: true + color: Material.theme === Material.Light ? "white" : Material.background + layer.effect: ElevationEffect { elevation: 6 } - color: Material.theme === Material.Light ? "white" : Material.background - } - padding: 20 - - property string previewImagePath - onPreviewImagePathChanged: img.source = Qt.resolvedUrl( - "file:///" + previewImagePath) - property real progress: 0.5 - property string name: "Headline" - property var steamStatus - onSteamStatusChanged: { - let errorText - switch (steamStatus) { - // Everyting that is not OK is a fail. See steam_qt_enums_generated.h - case SteamEnums.K_EResultNone: - root.contentItem.state = "uploadComplete" - return - case SteamEnums.K_EResultOK: - root.contentItem.state = "uploadComplete" - return - case SteamEnums.K_EResultFail: - errorText = qsTr("Fail") - break - case SteamEnums.K_EResultNoConnection: - errorText = qsTr("No Connection") - break - case SteamEnums.K_EResultInvalidPassword: - errorText = qsTr("Invalid Password") - break - case SteamEnums.K_EResultLoggedInElsewhere: - errorText = qsTr("Logged In Elsewhere") - break - case SteamEnums.K_EResultInvalidProtocolVer: - errorText = qsTr("Invalid Protocol Version") - break - case SteamEnums.K_EResultInvalidParam: - errorText = qsTr("Invalid Param") - break - case SteamEnums.K_EResultFileNotFound: - errorText = qsTr("File Not Found") - break - case SteamEnums.K_EResultBusy: - errorText = qsTr("Busy") - break - case SteamEnums.K_EResultInvalidState: - errorText = qsTr("Invalid State") - break - case SteamEnums.K_EResultInvalidName: - errorText = qsTr("Invalid Name") - break - case SteamEnums.K_EResultInvalidEmail: - errorText = qsTr("Invalid Email") - break - case SteamEnums.K_EResultDuplicateName: - errorText = qsTr("Duplicate Name") - break - case SteamEnums.K_EResultAccessDenied: - errorText = qsTr("Access Denied") - break - case SteamEnums.K_EResultTimeout: - errorText = qsTr("Timeout") - break - case SteamEnums.K_EResultBanned: - errorText = qsTr("Banned") - break - case SteamEnums.K_EResultAccountNotFound: - errorText = qsTr("Account Not Found") - break - case SteamEnums.K_EResultInvalidSteamID: - errorText = qsTr("Invalid SteamID") - break - case SteamEnums.K_EResultServiceUnavailable: - errorText = qsTr("Service Unavailable") - break - case SteamEnums.K_EResultNotLoggedOn: - errorText = qsTr("Not Logged On") - break - case SteamEnums.K_EResultPending: - errorText = qsTr("Pending") - break - case SteamEnums.K_EResultEncryptionFailure: - errorText = qsTr("Encryption Failure") - break - case SteamEnums.K_EResultInsufficientPrivilege: - errorText = qsTr("Insufficient Privilege") - break - case SteamEnums.K_EResultLimitExceeded: - errorText = qsTr("Limit Exceeded") - break - case SteamEnums.K_EResultRevoked: - errorText = qsTr("Revoked") - break - case SteamEnums.K_EResultExpired: - errorText = qsTr("Expired") - break - case SteamEnums.K_EResultAlreadyRedeemed: - errorText = qsTr("Already Redeemed") - break - case SteamEnums.K_EResultDuplicateRequest: - errorText = qsTr("Duplicate Request") - break - case SteamEnums.K_EResultAlreadyOwned: - errorText = qsTr("Already Owned") - break - case SteamEnums.K_EResultIPNotFound: - errorText = qsTr("IP Not Found") - break - case SteamEnums.K_EResultPersistFailed: - errorText = qsTr("Persist Failed") - break - case SteamEnums.K_EResultLockingFailed: - errorText = qsTr("Locking Failed") - break - case SteamEnums.K_EResultLogonSessionReplaced: - errorText = qsTr("Logon Session Replaced") - break - case SteamEnums.K_EResultConnectFailed: - errorText = qsTr("Connect Failed") - break - case SteamEnums.K_EResultHandshakeFailed: - errorText = qsTr("Handshake Failed") - break - case SteamEnums.K_EResultIOFailure: - errorText = qsTr("IO Failure") - break - case SteamEnums.K_EResultRemoteDisconnect: - errorText = qsTr("Remote Disconnect") - break - case SteamEnums.K_EResultShoppingCartNotFound: - errorText = qsTr("Shopping Cart Not Found") - break - case SteamEnums.K_EResultBlocked: - errorText = qsTr("Blocked") - break - case SteamEnums.K_EResultIgnored: - errorText = qsTr("Ignored") - break - case SteamEnums.K_EResultNoMatch: - errorText = qsTr("No Match") - break - case SteamEnums.K_EResultAccountDisabled: - errorText = qsTr("Account Disabled") - break - case SteamEnums.K_EResultServiceReadOnly: - errorText = qsTr("Service ReadOnly") - break - case SteamEnums.K_EResultAccountNotFeatured: - errorText = qsTr("Account Not Featured") - break - case SteamEnums.K_EResultAdministratorOK: - errorText = qsTr("Administrator OK") - break - case SteamEnums.K_EResultContentVersion: - errorText = qsTr("Content Version") - break - case SteamEnums.K_EResultTryAnotherCM: - errorText = qsTr("Try Another CM") - break - case SteamEnums.K_EResultPasswordRequiredToKickSession: - errorText = qsTr("Password Required T oKick Session") - break - case SteamEnums.K_EResultAlreadyLoggedInElsewhere: - errorText = qsTr("Already Logged In Elsewhere") - break - case SteamEnums.K_EResultSuspended: - errorText = qsTr("Suspended") - break - case SteamEnums.K_EResultCancelled: - errorText = qsTr("Cancelled") - break - case SteamEnums.K_EResultDataCorruption: - errorText = qsTr("Data Corruption") - break - case SteamEnums.K_EResultDiskFull: - errorText = qsTr("Disk Full") - break - case SteamEnums.K_EResultRemoteCallFailed: - errorText = qsTr("Remote Call Failed") - break - case SteamEnums.K_EResultPasswordUnset: - errorText = qsTr("Password Unset") - break - case SteamEnums.K_EResultExternalAccountUnlinked: - errorText = qsTr("External Account Unlinked") - break - case SteamEnums.K_EResultPSNTicketInvalid: - errorText = qsTr("PSN Ticket Invalid") - break - case SteamEnums.K_EResultExternalAccountAlreadyLinked: - errorText = qsTr("External Account Already Linked") - break - case SteamEnums.K_EResultRemoteFileConflict: - errorText = qsTr("Remote File Conflict") - break - case SteamEnums.K_EResultIllegalPassword: - errorText = qsTr("Illegal Password") - break - case SteamEnums.K_EResultSameAsPreviousValue: - errorText = qsTr("Same As Previous Value") - break - case SteamEnums.K_EResultAccountLogonDenied: - errorText = qsTr("Account Logon Denied") - break - case SteamEnums.K_EResultCannotUseOldPassword: - errorText = qsTr("Cannot Use Old Password") - break - case SteamEnums.K_EResultInvalidLoginAuthCode: - errorText = qsTr("Invalid Login AuthCode") - break - case SteamEnums.K_EResultAccountLogonDeniedNoMail: - errorText = qsTr("Account Logon Denied No Mail") - break - case SteamEnums.K_EResultHardwareNotCapableOfIPT: - errorText = qsTr("Hardware Not Capable Of IPT") - break - case SteamEnums.K_EResultIPTInitError: - errorText = qsTr("IPT Init Error") - break - case SteamEnums.K_EResultParentalControlRestricted: - errorText = qsTr("Parental Control Restricted") - break - case SteamEnums.K_EResultFacebookQueryError: - errorText = qsTr("Facebook Query Error") - break - case SteamEnums.K_EResultExpiredLoginAuthCode: - errorText = qsTr("Expired Login Auth Code") - break - case SteamEnums.K_EResultIPLoginRestrictionFailed: - errorText = qsTr("IP Login Restriction Failed") - break - case SteamEnums.K_EResultAccountLockedDown: - errorText = qsTr("Account Locked Down") - break - case SteamEnums.K_EResultAccountLogonDeniedVerifiedEmailRequired: - errorText = qsTr("Account Logon Denied Verified Email Required") - break - case SteamEnums.K_EResultNoMatchingURL: - errorText = qsTr("No MatchingURL") - break - case SteamEnums.K_EResultBadResponse: - errorText = qsTr("Bad Response") - break - case SteamEnums.K_EResultRequirePasswordReEntry: - errorText = qsTr("Require Password ReEntry") - break - case SteamEnums.K_EResultValueOutOfRange: - errorText = qsTr("Value Out Of Range") - break - case SteamEnums.K_EResultUnexpectedError: - errorText = qsTr("Unexpecte Error") - break - case SteamEnums.K_EResultDisabled: - errorText = qsTr("Disabled") - break - case SteamEnums.K_EResultInvalidCEGSubmission: - errorText = qsTr("Invalid CEG Submission") - break - case SteamEnums.K_EResultRestrictedDevice: - errorText = qsTr("Restricted Device") - break - case SteamEnums.K_EResultRegionLocked: - errorText = qsTr("Region Locked") - break - case SteamEnums.K_EResultRateLimitExceeded: - errorText = qsTr("Rate Limit Exceeded") - break - case SteamEnums.K_EResultAccountLoginDeniedNeedTwoFactor: - errorText = qsTr("Account Login Denied Need Two Factor") - break - case SteamEnums.K_EResultItemDeleted: - errorText = qsTr("Item Deleted") - break - case SteamEnums.K_EResultAccountLoginDeniedThrottle: - errorText = qsTr("Account Login Denied Throttle") - break - case SteamEnums.K_EResultTwoFactorCodeMismatch: - errorText = qsTr("Two Factor Code Mismatch") - break - case SteamEnums.K_EResultTwoFactorActivationCodeMismatch: - errorText = qsTr("Two Factor Activation Code Mismatch") - break - case SteamEnums.K_EResultAccountAssociatedToMultiplePartners: - errorText = qsTr("Account Associated To Multiple Partners") - break - case SteamEnums.K_EResultNotModified: - errorText = qsTr("Not Modified") - break - case SteamEnums.K_EResultNoMobileDevice: - errorText = qsTr("No Mobile Device") - break - case SteamEnums.K_EResultTimeNotSynced: - errorText = qsTr("Time Not Synced") - break - case SteamEnums.K_EResultSmsCodeFailed: - errorText = qsTr("Sms Code Failed") - break - case SteamEnums.K_EResultAccountLimitExceeded: - errorText = qsTr("Account Limit Exceeded") - break - case SteamEnums.K_EResultAccountActivityLimitExceeded: - errorText = qsTr("Account Activity Limit Exceeded") - break - case SteamEnums.K_EResultPhoneActivityLimitExceeded: - errorText = qsTr("Phone Activity Limit Exceeded") - break - case SteamEnums.K_EResultRefundToWallet: - errorText = qsTr("Refund To Wallet") - break - case SteamEnums.K_EResultEmailSendFailure: - errorText = qsTr("Email Send Failure") - break - case SteamEnums.K_EResultNotSettled: - errorText = qsTr("Not Settled") - break - case SteamEnums.K_EResultNeedCaptcha: - errorText = qsTr("Need Captcha") - break - case SteamEnums.K_EResultGSLTDenied: - errorText = qsTr("GSLT Denied") - break - case SteamEnums.K_EResultGSOwnerDenied: - errorText = qsTr("GS Owner Denied") - break - case SteamEnums.K_EResultInvalidItemType: - errorText = qsTr("Invalid Item Type") - break - case SteamEnums.K_EResultIPBanned: - errorText = qsTr("IP Banned") - break - case SteamEnums.K_EResultGSLTExpired: - errorText = qsTr("GSLT Expired") - break - case SteamEnums.K_EResultInsufficientFunds: - errorText = qsTr("Insufficient Funds") - break - case SteamEnums.K_EResultTooManyPending: - errorText = qsTr("Too Many Pending") - break - case SteamEnums.K_EResultNoSiteLicensesFound: - errorText = qsTr("No Site Licenses Found") - break - case SteamEnums.K_EResultWGNetworkSendExceeded: - errorText = qsTr("WG Network Send Exceeded") - break - case SteamEnums.K_EResultAccountNotFriends: - errorText = qsTr("Account Not Friends") - break - case SteamEnums.K_EResultLimitedUserAccount: - errorText = qsTr("Limited User Account") - break - case SteamEnums.K_EResultCantRemoveItem: - errorText = qsTr("Cant Remove Item") - break - case SteamEnums.K_EResultAccountDeleted: - errorText = qsTr("Account Deleted") - break - case SteamEnums.K_EResultExistingUserCancelledLicense: - errorText = qsTr("Existing User Cancelled License") - break - case SteamEnums.K_EResultCommunityCooldown: - errorText = qsTr("Community Cooldown") - break - } - root.contentItem.txtStatus.statusText = errorText - root.contentItem.state = "error" } contentItem: Item { @@ -395,45 +395,59 @@ Page { Image { id: img + width: 300 + anchors { top: parent.top left: parent.left bottom: parent.bottom } + LinearGradient { id: gradient + height: parent.height cached: true opacity: 0 anchors.fill: parent start: Qt.point(0, height) end: Qt.point(0, 0) + gradient: Gradient { GradientStop { id: gradientStop0 - position: 0.0 + + position: 0 color: "#DD000000" } + GradientStop { id: gradientStop1 - position: 1.0 + + position: 1 color: "#00000000" } + } + } + } ColumnLayout { spacing: 10 + anchors { top: parent.top right: parent.right left: img.right margins: 20 } + Text { id: name + text: root.name verticalAlignment: Text.AlignVCenter wrapMode: Text.WrapAtWordBoundaryOrAnywhere @@ -445,7 +459,9 @@ Page { Text { id: txtStatus + property string statusText: "Loading..." + text: qsTr("Status:") + " " + statusText verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter @@ -459,16 +475,16 @@ Page { Layout.preferredHeight: 60 Layout.fillWidth: true } + ColumnLayout { spacing: 10 Layout.fillWidth: true + Text { - text: qsTr("Upload Progress: ") + " " + Math.ceil( - root.progress) + "%" + text: qsTr("Upload Progress: ") + " " + Math.ceil(root.progress) + "%" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter wrapMode: Text.WrapAtWordBoundaryOrAnywhere - color: Material.primaryTextColor font.pointSize: 14 height: 50 @@ -476,52 +492,66 @@ Page { ProgressBar { id: progressBar + Layout.fillWidth: true value: root.progress to: 100 } + } + } states: [ - State { name: "uploading" - PropertyChanges {} + + PropertyChanges { + } + }, State { name: "uploadComplete" + PropertyChanges { target: gradient - opacity: .7 + opacity: 0.7 } + PropertyChanges { target: gradient - opacity: .7 + opacity: 0.7 } + PropertyChanges { target: gradientStop0 color: Material.color(Material.Lime) } + PropertyChanges { target: gradientStop1 color: Material.color(Material.LightGreen) } + }, State { name: "error" + PropertyChanges { target: gradient - opacity: .7 + opacity: 0.7 } + PropertyChanges { target: gradientStop0 color: Material.color(Material.Red) } + PropertyChanges { target: gradientStop1 color: Material.color(Material.DeepOrange) } + } ] transitions: [ @@ -533,14 +563,9 @@ Page { targets: [gradient, gradientStop0, gradientStop1] duration: 500 } + } ] } -} -/*##^## -Designer { - D{i:0;height:240;width:800} } -##^##*/ - diff --git a/ScreenPlayShader/ShadertoyShader.qml b/ScreenPlayShader/ShadertoyShader.qml index d0106b40..819e5c5c 100644 --- a/ScreenPlayShader/ShadertoyShader.qml +++ b/ScreenPlayShader/ShadertoyShader.qml @@ -6,96 +6,31 @@ ShaderEffect { // based on shadertoy default variables readonly property vector3d iResolution: defaultResolution - readonly property vector3d defaultResolution: Qt.vector3d( - root.width, root.height, - root.width / root.height) + readonly property vector3d defaultResolution: Qt.vector3d(root.width, root.height, root.width / root.height) property real iTime: 0 property real iTimeDelta: 100 property int iFrame: 10 property real iFrameRate property vector4d iMouse - //only Image or ShaderEffectSource property var iChannel0: ich0 property var iChannel1: ich1 property var iChannel2: ich2 property var iChannel3: ich3 - property var iChannelTime: [0, 1, 2, 3] - property var iChannelResolution: [calcResolution(iChannel0), calcResolution( - iChannel1), calcResolution(iChannel2), calcResolution(iChannel3)] + property var iChannelResolution: [calcResolution(iChannel0), calcResolution(iChannel1), calcResolution(iChannel2), calcResolution(iChannel3)] property vector4d iDate property real iSampleRate: 44100 - property bool hoverEnabled: false property bool running: true - - function restart() { - root.iTime = 0 - running = true - timer1.restart() - } - - function calcResolution(channel) { - if (channel) { - return Qt.vector3d(channel.width, channel.height, - channel.width / channel.height) - } else { - return defaultResolution - } - } - - Image { - id: ich0 - visible: false - } - Image { - id: ich1 - visible: false - } - Image { - id: ich2 - visible: false - } - Image { - id: ich3 - visible: false - } - - Timer { - id: timer1 - running: root.running - triggeredOnStart: true - interval: 16 - repeat: true - onTriggered: { - root.iTime += 0.016 - } - } - - Timer { - running: root.running - interval: 1000 - property date currentDate: new Date() - onTriggered: { - currentDate = new Date() - root.iDate.x = currentDate.getFullYear() - root.iDate.y = currentDate.getMonth() - root.iDate.z = currentDate.getDay() - root.iDate.w = currentDate.getSeconds() - } - } - readonly property string gles2Ver: " #define texture texture2D precision mediump float;" - readonly property string gles3Ver: "#version 300 es #define varying in #define gl_FragColor fragColor precision mediump float; out vec4 fragColor;" - readonly property string gl3Ver: " #version 150 #define varying in @@ -104,7 +39,6 @@ out vec4 fragColor;" #define mediump #define highp out vec4 fragColor;" - readonly property string gl3Ver_igpu: " #version 130 #define varying in @@ -113,26 +47,10 @@ out vec4 fragColor;" #define mediump #define highp out vec4 fragColor;" - readonly property string gl2Ver: " #version 110 #define texture texture2D" - - property string versionString: (GraphicsInfo.majorVersion === 3 - || GraphicsInfo.majorVersion === 4) ? gl3Ver : gl2Ver - - vertexShader: " -uniform mat4 qt_Matrix; -attribute vec4 qt_Vertex; -attribute vec2 qt_MultiTexCoord0; -varying vec2 qt_TexCoord0; -varying vec4 vertex; -void main() { -vertex = qt_Vertex; -gl_Position = qt_Matrix * vertex; -qt_TexCoord0 = qt_MultiTexCoord0; -}" - + property string versionString: (GraphicsInfo.majorVersion === 3 || GraphicsInfo.majorVersion === 4) ? gl3Ver : gl2Ver readonly property string forwardString: versionString + " varying vec2 qt_TexCoord0; varying vec4 vertex; @@ -151,14 +69,88 @@ uniform sampler2D iChannel0; uniform sampler2D iChannel1; uniform sampler2D iChannel2; uniform sampler2D iChannel3;" - readonly property string startCode: " void main(void) { mainImage(gl_FragColor, vec2(vertex.x, iResolution.y - vertex.y)); }" - property bool runShader: true property string pixelShader + + function restart() { + root.iTime = 0; + running = true; + timer1.restart(); + } + + function calcResolution(channel) { + if (channel) + return Qt.vector3d(channel.width, channel.height, channel.width / channel.height); + else + return defaultResolution; + } + + vertexShader: " +uniform mat4 qt_Matrix; +attribute vec4 qt_Vertex; +attribute vec2 qt_MultiTexCoord0; +varying vec2 qt_TexCoord0; +varying vec4 vertex; +void main() { +vertex = qt_Vertex; +gl_Position = qt_Matrix * vertex; +qt_TexCoord0 = qt_MultiTexCoord0; +}" onPixelShaderChanged: root.fragmentShader = forwardString + pixelShader + startCode + + Image { + id: ich0 + + visible: false + } + + Image { + id: ich1 + + visible: false + } + + Image { + id: ich2 + + visible: false + } + + Image { + id: ich3 + + visible: false + } + + Timer { + id: timer1 + + running: root.running + triggeredOnStart: true + interval: 16 + repeat: true + onTriggered: { + root.iTime += 0.016; + } + } + + Timer { + property date currentDate: new Date() + + running: root.running + interval: 1000 + onTriggered: { + currentDate = new Date(); + root.iDate.x = currentDate.getFullYear(); + root.iDate.y = currentDate.getMonth(); + root.iDate.z = currentDate.getDay(); + root.iDate.w = currentDate.getSeconds(); + } + } + } diff --git a/ScreenPlayWallpaper/GifWallpaper.qml b/ScreenPlayWallpaper/GifWallpaper.qml index 21081175..a7d1bb60 100644 --- a/ScreenPlayWallpaper/GifWallpaper.qml +++ b/ScreenPlayWallpaper/GifWallpaper.qml @@ -1,5 +1,4 @@ import QtQuick 2.0 AnimatedImage { - } diff --git a/ScreenPlayWallpaper/Test.qml b/ScreenPlayWallpaper/Test.qml index b58a8670..c801782e 100644 --- a/ScreenPlayWallpaper/Test.qml +++ b/ScreenPlayWallpaper/Test.qml @@ -7,13 +7,6 @@ import ScreenPlayWallpaper 1.0 Rectangle { id: root - anchors.fill: parent - color: Material.color(Material.Grey, Material.Shade800) - border.width: 10 - border.color: "orange" - - signal requestFadeIn - Component.onCompleted: root.requestFadeIn() property int attStrength: 800000 //Emitter @@ -23,38 +16,49 @@ Rectangle { property int size: 4 property int endSize: 8 property int sizeVariation: 4 - //Image - property real imgOpacity: .75 + property real imgOpacity: 0.75 + + signal requestFadeIn() + + anchors.fill: parent + color: Material.color(Material.Grey, Material.Shade800) + border.width: 10 + border.color: "orange" + Component.onCompleted: root.requestFadeIn() MouseArea { + // setPosition() + id: ma + + function setPosition() { + attractor.pointX = mouseX - 25; + attractor.pointY = mouseY - 25; + mouseDot.x = mouseX - mouseDot.center; + mouseDot.y = mouseY - mouseDot.center; + } + anchors.fill: parent preventStealing: true propagateComposedEvents: true hoverEnabled: true Component.onCompleted: { - attractor.pointX = parent.width * .5 - attractor.pointY = parent.height * .5 + attractor.pointX = parent.width * 0.5; + attractor.pointY = parent.height * 0.5; } - onPositionChanged: { - setPosition() + setPosition(); } onClicked: { - - // setPosition() - } - function setPosition() { - attractor.pointX = mouseX - 25 - attractor.pointY = mouseY - 25 - mouseDot.x = mouseX - mouseDot.center - mouseDot.y = mouseY - mouseDot.center } } + Rectangle { id: mouseDot - property int center: mouseDot.width * .5 + + property int center: mouseDot.width * 0.5 + width: 10 height: width radius: width @@ -64,6 +68,7 @@ Rectangle { Attractor { id: attractor + system: particleSystem affectedParameter: Attractor.Acceleration strength: root.attStrength @@ -76,14 +81,10 @@ Rectangle { Emitter { id: emitter - enabled: root.isEnabled - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - } + enabled: root.isEnabled width: parent.width - height: parent.height * .5 + height: parent.height * 0.5 system: particleSystem emitRate: root.emitRate lifeSpan: root.lifeSpan @@ -91,12 +92,19 @@ Rectangle { size: root.size endSize: root.endSize sizeVariation: root.sizeVariation + + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + } + velocity: AngleDirection { angle: -90 magnitude: 50 magnitudeVariation: 25 angleVariation: 10 } + } ImageParticle { @@ -106,39 +114,50 @@ Rectangle { system: particleSystem opacity: root.imgOpacity } + Text { id: txtMousePos + property int counter: 0 + text: attractor.pointY + " - " + attractor.pointX font.pointSize: 32 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap + color: "white" + anchors { horizontalCenter: parent.horizontalCenter bottom: txtButtonConter.top bottomMargin: 20 } - color: "white" + } Text { id: txtButtonConter + property int counter: 0 + text: txtButtonConter.counter font.pointSize: 32 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap + color: "white" + anchors { horizontalCenter: parent.horizontalCenter bottom: name.top bottomMargin: 20 } - color: "white" + } + Text { id: name + text: qsTr("This is a empty test window. You can change the source in test.qml") font.pointSize: 32 horizontalAlignment: Text.AlignHCenter @@ -150,60 +169,59 @@ Rectangle { } Row { + spacing: 20 + anchors { horizontalCenter: parent.horizontalCenter top: name.bottom topMargin: 20 } - spacing: 20 + Button { highlighted: true - - onClicked: { - focus = false - focus = true - print("Button Clicked!") - txtButtonConter.counter = txtButtonConter.counter - 1 - } text: qsTr("Click me! - 1") + onClicked: { + focus = false; + focus = true; + print("Button Clicked!"); + txtButtonConter.counter = txtButtonConter.counter - 1; + } } + Button { highlighted: true - - onClicked: { - focus = false - focus = true - print("Exit Wallpaper") - Wallpaper.terminate() - } text: qsTr("Exit Wallpaper") + onClicked: { + focus = false; + focus = true; + print("Exit Wallpaper"); + Wallpaper.terminate(); + } } + Button { highlighted: true focusPolicy: Qt.ClickFocus - onClicked: { - - print("Button Clicked!") - txtButtonConter.counter = txtButtonConter.counter + 1 - } text: qsTr("Click me! +1") + onClicked: { + print("Button Clicked!"); + txtButtonConter.counter = txtButtonConter.counter + 1; + } } + } WebView { width: 1000 height: 400 url: "https://screen-play.app" + anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: 50 } + } -} -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} } - ##^##*/ - diff --git a/ScreenPlayWallpaper/Wallpaper.qml b/ScreenPlayWallpaper/Wallpaper.qml index 73ec7939..c3c743a2 100644 --- a/ScreenPlayWallpaper/Wallpaper.qml +++ b/ScreenPlayWallpaper/Wallpaper.qml @@ -8,52 +8,82 @@ import "ShaderWrapper" as ShaderWrapper Rectangle { id: root - anchors.fill: parent - color: { - if (Qt.platform.os !== "windows") { - return "black" - } else { - return Wallpaper.windowsDesktopProperties.color - } - } property bool canFadeByWallpaperFillMode: true + function init() { + switch (Wallpaper.type) { + case InstalledType.VideoWallpaper: + loader.source = "qrc:/WebView.qml"; + break; + case InstalledType.HTMLWallpaper: + loader.setSource("qrc:/WebView.qml", { + "url": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) + }); + break; + case InstalledType.QMLWallpaper: + loader.source = Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute); + fadeIn(); + break; + case InstalledType.WebsiteWallpaper: + loader.setSource("qrc:/WebsiteWallpaper.qml", { + "url": Wallpaper.projectSourceFileAbsolute + }); + fadeIn(); + break; + case InstalledType.GifWallpaper: + loader.setSource("qrc:/GifWallpaper.qml", { + "source": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) + }); + fadeIn(); + break; + } + } + + function fadeIn() { + Wallpaper.setVisible(true); + if (canFadeByWallpaperFillMode && Wallpaper.canFade) + imgCover.state = "hideDefaultBackgroundImage"; + else + imgCover.opacity = 0; + } + + anchors.fill: parent + color: { + if (Qt.platform.os !== "windows") + return "black"; + else + return Wallpaper.windowsDesktopProperties.color; + } Component.onCompleted: { - init() + init(); } Connections { - target: Wallpaper - function onQmlExit() { - if (canFadeByWallpaperFillMode && Wallpaper.canFade) { - imgCover.state = "exit" - } else { - Wallpaper.terminate() - } + if (canFadeByWallpaperFillMode && Wallpaper.canFade) + imgCover.state = "exit"; + else + Wallpaper.terminate(); } function onQmlSceneValueReceived(key, value) { - var obj2 = 'import QtQuick 2.0; Item {Component.onCompleted: loader.item.' - + key + ' = ' + value + '; }' - var newObject = Qt.createQmlObject(obj2.toString(), root, "err") - newObject.destroy(10000) + var obj2 = 'import QtQuick 2.0; Item {Component.onCompleted: loader.item.' + key + ' = ' + value + '; }'; + var newObject = Qt.createQmlObject(obj2.toString(), root, "err"); + newObject.destroy(10000); } // Replace wallpaper with QML Scene function onReloadQML(oldType) { - - loader.sourceComponent = undefined - loader.source = "" - Wallpaper.clearComponentCache() - - loader.source = Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) + loader.sourceComponent = undefined; + loader.source = ""; + Wallpaper.clearComponentCache(); + loader.source = Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute); } // Replace wallpaper with GIF function onReloadGIF(oldType) { - init() + init(); } // This function only gets called here (the same function @@ -63,113 +93,117 @@ Rectangle { // We need to check if the old type // was also Video not get called twice if (oldType === InstalledType.VideoWallpaper) - return + return ; - imgCover.state = "showDefaultBackgroundImage" - loader.source = "qrc:/WebView.qml" + imgCover.state = "showDefaultBackgroundImage"; + loader.source = "qrc:/WebView.qml"; } - } - function init() { - switch (Wallpaper.type) { - case InstalledType.VideoWallpaper: - loader.source = "qrc:/WebView.qml" - break - case InstalledType.HTMLWallpaper: - loader.setSource("qrc:/WebView.qml", { - "url": Qt.resolvedUrl( - Wallpaper.projectSourceFileAbsolute) - }) - break - case InstalledType.QMLWallpaper: - loader.source = Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) - fadeIn() - break - case InstalledType.WebsiteWallpaper: - loader.setSource("qrc:/WebsiteWallpaper.qml", { - "url": Wallpaper.projectSourceFileAbsolute - }) - fadeIn() - break - case InstalledType.GifWallpaper: - loader.setSource("qrc:/GifWallpaper.qml", { - "source": Qt.resolvedUrl( - Wallpaper.projectSourceFileAbsolute) - }) - fadeIn() - break - } - } - - function fadeIn() { - Wallpaper.setVisible(true) - if (canFadeByWallpaperFillMode && Wallpaper.canFade) { - imgCover.state = "hideDefaultBackgroundImage" - } else { - imgCover.opacity = 0 - } + target: Wallpaper } Loader { id: loader + anchors.fill: parent // QML Engine deadlocks in 5.15.2 when a loader cannot load // an item. QApplication::quit(); waits for the destruction forever. asynchronous: true onStatusChanged: { if (loader.status === Loader.Error) { - loader.source = "" - Wallpaper.terminate() + loader.source = ""; + Wallpaper.terminate(); } } + Connections { + function onRequestFadeIn() { + fadeIn(); + } + ignoreUnknownSignals: true target: loader.item - function onRequestFadeIn() { - fadeIn() - } } + } Image { id: imgCover + + state: "showDefaultBackgroundImage" + sourceSize.width: Wallpaper.width + sourceSize.height: Wallpaper.height + source: { + if (Qt.platform.os === "windows") + return Qt.resolvedUrl("file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath); + + } + Component.onCompleted: { + if (Qt.platform.os !== "windows") { + root.canFadeByWallpaperFillMode = false; + return ; + } + switch (Wallpaper.windowsDesktopProperties.wallpaperStyle) { + case 10: + imgCover.fillMode = Image.PreserveAspectCrop; + break; + case 6: + imgCover.fillMode = Image.PreserveAspectFit; + break; + case 2: + break; + case 0: + if (desktopProperties.isTiled) { + // Tiled + imgCover.fillMode = Image.Tile; + } else { + // Center + imgCover.fillMode = Image.PreserveAspectFit; + imgCover.anchors.centerIn = parent; + imgCover.width = sourceSize.width; + imgCover.height = sourceSize.height; + } + break; + case 22: + root.canFadeByWallpaperFillMode = false; + break; + } + } + anchors { top: parent.top topMargin: -3 // To fix the offset from setupWallpaperForOneScreen left: parent.left right: parent.right } - state: "showDefaultBackgroundImage" - sourceSize.width: Wallpaper.width - sourceSize.height: Wallpaper.height - source: { - if (Qt.platform.os === "windows") { - return Qt.resolvedUrl( - "file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath) - } - } states: [ State { name: "showDefaultBackgroundImage" + PropertyChanges { target: imgCover opacity: 1 } + }, State { name: "hideDefaultBackgroundImage" + PropertyChanges { target: imgCover opacity: 0 } + }, State { name: "exit" + PropertyChanges { target: imgCover opacity: 1 } + } ] transitions: [ @@ -182,125 +216,113 @@ Rectangle { PauseAnimation { duration: 100 } + PropertyAnimation { target: imgCover duration: 600 property: "opacity" } + } + }, Transition { from: "hideDefaultBackgroundImage" to: "exit" reversible: true + SequentialAnimation { PropertyAnimation { target: imgCover duration: 600 property: "opacity" } + ScriptAction { script: Wallpaper.terminate() } + } + } ] - - Component.onCompleted: { - - if (Qt.platform.os !== "windows") { - root.canFadeByWallpaperFillMode = false - return - } - - switch (Wallpaper.windowsDesktopProperties.wallpaperStyle) { - case 10: - imgCover.fillMode = Image.PreserveAspectCrop - break - case 6: - imgCover.fillMode = Image.PreserveAspectFit - break - case 2: - break - case 0: - if (desktopProperties.isTiled) { - // Tiled - imgCover.fillMode = Image.Tile - } else { - // Center - imgCover.fillMode = Image.PreserveAspectFit - imgCover.anchors.centerIn = parent - imgCover.width = sourceSize.width - imgCover.height = sourceSize.height - } - break - case 22: - root.canFadeByWallpaperFillMode = false - break - } - } } Pane { id: debug + visible: Wallpaper.debugMode enabled: Wallpaper.debugMode - width: parent.width * .3 - height: parent.height * .3 + width: parent.width * 0.3 + height: parent.height * 0.3 anchors.centerIn: parent - background: Rectangle { - opacity: .5 - } Column { anchors.fill: parent anchors.margins: 20 spacing: 10 + Text { text: "appID " + Wallpaper.appID font.pointSize: 14 } + Text { text: "projectPath " + Wallpaper.projectPath font.pointSize: 14 } + Text { text: "projectSourceFileAbsolute " + Wallpaper.projectSourceFileAbsolute font.pointSize: 14 } + Text { text: "fillMode " + Wallpaper.fillMode font.pointSize: 14 } + Text { text: "sdk.type " + Wallpaper.sdk.type font.pointSize: 14 } + Text { text: "sdk.isConnected " + Wallpaper.sdk.isConnected font.pointSize: 14 } + Text { text: "sdk.appID " + Wallpaper.sdk.appID font.pointSize: 14 } + Text { text: "canFadeByWallpaperFillMode " + canFadeByWallpaperFillMode font.pointSize: 14 } + Text { text: "Wallpaper.canFade " + Wallpaper.canFade font.pointSize: 14 } + Text { - text: "imgCover.source " + Qt.resolvedUrl( - "file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath) + text: "imgCover.source " + Qt.resolvedUrl("file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath) font.pointSize: 14 } + Text { text: "imgCover.status " + imgCover.status font.pointSize: 14 } + } + + background: Rectangle { + opacity: 0.5 + } + } + } diff --git a/ScreenPlayWallpaper/WebView.qml b/ScreenPlayWallpaper/WebView.qml index 6b1ea5e0..cd5dbacd 100644 --- a/ScreenPlayWallpaper/WebView.qml +++ b/ScreenPlayWallpaper/WebView.qml @@ -5,58 +5,58 @@ import ScreenPlayWallpaper 1.0 Item { id: root + property alias url: webView.url - signal requestFadeIn - - Component.onCompleted: { - WebEngine.settings.localContentCanAccessFileUrls = true - WebEngine.settings.localContentCanAccessRemoteUrls = true - WebEngine.settings.allowRunningInsecureContent = true - WebEngine.settings.accelerated2dCanvasEnabled = true - WebEngine.settings.javascriptCanOpenWindows = false - WebEngine.settings.showScrollBars = false - WebEngine.settings.playbackRequiresUserGesture = false - WebEngine.settings.focusOnNavigationEnabled = true - } + signal requestFadeIn() function getSetVideoCommand() { // TODO 30: // Currently wont work. Commit anyways til QtCreator and Qt work with js template literals - var src = "" - src += "var videoPlayer = document.getElementById('videoPlayer');" - src += "var videoSource = document.getElementById('videoSource');" - src += "videoSource.src = '" + Wallpaper.projectSourceFileAbsolute + "';" - src += "videoPlayer.load();" - src += "videoPlayer.volume = " + Wallpaper.volume + ";" - src += "videoPlayer.setAttribute('style', 'object-fit :" + Wallpaper.fillMode + ";');" - src += "videoPlayer.play();" + var src = ""; + src += "var videoPlayer = document.getElementById('videoPlayer');"; + src += "var videoSource = document.getElementById('videoSource');"; + src += "videoSource.src = '" + Wallpaper.projectSourceFileAbsolute + "';"; + src += "videoPlayer.load();"; + src += "videoPlayer.volume = " + Wallpaper.volume + ";"; + src += "videoPlayer.setAttribute('style', 'object-fit :" + Wallpaper.fillMode + ";');"; + src += "videoPlayer.play();"; + return src; + } - return src + Component.onCompleted: { + WebEngine.settings.localContentCanAccessFileUrls = true; + WebEngine.settings.localContentCanAccessRemoteUrls = true; + WebEngine.settings.allowRunningInsecureContent = true; + WebEngine.settings.accelerated2dCanvasEnabled = true; + WebEngine.settings.javascriptCanOpenWindows = false; + WebEngine.settings.showScrollBars = false; + WebEngine.settings.playbackRequiresUserGesture = false; + WebEngine.settings.focusOnNavigationEnabled = true; } WebEngineView { id: webView + anchors.fill: parent url: "qrc:/index.html" backgroundColor: "transparent" onJavaScriptConsoleMessage: print(lineNumber, message) onLoadProgressChanged: { if ((loadProgress === 100)) { - if (Wallpaper.type === InstalledType.VideoWallpaper) { - webView.runJavaScript(root.getSetVideoCommand(), - function (result) { - requestFadeIn() - }) - } else { - requestFadeIn() - } + if (Wallpaper.type === InstalledType.VideoWallpaper) + webView.runJavaScript(root.getSetVideoCommand(), function(result) { + requestFadeIn(); + }); + else + requestFadeIn(); } } } Text { id: txtVisualsPaused + text: qsTr("If you can read this, then the VisualsPaused optimization does not work on your system. You can fix this by disable this in: \n Settings -> Perfromance -> Pause wallpaper video rendering while another app is in the foreground ") font.pointSize: 32 visible: false @@ -64,98 +64,86 @@ Item { verticalAlignment: Text.AlignVCenter wrapMode: Text.WrapAtWordBoundaryOrAnywhere anchors.centerIn: parent - - width: parent.width * .8 + width: parent.width * 0.8 color: "white" } Timer { id: timerCover + interval: 300 onTriggered: { - webView.visible = !Wallpaper.visualsPaused - txtVisualsPaused.visible = Wallpaper.visualsPaused + webView.visible = !Wallpaper.visualsPaused; + txtVisualsPaused.visible = Wallpaper.visualsPaused; } } Connections { - target: Wallpaper - function onReloadVideo(oldType) { - webView.runJavaScript(root.getSetVideoCommand()) + webView.runJavaScript(root.getSetVideoCommand()); } function onQmlExit() { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;") + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;"); } function onMutedChanged(muted) { - if (muted) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;") - } else { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + Wallpaper.volume + ";") - } + if (muted) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;"); + else + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + Wallpaper.volume + ";"); } function onFillModeChanged(fillMode) { - if (webView.loadProgress === 100) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.setAttribute('style', 'object-fit :" + fillMode + ";');") - } + if (webView.loadProgress === 100) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.setAttribute('style', 'object-fit :" + fillMode + ";');"); + } function onLoopsChanged(loops) { - if (webView.loadProgress === 100) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.loop = " + loops + ";") - } + if (webView.loadProgress === 100) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.loop = " + loops + ";"); + } function onVolumeChanged(volume) { - if (webView.loadProgress === 100) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + volume + ";") - } + if (webView.loadProgress === 100) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + volume + ";"); + } function onCurrentTimeChanged(currentTime) { - if (webView.loadProgress === 100) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.currentTime = " - + currentTime + " * videoPlayer.duration;") - } + if (webView.loadProgress === 100) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.currentTime = " + currentTime + " * videoPlayer.duration;"); + } function onPlaybackRateChanged(playbackRate) { - if (webView.loadProgress === 100) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.playbackRate = " + playbackRate + ";") - } + if (webView.loadProgress === 100) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.playbackRate = " + playbackRate + ";"); + } function onVisualsPausedChanged(visualsPaused) { if (visualsPaused) { // Wait until Wallpaper animation is finsihed - timerCover.restart() + timerCover.restart(); } else { - webView.visible = true - txtVisualsPaused.visible = false + webView.visible = true; + txtVisualsPaused.visible = false; } } function onIsPlayingChanged(isPlaying) { if (webView.loadProgress === 100) { - if (isPlaying) { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.play();") - } else { - webView.runJavaScript( - "var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.pause();") - } + if (isPlaying) + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.play();"); + else + webView.runJavaScript("var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.pause();"); } } + + target: Wallpaper } + } diff --git a/ScreenPlayWallpaper/WebsiteWallpaper.qml b/ScreenPlayWallpaper/WebsiteWallpaper.qml index 4bc366d5..f1e43a77 100644 --- a/ScreenPlayWallpaper/WebsiteWallpaper.qml +++ b/ScreenPlayWallpaper/WebsiteWallpaper.qml @@ -1,35 +1,36 @@ import QtQuick 2.14 import QtWebEngine 1.8 - import ScreenPlayWallpaper 1.0 Item { - id: root + property string url - signal requestFadeIn + signal requestFadeIn() Component.onCompleted: { - WebEngine.settings.localContentCanAccessFileUrls = true - WebEngine.settings.localContentCanAccessRemoteUrls = true - WebEngine.settings.allowRunningInsecureContent = true - WebEngine.settings.accelerated2dCanvasEnabled = true - WebEngine.settings.javascriptCanOpenWindows = false - WebEngine.settings.showScrollBars = false - WebEngine.settings.playbackRequiresUserGesture = false - WebEngine.settings.focusOnNavigationEnabled = true + WebEngine.settings.localContentCanAccessFileUrls = true; + WebEngine.settings.localContentCanAccessRemoteUrls = true; + WebEngine.settings.allowRunningInsecureContent = true; + WebEngine.settings.accelerated2dCanvasEnabled = true; + WebEngine.settings.javascriptCanOpenWindows = false; + WebEngine.settings.showScrollBars = false; + WebEngine.settings.playbackRequiresUserGesture = false; + WebEngine.settings.focusOnNavigationEnabled = true; } WebEngineView { id: webView + anchors.fill: parent url: root.url onJavaScriptConsoleMessage: print(lineNumber, message) onLoadProgressChanged: { - if ((loadProgress === 100)) { - root.requestFadeIn() - } + if ((loadProgress === 100)) + root.requestFadeIn(); + } } + } diff --git a/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/config.qml b/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/config.qml index 666a6da2..3cc30740 100644 --- a/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/config.qml +++ b/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/config.qml @@ -1,32 +1,31 @@ import QtQuick 2.11 import QtQuick.Controls 2.4 as QQC -import QtQuick.Window 2.0 +import QtQuick.Window 2.0 import QtGraphicalEffects 1.0 - import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.wallpapers.image 2.0 as Wallpaper import org.kde.kcm 1.1 as KCM import org.kde.kirigami 2.4 as Kirigami import org.kde.newstuff 1.1 as NewStuff +Column { + id: root + property alias cfg_StopWallpaperIfHidden: stopWallpaperIfHidden.checked - Column { - id: root - anchors.fill:parent + anchors.fill: parent + spacing: units.largeSpacing - property alias cfg_StopWallpaperIfHidden: stopWallpaperIfHidden.checked - spacing: units.largeSpacing + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: units.largeSpacing - Row { - anchors.horizontalCenter: parent.horizontalCenter - spacing: units.largeSpacing - QQC.CheckBox { - id: stopWallpaperIfHidden - text: i18nd("plasma_applet_org.kde.image","Stop animation when a window is maximized"); - } - } + QQC.CheckBox { + id: stopWallpaperIfHidden + text: i18nd("plasma_applet_org.kde.image", "Stop animation when a window is maximized") + } - } + } +} diff --git a/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/main.qml b/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/main.qml index d9ebd91f..60285a0a 100644 --- a/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/main.qml +++ b/ScreenPlayWallpaper/kde/ScreenPlay/contents/ui/main.qml @@ -6,77 +6,83 @@ import QtWebEngine 1.8 Rectangle { id: root - color: "#333333" + property string fullContentPath - property real volume: 1.0 + property real volume: 1 property string fillMode: "Cover" property string type - WebSocket { - id: socket - url: "ws://127.0.0.1:16395" - active: true - onTextMessageReceived: { - var obj = JSON.parse(message) - if (obj.command === "replace") { - root.type = obj.type - root.fillMode = obj.fillMode - root.volume = obj.volume - root.fullContentPath = obj.absolutePath + "/" + obj.file - webView.setVideo() - } - } - onStatusChanged: if (socket.status === WebSocket.Error) { - messageBox.text = "Error: " + socket.errorString - } else if (socket.status === WebSocket.Open) { - socket.sendTextMessage("Hello World") - } else if (socket.status === WebSocket.Closed) { - messageBox.text += "Socket closed" - } - } - Component.onCompleted: { - WebEngine.settings.localContentCanAccessFileUrls = true - WebEngine.settings.localContentCanAccessRemoteUrls = true - WebEngine.settings.allowRunningInsecureContent = true - WebEngine.settings.accelerated2dCanvasEnabled = true - WebEngine.settings.javascriptCanOpenWindows = false - WebEngine.settings.showScrollBars = false - WebEngine.settings.playbackRequiresUserGesture = false - WebEngine.settings.focusOnNavigationEnabled = true - } - function getSetVideoCommand() { // TODO 30: // Currently wont work. Commit anyways til QtCreator and Qt work with js template literals - var src = "" - src += "var videoPlayer = document.getElementById('videoPlayer');" - src += "var videoSource = document.getElementById('videoSource');" - src += "videoSource.src = '" + root.fullContentPath + "';" - src += "videoPlayer.load();" - src += "videoPlayer.volume = " + root.volume + ";" - src += "videoPlayer.setAttribute('style', 'object-fit :" + root.fillMode + ";');" - src += "videoPlayer.play();" - print(src) + var src = ""; + src += "var videoPlayer = document.getElementById('videoPlayer');"; + src += "var videoSource = document.getElementById('videoSource');"; + src += "videoSource.src = '" + root.fullContentPath + "';"; + src += "videoPlayer.load();"; + src += "videoPlayer.volume = " + root.volume + ";"; + src += "videoPlayer.setAttribute('style', 'object-fit :" + root.fillMode + ";');"; + src += "videoPlayer.play();"; + print(src); + return src; + } - return src + color: "#333333" + Component.onCompleted: { + WebEngine.settings.localContentCanAccessFileUrls = true; + WebEngine.settings.localContentCanAccessRemoteUrls = true; + WebEngine.settings.allowRunningInsecureContent = true; + WebEngine.settings.accelerated2dCanvasEnabled = true; + WebEngine.settings.javascriptCanOpenWindows = false; + WebEngine.settings.showScrollBars = false; + WebEngine.settings.playbackRequiresUserGesture = false; + WebEngine.settings.focusOnNavigationEnabled = true; + } + + WebSocket { + id: socket + + url: "ws://127.0.0.1:16395" + active: true + onStatusChanged: { + if (socket.status === WebSocket.Error) + messageBox.text = "Error: " + socket.errorString; + else if (socket.status === WebSocket.Open) + socket.sendTextMessage("Hello World"); + else if (socket.status === WebSocket.Closed) + messageBox.text += "Socket closed"; + } + onTextMessageReceived: { + var obj = JSON.parse(message); + if (obj.command === "replace") { + root.type = obj.type; + root.fillMode = obj.fillMode; + root.volume = obj.volume; + root.fullContentPath = obj.absolutePath + "/" + obj.file; + webView.setVideo(); + } + } } WebEngineView { id: webView + + function setVideo() { + webView.runJavaScript(root.getSetVideoCommand()); + } + anchors.fill: parent opacity: loadProgress === 100 ? 1 : 0 onLoadProgressChanged: { if (loadProgress === 100) - setVideo() - } + setVideo(); - function setVideo() { - webView.runJavaScript(root.getSetVideoCommand()) } } Rectangle { id: infoWrapper + width: 300 height: 200 opacity: 0 @@ -84,8 +90,11 @@ Rectangle { Text { id: messageBox + text: qsTr("text") anchors.centerIn: parent } + } + } diff --git a/ScreenPlayWidget/Widget.qml b/ScreenPlayWidget/Widget.qml index c3cfef46..51e2dd68 100644 --- a/ScreenPlayWidget/Widget.qml +++ b/ScreenPlayWidget/Widget.qml @@ -6,37 +6,35 @@ import ScreenPlay.Enums.InstalledType 1.0 Item { id: mainWindow + anchors.fill: parent Connections { - target: Widget - function onQmlExit() { - Widget.setWindowBlur(0) - animFadeOut.start() + Widget.setWindowBlur(0); + animFadeOut.start(); } function onQmlSceneValueReceived(key, value) { - var obj2 = 'import QtQuick 2.14; Item {Component.onCompleted: loader.item.' - + key + ' = ' + value + '; }' - var newObject = Qt.createQmlObject(obj2.toString(), root, "err") - newObject.destroy(10000) + var obj2 = 'import QtQuick 2.14; Item {Component.onCompleted: loader.item.' + key + ' = ' + value + '; }'; + var newObject = Qt.createQmlObject(obj2.toString(), root, "err"); + newObject.destroy(10000); } + // Replace wallpaper with QML Scene function onReloadQML(oldType) { - - loader.sourceComponent = undefined - loader.source = "" - Widget.clearComponentCache() - - loader.source = Qt.resolvedUrl(Widget.projectSourceFileAbsolute) + loader.sourceComponent = undefined; + loader.source = ""; + Widget.clearComponentCache(); + loader.source = Qt.resolvedUrl(Widget.projectSourceFileAbsolute); } - + target: Widget } OpacityAnimator { id: animFadeOut + from: 1 to: 0 target: parent @@ -47,132 +45,144 @@ Item { Rectangle { id: bgColor + anchors.fill: parent color: "white" - opacity: .15 + opacity: 0.15 } Image { id: bg + source: "qrc:/assets/image/noisy-texture-3.png" anchors.fill: parent - opacity: .05 + opacity: 0.05 fillMode: Image.Tile } Loader { id: loader + anchors.fill: parent asynchronous: true Component.onCompleted: { switch (Widget.type) { case InstalledType.QMLWidget: - loader.source = Qt.resolvedUrl( Widget.projectSourceFileAbsolute) - break + loader.source = Qt.resolvedUrl(Widget.projectSourceFileAbsolute); + break; case InstalledType.HTMLWidget: - loader.sourceComponent = webViewComponent - break + loader.sourceComponent = webViewComponent; + break; } } onStatusChanged: { if (loader.status == Loader.Ready) { - if (loader.item.widgetBackground !== undefined) { - bgColor.color = loader.item.widgetBackground - } - if (loader.item.widgetBackgroundOpacity !== undefined) { - bgColor.opacity = loader.item.widgetBackgroundOpacity - } - if (loader.item.widgetWidth !== undefined - && loader.item.widgetHeight !== undefined) { - Widget.setWidgetSize(loader.item.widgetWidth, - loader.item.widgetHeight) - } + if (loader.item.widgetBackground !== undefined) + bgColor.color = loader.item.widgetBackground; + + if (loader.item.widgetBackgroundOpacity !== undefined) + bgColor.opacity = loader.item.widgetBackgroundOpacity; + + if (loader.item.widgetWidth !== undefined && loader.item.widgetHeight !== undefined) + Widget.setWidgetSize(loader.item.widgetWidth, loader.item.widgetHeight); + } } } Component { id: webViewComponent + WebEngineView { id: webView + backgroundColor: "transparent" anchors.fill: parent onJavaScriptConsoleMessage: print(lineNumber, message) Component.onCompleted: { - webView.url = Qt.resolvedUrl(Widget.sourcePath) + webView.url = Qt.resolvedUrl(Widget.sourcePath); } } + } MouseArea { id: mouseArea + property var clickPos + anchors.fill: parent hoverEnabled: true onPressed: { clickPos = { "x": mouse.x, "y": mouse.y - } + }; } - onPositionChanged: { - if (mouseArea.pressed) { - Widget.setPos(Widget.cursorPos().x - clickPos.x, - Widget.cursorPos().y - clickPos.y) - } + if (mouseArea.pressed) + Widget.setPos(Widget.cursorPos().x - clickPos.x, Widget.cursorPos().y - clickPos.y); + } } MouseArea { id: mouseAreaClose + width: 20 height: width + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onEntered: imgClose.opacity = 1 + onExited: imgClose.opacity = 0.15 + onClicked: { + Widget.setWindowBlur(0); + animFadeOut.start(); + } + anchors { top: parent.top right: parent.right } - cursorShape: Qt.PointingHandCursor - onClicked: { - Widget.setWindowBlur(0) - animFadeOut.start() - } - hoverEnabled: true - onEntered: imgClose.opacity = 1 - onExited: imgClose.opacity = .15 Image { id: imgClose + source: "qrc:/assets/icons/baseline-close-24px.svg" anchors.centerIn: parent - opacity: .15 + opacity: 0.15 + OpacityAnimator { target: parent duration: 300 } + } + } MouseArea { id: mouseAreaResize + + property point clickPosition + width: 20 height: width + cursorShape: Qt.SizeFDiagCursor + onPressed: { + clickPosition = Qt.point(mouseX, mouseY); + } + onPositionChanged: { + if (mouseAreaResize.pressed) + Widget.setWidgetSize(clickPosition.x + mouseX, clickPosition.y + mouseY); + + } + anchors { bottom: parent.bottom right: parent.right } - cursorShape: Qt.SizeFDiagCursor - property point clickPosition - onPressed: { - clickPosition = Qt.point(mouseX, mouseY) - } - - onPositionChanged: { - if (mouseAreaResize.pressed) { - Widget.setWidgetSize(clickPosition.x + mouseX, - clickPosition.y + mouseY) - } - } } + } diff --git a/ScreenPlayWidget/test.qml b/ScreenPlayWidget/test.qml index 7ef167a3..33577896 100644 --- a/ScreenPlayWidget/test.qml +++ b/ScreenPlayWidget/test.qml @@ -6,6 +6,7 @@ Rectangle { Text { id: name + text: qsTr("This is a empty test widget. You can change the source in test.qml") horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -16,10 +17,3 @@ Rectangle { } } - - - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/