|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2013 - Raw Material Software Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
- */
-
- #ifndef JUCE_PROPERTIESFILE_H_INCLUDED
- #define JUCE_PROPERTIESFILE_H_INCLUDED
-
-
- //==============================================================================
- /** Wrapper on a file that stores a list of key/value data pairs.
-
- Useful for storing application settings, etc. See the PropertySet class for
- the interfaces that read and write values.
-
- Not designed for very large amounts of data, as it keeps all the values in
- memory and writes them out to disk lazily when they are changed.
-
- Because this class derives from ChangeBroadcaster, ChangeListeners can be registered
- with it, and these will be signalled when a value changes.
-
- @see PropertySet
- */
- class JUCE_API PropertiesFile : public PropertySet,
- public ChangeBroadcaster,
- private Timer
- {
- public:
- //==============================================================================
- enum StorageFormat
- {
- storeAsBinary,
- storeAsCompressedBinary,
- storeAsXML
- };
-
- //==============================================================================
- struct JUCE_API Options
- {
- /** Creates an empty Options structure.
- You'll need to fill-in the data memebers appropriately before using this structure.
- */
- Options();
-
- /** The name of your application - this is used to help generate the path and filename
- at which the properties file will be stored. */
- String applicationName;
-
- /** The suffix to use for your properties file.
- It doesn't really matter what this is - you may want to use ".settings" or
- ".properties" or something.
- */
- String filenameSuffix;
-
- /** The name of a subfolder in which you'd like your properties file to live.
- See the getDefaultFile() method for more details about how this is used.
- */
- String folderName;
-
- /** If you're using properties files on a Mac, you must set this value - failure to
- do so will cause a runtime assertion.
-
- The PropertiesFile class always used to put its settings files in "Library/Preferences", but Apple
- have changed their advice, and now stipulate that settings should go in "Library/Application Support".
-
- Because older apps would be broken by a silent change in this class's behaviour, you must now
- explicitly set the osxLibrarySubFolder value to indicate which path you want to use.
-
- In newer apps, you should always set this to "Application Support".
-
- If your app needs to load settings files that were created by older versions of juce and
- you want to maintain backwards-compatibility, then you can set this to "Preferences".
- But.. for better Apple-compliance, the recommended approach would be to write some code that
- finds your old settings files in ~/Library/Preferences, moves them to ~/Library/Application Support,
- and then uses the new path.
- */
- String osxLibrarySubFolder;
-
- /** If true, the file will be created in a location that's shared between users.
- The default constructor initialises this value to false.
- */
- bool commonToAllUsers;
-
- /** If true, this means that property names are matched in a case-insensitive manner.
- See the PropertySet constructor for more info.
- The default constructor initialises this value to false.
- */
- bool ignoreCaseOfKeyNames;
-
- /** If set to true, this prevents the file from being written to disk. */
- bool doNotSave;
-
- /** If this is zero or greater, then after a value is changed, the object will wait
- for this amount of time and then save the file. If this zero, the file will be
- written to disk immediately on being changed (which might be slow, as it'll re-write
- synchronously each time a value-change method is called). If it is less than zero,
- the file won't be saved until save() or saveIfNeeded() are explicitly called.
- The default constructor sets this to a reasonable value of a few seconds, so you
- only need to change it if you need a special case.
- */
- int millisecondsBeforeSaving;
-
- /** Specifies whether the file should be written as XML, binary, etc.
- The default constructor sets this to storeAsXML, so you only need to set it explicitly
- if you want to use a different format.
- */
- StorageFormat storageFormat;
-
- /** An optional InterprocessLock object that will be used to prevent multiple threads or
- processes from writing to the file at the same time. The PropertiesFile will keep a
- pointer to this object but will not take ownership of it - the caller is responsible for
- making sure that the lock doesn't get deleted before the PropertiesFile has been deleted.
- The default constructor initialises this value to nullptr, so you don't need to touch it
- unless you want to use a lock.
- */
- InterProcessLock* processLock;
-
- /** This can be called to suggest a file that should be used, based on the values
- in this structure.
-
- So on a Mac, this will return a file called:
- ~/Library/[osxLibrarySubFolder]/[folderName]/[applicationName].[filenameSuffix]
-
- On Windows it'll return something like:
- C:\\Documents and Settings\\username\\Application Data\\[folderName]\\[applicationName].[filenameSuffix]
-
- On Linux it'll return
- ~/[folderName]/[applicationName].[filenameSuffix]
-
- If the folderName variable is empty, it'll use the app name for this (or omit the
- folder name on the Mac).
-
- The paths will also vary depending on whether commonToAllUsers is true.
- */
- File getDefaultFile() const;
- };
-
- //==============================================================================
- /** Creates a PropertiesFile object.
- The file used will be chosen by calling PropertiesFile::Options::getDefaultFile()
- for the options provided. To set the file explicitly, use the other constructor.
- */
- explicit PropertiesFile (const Options& options);
-
- /** Creates a PropertiesFile object.
- Unlike the other constructor, this one allows you to explicitly set the file that you
- want to be used, rather than using the default one.
- */
- PropertiesFile (const File& file,
- const Options& options);
-
- /** Destructor.
- When deleted, the file will first call saveIfNeeded() to flush any changes to disk.
- */
- ~PropertiesFile();
-
- //==============================================================================
- /** Returns true if this file was created from a valid (or non-existent) file.
- If the file failed to load correctly because it was corrupt or had insufficient
- access, this will be false.
- */
- bool isValidFile() const noexcept { return loadedOk; }
-
- //==============================================================================
- /** This will flush all the values to disk if they've changed since the last
- time they were saved.
-
- Returns false if it fails to write to the file for some reason (maybe because
- it's read-only or the directory doesn't exist or something).
-
- @see save
- */
- bool saveIfNeeded();
-
- /** This will force a write-to-disk of the current values, regardless of whether
- anything has changed since the last save.
-
- Returns false if it fails to write to the file for some reason (maybe because
- it's read-only or the directory doesn't exist or something).
-
- @see saveIfNeeded
- */
- bool save();
-
- /** Returns true if the properties have been altered since the last time they were saved.
- The file is flagged as needing to be saved when you change a value, but you can
- explicitly set this flag with setNeedsToBeSaved().
- */
- bool needsToBeSaved() const;
-
- /** Explicitly sets the flag to indicate whether the file needs saving or not.
- @see needsToBeSaved
- */
- void setNeedsToBeSaved (bool needsToBeSaved);
-
- /** Attempts to reload the settings from the file. */
- bool reload();
-
- //==============================================================================
- /** Returns the file that's being used. */
- const File& getFile() const noexcept { return file; }
-
-
- protected:
- /** @internal */
- virtual void propertyChanged();
-
- private:
- //==============================================================================
- File file;
- Options options;
- bool loadedOk, needsWriting;
-
- typedef const ScopedPointer<InterProcessLock::ScopedLockType> ProcessScopedLock;
- InterProcessLock::ScopedLockType* createProcessLock() const;
-
- void timerCallback() override;
- bool saveAsXml();
- bool saveAsBinary();
- bool loadAsXml();
- bool loadAsBinary();
- bool loadAsBinary (InputStream&);
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertiesFile)
- };
-
- #endif // JUCE_PROPERTIESFILE_H_INCLUDED
|