Add wxStandardPaths::GetUserDir() to get Desktop, Download etc

All major supported platforms have well defined per-user directories to store
Downloads, Music, Pictures, Videos and the Desktop files. The new method
wxStandardPaths::GetUserDir() allows for a unified way to access these on MSW,
OS X and Unix (if XDG user dirs specification is implemented for the latter).

See https://github.com/wxWidgets/wxWidgets/pull/89
This commit is contained in:
Tobias Taschner
2015-09-07 22:06:48 +02:00
committed by Vadim Zeitlin
parent cfe4b4fd07
commit a0fb808087
11 changed files with 240 additions and 26 deletions

View File

@@ -50,6 +50,7 @@ Changes in behaviour which may result in build errors
All: All:
- Add UTF-8 and ZIP 64 support to wxZip{Input,Output}Stream (Tobias Taschner). - Add UTF-8 and ZIP 64 support to wxZip{Input,Output}Stream (Tobias Taschner).
- Add wxStandardPaths::GetUserDir() (Tobias Taschner).
- Allow calling wxItemContainer::Add() and similar with std::vector<> argument. - Allow calling wxItemContainer::Add() and similar with std::vector<> argument.
- Add "%z" support to printf()-like functions like wxString::Format() (RIVDSL). - Add "%z" support to printf()-like functions like wxString::Format() (RIVDSL).
- Add DOCTYPE support to wxXmlDocument (Nick Matthews). - Add DOCTYPE support to wxXmlDocument (Nick Matthews).

View File

@@ -26,7 +26,7 @@ public:
virtual wxString GetUserDataDir() const; virtual wxString GetUserDataDir() const;
virtual wxString GetUserLocalDataDir() const; virtual wxString GetUserLocalDataDir() const;
virtual wxString GetPluginsDir() const; virtual wxString GetPluginsDir() const;
virtual wxString GetDocumentsDir() const; virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
// MSW-specific methods // MSW-specific methods
@@ -72,6 +72,8 @@ protected:
// get the path corresponding to the given standard CSIDL_XXX constant // get the path corresponding to the given standard CSIDL_XXX constant
static wxString DoGetDirectory(int csidl); static wxString DoGetDirectory(int csidl);
static wxString DoGetKnownFolder(const GUID& rfid);
// return the directory of the application itself // return the directory of the application itself
wxString GetAppDir() const; wxString GetAppDir() const;

View File

@@ -52,7 +52,7 @@ public:
virtual wxString virtual wxString
GetLocalizedResourcesDir(const wxString& lang, GetLocalizedResourcesDir(const wxString& lang,
ResourceCat category = ResourceCat_None) const; ResourceCat category = ResourceCat_None) const;
virtual wxString GetDocumentsDir() const; virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
protected: protected:
// Ctor is protected, use wxStandardPaths::Get() instead of instantiating // Ctor is protected, use wxStandardPaths::Get() instead of instantiating

View File

@@ -49,6 +49,15 @@ public:
AppInfo_VendorName = 2 // the vendor name AppInfo_VendorName = 2 // the vendor name
}; };
enum Dir
{
Dir_Documents,
Dir_Desktop,
Dir_Downloads,
Dir_Music,
Dir_Pictures,
Dir_Videos
};
// return the global standard paths object // return the global standard paths object
static wxStandardPaths& Get(); static wxStandardPaths& Get();
@@ -130,7 +139,10 @@ public:
// //
// C:\Documents and Settings\username\My Documents under Windows, // C:\Documents and Settings\username\My Documents under Windows,
// $HOME under Unix and ~/Documents under Mac // $HOME under Unix and ~/Documents under Mac
virtual wxString GetDocumentsDir() const; virtual wxString GetDocumentsDir() const
{
return GetUserDir(Dir_Documents);
}
// return the directory for the documents files used by this application: // return the directory for the documents files used by this application:
// it's a subdirectory of GetDocumentsDir() constructed using the // it's a subdirectory of GetDocumentsDir() constructed using the
@@ -140,6 +152,7 @@ public:
// return the temporary directory for the current user // return the temporary directory for the current user
virtual wxString GetTempDir() const; virtual wxString GetTempDir() const;
virtual wxString GetUserDir(Dir userDir) const;
// virtual dtor for the base class // virtual dtor for the base class
virtual ~wxStandardPathsBase(); virtual ~wxStandardPathsBase();
@@ -205,7 +218,7 @@ public:
virtual wxString GetLocalDataDir() const { return m_prefix; } virtual wxString GetLocalDataDir() const { return m_prefix; }
virtual wxString GetUserDataDir() const { return m_prefix; } virtual wxString GetUserDataDir() const { return m_prefix; }
virtual wxString GetPluginsDir() const { return m_prefix; } virtual wxString GetPluginsDir() const { return m_prefix; }
virtual wxString GetDocumentsDir() const { return m_prefix; } virtual wxString GetUserDir(Dir WXUNUSED(userDir)) const { return m_prefix; }
protected: protected:
// Ctor is protected because wxStandardPaths::Get() should always be used // Ctor is protected because wxStandardPaths::Get() should always be used

