diff --git a/ScreenPlay/Resources.qrc b/ScreenPlay/Resources.qrc index a10350c6..7a1d0def 100644 --- a/ScreenPlay/Resources.qrc +++ b/ScreenPlay/Resources.qrc @@ -100,5 +100,20 @@ legal/lgpl-2.1.txt assets/icons/icon_delete.svg assets/icons/app.ico + assets/icons/icon_supervisor_account.svg + assets/icons/icon_new_releases.svg + assets/icons/icon_report_problem.svg + assets/icons/icon_help_center.svg + assets/icons/icon_forum.svg + assets/icons/icon_thumb_up.svg + assets/icons/icon_thumb_down.svg + assets/icons/icon_cake.afdesign + assets/icons/icon_window.svg + assets/WorkshopPreview.html + assets/images/ava.png + assets/images/mask.svg + assets/images/mask_workshop.png + assets/images/Untitled.png + assets/images/window.svg diff --git a/ScreenPlay/app.cpp b/ScreenPlay/app.cpp index 956598b3..4ebee074 100644 --- a/ScreenPlay/app.cpp +++ b/ScreenPlay/app.cpp @@ -124,8 +124,6 @@ App::App() // ScreenPlayManager first to check if another ScreenPlay Instace is running m_screenPlayManager = std::make_unique(); m_isAnotherScreenPlayInstanceRunning = m_screenPlayManager->isAnotherScreenPlayInstanceRunning(); - - } /*! @@ -181,6 +179,10 @@ void App::init() } qmlRegisterSingletonInstance("ScreenPlay", 1, 0, "ScreenPlay", this); + + if (!loadSteamPlugin()) + qWarning() << "Steam plugin not provided!"; + m_mainWindowEngine->load(QUrl(QStringLiteral("qrc:/main.qml"))); } @@ -199,4 +201,25 @@ void App::exit() QTimer::singleShot(150, []() { QApplication::instance()->quit(); }); } } + +bool App::loadSteamPlugin() +{ +#ifdef Q_OS_MACOS + const QString fileSuffix = ".dylib"; +#endif +#ifdef Q_OS_WIN + const QString fileSuffix = ".dll"; +#else + const QString fileSuffix = ".so"; +#endif + + m_workshopPlugin.setFileName(QApplication::applicationDirPath() + "/ScreenPlayWorkshop" + fileSuffix); + + if (!m_workshopPlugin.load()) { + return false; + } + + const ScreenPlayWorkshopPlugin* workshopPlugin = reinterpret_cast(m_workshopPlugin.instance()); + return true; +} } diff --git a/ScreenPlay/app.h b/ScreenPlay/app.h index 9b613809..250ec334 100644 --- a/ScreenPlay/app.h +++ b/ScreenPlay/app.h @@ -63,6 +63,8 @@ #include "src/settings.h" #include "src/util.h" +class ScreenPlayWorkshopPlugin; + namespace ScreenPlay { class App : public QObject { @@ -131,7 +133,6 @@ public: return m_installedListFilter.get(); } - QQmlApplicationEngine* mainWindowEngine() const { return m_mainWindowEngine.get(); @@ -238,7 +239,6 @@ public slots: emit installedListFilterChanged(m_installedListFilter.get()); } - void setMainWindowEngine(QQmlApplicationEngine* mainWindowEngine) { if (m_mainWindowEngine.get() == mainWindowEngine) @@ -249,6 +249,10 @@ public slots: } private: + bool loadSteamPlugin(); + +private: + QPluginLoader m_workshopPlugin; std::unique_ptr m_mainWindowEngine; std::unique_ptr m_create; diff --git a/ScreenPlay/assets/WorkshopPreview.html b/ScreenPlay/assets/WorkshopPreview.html new file mode 100644 index 00000000..2cdda277 --- /dev/null +++ b/ScreenPlay/assets/WorkshopPreview.html @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/icon_thumb_down.svg b/ScreenPlay/assets/icons/icon_thumb_down.svg new file mode 100644 index 00000000..c673773b --- /dev/null +++ b/ScreenPlay/assets/icons/icon_thumb_down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/icon_thumb_up.svg b/ScreenPlay/assets/icons/icon_thumb_up.svg new file mode 100644 index 00000000..8f3b5f05 --- /dev/null +++ b/ScreenPlay/assets/icons/icon_thumb_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/images/Untitled.png b/ScreenPlay/assets/images/Untitled.png new file mode 100644 index 00000000..e1a31bdd Binary files /dev/null and b/ScreenPlay/assets/images/Untitled.png differ diff --git a/ScreenPlay/assets/images/ava.png b/ScreenPlay/assets/images/ava.png new file mode 100644 index 00000000..0cdbe59c Binary files /dev/null and b/ScreenPlay/assets/images/ava.png differ diff --git a/ScreenPlay/assets/images/mask.svg b/ScreenPlay/assets/images/mask.svg new file mode 100644 index 00000000..1d490420 --- /dev/null +++ b/ScreenPlay/assets/images/mask.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/images/mask_workshop.png b/ScreenPlay/assets/images/mask_workshop.png new file mode 100644 index 00000000..e1a31bdd Binary files /dev/null and b/ScreenPlay/assets/images/mask_workshop.png differ diff --git a/ScreenPlay/qml.qrc b/ScreenPlay/qml.qrc index 2fc4fdc1..ad512dae 100644 --- a/ScreenPlay/qml.qrc +++ b/ScreenPlay/qml.qrc @@ -58,5 +58,20 @@ assets/icons/icon_report_problem.svg assets/icons/icon_help_center.svg assets/icons/icon_forum.svg + qml/Workshop/ScreenPlayItem.qml + qml/Workshop/ScreenPlayItemImage.qml + qml/Workshop/WorkshopAlertBanner.qml + qml/Workshop/WorkshopBackground.qml + qml/Workshop/WorkshopBanner.qml + qml/Workshop/WorkshopInstalled.qml + qml/Workshop/WorkshopItem.qml + qml/Workshop/WorkshopItemDetail.qml + qml/Workshop/WorkshopNavigation.qml + qml/Workshop/WorkshopPopupOffline.qml + qml/Workshop/WorkshopWrapper.qml + qml/Workshop/upload/PopupSteamWorkshopAgreement.qml + qml/Workshop/upload/UploadProject.qml + qml/Workshop/upload/UploadProjectBigItem.qml + qml/Workshop/upload/UploadProjectItem.qml diff --git a/ScreenPlay/qml/Workshop/ScreenPlayItem.qml b/ScreenPlay/qml/Workshop/ScreenPlayItem.qml new file mode 100644 index 00000000..7e76eb19 --- /dev/null +++ b/ScreenPlay/qml/Workshop/ScreenPlayItem.qml @@ -0,0 +1,288 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Styles 1.4 + +Item { + id: screenPlayItem + width: 320 + height: 180 + property alias checkBox: checkBox + state: "invisible" + opacity: 0 + + property string preview: screenPreview + property bool isSelected: false + property string customTitle: "name here" + property string absoluteStoragePath + property string type + property bool hasMenuOpen: false + property int workshopID: 0 + property int itemIndex + property string screenId: "" + signal itemClicked(var screenId, var type, var isActive) + + onTypeChanged: { + if (type === "widget") { + icnType.source = "icons/icon_widgets.svg" + } else if (type === "qmlScene") { + icnType.source = "icons/icon_code.svg" + } + } + + Component.onCompleted: { + 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 + 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 + to: 0 + duration: 500 + easing.type: Easing.OutQuint + property: "angle" + } + PropertyAnimation { + target: screenPlayItem + from: 0 + to: 1 + duration: 500 + easing.type: Easing.OutQuint + property: "opacity" + } + PropertyAnimation { + target: tr + from: 80 + to: 0 + duration: 500 + easing.type: Easing.OutQuint + property: "y" + } + PropertyAnimation { + target: sc + from: .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 + cached: true + glowRadius: 3 + spread: 0.2 + color: "black" + opacity: 0.4 + cornerRadius: 15 + } + + Item { + id: screenPlayItemWrapper + anchors.centerIn: parent + height: 180 + width: 320 + + Image { + id: mask + source: "qrc:/assets/img/window.svg" + sourceSize: Qt.size(screenPlayItem.width, screenPlayItem.height) + visible: false + smooth: true + fillMode: Image.PreserveAspectFit + } + + Item { + id: itemWrapper + anchors.fill: parent + visible: false + + ScreenPlayItemImage { + id: screenPlayItemImage + anchors.fill: parent + 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 { + anchors.fill: itemWrapper + source: itemWrapper + maskSource: mask + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton + onEntered: { + if (!hasMenuOpen) { + screenPlayItem.state = "hover" + } + } + onExited: { + if (!hasMenuOpen) { + screenPlayItem.state = "visible" + } + } + + onClicked: { + 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 + } + } + + anchors { + top: parent.top + right: parent.right + margins: 10 + } + } + } + + states: [ + State { + name: "invisible" + + PropertyChanges { + target: screenPlayItemWrapper + 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" + + PropertyChanges { + target: screenPlayItemWrapper + y: 0 + opacity: 1 + } + PropertyChanges { + target: icnType + opacity: .5 + } + } + ] + transitions: [ + Transition { + from: "invisible" + to: "visible" + }, + Transition { + from: "visible" + to: "selected" + reversible: true + + PropertyAnimation { + target: icnType + property: "opacity" + duration: 80 + } + } + ] +} diff --git a/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml b/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml new file mode 100644 index 00000000..b68e472e --- /dev/null +++ b/ScreenPlay/qml/Workshop/ScreenPlayItemImage.qml @@ -0,0 +1,59 @@ +import QtQuick 2.12 + +Item { + id: screenPlayItemImage + width: 320 + height: 121 + state: "loading" + + property string sourceImage + property string sourceImageGIF + + Image { + id: image + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: screenPlayItemImage.sourceImage.trim() + onStatusChanged: { + if (image.status === Image.Ready) { + screenPlayItemImage.state = "loaded" + } else if (image.status === Image.Error) { + source = "images/missingPreview.png" + screenPlayItemImage.state = "loaded" + } + } + } + + states: [ + State { + name: "loading" + + PropertyChanges { + target: image + opacity: 0 + } + }, + State { + name: "loaded" + + PropertyChanges { + target: image + opacity: 1 + } + } + ] + + transitions: [ + Transition { + from: "loading" + to: "loaded" + + NumberAnimation { + target: image + property: "opacity" + duration: 300 + easing.type: Easing.InOutQuad + } + } + ] +} diff --git a/ScreenPlay/qml/Workshop/Workshop.qml b/ScreenPlay/qml/Workshop/Workshop.qml index a2fc9cfd..35ee30e1 100644 --- a/ScreenPlay/qml/Workshop/Workshop.qml +++ b/ScreenPlay/qml/Workshop/Workshop.qml @@ -2,7 +2,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.2 import QtGraphicalEffects 1.0 -import ScreenPlay.Workshop 1.0 Item { id: workshop @@ -12,5 +11,4 @@ Item { anchors.fill: parent } - } diff --git a/ScreenPlay/qml/Workshop/WorkshopAlertBanner.qml b/ScreenPlay/qml/Workshop/WorkshopAlertBanner.qml new file mode 100644 index 00000000..4e01a83f --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopAlertBanner.qml @@ -0,0 +1,114 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 + +Item { + id: workshopAltertBannerWrapper + height: 50 + state: "out" + + anchors { + bottom: parent.bottom + right: parent.right + left: parent.left + } + + Rectangle { + id: workshopAltertBanner + height: 50 + color: "#3498db" + anchors { + top: parent.top + right: parent.right + left: parent.left + } + Image { + id: icoFrown + source: "qrc:/assets/icons/font-awsome/frown-o.svg" + sourceSize: Qt.size(18, 18) + anchors { + left: parent.left + leftMargin: 20 + verticalCenter: parent.verticalCenter + } + } + Text { + id: name + text: qsTr("Oh No! Looks like there a only a few wallpapers and widgets! Help us by creating your own wallpapers and Widgets :)") + color: "white" + font.pointSize: 11 + + font.family: ScreenPlay.settings.font + anchors { + left: icoFrown.right + leftMargin: 20 + verticalCenter: parent.verticalCenter + } + } + MouseArea { + anchors { + top: parent.top + right: closeWrapper.left + bottom: parent.bottom + left: parent.left + } + cursorShape: Qt.PointingHandCursor + onClicked: { + screenPlaySettings.setHasWorkshopBannerSeen(true) + ScreenPlay.ut.setNavigation("Create") + } + } + + Item { + id: closeWrapper + height: 50 + width: 50 + anchors { + top: parent.top + right: parent.right + } + Image { + id: icoClose + source: "qrc:/assets/icons/font-awsome/close.svg" + sourceSize: Qt.size(15, 15) + anchors.centerIn: parent + } + MouseArea { + anchors.fill: parent + z: 99 + onClicked: { + screenPlaySettings.setHasWorkshopBannerSeen(true) + workshopAltertBannerWrapper.state = "out" + } + } + } + } + states: [ + State { + name: "out" + PropertyChanges { + target: workshopAltertBanner + anchors.bottomMargin: -50 + } + }, + State { + name: "in" + PropertyChanges { + target: workshopAltertBanner + anchors.bottomMargin: 0 + } + } + ] + transitions: [ + Transition { + from: "out" + to: "in" + reversible: true + NumberAnimation { + target: footer + property: "anchors.bottomMargin" + duration: 300 + easing.type: Easing.InOutQuad + } + } + ] +} diff --git a/ScreenPlay/qml/Workshop/WorkshopBackground.qml b/ScreenPlay/qml/Workshop/WorkshopBackground.qml new file mode 100644 index 00000000..4dc95632 --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopBackground.qml @@ -0,0 +1,162 @@ +import QtQuick 2.13 +import QtGraphicalEffects 1.0 +import ScreenPlay.Workshop 1.0 + +Rectangle { + id: root + state: "base" + color: "#161C1D" + property string backgroundImage: "" + property int imageOffsetTop: 0 + onImageOffsetTopChanged: { + if ((imageOffsetTop * -1) >= 300) { + root.state = "backgroundColor" + } else { + if (root.state !== "backgroundImage") { + root.state = "backgroundImage" + } + } + } + onBackgroundImageChanged: { + if (backgroundImage === "") { + root.state = "base" + } else { + root.state = "backgroundImage" + } + } + + Image { + id: maskSource + visible: false + source: "qrc:/assets/images/mask_workshop.png" + } + + + + + Image { + id: bgImage + height: bgImage.sourceSize.height + anchors { + topMargin: root.imageOffsetTop + top: parent.top + right: parent.right + 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 + color: "#00ffffff" + } + GradientStop { + position: .9 + color: "#161C1D" + } + } + } + } + + MaskedBlur { + id:blur + anchors.fill: bgImage + source: bgImage + maskSource: maskSource + radius: 16 + cached: true + samples: 24 + } + + + + Rectangle { + id: bgColor + color: "#161C1D" + opacity: 0 + anchors.fill: parent + } + + + states: [ + State { + name: "base" + PropertyChanges { + target: bgImage + opacity: 0 + } + + PropertyChanges { + target: bgColor + opacity: 0 + } + PropertyChanges { + target: blur + opacity: 0 + } + }, + State { + name: "backgroundImage" + PropertyChanges { + target: bgImage + opacity: 1 + } + + PropertyChanges { + target: bgColor + opacity: 0 + } + PropertyChanges { + target: blur + opacity: 1 + } + }, + State { + name: "backgroundColor" + PropertyChanges { + target: bgImage + opacity: 0 + } + + PropertyChanges { + target: bgColor + opacity: 1 + } + PropertyChanges { + target: blur + opacity: 1 + } + } + ] + transitions: [ + Transition { + from: "base" + to: "backgroundImage" + reversible: true + PropertyAnimation { + targets: [bgImage, bgColor, blur] + duration: 2000 + easing.type: Easing.InOutQuart + property: "opacity" + } + }, + Transition { + from: "backgroundImage" + to: "backgroundColor" + reversible: true + PropertyAnimation { + targets: [bgImage, bgColor] + duration: 1000 + easing.type: Easing.InOutQuart + property: "opacity" + } + } + ] +} diff --git a/ScreenPlay/qml/Workshop/WorkshopBanner.qml b/ScreenPlay/qml/Workshop/WorkshopBanner.qml new file mode 100644 index 00000000..822d45f0 --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopBanner.qml @@ -0,0 +1,51 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.3 + +Item { + Connections { + target: steamWorkshop + function onWorkshopSearched() { + bannerTxt.text = workshopListModel.getBannerText() + bannerImg.source = workshopListModel.getBannerUrl() + } + } + + Rectangle { + id: banner + color: "#44131313" + height: 350 + anchors { + top: parent.top + right: parent.right + left: parent.left + } + Image { + id: bannerImg + anchors { + right: parent.right + left: parent.left + bottom: parent.bottom + } + + asynchronous: true + fillMode: Image.PreserveAspectCrop + } + + Text { + id: bannerTxt + text: "loading" + font.pointSize: 36 + color: "white" + } + } + + Item { + id: searchBar + height: 70 + anchors { + top: banner.bottom + right: parent.right + left: parent.left + } + } +} diff --git a/ScreenPlay/qml/Workshop/WorkshopInstalled.qml b/ScreenPlay/qml/Workshop/WorkshopInstalled.qml new file mode 100644 index 00000000..334df2cc --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopInstalled.qml @@ -0,0 +1,49 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Styles 1.4 +import QtGraphicalEffects 1.0 +import ScreenPlay.Workshop 1.0 as SP + +Item { + id: pageInstalled + state: "out" + clip: true + + signal setSidebaractiveItem(var screenId, var type) + signal setNavigationItem(var pos) + signal setSidebarActive(var active) + + property bool refresh: false + property bool enabled: true + + Component.onCompleted: { + pageInstalled.state = "in" + } + + Connections { + target: loaderHelp.item + function onHelperButtonPressed(pos) { + setNavigationItem(pos) + } + } + + Loader { + id: loaderHelp + asynchronous: true + active: false + z: 99 + anchors.fill: parent + source: "qrc:/qml/Installed/InstalledUserHelper.qml" + } + + + + states: [] + + transitions: [ + Transition { + from: "out" + to: "in" + } + ] +} diff --git a/ScreenPlay/qml/Workshop/WorkshopItem.qml b/ScreenPlay/qml/Workshop/WorkshopItem.qml new file mode 100644 index 00000000..63df73d9 --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopItem.qml @@ -0,0 +1,478 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Material 2.2 +import Qt.labs.platform 1.0 +import ScreenPlay.Workshop 1.0 as SP + +import ScreenPlay 1.0 + +Item { + id: root + width: 320 + height: 180 + + property url imgUrl + property url additionalPreviewUrl + property string name + property int workshopID + property int itemIndex + property int subscriptionCount + + property bool isDownloading: false + + signal clicked(int workshopID, url imgUrl) + + RectangularGlow { + id: effect + anchors { + top: parent.top + topMargin: 3 + } + + height: parent.height + width: parent.width + cached: true + glowRadius: 3 + spread: 0.2 + color: "black" + opacity: 0.4 + cornerRadius: 15 + } + 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 + to: 0 + duration: 500 + easing.type: Easing.OutQuint + property: "angle" + } + PropertyAnimation { + target: root + from: 0 + to: 1 + duration: 500 + easing.type: Easing.OutQuint + property: "opacity" + } + PropertyAnimation { + target: tr + from: 80 + to: 0 + duration: 500 + easing.type: Easing.OutQuint + property: "y" + } + PropertyAnimation { + target: sc + from: .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 + smooth: true + fillMode: Image.PreserveAspectFit + } + + Item { + id: itemWrapper + visible: false + anchors { + fill: parent + margins: 5 + } + + ScreenPlayItemImage { + id: screenPlayItemImage + anchors.fill: parent + sourceImage: root.imgUrl + sourceImageGIF: root.additionalPreviewUrl + } + + LinearGradient { + id: shadow + height: 80 + opacity: 0 + cached: true + 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 + color: "#CC000000" + } + GradientStop { + position: 1.0 + color: "#00000000" + } + } + } + Text { + id: txtTitle + text: root.name + + opacity: 0 + height: 30 + width: 180 + verticalAlignment: Text.AlignVCenter + color: "white" + font.pointSize: 18 + wrapMode: Text.WordWrap + font.family: ScreenPlay.settings.font + anchors { + bottom: parent.bottom + right: button.left + rightMargin: 10 + left: parent.left + leftMargin: 20 + bottomMargin: -50 + } + } + + Button { + id: button + text: qsTr("Download") + anchors { + right: parent.right + rightMargin: 20 + bottom: parent.bottom + bottomMargin: -50 + } + opacity: 0 + Material.background: Material.Orange + Material.foreground: "white" + icon.source: "qrc:/assets/icons/icon_download.svg" + icon.width: 12 + icon.height: 12 + } + + 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 { + anchors.fill: itemWrapper + source: itemWrapper + maskSource: mask + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onContainsMouseChanged: { + if (!isDownloading) { + if (containsMouse) { + root.state = "hover" + } else { + root.state = "" + } + } + } + onClicked: { + root.clicked(root.workshopID, root.imgUrl) + } + } + MouseArea { + cursorShape: Qt.PointingHandCursor + height: 50 + anchors { + right: parent.right + left: parent.left + bottom: parent.bottom + } + + onClicked: { + isDownloading = true + root.state = "downloading" + SP.Workshop.steamWorkshop.subscribeItem(root.workshopID) + ScreenPlay.setTrackerSendEvent("subscribeItem", + root.workshopID) + } + + Connections { + target: SP.Workshop.steamWorkshop + function onWorkshopItemInstalled(appID, publishedFile) { + if (appID === SP.Workshop.steamWorkshop.appID) { + root.state = "installed" + } + } + } + } + + MouseArea { + height: 20 + width: 20 + cursorShape: Qt.PointingHandCursor + anchors { + margins: 10 + top: parent.top + right: parent.right + } + onClicked: { + Qt.openUrlExternally( + "steam://url/CommunityFilePage/" + root.workshopID) + } + } + } + FastBlur { + id: effBlur + anchors.fill: itemWrapper + source: itemWrapper + radius: 0 + } + + Item { + id: itmDownloading + opacity: 0 + anchors { + top: parent.top + topMargin: 50 + right: parent.right + bottom: parent.bottom + left: parent.left + } + + 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 + rightMargin: 20 + left: parent.left + leftMargin: 20 + } + } + } + } + + states: [ + State { + name: "hover" + + PropertyChanges { + target: button + opacity: 1 + anchors.bottomMargin: 10 + } + + PropertyChanges { + target: openInWorkshop + opacity: .75 + } + + PropertyChanges { + target: txtTitle + opacity: 1 + anchors.bottomMargin: 20 + } + + PropertyChanges { + target: shadow + opacity: 1 + } + PropertyChanges { + target: effBlur + radius: 0 + } + }, + State { + name: "downloading" + + PropertyChanges { + target: button + opacity: 0 + } + PropertyChanges { + target: openInWorkshop + opacity: 0 + } + + PropertyChanges { + target: txtTitle + opacity: 0 + } + + PropertyChanges { + target: shadow + opacity: 0 + } + + PropertyChanges { + target: effBlur + radius: 64 + } + + PropertyChanges { + target: itmDownloading + opacity: 1 + anchors.topMargin: 0 + } + }, + State { + name: "installed" + + PropertyChanges { + target: button + opacity: 0 + } + + PropertyChanges { + target: txtTitle + opacity: 0 + } + + PropertyChanges { + target: shadow + opacity: 0 + } + + PropertyChanges { + target: effBlur + radius: 64 + } + + PropertyChanges { + target: itmDownloading + opacity: 1 + anchors.topMargin: 0 + } + PropertyChanges { + target: txtDownloading + text: qsTr("Download complete!") + } + } + ] + transitions: [ + Transition { + from: "" + to: "hover" + reversible: true + + PropertyAnimation { + target: button + duration: 100 + properties: "opacity, anchors.bottomMargin" + } + PropertyAnimation { + target: openInWorkshop + duration: 100 + properties: "opacity" + } + PropertyAnimation { + target: txtTitle + duration: 100 + properties: "opacity, anchors.bottomMargin" + } + PropertyAnimation { + target: shadow + duration: 100 + properties: "opacity" + } + }, + Transition { + from: "*" + to: "downloading" + reversible: true + + PropertyAnimation { + target: button + duration: 100 + properties: "opacity" + } + PropertyAnimation { + target: txtTitle + 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/WorkshopItemDetail.qml b/ScreenPlay/qml/Workshop/WorkshopItemDetail.qml new file mode 100644 index 00000000..9fdd8b23 --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopItemDetail.qml @@ -0,0 +1,373 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 +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 as SP +import ScreenPlay 1.0 + +Drawer { + id: root + edge: Qt.RightEdge + height: parent.height - 60 + dim: false + modal: false + width: 400 + interactive: false + 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 + property int workshopID + property int itemIndex + property int subscriptionCount + property bool subscribed: false + + function setWorkshopItem(id, imgUrl, videoPreview, subscriptionCount) { + + if (root.workshopID === id) { + if (!root.visible) { + root.open() + } else { + root.close() + } + return + } + webView.opacity = 0 + root.workshopID = id + root.imgUrl = imgUrl + root.subscriptionCount = subscriptionCount + root.videoPreview = videoPreview + root.subscribed = false + txtVotesUp.highlighted = false + txtVotesDown.highlighted = false + + if (!root.visible) { + root.open() + } + SP.Workshop.steamWorkshop.requestWorkshopItemDetails(workshopID) + + webView.setVideo() + } + + Connections { + target: SP.Workshop.steamWorkshop + function onRequestItemDetailReturned(title, tags, steamIDOwner, description, votesUp, votesDown, url, fileSize, publishedFileId) { + + txtTitle.text = title + txtTags.tags = tags + const size = Math.floor((1000 * ((fileSize / 1024) / 1000)) / 1000) + txtFileSize.text = qsTr("Project 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 + } + } + + 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 + url: Qt.resolvedUrl(".") + "WorkshopPreview.html" + onUrlChanged: print(url) + + Behavior on opacity { + NumberAnimation { + duration: 200 + } + } + + function getUpdateVideoCommand() { + let src = "" + src += "var videoPlayer1 = document.getElementById('video');\n" + src += "videoPlayer1.src = '" + root.videoPreview + "';\n" + src += "videoPlayer1.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 + + 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 + color: "#EE000000" + } + GradientStop { + position: 1.0 + color: "#00000000" + } + } + } + + Text { + id: txtTitle + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + verticalAlignment: Text.AlignBottom + font.pointSize: 16 + color: "white" + 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 + anchors.left: parent.left + cursorShape: Qt.PointingHandCursor + onClicked: root.close() + + Image { + id: imgBack + source: "qrc:/assets/icons/icon_arrow_right.svg" + sourceSize: Qt.size(15, 15) + fillMode: Image.PreserveAspectFit + anchors.centerIn: parent + } + } + } + + ColumnLayout { + anchors { + top: imgWrapper.bottom + right: parent.right + left: parent.left + + margins: 20 + } + + spacing: 20 + + ColumnLayout { + Layout.fillHeight: true + Layout.fillWidth: true + spacing: 20 + + ColumnLayout { + Layout.maximumWidth: 280 + Layout.alignment: Qt.AlignHCenter + + RowLayout { + Layout.fillWidth: true + spacing: 20 + + 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: { + SP.Workshop.steamWorkshop.vote(root.workshopID, + 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: { + SP.Workshop.steamWorkshop.vote(root.workshopID, + 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 + } + } + + RowLayout { + Layout.fillWidth: true + spacing: 20 + + Text { + id: txtFileSize + color: Material.secondaryTextColor + font.family: ScreenPlay.settings.font + font.pointSize: 11 + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + + Text { + id: txtTags + Layout.alignment: Qt.AlignLeft + text: qsTr("Tags: ") + tags + font.pointSize: 11 + opacity: tags !== "" ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 200 + } + } + + color: Material.secondaryTextColor + font.family: ScreenPlay.settings.font + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + elide: Text.ElideRight + property string tags + } + } + + 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 + } + + ToolButton { + icon.source: "qrc:/assets/icons/icon_open_in_new.svg" + text: qsTr("Open In Steam") + //Material.color: Material.secondaryTextColor + onClicked: Qt.openUrlExternally( + "steam://url/CommunityFilePage/" + root.workshopID) + } + } + + Rectangle { + Layout.fillWidth: true + Layout.minimumHeight: 150 + Layout.fillHeight: true //txtDescription.paintedHeight > 100 + color: Material.backgroundColor + radius: 3 + ScrollView { + anchors.fill: parent + anchors.margins: 10 + clip: true + ScrollBar.vertical.policy: ScrollBar.AsNeeded + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + Text { + id: txtDescription + width: parent.width + color: Material.primaryTextColor + font.family: ScreenPlay.settings.font + font.pointSize: 10 + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + } + } + } + } + + Button { + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 20 + } + + highlighted: !root.subscribed + enabled: !root.subscribed + icon.source: "qrc:/assets/icons/icon_download.svg" + text: root.subscribed ? qsTr("Subscribed!") : qsTr("Subscribe") + onClicked: { + root.subscribed = true + SP.Workshop.steamWorkshop.subscribeItem(root.workshopID) + } + } +} + +/*##^## +Designer { + D{i:0;formeditorZoom:0.75;height:800;width:300} +} +##^##*/ + diff --git a/ScreenPlay/qml/Workshop/WorkshopNavigation.qml b/ScreenPlay/qml/Workshop/WorkshopNavigation.qml new file mode 100644 index 00000000..8f9672c6 --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopNavigation.qml @@ -0,0 +1,116 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtQuick.Controls.Material 2.13 +import QtGraphicalEffects 1.0 + +import ScreenPlay.Workshop 1.0 +import ScreenPlay.Workshop.SteamEnums 1.0 +import SteamQMLImageProvider 1.0 +import ScreenPlay 1.0 + +Item { + id: root + width: 800 + height: 60 + + signal uploadPressed + + Rectangle { + id: bg + color: Material.theme === Material.Light ? "white" : Qt.darker(Material.background) + opacity: .9 + radius: 3 + anchors.fill: wrapper + } + + Item { + id: wrapper + + anchors { + top: parent.top + right: parent.right + left: parent.left + bottom: parent.bottom + bottomMargin: 5 + } + + Text { + id: name + text: { + return Workshop.steamWorkshop.steamAccount.username + qsTr( + " Subscribed items: ") + + Workshop.steamWorkshop.steamAccount.amountSubscribedItems + } + + font.pointSize: 14 + color: Material.primaryTextColor + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + verticalAlignment: Qt.AlignVCenter + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + anchors { + top: parent.top + left: avatar.right + leftMargin: 10 + bottom: parent.bottom + right: btnUplaod.left + rightMargin: 10 + } + } + + SteamImage { + id: avatar + width: 40 + height: 40 + anchors { + left: parent.left + leftMargin: 10 + verticalCenter: parent.verticalCenter + } + Component.onCompleted: Workshop.steamWorkshop.steamAccount.loadAvatar() + Connections { + target: Workshop.steamWorkshop.steamAccount + function onAvatarChanged(_avatar) { + avatar.setImage(_avatar) + } + } + } + + Button { + id: btnUplaod + text: qsTr("Upload to the Steam Workshop") + Material.background: Material.accent + Material.foreground: "white" + icon.source: "qrc:/assets/icons/icon_plus.svg" + icon.color: "white" + icon.width: 16 + icon.height: 16 + highlighted: true + + onClicked: uploadPressed() + anchors { + top: parent.top + right: parent.right + rightMargin: 10 + bottom: parent.bottom + } + } + } + + states: [ + State { + name: "base" + PropertyChanges { + target: bg + radius: 3 + } + }, + State { + name: "scrolling" + PropertyChanges { + target: bg + radius: 0 + } + } + ] +} diff --git a/ScreenPlay/qml/Workshop/WorkshopPopupOffline.qml b/ScreenPlay/qml/Workshop/WorkshopPopupOffline.qml new file mode 100644 index 00000000..3014637a --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopPopupOffline.qml @@ -0,0 +1,43 @@ +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 + closePolicy: Popup.NoAutoClose + 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 + color: Material.foreground + text: qsTr("You need to run Steam for this :)") + } + + Button { + anchors { + horizontalCenter: parent.horizontalCenter + top: txtOffline.bottom + } + highlighted: true + text: qsTr("Back") + onClicked: { + ScreenPlay.util.setNavigation("Installed") + popupOffline.close() + } + } +} diff --git a/ScreenPlay/qml/Workshop/WorkshopWrapper.qml b/ScreenPlay/qml/Workshop/WorkshopWrapper.qml new file mode 100644 index 00000000..f404f24a --- /dev/null +++ b/ScreenPlay/qml/Workshop/WorkshopWrapper.qml @@ -0,0 +1,417 @@ +import QtQuick 2.13 +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/" + +Item { + id: workshop + state: "base" + anchors.fill: parent + onVisibleChanged: { + if (!visible) + workshopItemDetail.close() + } + + Component.onCompleted: { + if (Workshop.steamWorkshop.online) { + Workshop.steamWorkshop.workshopListModel.searchWorkshop( + SteamEnums.K_EUGCQuery_RankedByTrend) + } else { + popupOffline.open() + } + } + + Connections { + target: Workshop.steamWorkshop.workshopListModel + function onWorkshopSearched() { + bannerTxt.text = Workshop.steamWorkshop.workshopListModel.getBannerText() + background.backgroundImage = Workshop.steamWorkshop.workshopListModel.getBannerUrl() + banner.bannerWorkshopID = Workshop.steamWorkshop.workshopListModel.getBannerID() + bannerTxtUnderline.numberSubscriber + = Workshop.steamWorkshop.workshopListModel.getBannerAmountSubscriber() + } + } + + WorkshopBackground { + id: background + anchors.fill: parent + } + + WorkshopPopupOffline { + id: popupOffline + } + + UploadProject { + id: popupUploadProject + anchors.centerIn: Overlay.overlay + } + + Flickable { + id: scrollView + anchors.fill: parent + contentWidth: parent.width + contentHeight: gridView.height + header.height + 300 + + onContentYChanged: { + // Calculate parallax scrolling + if (contentY >= 0) { + background.imageOffsetTop = (contentY * -.4) + } else { + background.imageOffsetTop = 0 + } + if (contentY >= (header.height)) { + workshop.state = "scrolling" + } else { + workshop.state = "base" + } + } + + transitions: Transition { + PropertyAnimation { + properties: "y" + easing.type: Easing.InOutQuad + duration: 300 + } + } + + // This wrapper is needed for the parent change + // of the nav. Otherwhise it wont work. Dunno why + Item { + id: wrapper + width: parent.width + height: nav.height + header.height + gridView.height + + WorkshopNavigation { + id: nav + anchors.horizontalCenter: parent.horizontalCenter + onUploadPressed: popupUploadProject.open() + } + + Item { + id: header + height: 440 + anchors { + right: parent.right + left: parent.left + } + + Item { + id: banner + height: 350 + z: 5 + property int bannerWorkshopID + anchors { + top: parent.top + right: parent.right + left: parent.left + } + Image { + id: bannerImg2 + anchors { + right: parent.right + left: parent.left + bottom: parent.bottom + } + height: { + + } + + asynchronous: true + fillMode: Image.PreserveAspectCrop + } + + ColumnLayout { + anchors { + top: parent.top + topMargin: 100 + right: parent.right + left: parent.left + leftMargin: 100 + } + + Text { + id: bannerTxtUnderline + property int numberSubscriber: 0 + text: numberSubscriber + " SUBSCRIBED TO:" + font.pointSize: 12 + color: "white" + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + } + + Text { + id: bannerTxt + text: qsTr("Loading") + font.pointSize: 42 + color: "white" + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + width: 400 + } + + 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...") + Workshop.steamWorkshop.subscribeItem( + Workshop.steamWorkshop.workshopListModel.getBannerID( + )) + } + } + Button { + text: qsTr("Details") + Material.background: Material.accent + Material.foreground: "white" + icon.source: "qrc:/assets/icons/icon_info.svg" + visible: false + onClicked: { + workshopItemDetail.setWorkshopItem( + workshopID, imgUrl, + additionalPreviewUrl, + subscriptionCount) + } + } + } + + MouseArea { + onClicked: Qt.openUrlExternally( + "steam://url/CommunityFilePage/" + + banner.bannerWorkshopID) + height: 30 + width: bannerTxtOpenInSteam.paintedWidth + cursorShape: Qt.PointingHandCursor + Text { + id: bannerTxtOpenInSteam + opacity: .7 + text: qsTr("Open In Steam") + font.pointSize: 10 + color: "white" + font.underline: true + 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: Workshop.steamWorkshop.workshopListModel + anchors { + top: header.bottom + topMargin: 100 + left: parent.left + right: parent.right + leftMargin: 50 + } + + header: Item { + height: 70 + width: parent.width + + Item { + id: searchWrapper + + width: 400 + height: 45 + + anchors { + top: parent.top + left: parent.left + } + + Rectangle { + anchors.fill: parent + color: Material.theme === Material.Light ? "white" : Qt.darker( + Material.background) + opacity: .95 + radius: 3 + } + + TextField { + id: tiSearch + anchors { + top: parent.top + right: parent.right + rightMargin: 10 + bottom: parent.bottom + left: parent.left + leftMargin: 10 + } + placeholderText: qsTr("Search for Wallpaper and Widgets...") + placeholderTextColor: "#666666" + font.pointSize: 10 + font.family: ScreenPlay.settings.font + color: "white" + onTextChanged: timerSearch.restart() + Timer { + id: timerSearch + interval: 300 + onTriggered: Workshop.steamWorkshop.workshopListModel.searchWorkshopByText( + tiSearch.text) + } + } + } + + ComboBox { + id: cbQuerySort + width: 250 + height: searchWrapper.height + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 50 + } + + textRole: "text" + valueRole: "value" + currentIndex: 2 + Layout.preferredHeight: searchWrapper.height + font.family: ScreenPlay.settings.font + onActivated: { + Workshop.steamWorkshop.workshopListModel.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 + name: m_workshopTitle + workshopID: m_workshopID + additionalPreviewUrl: m_additionalPreviewUrl + subscriptionCount: m_subscriptionCount + itemIndex: index + onClicked: { + workshopItemDetail.setWorkshopItem( + workshopID, imgUrl, additionalPreviewUrl, + subscriptionCount) + } + } + + ScrollBar.vertical: ScrollBar { + id: workshopScrollBar + snapMode: ScrollBar.SnapOnRelease + } + } + } + } + + WorkshopItemDetail { + id: workshopItemDetail + topMargin: 60 + } + + states: [ + State { + name: "base" + + ParentChange { + target: nav + parent: wrapper + } + + PropertyChanges { + target: nav + anchors.top: wrapper.top + anchors.topMargin: header.height + width: 800 + state: "base" + } + }, + State { + name: "scrolling" + ParentChange { + target: nav + parent: workshop + } + PropertyChanges { + target: nav + anchors.topMargin: 0 + anchors.top: workshop.top + width: wrapper.width + state: "scrolling" + } + } + ] + + transitions: [ + Transition { + from: "base" + to: "scrolling" + PropertyAnimation { + target: nav + properties: "width" + duration: 100 + } + }, + Transition { + from: "scrolling" + to: "base" + + PropertyAnimation { + target: nav + properties: "width,x,y" + duration: 300 + } + } + ] +} + +/*##^## Designer { + D{i:0;autoSize:true;height:800;width:1366} +} + ##^##*/ + diff --git a/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml b/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml new file mode 100644 index 00000000..3d4b6a3a --- /dev/null +++ b/ScreenPlay/qml/Workshop/upload/PopupSteamWorkshopAgreement.qml @@ -0,0 +1,38 @@ +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 + +Popup { + id: popupSteamWorkshopAgreement + dim: true + width: 1100 + height: 600 + closePolicy: Popup.NoAutoClose + anchors.centerIn: Overlay.overlay + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Material.background + } + + Button { + id:btnAbort + text: qsTr("Abort Upload.") + onClicked: { + + } + } + + Button { + id:btnAgree + text: qsTr("I Agree to the Steam Workshop Agreement") + highlighted: true + Material.background: Material.accent + Material.foreground: "white" + onClicked: { + + } + } +} diff --git a/ScreenPlay/qml/Workshop/upload/UploadProject.qml b/ScreenPlay/qml/Workshop/upload/UploadProject.qml new file mode 100644 index 00000000..ff46f6be --- /dev/null +++ b/ScreenPlay/qml/Workshop/upload/UploadProject.qml @@ -0,0 +1,248 @@ +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 + +Popup { + id: root + width: 1100 + height: 600 + modal: true + dim: true + closePolicy: Popup.NoAutoClose +// anchors.centerIn: Overlay.overlay + onAboutToShow: uploadLoader.sourceComponent = com + onAboutToHide: uploadLoader.sourceComponent = undefined + background: Rectangle { + color: Material.theme === Material.Light ? "white" : Material.background + } + + Loader { + id: uploadLoader + anchors.fill: parent + } + + Connections { + target: uploadLoader.item + function onRequestClosePopup() { + root.close() + } + } + + Connections { + target: SP.Workshop.steamWorkshop.uploadListModel + function onUserNeedsToAcceptWorkshopLegalAgreement() { + popupSteamWorkshopAgreement.open() + } + } + + PopupSteamWorkshopAgreement { + id: popupSteamWorkshopAgreement + } + + Component { + id: com + Item { + id: wrapper + signal requestClosePopup + + Item { + id: headerWrapper + height: 50 + anchors { + top: parent.top + right: parent.right + left: parent.left + margins: 10 + } + + Text { + id: txtHeadline + text: qsTr("Upload Wallpaper/Widgets to Steam") + color: Material.foreground + font.pointSize: 21 + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + } + } + + SwipeView { + id: view + clip: true + currentIndex: 0 + anchors { + top: headerWrapper.bottom + right: parent.right + bottom: parent.bottom + left: parent.left + margins: 10 + } + interactive: false + + Item { + id: firstPage + + GridView { + id: gridView + boundsBehavior: Flickable.DragOverBounds + maximumFlickVelocity: 7000 + flickDeceleration: 5000 + cellWidth: parent.width + cellHeight: 250 + clip: true + model: SP.Workshop.installedListModel + anchors { + top: parent.top + right: parent.right + bottom: btnAbort.top + left: parent.left + margins: 10 + } + delegate: UploadProjectBigItem { + id: delegate + focus: true + width: gridView.cellWidth - 30 + customTitle: screenTitle + type: screenType + screenId: screenFolderId + absoluteStoragePath: screenAbsoluteStoragePath + workshopID: screenWorkshopID + preview: screenPreview + itemIndex: index + onItemClicked: { + for (let childItem in gridView.contentItem.children) { + if (gridView.contentItem.children[childItem].isSelected) { + btnUploadProjects.enabled = true + return + } + } + btnUploadProjects.enabled = false + } + } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + policy: ScrollBar.AlwaysOn + } + } + Button { + id:btnAbort + text: qsTr("Abort") + onClicked: { + SP.Workshop.steamWorkshop.uploadListModel.clear() + wrapper.requestClosePopup() + } + + anchors { + right: btnUploadProjects.left + bottom: parent.bottom + margins: 10 + } + } + + Button { + id: btnUploadProjects + text: qsTr("Upload Projects") + highlighted: true + enabled: false + 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 + SP.Workshop.steamWorkshop.bulkUploadToWorkshop( + uploadListArray) + } + } + } + Item { + id: secondPage + + ListView { + id: listView + boundsBehavior: Flickable.DragOverBounds + maximumFlickVelocity: 7000 + flickDeceleration: 5000 + cacheBuffer: 1000 + clip: true + model: SP.Workshop.steamWorkshop.uploadListModel + width: parent.width - 50 + spacing: 25 + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + margins: 10 + } + + delegate: UploadProjectItem { + + previewImagePath: _absolutePreviewImagePath + progress: _uploadProgress + name: _name + steamStatus: _status + } + + ScrollBar.vertical: ScrollBar { + snapMode: ScrollBar.SnapOnRelease + } + } + + Button { + id: btnFinish + text: qsTr("Finish") + onClicked: { + SP.Workshop.steamWorkshop.uploadListModel.clear() + wrapper.requestClosePopup() + } + highlighted: true + enabled: false + anchors { + right: parent.right + bottom: parent.bottom + margins: 10 + } + Connections { + target: SP.Workshop.steamWorkshop.uploadListModel + function onUploadCompleted() { + btnFinish.enabled = true + } + } + } + } + + + } + + PageIndicator { + id: indicator + + count: view.count + currentIndex: view.currentIndex + + anchors.bottom: view.bottom + anchors.horizontalCenter: parent.horizontalCenter + } + } + } +} diff --git a/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml b/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml new file mode 100644 index 00000000..fbc688dd --- /dev/null +++ b/ScreenPlay/qml/Workshop/upload/UploadProjectBigItem.qml @@ -0,0 +1,211 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Material 2.12 +import QtQuick.Layouts 1.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" + property string absoluteStoragePath: "" + property string screenId: "" + property string preview: "" + property string type: "" + property bool hasMenuOpen: false + property int workshopID: 0 + property int itemIndex + signal itemClicked(var screenId, var type, var isActive) + + onTypeChanged: { + 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" +// } +// } + + Rectangle { + id: screenPlayItemWrapper + color: Material.theme === Material.Light ? "white" : Qt.darker( + Material.background) + anchors.fill: parent + anchors.margins: 20 + + Item { + id: itemWrapper + width: parent.width + height: parent.height + clip: true + + Image { + id: screenPlayItemImage + width: 400 + 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 { + anchors { + top: parent.top + right: parent.right + left: screenPlayItemImage.right + margins: 20 + } + spacing: 10 + + Text { + id: name + text: screenTitle + color: Material.foreground + font.pointSize: 18 + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + } + + Text { + text: qsTr("Type: ") + screenType + color: Material.foreground + font.family: ScreenPlay.settings.font + } + } + + Button { + text: qsTr("Open Folder") + onClicked: ScreenPlay.util.openFolderInExplorer( + screenAbsoluteStoragePath) + anchors { + right: parent.right + bottom: parent.bottom + margins: 20 + } + } + + Rectangle { + id: rctInvalid + anchors.fill: parent + color: screenPlayItemWrapper.color + opacity: 0 + visible: false + } + + Text { + id: txtInvalidError + text: qsTr("Invalid Project!") + color: Material.color(Material.Red) + anchors.fill: screenPlayItemImage + font.pointSize: 18 + font.family: ScreenPlay.settings.font + font.weight: Font.Thin + opacity: 0 + } + } + + CheckBox { + id: checkBox + onCheckStateChanged: { + if (checkState == Qt.Checked) { + isSelected = true + } else { + isSelected = false + } + itemClicked(screenId, type, isSelected) + } + + anchors { + top: parent.top + right: parent.right + margins: 10 + } + } + } + + states: [ + State { + name: "selected" + + PropertyChanges { + target: screenPlayItemWrapper + y: 0 + opacity: 1 + } + PropertyChanges { + target: icnType + opacity: .5 + } + }, + State { + name: "invalid" + + PropertyChanges { + target: checkBox + enabled: false + } + PropertyChanges { + target: txtInvalidError + opacity: 1 + } + + PropertyChanges { + target: rctInvalid + opacity: .8 + visible: true + } + } + ] + transitions: [ + 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 new file mode 100644 index 00000000..92c88a7b --- /dev/null +++ b/ScreenPlay/qml/Workshop/upload/UploadProjectItem.qml @@ -0,0 +1,534 @@ +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 + +Page { + id: root + background: Rectangle { + color: "#333333" + // color: Material.theme === Material.Light ? Material.background : Qt.darker( + // Material.background) + radius: 3 + } + + padding: 20 + height: 240 + + 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) { + case SteamEnums.K_EResultNone: + root.contentItem.state = "uploadComplete" + return + // Everyting that is not OK is a fail. See steam_qt_enums_generated.h + 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 { + anchors.fill: parent + state: "base" + 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 + color: "#DD000000" + } + GradientStop { + id: gradientStop1 + position: 1.0 + 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 + color: "white" + font.pointSize: 18 + Layout.preferredHeight: 30 + Layout.fillWidth: true + } + + Text { + id: txtStatus + property string statusText: "Loading..." + text: qsTr("Status:") + " " + statusText + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + color: "white" + font.pointSize: 14 + Layout.preferredHeight: 30 + } + + Item { + Layout.preferredHeight: 60 + Layout.fillWidth: true + } + ColumnLayout { + spacing: 10 + Layout.fillWidth: true + Text { + text: qsTr("Upload Progress: ") + " " + Math.ceil( + root.progress * 100) + "%" + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + + color: "white" + font.pointSize: 14 + height: 50 + } + + ProgressBar { + id: progressBar + Layout.fillWidth: true + value: root.progress + } + } + } + + states: [ + + State { + name: "uploading" + PropertyChanges {} + }, + State { + name: "uploadComplete" + PropertyChanges { + target: gradient + opacity: .7 + } + PropertyChanges { + target: gradient + opacity: .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 + } + PropertyChanges { + target: gradientStop0 + color: Material.color(Material.Red) + } + PropertyChanges { + target: gradientStop1 + color: Material.color(Material.DeepOrange) + } + } + ] + transitions: [ + Transition { + from: "base" + to: "uploading" + + PropertyAnimation { + targets: [gradient, gradientStop0, gradientStop1] + duration: 500 + } + } + ] + } +} + +/*##^## +Designer { + D{i:0;height:240;width:800} +} +##^##*/ +