The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

263 lines
8.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. FileBasedDocument::FileBasedDocument (const String& fileExtension_,
  18. const String& fileWildcard_,
  19. const String& openFileDialogTitle_,
  20. const String& saveFileDialogTitle_)
  21. : changedSinceSave (false),
  22. fileExtension (fileExtension_),
  23. fileWildcard (fileWildcard_),
  24. openFileDialogTitle (openFileDialogTitle_),
  25. saveFileDialogTitle (saveFileDialogTitle_)
  26. {
  27. }
  28. FileBasedDocument::~FileBasedDocument()
  29. {
  30. }
  31. //==============================================================================
  32. void FileBasedDocument::setChangedFlag (const bool hasChanged)
  33. {
  34. if (changedSinceSave != hasChanged)
  35. {
  36. changedSinceSave = hasChanged;
  37. sendChangeMessage();
  38. }
  39. }
  40. void FileBasedDocument::changed()
  41. {
  42. changedSinceSave = true;
  43. sendChangeMessage();
  44. }
  45. //==============================================================================
  46. void FileBasedDocument::setFile (const File& newFile)
  47. {
  48. if (documentFile != newFile)
  49. {
  50. documentFile = newFile;
  51. changed();
  52. }
  53. }
  54. //==============================================================================
  55. #if JUCE_MODAL_LOOPS_PERMITTED
  56. bool FileBasedDocument::loadFrom (const File& newFile,
  57. const bool showMessageOnFailure)
  58. {
  59. MouseCursor::showWaitCursor();
  60. const File oldFile (documentFile);
  61. documentFile = newFile;
  62. Result result (Result::fail ("The file doesn't exist"));
  63. if (newFile.existsAsFile())
  64. {
  65. result = loadDocument (newFile);
  66. if (result.wasOk())
  67. {
  68. setChangedFlag (false);
  69. MouseCursor::hideWaitCursor();
  70. setLastDocumentOpened (newFile);
  71. return true;
  72. }
  73. }
  74. documentFile = oldFile;
  75. MouseCursor::hideWaitCursor();
  76. if (showMessageOnFailure)
  77. {
  78. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  79. TRANS("Failed to open file..."),
  80. TRANS("There was an error while trying to load the file: FLNM")
  81. .replace ("FLNM", "\n" + newFile.getFullPathName())
  82. + "\n\n"
  83. + result.getErrorMessage());
  84. }
  85. return false;
  86. }
  87. bool FileBasedDocument::loadFromUserSpecifiedFile (const bool showMessageOnFailure)
  88. {
  89. FileChooser fc (openFileDialogTitle,
  90. getLastDocumentOpened(),
  91. fileWildcard);
  92. if (fc.browseForFileToOpen())
  93. return loadFrom (fc.getResult(), showMessageOnFailure);
  94. return false;
  95. }
  96. static bool askToOverwriteFile (const File& newFile)
  97. {
  98. return AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
  99. TRANS("File already exists"),
  100. TRANS("There's already a file called: FLMN")
  101. .replace ("FLNM", newFile.getFullPathName())
  102. + "\n\n"
  103. + TRANS("Are you sure you want to overwrite it?"),
  104. TRANS("Overwrite"),
  105. TRANS("Cancel"));
  106. }
  107. //==============================================================================
  108. FileBasedDocument::SaveResult FileBasedDocument::save (const bool askUserForFileIfNotSpecified,
  109. const bool showMessageOnFailure)
  110. {
  111. return saveAs (documentFile,
  112. false,
  113. askUserForFileIfNotSpecified,
  114. showMessageOnFailure);
  115. }
  116. FileBasedDocument::SaveResult FileBasedDocument::saveAs (const File& newFile,
  117. const bool warnAboutOverwritingExistingFiles,
  118. const bool askUserForFileIfNotSpecified,
  119. const bool showMessageOnFailure)
  120. {
  121. if (newFile == File::nonexistent)
  122. {
  123. if (askUserForFileIfNotSpecified)
  124. return saveAsInteractive (true);
  125. // can't save to an unspecified file
  126. jassertfalse;
  127. return failedToWriteToFile;
  128. }
  129. if (warnAboutOverwritingExistingFiles
  130. && newFile.exists()
  131. && ! askToOverwriteFile (newFile))
  132. return userCancelledSave;
  133. MouseCursor::showWaitCursor();
  134. const File oldFile (documentFile);
  135. documentFile = newFile;
  136. const Result result (saveDocument (newFile));
  137. if (result.wasOk())
  138. {
  139. setChangedFlag (false);
  140. MouseCursor::hideWaitCursor();
  141. return savedOk;
  142. }
  143. documentFile = oldFile;
  144. MouseCursor::hideWaitCursor();
  145. if (showMessageOnFailure)
  146. {
  147. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  148. TRANS("Error writing to file..."),
  149. TRANS("An error occurred while trying to save \"DCNM\" to the file: FLNM")
  150. .replace ("DCNM", getDocumentTitle())
  151. .replace ("FLNM", "\n" + newFile.getFullPathName())
  152. + "\n\n"
  153. + result.getErrorMessage());
  154. }
  155. return failedToWriteToFile;
  156. }
  157. FileBasedDocument::SaveResult FileBasedDocument::saveIfNeededAndUserAgrees()
  158. {
  159. if (! hasChangedSinceSaved())
  160. return savedOk;
  161. const int r = AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon,
  162. TRANS("Closing document..."),
  163. TRANS("Do you want to save the changes to \"DCNM\"?")
  164. .replace ("DCNM", getDocumentTitle()),
  165. TRANS("Save"),
  166. TRANS("Discard changes"),
  167. TRANS("Cancel"));
  168. if (r == 1) // save changes
  169. return save (true, true);
  170. if (r == 2) // discard changes
  171. return savedOk;
  172. return userCancelledSave;
  173. }
  174. File FileBasedDocument::getSuggestedSaveAsFile (const File& defaultFile)
  175. {
  176. return defaultFile.withFileExtension (fileExtension).getNonexistentSibling (true);
  177. }
  178. FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool warnAboutOverwritingExistingFiles)
  179. {
  180. File f;
  181. if (documentFile.existsAsFile())
  182. f = documentFile;
  183. else
  184. f = getLastDocumentOpened();
  185. String legalFilename (File::createLegalFileName (getDocumentTitle()));
  186. if (legalFilename.isEmpty())
  187. legalFilename = "unnamed";
  188. if (f.existsAsFile() || f.getParentDirectory().isDirectory())
  189. f = f.getSiblingFile (legalFilename);
  190. else
  191. f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename);
  192. f = getSuggestedSaveAsFile (f);
  193. FileChooser fc (saveFileDialogTitle, f, fileWildcard);
  194. if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles))
  195. {
  196. File chosen (fc.getResult());
  197. if (chosen.getFileExtension().isEmpty())
  198. {
  199. chosen = chosen.withFileExtension (fileExtension);
  200. if (chosen.exists() && ! askToOverwriteFile (chosen))
  201. return userCancelledSave;
  202. }
  203. setLastDocumentOpened (chosen);
  204. return saveAs (chosen, false, false, true);
  205. }
  206. return userCancelledSave;
  207. }
  208. #endif