Add QStandardPaths::findExecutable.

Change-Id: If30a83622e2ac5af48e47a38b8f70fce73044d74
Reviewed-by: Thiago Macieira (Intel) <thiago.macieira@intel.com>
This commit is contained in:
David Faure 2011-10-21 20:57:31 +02:00 committed by Qt by Nokia
parent fa0ad643a6
commit 4b72c3f434
3 changed files with 92 additions and 14 deletions

View File

@ -176,6 +176,93 @@ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &file
return result;
}
#ifdef Q_OS_WIN
static QStringList executableExtensions()
{
QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
// If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
ret.clear();
ret << QLatin1String(".exe")
<< QLatin1String(".com")
<< QLatin1String(".bat")
<< QLatin1String(".cmd");
}
return ret;
}
#endif
static QString checkExecutable(const QString &path)
{
const QFileInfo info(path);
if (info.isBundle())
return info.bundleName();
if (info.isFile() && info.isExecutable())
return QDir::cleanPath(path);
return QString();
}
/*!
Finds the executable named \a executableName in the paths specified by \a paths,
or the system paths if \a paths is empty.
On most operating systems the system path is determined by the PATH environment variable.
The directories where to search for the executable can be set in the \a paths argument.
To search in both your own paths and the system paths, call findExecutable twice, once with
\a paths set and once with \a paths empty.
Symlinks are not resolved, in order to preserve behavior for the case of executables
whose behavior depends on the name they are invoked with.
\note On Windows, the usual executable extensions (from the PATHEXT environment variable)
are automatically appended, so that for instance findExecutable("foo") will find foo.exe
or foo.bat if present.
Returns the absolute file path to the executable, or an empty string if not found.
*/
QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths)
{
if (QFileInfo(executableName).isAbsolute())
return checkExecutable(executableName);
QStringList searchPaths = paths;
if (paths.isEmpty()) {
QByteArray pEnv = qgetenv("PATH");
#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
const QLatin1Char pathSep(';');
#else
const QLatin1Char pathSep(':');
#endif
searchPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
}
QDir currentDir = QDir::current();
QString absPath;
#ifdef Q_OS_WIN
static QStringList executable_extensions = executableExtensions();
#endif
for (QStringList::const_iterator p = searchPaths.constBegin(); p != searchPaths.constEnd(); ++p) {
const QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + executableName);
#ifdef Q_OS_WIN
const QString extension = QLatin1Char('.') + QFileInfo(executableName).suffix();
if (!executable_extensions.contains(extension, Qt::CaseInsensitive)) {
foreach (const QString &extension, executable_extensions) {
absPath = checkExecutable(candidate + extension.toLower());
if (!absPath.isEmpty())
break;
}
}
#endif
absPath = checkExecutable(candidate);
if (!absPath.isEmpty()) {
break;
}
}
return absPath;
}
/*!
\fn QString QStandardPaths::displayName(StandardLocation type)

View File

@ -42,7 +42,7 @@
#ifndef QSTANDARDPATHS_H
#define QSTANDARDPATHS_H
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_HEADER
@ -87,6 +87,8 @@ public:
static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
static QString displayName(StandardLocation type);
static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
private:
// prevent construction
QStandardPaths();

View File

@ -53,6 +53,7 @@
#include <qfileinfo.h>
#include <qhash.h>
#include <private/qprocess_p.h>
#include <qstandardpaths.h>
#include <qtextcodec.h>
#include <qthread.h>
#include <qthreadpool.h>
@ -2019,19 +2020,7 @@ QString QCoreApplication::applicationFilePath()
Otherwise, the file path has to be determined using the
PATH environment variable.
*/
QByteArray pEnv = qgetenv("PATH");
QDir currentDir = QDir::current();
QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
if ((*p).isEmpty())
continue;
QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
QFileInfo candidate_fi(candidate);
if (candidate_fi.exists() && !candidate_fi.isDir()) {
absPath = candidate;
break;
}
}
absPath = QStandardPaths::findExecutable(argv0);
}
absPath = QDir::cleanPath(absPath);