mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-21 16:37:12 +01:00
New library for preferences...
... It mentions some wxWidgets types in its interface, but these are in the acceptable utility subset of wxBase that we still consider GUI toolkit-neutral.
This commit is contained in:
286
libraries/lib-preferences/FileConfig.cpp
Normal file
286
libraries/lib-preferences/FileConfig.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
FileConfig.cpp
|
||||
|
||||
Leland Lucius
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
#include "FileConfig.h"
|
||||
|
||||
#include <cerrno> // for ENOENT
|
||||
|
||||
#if !defined(F_OK)
|
||||
#define F_OK 0x00
|
||||
#endif
|
||||
#if !defined(W_OK)
|
||||
#define W_OK 0x02
|
||||
#endif
|
||||
#if !defined(R_OK)
|
||||
#define R_OK 0x04
|
||||
#endif
|
||||
|
||||
FileConfig::FileConfig(const wxString& appName,
|
||||
const wxString& vendorName,
|
||||
const wxString& localFilename,
|
||||
const wxString& globalFilename,
|
||||
long style,
|
||||
const wxMBConv& conv)
|
||||
: wxConfigBase(appName, vendorName, localFilename, globalFilename, style),
|
||||
mAppName(appName),
|
||||
mVendorName(vendorName),
|
||||
mLocalFilename(localFilename),
|
||||
mGlobalFilename(globalFilename),
|
||||
mStyle(style),
|
||||
mConv(conv),
|
||||
mDirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
void FileConfig::Init()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
mConfig = std::make_unique<wxFileConfig>
|
||||
(mAppName, mVendorName, mLocalFilename, mGlobalFilename, mStyle, mConv);
|
||||
|
||||
// Prevent wxFileConfig from attempting a Flush() during object deletion. This happens
|
||||
// because we don't use the wxFileConfig::Flush() method and so the wxFileConfig dirty
|
||||
// flag never gets reset. During deletion, the dirty flag is checked and a Flush()
|
||||
// performed. This can (and probably will) create bogus temporary files.
|
||||
mConfig->DisableAutoSave();
|
||||
|
||||
bool canRead = false;
|
||||
bool canWrite = false;
|
||||
int fd;
|
||||
|
||||
fd = wxOpen(mLocalFilename, O_RDONLY, S_IREAD);
|
||||
if (fd != -1 || errno == ENOENT)
|
||||
{
|
||||
canRead = true;
|
||||
if (fd != -1)
|
||||
{
|
||||
wxClose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
fd = wxOpen(mLocalFilename, O_WRONLY | O_CREAT, S_IWRITE);
|
||||
if (fd != -1)
|
||||
{
|
||||
canWrite = true;
|
||||
wxClose(fd);
|
||||
}
|
||||
|
||||
if (canRead && canWrite)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Warn();
|
||||
}
|
||||
}
|
||||
|
||||
FileConfig::~FileConfig()
|
||||
{
|
||||
wxASSERT(mDirty == false);
|
||||
}
|
||||
|
||||
void FileConfig::SetPath(const wxString& strPath)
|
||||
{
|
||||
mConfig->SetPath(strPath);
|
||||
}
|
||||
|
||||
const wxString& FileConfig::GetPath() const
|
||||
{
|
||||
return mConfig->GetPath();
|
||||
}
|
||||
|
||||
bool FileConfig::GetFirstGroup(wxString& str, long& lIndex) const
|
||||
{
|
||||
return mConfig->GetFirstGroup(str, lIndex);
|
||||
}
|
||||
|
||||
bool FileConfig::GetNextGroup(wxString& str, long& lIndex) const
|
||||
{
|
||||
return mConfig->GetNextGroup(str, lIndex);
|
||||
}
|
||||
|
||||
bool FileConfig::GetFirstEntry(wxString& str, long& lIndex) const
|
||||
{
|
||||
return mConfig->GetFirstEntry(str, lIndex);
|
||||
}
|
||||
|
||||
bool FileConfig::GetNextEntry(wxString& str, long& lIndex) const
|
||||
{
|
||||
return mConfig->GetNextEntry(str, lIndex);
|
||||
}
|
||||
|
||||
size_t FileConfig::GetNumberOfEntries(bool bRecursive) const
|
||||
{
|
||||
return mConfig->GetNumberOfEntries(bRecursive);
|
||||
}
|
||||
|
||||
size_t FileConfig::GetNumberOfGroups(bool bRecursive) const
|
||||
{
|
||||
return mConfig->GetNumberOfGroups(bRecursive);
|
||||
}
|
||||
|
||||
bool FileConfig::HasGroup(const wxString& strName) const
|
||||
{
|
||||
return mConfig->HasGroup(strName);
|
||||
}
|
||||
|
||||
bool FileConfig::HasEntry(const wxString& strName) const
|
||||
{
|
||||
return mConfig->HasEntry(strName);
|
||||
}
|
||||
|
||||
bool FileConfig::Flush(bool WXUNUSED(bCurrentOnly))
|
||||
{
|
||||
if (!mDirty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
FilePath backup = mLocalFilename + ".bkp";
|
||||
|
||||
if (!wxFileExists(backup) || (wxRemove(backup) == 0))
|
||||
{
|
||||
if (!wxFileExists(mLocalFilename) || (wxRename(mLocalFilename, backup) == 0))
|
||||
{
|
||||
wxFileOutputStream stream(mLocalFilename);
|
||||
if (stream.IsOk())
|
||||
{
|
||||
if (mConfig->Save(stream))
|
||||
{
|
||||
stream.Sync();
|
||||
if (stream.IsOk() && stream.Close())
|
||||
{
|
||||
if (!wxFileExists(backup) || (wxRemove(backup) == 0))
|
||||
{
|
||||
mDirty = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wxFileExists(backup))
|
||||
{
|
||||
wxRemove(mLocalFilename);
|
||||
wxRename(backup, mLocalFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Warn();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileConfig::RenameEntry(const wxString& oldName, const wxString& newName)
|
||||
{
|
||||
auto res = mConfig->RenameEntry(oldName, newName);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::RenameGroup(const wxString& oldName, const wxString& newName)
|
||||
{
|
||||
auto res = mConfig->RenameGroup(oldName, newName);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::DeleteEntry(const wxString& key, bool bDeleteGroupIfEmpty)
|
||||
{
|
||||
auto res = mConfig->DeleteEntry(key, bDeleteGroupIfEmpty);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::DeleteGroup(const wxString& key)
|
||||
{
|
||||
auto res = mConfig->DeleteGroup(key);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::DeleteAll()
|
||||
{
|
||||
auto res = mConfig->DeleteAll();
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::DoReadString(const wxString& key, wxString *pStr) const
|
||||
{
|
||||
return mConfig->Read(key, pStr);
|
||||
}
|
||||
|
||||
bool FileConfig::DoReadLong(const wxString& key, long *pl) const
|
||||
{
|
||||
return mConfig->Read(key, pl);
|
||||
}
|
||||
|
||||
#if wxUSE_BASE64
|
||||
bool FileConfig::DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const
|
||||
{
|
||||
return mConfig->Read(key, buf);
|
||||
}
|
||||
#endif // wxUSE_BASE64
|
||||
|
||||
bool FileConfig::DoWriteString(const wxString& key, const wxString& szValue)
|
||||
{
|
||||
bool res = mConfig->Write(key, szValue);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FileConfig::DoWriteLong(const wxString& key, long lValue)
|
||||
{
|
||||
bool res = mConfig->Write(key, lValue);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if wxUSE_BASE64
|
||||
bool FileConfig::DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf)
|
||||
{
|
||||
bool res = mConfig->Write(key, buf);
|
||||
if (res)
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif // wxUSE_BASE64
|
||||
Reference in New Issue
Block a user