mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-04 03:40:07 +00:00
Refactored the PropertiesFile construction, introducing a PropertiesFile::Options structure to hold all the settings that previously were just passed as parameters. Also added a mandatory option for setting the OSX preferences path to be used - see the PropertiesFile::Options::osxLibrarySubFolder value for details.
Also on OSX, changed the location used for interprocess lock files to /var/tmp - this may affect applications which try to share locks with older builds of the same app.
This commit is contained in:
parent
b94782d388
commit
74469aaa83
15 changed files with 568 additions and 433 deletions
|
|
@ -54,27 +54,99 @@ namespace PropertyFileConstants
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving,
|
||||
const int options_, InterProcessLock* const processLock_)
|
||||
: PropertySet (ignoreCaseOfKeyNames),
|
||||
file (f),
|
||||
timerInterval (millisecondsBeforeSaving),
|
||||
options (options_),
|
||||
loadedOk (false),
|
||||
needsWriting (false),
|
||||
processLock (processLock_)
|
||||
PropertiesFile::Options::Options()
|
||||
: commonToAllUsers (false),
|
||||
ignoreCaseOfKeyNames (false),
|
||||
millisecondsBeforeSaving (3000),
|
||||
storageFormat (PropertiesFile::storeAsXML),
|
||||
processLock (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
File PropertiesFile::Options::getDefaultFile() const
|
||||
{
|
||||
// mustn't have illegal characters in this name..
|
||||
jassert (applicationName == File::createLegalFileName (applicationName));
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
File dir (commonToAllUsers ? "/Library/"
|
||||
: "~/Library/");
|
||||
|
||||
if (osxLibrarySubFolder != "Preferences" && osxLibrarySubFolder != "Application Support")
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
jassertfalse;
|
||||
|
||||
dir = dir.getChildFile ("Application Support");
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = dir.getChildFile (osxLibrarySubFolder);
|
||||
}
|
||||
|
||||
if (folderName.isNotEmpty())
|
||||
dir = dir.getChildFile (folderName);
|
||||
|
||||
#elif JUCE_LINUX || JUCE_ANDROID
|
||||
const File dir ((commonToAllUsers ? "/var/" : "~/")
|
||||
+ (folderName.isNotEmpty() ? folderName
|
||||
: ("." + applicationName)));
|
||||
|
||||
#elif JUCE_WINDOWS
|
||||
File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory
|
||||
: File::userApplicationDataDirectory));
|
||||
|
||||
if (dir == File::nonexistent)
|
||||
return File::nonexistent;
|
||||
|
||||
dir = dir.getChildFile (folderName.isNotEmpty() ? folderName
|
||||
: applicationName);
|
||||
#endif
|
||||
|
||||
return dir.getChildFile (applicationName)
|
||||
.withFileExtension (filenameSuffix);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PropertiesFile::PropertiesFile (const File& file_, const Options& options_)
|
||||
: PropertySet (options.ignoreCaseOfKeyNames),
|
||||
file (file_), options (options_),
|
||||
loadedOk (false), needsWriting (false)
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
|
||||
PropertiesFile::PropertiesFile (const Options& options_)
|
||||
: PropertySet (options.ignoreCaseOfKeyNames),
|
||||
file (options_.getDefaultFile()), options (options_),
|
||||
loadedOk (false), needsWriting (false)
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
|
||||
void PropertiesFile::initialise()
|
||||
{
|
||||
// You need to correctly specify just one storage format for the file
|
||||
jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary
|
||||
|| (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary
|
||||
|| (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML);
|
||||
|
||||
ProcessScopedLock pl (createProcessLock());
|
||||
|
||||
if (pl != nullptr && ! pl->isLocked())
|
||||
return; // locking failure..
|
||||
|
||||
ScopedPointer<InputStream> fileStream (f.createInputStream());
|
||||
ScopedPointer<InputStream> fileStream (file.createInputStream());
|
||||
|
||||
if (fileStream != nullptr)
|
||||
{
|
||||
|
|
@ -108,7 +180,7 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin
|
|||
// Not a binary props file - let's see if it's XML..
|
||||
fileStream = nullptr;
|
||||
|
||||
XmlDocument parser (f);
|
||||
XmlDocument parser (file);
|
||||
ScopedPointer<XmlElement> doc (parser.getDocumentElement (true));
|
||||
|
||||
if (doc != nullptr && doc->hasTagName (PropertyFileConstants::fileTag))
|
||||
|
|
@ -144,7 +216,7 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin
|
|||
}
|
||||
else
|
||||
{
|
||||
loadedOk = ! f.exists();
|
||||
loadedOk = ! file.exists();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +228,7 @@ PropertiesFile::~PropertiesFile()
|
|||
|
||||
InterProcessLock::ScopedLockType* PropertiesFile::createProcessLock() const
|
||||
{
|
||||
return processLock != nullptr ? new InterProcessLock::ScopedLockType (*processLock) : nullptr;
|
||||
return options.processLock != nullptr ? new InterProcessLock::ScopedLockType (*options.processLock) : nullptr;
|
||||
}
|
||||
|
||||
bool PropertiesFile::saveIfNeeded()
|
||||
|
|
@ -188,7 +260,7 @@ bool PropertiesFile::save()
|
|||
|| ! file.getParentDirectory().createDirectory())
|
||||
return false;
|
||||
|
||||
if ((options & storeAsXML) != 0)
|
||||
if (options.storageFormat == storeAsXML)
|
||||
{
|
||||
XmlElement doc (PropertyFileConstants::fileTag);
|
||||
|
||||
|
|
@ -230,7 +302,7 @@ bool PropertiesFile::save()
|
|||
|
||||
if (out != nullptr)
|
||||
{
|
||||
if ((options & storeAsCompressedBinary) != 0)
|
||||
if (options.storageFormat == storeAsCompressedBinary)
|
||||
{
|
||||
out->writeInt (PropertyFileConstants::magicNumberCompressed);
|
||||
out->flush();
|
||||
|
|
@ -240,7 +312,7 @@ bool PropertiesFile::save()
|
|||
else
|
||||
{
|
||||
// have you set up the storage option flags correctly?
|
||||
jassert ((options & storeAsBinary) != 0);
|
||||
jassert (options.storageFormat == storeAsBinary);
|
||||
|
||||
out->writeInt (PropertyFileConstants::magicNumber);
|
||||
}
|
||||
|
|
@ -279,66 +351,11 @@ void PropertiesFile::propertyChanged()
|
|||
|
||||
needsWriting = true;
|
||||
|
||||
if (timerInterval > 0)
|
||||
startTimer (timerInterval);
|
||||
else if (timerInterval == 0)
|
||||
if (options.millisecondsBeforeSaving > 0)
|
||||
startTimer (options.millisecondsBeforeSaving);
|
||||
else if (options.millisecondsBeforeSaving == 0)
|
||||
saveIfNeeded();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
File PropertiesFile::getDefaultAppSettingsFile (const String& applicationName,
|
||||
const String& fileNameSuffix,
|
||||
const String& folderName,
|
||||
const bool commonToAllUsers)
|
||||
{
|
||||
// mustn't have illegal characters in this name..
|
||||
jassert (applicationName == File::createLegalFileName (applicationName));
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
File dir (commonToAllUsers ? "/Library/Preferences"
|
||||
: "~/Library/Preferences");
|
||||
|
||||
if (folderName.isNotEmpty())
|
||||
dir = dir.getChildFile (folderName);
|
||||
#elif JUCE_LINUX || JUCE_ANDROID
|
||||
const File dir ((commonToAllUsers ? "/var/" : "~/")
|
||||
+ (folderName.isNotEmpty() ? folderName
|
||||
: ("." + applicationName)));
|
||||
#elif JUCE_WINDOWS
|
||||
File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory
|
||||
: File::userApplicationDataDirectory));
|
||||
|
||||
if (dir == File::nonexistent)
|
||||
return File::nonexistent;
|
||||
|
||||
dir = dir.getChildFile (folderName.isNotEmpty() ? folderName
|
||||
: applicationName);
|
||||
#endif
|
||||
|
||||
return dir.getChildFile (applicationName)
|
||||
.withFileExtension (fileNameSuffix);
|
||||
}
|
||||
|
||||
PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& applicationName,
|
||||
const String& fileNameSuffix,
|
||||
const String& folderName,
|
||||
const bool commonToAllUsers,
|
||||
const int millisecondsBeforeSaving,
|
||||
const int propertiesFileOptions,
|
||||
InterProcessLock* processLock_)
|
||||
{
|
||||
const File file (getDefaultAppSettingsFile (applicationName,
|
||||
fileNameSuffix,
|
||||
folderName,
|
||||
commonToAllUsers));
|
||||
|
||||
jassert (file != File::nonexistent);
|
||||
|
||||
if (file == File::nonexistent)
|
||||
return nullptr;
|
||||
|
||||
return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions,processLock_);
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue