1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-09-14 22:42:34 +02:00

Add workshop as QPlugin

This commit is contained in:
Elias Steurer 2020-08-20 17:21:09 +02:00
parent 5fcc4be4ab
commit 33995204b2
27 changed files with 3266 additions and 6 deletions

View File

@ -100,5 +100,20 @@
<file>legal/lgpl-2.1.txt</file>
<file>assets/icons/icon_delete.svg</file>
<file>assets/icons/app.ico</file>
<file>assets/icons/icon_supervisor_account.svg</file>
<file>assets/icons/icon_new_releases.svg</file>
<file>assets/icons/icon_report_problem.svg</file>
<file>assets/icons/icon_help_center.svg</file>
<file>assets/icons/icon_forum.svg</file>
<file>assets/icons/icon_thumb_up.svg</file>
<file>assets/icons/icon_thumb_down.svg</file>
<file>assets/icons/icon_cake.afdesign</file>
<file>assets/icons/icon_window.svg</file>
<file>assets/WorkshopPreview.html</file>
<file>assets/images/ava.png</file>
<file>assets/images/mask.svg</file>
<file>assets/images/mask_workshop.png</file>
<file>assets/images/Untitled.png</file>
<file>assets/images/window.svg</file>
</qresource>
</RCC>

View File

@ -124,8 +124,6 @@ App::App()
// ScreenPlayManager first to check if another ScreenPlay Instace is running
m_screenPlayManager = std::make_unique<ScreenPlayManager>();
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<ScreenPlayWorkshopPlugin*>(m_workshopPlugin.instance());
return true;
}
}

View File

@ -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<QQmlApplicationEngine> m_mainWindowEngine;
std::unique_ptr<Create> m_create;

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<body>
<script>
let body = document.getElementsByTagName('body')[0];
body.setAttribute('style', 'margin: 0px;padding: 0px;overflow: hidden;background:black;');
let html = document.getElementsByTagName('html')[0];
html.setAttribute('style', 'margin: 0px;padding: 0px;overflow: hidden;background:black;');
var videoElem = document.createElement('VIDEO');
videoElem.setAttribute('width', '100%');
videoElem.setAttribute('height', '100%');
videoElem.setAttribute('id', 'video');
videoElem.muted = true;
videoElem.autoplay = true;
videoElem.loop = true;
document.body.appendChild(videoElem);
</script>
</body>
</html>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M24 24H0V0h24v24z" fill="none"/><path d="M22 4h-2c-.55 0-1 .45-1 1v9c0 .55.45 1 1 1h2V4zM2.17 11.12c-.11.25-.17.52-.17.8V13c0 1.1.9 2 2 2h5.5l-.92 4.65c-.05.22-.02.46.08.66.23.45.52.86.88 1.22L10 22l6.41-6.41c.38-.38.59-.89.59-1.42V6.34C17 5.05 15.95 4 14.66 4h-8.1c-.71 0-1.36.37-1.72.97l-2.67 6.15z"/></svg>

After

Width:  |  Height:  |  Size: 401 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M24 24H0V0h24v24z" fill="none"/><path d="M2 20h2c.55 0 1-.45 1-1v-9c0-.55-.45-1-1-1H2v11zm19.83-7.12c.11-.25.17-.52.17-.8V11c0-1.1-.9-2-2-2h-5.5l.92-4.65c.05-.22.02-.46-.08-.66-.23-.45-.52-.86-.88-1.22L14 2 7.59 8.41C7.21 8.79 7 9.3 7 9.83v7.84C7 18.95 8.05 20 9.34 20h8.11c.7 0 1.36-.37 1.72-.97l2.66-6.15z"/></svg>

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 120 120" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><circle cx="60" cy="60" r="59.5" style="fill:#fff;"/></svg>

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -58,5 +58,20 @@
<file>assets/icons/icon_report_problem.svg</file>
<file>assets/icons/icon_help_center.svg</file>
<file>assets/icons/icon_forum.svg</file>
<file>qml/Workshop/ScreenPlayItem.qml</file>
<file>qml/Workshop/ScreenPlayItemImage.qml</file>
<file>qml/Workshop/WorkshopAlertBanner.qml</file>
<file>qml/Workshop/WorkshopBackground.qml</file>
<file>qml/Workshop/WorkshopBanner.qml</file>
<file>qml/Workshop/WorkshopInstalled.qml</file>
<file>qml/Workshop/WorkshopItem.qml</file>
<file>qml/Workshop/WorkshopItemDetail.qml</file>
<file>qml/Workshop/WorkshopNavigation.qml</file>
<file>qml/Workshop/WorkshopPopupOffline.qml</file>
<file>qml/Workshop/WorkshopWrapper.qml</file>
<file>qml/Workshop/upload/PopupSteamWorkshopAgreement.qml</file>
<file>qml/Workshop/upload/UploadProject.qml</file>
<file>qml/Workshop/upload/UploadProjectBigItem.qml</file>
<file>qml/Workshop/upload/UploadProjectItem.qml</file>
</qresource>
</RCC>

View File

@ -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
}
}
]
}

View File

@ -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
}
}
]
}

View File

@ -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
}
}

View File

@ -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
}
}
]
}

View File

@ -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"
}
}
]
}

View File

@ -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
}
}
}

View File

@ -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"
}
]
}

View File

@ -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"
}
}
}
]
}

View File

@ -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}
}
##^##*/

View File

@ -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
}
}
]
}

View File

@ -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()
}
}
}

View File

@ -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}
}
##^##*/

View File

@ -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: {
}
}
}

View File

@ -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
}
}
}
}

View File

@ -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}
}
##^##*/

View File

@ -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}
}
##^##*/