Resolve relative compiled-in data paths from the binary, not the CWD

commonElementsDir(), commonTitleBlockTemplatesDir() and languagesPath()
return the compile-time path verbatim when it is not marked
*_RELATIVE_TO_BINARY_PATH. On Windows those paths are relative
("./elements/", "./titleblocks/", "./lang/"), so they resolve against the
process working directory.

That only holds when QET is started from its own installation folder.
Opening a document from a file manager sets the working directory to the
document's folder, and the data is then looked for next to the user's
file. The shortcuts hide this by passing --common-elements-dir,
--common-tbt-dir and --lang-dir explicitly; anything that launches the
binary without them does not (see #554).

Add resolveConfiguredDataPath(): absolute paths are returned unchanged,
and a relative one is tried against the working directory first (so any
setup relying on the old behaviour keeps working), then next to the
executable, then in its parent -- the layout used by the Windows
packaging, where the binary sits in bin/ with the data beside it. This is
the same fallback the no-compile-option branch already performs for
issue #86, which was unreachable whenever the compile option is set.

The *_RELATIVE_TO_BINARY_PATH defines are left alone; they are only set
for macOS in qelectrotech.pro, and the CMake guard that would set them
tests a variable that is never defined.
This commit is contained in:
ispyisail
2026-07-26 22:41:44 +12:00
parent 69c595fdb8
commit d4ec9f9c65
+46 -3
View File
@@ -539,6 +539,48 @@ TitleBlockTemplatesCollection *QETApp::titleBlockTemplatesCollection(
return(nullptr); return(nullptr);
} }
/**
@brief resolveConfiguredDataPath
Resolve a data directory baked in at compile time.
An absolute path is returned unchanged. A relative one used to be
interpreted against the process working directory, which is only correct
when QET is started from its own installation folder: opening a document
from a file manager sets the working directory to the document's folder,
so the data was not found there. Resolve it against the executable
instead, trying the folder next to the binary and then its parent -- some
packagings put the binary in a "bin" subfolder with the data beside it
(see issue #86).
The working-directory interpretation is still attempted first, so any
setup that relied on it keeps working.
\~French Resout un dossier de donnees fixe a la compilation.
@param configured : the compile-time path
@return an existing directory if one is found, @a configured otherwise
*/
static QString resolveConfiguredDataPath(const QString &configured)
{
if (configured.isEmpty() || QDir::isAbsolutePath(configured)) {
return(configured);
}
if (QDir(configured).exists()) {
return(configured);
}
const QString bin_dir = QCoreApplication::applicationDirPath();
const QStringList candidates = {
QDir::cleanPath(bin_dir + "/" + configured) + "/",
QDir::cleanPath(bin_dir + "/../" + configured) + "/"
};
for (const QString &candidate : candidates) {
if (QDir(candidate).exists()) {
return(candidate);
}
}
return(configured);
}
/** /**
@brief QETApp::commonElementsDir @brief QETApp::commonElementsDir
@return the dir path of the common elements collection. @return the dir path of the common elements collection.
@@ -586,7 +628,8 @@ QString QETApp::commonElementsDir()
/* the compilation option represents a classic absolute /* the compilation option represents a classic absolute
* or relative path * or relative path
*/ */
m_common_element_dir = QUOTE(QET_COMMON_COLLECTION_PATH); m_common_element_dir =
resolveConfiguredDataPath(QUOTE(QET_COMMON_COLLECTION_PATH));
return m_common_element_dir; return m_common_element_dir;
#else #else
/* the compilation option represents a path /* the compilation option represents a path
@@ -754,7 +797,7 @@ QString QETApp::commonTitleBlockTemplatesDir()
#ifndef QET_COMMON_COLLECTION_PATH_RELATIVE_TO_BINARY_PATH #ifndef QET_COMMON_COLLECTION_PATH_RELATIVE_TO_BINARY_PATH
// the compile-time option represents a usual path // the compile-time option represents a usual path
// (be it absolute or relative) // (be it absolute or relative)
return(QUOTE(QET_COMMON_TBT_PATH)); return(resolveConfiguredDataPath(QUOTE(QET_COMMON_TBT_PATH)));
#else #else
/* the compile-time option represents a path relative /* the compile-time option represents a path relative
* to the directory that contains the executable binary * to the directory that contains the executable binary
@@ -1261,7 +1304,7 @@ QString QETApp::languagesPath()
* l'option de compilation represente * l'option de compilation represente
* un chemin absolu ou relatif classique * un chemin absolu ou relatif classique
*/ */
return(QUOTE(QET_LANG_PATH)); return(resolveConfiguredDataPath(QUOTE(QET_LANG_PATH)));
#else #else
/* the compilation option represents a path relative /* the compilation option represents a path relative
* to the folder containing the executable binary * to the folder containing the executable binary