Merge branch 'config-xdg'
Make it easier to use wxFileConfig in XDG-compliant way. See #24180.
This commit is contained in:
commit
b294a6b2bc
15 changed files with 372 additions and 40 deletions
|
|
@ -168,6 +168,10 @@ Currently the following symbols exist:
|
||||||
implemented in a generic way, using a critical section.}
|
implemented in a generic way, using a critical section.}
|
||||||
@itemdef{wxHAS_BITMAPTOGGLEBUTTON, Defined in @c wx/tglbtn.h if
|
@itemdef{wxHAS_BITMAPTOGGLEBUTTON, Defined in @c wx/tglbtn.h if
|
||||||
wxBitmapToggleButton class is available in addition to wxToggleButton.}
|
wxBitmapToggleButton class is available in addition to wxToggleButton.}
|
||||||
|
@itemdef{wxHAS_CONFIG_AS_FILECONFIG, Defined if wxConfig is defined as
|
||||||
|
wxFileConfig. This constant is available since wxWidgets 3.3.0.}
|
||||||
|
@itemdef{wxHAS_CONFIG_AS_REGCONFIG, Defined if wxConfig is defined as
|
||||||
|
wxRegConfig. This constant is available since wxWidgets 3.3.0.}
|
||||||
@itemdef{wxHAS_CONFIG_TEMPLATE_RW, Defined if the currently used compiler
|
@itemdef{wxHAS_CONFIG_TEMPLATE_RW, Defined if the currently used compiler
|
||||||
supports template Read() and Write() methods in wxConfig.}
|
supports template Read() and Write() methods in wxConfig.}
|
||||||
@itemdef{wxHAS_DEPRECATED_ATTR, Defined if C++14 @c [[deprecated]] attribute is
|
@itemdef{wxHAS_DEPRECATED_ATTR, Defined if C++14 @c [[deprecated]] attribute is
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ enum
|
||||||
wxCONFIG_USE_GLOBAL_FILE = 2,
|
wxCONFIG_USE_GLOBAL_FILE = 2,
|
||||||
wxCONFIG_USE_RELATIVE_PATH = 4,
|
wxCONFIG_USE_RELATIVE_PATH = 4,
|
||||||
wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8,
|
wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8,
|
||||||
wxCONFIG_USE_SUBDIR = 16
|
wxCONFIG_USE_SUBDIR = 16,
|
||||||
|
wxCONFIG_USE_XDG = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,11 @@
|
||||||
#if defined(__WINDOWS__) && wxUSE_CONFIG_NATIVE
|
#if defined(__WINDOWS__) && wxUSE_CONFIG_NATIVE
|
||||||
#include "wx/msw/regconf.h"
|
#include "wx/msw/regconf.h"
|
||||||
#define wxConfig wxRegConfig
|
#define wxConfig wxRegConfig
|
||||||
|
#define wxHAS_CONFIG_AS_REGCONFIG
|
||||||
#else // either we're under Unix or wish to always use config files
|
#else // either we're under Unix or wish to always use config files
|
||||||
#include "wx/fileconf.h"
|
#include "wx/fileconf.h"
|
||||||
#define wxConfig wxFileConfig
|
#define wxConfig wxFileConfig
|
||||||
|
#define wxHAS_CONFIG_AS_FILECONFIG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // wxUSE_CONFIG
|
#endif // wxUSE_CONFIG
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,22 @@ public:
|
||||||
return GetLocalFile(szFile, style).GetFullPath();
|
return GetLocalFile(szFile, style).GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to migrate, i.e. move, an existing local config file to another
|
||||||
|
// location. Old and new style determine the existing and new file paths.
|
||||||
|
struct MigrationResult
|
||||||
|
{
|
||||||
|
// If empty, it means the old file wasn't found and nothing was done.
|
||||||
|
wxString oldPath;
|
||||||
|
|
||||||
|
// The name of the new file.
|
||||||
|
wxString newPath;
|
||||||
|
|
||||||
|
// If empty, means the file was successfully migrated.
|
||||||
|
wxString error;
|
||||||
|
};
|
||||||
|
static MigrationResult
|
||||||
|
MigrateLocalFile(const wxString& name, int newStyle, int oldStyle = 0);
|
||||||
|
|
||||||
// ctor & dtor
|
// ctor & dtor
|
||||||
// New constructor: one size fits all. Specify wxCONFIG_USE_LOCAL_FILE or
|
// New constructor: one size fits all. Specify wxCONFIG_USE_LOCAL_FILE or
|
||||||
// wxCONFIG_USE_GLOBAL_FILE to say which files should be used.
|
// wxCONFIG_USE_GLOBAL_FILE to say which files should be used.
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ public:
|
||||||
enum Dir
|
enum Dir
|
||||||
{
|
{
|
||||||
Dir_Cache,
|
Dir_Cache,
|
||||||
|
Dir_Config,
|
||||||
Dir_Documents,
|
Dir_Documents,
|
||||||
Dir_Desktop,
|
Dir_Desktop,
|
||||||
Dir_Downloads,
|
Dir_Downloads,
|
||||||
|
|
@ -184,6 +185,11 @@ public:
|
||||||
|
|
||||||
bool UsesAppInfo(int info) const { return (m_usedAppInfo & info) != 0; }
|
bool UsesAppInfo(int info) const { return (m_usedAppInfo & info) != 0; }
|
||||||
|
|
||||||
|
// append application information determined by m_usedAppInfo to dir
|
||||||
|
wxNODISCARD
|
||||||
|
wxString AppendAppInfo(const wxString& dir) const;
|
||||||
|
|
||||||
|
|
||||||
void SetFileLayout(FileLayout layout)
|
void SetFileLayout(FileLayout layout)
|
||||||
{
|
{
|
||||||
m_fileLayout = layout;
|
m_fileLayout = layout;
|
||||||
|
|
@ -203,10 +209,6 @@ protected:
|
||||||
// path separator or dot (.) is not already at the end of dir
|
// path separator or dot (.) is not already at the end of dir
|
||||||
static wxString AppendPathComponent(const wxString& dir, const wxString& component);
|
static wxString AppendPathComponent(const wxString& dir, const wxString& component);
|
||||||
|
|
||||||
// append application information determined by m_usedAppInfo to dir
|
|
||||||
wxString AppendAppInfo(const wxString& dir) const;
|
|
||||||
|
|
||||||
|
|
||||||
// combination of AppInfo_XXX flags used by AppendAppInfo()
|
// combination of AppInfo_XXX flags used by AppendAppInfo()
|
||||||
int m_usedAppInfo;
|
int m_usedAppInfo;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,41 @@
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// Flags for constructor style parameter
|
/// Flags for wxConfig constructor style parameter.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
wxCONFIG_USE_LOCAL_FILE = 1,
|
wxCONFIG_USE_LOCAL_FILE = 1,
|
||||||
wxCONFIG_USE_GLOBAL_FILE = 2,
|
wxCONFIG_USE_GLOBAL_FILE = 2,
|
||||||
wxCONFIG_USE_RELATIVE_PATH = 4,
|
wxCONFIG_USE_RELATIVE_PATH = 4,
|
||||||
wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8,
|
wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8,
|
||||||
wxCONFIG_USE_SUBDIR = 16
|
|
||||||
|
/**
|
||||||
|
Use subdirectory for the local configuration file location.
|
||||||
|
|
||||||
|
Specifying this flag changes the default local configuration file
|
||||||
|
location to `~/.appname/appname.conf`. Please note that this path is
|
||||||
|
_not_ affected by layout set using wxStandardPaths::SetFileLayout() and
|
||||||
|
it is recommended to use wxCONFIG_USE_XDG flag in addition to this file
|
||||||
|
on contemporary Linux systems.
|
||||||
|
|
||||||
|
@since 2.8.2
|
||||||
|
*/
|
||||||
|
wxCONFIG_USE_SUBDIR = 16,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Use XDG-compliant file location on Unix systems.
|
||||||
|
|
||||||
|
If wxCONFIG_USE_SUBDIR is not specified, using this flag has the same
|
||||||
|
effect as calling wxStandardPaths::SetFileLayout() with
|
||||||
|
wxStandardPaths::FileLayout_XDG, i.e. it changes the default local
|
||||||
|
configuration file location to `~/.config/appname.conf`.
|
||||||
|
|
||||||
|
In combination with wxCONFIG_USE_SUBDIR, this flag changes the default
|
||||||
|
configuration file location to ~/.config/appname/appname.conf`.
|
||||||
|
|
||||||
|
@since 3.3.0
|
||||||
|
*/
|
||||||
|
wxCONFIG_USE_XDG = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,7 +57,9 @@ enum
|
||||||
with the registry under Windows or text-based config files under Unix.
|
with the registry under Windows or text-based config files under Unix.
|
||||||
To make writing the portable code even easier, wxWidgets provides a typedef
|
To make writing the portable code even easier, wxWidgets provides a typedef
|
||||||
wxConfig which is mapped onto the native wxConfigBase implementation on the
|
wxConfig which is mapped onto the native wxConfigBase implementation on the
|
||||||
given platform: i.e. wxRegConfig under Windows and wxFileConfig otherwise.
|
given platform: i.e. wxRegConfig under Windows (in this case
|
||||||
|
`wxHAS_CONFIG_AS_REGCONFIG` preprocessor symbol is defined) and
|
||||||
|
wxFileConfig otherwise (in this case `wxHAS_CONFIG_AS_FILECONFIG` is).
|
||||||
|
|
||||||
See @ref overview_config for a description of all features of this class.
|
See @ref overview_config for a description of all features of this class.
|
||||||
|
|
||||||
|
|
@ -296,14 +325,16 @@ public:
|
||||||
@n For wxFileConfig you can also add @c wxCONFIG_USE_RELATIVE_PATH by
|
@n For wxFileConfig you can also add @c wxCONFIG_USE_RELATIVE_PATH by
|
||||||
logically or'ing it to either of the _FILE options to tell
|
logically or'ing it to either of the _FILE options to tell
|
||||||
wxFileConfig to use relative instead of absolute paths.
|
wxFileConfig to use relative instead of absolute paths.
|
||||||
@n On non-VMS Unix systems, the default local configuration file is
|
@n On Unix-like systems, the default local configuration file is
|
||||||
"~/.appname". However, this path may be also used as user data
|
`~/.appname` unless wxStandardPaths::SetFileLayout() is called with
|
||||||
|
wxStandardPaths::FileLayout_XDG parameter in which case the default
|
||||||
|
becomes `~/.config/appname.conf`.
|
||||||
|
@n Note that this default path may be also used as user data
|
||||||
directory (see wxStandardPaths::GetUserDataDir()) if the
|
directory (see wxStandardPaths::GetUserDataDir()) if the
|
||||||
application has several data files. In this case
|
application has several data files. In this case it is recommended
|
||||||
@c wxCONFIG_USE_SUBDIR flag, which changes the default local
|
to use ::wxCONFIG_USE_XDG flag (available since wxWidgets 3.3.0)
|
||||||
configuration file to "~/.appname/appname" should be used. Notice
|
and/or older ::wxCONFIG_USE_SUBDIR (available since 2.8.2) to
|
||||||
that this flag is ignored if @a localFilename is provided.
|
change the default local configuration file location.
|
||||||
@c wxCONFIG_USE_SUBDIR is new since wxWidgets version 2.8.2.
|
|
||||||
@n For wxFileConfig, you can also add
|
@n For wxFileConfig, you can also add
|
||||||
@c wxCONFIG_USE_NO_ESCAPE_CHARACTERS which will turn off character
|
@c wxCONFIG_USE_NO_ESCAPE_CHARACTERS which will turn off character
|
||||||
escaping for the values of entries stored in the config file: for
|
escaping for the values of entries stored in the config file: for
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,25 @@
|
||||||
used explicitly if you want to use files and not the registry even under
|
used explicitly if you want to use files and not the registry even under
|
||||||
Windows.
|
Windows.
|
||||||
|
|
||||||
|
@section fileconf_paths Configuration Files Paths
|
||||||
|
|
||||||
|
The default path for local (or user) configuration file is `~/.appname`,
|
||||||
|
i.e. it is stored directly in the user home directory. This default
|
||||||
|
path is backwards-compatible but not recommended any more and it is advised
|
||||||
|
to call wxStandardPaths::SetFileLayout() with
|
||||||
|
wxStandardPaths::FileLayout_XDG parameter to change the default path to
|
||||||
|
`~/.config/appname.conf`. MigrateLocalFile() may be helpful for moving the
|
||||||
|
existing configuration file to the new location.
|
||||||
|
|
||||||
|
Alternatively, it is possible to specify ::wxCONFIG_USE_XDG flag in the
|
||||||
|
style parameter of the constructor to use this XDG-compliant path without
|
||||||
|
changing the global file layout.
|
||||||
|
|
||||||
|
And for the programs using multiple configuration files it is recommended
|
||||||
|
to use both ::wxCONFIG_USE_XDG and ::wxCONFIG_USE_SUBDIR which change the
|
||||||
|
default file path to `~/.config/appname/appname.conf` -- and allow the
|
||||||
|
program to store other files in the same `~/.config/appname` directory.
|
||||||
|
|
||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{cfg}
|
@category{cfg}
|
||||||
|
|
||||||
|
|
@ -71,8 +90,8 @@ public:
|
||||||
parameter in the constructor.
|
parameter in the constructor.
|
||||||
|
|
||||||
@a style has the same meaning as in @ref wxConfigBase::wxConfigBase "wxConfig constructor"
|
@a style has the same meaning as in @ref wxConfigBase::wxConfigBase "wxConfig constructor"
|
||||||
and can contain any combination of styles but only wxCONFIG_USE_SUBDIR bit is
|
and can contain any combination of styles but only wxCONFIG_USE_SUBDIR
|
||||||
examined by this function.
|
and wxCONFIG_USE_XDG are really used by this function.
|
||||||
|
|
||||||
Notice that this function cannot be used if @a basename is already a full path name.
|
Notice that this function cannot be used if @a basename is already a full path name.
|
||||||
*/
|
*/
|
||||||
|
|
@ -81,6 +100,70 @@ public:
|
||||||
static wxString GetGlobalFileName(const wxString& szFile);
|
static wxString GetGlobalFileName(const wxString& szFile);
|
||||||
static wxString GetLocalFileName(const wxString& szFile, int style = 0);
|
static wxString GetLocalFileName(const wxString& szFile, int style = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Contains return value of MigrateLocalFile().
|
||||||
|
|
||||||
|
@since 3.3.0
|
||||||
|
*/
|
||||||
|
struct MigrationResult
|
||||||
|
{
|
||||||
|
/// If empty, it means the old file wasn't found and nothing was done.
|
||||||
|
wxString oldPath;
|
||||||
|
|
||||||
|
/// The name of the new file.
|
||||||
|
wxString newPath;
|
||||||
|
|
||||||
|
/// If empty, means the file was successfully migrated.
|
||||||
|
wxString error;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Move the existing configuration file to a new location.
|
||||||
|
|
||||||
|
This function is useful for moving legacy configuration files in
|
||||||
|
`~/.appname` or `~/.appname/appname.conf` to the XDG-compliant location
|
||||||
|
under `~/.config`. To do this, simply specify ::wxCONFIG_USE_XDG as
|
||||||
|
part of @a newStyle.
|
||||||
|
|
||||||
|
The returned MigrationResult object describes what, if anything, was
|
||||||
|
done: if its `oldPath` member is empty, it means that the file
|
||||||
|
corresponding to @a oldStyle was not found and nothing was done.
|
||||||
|
Otherwise, if its `error` member is empty, the old file was found and
|
||||||
|
moved to `newPath`. And if `error` is not empty, it contains the
|
||||||
|
user-readable error message describing why moving the file failed.
|
||||||
|
|
||||||
|
Typical example of using this function is shown in the widgets sample:
|
||||||
|
@code
|
||||||
|
// Execute this early during the application startup, before the
|
||||||
|
// global wxConfig object is created.
|
||||||
|
const auto res = wxFileConfig::MigrateLocalFile("app", wxCONFIG_USE_XDG);
|
||||||
|
if ( !res.oldPath.empty() ) {
|
||||||
|
if ( res.error.empty() ) {
|
||||||
|
wxLogMessage("Config file was migrated from \"%s\" to \"%s\"",
|
||||||
|
res.oldPath, res.newPath);
|
||||||
|
} else {
|
||||||
|
wxLogWarning("Migrating old config failed: %s.", res.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that this must be done after calling MigrateLocalFile(),
|
||||||
|
// otherwise the old style would use XDG layout already and the actual
|
||||||
|
// file at non-XDG-compliant location wouldn't be migrated.
|
||||||
|
wxStandardPaths::Get().SetFileLayout(wxStandardPaths::FileLayout_XDG);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@param name Name of the configuration file.
|
||||||
|
@param newStyle Style which is used by the current version of the
|
||||||
|
program, typically including ::wxCONFIG_USE_XDG and possibly also
|
||||||
|
including ::wxCONFIG_USE_SUBDIR.
|
||||||
|
@param oldStyle Style which was used by the previous versions of the
|
||||||
|
program, possibly including ::wxCONFIG_USE_SUBDIR.
|
||||||
|
|
||||||
|
@since 3.3.0
|
||||||
|
*/
|
||||||
|
static MigrationResult
|
||||||
|
MigrateLocalFile(const wxString& name, int newStyle, int oldStyle = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Saves all config data to the given stream, returns @true if data was saved
|
Saves all config data to the given stream, returns @true if data was saved
|
||||||
successfully or @false on error.
|
successfully or @false on error.
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,18 @@ public:
|
||||||
*/
|
*/
|
||||||
Dir_Cache,
|
Dir_Cache,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Directory containing configuration information.
|
||||||
|
|
||||||
|
Example return values:
|
||||||
|
- Unix: `~/.config`
|
||||||
|
- Windows: `C:\Users\username\AppData\Roaming`
|
||||||
|
- Mac: @c `~/Library/Preferences`
|
||||||
|
|
||||||
|
@since 3.3.0
|
||||||
|
*/
|
||||||
|
Dir_Config,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Directory containing user documents.
|
Directory containing user documents.
|
||||||
|
|
||||||
|
|
@ -195,6 +207,20 @@ public:
|
||||||
ConfigFileConv_Ext
|
ConfigFileConv_Ext
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Append application and/or vendor name to the given directory.
|
||||||
|
|
||||||
|
By default, appends the subdirectory with the application name, as
|
||||||
|
returned by wxApp::GetAppName(), to the given directory.
|
||||||
|
|
||||||
|
This behaviour is affected by UseAppInfo(), e.g. if this function is
|
||||||
|
called with `AppInfo_VendorName` then the vendor name would be appended
|
||||||
|
instead of the application name.
|
||||||
|
|
||||||
|
@since 3.3.0
|
||||||
|
*/
|
||||||
|
wxString AppendAppInfo(const wxString& dir) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
|
MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
|
||||||
|
|
||||||
|
|
@ -370,17 +396,25 @@ public:
|
||||||
- Mac: @c ~/Library/Preferences
|
- Mac: @c ~/Library/Preferences
|
||||||
|
|
||||||
Only use this method if you have a single configuration file to put in this
|
Only use this method if you have a single configuration file to put in this
|
||||||
directory, otherwise GetUserDataDir() is more appropriate as the latter
|
directory, otherwise calling AppendAppInfo() with the value returned by
|
||||||
adds @c appinfo to the path, unlike this function.
|
GetDir() with wxStandardPaths::Dir_Config is more appropriate.
|
||||||
*/
|
*/
|
||||||
virtual wxString GetUserConfigDir() const;
|
virtual wxString GetUserConfigDir() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return the directory for the user-dependent application data files:
|
Return the directory for the user-dependent application data files.
|
||||||
|
|
||||||
|
The returned path is:
|
||||||
|
|
||||||
- Unix: @c ~/.appinfo
|
- Unix: @c ~/.appinfo
|
||||||
- Windows: @c "C:\Users\username\AppData\Roaming\appinfo" or
|
- Windows: @c "C:\Users\username\AppData\Roaming\appinfo" or
|
||||||
@c "C:\Documents and Settings\username\Application Data\appinfo"
|
@c "C:\Documents and Settings\username\Application Data\appinfo"
|
||||||
- Mac: @c "~/Library/Application Support/appinfo"
|
- Mac: @c "~/Library/Application Support/appinfo"
|
||||||
|
|
||||||
|
Please note that under Unix this function return value doesn't depend
|
||||||
|
on the file layout, and so returns a possibly unexpected value when
|
||||||
|
wxStandardPaths::FileLayout_XDG is used. Consider using GetUserDir()
|
||||||
|
instead if you use XDG layout, as this function does respect it.
|
||||||
*/
|
*/
|
||||||
virtual wxString GetUserDataDir() const;
|
virtual wxString GetUserDataDir() const;
|
||||||
|
|
||||||
|
|
@ -505,6 +539,8 @@ public:
|
||||||
|
|
||||||
By default, only the application name is used.
|
By default, only the application name is used.
|
||||||
|
|
||||||
|
@see AppendAppInfo()
|
||||||
|
|
||||||
@since 2.9.0
|
@since 2.9.0
|
||||||
*/
|
*/
|
||||||
void UseAppInfo(int info);
|
void UseAppInfo(int info);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@
|
||||||
#include "wx/msgdlg.h"
|
#include "wx/msgdlg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "wx/config.h"
|
||||||
|
#include "wx/stdpaths.h"
|
||||||
|
|
||||||
#include "wx/sysopt.h"
|
#include "wx/sysopt.h"
|
||||||
#include "wx/bookctrl.h"
|
#include "wx/bookctrl.h"
|
||||||
#include "wx/treebook.h"
|
#include "wx/treebook.h"
|
||||||
|
|
@ -141,6 +144,30 @@ public:
|
||||||
#if USE_LOG
|
#if USE_LOG
|
||||||
m_logTarget = nullptr;
|
m_logTarget = nullptr;
|
||||||
#endif // USE_LOG
|
#endif // USE_LOG
|
||||||
|
|
||||||
|
#ifdef wxHAS_CONFIG_AS_FILECONFIG
|
||||||
|
// We want to put our config file (implicitly created for persistent
|
||||||
|
// controls settings) in XDG-compliant location, so we want to change
|
||||||
|
// the default file layout, but before doing this migrate any existing
|
||||||
|
// config files to the new location as the previous versions of this
|
||||||
|
// sample didn't use XDG layout.
|
||||||
|
const auto
|
||||||
|
res = wxFileConfig::MigrateLocalFile("widgets", wxCONFIG_USE_XDG);
|
||||||
|
if ( !res.oldPath.empty() )
|
||||||
|
{
|
||||||
|
if ( res.error.empty() )
|
||||||
|
{
|
||||||
|
wxLogMessage("Config file was migrated from \"%s\" to \"%s\"",
|
||||||
|
res.oldPath, res.newPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogWarning("Migrating old config failed: %s.", res.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxStandardPaths::Get().SetFileLayout(wxStandardPaths::FileLayout_XDG);
|
||||||
|
#endif // wxHAS_CONFIG_AS_FILECONFIG
|
||||||
}
|
}
|
||||||
WidgetsApp(const WidgetsApp&) = delete;
|
WidgetsApp(const WidgetsApp&) = delete;
|
||||||
WidgetsApp& operator=(const WidgetsApp&) = delete;
|
WidgetsApp& operator=(const WidgetsApp&) = delete;
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,13 @@ bool wxConfigBase::ms_bAutoCreate = true;
|
||||||
|
|
||||||
wxConfigBase *wxAppTraitsBase::CreateConfig()
|
wxConfigBase *wxAppTraitsBase::CreateConfig()
|
||||||
{
|
{
|
||||||
return new
|
#if defined(wxHAS_CONFIG_AS_REGCONFIG)
|
||||||
#if defined(__WINDOWS__) && wxUSE_CONFIG_NATIVE
|
return new wxRegConfig(wxTheApp->GetAppName(), wxTheApp->GetVendorName());
|
||||||
wxRegConfig(wxTheApp->GetAppName(), wxTheApp->GetVendorName());
|
#elif defined(wxHAS_CONFIG_AS_FILECONFIG)
|
||||||
#else // either we're under Unix or wish to use files even under Windows
|
return new wxFileConfig(wxTheApp->GetAppName());
|
||||||
wxFileConfig(wxTheApp->GetAppName());
|
#else
|
||||||
#endif
|
#error No wxConfig implementation defined.
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -247,42 +247,154 @@ wxString wxFileConfig::GetGlobalDir()
|
||||||
|
|
||||||
wxString wxFileConfig::GetLocalDir(int style)
|
wxString wxFileConfig::GetLocalDir(int style)
|
||||||
{
|
{
|
||||||
wxUnusedVar(style);
|
const wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||||
|
|
||||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
if ( style & wxCONFIG_USE_XDG )
|
||||||
|
{
|
||||||
|
// When XDG-compliant layout is requested, we need to use this function
|
||||||
|
// as GetUserDataDir() doesn't support it.
|
||||||
|
wxString dir = stdp.GetUserDir(wxStandardPaths::Dir_Config);
|
||||||
|
|
||||||
// it so happens that user data directory is a subdirectory of user config
|
if ( style & wxCONFIG_USE_SUBDIR )
|
||||||
// directory on all supported platforms, which explains why we use it here
|
dir = stdp.AppendAppInfo(dir);
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normally we'd like to use GetUserConfigDir() and just append app info
|
||||||
|
// subdirectories to it, but we can't do it for compatibility reasons:
|
||||||
|
// there are existing configuration files in the locations returned by
|
||||||
|
// these functions already, so return the same values as we always did.
|
||||||
return style & wxCONFIG_USE_SUBDIR ? stdp.GetUserDataDir()
|
return style & wxCONFIG_USE_SUBDIR ? stdp.GetUserDataDir()
|
||||||
: stdp.GetUserConfigDir();
|
: stdp.GetUserConfigDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxFileName wxFileConfig::GetGlobalFile(const wxString& szFile)
|
wxFileName wxFileConfig::GetGlobalFile(const wxString& szFile)
|
||||||
{
|
{
|
||||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
const wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||||
|
|
||||||
return wxFileName(GetGlobalDir(), stdp.MakeConfigFileName(szFile));
|
return wxFileName(GetGlobalDir(), stdp.MakeConfigFileName(szFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
|
wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
|
||||||
{
|
{
|
||||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
const wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||||
|
|
||||||
// If the config file is located in a subdirectory, we always use an
|
// If the config file is located in a subdirectory, we always use an
|
||||||
// extension for it, but we use just the leading dot if it is located
|
// extension for it, but we use just the leading dot if it is located
|
||||||
// directly in the home directory. Note that if wxStandardPaths is
|
// directly in the home directory. Note that if wxStandardPaths is
|
||||||
// configured to follow XDG specification, all config files go to a
|
// configured to follow XDG specification, all config files go to a
|
||||||
// subdirectory of XDG_CONFIG_HOME anyhow, so in this case we'll still end
|
// subdirectory of XDG_CONFIG_HOME anyhow, so in this case we'll still end
|
||||||
// up using the extension even if wxCONFIG_USE_SUBDIR is not set, but this
|
// up using the extension even if neither wxCONFIG_USE_SUBDIR nor
|
||||||
// is the correct and expected (if a little confusing) behaviour.
|
// wxCONFIG_USE_XDG is set, but this is the correct and expected (if a
|
||||||
|
// little confusing) behaviour.
|
||||||
const wxStandardPaths::ConfigFileConv
|
const wxStandardPaths::ConfigFileConv
|
||||||
conv = style & wxCONFIG_USE_SUBDIR
|
conv = style & (wxCONFIG_USE_SUBDIR | wxCONFIG_USE_XDG)
|
||||||
? wxStandardPaths::ConfigFileConv_Ext
|
? wxStandardPaths::ConfigFileConv_Ext
|
||||||
: wxStandardPaths::ConfigFileConv_Dot;
|
: wxStandardPaths::ConfigFileConv_Dot;
|
||||||
|
|
||||||
return wxFileName(GetLocalDir(style), stdp.MakeConfigFileName(szFile, conv));
|
return wxFileName(GetLocalDir(style), stdp.MakeConfigFileName(szFile, conv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxFileConfig::MigrationResult
|
||||||
|
wxFileConfig::MigrateLocalFile(const wxString& name, int newStyle, int oldStyle)
|
||||||
|
{
|
||||||
|
MigrationResult res;
|
||||||
|
|
||||||
|
const auto oldPath = GetLocalFile(name, oldStyle);
|
||||||
|
if ( !oldPath.FileExists() )
|
||||||
|
return res;
|
||||||
|
|
||||||
|
const auto newPath = GetLocalFile(name, newStyle);
|
||||||
|
if ( newPath == oldPath )
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res.oldPath = oldPath.GetFullPath();
|
||||||
|
res.newPath = newPath.GetFullPath();
|
||||||
|
|
||||||
|
// This class ensures that we (at least try to) rename the existing config
|
||||||
|
// file back to its original name if we fail with an error.
|
||||||
|
class RenameBackOnError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RenameBackOnError(wxFileConfig::MigrationResult& res)
|
||||||
|
: m_res(res)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(const wxString& tempPath)
|
||||||
|
{
|
||||||
|
m_tempPath = tempPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dismiss()
|
||||||
|
{
|
||||||
|
m_tempPath.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
~RenameBackOnError()
|
||||||
|
{
|
||||||
|
if ( !m_tempPath.empty() )
|
||||||
|
{
|
||||||
|
if ( !wxRenameFile(m_tempPath, m_res.oldPath) )
|
||||||
|
{
|
||||||
|
// This should never happen, but if it does, do at least
|
||||||
|
// let the user know that we moved their file to a wrong
|
||||||
|
// place and couldn't put it back.
|
||||||
|
m_res.error += wxString::Format(
|
||||||
|
_(" and additionally, the existing configuration file"
|
||||||
|
" was renamed to \"%s\" and couldn't be renamed back,"
|
||||||
|
" please rename it to its original path \"%s\""),
|
||||||
|
m_tempPath,
|
||||||
|
m_res.oldPath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MigrationResult& m_res;
|
||||||
|
|
||||||
|
wxString m_tempPath;
|
||||||
|
} renameBackOnError{res};
|
||||||
|
|
||||||
|
wxString currentPath = res.oldPath;
|
||||||
|
|
||||||
|
const auto newDir = newPath.GetPath();
|
||||||
|
if ( !wxFileName::DirExists(newDir) )
|
||||||
|
{
|
||||||
|
// There is an annoying failure mode here when the new directory can't
|
||||||
|
// be created because its name is the same as the name of the existing
|
||||||
|
// file, e.g. when oldStyle==0 and newStyle==wxCONFIG_USE_SUBDIR and
|
||||||
|
// XDG layout is not used, so check for this specially.
|
||||||
|
if ( newDir == res.oldPath )
|
||||||
|
{
|
||||||
|
currentPath = wxFileName::CreateTempFileName(currentPath);
|
||||||
|
if ( !wxRenameFile(res.oldPath, currentPath) )
|
||||||
|
{
|
||||||
|
res.error = _("failed to rename the existing file");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
renameBackOnError.Init(currentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !wxFileName::Mkdir(newDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL) )
|
||||||
|
{
|
||||||
|
res.error = _("failed to create the new file directory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !wxRenameFile(currentPath, res.newPath) )
|
||||||
|
{
|
||||||
|
res.error = _("failed to move the file to the new location");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ctor
|
// ctor
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -488,14 +488,18 @@ static void DoCommonPostCleanup()
|
||||||
|
|
||||||
void wxEntryCleanup()
|
void wxEntryCleanup()
|
||||||
{
|
{
|
||||||
DoCommonPreCleanup();
|
|
||||||
|
|
||||||
|
|
||||||
// delete the application object
|
// delete the application object
|
||||||
if ( wxTheApp )
|
if ( wxTheApp )
|
||||||
{
|
{
|
||||||
wxTheApp->CleanUp();
|
wxTheApp->CleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's important to call this after wxApp::CleanUp() as it can log some
|
||||||
|
// messages that will be flushed inside DoCommonPreCleanup().
|
||||||
|
DoCommonPreCleanup();
|
||||||
|
|
||||||
|
if ( wxTheApp )
|
||||||
|
{
|
||||||
// reset the global pointer to it to nullptr before destroying it as in
|
// reset the global pointer to it to nullptr before destroying it as in
|
||||||
// some circumstances this can result in executing the code using
|
// some circumstances this can result in executing the code using
|
||||||
// wxTheApp and using half-destroyed object is no good
|
// wxTheApp and using half-destroyed object is no good
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,9 @@ wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||||
case Dir_Cache:
|
case Dir_Cache:
|
||||||
csidl = CSIDL_LOCAL_APPDATA;
|
csidl = CSIDL_LOCAL_APPDATA;
|
||||||
break;
|
break;
|
||||||
|
case Dir_Config:
|
||||||
|
csidl = CSIDL_APPDATA;
|
||||||
|
break;
|
||||||
case Dir_Desktop:
|
case Dir_Desktop:
|
||||||
csidl = CSIDL_DESKTOPDIRECTORY;
|
csidl = CSIDL_DESKTOPDIRECTORY;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -101,12 +101,18 @@ wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang,
|
||||||
|
|
||||||
wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||||
{
|
{
|
||||||
|
wxString subdir;
|
||||||
|
|
||||||
NSSearchPathDirectory dirType;
|
NSSearchPathDirectory dirType;
|
||||||
switch (userDir)
|
switch (userDir)
|
||||||
{
|
{
|
||||||
case Dir_Cache:
|
case Dir_Cache:
|
||||||
dirType = NSCachesDirectory;
|
dirType = NSCachesDirectory;
|
||||||
break;
|
break;
|
||||||
|
case Dir_Config:
|
||||||
|
dirType = NSLibraryDirectory;
|
||||||
|
subdir = "/Preferences";
|
||||||
|
break;
|
||||||
case Dir_Desktop:
|
case Dir_Desktop:
|
||||||
dirType = NSDesktopDirectory;
|
dirType = NSDesktopDirectory;
|
||||||
break;
|
break;
|
||||||
|
|
@ -127,7 +133,7 @@ wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetFMDirectory(dirType, NSUserDomainMask);
|
return GetFMDirectory(dirType, NSUserDomainMask) + subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString
|
wxString
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,11 @@ wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||||
return cacheDir;
|
return cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxFileName dirsFile(GetXDGConfigHome(), wxS("user-dirs.dirs"));
|
const wxString configDir = GetXDGConfigHome();
|
||||||
|
if (userDir == Dir_Config)
|
||||||
|
return configDir;
|
||||||
|
|
||||||
|
const wxFileName dirsFile(configDir, wxS("user-dirs.dirs"));
|
||||||
if ( dirsFile.FileExists() )
|
if ( dirsFile.FileExists() )
|
||||||
{
|
{
|
||||||
wxString userDirId;
|
wxString userDirId;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue