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:
- 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.
- Add "%z" support to printf()-like functions like wxString::Format() (RIVDSL).
- Add DOCTYPE support to wxXmlDocument (Nick Matthews).

View File

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

View File

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

View File

@@ -49,6 +49,15 @@ public:
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
static wxStandardPaths& Get();
@@ -130,7 +139,10 @@ public:
//
// C:\Documents and Settings\username\My Documents under Windows,
// $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:
// it's a subdirectory of GetDocumentsDir() constructed using the
@@ -140,6 +152,7 @@ public:
// return the temporary directory for the current user
virtual wxString GetTempDir() const;
virtual wxString GetUserDir(Dir userDir) const;
// virtual dtor for the base class
virtual ~wxStandardPathsBase();
@@ -205,7 +218,7 @@ public:
virtual wxString GetLocalDataDir() const { return m_prefix; }
virtual wxString GetUserDataDir() 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:
// Ctor is protected because wxStandardPaths::Get() should always be used

View File

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

View File

@@ -66,6 +66,64 @@ public:
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.
@@ -138,17 +196,11 @@ public:
virtual wxString GetDataDir() const;
/**
Return the directory containing the current user's documents.
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
Same as calling GetUserDir() with Dir_Documents parameter.
@since 2.7.0
@see GetAppDocumentsDir()
@see GetAppDocumentsDir(), GetUserDir()
*/
virtual wxString GetDocumentsDir() const;
@@ -259,6 +311,17 @@ public:
*/
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
the other machines.

View File

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

View File

@@ -36,6 +36,7 @@
#include "wx/msw/private.h"
#include "wx/msw/wrapshl.h"
#include <initguid.h>
// ----------------------------------------------------------------------------
// types
@@ -43,6 +44,7 @@
typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR);
typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID&, DWORD, HANDLE, PWSTR *);
// ----------------------------------------------------------------------------
// constants
@@ -86,6 +88,9 @@ typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
namespace
{
DEFINE_GUID(wxFOLDERID_Downloads,
0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
struct ShellFunctions
{
ShellFunctions()
@@ -97,6 +102,7 @@ struct ShellFunctions
SHGetFolderPath_t pSHGetFolderPath;
SHGetSpecialFolderPath_t pSHGetSpecialFolderPath;
SHGetKnownFolderPath_t pSHGetKnownFolderPath;
bool initialized;
};
@@ -146,6 +152,9 @@ void ResolveShellFunctions()
dllShellFunctions.GetSymbol(funcname + UNICODE_SUFFIX);
}
gs_shellFuncs.pSHGetKnownFolderPath = (SHGetKnownFolderPath_t)
dllShellFunctions.GetSymbol("SHGetKnownFolderPath");
// 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
@@ -242,6 +251,28 @@ wxString wxStandardPaths::DoGetDirectory(int csidl)
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
{
if ( m_appDir.empty() )
@@ -252,9 +283,38 @@ wxString wxStandardPaths::GetAppDir() const
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;
}
wxString wxStandardPathsCF::GetDocumentsDir() const
wxString wxStandardPathsCF::GetUserDir(Dir userDir) const
{
#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
(
kUserDomain,
kDocumentsFolderType,
folderType,
kCreateFolder
);
#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
}

View File

@@ -233,7 +233,7 @@ wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang,
return GetInstallPrefix() + wxT("/share/locale/") + lang + wxT("/LC_MESSAGES");
}
wxString wxStandardPaths::GetDocumentsDir() const
wxString wxStandardPaths::GetUserDir(Dir userDir) const
{
{
wxLogNull logNull;
@@ -246,6 +246,29 @@ wxString wxStandardPaths::GetDocumentsDir() const
wxString dirsFile = configPath + wxT("/user-dirs.dirs");
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;
if (textFile.Open(dirsFile))
{
@@ -253,13 +276,15 @@ wxString wxStandardPaths::GetDocumentsDir() const
for (i = 0; i < textFile.GetLineCount(); i++)
{
wxString line(textFile[i]);
int pos = line.Find(wxT("XDG_DOCUMENTS_DIR"));
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
@@ -270,7 +295,7 @@ wxString wxStandardPaths::GetDocumentsDir() const
}
}
return wxStandardPathsBase::GetDocumentsDir();
return wxStandardPathsBase::GetUserDir(userDir);
}
#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 local):\t%s\n"), stdp.GetUserLocalDataDir().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("Plugins dir:\t\t%s\n"), stdp.GetPluginsDir().c_str());
wxPrintf(wxT("Resources dir:\t\t%s\n"), stdp.GetResourcesDir().c_str());