Revision control

++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++
++ import QtQuick
++ import QtQuick.Controls
++ import QtQuick3D.MaterialEditor
++
++ Dialog {
++ id: root
++ title: qsTr("Unsaved changes")
++ modal: true
++
++ required property MaterialAdapter materialAdapter
++ required property var saveAsDialog
++
++ function doIfChangesSavedOrDiscarded(actionFunction) {
++ if (!materialAdapter.unsavedChanges) {
++ actionFunction()
++ return
++ }
++
++ // There are unsaved changes, so we need to prompt.
++
++ function disconnectSaveChangesSignals() {
++ root.accepted.disconnect(saveChanges)
++ root.discarded.disconnect(discardChanges)
++ root.rejected.disconnect(cancel)
++ }
++
++ function saveChanges() {
++ if (materialAdapter.materialSaveFile.toString().length > 0) {
++ // Existing project; can save without a dialog.
++ if (materialAdapter.save()) {
++ // Saved successfully, so now we can perform the action.
++ performAction()
++ } else {
++ // Failed to save; cancel.
++ cancel()
++ }
++ } else {
++ // New project; need to save as.
++ function disconnectSaveAsSignals() {
++ materialAdapter.errorOccurred.disconnect(saveAsFailed)
++ materialAdapter.postMaterialSaved.disconnect(saveAsSucceeded)
++ saveAsDialog.rejected.disconnect(saveAsDialogRejected)
++ }
++
++ function saveAsSucceeded() {
++ disconnectSaveAsSignals()
++ performAction()
++ }
++
++ function saveAsFailed() {
++ disconnectSaveAsSignals()
++ disconnectSaveChangesSignals()
++ }
++
++ function saveAsDialogRejected() {
++ disconnectSaveAsSignals()
++ cancel()
++ }
++
++ materialAdapter.errorOccurred.connect(saveAsFailed)
++ materialAdapter.postMaterialSaved.connect(saveAsSucceeded)
++ saveAsDialog.rejected.connect(saveAsDialogRejected)
++
++ saveAsDialog.open()
++ }
++ }
++
++ function discardChanges() {
++ performAction()
++ root.close()
++ }
++
++ function performAction() {
++ disconnectSaveChangesSignals()
++ actionFunction()
++ }
++
++ function cancel() {
++ disconnectSaveChangesSignals()
++ }
++
++ root.accepted.connect(saveChanges)
++ root.discarded.connect(discardChanges)
++ root.rejected.connect(cancel)
++ root.open()
++ }
++
++ Label {
++ text: qsTr("Save changes to the material before closing?")
++ }
++
++ // Using a DialogButtonBox allows us to assign objectNames to the buttons,
++ // which makes it possible to test them.
++ footer: DialogButtonBox {
++ Button {
++ objectName: "cancelDialogButton"
++ text: qsTr("Cancel")
++ DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
++ }
++ Button {
++ objectName: "saveChangesDialogButton"
++ text: qsTr("Save")
++ DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
++ }
++ Button {
++ objectName: "discardChangesDialogButton"
++ text: qsTr("Don't save")
++ DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
++ }
++ }
++ }