2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
23 ==============================================================================
29 //==============================================================================
30 class FileBasedDocument::Pimpl
33 //==============================================================================
34 class SafeParentPointer
37 SafeParentPointer (Pimpl
* parent
, bool isAsync
)
38 : ptr (parent
), shouldCheck (isAsync
)
41 Pimpl
* operator->() const noexcept
46 bool operator== (Pimpl
* object
) const noexcept
{ return ptr
.get() == object
; }
47 bool operator!= (Pimpl
* object
) const noexcept
{ return ptr
.get() != object
; }
49 bool shouldExitAsyncCallback() const noexcept
51 return shouldCheck
&& ptr
== nullptr;
55 WeakReference
<Pimpl
> ptr
;
56 bool shouldCheck
= false;
60 //==============================================================================
61 Pimpl (FileBasedDocument
& parent_
,
62 const String
& fileExtension_
,
63 const String
& fileWildcard_
,
64 const String
& openFileDialogTitle_
,
65 const String
& saveFileDialogTitle_
)
67 fileExtension (fileExtension_
),
68 fileWildcard (fileWildcard_
),
69 openFileDialogTitle (openFileDialogTitle_
),
70 saveFileDialogTitle (saveFileDialogTitle_
)
74 //==============================================================================
75 bool hasChangedSinceSaved() const
77 return changedSinceSave
;
80 void setChangedFlag (bool hasChanged
)
82 if (changedSinceSave
!= hasChanged
)
84 changedSinceSave
= hasChanged
;
85 document
.sendChangeMessage();
91 changedSinceSave
= true;
92 document
.sendChangeMessage();
95 //==============================================================================
96 Result
loadFrom (const File
& newFile
, bool showMessageOnFailure
, bool showWaitCursor
= true)
98 SafeParentPointer parent
{ this, false };
99 auto result
= Result::ok();
100 loadFromImpl (parent
,
102 showMessageOnFailure
,
104 [this] (const File
& file
, const auto& callback
) { callback (document
.loadDocument (file
)); },
105 [&result
] (Result r
) { result
= r
; });
109 void loadFromAsync (const File
& newFile
,
110 bool showMessageOnFailure
,
111 std::function
<void (Result
)> callback
)
113 SafeParentPointer parent
{ this, true };
114 loadFromImpl (parent
,
116 showMessageOnFailure
,
118 [parent
] (const File
& file
, auto cb
)
120 if (parent
!= nullptr)
121 parent
->document
.loadDocumentAsync (file
, std::move (cb
));
123 std::move (callback
));
126 //==============================================================================
127 #if JUCE_MODAL_LOOPS_PERMITTED
128 Result
loadFromUserSpecifiedFile (bool showMessageOnFailure
)
130 FileChooser
fc (openFileDialogTitle
,
131 document
.getLastDocumentOpened(),
134 if (fc
.browseForFileToOpen())
135 return loadFrom (fc
.getResult(), showMessageOnFailure
);
137 return Result::fail (TRANS ("User cancelled"));
141 void loadFromUserSpecifiedFileAsync (const bool showMessageOnFailure
, std::function
<void (Result
)> callback
)
143 asyncFc
= std::make_unique
<FileChooser
> (openFileDialogTitle
,
144 document
.getLastDocumentOpened(),
147 asyncFc
->launchAsync (FileBrowserComponent::openMode
| FileBrowserComponent::canSelectFiles
,
148 [this, showMessageOnFailure
, callback
= std::move (callback
)] (const FileChooser
& fc
)
150 auto chosenFile
= fc
.getResult();
152 if (chosenFile
== File
{})
154 if (callback
!= nullptr)
155 callback (Result::fail (TRANS ("User cancelled")));
160 WeakReference
<Pimpl
> parent
{ this };
161 loadFromAsync (chosenFile
, showMessageOnFailure
, [parent
, callback
] (Result result
)
163 if (parent
!= nullptr && callback
!= nullptr)
171 //==============================================================================
172 #if JUCE_MODAL_LOOPS_PERMITTED
173 FileBasedDocument::SaveResult
save (bool askUserForFileIfNotSpecified
,
174 bool showMessageOnFailure
)
176 return saveAs (documentFile
,
178 askUserForFileIfNotSpecified
,
179 showMessageOnFailure
);
183 void saveAsync (bool askUserForFileIfNotSpecified
,
184 bool showMessageOnFailure
,
185 std::function
<void (SaveResult
)> callback
)
187 saveAsAsync (documentFile
,
189 askUserForFileIfNotSpecified
,
190 showMessageOnFailure
,
191 std::move (callback
));
194 //==============================================================================
195 #if JUCE_MODAL_LOOPS_PERMITTED
196 FileBasedDocument::SaveResult
saveIfNeededAndUserAgrees()
198 SafeParentPointer parent
{ this, false };
200 saveIfNeededAndUserAgreesImpl (parent
,
201 [&result
] (SaveResult r
) { result
= r
; },
202 AskToSaveChangesSync
{ *this },
208 void saveIfNeededAndUserAgreesAsync (std::function
<void (SaveResult
)> callback
)
210 SafeParentPointer parent
{ this, true };
212 saveIfNeededAndUserAgreesImpl (parent
,
213 std::move (callback
),
214 [] (SafeParentPointer ptr
, auto cb
)
217 ptr
->askToSaveChanges (ptr
, std::move (cb
));
219 [parent
] (bool askUserForFileIfNotSpecified
,
220 bool showMessageOnFailure
,
223 if (parent
!= nullptr)
224 parent
->saveAsync (askUserForFileIfNotSpecified
,
225 showMessageOnFailure
,
230 //==============================================================================
231 #if JUCE_MODAL_LOOPS_PERMITTED
232 FileBasedDocument::SaveResult
saveAs (const File
& newFile
,
233 bool warnAboutOverwritingExistingFiles
,
234 bool askUserForFileIfNotSpecified
,
235 bool showMessageOnFailure
,
236 bool showWaitCursor
= true)
238 SafeParentPointer parent
{ this, false };
240 saveAsSyncImpl (parent
,
242 warnAboutOverwritingExistingFiles
,
243 askUserForFileIfNotSpecified
,
244 showMessageOnFailure
,
245 [&result
] (SaveResult r
) { result
= r
; },
251 void saveAsAsync (const File
& newFile
,
252 bool warnAboutOverwritingExistingFiles
,
253 bool askUserForFileIfNotSpecified
,
254 bool showMessageOnFailure
,
255 std::function
<void (SaveResult
)> callback
)
257 SafeParentPointer parent
{ this, true };
258 saveAsAsyncImpl (parent
,
260 warnAboutOverwritingExistingFiles
,
261 askUserForFileIfNotSpecified
,
262 showMessageOnFailure
,
263 std::move (callback
),
267 //==============================================================================
268 #if JUCE_MODAL_LOOPS_PERMITTED
269 FileBasedDocument::SaveResult
saveAsInteractive (bool warnAboutOverwritingExistingFiles
)
271 SafeParentPointer parent
{ this, false };
273 saveAsInteractiveSyncImpl (parent
,
274 warnAboutOverwritingExistingFiles
,
275 [&result
] (SaveResult r
) { result
= r
; });
280 void saveAsInteractiveAsync (bool warnAboutOverwritingExistingFiles
,
281 std::function
<void (SaveResult
)> callback
)
283 SafeParentPointer parent
{ this, true };
284 saveAsInteractiveAsyncImpl (parent
,
285 warnAboutOverwritingExistingFiles
,
286 std::move (callback
));
289 //==============================================================================
290 const File
& getFile() const
295 void setFile (const File
& newFile
)
297 if (documentFile
!= newFile
)
299 documentFile
= newFile
;
304 //==============================================================================
305 const String
& getFileExtension() const
307 return fileExtension
;
311 //==============================================================================
312 template <typename DoLoadDocument
>
313 void loadFromImpl (SafeParentPointer parent
,
315 bool showMessageOnFailure
,
317 DoLoadDocument
&& doLoadDocument
,
318 std::function
<void (Result
)> completed
)
320 if (parent
.shouldExitAsyncCallback())
324 MouseCursor::showWaitCursor();
326 auto oldFile
= documentFile
;
327 documentFile
= newFile
;
329 auto tidyUp
= [parent
, newFile
, oldFile
, showMessageOnFailure
, showWaitCursor
, completed
] (Result result
)
331 if (parent
.shouldExitAsyncCallback())
334 parent
->documentFile
= oldFile
;
337 MouseCursor::hideWaitCursor();
339 if (showMessageOnFailure
)
340 AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon
,
341 TRANS ("Failed to open file..."),
342 TRANS ("There was an error while trying to load the file: FLNM")
343 .replace ("FLNM", "\n" + newFile
.getFullPathName())
345 + result
.getErrorMessage());
347 if (completed
!= nullptr)
351 if (newFile
.existsAsFile())
353 auto afterLoading
= [parent
,
356 completed
= std::move (completed
),
357 tidyUp
] (Result result
)
361 parent
->setChangedFlag (false);
364 MouseCursor::hideWaitCursor();
366 parent
->document
.setLastDocumentOpened (newFile
);
368 if (completed
!= nullptr)
377 doLoadDocument (newFile
, std::move (afterLoading
));
382 tidyUp (Result::fail (TRANS ("The file doesn't exist")));
385 //==============================================================================
386 template <typename DoAskToSaveChanges
, typename DoSave
>
387 void saveIfNeededAndUserAgreesImpl (SafeParentPointer parent
,
388 std::function
<void (SaveResult
)> completed
,
389 DoAskToSaveChanges
&& doAskToSaveChanges
,
392 if (parent
.shouldExitAsyncCallback())
395 if (! hasChangedSinceSaved())
397 if (completed
!= nullptr)
403 auto afterAsking
= [doSave
= std::forward
<DoSave
> (doSave
),
404 completed
= std::move (completed
)] (SafeParentPointer ptr
,
407 if (ptr
.shouldExitAsyncCallback())
412 case 1: // save changes
413 doSave (true, true, [ptr
, completed
] (SaveResult result
)
415 if (ptr
.shouldExitAsyncCallback())
418 if (completed
!= nullptr)
423 case 2: // discard changes
424 if (completed
!= nullptr)
430 if (completed
!= nullptr)
431 completed (userCancelledSave
);
434 doAskToSaveChanges (parent
, std::move (afterAsking
));
437 //==============================================================================
438 int askToSaveChanges (SafeParentPointer parent
,
439 std::function
<void (SafeParentPointer
, int)> callback
)
441 auto* modalCallback
= callback
== nullptr
443 : ModalCallbackFunction::create ([parent
, callback
= std::move (callback
)] (int alertResult
)
445 if (parent
!= nullptr)
446 callback (parent
, alertResult
);
449 return AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon
,
450 TRANS ("Closing document..."),
451 TRANS ("Do you want to save the changes to \"DCNM\"?")
452 .replace ("DCNM", document
.getDocumentTitle()),
454 TRANS ("Discard changes"),
460 //==============================================================================
461 template <typename DoSaveDocument
>
462 void saveInternal (SafeParentPointer parent
,
464 bool showMessageOnFailure
,
466 std::function
<void (SaveResult
)> afterSave
,
467 DoSaveDocument
&& doSaveDocument
)
470 MouseCursor::showWaitCursor();
472 auto oldFile
= documentFile
;
473 documentFile
= newFile
;
475 doSaveDocument (newFile
, [parent
,
476 showMessageOnFailure
,
480 afterSave
= std::move (afterSave
)] (Result result
)
482 if (parent
.shouldExitAsyncCallback())
485 MouseCursor::hideWaitCursor();
492 parent
->setChangedFlag (false);
495 MouseCursor::hideWaitCursor();
497 parent
->document
.sendChangeMessage(); // because the filename may have changed
499 if (afterSave
!= nullptr)
505 parent
->documentFile
= oldFile
;
508 MouseCursor::hideWaitCursor();
510 if (showMessageOnFailure
)
511 AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon
,
512 TRANS ("Error writing to file..."),
513 TRANS ("An error occurred while trying to save \"DCNM\" to the file: FLNM")
514 .replace ("DCNM", parent
->document
.getDocumentTitle())
515 .replace ("FLNM", "\n" + newFile
.getFullPathName())
517 + result
.getErrorMessage());
519 parent
->document
.sendChangeMessage(); // because the filename may have changed
521 if (afterSave
!= nullptr)
522 afterSave (failedToWriteToFile
);
526 template <typename DoSaveAsInteractive
, typename DoAskToOverwriteFile
, typename DoSaveDocument
>
527 void saveAsImpl (SafeParentPointer parent
,
529 bool warnAboutOverwritingExistingFiles
,
530 bool askUserForFileIfNotSpecified
,
531 bool showMessageOnFailure
,
532 std::function
<void (SaveResult
)> callback
,
534 DoSaveAsInteractive
&& doSaveAsInteractive
,
535 DoAskToOverwriteFile
&& doAskToOverwriteFile
,
536 DoSaveDocument
&& doSaveDocument
)
538 if (parent
.shouldExitAsyncCallback())
541 if (newFile
== File())
543 if (askUserForFileIfNotSpecified
)
545 doSaveAsInteractive (parent
, true, std::move (callback
));
549 // can't save to an unspecified file
552 if (callback
!= nullptr)
553 callback (failedToWriteToFile
);
558 auto saveInternalHelper
= [parent
,
561 showMessageOnFailure
,
563 doSaveDocument
= std::forward
<DoSaveDocument
> (doSaveDocument
)]
565 if (! parent
.shouldExitAsyncCallback())
566 parent
->saveInternal (parent
,
568 showMessageOnFailure
,
574 if (warnAboutOverwritingExistingFiles
&& newFile
.exists())
576 auto afterAsking
= [callback
= std::move (callback
),
577 saveInternalHelper
] (SafeParentPointer ptr
,
578 bool shouldOverwrite
)
580 if (ptr
.shouldExitAsyncCallback())
584 saveInternalHelper();
585 else if (callback
!= nullptr)
586 callback (userCancelledSave
);
588 doAskToOverwriteFile (parent
, newFile
, std::move (afterAsking
));
592 saveInternalHelper();
595 void saveAsAsyncImpl (SafeParentPointer parent
,
597 bool warnAboutOverwritingExistingFiles
,
598 bool askUserForFileIfNotSpecified
,
599 bool showMessageOnFailure
,
600 std::function
<void (SaveResult
)> callback
,
605 warnAboutOverwritingExistingFiles
,
606 askUserForFileIfNotSpecified
,
607 showMessageOnFailure
,
608 std::move (callback
),
610 [] (SafeParentPointer ptr
, bool warnAboutOverwriting
, auto cb
)
613 ptr
->saveAsInteractiveAsyncImpl (ptr
, warnAboutOverwriting
, std::move (cb
));
615 [] (SafeParentPointer ptr
, const File
& destination
, std::function
<void (SafeParentPointer
, bool)> cb
)
618 ptr
->askToOverwriteFile (ptr
, destination
, std::move (cb
));
620 [parent
] (const File
& destination
, std::function
<void (Result
)> cb
)
622 if (parent
!= nullptr)
623 parent
->document
.saveDocumentAsync (destination
, std::move (cb
));
627 //==============================================================================
628 void saveAsInteractiveAsyncImpl (SafeParentPointer parent
,
629 bool warnAboutOverwritingExistingFiles
,
630 std::function
<void (SaveResult
)> callback
)
632 if (parent
== nullptr)
635 saveAsInteractiveImpl (parent
,
636 warnAboutOverwritingExistingFiles
,
637 std::move (callback
),
638 [] (SafeParentPointer ptr
, bool warnAboutOverwriting
, auto cb
)
641 ptr
->getSaveAsFilenameAsync (ptr
, warnAboutOverwriting
, std::move (cb
));
643 [] (SafeParentPointer ptr
,
645 bool warnAboutOverwriting
,
646 bool askUserForFileIfNotSpecified
,
647 bool showMessageOnFailure
,
652 ptr
->saveAsAsyncImpl (ptr
,
654 warnAboutOverwriting
,
655 askUserForFileIfNotSpecified
,
656 showMessageOnFailure
,
660 [] (SafeParentPointer ptr
, const File
& destination
, auto cb
)
663 ptr
->askToOverwriteFile (ptr
, destination
, std::move (cb
));
667 //==============================================================================
668 bool askToOverwriteFile (SafeParentPointer parent
,
670 std::function
<void (SafeParentPointer
, bool)> callback
)
672 if (parent
== nullptr)
675 auto* modalCallback
= callback
== nullptr
677 : ModalCallbackFunction::create ([parent
, callback
= std::move (callback
)] (int r
)
679 if (parent
!= nullptr)
680 callback (parent
, r
== 1);
683 return AlertWindow::showOkCancelBox (MessageBoxIconType::WarningIcon
,
684 TRANS ("File already exists"),
685 TRANS ("There's already a file called: FLNM")
686 .replace ("FLNM", newFile
.getFullPathName())
688 + TRANS ("Are you sure you want to overwrite it?"),
695 //==============================================================================
696 void getSaveAsFilenameAsync (SafeParentPointer parent
,
697 bool warnAboutOverwritingExistingFiles
,
698 std::function
<void (SafeParentPointer
, const File
&)> callback
)
700 asyncFc
= getInteractiveFileChooser();
702 auto flags
= FileBrowserComponent::saveMode
| FileBrowserComponent::canSelectFiles
;
704 if (warnAboutOverwritingExistingFiles
)
705 flags
|= FileBrowserComponent::warnAboutOverwriting
;
707 asyncFc
->launchAsync (flags
, [parent
, callback
= std::move (callback
)] (const FileChooser
& fc
)
709 callback (parent
, fc
.getResult());
713 //==============================================================================
714 template <typename DoSelectFilename
, typename DoSaveAs
, typename DoAskToOverwriteFile
>
715 void saveAsInteractiveImpl (SafeParentPointer parent
,
716 bool warnAboutOverwritingExistingFiles
,
717 std::function
<void (SaveResult
)> callback
,
718 DoSelectFilename
&& doSelectFilename
,
720 DoAskToOverwriteFile
&& doAskToOverwriteFile
)
722 doSelectFilename (parent
,
723 warnAboutOverwritingExistingFiles
,
724 [doSaveAs
= std::forward
<DoSaveAs
> (doSaveAs
),
725 doAskToOverwriteFile
= std::forward
<DoAskToOverwriteFile
> (doAskToOverwriteFile
),
726 callback
= std::move (callback
)] (SafeParentPointer parentPtr
, File chosen
)
728 if (parentPtr
.shouldExitAsyncCallback())
731 if (chosen
== File
{})
733 if (callback
!= nullptr)
734 callback (userCancelledSave
);
739 auto updateAndSaveAs
= [parentPtr
, doSaveAs
, callback
] (const File
& chosenFile
)
741 if (parentPtr
.shouldExitAsyncCallback())
744 parentPtr
->document
.setLastDocumentOpened (chosenFile
);
745 doSaveAs (parentPtr
, chosenFile
, false, false, true, callback
, false);
748 if (chosen
.getFileExtension().isEmpty())
750 chosen
= chosen
.withFileExtension (parentPtr
->fileExtension
);
754 auto afterAsking
= [chosen
, updateAndSaveAs
, callback
] (SafeParentPointer overwritePtr
,
757 if (overwritePtr
.shouldExitAsyncCallback())
761 updateAndSaveAs (chosen
);
762 else if (callback
!= nullptr)
763 callback (userCancelledSave
);
766 doAskToOverwriteFile (parentPtr
, chosen
, std::move (afterAsking
));
771 updateAndSaveAs (chosen
);
775 //==============================================================================
776 std::unique_ptr
<FileChooser
> getInteractiveFileChooser()
778 auto f
= documentFile
.existsAsFile() ? documentFile
: document
.getLastDocumentOpened();
780 auto legalFilename
= File::createLegalFileName (document
.getDocumentTitle());
782 if (legalFilename
.isEmpty())
783 legalFilename
= "unnamed";
785 f
= (f
.existsAsFile() || f
.getParentDirectory().isDirectory())
786 ? f
.getSiblingFile (legalFilename
)
787 : File::getSpecialLocation (File::userDocumentsDirectory
).getChildFile (legalFilename
);
789 f
= document
.getSuggestedSaveAsFile (f
);
791 return std::make_unique
<FileChooser
> (saveFileDialogTitle
,
796 //==============================================================================
797 #if JUCE_MODAL_LOOPS_PERMITTED
798 struct SaveAsInteractiveSyncImpl
800 template <typename
... Ts
>
801 void operator() (Ts
&&... ts
) const noexcept
803 p
.saveAsInteractiveSyncImpl (std::forward
<Ts
> (ts
)...);
809 struct AskToOverwriteFileSync
811 template <typename
... Ts
>
812 void operator() (Ts
&&... ts
) const noexcept
814 p
.askToOverwriteFileSync (std::forward
<Ts
> (ts
)...);
820 struct AskToSaveChangesSync
822 template <typename
... Ts
>
823 void operator() (Ts
&&... ts
) const noexcept
825 p
.askToSaveChangesSync (std::forward
<Ts
> (ts
)...);
833 template <typename
... Ts
>
834 void operator() (Ts
&&... ts
) const noexcept
836 p
.saveSync (std::forward
<Ts
> (ts
)...);
842 struct GetSaveAsFilenameSync
844 template <typename
... Ts
>
845 void operator() (Ts
&&... ts
) const noexcept
847 p
.getSaveAsFilenameSync (std::forward
<Ts
> (ts
)...);
853 struct SaveAsSyncImpl
855 template <typename
... Ts
>
856 void operator() (Ts
&&... ts
) const noexcept
858 p
.saveAsSyncImpl (std::forward
<Ts
> (ts
)...);
864 //==============================================================================
865 void saveAsSyncImpl (SafeParentPointer parent
,
867 bool warnAboutOverwritingExistingFiles
,
868 bool askUserForFileIfNotSpecified
,
869 bool showMessageOnFailure
,
870 std::function
<void (SaveResult
)> callback
,
875 warnAboutOverwritingExistingFiles
,
876 askUserForFileIfNotSpecified
,
877 showMessageOnFailure
,
878 std::move (callback
),
880 SaveAsInteractiveSyncImpl
{ *this },
881 AskToOverwriteFileSync
{ *this },
882 [this] (const File
& file
, const auto& cb
) { cb (document
.saveDocument (file
)); });
885 //==============================================================================
886 template <typename Callback
>
887 void askToSaveChangesSync (SafeParentPointer parent
, Callback
&& callback
)
889 callback (parent
, askToSaveChanges (parent
, nullptr));
892 //==============================================================================
893 void saveAsInteractiveSyncImpl (SafeParentPointer parent
,
894 bool warnAboutOverwritingExistingFiles
,
895 std::function
<void (SaveResult
)> callback
)
897 saveAsInteractiveImpl (parent
,
898 warnAboutOverwritingExistingFiles
,
899 std::move (callback
),
900 GetSaveAsFilenameSync
{ *this },
901 SaveAsSyncImpl
{ *this },
902 AskToOverwriteFileSync
{ *this });
905 //==============================================================================
906 template <typename Callback
>
907 void askToOverwriteFileSync (SafeParentPointer parent
,
911 callback (parent
, askToOverwriteFile (parent
, newFile
, nullptr));
914 //==============================================================================
915 template <typename Callback
>
916 void saveSync (bool askUserForFileIfNotSpecified
,
917 bool showMessageOnFailure
,
920 callback (save (askUserForFileIfNotSpecified
, showMessageOnFailure
));
923 //==============================================================================
924 template <typename Callback
>
925 void getSaveAsFilenameSync (SafeParentPointer parent
,
926 bool warnAboutOverwritingExistingFiles
,
929 auto fc
= getInteractiveFileChooser();
931 if (fc
->browseForFileToSave (warnAboutOverwritingExistingFiles
))
933 callback (parent
, fc
->getResult());
937 callback (parent
, {});
941 //==============================================================================
942 FileBasedDocument
& document
;
945 bool changedSinceSave
= false;
946 String fileExtension
, fileWildcard
, openFileDialogTitle
, saveFileDialogTitle
;
947 std::unique_ptr
<FileChooser
> asyncFc
;
949 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl
)
950 JUCE_DECLARE_WEAK_REFERENCEABLE (Pimpl
)
953 //==============================================================================
954 FileBasedDocument::FileBasedDocument (const String
& fileExtension
,
955 const String
& fileWildcard
,
956 const String
& openFileDialogTitle
,
957 const String
& saveFileDialogTitle
)
958 : pimpl (new Pimpl (*this,
962 saveFileDialogTitle
))
966 FileBasedDocument::~FileBasedDocument() = default;
968 //==============================================================================
969 bool FileBasedDocument::hasChangedSinceSaved() const
971 return pimpl
->hasChangedSinceSaved();
974 void FileBasedDocument::setChangedFlag (bool hasChanged
)
976 pimpl
->setChangedFlag (hasChanged
);
979 void FileBasedDocument::changed()
984 //==============================================================================
985 Result
FileBasedDocument::loadFrom (const File
& fileToLoadFrom
,
986 bool showMessageOnFailure
,
989 return pimpl
->loadFrom (fileToLoadFrom
, showMessageOnFailure
, showWaitCursor
);
992 void FileBasedDocument::loadFromAsync (const File
& fileToLoadFrom
,
993 bool showMessageOnFailure
,
994 std::function
<void (Result
)> callback
)
996 pimpl
->loadFromAsync (fileToLoadFrom
, showMessageOnFailure
, std::move (callback
));
999 //==============================================================================
1000 #if JUCE_MODAL_LOOPS_PERMITTED
1001 Result
FileBasedDocument::loadFromUserSpecifiedFile (bool showMessageOnFailure
)
1003 return pimpl
->loadFromUserSpecifiedFile (showMessageOnFailure
);
1007 void FileBasedDocument::loadFromUserSpecifiedFileAsync (const bool showMessageOnFailure
,
1008 std::function
<void (Result
)> callback
)
1010 pimpl
->loadFromUserSpecifiedFileAsync (showMessageOnFailure
, std::move (callback
));
1013 //==============================================================================
1014 #if JUCE_MODAL_LOOPS_PERMITTED
1015 FileBasedDocument::SaveResult
FileBasedDocument::save (bool askUserForFileIfNotSpecified
,
1016 bool showMessageOnFailure
)
1018 return pimpl
->save (askUserForFileIfNotSpecified
, showMessageOnFailure
);
1022 void FileBasedDocument::saveAsync (bool askUserForFileIfNotSpecified
,
1023 bool showMessageOnFailure
,
1024 std::function
<void (SaveResult
)> callback
)
1026 pimpl
->saveAsync (askUserForFileIfNotSpecified
, showMessageOnFailure
, std::move (callback
));
1029 //==============================================================================
1030 #if JUCE_MODAL_LOOPS_PERMITTED
1031 FileBasedDocument::SaveResult
FileBasedDocument::saveIfNeededAndUserAgrees()
1033 return pimpl
->saveIfNeededAndUserAgrees();
1037 void FileBasedDocument::saveIfNeededAndUserAgreesAsync (std::function
<void (SaveResult
)> callback
)
1039 pimpl
->saveIfNeededAndUserAgreesAsync (std::move (callback
));
1042 //==============================================================================
1043 #if JUCE_MODAL_LOOPS_PERMITTED
1044 FileBasedDocument::SaveResult
FileBasedDocument::saveAs (const File
& newFile
,
1045 bool warnAboutOverwritingExistingFiles
,
1046 bool askUserForFileIfNotSpecified
,
1047 bool showMessageOnFailure
,
1048 bool showWaitCursor
)
1050 return pimpl
->saveAs (newFile
,
1051 warnAboutOverwritingExistingFiles
,
1052 askUserForFileIfNotSpecified
,
1053 showMessageOnFailure
,
1058 void FileBasedDocument::saveAsAsync (const File
& newFile
,
1059 bool warnAboutOverwritingExistingFiles
,
1060 bool askUserForFileIfNotSpecified
,
1061 bool showMessageOnFailure
,
1062 std::function
<void (SaveResult
)> callback
)
1064 pimpl
->saveAsAsync (newFile
,
1065 warnAboutOverwritingExistingFiles
,
1066 askUserForFileIfNotSpecified
,
1067 showMessageOnFailure
,
1068 std::move (callback
));
1071 //==============================================================================
1072 #if JUCE_MODAL_LOOPS_PERMITTED
1073 FileBasedDocument::SaveResult
FileBasedDocument::saveAsInteractive (bool warnAboutOverwritingExistingFiles
)
1075 return pimpl
->saveAsInteractive (warnAboutOverwritingExistingFiles
);
1079 void FileBasedDocument::saveAsInteractiveAsync (bool warnAboutOverwritingExistingFiles
,
1080 std::function
<void (SaveResult
)> callback
)
1082 pimpl
->saveAsInteractiveAsync (warnAboutOverwritingExistingFiles
, std::move (callback
));
1085 //==============================================================================
1086 const File
& FileBasedDocument::getFile() const
1088 return pimpl
->getFile();
1091 void FileBasedDocument::setFile (const File
& newFile
)
1093 pimpl
->setFile (newFile
);
1096 //==============================================================================
1097 void FileBasedDocument::loadDocumentAsync (const File
& file
, std::function
<void (Result
)> callback
)
1099 const auto result
= loadDocument (file
);
1101 if (callback
!= nullptr)
1105 void FileBasedDocument::saveDocumentAsync (const File
& file
, std::function
<void (Result
)> callback
)
1107 const auto result
= saveDocument (file
);
1109 if (callback
!= nullptr)
1113 File
FileBasedDocument::getSuggestedSaveAsFile (const File
& defaultFile
)
1115 return defaultFile
.withFileExtension (pimpl
->getFileExtension()).getNonexistentSibling (true);