diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt
index 004a00fe..f1007ed0 100644
--- a/ScreenPlay/CMakeLists.txt
+++ b/ScreenPlay/CMakeLists.txt
@@ -231,6 +231,7 @@ set(RESOURCES
assets/icons/icon_sort-up-solid.svg
assets/icons/icon_sort-down-solid.svg
assets/icons/brand_reddit.svg
+ assets/icons/icon_import_export_.svg
assets/icons/steam_default_avatar.png
assets/macos/app.screenplay.plist
assets/icons/item_banner_new.svg
diff --git a/ScreenPlay/assets/icons/icon_import_export_.svg b/ScreenPlay/assets/icons/icon_import_export_.svg
new file mode 100644
index 00000000..5db7d8f3
--- /dev/null
+++ b/ScreenPlay/assets/icons/icon_import_export_.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ScreenPlay/inc/public/ScreenPlay/util.h b/ScreenPlay/inc/public/ScreenPlay/util.h
index 5a5c1f70..59850a4e 100644
--- a/ScreenPlay/inc/public/ScreenPlay/util.h
+++ b/ScreenPlay/inc/public/ScreenPlay/util.h
@@ -88,14 +88,15 @@ class Util : public QObject {
QML_ELEMENT
Q_PROPERTY(QString debugMessages READ debugMessages NOTIFY debugMessagesChanged)
+ Q_PROPERTY(QArchive::DiskCompressor* compressor READ compressor NOTIFY compressorChanged)
+ Q_PROPERTY(QArchive::DiskExtractor* extractor READ extractor NOTIFY extractorChanged)
public:
explicit Util(QNetworkAccessManager* networkAccessManager, QObject* parent = nullptr);
- QString debugMessages() const
- {
- return m_debugMessages;
- }
+ QString debugMessages() const { return m_debugMessages; }
+ QArchive::DiskCompressor* compressor() const { return m_compressor.get(); }
+ QArchive::DiskExtractor* extractor() const { return m_extractor.get(); }
signals:
void requestNavigation(QString nav);
@@ -105,13 +106,15 @@ signals:
void allLicenseLoaded(QString licensesText);
void allDataProtectionLoaded(QString dataProtectionText);
void debugMessagesChanged(QString debugMessages);
+ void compressorChanged(QArchive::DiskCompressor* compressor);
+ void extractorChanged(QArchive::DiskExtractor* extractor);
public slots:
void copyToClipboard(const QString& text) const;
void openFolderInExplorer(const QString& url) const;
QString toLocal(const QString& url);
- bool exportProject(QString& contentPath, QString& exportPath);
- bool importProject(QString& archivePath, QString& extractionPath);
+ bool exportProject(QString& contentPath, QString& exportFileName);
+ bool importProject(QString& archivePath, QString extractionPath);
void requestAllLicenses();
void requestDataProtection();
@@ -148,6 +151,22 @@ public slots:
emit debugMessagesChanged(m_debugMessages);
}
+ void setCompressor(QArchive::DiskCompressor* compressor)
+ {
+ if (m_compressor.get() == compressor)
+ return;
+ m_compressor.reset(compressor);
+ emit compressorChanged(m_compressor.get());
+ }
+
+ void setExtractor(QArchive::DiskExtractor* extractor)
+ {
+ if (m_extractor.get() == extractor)
+ return;
+ m_extractor.reset(extractor);
+ emit extractorChanged(m_extractor.get());
+ }
+
private:
QNetworkAccessManager* m_networkAccessManager { nullptr };
diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml
index c47607dc..65f691be 100644
--- a/ScreenPlay/qml/Installed/Installed.qml
+++ b/ScreenPlay/qml/Installed/Installed.qml
@@ -19,7 +19,7 @@ Item {
property bool enabled: true
property Sidebar sidebar
-
+ property Item modalSource
signal setNavigationItem(var pos)
signal setSidebarActive(var active)
@@ -284,7 +284,7 @@ Item {
MenuItem {
text: qsTr("Export")
objectName: enabled ? "removeItem" : "removeWorkshopItem"
- icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_download.svg"
+ icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_import_export_.svg"
onClicked: {
exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath
let urlFileName = Labs.StandardPaths.writableLocation(
@@ -301,6 +301,7 @@ Item {
objectName: enabled ? "removeItem" : "removeWorkshopItem"
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_delete.svg"
enabled: contextMenu.publishedFileID === 0
+ || !App.settings.steamVersion
onClicked: {
deleteDialog.open()
}
@@ -309,6 +310,7 @@ Item {
MenuItem {
text: qsTr("Open Workshop Page")
enabled: contextMenu.publishedFileID !== 0
+ && App.settings.steamVersion
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg"
onClicked: {
Qt.openUrlExternally(
@@ -316,36 +318,13 @@ Item {
}
}
}
- Labs.FileDialog {
- id: exportFileDialog
- fileMode: FileDialog.SaveFile
- property string absoluteStoragePath
- onAccepted: {
- const success = App.util.exportProject(
- exportFileDialog.absoluteStoragePath,
- exportFileDialog.currentFile)
- }
-
- Dialog {
- id: exportFileProgressDialog
- modal: true
- anchors.centerIn: Overlay.overlay
- standardButtons: Dialog.Ok
- onAccepted: errorDialog.close()
-
- ProgressBar {
- id: exportFileProgressBar
- anchors.centerIn: parent
- }
- }
- }
-
- Dialog {
+ Util.Dialog {
id: deleteDialog
title: qsTr("Are you sure you want to delete this item?")
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
dim: true
+ modalSource: root.modalSource
anchors.centerIn: Overlay.overlay
onAccepted: {
root.sidebar.clear()
@@ -354,6 +333,59 @@ Item {
}
}
+ Labs.FileDialog {
+ id: exportFileDialog
+ fileMode: FileDialog.SaveFile
+ property string absoluteStoragePath
+ onAccepted: {
+ exportFileProgressDialog.open()
+ }
+ }
+
+ Util.Dialog {
+ id: exportFileProgressDialog
+ modal: true
+ anchors.centerIn: Overlay.overlay
+ width: 400
+ focus: true
+ modalSource: root.modalSource
+ closePolicy: Popup.NoAutoClose
+ onOpened: {
+ const success = App.util.exportProject(
+ exportFileDialog.absoluteStoragePath,
+ exportFileDialog.currentFile)
+ }
+ onClosed: exportProgressBar.value = 0
+ ColumnLayout {
+ width: parent.width
+ spacing: 20
+
+ Text {
+ text: qsTr("Export Content...")
+ color: Material.primaryTextColor
+ font.pointSize: 18
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ }
+ ProgressBar {
+ id: exportProgressBar
+ from: 0
+ to: 100
+ Layout.alignment: Qt.AlignHCenter
+ }
+ }
+ Connections {
+ id: exportConnections
+ target: App.util.compressor
+ function onProgress(file, proc, total, br, bt) {
+ exportProgressBar.value = (br * 100 / bt)
+ }
+ function onFinished() {
+ exportFileProgressDialog.close()
+ }
+ }
+ }
+
InstalledNavigation {
id: navWrapper
@@ -376,17 +408,17 @@ Item {
dropArea.enabled = false
if (drop.urls.length > 1) {
- errorDialog.title = qsTr(
+ importProjectErrorDialog.title = qsTr(
"We only support adding one item at once.")
- errorDialog.open()
+ importProjectErrorDialog.open()
return
}
var file = "" // Convert url to string
file = "" + drop.urls[0]
if (!file.endsWith('.screenplay')) {
- errorDialog.title = qsTr(
+ importProjectErrorDialog.title = qsTr(
"File type not supported. We only support '.screenplay' files.")
- errorDialog.open()
+ importProjectErrorDialog.open()
return
}
importDialog.open()
@@ -396,30 +428,54 @@ Item {
dropPopup.close()
}
- Dialog {
- id: errorDialog
+ Util.Dialog {
+ id: importProjectErrorDialog
modal: true
+ modalSource: root.modalSource
anchors.centerIn: Overlay.overlay
standardButtons: Dialog.Ok
- onAccepted: errorDialog.close()
+ onAccepted: importProjectErrorDialog.close()
}
- Dialog {
+ Util.Dialog {
id: importDialog
modal: true
+ modalSource: root.modalSource
anchors.centerIn: Overlay.overlay
- standardButtons: Dialog.Ok
- RowLayout {
- Text {
- text: qsTr("Import Content...")
- }
- }
+ width: 400
+ focus: true
+ closePolicy: Popup.NoAutoClose
+ onClosed: importProgressBar.value = 0
onOpened: {
App.util.importProject(dropArea.filePath,
App.globalVariables.localStoragePath)
dropArea.filePath = ""
}
- onAccepted: {
- importDialog.close()
+ ColumnLayout {
+ width: parent.width
+ spacing: 20
+ Text {
+ text: qsTr("Import Content...")
+ color: Material.primaryTextColor
+ font.pointSize: 18
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ }
+ ProgressBar {
+ id: importProgressBar
+ from: 0
+ to: 100
+ Layout.alignment: Qt.AlignHCenter
+ }
+ Connections {
+ id: importConnections
+ target: App.util.extractor
+ function onProgress(file, proc, total, br, bt) {
+ importProgressBar.value = (br * 100 / bt)
+ }
+ function onFinished() {
+ importDialog.close()
+ }
+ }
}
}
}
diff --git a/ScreenPlay/src/util.cpp b/ScreenPlay/src/util.cpp
index 633ed3cf..4529c946 100644
--- a/ScreenPlay/src/util.cpp
+++ b/ScreenPlay/src/util.cpp
@@ -18,13 +18,13 @@ namespace ScreenPlay {
Util::Util(QNetworkAccessManager* networkAccessManager, QObject* parent)
: QObject(parent)
, m_networkAccessManager { networkAccessManager }
+ , m_extractor { std::make_unique() }
+ , m_compressor { std::make_unique() }
{
utilPointer = this;
// Fix log access vilation on quit
QObject::connect(QGuiApplication::instance(), &QGuiApplication::aboutToQuit, this, []() { utilPointer = nullptr; });
- qmlRegisterUncreatableType("ScreenPlay.QMLUtilities", 1, 0, "QMLUtilities", "Error only for enums");
-
// In release mode redirect messages to logging otherwhise we break the nice clickable output :(
#ifdef QT_NO_DEBUG
qInstallMessageHandler(Util::logToGui);
@@ -108,10 +108,11 @@ QString Util::toLocal(const QString& url)
/*!
\brief Exports a given project into a .screenplay 7Zip file.
*/
-bool Util::exportProject(QString& contentPath, QString& exportPath)
+bool Util::exportProject(QString& contentPath, QString& exportFileName)
{
+ m_compressor->clear();
contentPath = ScreenPlayUtil::toLocal(contentPath);
- exportPath = ScreenPlayUtil::toLocal(exportPath);
+ exportFileName = ScreenPlayUtil::toLocal(exportFileName);
QDir dir(contentPath);
bool success = true;
@@ -123,38 +124,27 @@ bool Util::exportProject(QString& contentPath, QString& exportPath)
for (auto& item : dir.entryInfoList(QDir::Files)) {
files.append(item.absoluteFilePath());
}
- m_compressor = std::make_unique(exportPath);
+ QFile exportFile(exportFileName);
+ if (exportFile.exists()) {
+ if (!exportFile.remove()) {
+ qWarning() << "Unable to delte file marked to override!" << dir;
+ return false;
+ }
+ }
+ m_compressor->setFileName(exportFileName);
m_compressor->setArchiveFormat(QArchive::SevenZipFormat);
m_compressor->addFiles(files);
- /* Connect Signals with Slots (in this case lambda functions). */
- QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::started, [&]() {
- qInfo() << "[+] Starting Compressor... ";
- });
- QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::finished, [&]() {
- qInfo() << "[+] Compressed File(s) Successfully!";
-
- return;
- });
- QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::error, [&](short code, QString file) {
- qInfo() << "[-] An error has occured :: " << QArchive::errorCodeToString(code) << " :: " << file;
-
- return;
- });
-
- QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::progress, [&](QString file, int proc, int total, qint64 br, qint64 bt) {
- qInfo() << "Progress::" << file << ":: Done ( " << proc << " / " << total << ") " << (br * 100 / bt) << "%.";
- return;
- });
-
m_compressor->start();
return true;
}
/*!
- \brief Imports a given project from a .screenplay zip file.
+ \brief Imports a given project from a .screenplay zip file. The argument extractionPath
+ must be copied otherwise it will get reset in qml before extracting.
*/
-bool Util::importProject(QString& archivePath, QString& extractionPath)
+bool Util::importProject(QString& archivePath, QString extractionPath)
{
+ m_extractor->clear();
archivePath = ScreenPlayUtil::toLocal(archivePath);
extractionPath = ScreenPlayUtil::toLocal(extractionPath);
@@ -179,33 +169,8 @@ bool Util::importProject(QString& archivePath, QString& extractionPath)
return false;
}
- m_extractor = std::make_unique(archivePath, extractionPath);
-
- QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::started, [&]() {
- qInfo() << "[+] Starting Extractor... ";
- });
- QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::finished, [&]() {
- qInfo() << "[+] Extracted File(s) Successfully!";
- return;
- });
- QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::error, [&](short code) {
- if (code == QArchive::ArchivePasswordNeeded || code == QArchive::ArchivePasswordIncorrect) {
- return;
- }
- qInfo() << "[-] An error has occured :: " << QArchive::errorCodeToString(code);
- return;
- });
- QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::info, [&](QJsonObject info) {
- qInfo() << "ARCHIVE CONTENTS:: " << info;
- return;
- });
-
- QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::progress,
- [&](QString file, int proc, int total, qint64 br, qint64 bt) {
- qInfo() << "Progress(" << proc << "/" << total << "): "
- << file << " : " << (br * 100 / bt) << "% done.";
- });
-
+ m_extractor->setArchive(archivePath);
+ m_extractor->setOutputDirectory(extractionPath);
m_extractor->setCalculateProgress(true);
m_extractor->getInfo();
m_extractor->start();