LMMS
Loading...
Searching...
No Matches
juce_FileBasedDocument.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29//==============================================================================
31{
32private:
33 //==============================================================================
35 {
36 public:
38 : ptr (parent), shouldCheck (isAsync)
39 {}
40
42 {
43 return ptr.get();
44 }
45
46 bool operator== (Pimpl* object) const noexcept { return ptr.get() == object; }
47 bool operator!= (Pimpl* object) const noexcept { return ptr.get() != object; }
48
50 {
51 return shouldCheck && ptr == nullptr;
52 }
53
54 private:
56 bool shouldCheck = false;
57 };
58
59public:
60 //==============================================================================
62 const String& fileExtension_,
63 const String& fileWildcard_,
64 const String& openFileDialogTitle_,
65 const String& saveFileDialogTitle_)
66 : document (parent_),
67 fileExtension (fileExtension_),
68 fileWildcard (fileWildcard_),
69 openFileDialogTitle (openFileDialogTitle_),
70 saveFileDialogTitle (saveFileDialogTitle_)
71 {
72 }
73
74 //==============================================================================
76 {
77 return changedSinceSave;
78 }
79
80 void setChangedFlag (bool hasChanged)
81 {
82 if (changedSinceSave != hasChanged)
83 {
84 changedSinceSave = hasChanged;
85 document.sendChangeMessage();
86 }
87 }
88
89 void changed()
90 {
91 changedSinceSave = true;
92 document.sendChangeMessage();
93 }
94
95 //==============================================================================
96 Result loadFrom (const File& newFile, bool showMessageOnFailure, bool showWaitCursor = true)
97 {
98 SafeParentPointer parent { this, false };
99 auto result = Result::ok();
101 newFile,
102 showMessageOnFailure,
103 showWaitCursor,
104 [this] (const File& file, const auto& callback) { callback (document.loadDocument (file)); },
105 [&result] (Result r) { result = r; });
106 return result;
107 }
108
109 void loadFromAsync (const File& newFile,
110 bool showMessageOnFailure,
111 std::function<void (Result)> callback)
112 {
113 SafeParentPointer parent { this, true };
115 newFile,
116 showMessageOnFailure,
117 false,
118 [parent] (const File& file, auto cb)
119 {
120 if (parent != nullptr)
121 parent->document.loadDocumentAsync (file, std::move (cb));
122 },
123 std::move (callback));
124 }
125
126 //==============================================================================
127 #if JUCE_MODAL_LOOPS_PERMITTED
128 Result loadFromUserSpecifiedFile (bool showMessageOnFailure)
129 {
130 FileChooser fc (openFileDialogTitle,
131 document.getLastDocumentOpened(),
132 fileWildcard);
133
134 if (fc.browseForFileToOpen())
135 return loadFrom (fc.getResult(), showMessageOnFailure);
136
137 return Result::fail (TRANS ("User cancelled"));
138 }
139 #endif
140
141 void loadFromUserSpecifiedFileAsync (const bool showMessageOnFailure, std::function<void (Result)> callback)
142 {
143 asyncFc = std::make_unique<FileChooser> (openFileDialogTitle,
144 document.getLastDocumentOpened(),
146
148 [this, showMessageOnFailure, callback = std::move (callback)] (const FileChooser& fc)
149 {
150 auto chosenFile = fc.getResult();
151
152 if (chosenFile == File{})
153 {
154 if (callback != nullptr)
155 callback (Result::fail (TRANS ("User cancelled")));
156
157 return;
158 }
159
161 loadFromAsync (chosenFile, showMessageOnFailure, [parent, callback] (Result result)
162 {
163 if (parent != nullptr && callback != nullptr)
165 });
166
167 asyncFc = nullptr;
168 });
169 }
170
171 //==============================================================================
172 #if JUCE_MODAL_LOOPS_PERMITTED
173 FileBasedDocument::SaveResult save (bool askUserForFileIfNotSpecified,
174 bool showMessageOnFailure)
175 {
176 return saveAs (documentFile,
177 false,
178 askUserForFileIfNotSpecified,
179 showMessageOnFailure);
180 }
181 #endif
182
183 void saveAsync (bool askUserForFileIfNotSpecified,
184 bool showMessageOnFailure,
185 std::function<void (SaveResult)> callback)
186 {
188 false,
189 askUserForFileIfNotSpecified,
190 showMessageOnFailure,
191 std::move (callback));
192 }
193
194 //==============================================================================
195 #if JUCE_MODAL_LOOPS_PERMITTED
196 FileBasedDocument::SaveResult saveIfNeededAndUserAgrees()
197 {
198 SafeParentPointer parent { this, false };
199 SaveResult result;
200 saveIfNeededAndUserAgreesImpl (parent,
201 [&result] (SaveResult r) { result = r; },
202 AskToSaveChangesSync { *this },
203 SaveSync { *this });
204 return result;
205 }
206 #endif
207
209 {
210 SafeParentPointer parent { this, true };
211
213 std::move (callback),
214 [] (SafeParentPointer ptr, auto cb)
215 {
216 if (ptr != nullptr)
217 ptr->askToSaveChanges (ptr, std::move (cb));
218 },
219 [parent] (bool askUserForFileIfNotSpecified,
220 bool showMessageOnFailure,
221 auto cb)
222 {
223 if (parent != nullptr)
224 parent->saveAsync (askUserForFileIfNotSpecified,
225 showMessageOnFailure,
226 std::move (cb));
227 });
228 }
229
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)
237 {
238 SafeParentPointer parent { this, false };
239 SaveResult result{};
240 saveAsSyncImpl (parent,
241 newFile,
242 warnAboutOverwritingExistingFiles,
243 askUserForFileIfNotSpecified,
244 showMessageOnFailure,
245 [&result] (SaveResult r) { result = r; },
246 showWaitCursor);
247 return result;
248 }
249 #endif
250
251 void saveAsAsync (const File& newFile,
252 bool warnAboutOverwritingExistingFiles,
253 bool askUserForFileIfNotSpecified,
254 bool showMessageOnFailure,
255 std::function<void (SaveResult)> callback)
256 {
257 SafeParentPointer parent { this, true };
259 newFile,
260 warnAboutOverwritingExistingFiles,
261 askUserForFileIfNotSpecified,
262 showMessageOnFailure,
263 std::move (callback),
264 false);
265 }
266
267 //==============================================================================
268 #if JUCE_MODAL_LOOPS_PERMITTED
269 FileBasedDocument::SaveResult saveAsInteractive (bool warnAboutOverwritingExistingFiles)
270 {
271 SafeParentPointer parent { this, false };
272 SaveResult result{};
273 saveAsInteractiveSyncImpl (parent,
274 warnAboutOverwritingExistingFiles,
275 [&result] (SaveResult r) { result = r; });
276 return result;
277 }
278 #endif
279
280 void saveAsInteractiveAsync (bool warnAboutOverwritingExistingFiles,
281 std::function<void (SaveResult)> callback)
282 {
283 SafeParentPointer parent { this, true };
285 warnAboutOverwritingExistingFiles,
286 std::move (callback));
287 }
288
289 //==============================================================================
290 const File& getFile() const
291 {
292 return documentFile;
293 }
294
295 void setFile (const File& newFile)
296 {
297 if (documentFile != newFile)
298 {
299 documentFile = newFile;
300 changed();
301 }
302 }
303
304 //==============================================================================
306 {
307 return fileExtension;
308 }
309
310private:
311 //==============================================================================
312 template <typename DoLoadDocument>
314 const File& newFile,
315 bool showMessageOnFailure,
316 bool showWaitCursor,
317 DoLoadDocument&& doLoadDocument,
318 std::function<void (Result)> completed)
319 {
320 if (parent.shouldExitAsyncCallback())
321 return;
322
323 if (showWaitCursor)
325
326 auto oldFile = documentFile;
327 documentFile = newFile;
328
329 auto tidyUp = [parent, newFile, oldFile, showMessageOnFailure, showWaitCursor, completed] (Result result)
330 {
331 if (parent.shouldExitAsyncCallback())
332 return;
333
334 parent->documentFile = oldFile;
335
336 if (showWaitCursor)
338
339 if (showMessageOnFailure)
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())
344 + "\n\n"
345 + result.getErrorMessage());
346
347 if (completed != nullptr)
348 completed (result);
349 };
350
351 if (newFile.existsAsFile())
352 {
353 auto afterLoading = [parent,
354 showWaitCursor,
355 newFile,
356 completed = std::move (completed),
357 tidyUp] (Result result)
358 {
359 if (result.wasOk())
360 {
361 parent->setChangedFlag (false);
362
363 if (showWaitCursor)
365
366 parent->document.setLastDocumentOpened (newFile);
367
368 if (completed != nullptr)
369 completed (result);
370
371 return;
372 }
373
374 tidyUp (result);
375 };
376
377 doLoadDocument (newFile, std::move (afterLoading));
378
379 return;
380 }
381
382 tidyUp (Result::fail (TRANS ("The file doesn't exist")));
383 }
384
385 //==============================================================================
386 template <typename DoAskToSaveChanges, typename DoSave>
388 std::function<void (SaveResult)> completed,
389 DoAskToSaveChanges&& doAskToSaveChanges,
390 DoSave&& doSave)
391 {
392 if (parent.shouldExitAsyncCallback())
393 return;
394
395 if (! hasChangedSinceSaved())
396 {
397 if (completed != nullptr)
398 completed (savedOk);
399
400 return;
401 }
402
403 auto afterAsking = [doSave = std::forward<DoSave> (doSave),
404 completed = std::move (completed)] (SafeParentPointer ptr,
405 int alertResult)
406 {
407 if (ptr.shouldExitAsyncCallback())
408 return;
409
410 switch (alertResult)
411 {
412 case 1: // save changes
413 doSave (true, true, [ptr, completed] (SaveResult result)
414 {
415 if (ptr.shouldExitAsyncCallback())
416 return;
417
418 if (completed != nullptr)
419 completed (result);
420 });
421 return;
422
423 case 2: // discard changes
424 if (completed != nullptr)
425 completed (savedOk);
426
427 return;
428 }
429
430 if (completed != nullptr)
431 completed (userCancelledSave);
432 };
433
434 doAskToSaveChanges (parent, std::move (afterAsking));
435 }
436
437 //==============================================================================
439 std::function<void (SafeParentPointer, int)> callback)
440 {
441 auto* modalCallback = callback == nullptr
442 ? nullptr
443 : ModalCallbackFunction::create ([parent, callback = std::move (callback)] (int alertResult)
444 {
445 if (parent != nullptr)
446 callback (parent, alertResult);
447 });
448
450 TRANS ("Closing document..."),
451 TRANS ("Do you want to save the changes to \"DCNM\"?")
452 .replace ("DCNM", document.getDocumentTitle()),
453 TRANS ("Save"),
454 TRANS ("Discard changes"),
455 TRANS ("Cancel"),
456 nullptr,
457 modalCallback);
458 }
459
460 //==============================================================================
461 template <typename DoSaveDocument>
463 const File& newFile,
464 bool showMessageOnFailure,
465 bool showWaitCursor,
466 std::function<void (SaveResult)> afterSave,
467 DoSaveDocument&& doSaveDocument)
468 {
469 if (showWaitCursor)
471
472 auto oldFile = documentFile;
473 documentFile = newFile;
474
475 doSaveDocument (newFile, [parent,
476 showMessageOnFailure,
477 showWaitCursor,
478 oldFile,
479 newFile,
480 afterSave = std::move (afterSave)] (Result result)
481 {
482 if (parent.shouldExitAsyncCallback())
483 {
484 if (showWaitCursor)
486
487 return;
488 }
489
490 if (result.wasOk())
491 {
492 parent->setChangedFlag (false);
493
494 if (showWaitCursor)
496
497 parent->document.sendChangeMessage(); // because the filename may have changed
498
499 if (afterSave != nullptr)
500 afterSave (savedOk);
501
502 return;
503 }
504
505 parent->documentFile = oldFile;
506
507 if (showWaitCursor)
509
510 if (showMessageOnFailure)
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())
516 + "\n\n"
517 + result.getErrorMessage());
518
519 parent->document.sendChangeMessage(); // because the filename may have changed
520
521 if (afterSave != nullptr)
522 afterSave (failedToWriteToFile);
523 });
524 }
525
526 template <typename DoSaveAsInteractive, typename DoAskToOverwriteFile, typename DoSaveDocument>
528 const File& newFile,
529 bool warnAboutOverwritingExistingFiles,
530 bool askUserForFileIfNotSpecified,
531 bool showMessageOnFailure,
532 std::function<void (SaveResult)> callback,
533 bool showWaitCursor,
534 DoSaveAsInteractive&& doSaveAsInteractive,
535 DoAskToOverwriteFile&& doAskToOverwriteFile,
536 DoSaveDocument&& doSaveDocument)
537 {
538 if (parent.shouldExitAsyncCallback())
539 return;
540
541 if (newFile == File())
542 {
543 if (askUserForFileIfNotSpecified)
544 {
545 doSaveAsInteractive (parent, true, std::move (callback));
546 return;
547 }
548
549 // can't save to an unspecified file
551
552 if (callback != nullptr)
554
555 return;
556 }
557
558 auto saveInternalHelper = [parent,
559 callback,
560 newFile,
561 showMessageOnFailure,
562 showWaitCursor,
563 doSaveDocument = std::forward<DoSaveDocument> (doSaveDocument)]
564 {
565 if (! parent.shouldExitAsyncCallback())
566 parent->saveInternal (parent,
567 newFile,
568 showMessageOnFailure,
569 showWaitCursor,
570 callback,
571 doSaveDocument);
572 };
573
574 if (warnAboutOverwritingExistingFiles && newFile.exists())
575 {
576 auto afterAsking = [callback = std::move (callback),
577 saveInternalHelper] (SafeParentPointer ptr,
578 bool shouldOverwrite)
579 {
580 if (ptr.shouldExitAsyncCallback())
581 return;
582
583 if (shouldOverwrite)
584 saveInternalHelper();
585 else if (callback != nullptr)
587 };
588 doAskToOverwriteFile (parent, newFile, std::move (afterAsking));
589 return;
590 }
591
592 saveInternalHelper();
593 }
594
596 const File& newFile,
597 bool warnAboutOverwritingExistingFiles,
598 bool askUserForFileIfNotSpecified,
599 bool showMessageOnFailure,
600 std::function<void (SaveResult)> callback,
601 bool showWaitCursor)
602 {
604 newFile,
605 warnAboutOverwritingExistingFiles,
606 askUserForFileIfNotSpecified,
607 showMessageOnFailure,
608 std::move (callback),
609 showWaitCursor,
610 [] (SafeParentPointer ptr, bool warnAboutOverwriting, auto cb)
611 {
612 if (ptr != nullptr)
613 ptr->saveAsInteractiveAsyncImpl (ptr, warnAboutOverwriting, std::move (cb));
614 },
615 [] (SafeParentPointer ptr, const File& destination, std::function<void (SafeParentPointer, bool)> cb)
616 {
617 if (ptr != nullptr)
618 ptr->askToOverwriteFile (ptr, destination, std::move (cb));
619 },
620 [parent] (const File& destination, std::function<void (Result)> cb)
621 {
622 if (parent != nullptr)
623 parent->document.saveDocumentAsync (destination, std::move (cb));
624 });
625 }
626
627 //==============================================================================
629 bool warnAboutOverwritingExistingFiles,
630 std::function<void (SaveResult)> callback)
631 {
632 if (parent == nullptr)
633 return;
634
636 warnAboutOverwritingExistingFiles,
637 std::move (callback),
638 [] (SafeParentPointer ptr, bool warnAboutOverwriting, auto cb)
639 {
640 if (ptr != nullptr)
641 ptr->getSaveAsFilenameAsync (ptr, warnAboutOverwriting, std::move (cb));
642 },
644 const File& newFile,
645 bool warnAboutOverwriting,
646 bool askUserForFileIfNotSpecified,
647 bool showMessageOnFailure,
648 auto cb,
649 bool showWaitCursor)
650 {
651 if (ptr != nullptr)
652 ptr->saveAsAsyncImpl (ptr,
653 newFile,
654 warnAboutOverwriting,
655 askUserForFileIfNotSpecified,
656 showMessageOnFailure,
657 std::move (cb),
658 showWaitCursor);
659 },
660 [] (SafeParentPointer ptr, const File& destination, auto cb)
661 {
662 if (ptr != nullptr)
663 ptr->askToOverwriteFile (ptr, destination, std::move (cb));
664 });
665 }
666
667 //==============================================================================
669 const File& newFile,
670 std::function<void (SafeParentPointer, bool)> callback)
671 {
672 if (parent == nullptr)
673 return false;
674
675 auto* modalCallback = callback == nullptr
676 ? nullptr
677 : ModalCallbackFunction::create ([parent, callback = std::move (callback)] (int r)
678 {
679 if (parent != nullptr)
680 callback (parent, r == 1);
681 });
682
684 TRANS ("File already exists"),
685 TRANS ("There's already a file called: FLNM")
686 .replace ("FLNM", newFile.getFullPathName())
687 + "\n\n"
688 + TRANS ("Are you sure you want to overwrite it?"),
689 TRANS ("Overwrite"),
690 TRANS ("Cancel"),
691 nullptr,
692 modalCallback);
693 }
694
695 //==============================================================================
697 bool warnAboutOverwritingExistingFiles,
698 std::function<void (SafeParentPointer, const File&)> callback)
699 {
701
703
704 if (warnAboutOverwritingExistingFiles)
706
707 asyncFc->launchAsync (flags, [parent, callback = std::move (callback)] (const FileChooser& fc)
708 {
709 callback (parent, fc.getResult());
710 });
711 }
712
713 //==============================================================================
714 template <typename DoSelectFilename, typename DoSaveAs, typename DoAskToOverwriteFile>
716 bool warnAboutOverwritingExistingFiles,
717 std::function<void (SaveResult)> callback,
718 DoSelectFilename&& doSelectFilename,
719 DoSaveAs&& doSaveAs,
720 DoAskToOverwriteFile&& doAskToOverwriteFile)
721 {
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)
727 {
728 if (parentPtr.shouldExitAsyncCallback())
729 return;
730
731 if (chosen == File{})
732 {
733 if (callback != nullptr)
735
736 return;
737 }
738
739 auto updateAndSaveAs = [parentPtr, doSaveAs, callback] (const File& chosenFile)
740 {
741 if (parentPtr.shouldExitAsyncCallback())
742 return;
743
744 parentPtr->document.setLastDocumentOpened (chosenFile);
745 doSaveAs (parentPtr, chosenFile, false, false, true, callback, false);
746 };
747
748 if (chosen.getFileExtension().isEmpty())
749 {
750 chosen = chosen.withFileExtension (parentPtr->fileExtension);
751
752 if (chosen.exists())
753 {
754 auto afterAsking = [chosen, updateAndSaveAs, callback] (SafeParentPointer overwritePtr,
755 bool overwrite)
756 {
757 if (overwritePtr.shouldExitAsyncCallback())
758 return;
759
760 if (overwrite)
761 updateAndSaveAs (chosen);
762 else if (callback != nullptr)
764 };
765
766 doAskToOverwriteFile (parentPtr, chosen, std::move (afterAsking));
767 return;
768 }
769 }
770
771 updateAndSaveAs (chosen);
772 });
773 }
774
775 //==============================================================================
776 std::unique_ptr<FileChooser> getInteractiveFileChooser()
777 {
778 auto f = documentFile.existsAsFile() ? documentFile : document.getLastDocumentOpened();
779
780 auto legalFilename = File::createLegalFileName (document.getDocumentTitle());
781
782 if (legalFilename.isEmpty())
783 legalFilename = "unnamed";
784
785 f = (f.existsAsFile() || f.getParentDirectory().isDirectory())
786 ? f.getSiblingFile (legalFilename)
788
789 f = document.getSuggestedSaveAsFile (f);
790
791 return std::make_unique<FileChooser> (saveFileDialogTitle,
792 f,
794 }
795
796 //==============================================================================
797 #if JUCE_MODAL_LOOPS_PERMITTED
798 struct SaveAsInteractiveSyncImpl
799 {
800 template <typename... Ts>
801 void operator() (Ts&&... ts) const noexcept
802 {
803 p.saveAsInteractiveSyncImpl (std::forward<Ts> (ts)...);
804 }
805
806 Pimpl& p;
807 };
808
809 struct AskToOverwriteFileSync
810 {
811 template <typename... Ts>
812 void operator() (Ts&&... ts) const noexcept
813 {
814 p.askToOverwriteFileSync (std::forward<Ts> (ts)...);
815 }
816
817 Pimpl& p;
818 };
819
820 struct AskToSaveChangesSync
821 {
822 template <typename... Ts>
823 void operator() (Ts&&... ts) const noexcept
824 {
825 p.askToSaveChangesSync (std::forward<Ts> (ts)...);
826 }
827
828 Pimpl& p;
829 };
830
831 struct SaveSync
832 {
833 template <typename... Ts>
834 void operator() (Ts&&... ts) const noexcept
835 {
836 p.saveSync (std::forward<Ts> (ts)...);
837 }
838
839 Pimpl& p;
840 };
841
842 struct GetSaveAsFilenameSync
843 {
844 template <typename... Ts>
845 void operator() (Ts&&... ts) const noexcept
846 {
847 p.getSaveAsFilenameSync (std::forward<Ts> (ts)...);
848 }
849
850 Pimpl& p;
851 };
852
853 struct SaveAsSyncImpl
854 {
855 template <typename... Ts>
856 void operator() (Ts&&... ts) const noexcept
857 {
858 p.saveAsSyncImpl (std::forward<Ts> (ts)...);
859 }
860
861 Pimpl& p;
862 };
863
864 //==============================================================================
865 void saveAsSyncImpl (SafeParentPointer parent,
866 const File& newFile,
867 bool warnAboutOverwritingExistingFiles,
868 bool askUserForFileIfNotSpecified,
869 bool showMessageOnFailure,
870 std::function<void (SaveResult)> callback,
871 bool showWaitCursor)
872 {
874 newFile,
875 warnAboutOverwritingExistingFiles,
876 askUserForFileIfNotSpecified,
877 showMessageOnFailure,
878 std::move (callback),
879 showWaitCursor,
880 SaveAsInteractiveSyncImpl { *this },
881 AskToOverwriteFileSync { *this },
882 [this] (const File& file, const auto& cb) { cb (document.saveDocument (file)); });
883 }
884
885 //==============================================================================
886 template <typename Callback>
887 void askToSaveChangesSync (SafeParentPointer parent, Callback&& callback)
888 {
889 callback (parent, askToSaveChanges (parent, nullptr));
890 }
891
892 //==============================================================================
893 void saveAsInteractiveSyncImpl (SafeParentPointer parent,
894 bool warnAboutOverwritingExistingFiles,
895 std::function<void (SaveResult)> callback)
896 {
898 warnAboutOverwritingExistingFiles,
899 std::move (callback),
900 GetSaveAsFilenameSync { *this },
901 SaveAsSyncImpl { *this },
902 AskToOverwriteFileSync { *this });
903 }
904
905 //==============================================================================
906 template <typename Callback>
907 void askToOverwriteFileSync (SafeParentPointer parent,
908 const File& newFile,
909 Callback&& callback)
910 {
911 callback (parent, askToOverwriteFile (parent, newFile, nullptr));
912 }
913
914 //==============================================================================
915 template <typename Callback>
916 void saveSync (bool askUserForFileIfNotSpecified,
917 bool showMessageOnFailure,
918 Callback&& callback)
919 {
920 callback (save (askUserForFileIfNotSpecified, showMessageOnFailure));
921 }
922
923 //==============================================================================
924 template <typename Callback>
925 void getSaveAsFilenameSync (SafeParentPointer parent,
926 bool warnAboutOverwritingExistingFiles,
927 Callback&& callback)
928 {
929 auto fc = getInteractiveFileChooser();
930
931 if (fc->browseForFileToSave (warnAboutOverwritingExistingFiles))
932 {
933 callback (parent, fc->getResult());
934 return;
935 }
936
937 callback (parent, {});
938 }
939 #endif
940
941 //==============================================================================
943
945 bool changedSinceSave = false;
947 std::unique_ptr<FileChooser> asyncFc;
948
951};
952
953//==============================================================================
955 const String& fileWildcard,
956 const String& openFileDialogTitle,
957 const String& saveFileDialogTitle)
958 : pimpl (new Pimpl (*this,
959 fileExtension,
960 fileWildcard,
961 openFileDialogTitle,
962 saveFileDialogTitle))
963{
964}
965
967
968//==============================================================================
970{
971 return pimpl->hasChangedSinceSaved();
972}
973
975{
976 pimpl->setChangedFlag (hasChanged);
977}
978
980{
981 pimpl->changed();
982}
983
984//==============================================================================
986 bool showMessageOnFailure,
987 bool showWaitCursor)
988{
989 return pimpl->loadFrom (fileToLoadFrom, showMessageOnFailure, showWaitCursor);
990}
991
992void FileBasedDocument::loadFromAsync (const File& fileToLoadFrom,
993 bool showMessageOnFailure,
994 std::function<void (Result)> callback)
995{
996 pimpl->loadFromAsync (fileToLoadFrom, showMessageOnFailure, std::move (callback));
997}
998
999//==============================================================================
1000#if JUCE_MODAL_LOOPS_PERMITTED
1001Result FileBasedDocument::loadFromUserSpecifiedFile (bool showMessageOnFailure)
1002{
1003 return pimpl->loadFromUserSpecifiedFile (showMessageOnFailure);
1004}
1005#endif
1006
1007void FileBasedDocument::loadFromUserSpecifiedFileAsync (const bool showMessageOnFailure,
1008 std::function<void (Result)> callback)
1009{
1010 pimpl->loadFromUserSpecifiedFileAsync (showMessageOnFailure, std::move (callback));
1011}
1012
1013//==============================================================================
1014#if JUCE_MODAL_LOOPS_PERMITTED
1015FileBasedDocument::SaveResult FileBasedDocument::save (bool askUserForFileIfNotSpecified,
1016 bool showMessageOnFailure)
1017{
1018 return pimpl->save (askUserForFileIfNotSpecified, showMessageOnFailure);
1019}
1020#endif
1021
1022void FileBasedDocument::saveAsync (bool askUserForFileIfNotSpecified,
1023 bool showMessageOnFailure,
1024 std::function<void (SaveResult)> callback)
1025{
1026 pimpl->saveAsync (askUserForFileIfNotSpecified, showMessageOnFailure, std::move (callback));
1027}
1028
1029//==============================================================================
1030#if JUCE_MODAL_LOOPS_PERMITTED
1031FileBasedDocument::SaveResult FileBasedDocument::saveIfNeededAndUserAgrees()
1032{
1033 return pimpl->saveIfNeededAndUserAgrees();
1034}
1035#endif
1036
1038{
1039 pimpl->saveIfNeededAndUserAgreesAsync (std::move (callback));
1040}
1041
1042//==============================================================================
1043#if JUCE_MODAL_LOOPS_PERMITTED
1044FileBasedDocument::SaveResult FileBasedDocument::saveAs (const File& newFile,
1045 bool warnAboutOverwritingExistingFiles,
1046 bool askUserForFileIfNotSpecified,
1047 bool showMessageOnFailure,
1048 bool showWaitCursor)
1049{
1050 return pimpl->saveAs (newFile,
1051 warnAboutOverwritingExistingFiles,
1052 askUserForFileIfNotSpecified,
1053 showMessageOnFailure,
1054 showWaitCursor);
1055}
1056#endif
1057
1059 bool warnAboutOverwritingExistingFiles,
1060 bool askUserForFileIfNotSpecified,
1061 bool showMessageOnFailure,
1062 std::function<void (SaveResult)> callback)
1063{
1064 pimpl->saveAsAsync (newFile,
1065 warnAboutOverwritingExistingFiles,
1066 askUserForFileIfNotSpecified,
1067 showMessageOnFailure,
1068 std::move (callback));
1069}
1070
1071//==============================================================================
1072#if JUCE_MODAL_LOOPS_PERMITTED
1073FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (bool warnAboutOverwritingExistingFiles)
1074{
1075 return pimpl->saveAsInteractive (warnAboutOverwritingExistingFiles);
1076}
1077#endif
1078
1079void FileBasedDocument::saveAsInteractiveAsync (bool warnAboutOverwritingExistingFiles,
1080 std::function<void (SaveResult)> callback)
1081{
1082 pimpl->saveAsInteractiveAsync (warnAboutOverwritingExistingFiles, std::move (callback));
1083}
1084
1085//==============================================================================
1087{
1088 return pimpl->getFile();
1089}
1090
1092{
1093 pimpl->setFile (newFile);
1094}
1095
1096//==============================================================================
1098{
1099 const auto result = loadDocument (file);
1100
1101 if (callback != nullptr)
1102 callback (result);
1103}
1104
1106{
1107 const auto result = saveDocument (file);
1108
1109 if (callback != nullptr)
1110 callback (result);
1111}
1112
1114{
1115 return defaultFile.withFileExtension (pimpl->getFileExtension()).getNonexistentSibling (true);
1116}
1117
1118} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
static String createLegalFileName(const String &fileNameToFix)
Definition File.cpp:848
static File getSpecialLocation(const SpecialLocationType type)
Definition File.cpp:1642
static Result ok() noexcept
Definition Result.h:68
static Result fail(const std::string &errorMessage) noexcept
Definition Result.cpp:58
static int JUCE_CALLTYPE showYesNoCancelBox(MessageBoxIconType iconType, const String &title, const String &message, const String &button1Text, const String &button2Text, const String &button3Text, Component *associatedComponent, ModalComponentManager::Callback *callback)
Definition juce_AlertWindow.cpp:773
static bool JUCE_CALLTYPE showOkCancelBox(MessageBoxIconType iconType, const String &title, const String &message, const String &button1Text, const String &button2Text, Component *associatedComponent, ModalComponentManager::Callback *callback)
Definition juce_AlertWindow.cpp:752
static void JUCE_CALLTYPE showMessageBoxAsync(MessageBoxIconType iconType, const String &title, const String &message, const String &buttonText=String(), Component *associatedComponent=nullptr, ModalComponentManager::Callback *callback=nullptr)
Definition juce_AlertWindow.cpp:712
Definition juce_FileBasedDocument.cpp:35
SafeParentPointer(Pimpl *parent, bool isAsync)
Definition juce_FileBasedDocument.cpp:37
WeakReference< Pimpl > ptr
Definition juce_FileBasedDocument.cpp:55
bool shouldExitAsyncCallback() const noexcept
Definition juce_FileBasedDocument.cpp:49
Pimpl * operator->() const noexcept
Definition juce_FileBasedDocument.cpp:41
bool shouldCheck
Definition juce_FileBasedDocument.cpp:56
Definition juce_FileBasedDocument.cpp:31
void loadFromAsync(const File &newFile, bool showMessageOnFailure, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:109
void saveAsInteractiveImpl(SafeParentPointer parent, bool warnAboutOverwritingExistingFiles, std::function< void(SaveResult)> callback, DoSelectFilename &&doSelectFilename, DoSaveAs &&doSaveAs, DoAskToOverwriteFile &&doAskToOverwriteFile)
Definition juce_FileBasedDocument.cpp:715
const String & getFileExtension() const
Definition juce_FileBasedDocument.cpp:305
String fileExtension
Definition juce_FileBasedDocument.cpp:946
void saveAsInteractiveAsyncImpl(SafeParentPointer parent, bool warnAboutOverwritingExistingFiles, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:628
Pimpl(FileBasedDocument &parent_, const String &fileExtension_, const String &fileWildcard_, const String &openFileDialogTitle_, const String &saveFileDialogTitle_)
Definition juce_FileBasedDocument.cpp:61
std::unique_ptr< FileChooser > asyncFc
Definition juce_FileBasedDocument.cpp:947
std::unique_ptr< FileChooser > getInteractiveFileChooser()
Definition juce_FileBasedDocument.cpp:776
void setFile(const File &newFile)
Definition juce_FileBasedDocument.cpp:295
String saveFileDialogTitle
Definition juce_FileBasedDocument.cpp:946
const File & getFile() const
Definition juce_FileBasedDocument.cpp:290
String openFileDialogTitle
Definition juce_FileBasedDocument.cpp:946
File documentFile
Definition juce_FileBasedDocument.cpp:944
bool changedSinceSave
Definition juce_FileBasedDocument.cpp:945
Result loadFrom(const File &newFile, bool showMessageOnFailure, bool showWaitCursor=true)
Definition juce_FileBasedDocument.cpp:96
void saveAsAsync(const File &newFile, bool warnAboutOverwritingExistingFiles, bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:251
void saveAsAsyncImpl(SafeParentPointer parent, const File &newFile, bool warnAboutOverwritingExistingFiles, bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback, bool showWaitCursor)
Definition juce_FileBasedDocument.cpp:595
void setChangedFlag(bool hasChanged)
Definition juce_FileBasedDocument.cpp:80
void saveAsImpl(SafeParentPointer parent, const File &newFile, bool warnAboutOverwritingExistingFiles, bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback, bool showWaitCursor, DoSaveAsInteractive &&doSaveAsInteractive, DoAskToOverwriteFile &&doAskToOverwriteFile, DoSaveDocument &&doSaveDocument)
Definition juce_FileBasedDocument.cpp:527
void saveAsInteractiveAsync(bool warnAboutOverwritingExistingFiles, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:280
String fileWildcard
Definition juce_FileBasedDocument.cpp:946
void saveAsync(bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:183
void loadFromUserSpecifiedFileAsync(const bool showMessageOnFailure, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:141
int askToSaveChanges(SafeParentPointer parent, std::function< void(SafeParentPointer, int)> callback)
Definition juce_FileBasedDocument.cpp:438
void getSaveAsFilenameAsync(SafeParentPointer parent, bool warnAboutOverwritingExistingFiles, std::function< void(SafeParentPointer, const File &)> callback)
Definition juce_FileBasedDocument.cpp:696
void saveIfNeededAndUserAgreesAsync(std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:208
void saveIfNeededAndUserAgreesImpl(SafeParentPointer parent, std::function< void(SaveResult)> completed, DoAskToSaveChanges &&doAskToSaveChanges, DoSave &&doSave)
Definition juce_FileBasedDocument.cpp:387
void changed()
Definition juce_FileBasedDocument.cpp:89
bool hasChangedSinceSaved() const
Definition juce_FileBasedDocument.cpp:75
FileBasedDocument & document
Definition juce_FileBasedDocument.cpp:942
void loadFromImpl(SafeParentPointer parent, const File &newFile, bool showMessageOnFailure, bool showWaitCursor, DoLoadDocument &&doLoadDocument, std::function< void(Result)> completed)
Definition juce_FileBasedDocument.cpp:313
bool askToOverwriteFile(SafeParentPointer parent, const File &newFile, std::function< void(SafeParentPointer, bool)> callback)
Definition juce_FileBasedDocument.cpp:668
void saveInternal(SafeParentPointer parent, const File &newFile, bool showMessageOnFailure, bool showWaitCursor, std::function< void(SaveResult)> afterSave, DoSaveDocument &&doSaveDocument)
Definition juce_FileBasedDocument.cpp:462
void loadFromAsync(const File &fileToLoadFrom, bool showMessageOnFailure, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:992
virtual Result loadDocument(const File &file)=0
void saveIfNeededAndUserAgreesAsync(std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:1037
void saveAsync(bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:1022
~FileBasedDocument() override
virtual void changed()
Definition juce_FileBasedDocument.cpp:979
bool hasChangedSinceSaved() const
Definition juce_FileBasedDocument.cpp:969
virtual void loadDocumentAsync(const File &file, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:1097
void loadFromUserSpecifiedFileAsync(bool showMessageOnFailure, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:1007
virtual File getSuggestedSaveAsFile(const File &defaultFile)
Definition juce_FileBasedDocument.cpp:1113
Result loadFrom(const File &fileToLoadFrom, bool showMessageOnFailure, bool showWaitCursor=true)
Definition juce_FileBasedDocument.cpp:985
std::unique_ptr< Pimpl > pimpl
Definition juce_FileBasedDocument.h:426
virtual void saveDocumentAsync(const File &file, std::function< void(Result)> callback)
Definition juce_FileBasedDocument.cpp:1105
SaveResult
Definition juce_FileBasedDocument.h:159
@ userCancelledSave
Definition juce_FileBasedDocument.h:161
@ failedToWriteToFile
Definition juce_FileBasedDocument.h:162
@ savedOk
Definition juce_FileBasedDocument.h:160
void setChangedFlag(bool hasChanged)
Definition juce_FileBasedDocument.cpp:974
void saveAsInteractiveAsync(bool warnAboutOverwritingExistingFiles, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:1079
virtual Result saveDocument(const File &file)=0
const File & getFile() const
Definition juce_FileBasedDocument.cpp:1086
void setFile(const File &newFile)
Definition juce_FileBasedDocument.cpp:1091
virtual void setLastDocumentOpened(const File &file)=0
virtual File getLastDocumentOpened()=0
FileBasedDocument(const String &fileExtension, const String &fileWildCard, const String &openFileDialogTitle, const String &saveFileDialogTitle)
Definition juce_FileBasedDocument.cpp:954
void saveAsAsync(const File &newFile, bool warnAboutOverwritingExistingFiles, bool askUserForFileIfNotSpecified, bool showMessageOnFailure, std::function< void(SaveResult)> callback)
Definition juce_FileBasedDocument.cpp:1058
@ saveMode
Definition juce_FileBrowserComponent.h:56
@ warnAboutOverwriting
Definition juce_FileBrowserComponent.h:65
@ canSelectFiles
Definition juce_FileBrowserComponent.h:58
@ openMode
Definition juce_FileBrowserComponent.h:54
Definition juce_FileChooser.h:56
File getResult() const
Definition juce_FileChooser.cpp:240
Definition juce_File.h:45
String getFileExtension() const
Definition juce_File.cpp:664
const String & getFullPathName() const noexcept
Definition juce_File.h:153
File getNonexistentSibling(bool putNumbersInBrackets=true) const
Definition juce_File.cpp:653
@ userDocumentsDirectory
Definition juce_File.h:869
File withFileExtension(StringRef newExtension) const
Definition juce_File.cpp:699
bool exists() const
Definition juce_posix_SharedCode.h:246
static ModalComponentManager::Callback * create(CallbackFn &&fn)
Definition juce_ModalComponentManager.h:174
static void hideWaitCursor()
Definition juce_MouseCursor.cpp:138
static void showWaitCursor()
Definition juce_MouseCursor.cpp:133
Definition juce_Result.h:57
static Result fail(const String &errorMessage) noexcept
Definition juce_Result.cpp:65
Definition juce_String.h:53
bool isEmpty() const noexcept
Definition juce_String.h:310
Definition juce_WeakReference.h:78
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition File.cpp:418
unsigned f
Definition inflate.c:1572
static uintptr_t parent
Definition pugl.h:1644
void * object
Definition jmemsys.h:50
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class)
Definition juce_WeakReference.h:234
Definition carla_juce.cpp:31
@ WarningIcon
Definition juce_MessageBoxOptions.h:35
@ QuestionIcon
Definition juce_MessageBoxOptions.h:33
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags const jack_port_t port jack_client_t jack_port_id_t port_id const jack_port_t const char port_name const jack_port_t port void * ptr
Definition juce_linux_JackAudio.cpp:79
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags
Definition juce_linux_JackAudio.cpp:69
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
static LV2_State_Status save(LV2_Handle instance, LV2_State_Store_Function store, void *callback_data, uint32_t flags, const LV2_Feature *const *features)
Definition test.c:161
uch * p
Definition crypt.c:594
int r
Definition crypt.c:458
int result
Definition process.c:1455
#define void
Definition unzip.h:396
struct zdirent * file
Definition win32.c:1500
#define const
Definition zconf.h:137