View File

@@ -47,7 +47,7 @@ public:
virtual wxString GetLocalizedResourcesDir(const wxString& lang, virtual wxString GetLocalizedResourcesDir(const wxString& lang,
ResourceCat category) const wxOVERRIDE; ResourceCat category) const wxOVERRIDE;
#ifndef __VMS #ifndef __VMS
virtual wxString GetDocumentsDir() const wxOVERRIDE; virtual wxString GetUserDir(Dir userDir) const wxOVERRIDE;
#endif #endif
protected: protected:

View File

@@ -66,6 +66,64 @@ public:
ResourceCat_Messages ResourceCat_Messages
}; };
/// Possible values for userDir parameter of GetUserDir().
enum Dir
{
/**
Directory containing user documents.
Example return values:
- Unix/Mac: @c ~/Documents
- Windows: @c "C:\Users\username\Documents"
*/
Dir_Documents,
/**
Directory containing files on the users desktop.
Example return values:
- Unix/Mac: @c ~/Desktop
- Windows: @c "C:\Users\username\Desktop"
*/
Dir_Desktop,
/**
Directory for downloaded files
Example return values:
- Unix/Mac: @c ~/Downloads
- Windows: @c "C:\Users\username\Downloads" (Only available on Vista and newer)
*/
Dir_Downloads,
/**
Directory containing music files.
Example return values:
- Unix/Mac: @c ~/Music
- Windows: @c "C:\Users\username\Music"
*/
Dir_Music,
/**
Directory containing picture files.
Example return values:
- Unix/Mac: @c ~/Pictures
- Windows: @c "C:\Users\username\Pictures"
*/
Dir_Pictures,
/**
Directory containing video files.
Example return values:
- Unix: @c ~/Videos
- Windows: @c "C:\Users\username\Videos"
- Mac: @c ~/Movies
*/
Dir_Videos
};
/** /**
MSW-specific function undoing the effect of IgnoreAppSubDir() calls. MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
@@ -138,17 +196,11 @@ public:
virtual wxString GetDataDir() const; virtual wxString GetDataDir() const;
/** /**
Return the directory containing the current user's documents. Same as calling GetUserDir() with Dir_Documents parameter.
Example return values:
- Unix: @c ~ (the home directory)
- Windows: @c "C:\Users\username\Documents" or
@c "C:\Documents and Settings\username\My Documents"
- Mac: @c ~/Documents
@since 2.7.0 @since 2.7.0
@see GetAppDocumentsDir() @see GetAppDocumentsDir(), GetUserDir()
*/ */
virtual wxString GetDocumentsDir() const; virtual wxString GetDocumentsDir() const;
@@ -259,6 +311,17 @@ public:
*/ */
virtual wxString GetUserDataDir() const; virtual wxString GetUserDataDir() const;
/**
Return the path of the specified user data directory.
If the value could not be determined the users home directory is returned.
@note On Unix this supports the xdg user dirs specification.
@since 3.1.0
*/
virtual wxString GetUserDir(Dir userDir) const;
/** /**
Return the directory for user data files which shouldn't be shared with Return the directory for user data files which shouldn't be shared with
the other machines. the other machines.

View File

@@ -114,11 +114,6 @@ wxString wxStandardPathsBase::GetUserLocalDataDir() const
return GetUserDataDir(); return GetUserDataDir();
} }
wxString wxStandardPathsBase::GetDocumentsDir() const
{
return wxFileName::GetHomeDir();
}
wxString wxStandardPathsBase::GetAppDocumentsDir() const wxString wxStandardPathsBase::GetAppDocumentsDir() const
{ {
const wxString docsDir = GetDocumentsDir(); const wxString docsDir = GetDocumentsDir();
@@ -133,6 +128,11 @@ wxString wxStandardPathsBase::GetTempDir() const
return wxFileName::GetTempDir(); return wxFileName::GetTempDir();
} }
wxString wxStandardPathsBase::GetUserDir(Dir WXUNUSED(userDir)) const
{
return wxFileName::GetHomeDir();
}
/* static */ /* static */
wxString wxString
wxStandardPathsBase::AppendPathComponent(const wxString& dir, wxStandardPathsBase::AppendPathComponent(const wxString& dir,

View File

@@ -36,6 +36,7 @@
#include "wx/msw/private.h" #include "wx/msw/private.h"
#include "wx/msw/wrapshl.h" #include "wx/msw/wrapshl.h"
#include <initguid.h>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// types // types
@@ -43,6 +44,7 @@
typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR); typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR);
typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL); typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID&, DWORD, HANDLE, PWSTR *);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// constants // constants
@@ -86,6 +88,9 @@ typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
namespace namespace
{ {
DEFINE_GUID(wxFOLDERID_Downloads,
0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
struct ShellFunctions struct ShellFunctions
{ {
ShellFunctions() ShellFunctions()
@@ -97,6 +102,7 @@ struct ShellFunctions
SHGetFolderPath_t pSHGetFolderPath; SHGetFolderPath_t pSHGetFolderPath;
SHGetSpecialFolderPath_t pSHGetSpecialFolderPath; SHGetSpecialFolderPath_t pSHGetSpecialFolderPath;
SHGetKnownFolderPath_t pSHGetKnownFolderPath;
bool initialized; bool initialized;
}; };
@@ -146,6 +152,9 @@ void ResolveShellFunctions()
dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX); dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
} }
gs_shellFuncs.pSHGetKnownFolderPath = (SHGetKnownFolderPath_t)
dllShellFunctions.GetSymbol("SHGetKnownFolderPath");
// finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0), // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0),
// but we don't need to test for it -- it is available even under Win95 // but we don't need to test for it -- it is available even under Win95
@@ -242,6 +251,28 @@ wxString wxStandardPaths::DoGetDirectory(int csidl)
return dir; return dir;
} }
wxString wxStandardPaths::DoGetKnownFolder(const GUID& rfid)
{
if (!gs_shellFuncs.initialized)
ResolveShellFunctions();
wxString dir;
if ( gs_shellFuncs.pSHGetKnownFolderPath )
{
PWSTR pDir;
HRESULT hr = gs_shellFuncs.pSHGetKnownFolderPath(rfid, 0, 0, &pDir);
if ( SUCCEEDED(hr) )
{
dir = pDir;
CoTaskMemFree(pDir);
}
}
return dir;
}
wxString wxStandardPaths::GetAppDir() const wxString wxStandardPaths::GetAppDir() const
{ {
if ( m_appDir.empty() ) if ( m_appDir.empty() )
@@ -252,9 +283,38 @@ wxString wxStandardPaths::GetAppDir() const
return m_appDir; return m_appDir;
} }
wxString wxStandardPaths::GetDocumentsDir() const wxString wxStandardPaths::GetUserDir(Dir userDir) const
{ {
return DoGetDirectory(CSIDL_PERSONAL); int csidl;
switch (userDir)
{
case Dir_Desktop:
csidl = CSIDL_DESKTOPDIRECTORY;
break;
case Dir_Downloads:
{
csidl = CSIDL_PERSONAL;
// Downloads folder is only available since Vista
wxString dir = DoGetKnownFolder(wxFOLDERID_Downloads);
if ( !dir.empty() )
return dir;
break;
}
case Dir_Music:
csidl = CSIDL_MYMUSIC;
break;
case Dir_Pictures:
csidl = CSIDL_MYPICTURES;
break;
case Dir_Videos:
csidl = CSIDL_MYVIDEO;
break;
default:
csidl = CSIDL_PERSONAL;
break;
}
return DoGetDirectory(csidl);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -96,17 +96,62 @@ wxString wxStandardPathsCF::GetFromFunc(wxCFURLRef (*func)(wxCFBundleRef)) const
return ret; return ret;
} }
wxString wxStandardPathsCF::GetDocumentsDir() const wxString wxStandardPathsCF::GetUserDir(Dir userDir) const
{ {
#if defined( __WXMAC__ ) && wxOSX_USE_CARBON #if defined( __WXMAC__ ) && wxOSX_USE_CARBON
OSType folderType;
switch (userDir)
{
case Dir_Desktop:
folderType = kDesktopFolderType;
break;
case Dir_Downloads:
folderType = kDownloadsFolderType;
break;
case Dir_Music:
folderType = kMusicDocumentsFolderType;
break;
case Dir_Pictures:
folderType = kPictureDocumentsFolderType;
break;
case Dir_Videos:
folderType = kMovieDocumentsFolderType;
break;
default:
folderType = kDocumentsFolderType;
break;
}
return wxMacFindFolderNoSeparator return wxMacFindFolderNoSeparator
( (
kUserDomain, kUserDomain,
kDocumentsFolderType, folderType,
kCreateFolder kCreateFolder
); );
#else #else
return wxFileName::GetHomeDir() + wxT("/Documents"); wxString userDirName;
switch (userDir)
{
case Dir_Desktop:
userDirName = "Desktop";
break;
case Dir_Downloads:
userDirName = "Downloads";
break;
case Dir_Music:
userDirName = "Music";
break;
case Dir_Pictures:
userDirName = "Pictures";
break;
case Dir_Videos:
userDirName = "Movies";
break;
default:
userDirName = "Documents";
break;
}
return wxFileName::GetHomeDir() + "/" + userDirName;
#endif #endif
} }

