diff --git a/ScreenPlay/Resources.qrc b/ScreenPlay/Resources.qrc index ecf38fe4..2752c17e 100644 --- a/ScreenPlay/Resources.qrc +++ b/ScreenPlay/Resources.qrc @@ -113,7 +113,6 @@ settings.json translations/ScreenPlay_de.qm translations/ScreenPlay_en.qm - qml/Create/Wizards/CreateWallpaper/NextButton.qml qml/Screen/Screen.qml assets/icons/icon_screen.svg qml/Background.qml @@ -122,5 +121,8 @@ qml/Workshop/WorkshopLoader.qml qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml qml/Create/Wizards/CreateWallpaper/CreateWallpaperResult.qml + qml/Common/TagSelector.qml + qml/Common/Tag.qml + assets/icons/icon_close.svg diff --git a/ScreenPlay/assets/icons/icon_close.svg b/ScreenPlay/assets/icons/icon_close.svg new file mode 100644 index 00000000..48bd9c5d --- /dev/null +++ b/ScreenPlay/assets/icons/icon_close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/qml/Common/Tag.qml b/ScreenPlay/qml/Common/Tag.qml new file mode 100644 index 00000000..c80d3770 --- /dev/null +++ b/ScreenPlay/qml/Common/Tag.qml @@ -0,0 +1,87 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Controls.Material 2.3 + +Item { + id: tag + width: textMetrics.width + 20 + height: parent.height + + property int itemIndex + property alias text: txt.text + signal removeThis(var index) + + Rectangle { + id: rectangle + radius: 3 + + anchors.fill: parent + + Text { + id: txt + text: _name + color: Material.color(Material.Grey) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + TextField { + id: textField + enabled: false + opacity: 0 + anchors.fill: parent + anchors.margins: 10 + anchors.bottomMargin: 0 + } + + TextMetrics { + id: textMetrics + text: txt.text + font.pointSize: 14 + font.family: "Roboto" + } + } + MouseArea { + id: ma + width: 10 + height: width + cursorShape: Qt.PointingHandCursor + anchors { + top: parent.top + right: parent.right + margins: 5 + } + onClicked: { + tag.removeThis(itemIndex) + } + + Image { + id: name + anchors.fill: parent + source: "qrc:/assets/icons/icon_close.svg" + } + } + + states: [ + State { + name: "edit" + + PropertyChanges { + target: txt + opacity: 0 + } + + PropertyChanges { + target: textField + opacity: 1 + enabled: true + } + } + ] +} + +/*##^## Designer { + D{i:0;height:50;width:100} +} + ##^##*/ + diff --git a/ScreenPlay/qml/Common/TagSelector.qml b/ScreenPlay/qml/Common/TagSelector.qml new file mode 100644 index 00000000..8ba27aa0 --- /dev/null +++ b/ScreenPlay/qml/Common/TagSelector.qml @@ -0,0 +1,180 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtGraphicalEffects 1.0 +import QtQuick.Controls.Material 2.12 + +Item { + id: tagSelector + height: 70 + onStateChanged: { + if (tagSelector.state === "add") { + btnAdd.text = qsTr("Save") + textField.focus = true + } else { + btnAdd.text = qsTr("Add tag") + } + } + + function getTags(){ + var array = []; + for(var i = 0; i < listModel.count; i++) { + array.push(listModel.get(i)._name) + } + return array + } + + Rectangle { + id: rectangle + color: "#F0F0F0" + radius: 3 + clip: true + anchors { + fill: parent + margins: 3 + } + + ListView { + orientation: ListView.Horizontal + model: listModel + spacing: 10 + anchors { + top: parent.top + right: btnAdd.left + bottom: parent.bottom + left: parent.left + margins: 10 + } + + delegate: Tag { + id: delegate + text: _name + itemIndex: index + + Connections { + target: delegate + onRemoveThis: { + listModel.remove(itemIndex) + } + } + } + } + + ListModel { + id: listModel + onCountChanged: getTags() + } + + Rectangle { + id: textFieldWrapper + opacity: 0 + enabled: false + radius: 3 + height: parent.height - 20 + width: 200 + color: "#aaffffff" + anchors { + top: parent.top + topMargin: -80 + right: btnCancel.left + margins: 10 + } + Gradient { + GradientStop { + position: 0.0 + color: "#00000000" + } + GradientStop { + position: 1.0 + color: "#FF000000" + } + } + + TextField { + id: textField + anchors.fill: parent + anchors.rightMargin: 15 + anchors.leftMargin: 15 + onTextChanged: { + if(textField.length >= 10){ + textField.text = textField.text + } + } + } + } + + Button { + id: btnCancel + text: qsTr("Cancel") + opacity: 0 + enabled: false + Material.background: Material.Red + Material.foreground: "white" + anchors { + right: btnAdd.left + rightMargin: 10 + verticalCenter: parent.verticalCenter + } + + onClicked: { + tagSelector.state = "" + textField.clear() + } + } + Button { + id: btnAdd + text: qsTr("Add Tag") + Material.background: Material.LightGreen + Material.foreground: "white" + anchors { + right: parent.right + rightMargin: 20 + verticalCenter: parent.verticalCenter + } + + onClicked: { + if (tagSelector.state === "add") { + listModel.append({ + "_name": textField.text + }) + textField.clear() + tagSelector.state = "" + } else { + tagSelector.state = "add" + } + } + } + } + + states: [ + + State { + name: "add" + + PropertyChanges { + target: textFieldWrapper + color: "#ccffffff" + anchors.topMargin: 10 + opacity: 1 + enabled: true + } + + PropertyChanges { + target: btnCancel + opacity: 1 + enabled: true + } + } + ] + transitions: [ + Transition { + from: "" + to: "add" + reversible: true + NumberAnimation { + properties: "anchors.topMargin, opacity" + duration: 200 + easing.type: Easing.OutQuart + } + } + ] +} diff --git a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml b/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml index 1cfd1e57..7960d88d 100644 --- a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/CreateWallpaper/CreateWallpaperVideoImportConvert.qml @@ -7,13 +7,69 @@ import QtQuick.Layouts 1.12 import net.aimber.create 1.0 +import "../../../Common" + Item { id: wrapperContent property bool conversionFinishedSuccessful: false property bool canSave: false + onCanSaveChanged: wrapperContent.checkCanSave() signal save + function checkCanSave() { + if (canSave && conversionFinishedSuccessful) { + btnSave.enabled = true + } else { + btnSave.enabled = false + } + } + + Connections { + target: screenPlayCreate + + onCreateWallpaperStateChanged: { + if (state === CreateImportVideo.State.ConvertingPreviewImageFinished) { + imgPreview.source = "file:///" + screenPlayCreate.workingDir + "/preview.png" + imgPreview.visible = true + txtConvert.text = qsTr("Converting Video preview mp4") + } + + if (state === CreateImportVideo.State.ConvertingPreviewVideo) { + txtConvert.text = qsTr("Generating preview video...") + } + + if (state === CreateImportVideo.State.ConvertingPreviewGif) { + txtConvert.text = qsTr("Generating preview gif...") + } + + if (state === CreateImportVideo.State.ConvertingPreviewGifFinished) { + imgPreview.source = "file:///" + screenPlayCreate.workingDir + "/preview.gif" + imgPreview.visible = true + imgPreview.playing = true + } + if (state === CreateImportVideo.State.ConvertingAudio) { + txtConvert.text = qsTr("Converting Audio...") + } + if (state === CreateImportVideo.State.ConvertingVideo) { + txtConvert.text = qsTr("Converting Video...") + } + + if (state === CreateImportVideo.State.Finished) { + txtConvert.text = "" + conversionFinishedSuccessful = true + busyIndicator.running = false + wrapperContent.checkCanSave() + } + } + onProgressChanged: { + var percentage = Math.floor(progress * 100) + if (percentage > 100) + percentage = 100 + txtConvertNumber.text = percentage + "%" + } + } + Text { id: txtHeadline text: qsTr("Convert a video to a wallpaper") @@ -45,13 +101,12 @@ Item { id: imgWrapper width: 425 height: 247 + color: Material.color(Material.Grey) anchors { top: parent.top left: parent.left } - color: Material.color(Material.Grey) - AnimatedImage { id: imgPreview asynchronous: true @@ -89,52 +144,6 @@ Item { bottomMargin: 20 } } - - Connections { - target: screenPlayCreate - - onCreateWallpaperStateChanged: { - if (state === CreateImportVideo.State.ConvertingPreviewImageFinished) { - imgPreview.source = "file:///" - + screenPlayCreate.workingDir + "/preview.png" - imgPreview.visible = true - txtConvert.text = qsTr("Converting Video preview mp4") - } - - if (state === CreateImportVideo.State.ConvertingPreviewVideo) { - txtConvert.text = qsTr("Generating preview video...") - } - - if (state === CreateImportVideo.State.ConvertingPreviewGif) { - txtConvert.text = qsTr("Generating preview gif...") - } - - if (state === CreateImportVideo.State.ConvertingPreviewGifFinished) { - imgPreview.source = "file:///" - + screenPlayCreate.workingDir + "/preview.gif" - imgPreview.visible = true - imgPreview.playing = true - } - if (state === CreateImportVideo.State.ConvertingAudio) { - txtConvert.text = qsTr("Converting Audio...") - } - if (state === CreateImportVideo.State.ConvertingVideo) { - txtConvert.text = qsTr("Converting Video...") - } - - if (state === CreateImportVideo.State.Finished) { - txtConvert.text = "" - conversionFinishedSuccessful = true - busyIndicator.running = false - } - } - onProgressChanged: { - var percentage = Math.floor(progress * 100) - if (percentage > 100) - percentage = 100 - txtConvertNumber.text = percentage + "%" - } - } } RowLayout { id: row @@ -142,7 +151,6 @@ Item { anchors { top: imgWrapper.bottom topMargin: 20 - right: parent.right rightMargin: 30 left: parent.left @@ -215,7 +223,7 @@ Item { TextField { id: textFieldName - placeholderText: qsTr("Name") + placeholderText: qsTr("Name (required!)") width: parent.width Layout.fillWidth: true onTextChanged: { @@ -241,10 +249,9 @@ Item { Layout.fillWidth: true } - TextField { + TagSelector { id: textFieldTags width: parent.width - placeholderText: qsTr("Tags (seperate with comma)") Layout.fillWidth: true } } @@ -262,7 +269,7 @@ Item { Button { id: btnExit text: qsTr("Abort") - Material.background: Material.Gray + Material.background: Material.Red Material.foreground: "white" onClicked: { screenPlayCreate.abortAndCleanup() @@ -272,27 +279,54 @@ Item { } Button { - id: btnFinish + id: btnSave text: qsTr("Save") - Material.background: Material.Gray + enabled: false + Material.background: Material.Orange Material.foreground: "white" - enabled: { - if (canSave && conversionFinishedSuccessful) { - return true - } else { - return false - } - } onClicked: { if (conversionFinishedSuccessful) { screenPlayCreate.saveWallpaper( - textFieldName.text, textFieldDescription.text, textFieldYoutubeURL.text, textFieldTags.text) + textFieldName.text, + textFieldDescription.text, + textFieldYoutubeURL.text, + textFieldTags.getTags()) + savePopup.open() } } } } } + Popup { + id: savePopup + modal: true + focus: true + width: 250 + anchors.centerIn: parent + height: 200 + onOpened: timerSave.start() + + BusyIndicator { + anchors.centerIn: parent + running: true + } + Text { + text: qsTr("Save Wallpaper...") + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 30 + } + + Timer { + id: timerSave + interval: 3000 - Math.random() * 1000 + onTriggered: { + utility.setNavigationActive(true) + utility.setNavigation("Create") + } + } + } } /*##^## Designer { diff --git a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/NextButton.qml b/ScreenPlay/qml/Create/Wizards/CreateWallpaper/NextButton.qml deleted file mode 100644 index 0898305a..00000000 --- a/ScreenPlay/qml/Create/Wizards/CreateWallpaper/NextButton.qml +++ /dev/null @@ -1,44 +0,0 @@ -import QtQuick 2.12 -import QtGraphicalEffects 1.0 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 -import Qt.labs.platform 1.0 -import QtQuick.Layouts 1.3 - -Button { - id: root - text: qsTr("Next") - state: "disabled" - Material.background: Material.Orange - Material.foreground: "white" - - states: [ - State { - name: "enabled" - PropertyChanges { - target: root - text: qsTr("Finish") - } - }, - State { - name: "disabled" - PropertyChanges { - target: root - text: qsTr("Creating") - Material.background: Material.Grey - } - } - ] -// TODO find a way to smoothly change with on text change -// transitions: [ -// Transition { -// from: "*" -// to: "*" -// NumberAnimation { -// property: "width" -// easing.type: Easing.OutQuart -// duration: 2000 -// } -// } -// ] -} diff --git a/ScreenPlay/src/create.cpp b/ScreenPlay/src/create.cpp index d349c285..f551db22 100644 --- a/ScreenPlay/src/create.cpp +++ b/ScreenPlay/src/create.cpp @@ -80,14 +80,43 @@ void Create::createWallpaperStart(QString videoPath) m_createImportVideoThread->start(); } -void Create::createWallpaperProjectFile(QString name, QString description, QString youtube, QStringList tags) +void Create::saveWallpaper(QString title, QString description, QString youtube, QVector tags) { + qDebug() << tags; + QFile file(m_workingDir + "/project.json"); + + QJsonObject obj; + obj.insert("description", description); + obj.insert("title", title); + obj.insert("file", "video.webm"); + obj.insert("previewGIF", "preview.gif"); + obj.insert("previewWEBM", "preview.webm"); + obj.insert("type", "video"); + + QJsonArray arr; + for (QString tmp : tags) { + arr.append(tmp); + } + obj.insert("tags", arr); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Could not open /project.json"; + return; + } + + QTextStream out(&file); + QJsonDocument doc(obj); + + out << doc.toJson(); + + file.close(); } void Create::abortAndCleanup() { - if (m_createImportVideo != nullptr || m_createImportVideoThread != nullptr) { + if (m_createImportVideo == nullptr || m_createImportVideoThread == nullptr) { + qDebug() << m_createImportVideo << m_createImportVideoThread; return; } diff --git a/ScreenPlay/src/create.h b/ScreenPlay/src/create.h index 259c665f..1ff95bfa 100644 --- a/ScreenPlay/src/create.h +++ b/ScreenPlay/src/create.h @@ -58,7 +58,7 @@ public slots: void copyProject(QString relativeProjectPath, QString toPath); bool copyRecursively(const QString& srcFilePath, const QString& tgtFilePath); void createWallpaperStart(QString videoPath); - void saveWallpaper(QString name, QString description, QString youtube, QString tags); + void saveWallpaper(QString title, QString description, QString youtube, QVector tags); void abortAndCleanup(); void setProgress(float progress)