mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-25 12:13:00 +01:00
Add edit menu entry
This commit is contained in:
parent
99e427b6cb
commit
893844f023
@ -185,6 +185,7 @@ set(RESOURCES
|
||||
assets/icons/icon_widgets.svg
|
||||
assets/icons/icon_window.svg
|
||||
assets/icons/item_banner_new.svg
|
||||
assets/icons/icon_edit.svg
|
||||
assets/icons/monitor_setup.svg
|
||||
assets/icons/steam_default_avatar.png
|
||||
assets/images/Early_Access.png
|
||||
|
@ -58,7 +58,8 @@ class Util : public QObject {
|
||||
Q_PROPERTY(QString debugMessages READ debugMessages NOTIFY debugMessagesChanged)
|
||||
|
||||
public:
|
||||
Util();
|
||||
Util(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables);
|
||||
~Util();
|
||||
|
||||
QString debugMessages() const { return m_debugMessages; }
|
||||
@ -82,6 +83,7 @@ public slots:
|
||||
void openFolderInExplorer(const QString& url) const;
|
||||
QString toLocal(const QString& url) const;
|
||||
bool exportProject(QString contentPath, QString exportFileName);
|
||||
bool openGodotEditor(QString contentPath) const;
|
||||
bool importProject(QString archivePath, QString extractionPath);
|
||||
void requestAllLicenses();
|
||||
void requestDataProtection();
|
||||
@ -124,6 +126,7 @@ private:
|
||||
QFuture<void> m_requestAllLicensesFuture;
|
||||
std::unique_ptr<QArchive::DiskCompressor> m_compressor;
|
||||
std::unique_ptr<QArchive::DiskExtractor> m_extractor;
|
||||
const std::shared_ptr<GlobalVariables>& m_globalVariables;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -34,9 +34,11 @@ namespace ScreenPlay {
|
||||
class Wizards : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("CPP ONLY")
|
||||
public:
|
||||
explicit Wizards(const std::shared_ptr<GlobalVariables>& globalVariables, QObject* parent = nullptr);
|
||||
Wizards() { }
|
||||
explicit Wizards(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables,
|
||||
QObject* parent = nullptr);
|
||||
|
||||
enum class WizardResult {
|
||||
Ok,
|
||||
|
@ -25,23 +25,23 @@ Item {
|
||||
|
||||
function checkIsContentInstalled() {
|
||||
if (App.installedListModel.count === 0) {
|
||||
loaderHelp.active = true;
|
||||
gridView.footerItem.isVisible = true;
|
||||
gridView.visible = false;
|
||||
navWrapper.visible = false;
|
||||
loaderHelp.active = true
|
||||
gridView.footerItem.isVisible = true
|
||||
gridView.visible = false
|
||||
navWrapper.visible = false
|
||||
} else {
|
||||
loaderHelp.active = false;
|
||||
gridView.footerItem.isVisible = false;
|
||||
refresh = false;
|
||||
gridView.contentY = -82;
|
||||
gridView.visible = true;
|
||||
navWrapper.visible = true;
|
||||
loaderHelp.active = false
|
||||
gridView.footerItem.isVisible = false
|
||||
refresh = false
|
||||
gridView.contentY = -82
|
||||
gridView.visible = true
|
||||
navWrapper.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
StackView.onActivated: {
|
||||
navWrapper.state = "in";
|
||||
checkIsContentInstalled();
|
||||
navWrapper.state = "in"
|
||||
checkIsContentInstalled()
|
||||
}
|
||||
|
||||
Action {
|
||||
@ -51,12 +51,12 @@ Item {
|
||||
|
||||
Connections {
|
||||
function onInstalledLoadingFinished() {
|
||||
checkIsContentInstalled();
|
||||
checkIsContentInstalled()
|
||||
}
|
||||
|
||||
function onCountChanged(count) {
|
||||
if (count === 0)
|
||||
checkIsContentInstalled();
|
||||
checkIsContentInstalled()
|
||||
}
|
||||
|
||||
target: App.installedListModel
|
||||
@ -71,7 +71,7 @@ Item {
|
||||
|
||||
Connections {
|
||||
function onSortChanged() {
|
||||
gridView.positionViewAtBeginning();
|
||||
gridView.positionViewAtBeginning()
|
||||
}
|
||||
|
||||
target: App.installedListFilter
|
||||
@ -128,12 +128,12 @@ Item {
|
||||
}
|
||||
onContentYChanged: {
|
||||
if (contentY <= -180)
|
||||
gridView.headerItem.isVisible = true;
|
||||
gridView.headerItem.isVisible = true
|
||||
else
|
||||
gridView.headerItem.isVisible = false;
|
||||
gridView.headerItem.isVisible = false
|
||||
//Pull to refresh
|
||||
if (contentY <= -180 && !refresh && !isDragging)
|
||||
App.installedListModel.reset();
|
||||
App.installedListModel.reset()
|
||||
}
|
||||
|
||||
anchors {
|
||||
@ -150,11 +150,11 @@ Item {
|
||||
opacity: 0
|
||||
onIsVisibleChanged: {
|
||||
if (isVisible) {
|
||||
txtHeader.color = Material.accent;
|
||||
txtHeader.text = qsTr("Refreshing!");
|
||||
txtHeader.color = Material.accent
|
||||
txtHeader.text = qsTr("Refreshing!")
|
||||
} else {
|
||||
txtHeader.color = "gray";
|
||||
txtHeader.text = qsTr("Pull to refresh!");
|
||||
txtHeader.color = "gray"
|
||||
txtHeader.text = qsTr("Pull to refresh!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ Item {
|
||||
interval: 150
|
||||
running: true
|
||||
onTriggered: {
|
||||
animFadeIn.start();
|
||||
animFadeIn.start()
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ Item {
|
||||
interval: 400
|
||||
running: true
|
||||
onTriggered: {
|
||||
animFadeInTxtFooter.start();
|
||||
animFadeInTxtFooter.start()
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,15 +236,23 @@ Item {
|
||||
isScrolling: gridView.isScrolling
|
||||
onOpenContextMenu: function (position) {
|
||||
// Set the menu to the current item informations
|
||||
contextMenu.publishedFileID = delegate.publishedFileID;
|
||||
contextMenu.absoluteStoragePath = delegate.absoluteStoragePath;
|
||||
contextMenu.fileName = delegate.customTitle;
|
||||
const pos = delegate.mapToItem(root, position.x, position.y);
|
||||
contextMenu.publishedFileID = delegate.publishedFileID
|
||||
contextMenu.absoluteStoragePath = delegate.absoluteStoragePath
|
||||
contextMenu.fileName = delegate.customTitle
|
||||
contextMenu.type = delegate.type
|
||||
print(delegate.publishedFileID)
|
||||
if(contextMenu.godotItem)
|
||||
contextMenu.godotItem.destroy()
|
||||
const pos = delegate.mapToItem(root, position.x, position.y)
|
||||
// Disable duplicate opening. The can happen if we
|
||||
// call popup when we are in the closing animtion.
|
||||
if (contextMenu.visible || contextMenu.opened)
|
||||
return;
|
||||
contextMenu.popup(pos.x, pos.y);
|
||||
return
|
||||
if (delegate.type === InstalledType.GodotWallpaper) {
|
||||
contextMenu.godotItem = editGodotWallpaperComp.createObject()
|
||||
contextMenu.insertItem(0, contextMenu.godotItem)
|
||||
}
|
||||
contextMenu.popup(pos.x, pos.y)
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,21 +260,37 @@ Item {
|
||||
snapMode: ScrollBar.SnapOnRelease
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: editGodotWallpaperComp
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Edit Wallpaper")
|
||||
objectName: "editWallpaper"
|
||||
enabled: contextMenu.type === InstalledType.GodotWallpaper
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_edit.svg"
|
||||
onClicked: {
|
||||
App.util.openGodotEditor(contextMenu.absoluteStoragePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
Menu {
|
||||
id: contextMenu
|
||||
objectName: "installedItemContextMenu"
|
||||
// Must be var to support 64-bit size!
|
||||
property var publishedFileID: 0
|
||||
property var type: 0
|
||||
property url absoluteStoragePath
|
||||
property string fileName
|
||||
// We need to dynamically add this menu item
|
||||
// if it is a Godot Wallpaper, see onOpenContextMenu
|
||||
property var godotItem
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Open containing folder")
|
||||
objectName: "openFolder"
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_folder_open.svg"
|
||||
onClicked: {
|
||||
App.util.openFolderInExplorer(contextMenu.absoluteStoragePath);
|
||||
App.util.openFolderInExplorer(contextMenu.absoluteStoragePath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,10 +299,12 @@ Item {
|
||||
objectName: enabled ? "removeItem" : "removeWorkshopItem"
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_import_export_.svg"
|
||||
onClicked: {
|
||||
exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath;
|
||||
let urlFileName = QCore.StandardPaths.writableLocation(QCore.StandardPaths.DesktopLocation) + "/" + contextMenu.fileName + ".screenplay";
|
||||
exportFileDialog.currentFile = urlFileName;
|
||||
exportFileDialog.open();
|
||||
exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath
|
||||
let urlFileName = QCore.StandardPaths.writableLocation(
|
||||
QCore.StandardPaths.DesktopLocation) + "/"
|
||||
+ contextMenu.fileName + ".screenplay"
|
||||
exportFileDialog.currentFile = urlFileName
|
||||
exportFileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,18 +312,21 @@ Item {
|
||||
text: enabled ? qsTr("Remove Item") : qsTr("Remove via Workshop")
|
||||
objectName: enabled ? "removeItem" : "removeWorkshopItem"
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_delete.svg"
|
||||
enabled: contextMenu.publishedFileID === 0 || !App.settings.steamVersion
|
||||
enabled: contextMenu.publishedFileID === 0
|
||||
|| !App.settings.steamVersion
|
||||
onClicked: {
|
||||
deleteDialog.open();
|
||||
deleteDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Open Workshop Page")
|
||||
enabled: contextMenu.publishedFileID !== 0 && App.settings.steamVersion
|
||||
enabled: contextMenu.publishedFileID !== 0
|
||||
&& App.settings.steamVersion
|
||||
icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg"
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("steam://url/CommunityFilePage/" + contextMenu.publishedFileID);
|
||||
Qt.openUrlExternally(
|
||||
"steam://url/CommunityFilePage/" + contextMenu.publishedFileID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,8 +339,9 @@ Item {
|
||||
modalSource: root.modalSource
|
||||
anchors.centerIn: Overlay.overlay
|
||||
onAccepted: {
|
||||
root.sidebar.clear();
|
||||
App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath);
|
||||
root.sidebar.clear()
|
||||
App.installedListModel.deinstallItemAt(
|
||||
contextMenu.absoluteStoragePath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +350,7 @@ Item {
|
||||
fileMode: FileDialog.SaveFile
|
||||
property string absoluteStoragePath
|
||||
onAccepted: {
|
||||
exportFileProgressDialog.open();
|
||||
exportFileProgressDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +363,9 @@ Item {
|
||||
modalSource: root.modalSource
|
||||
closePolicy: Popup.NoAutoClose
|
||||
onOpened: {
|
||||
const success = App.util.exportProject(exportFileDialog.absoluteStoragePath, exportFileDialog.currentFile);
|
||||
const success = App.util.exportProject(
|
||||
exportFileDialog.absoluteStoragePath,
|
||||
exportFileDialog.currentFile)
|
||||
}
|
||||
onClosed: exportProgressBar.value = 0
|
||||
ColumnLayout {
|
||||
@ -358,10 +390,10 @@ Item {
|
||||
id: exportConnections
|
||||
target: App.util
|
||||
function onCompressionProgressChanged(file, proc, total, br, bt) {
|
||||
exportProgressBar.value = (br * 100 / bt);
|
||||
exportProgressBar.value = (br * 100 / bt)
|
||||
}
|
||||
function onCompressionFinished() {
|
||||
exportFileProgressDialog.close();
|
||||
exportFileProgressDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,28 +413,31 @@ Item {
|
||||
anchors.fill: parent
|
||||
property string filePath
|
||||
onEntered: function (drag) {
|
||||
dropPopup.open();
|
||||
dropPopup.open()
|
||||
}
|
||||
onDropped: function (drop) {
|
||||
dropPopup.close();
|
||||
dropArea.enabled = false;
|
||||
dropPopup.close()
|
||||
dropArea.enabled = false
|
||||
if (drop.urls.length > 1) {
|
||||
importProjectErrorDialog.title = qsTr("We only support adding one item at once.");
|
||||
importProjectErrorDialog.open();
|
||||
return;
|
||||
importProjectErrorDialog.title = qsTr(
|
||||
"We only support adding one item at once.")
|
||||
importProjectErrorDialog.open()
|
||||
return
|
||||
}
|
||||
var file = ""; // Convert url to string
|
||||
file = "" + drop.urls[0];
|
||||
var file = ""
|
||||
// Convert url to string
|
||||
file = "" + drop.urls[0]
|
||||
if (!file.endsWith('.screenplay')) {
|
||||
importProjectErrorDialog.title = qsTr("File type not supported. We only support '.screenplay' files.");
|
||||
importProjectErrorDialog.open();
|
||||
return;
|
||||
importProjectErrorDialog.title = qsTr(
|
||||
"File type not supported. We only support '.screenplay' files.")
|
||||
importProjectErrorDialog.open()
|
||||
return
|
||||
}
|
||||
importDialog.open();
|
||||
dropArea.filePath = file;
|
||||
importDialog.open()
|
||||
dropArea.filePath = file
|
||||
}
|
||||
onExited: {
|
||||
dropPopup.close();
|
||||
dropPopup.close()
|
||||
}
|
||||
|
||||
Util.Dialog {
|
||||
@ -423,9 +458,11 @@ Item {
|
||||
closePolicy: Popup.NoAutoClose
|
||||
onClosed: importProgressBar.value = 0
|
||||
onOpened: {
|
||||
const success = App.util.importProject(dropArea.filePath, App.globalVariables.localStoragePath);
|
||||
print("finished", success);
|
||||
dropArea.filePath = "";
|
||||
const success = App.util.importProject(
|
||||
dropArea.filePath,
|
||||
App.globalVariables.localStoragePath)
|
||||
print("finished", success)
|
||||
dropArea.filePath = ""
|
||||
}
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
@ -447,10 +484,10 @@ Item {
|
||||
id: importConnections
|
||||
target: App.util
|
||||
function onExtractionProgressChanged(file, proc, total, br, bt) {
|
||||
importProgressBar.value = (br * 100 / bt);
|
||||
importProgressBar.value = (br * 100 / bt)
|
||||
}
|
||||
function onExtractionFinished() {
|
||||
importDialog.close();
|
||||
importDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -466,8 +503,8 @@ Item {
|
||||
modal: true
|
||||
onOpened: fileDropAnimation.state = "fileDrop"
|
||||
onClosed: {
|
||||
fileDropAnimation.state = "";
|
||||
dropArea.enabled = true;
|
||||
fileDropAnimation.state = ""
|
||||
dropArea.enabled = true
|
||||
}
|
||||
|
||||
Util.FileDropAnimation {
|
||||
|
@ -14,6 +14,7 @@ Item {
|
||||
property string screenId
|
||||
property url absoluteStoragePath
|
||||
property int type: InstalledType.Unknown
|
||||
// Must be var to make it work wit 64bit ints
|
||||
property var publishedFileID: 0
|
||||
property int itemIndex
|
||||
property bool isScrolling: false
|
||||
|
@ -138,10 +138,9 @@ void App::init()
|
||||
|
||||
using std::make_shared, std::make_unique;
|
||||
|
||||
// Util should be created as first so we redirect qDebugs etc. into the log
|
||||
m_util = make_unique<Util>();
|
||||
m_globalVariables = make_shared<GlobalVariables>();
|
||||
m_monitorListModel = make_shared<MonitorListModel>();
|
||||
m_util = make_unique<Util>(m_globalVariables);
|
||||
m_profileListModel = make_shared<ProfileListModel>(m_globalVariables);
|
||||
m_settings = make_shared<Settings>(m_globalVariables);
|
||||
m_installedListModel = make_shared<InstalledListModel>(m_globalVariables, m_settings);
|
||||
|
@ -22,7 +22,9 @@ namespace ScreenPlay {
|
||||
/*!
|
||||
Constructor
|
||||
*/
|
||||
ProfileListModel::ProfileListModel(const std::shared_ptr<GlobalVariables>& globalVariables, QObject* parent)
|
||||
ProfileListModel::ProfileListModel(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables,
|
||||
QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_globalVariables { globalVariables }
|
||||
{
|
||||
|
@ -23,8 +23,10 @@ namespace ScreenPlay {
|
||||
/*!
|
||||
\brief Constructor.
|
||||
*/
|
||||
Util::Util()
|
||||
Util::Util(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables)
|
||||
: QObject(nullptr)
|
||||
, m_globalVariables { globalVariables }
|
||||
{
|
||||
m_extractor = std::make_unique<QArchive::DiskExtractor>();
|
||||
m_compressor = std::make_unique<QArchive::DiskCompressor>();
|
||||
@ -144,6 +146,15 @@ bool Util::exportProject(QString contentPath, QString exportFileName)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Util::openGodotEditor(QString contentPath) const
|
||||
{
|
||||
const QList<QString> godotCmd = { "--editor", "--path", toLocal(contentPath) };
|
||||
QProcess process;
|
||||
process.setProgram(m_globalVariables->godotEditorExecutablePath().toString());
|
||||
process.setArguments(godotCmd);
|
||||
return process.startDetached();
|
||||
}
|
||||
|
||||
/*!
|
||||
\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.
|
||||
|
Loading…
Reference in New Issue
Block a user