View File

@@ -233,7 +233,7 @@ wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang,
return GetInstallPrefix() + wxT("/share/locale/") + lang + wxT("/LC_MESSAGES"); return GetInstallPrefix() + wxT("/share/locale/") + lang + wxT("/LC_MESSAGES");
} }
wxString wxStandardPaths::GetDocumentsDir() const wxString wxStandardPaths::GetUserDir(Dir userDir) const
{ {
{ {
wxLogNull logNull; wxLogNull logNull;
@@ -246,6 +246,29 @@ wxString wxStandardPaths::GetDocumentsDir() const
wxString dirsFile = configPath + wxT("/user-dirs.dirs"); wxString dirsFile = configPath + wxT("/user-dirs.dirs");
if (wxFileExists(dirsFile)) if (wxFileExists(dirsFile))
{ {
wxString userDirId;
switch (userDir)
{
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; wxTextFile textFile;
if (textFile.Open(dirsFile)) if (textFile.Open(dirsFile))
{ {
@@ -253,13 +276,15 @@ wxString wxStandardPaths::GetDocumentsDir() const
for (i = 0; i < textFile.GetLineCount(); i++) for (i = 0; i < textFile.GetLineCount(); i++)
{ {
wxString line(textFile[i]); wxString line(textFile[i]);
int pos = line.Find(wxT("XDG_DOCUMENTS_DIR")); int pos = line.Find(userDirId);
if (pos != wxNOT_FOUND) if (pos != wxNOT_FOUND)
{ {
wxString value = line.AfterFirst(wxT('=')); wxString value = line.AfterFirst(wxT('='));
value.Replace(wxT("$HOME"), homeDir); value.Replace(wxT("$HOME"), homeDir);
value.Trim(true); value.Trim(true);
value.Trim(false); value.Trim(false);
// Remove quotes
value.Replace("\"", "", true /* replace all */);
if (!value.IsEmpty() && wxDirExists(value)) if (!value.IsEmpty() && wxDirExists(value))
return value; return value;
else else
@@ -270,7 +295,7 @@ wxString wxStandardPaths::GetDocumentsDir() const
} }
} }
return wxStandardPathsBase::GetDocumentsDir(); return wxStandardPathsBase::GetUserDir(userDir);
} }
#endif // __VMS/!__VMS #endif // __VMS/!__VMS

View File

@@ -404,6 +404,11 @@ void InteractiveOutputTestCase::TestStandardPaths()
wxPrintf(wxT("Data dir (user):\t%s\n"), stdp.GetUserDataDir().c_str()); wxPrintf(wxT("Data dir (user):\t%s\n"), stdp.GetUserDataDir().c_str());
wxPrintf(wxT("Data dir (user local):\t%s\n"), stdp.GetUserLocalDataDir().c_str()); wxPrintf(wxT("Data dir (user local):\t%s\n"), stdp.GetUserLocalDataDir().c_str());
wxPrintf(wxT("Documents dir:\t\t%s\n"), stdp.GetDocumentsDir().c_str()); wxPrintf(wxT("Documents dir:\t\t%s\n"), stdp.GetDocumentsDir().c_str());
wxPrintf(wxT("Desktop dir:\t\t%s\n"), stdp.GetUserDir(wxStandardPaths::Dir_Desktop).c_str());
wxPrintf(wxT("Downloads dir:\t\t%s\n"), stdp.GetUserDir(wxStandardPaths::Dir_Downloads).c_str());
wxPrintf(wxT("Music dir:\t\t%s\n"), stdp.GetUserDir(wxStandardPaths::Dir_Music).c_str());
wxPrintf(wxT("Pictures dir:\t\t%s\n"), stdp.GetUserDir(wxStandardPaths::Dir_Pictures).c_str());
wxPrintf(wxT("Videos dir:\t\t%s\n"), stdp.GetUserDir(wxStandardPaths::Dir_Videos).c_str());
wxPrintf(wxT("Executable path:\t%s\n"), stdp.GetExecutablePath().c_str()); wxPrintf(wxT("Executable path:\t%s\n"), stdp.GetExecutablePath().c_str());
wxPrintf(wxT("Plugins dir:\t\t%s\n"), stdp.GetPluginsDir().c_str()); wxPrintf(wxT("Plugins dir:\t\t%s\n"), stdp.GetPluginsDir().c_str());
wxPrintf(wxT("Resources dir:\t\t%s\n"), stdp.GetResourcesDir().c_str()); wxPrintf(wxT("Resources dir:\t\t%s\n"), stdp.GetResourcesDir().c_str());