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.

267 lines
8.9KB

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