allow customizing wxStandardPaths logic for the program directory determination

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61003 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2009-06-11 16:46:19 +00:00
parent 89391a4ea1
commit 4cd15b49b4
4 changed files with 173 additions and 23 deletions

View File

@ -356,6 +356,7 @@ MSW:
- Update CRT environment block in wxSetEnv() too.
- Fix wxMDIChildFrame::SetSize() (Lars Rosenboom).
- Fix wxTreeCtrl::UnselectItem() in single selection controls.
- Allow customizing wxStandardPaths logic for program directory determination.
i18n:

View File

@ -19,12 +19,9 @@
class WXDLLIMPEXP_BASE wxStandardPaths : public wxStandardPathsBase
{
public:
wxStandardPaths()
{
UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
}
~wxStandardPaths() { }
// ctor calls IgnoreAppBuildSubDirs() and also sets up the object to use
// both vendor and application name by default
wxStandardPaths();
// implement base class pure virtuals
virtual wxString GetExecutablePath() const;
@ -36,12 +33,44 @@ public:
virtual wxString GetPluginsDir() const;
virtual wxString GetDocumentsDir() const;
// MSW-specific methods
// This class supposes that data, plugins &c files are located under the
// program directory which is the directory containing the application
// binary itself. But sometimes this binary may be in a subdirectory of the
// main program directory, e.g. this happens in at least the following
// common cases:
// 1. The program is in "bin" subdirectory of the installation directory.
// 2. The program is in "debug" subdirectory of the directory containing
// sources and data files during development
//
// By calling this function you instruct the class to remove the last
// component of the path if it matches its argument. Notice that it may be
// called more than once, e.g. you can call both IgnoreAppSubDir("bin") and
// IgnoreAppSubDir("debug") to take care of both production and development
// cases above but that each call will only remove the last path component.
// Finally note that the argument can contain wild cards so you can also
// call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once
// when using wxWidgets-inspired output directories names.
void IgnoreAppSubDir(const wxString& subdirPattern);
// This function is used to ignore all common build directories and is
// called from the ctor -- use DontIgnoreAppSubDir() to undo this.
void IgnoreAppBuildSubDirs();
// Undo the effects of all preceding IgnoreAppSubDir() calls.
void DontIgnoreAppSubDir();
protected:
// get the path corresponding to the given standard CSIDL_XXX constant
static wxString DoGetDirectory(int csidl);
// return the directory of the application itself
static wxString GetAppDir();
wxString GetAppDir() const;
// directory returned by GetAppDir()
mutable wxString m_appDir;
};
// ----------------------------------------------------------------------------

View File

