Merge branch 'more-xdg-dirs'
Add possibility to use wxStandardPaths and, hence, wxFileConfig, in XDG-compliant (but backwards-incompatible) mode. Closes #17727.
This commit is contained in:
commit
3eda902331
@ -195,6 +195,7 @@ wxOSX:
|
||||
Unix:
|
||||
|
||||
- Support new gstreamer API in 1.7.2+ in wxMediaCtrl (Sebastian Dröge).
|
||||
- Add wxStandardPaths::SetFileLayout(FileLayout_XDG) (Martin Koegler).
|
||||
|
||||
|
||||
3.1.0: (released 2016-02-29)
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
virtual wxString GetUserLocalDataDir() const wxOVERRIDE;
|
||||
virtual wxString GetPluginsDir() const wxOVERRIDE;
|
||||
virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
|
||||
virtual wxString MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv) const wxOVERRIDE;
|
||||
|
||||
|
||||
// MSW-specific methods
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
GetLocalizedResourcesDir(const wxString& lang,
|
||||
ResourceCat category = ResourceCat_None) const wxOVERRIDE;
|
||||
virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
|
||||
virtual wxString MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv) const wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
// Ctor is protected, use wxStandardPaths::Get() instead of instantiating
|
||||
|
@ -60,6 +60,21 @@ public:
|
||||
Dir_Videos
|
||||
};
|
||||
|
||||
// Layout to use for user config/data files under Unix.
|
||||
enum FileLayout
|
||||
{
|
||||
FileLayout_Classic, // Default: use home directory.
|
||||
FileLayout_XDG // Recommended: use XDG specification.
|
||||
};
|
||||
|
||||
// Naming convention for the config files under Unix.
|
||||
enum ConfigFileConv
|
||||
{
|
||||
ConfigFileConv_Dot, // Classic Unix dot-file convention.
|
||||
ConfigFileConv_Ext // Use .conf extension.
|
||||
};
|
||||
|
||||
|
||||
// return the global standard paths object
|
||||
static wxStandardPaths& Get();
|
||||
|
||||
@ -155,6 +170,10 @@ public:
|
||||
|
||||
virtual wxString GetUserDir(Dir userDir) const;
|
||||
|
||||
virtual wxString
|
||||
MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv = ConfigFileConv_Ext) const = 0;
|
||||
|
||||
// virtual dtor for the base class
|
||||
virtual ~wxStandardPathsBase();
|
||||
|
||||
@ -166,6 +185,15 @@ public:
|
||||
|
||||
bool UsesAppInfo(int info) const { return (m_usedAppInfo & info) != 0; }
|
||||
|
||||
void SetFileLayout(FileLayout layout)
|
||||
{
|
||||
m_fileLayout = layout;
|
||||
}
|
||||
|
||||
FileLayout GetFileLayout() const
|
||||
{
|
||||
return m_fileLayout;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Ctor is protected as this is a base class which should never be created
|
||||
@ -182,6 +210,9 @@ protected:
|
||||
|
||||
// combination of AppInfo_XXX flags used by AppendAppInfo()
|
||||
int m_usedAppInfo;
|
||||
|
||||
// The file layout to use, currently only used under Unix.
|
||||
FileLayout m_fileLayout;
|
||||
};
|
||||
|
||||
#if wxUSE_STDPATHS
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
#ifndef __VMS
|
||||
virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
|
||||
#endif
|
||||
virtual wxString MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv) const wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
// Ctor is protected, use wxStandardPaths::Get() instead of instantiating
|
||||
|
@ -135,6 +135,66 @@ public:
|
||||
Dir_Videos
|
||||
};
|
||||
|
||||
/**
|
||||
Possible values for SetFileLayout() argument.
|
||||
|
||||
The elements of this enum correspond to the different file layout
|
||||
standards under Unix systems.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
enum FileLayout
|
||||
{
|
||||
/**
|
||||
Use the classic file layout.
|
||||
|
||||
User configuration and data files are located directly in the home
|
||||
directory.
|
||||
|
||||
This is the default behaviour for compatibility reasons.
|
||||
*/
|
||||
FileLayout_Classic,
|
||||
|
||||
/**
|
||||
Use a XDG styled file layout.
|
||||
|
||||
File layout follows the XDG Base Directory Specification (see
|
||||
https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html).
|
||||
|
||||
This is the recommended layout for new applications.
|
||||
*/
|
||||
FileLayout_XDG
|
||||
};
|
||||
|
||||
/**
|
||||
Possible values for MakeConfigFileName() naming convention argument.
|
||||
|
||||
The values in this enum are only used under Unix and only when using
|
||||
the classic Unix convention for file layout, in XDG mode, XDG naming
|
||||
convention is used unconditionally.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
enum ConfigFileConv
|
||||
{
|
||||
/**
|
||||
Use the class Unix dot-file convention.
|
||||
|
||||
Prepend the dot to the file base name.
|
||||
|
||||
This value is ignored when in XDG mode, where MakeConfigFileName()
|
||||
always behaves as if ConfigFileConv_Ext was specified.
|
||||
*/
|
||||
ConfigFileConv_Dot,
|
||||
|
||||
/**
|
||||
Use @c .conf extension for the file names.
|
||||
|
||||
This convention is always used in XDG mode.
|
||||
*/
|
||||
ConfigFileConv_Ext
|
||||
};
|
||||
|
||||
/**
|
||||
MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
|
||||
|
||||
@ -300,8 +360,11 @@ public:
|
||||
virtual wxString GetTempDir() const;
|
||||
|
||||
/**
|
||||
Return the directory for the user config files:
|
||||
- Unix: @c ~ (the home directory)
|
||||
Return the directory for the user config files.
|
||||
|
||||
This directory is:
|
||||
- Unix: @c ~ (the home directory) or @c XDG_CONFIG_HOME depending on
|
||||
GetFileLayout() return value
|
||||
- Windows: @c "C:\Users\username\AppData\Roaming" or
|
||||
@c "C:\Documents and Settings\username\Application Data"
|
||||
- Mac: @c ~/Library/Preferences
|
||||
@ -326,7 +389,8 @@ public:
|
||||
|
||||
If the value could not be determined the users home directory is returned.
|
||||
|
||||
@note On Unix this supports the xdg user dirs specification.
|
||||
@note On Unix this method respects the XDG base directory specification
|
||||
only if SetFileLayout() with @c FileLayout_XDG had been called.
|
||||
|
||||
@since 3.1.0
|
||||
*/
|
||||
@ -444,6 +508,44 @@ public:
|
||||
*/
|
||||
void UseAppInfo(int info);
|
||||
|
||||
/**
|
||||
Returns the current file layout.
|
||||
|
||||
The default layout is @c FileLayout_Classic for compatibility, however
|
||||
newer applications are encouraged to set it to @c FileLayout_XDG on
|
||||
program startup.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
void SetFileLayout(FileLayout layout);
|
||||
|
||||
/**
|
||||
Returns the current file layout.
|
||||
|
||||
@see SetFileLayout()
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
FileLayout GetFileLayout() const;
|
||||
|
||||
/**
|
||||
Return the file name which would be used by wxFileConfig if it were
|
||||
constructed with @a basename.
|
||||
|
||||
@a conv is used to construct the name of the file under Unix and only
|
||||
matters when using the class file layout, i.e. if SetFileLayout() had
|
||||
@e not been called with @c FileLayout_XDG argument. In this case, this
|
||||
argument is used to determine whether to use an extension or a leading
|
||||
dot. When following XDG specification, the function always appends the
|
||||
extension, regardless of @a conv value. Finally, this argument is not
|
||||
used at all under non-Unix platforms.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
virtual wxString
|
||||
MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv = ConfigFileConv_Ext) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
Protected default constructor.
|
||||
|
@ -247,26 +247,6 @@ public:
|
||||
// static functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// this function modifies in place the given wxFileName object if it doesn't
|
||||
// already have an extension
|
||||
//
|
||||
// note that it's slightly misnamed under Mac as there it doesn't add an
|
||||
// extension but modifies the file name instead, so you shouldn't suppose that
|
||||
// fn.HasExt() is true after it returns
|
||||
static void AddConfFileExtIfNeeded(wxFileName& fn)
|
||||
{
|
||||
if ( !fn.HasExt() )
|
||||
{
|
||||
#if defined( __WXMAC__ )
|
||||
fn.SetName(fn.GetName() + wxT(" Preferences"));
|
||||
#elif defined( __UNIX__ )
|
||||
fn.SetExt(wxT("conf"));
|
||||
#else // Windows
|
||||
fn.SetExt(wxT("ini"));
|
||||
#endif // UNIX/Win
|
||||
}
|
||||
}
|
||||
|
||||
wxString wxFileConfig::GetGlobalDir()
|
||||
{
|
||||
return wxStandardPaths::Get().GetConfigDir();
|
||||
@ -286,31 +266,28 @@ wxString wxFileConfig::GetLocalDir(int style)
|
||||
|
||||
wxFileName wxFileConfig::GetGlobalFile(const wxString& szFile)
|
||||
{
|
||||
wxFileName fn(GetGlobalDir(), szFile);
|
||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||
|
||||
AddConfFileExtIfNeeded(fn);
|
||||
|
||||
return fn;
|
||||
return wxFileName(GetGlobalDir(), stdp.MakeConfigFileName(szFile));
|
||||
}
|
||||
|
||||
wxFileName wxFileConfig::GetLocalFile(const wxString& szFile, int style)
|
||||
{
|
||||
wxFileName fn(GetLocalDir(style), szFile);
|
||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||
|
||||
#if defined( __UNIX__ ) && !defined( __WXMAC__ )
|
||||
if ( !(style & wxCONFIG_USE_SUBDIR) )
|
||||
{
|
||||
// dot-files under Unix start with, well, a dot (but OTOH they usually
|
||||
// don't have any specific extension)
|
||||
fn.SetName(wxT('.') + fn.GetName());
|
||||
}
|
||||
else // we do append ".conf" extension to config files in subdirectories
|
||||
#endif // defined( __UNIX__ ) && !defined( __WXMAC__ )
|
||||
{
|
||||
AddConfFileExtIfNeeded(fn);
|
||||
}
|
||||
// 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
|
||||
// directly in the home directory. Note that if wxStandardPaths is
|
||||
// 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
|
||||
// up using the extension even if wxCONFIG_USE_SUBDIR is not set, but this
|
||||
// is the correct and expected (if a little confusing) behaviour.
|
||||
const wxStandardPaths::ConfigFileConv
|
||||
conv = style & wxCONFIG_USE_SUBDIR
|
||||
? wxStandardPaths::ConfigFileConv_Ext
|
||||
: wxStandardPaths::ConfigFileConv_Dot;
|
||||
|
||||
return fn;
|
||||
return wxFileName(GetLocalDir(style), stdp.MakeConfigFileName(szFile, conv));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -97,6 +97,9 @@ wxStandardPathsBase::wxStandardPathsBase()
|
||||
// Derived classes can call this in their constructors
|
||||
// to set the platform-specific settings
|
||||
UseAppInfo(AppInfo_AppName);
|
||||
|
||||
// Default for compatibility with the existing config files.
|
||||
SetFileLayout(FileLayout_Classic);
|
||||
}
|
||||
|
||||
wxStandardPathsBase::~wxStandardPathsBase()
|
||||
|
@ -345,6 +345,16 @@ wxString wxStandardPaths::GetPluginsDir() const
|
||||
return GetAppDir();
|
||||
}
|
||||
|
||||
|
||||
wxString
|
||||
wxStandardPaths::MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv WXUNUSED(conv)) const
|
||||
{
|
||||
wxFileName fn(wxEmptyString, basename);
|
||||
fn.SetExt(wxT("ini"));
|
||||
return fn.GetFullName();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxStandardPathsWin16 implementation
|
||||
// ============================================================================
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#if wxUSE_STDPATHS
|
||||
|
||||
#include "wx/filename.h"
|
||||
#include "wx/stdpaths.h"
|
||||
#include "wx/osx/private.h"
|
||||
#include "wx/osx/core/cfstring.h"
|
||||
@ -129,4 +130,13 @@ wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||
return GetFMDirectory(dirType, NSUserDomainMask);
|
||||
}
|
||||
|
||||
wxString
|
||||
wxStandardPaths::MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv WXUNUSED(conv)) const
|
||||
{
|
||||
wxFileName fn(wxEmptyString, basename);
|
||||
fn.SetName(fn.GetName() + wxT(" Preferences"));
|
||||
return fn.GetFullName();
|
||||
}
|
||||
|
||||
#endif // wxUSE_STDPATHS
|
||||
|
@ -50,9 +50,34 @@ void wxStandardPaths::SetInstallPrefix(const wxString& prefix)
|
||||
m_prefix = prefix;
|
||||
}
|
||||
|
||||
// Helper function returning the value of XDG_CONFIG_HOME environment variable
|
||||
// or its default value if it is not defined.
|
||||
static wxString GetXDGConfigHome()
|
||||
{
|
||||
wxString dir;
|
||||
if ( !wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() )
|
||||
dir = wxFileName::GetHomeDir() + wxS("/.config");
|
||||
return dir;
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetUserConfigDir() const
|
||||
{
|
||||
return wxFileName::GetHomeDir();
|
||||
wxString dir;
|
||||
|
||||
switch ( GetFileLayout() )
|
||||
{
|
||||
case FileLayout_Classic:
|
||||
dir = wxFileName::GetHomeDir();
|
||||
break;
|
||||
|
||||
case FileLayout_XDG:
|
||||
dir = GetXDGConfigHome();
|
||||
break;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( !dir.empty(), wxS("unsupported file layout") );
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
@ -235,69 +260,70 @@ wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang,
|
||||
|
||||
wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||
{
|
||||
// Note that we do not use the file layout here because there is no reason
|
||||
// not to respect the XDG convention even if SetFileLayout(FileLayout_XDG)
|
||||
// hadn't been called: we're not bound by any backwards compatibility
|
||||
// considerations as there can't be any pre-existing config or data files
|
||||
// in the home directory that wouldn't be found any longer after updating
|
||||
// the version of wxWidgets used by the application.
|
||||
|
||||
wxLogNull logNull;
|
||||
const wxString homeDir = wxFileName::GetHomeDir();
|
||||
if (userDir == Dir_Cache)
|
||||
{
|
||||
wxLogNull logNull;
|
||||
wxString homeDir = wxFileName::GetHomeDir();
|
||||
if (userDir == Dir_Cache)
|
||||
wxString cacheDir;
|
||||
if ( !wxGetEnv(wxS("XDG_CACHE_HOME"), &cacheDir) )
|
||||
cacheDir = homeDir + wxS("/.cache");
|
||||
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
const wxFileName dirsFile(GetXDGConfigHome(), wxS("user-dirs.dirs"));
|
||||
if ( dirsFile.FileExists() )
|
||||
{
|
||||
wxString userDirId;
|
||||
switch (userDir)
|
||||
{
|
||||
if (wxGetenv(wxT("XDG_CACHE_HOME")))
|
||||
return wxGetenv(wxT("XDG_CACHE_HOME"));
|
||||
else
|
||||
return homeDir + wxT("/.cache");
|
||||
case Dir_Desktop:
|
||||
userDirId = "XDG_DESKTOP_DIR";
|
||||
break;
|
||||
case Dir_Downloads:
|
||||
userDirId = "XDG_DOWNLOAD_DIR";
|
||||
break;
|
||||
case Dir_Music:
|
||||
userDirId = "XDG_MUSIC_DIR";
|
||||
break;
|
||||
case Dir_Pictures:
|
||||
userDirId = "XDG_PICTURES_DIR";
|
||||
break;
|
||||
case Dir_Videos:
|
||||
userDirId = "XDG_VIDEOS_DIR";
|
||||
break;
|
||||
default:
|
||||
userDirId = "XDG_DOCUMENTS_DIR";
|
||||
break;
|
||||
}
|
||||
|
||||
wxString configPath;
|
||||
if (wxGetenv(wxT("XDG_CONFIG_HOME")))
|
||||
configPath = wxGetenv(wxT("XDG_CONFIG_HOME"));
|
||||
else
|
||||
configPath = homeDir + wxT("/.config");
|
||||
wxString dirsFile = configPath + wxT("/user-dirs.dirs");
|
||||
if (wxFileExists(dirsFile))
|
||||
wxTextFile textFile;
|
||||
if ( textFile.Open(dirsFile.GetFullPath()) )
|
||||
{
|
||||
wxString userDirId;
|
||||
switch (userDir)
|
||||
for ( wxString line = textFile.GetFirstLine();
|
||||
!textFile.Eof();
|
||||
line = textFile.GetNextLine() )
|
||||
{
|
||||
case Dir_Desktop:
|
||||
userDirId = "XDG_DESKTOP_DIR";
|
||||
break;
|
||||
case Dir_Downloads:
|
||||
userDirId = "XDG_DOWNLOAD_DIR";
|
||||
break;
|
||||
case Dir_Music:
|
||||
userDirId = "XDG_MUSIC_DIR";
|
||||
break;
|
||||
case Dir_Pictures:
|
||||
userDirId = "XDG_PICTURES_DIR";
|
||||
break;
|
||||
case Dir_Videos:
|
||||
userDirId = "XDG_VIDEOS_DIR";
|
||||
break;
|
||||
default:
|
||||
userDirId = "XDG_DOCUMENTS_DIR";
|
||||
break;
|
||||
}
|
||||
|
||||
wxTextFile textFile;
|
||||
if (textFile.Open(dirsFile))
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < textFile.GetLineCount(); i++)
|
||||
int pos = line.Find(userDirId);
|
||||
if (pos != wxNOT_FOUND)
|
||||
{
|
||||
wxString line(textFile[i]);
|
||||
int pos = line.Find(userDirId);
|
||||
if (pos != wxNOT_FOUND)
|
||||
{
|
||||
wxString value = line.AfterFirst(wxT('='));
|
||||
value.Replace(wxT("$HOME"), homeDir);
|
||||
value.Trim(true);
|
||||
value.Trim(false);
|
||||
// Remove quotes
|
||||
value.Replace("\"", "", true /* replace all */);
|
||||
if (!value.IsEmpty() && wxDirExists(value))
|
||||
return value;
|
||||
else
|
||||
break;
|
||||
}
|
||||
wxString value = line.AfterFirst(wxT('='));
|
||||
value.Replace(wxT("$HOME"), homeDir);
|
||||
value.Trim(true);
|
||||
value.Trim(false);
|
||||
// Remove quotes
|
||||
value.Replace("\"", "", true /* replace all */);
|
||||
if (!value.IsEmpty() && wxDirExists(value))
|
||||
return value;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -308,4 +334,39 @@ wxString wxStandardPaths::GetUserDir(Dir userDir) const
|
||||
|
||||
#endif // __VMS/!__VMS
|
||||
|
||||
wxString
|
||||
wxStandardPaths::MakeConfigFileName(const wxString& basename,
|
||||
ConfigFileConv conv) const
|
||||
{
|
||||
wxFileName fn(wxEmptyString, basename);
|
||||
|
||||
bool addExt = false;
|
||||
|
||||
switch ( GetFileLayout() )
|
||||
{
|
||||
case FileLayout_Classic:
|
||||
switch ( conv )
|
||||
{
|
||||
case ConfigFileConv_Dot:
|
||||
fn.SetName(wxT('.') + fn.GetName());
|
||||
break;
|
||||
|
||||
case ConfigFileConv_Ext:
|
||||
addExt = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FileLayout_XDG:
|
||||
// Dot files are never used in XDG mode.
|
||||
addExt = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( addExt )
|
||||
fn.SetExt(wxS("conf"));
|
||||
|
||||
return fn.GetFullName();
|
||||
}
|
||||
|
||||
#endif // wxUSE_STDPATHS
|
||||
|
Loading…
Reference in New Issue
Block a user