Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_FileBasedDocument.cpp 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. FileBasedDocument::FileBasedDocument (const String& fileExtension_,
  21. const String& fileWildcard_,
  22. const String& openFileDialogTitle_,
  23. const String& saveFileDialogTitle_)
  24. : fileExtension (fileExtension_),
  25. fileWildcard (fileWildcard_),
  26. openFileDialogTitle (openFileDialogTitle_),
  27. saveFileDialogTitle (saveFileDialogTitle_)
  28. {
  29. }
  30. FileBasedDocument::~FileBasedDocument()
  31. {
  32. }
  33. //==============================================================================
  34. void FileBasedDocument::setChangedFlag (bool hasChanged)
  35. {
  36. if (changedSinceSave != hasChanged)
  37. {
  38. changedSinceSave = hasChanged;
  39. sendChangeMessage();
  40. }
  41. }
  42. void FileBasedDocument::changed()
  43. {
  44. changedSinceSave = true;
  45. sendChangeMessage();
  46. }
  47. //==============================================================================
  48. void FileBasedDocument::setFile (const File& newFile)
  49. {
  50. if (documentFile != newFile)
  51. {
  52. documentFile = newFile;
  53. changed();
  54. }
  55. }
  56. //==============================================================================
  57. Result FileBasedDocument::loadFrom (const File& newFile, bool showMessageOnFailure, bool showWaitCursor)
  58. {
  59. if (showWaitCursor)
  60. MouseCursor::showWaitCursor();
  61. auto oldFile = documentFile;
  62. documentFile = newFile;
  63. auto result = Result::fail (TRANS("The file doesn't exist"));
  64. if (newFile.existsAsFile())
  65. {
  66. result = loadDocument (newFile);
  67. if (result.wasOk())
  68. {
  69. setChangedFlag (false);
  70. if (showWaitCursor)
  71. MouseCursor::hideWaitCursor();
  72. setLastDocumentOpened (newFile);
  73. return result;
  74. }
  75. }
  76. documentFile = oldFile;
  77. if (showWaitCursor)
  78. MouseCursor::hideWaitCursor();
  79. if (showMessageOnFailure)
  80. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  81. TRANS("Failed to open file..."),
  82. TRANS("There was an error while trying to load the file: FLNM")
  83. .replace ("FLNM", "\n" + newFile.getFullPathName())
  84. + "\n\n"
  85. + result.getErrorMessage());
  86. return result;
  87. }
  88. #if JUCE_MODAL_LOOPS_PERMITTED
  89. Result FileBasedDocument::loadFromUserSpecifiedFile (const bool showMessageOnFailure)
  90. {
  91. FileChooser fc (openFileDialogTitle,
  92. getLastDocumentOpened(),
  93. fileWildcard);
  94. if (fc.browseForFileToOpen())
  95. return loadFrom (fc.getResult(), showMessageOnFailure);
  96. return Result::fail (TRANS("User cancelled"));
  97. }
  98. static bool askToOverwriteFile (const File& newFile)
  99. {
  100. return AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
  101. TRANS("File already exists"),
  102. TRANS("There's already a file called: FLNM")
  103. .replace ("FLNM", newFile.getFullPathName())
  104. + "\n\n"
  105. + TRANS("Are you sure you want to overwrite it?"),
  106. TRANS("Overwrite"),
  107. TRANS("Cancel"));
  108. }
  109. //==============================================================================
  110. FileBasedDocument::SaveResult FileBasedDocument::save (bool askUserForFileIfNotSpecified,
  111. bool showMessageOnFailure)
  112. {
  113. return saveAs (documentFile,
  114. false,
  115. askUserForFileIfNotSpecified,
  116. showMessageOnFailure);
  117. }
  118. FileBasedDocument::SaveResult FileBasedDocument::saveAs (const File& newFile,
  119. bool warnAboutOverwritingExistingFiles,
  120. bool askUserForFileIfNotSpecified,
  121. bool showMessageOnFailure,
  122. bool showWaitCursor)
  123. {
  124. if (newFile == File())
  125. {
  126. if (askUserForFileIfNotSpecified)
  127. return saveAsInteractive (true);
  128. // can't save to an unspecified file
  129. jassertfalse;
  130. return failedToWriteToFile;
  131. }
  132. if (warnAboutOverwritingExistingFiles
  133. && newFile.exists()
  134. && ! askToOverwriteFile (newFile))
  135. return userCancelledSave;
  136. if (showWaitCursor)
  137. MouseCursor::showWaitCursor();
  138. auto oldFile = documentFile;
  139. documentFile = newFile;
  140. auto result = saveDocument (newFile);
  141. if (result.wasOk())
  142. {
  143. setChangedFlag (false);
  144. if (showWaitCursor)
  145. MouseCursor::hideWaitCursor();
  146. sendChangeMessage(); // because the filename may have changed
  147. return savedOk;
  148. }
  149. documentFile = oldFile;
  150. if (showWaitCursor)
  151. MouseCursor::hideWaitCursor();
  152. if (showMessageOnFailure)
  153. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  154. TRANS("Error writing to file..."),
  155. TRANS("An error occurred while trying to save \"DCNM\" to the file: FLNM")
  156. .replace ("DCNM", getDocumentTitle())
  157. .replace ("FLNM", "\n" + newFile.getFullPathName())
  158. + "\n\n"
  159. + result.getErrorMessage());
  160. sendChangeMessage(); // because the filename may have changed
  161. return failedToWriteToFile;
  162. }
  163. FileBasedDocument::SaveResult FileBasedDocument::saveIfNeededAndUserAgrees()
  164. {
  165. if (! hasChangedSinceSaved())
  166. return savedOk;
  167. auto r = AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon,
  168. TRANS("Closing document..."),
  169. TRANS("Do you want to save the changes to \"DCNM\"?")
  170. .replace ("DCNM", getDocumentTitle()),
  171. TRANS("Save"),
  172. TRANS("Discard changes"),
  173. TRANS("Cancel"));
  174. if (r == 1) // save changes
  175. return save (true, true);
  176. if (r == 2) // discard changes
  177. return savedOk;
  178. return userCancelledSave;
  179. }
  180. File FileBasedDocument::getSuggestedSaveAsFile (const File& defaultFile)
  181. {
  182. return defaultFile.withFileExtension (fileExtension).getNonexistentSibling (true);
  183. }
  184. FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (bool warnAboutOverwritingExistingFiles)
  185. {
  186. auto f = documentFile.existsAsFile() ? documentFile : getLastDocumentOpened();
  187. auto legalFilename = File::createLegalFileName (getDocumentTitle());
  188. if (legalFilename.isEmpty())
  189. legalFilename = "unnamed";
  190. if (f.existsAsFile() || f.getParentDirectory().isDirectory())
  191. f = f.getSiblingFile (legalFilename);
  192. else
  193. f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename);
  194. f = getSuggestedSaveAsFile (f);
  195. FileChooser fc (saveFileDialogTitle, f, fileWildcard);
  196. if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles))
  197. {
  198. auto chosen = fc.getResult();
  199. if (chosen.getFileExtension().isEmpty())
  200. {
  201. chosen = chosen.withFileExtension (fileExtension);
  202. if (chosen.exists() && ! askToOverwriteFile (chosen))
  203. return userCancelledSave;
  204. }
  205. setLastDocumentOpened (chosen);
  206. return saveAs (chosen, false, false, true);
  207. }
  208. return userCancelledSave;
  209. }
  210. #endif
  211. } // namespace juce