SaveChangesDialog.qml 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (C) 2021 The Qt Company Ltd.
  2. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
  3. import QtQuick
  4. import QtQuick.Controls
  5. import QtQuick3D.MaterialEditor
  6. Dialog {
  7. id: root
  8. title: qsTr("Unsaved changes")
  9. modal: true
  10. required property MaterialAdapter materialAdapter
  11. required property var saveAsDialog
  12. function doIfChangesSavedOrDiscarded(actionFunction) {
  13. if (!materialAdapter.unsavedChanges) {
  14. actionFunction()
  15. return
  16. }
  17. // There are unsaved changes, so we need to prompt.
  18. function disconnectSaveChangesSignals() {
  19. root.accepted.disconnect(saveChanges)
  20. root.discarded.disconnect(discardChanges)
  21. root.rejected.disconnect(cancel)
  22. }
  23. function saveChanges() {
  24. if (materialAdapter.materialSaveFile.toString().length > 0) {
  25. // Existing project; can save without a dialog.
  26. if (materialAdapter.save()) {
  27. // Saved successfully, so now we can perform the action.
  28. performAction()
  29. } else {
  30. // Failed to save; cancel.
  31. cancel()
  32. }
  33. } else {
  34. // New project; need to save as.
  35. function disconnectSaveAsSignals() {
  36. materialAdapter.errorOccurred.disconnect(saveAsFailed)
  37. materialAdapter.postMaterialSaved.disconnect(saveAsSucceeded)
  38. saveAsDialog.rejected.disconnect(saveAsDialogRejected)
  39. }
  40. function saveAsSucceeded() {
  41. disconnectSaveAsSignals()
  42. performAction()
  43. }
  44. function saveAsFailed() {
  45. disconnectSaveAsSignals()
  46. disconnectSaveChangesSignals()
  47. }
  48. function saveAsDialogRejected() {
  49. disconnectSaveAsSignals()
  50. cancel()
  51. }
  52. materialAdapter.errorOccurred.connect(saveAsFailed)
  53. materialAdapter.postMaterialSaved.connect(saveAsSucceeded)
  54. saveAsDialog.rejected.connect(saveAsDialogRejected)
  55. saveAsDialog.open()
  56. }
  57. }
  58. function discardChanges() {
  59. performAction()
  60. root.close()
  61. }
  62. function performAction() {
  63. disconnectSaveChangesSignals()
  64. actionFunction()
  65. }
  66. function cancel() {
  67. disconnectSaveChangesSignals()
  68. }
  69. root.accepted.connect(saveChanges)
  70. root.discarded.connect(discardChanges)
  71. root.rejected.connect(cancel)
  72. root.open()
  73. }
  74. Label {
  75. text: qsTr("Save changes to the material before closing?")
  76. }
  77. // Using a DialogButtonBox allows us to assign objectNames to the buttons,
  78. // which makes it possible to test them.
  79. footer: DialogButtonBox {
  80. Button {
  81. objectName: "cancelDialogButton"
  82. text: qsTr("Cancel")
  83. DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
  84. }
  85. Button {
  86. objectName: "saveChangesDialogButton"
  87. text: qsTr("Save")
  88. DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
  89. }
  90. Button {
  91. objectName: "discardChangesDialogButton"
  92. text: qsTr("Don't save")
  93. DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
  94. }
  95. }
  96. }