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.

295 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI 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. #ifndef JUCE_FILEBASEDDOCUMENT_H_INCLUDED
  18. #define JUCE_FILEBASEDDOCUMENT_H_INCLUDED
  19. //==============================================================================
  20. /**
  21. A class to take care of the logic involved with the loading/saving of some kind
  22. of document.
  23. There's quite a lot of tedious logic involved in writing all the load/save/save-as
  24. functions you need for documents that get saved to a file, so this class attempts
  25. to abstract most of the boring stuff.
  26. Your subclass should just implement all the pure virtual methods, and you can
  27. then use the higher-level public methods to do the load/save dialogs, to warn the user
  28. about overwriting files, etc.
  29. The document object keeps track of whether it has changed since it was last saved or
  30. loaded, so when you change something, call its changed() method. This will set a
  31. flag so it knows it needs saving, and will also broadcast a change message using the
  32. ChangeBroadcaster base class.
  33. @see ChangeBroadcaster
  34. */
  35. class JUCE_API FileBasedDocument : public ChangeBroadcaster
  36. {
  37. public:
  38. /** Creates a FileBasedDocument.
  39. @param fileExtension the extension to use when loading/saving files, e.g. ".doc"
  40. @param fileWildCard the wildcard to use in file dialogs, e.g. "*.doc"
  41. @param openFileDialogTitle the title to show on an open-file dialog, e.g. "Choose a file to open.."
  42. @param saveFileDialogTitle the title to show on an save-file dialog, e.g. "Choose a file to save as.."
  43. */
  44. FileBasedDocument (const String& fileExtension,
  45. const String& fileWildCard,
  46. const String& openFileDialogTitle,
  47. const String& saveFileDialogTitle);
  48. /** Destructor. */
  49. virtual ~FileBasedDocument();
  50. //==============================================================================
  51. /** Returns true if the changed() method has been called since the file was
  52. last saved or loaded.
  53. @see setChangedFlag, changed
  54. */
  55. bool hasChangedSinceSaved() const { return changedSinceSave; }
  56. /** Called to indicate that the document has changed and needs saving.
  57. This method will also trigger a change message to be sent out using the
  58. ChangeBroadcaster base class.
  59. After calling the method, the hasChangedSinceSaved() method will return true, until
  60. it is reset either by saving to a file or using the setChangedFlag() method.
  61. @see hasChangedSinceSaved, setChangedFlag
  62. */
  63. virtual void changed();
  64. /** Sets the state of the 'changed' flag.
  65. The 'changed' flag is set to true when the changed() method is called - use this method
  66. to reset it or to set it without also broadcasting a change message.
  67. @see changed, hasChangedSinceSaved
  68. */
  69. void setChangedFlag (bool hasChanged);
  70. //==============================================================================
  71. /** Tries to open a file.
  72. If the file opens correctly, the document's file (see the getFile() method) is set
  73. to this new one; if it fails, the document's file is left unchanged, and optionally
  74. a message box is shown telling the user there was an error.
  75. @returns A result indicating whether the new file loaded successfully, or the error
  76. message if it failed.
  77. @see loadDocument, loadFromUserSpecifiedFile
  78. */
  79. Result loadFrom (const File& fileToLoadFrom,
  80. bool showMessageOnFailure);
  81. /** Asks the user for a file and tries to load it.
  82. This will pop up a dialog box using the title, file extension and
  83. wildcard specified in the document's constructor, and asks the user
  84. for a file. If they pick one, the loadFrom() method is used to
  85. try to load it, optionally showing a message if it fails.
  86. @returns a result indicating success; This will be a failure message if the user
  87. cancelled or if they picked a file which failed to load correctly
  88. @see loadFrom
  89. */
  90. Result loadFromUserSpecifiedFile (bool showMessageOnFailure);
  91. //==============================================================================
  92. /** A set of possible outcomes of one of the save() methods
  93. */
  94. enum SaveResult
  95. {
  96. savedOk = 0, /**< indicates that a file was saved successfully. */
  97. userCancelledSave, /**< indicates that the user aborted the save operation. */
  98. failedToWriteToFile /**< indicates that it tried to write to a file but this failed. */
  99. };
  100. /** Tries to save the document to the last file it was saved or loaded from.
  101. This will always try to write to the file, even if the document isn't flagged as
  102. having changed.
  103. @param askUserForFileIfNotSpecified if there's no file currently specified and this is
  104. true, it will prompt the user to pick a file, as if
  105. saveAsInteractive() was called.
  106. @param showMessageOnFailure if true it will show a warning message when if the
  107. save operation fails
  108. @see saveIfNeededAndUserAgrees, saveAs, saveAsInteractive
  109. */
  110. SaveResult save (bool askUserForFileIfNotSpecified,
  111. bool showMessageOnFailure);
  112. /** If the file needs saving, it'll ask the user if that's what they want to do, and save
  113. it if they say yes.
  114. If you've got a document open and want to close it (e.g. to quit the app), this is the
  115. method to call.
  116. If the document doesn't need saving it'll return the value savedOk so
  117. you can go ahead and delete the document.
  118. If it does need saving it'll prompt the user, and if they say "discard changes" it'll
  119. return savedOk, so again, you can safely delete the document.
  120. If the user clicks "cancel", it'll return userCancelledSave, so if you can abort the
  121. close-document operation.
  122. And if they click "save changes", it'll try to save and either return savedOk, or
  123. failedToWriteToFile if there was a problem.
  124. @see save, saveAs, saveAsInteractive
  125. */
  126. SaveResult saveIfNeededAndUserAgrees();
  127. /** Tries to save the document to a specified file.
  128. If this succeeds, it'll also change the document's internal file (as returned by
  129. the getFile() method). If it fails, the file will be left unchanged.
  130. @param newFile the file to try to write to
  131. @param warnAboutOverwritingExistingFiles if true and the file exists, it'll ask
  132. the user first if they want to overwrite it
  133. @param askUserForFileIfNotSpecified if the file is non-existent and this is true, it'll
  134. use the saveAsInteractive() method to ask the user for a
  135. filename
  136. @param showMessageOnFailure if true and the write operation fails, it'll show
  137. a message box to warn the user
  138. @see saveIfNeededAndUserAgrees, save, saveAsInteractive
  139. */
  140. SaveResult saveAs (const File& newFile,
  141. bool warnAboutOverwritingExistingFiles,
  142. bool askUserForFileIfNotSpecified,
  143. bool showMessageOnFailure);
  144. /** Prompts the user for a filename and tries to save to it.
  145. This will pop up a dialog box using the title, file extension and
  146. wildcard specified in the document's constructor, and asks the user
  147. for a file. If they pick one, the saveAs() method is used to try to save
  148. to this file.
  149. @param warnAboutOverwritingExistingFiles if true and the file exists, it'll ask
  150. the user first if they want to overwrite it
  151. @see saveIfNeededAndUserAgrees, save, saveAs
  152. */
  153. SaveResult saveAsInteractive (bool warnAboutOverwritingExistingFiles);
  154. //==============================================================================
  155. /** Returns the file that this document was last successfully saved or loaded from.
  156. When the document object is created, this will be set to File::nonexistent.
  157. It is changed when one of the load or save methods is used, or when setFile()
  158. is used to explicitly set it.
  159. */
  160. const File& getFile() const { return documentFile; }
  161. /** Sets the file that this document thinks it was loaded from.
  162. This won't actually load anything - it just changes the file stored internally.
  163. @see getFile
  164. */
  165. void setFile (const File& newFile);
  166. protected:
  167. //==============================================================================
  168. /** Overload this to return the title of the document.
  169. This is used in message boxes, filenames and file choosers, so it should be
  170. something sensible.
  171. */
  172. virtual String getDocumentTitle() = 0;
  173. /** This method should try to load your document from the given file.
  174. @returns a Result object to indicate the whether there was an error.
  175. */
  176. virtual Result loadDocument (const File& file) = 0;
  177. /** This method should try to write your document to the given file.
  178. @returns a Result object to indicate the whether there was an error.
  179. */
  180. virtual Result saveDocument (const File& file) = 0;
  181. /** This is used for dialog boxes to make them open at the last folder you
  182. were using.
  183. getLastDocumentOpened() and setLastDocumentOpened() are used to store
  184. the last document that was used - you might want to store this value
  185. in a static variable, or even in your application's properties. It should
  186. be a global setting rather than a property of this object.
  187. This method works very well in conjunction with a RecentlyOpenedFilesList
  188. object to manage your recent-files list.
  189. As a default value, it's ok to return File::nonexistent, and the document
  190. object will use a sensible one instead.
  191. @see RecentlyOpenedFilesList
  192. */
  193. virtual File getLastDocumentOpened() = 0;
  194. /** This is used for dialog boxes to make them open at the last folder you
  195. were using.
  196. getLastDocumentOpened() and setLastDocumentOpened() are used to store
  197. the last document that was used - you might want to store this value
  198. in a static variable, or even in your application's properties. It should
  199. be a global setting rather than a property of this object.
  200. This method works very well in conjunction with a RecentlyOpenedFilesList
  201. object to manage your recent-files list.
  202. @see RecentlyOpenedFilesList
  203. */
  204. virtual void setLastDocumentOpened (const File& file) = 0;
  205. #if JUCE_MODAL_LOOPS_PERMITTED
  206. /** This is called by saveAsInteractive() to allow you to optionally customise the
  207. filename that the user is presented with in the save dialog.
  208. The defaultFile parameter is an initial suggestion based on what the class knows
  209. about the current document - you can return a variation on this file with a different
  210. extension, etc, or just return something completely different.
  211. */
  212. virtual File getSuggestedSaveAsFile (const File& defaultFile);
  213. #endif
  214. private:
  215. //==============================================================================
  216. File documentFile;
  217. bool changedSinceSave;
  218. String fileExtension, fileWildcard, openFileDialogTitle, saveFileDialogTitle;
  219. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileBasedDocument)
  220. };
  221. #endif // JUCE_FILEBASEDDOCUMENT_H_INCLUDED