QCoreApplication: Add static setter for application file path.

In cases where QGuiApplication is instantiated by a library
embedded into another application via some plugin mechanism
(for example, Active X controls built using Qt), the QPA platform plugin
and other plugins cannot be found next to the application executable.
In this case, the library should set the application file path to
its deployment location such that plugin paths are set accordingly,
the directory is added to the path and qt.conf is found, should it exist.

Task-number: QTBUG-34989

Change-Id: I4a53104b5121a8d26751129912f999228be45dfd
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
This commit is contained in:
Friedemann Kleint 2013-11-22 14:31:05 +01:00 committed by The Qt Project
parent db4afbef7d
commit 75a7562491
2 changed files with 43 additions and 21 deletions

View File

@ -160,6 +160,8 @@ QString QCoreApplicationPrivate::appName() const
}
#endif
QString *QCoreApplicationPrivate::cachedApplicationFilePath = 0;
bool QCoreApplicationPrivate::checkInstance(const char *function)
{
bool b = (QCoreApplication::self != 0);
@ -425,6 +427,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate()
#ifdef Q_OS_WIN
delete [] origArgv;
#endif
QCoreApplicationPrivate::clearApplicationFilePath();
}
#ifndef QT_NO_QOBJECT
@ -1884,6 +1887,20 @@ QString QCoreApplication::translate(const char *context, const char *sourceText,
#endif //QT_NO_TRANSLATE
// Makes it possible to point QCoreApplication to a custom location to ensure
// the directory is added to the patch, and qt.conf and deployed plugins are
// found from there. This is for use cases in which QGuiApplication is
// instantiated by a library and not by an application executable, for example,
// Active X servers.
void QCoreApplicationPrivate::setApplicationFilePath(const QString &path)
{
if (QCoreApplicationPrivate::cachedApplicationFilePath)
*QCoreApplicationPrivate::cachedApplicationFilePath = path;
else
QCoreApplicationPrivate::cachedApplicationFilePath = new QString(path);
}
/*!
Returns the directory that contains the application executable.
@ -1943,24 +1960,24 @@ QString QCoreApplication::applicationFilePath()
static char *procName = d->argv[0];
if (qstrcmp(procName, d->argv[0]) != 0) {
// clear the cache if the procname changes, so we reprocess it.
d->cachedApplicationFilePath = QString();
QCoreApplicationPrivate::clearApplicationFilePath();
procName = d->argv[0];
}
if (!d->cachedApplicationFilePath.isNull())
return d->cachedApplicationFilePath;
if (QCoreApplicationPrivate::cachedApplicationFilePath)
return *QCoreApplicationPrivate::cachedApplicationFilePath;
#if defined(Q_OS_WIN)
d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath();
return d->cachedApplicationFilePath;
QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath());
return *QCoreApplicationPrivate::cachedApplicationFilePath;
#elif defined(Q_OS_BLACKBERRY)
if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day
QFileInfo fileInfo(arguments().at(0));
const bool zygotized = fileInfo.exists();
if (zygotized) {
// Handle the zygotized case:
d->cachedApplicationFilePath = QDir::cleanPath(fileInfo.absoluteFilePath());
return d->cachedApplicationFilePath;
QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(fileInfo.absoluteFilePath()));
return *QCoreApplicationPrivate::cachedApplicationFilePath;
}
}
@ -1968,7 +1985,7 @@ QString QCoreApplication::applicationFilePath()
const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX));
char buff[maximum_path+1];
if (_cmdname(buff)) {
d->cachedApplicationFilePath = QDir::cleanPath(QString::fromLocal8Bit(buff));
QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(QString::fromLocal8Bit(buff)));
} else {
qWarning("QCoreApplication::applicationFilePath: _cmdname() failed");
// _cmdname() won't fail, but just in case, fallback to the old method
@ -1976,18 +1993,19 @@ QString QCoreApplication::applicationFilePath()
QStringList executables = dir.entryList(QDir::Executable | QDir::Files);
if (!executables.empty()) {
//We assume that there is only one executable in the folder
d->cachedApplicationFilePath = dir.absoluteFilePath(executables.first());
} else {
d->cachedApplicationFilePath = QString();
QCoreApplicationPrivate::setApplicationFilePath(dir.absoluteFilePath(executables.first()));
}
}
return d->cachedApplicationFilePath;
return *QCoreApplicationPrivate::cachedApplicationFilePath;
#elif defined(Q_OS_MAC)
QString qAppFileName_str = qAppFileName();
if(!qAppFileName_str.isEmpty()) {
QFileInfo fi(qAppFileName_str);
d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
return d->cachedApplicationFilePath;
if (fi.exists()) {
QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath());
return *QCoreApplicationPrivate::cachedApplicationFilePath;
}
return QString();
}
#endif
#if defined( Q_OS_UNIX )
@ -1996,8 +2014,8 @@ QString QCoreApplication::applicationFilePath()
// the absolute path of the executable
QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
if (pfi.exists() && pfi.isSymLink()) {
d->cachedApplicationFilePath = pfi.canonicalFilePath();
return d->cachedApplicationFilePath;
QCoreApplicationPrivate::setApplicationFilePath(pfi.canonicalFilePath());
return *QCoreApplicationPrivate::cachedApplicationFilePath;
}
# endif
if (!arguments().isEmpty()) {
@ -2027,13 +2045,15 @@ QString QCoreApplication::applicationFilePath()
absPath = QDir::cleanPath(absPath);
QFileInfo fi(absPath);
d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
} else {
d->cachedApplicationFilePath = QString();
if (fi.exists()) {
QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath());
return *QCoreApplicationPrivate::cachedApplicationFilePath;
}
}
return d->cachedApplicationFilePath;
return QString();
#endif
Q_UNREACHABLE();
}
/*!

View File

@ -139,7 +139,9 @@ public:
QCoreApplicationPrivate::Type application_type;
QString cachedApplicationDirPath;
QString cachedApplicationFilePath;
static QString *cachedApplicationFilePath;
static void setApplicationFilePath(const QString &path);
static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; }
#ifndef QT_NO_QOBJECT
bool in_exec;