@ -48,6 +48,19 @@
class wxStandardPaths
{
public:
/**
MSW-specific function undoing the effect of IgnoreAppSubDir() calls.
After a call to this function the program directory will be exactly the
directory containing the main application binary, i.e. it undoes the
effect of any previous IgnoreAppSubDir() calls including the ones done
indirectly by IgnoreAppBuildSubDirs() called from the class
constructor.
@since 2.9.1
*/
void DontIgnoreAppSubDir();
/**
Returns reference to the unique global standard paths object.
*/
@ -215,6 +228,53 @@ public:
*/
virtual wxString GetUserLocalDataDir() const;
/**
MSW-specific function to customize application directory detection.
This class supposes that data, plugins &c files are located under the
program directory which is the directory containing the application
binary itself. But sometimes this binary may be in a subdirectory of
the main program directory, e.g. this happens in at least the following
common cases:
- The program is in "bin" subdirectory of the installation directory.
- The program is in "debug" subdirectory of the directory containing
sources and data files during development
By calling this function you instruct the class to remove the last
component of the path if it matches its argument. Notice that it may be
called more than once, e.g. you can call both IgnoreAppSubDir("bin") and
IgnoreAppSubDir("debug") to take care of both production and development
cases above but that each call will only remove the last path component.
Finally note that the argument can contain wild cards so you can also
call IgnoreAppSubDir("vc*msw*") to ignore all build directories at once
when using wxWidgets-inspired output directories names.
@since 2.9.1
@see IgnoreAppBuildSubDirs()
@param subdirPattern
The subdirectory containing the application binary which should be
ignored when determining the top application directory. The pattern
is case-insensitive and may contain wild card characters @c '?' and
@c '*'.
*/
void IgnoreAppSubDir(const wxString& subdirPattern);
/**
MSW-specific function to ignore all common build directories.
This function calls IgnoreAppSubDir() with all common values for build
directory, e.g. @c "debug" and @c "release".
It is called by the class constructor and so the build directories are
always ignored by default. You may use DontIgnoreAppSubDir() to avoid
ignoring them if this is inappropriate for your application.
@since 2.9.1
*/
void IgnoreAppBuildSubDirs();
/**
Lets wxStandardPaths know about the real program installation prefix on a Unix
system. By default, the value returned by GetInstallPrefix() is used.

View File

@ -79,10 +79,14 @@ typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL);
#ifndef SHGFP_TYPE_DEFAULT
#define SHGFP_TYPE_DEFAULT 1
#endif
// ----------------------------------------------------------------------------
// module globals
// ----------------------------------------------------------------------------
namespace
{
struct ShellFunctions
{
ShellFunctions()
@ -101,13 +105,13 @@ struct ShellFunctions
// in spite of using a static variable, this is MT-safe as in the worst case it
// results in initializing the function pointer several times -- but this is
// harmless
static ShellFunctions gs_shellFuncs;
ShellFunctions gs_shellFuncs;
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
static void ResolveShellFunctions()
void ResolveShellFunctions()
{
#if wxUSE_DYNLIB_CLASS
@ -161,6 +165,8 @@ static void ResolveShellFunctions()
#endif
}
} // anonymous namespace
// ============================================================================
// wxStandardPaths implementation
// ============================================================================
@ -245,24 +251,14 @@ wxString wxStandardPaths::DoGetDirectory(int csidl)
return dir;
}
/* static */
wxString wxStandardPaths::GetAppDir()
wxString wxStandardPaths::GetAppDir() const
{
wxFileName fn(wxGetFullModuleName());
// allow running the apps directly from build directory in MSVC debug builds
#ifdef _DEBUG
wxString lastdir;
if ( fn.GetDirCount() )
if ( m_appDir.empty() )
{
lastdir = fn.GetDirs().Last();
lastdir.MakeLower();
if ( lastdir.Matches(_T("debug*")) || lastdir.Matches(_T("vc*msw*")) )
fn.RemoveLastDir();
m_appDir = wxFileName(wxGetFullModuleName()).GetPath();
}
#endif // _DEBUG
return fn.GetPath();
return m_appDir;
}
wxString wxStandardPaths::GetDocumentsDir() const
@ -270,10 +266,74 @@ wxString wxStandardPaths::GetDocumentsDir() const
return DoGetDirectory(CSIDL_PERSONAL);
}
// ----------------------------------------------------------------------------
// MSW-specific functions
// ----------------------------------------------------------------------------
void wxStandardPaths::IgnoreAppSubDir(const wxString& subdirPattern)
{
wxFileName fn = wxFileName::DirName(GetAppDir());
if ( !fn.GetDirCount() )
{
// no last directory to ignore anyhow
return;
}
const wxString lastdir = fn.GetDirs().Last().Lower();
if ( lastdir.Matches(subdirPattern.Lower()) )
{
fn.RemoveLastDir();
// store the cached value so that subsequent calls to GetAppDir() will
// reuse it instead of using just the program binary directory
m_appDir = fn.GetPath();
}
}
void wxStandardPaths::IgnoreAppBuildSubDirs()
{
IgnoreAppSubDir("debug");
IgnoreAppSubDir("release");
wxString compilerPrefix;
#ifdef __VISUALC__
compilerPrefix = "vc";
#elif defined(__GNUG__)
compilerPrefix = "gcc";
#elif defined(__BORLANDC__)
compilerPrefix = "bcc";
#elif defined(__DIGITALMARS__)
compilerPrefix = "dmc";
#elif defined(__WATCOMC__)
compilerPrefix = "wat";
#else
return;
#endif
IgnoreAppSubDir(compilerPrefix + "_msw*");
}
void wxStandardPaths::DontIgnoreAppSubDir()
{
// this will force the next call to GetAppDir() to use the program binary
// path as the application directory
m_appDir.clear();
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
wxStandardPaths::wxStandardPaths()
{
// under MSW it's common to use both the applicatio nand vendor
UseAppInfo(AppInfo_AppName | AppInfo_VendorName);
// make it possible to run uninstalled application from the build directory
IgnoreAppBuildSubDirs();
}
wxString wxStandardPaths::GetExecutablePath() const
{
return wxGetFullModuleName();