From d4ec9f9c653839cb1937939d07e8a5cbf57b4326 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 26 Jul 2026 22:41:44 +1200 Subject: [PATCH] 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. --- sources/qetapp.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index adac51c54..191e820fa 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -539,6 +539,48 @@ TitleBlockTemplatesCollection *QETApp::titleBlockTemplatesCollection( 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 @return the dir path of the common elements collection. @@ -586,7 +628,8 @@ QString QETApp::commonElementsDir() /* the compilation option represents a classic absolute * 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; #else /* the compilation option represents a path @@ -754,7 +797,7 @@ QString QETApp::commonTitleBlockTemplatesDir() #ifndef QET_COMMON_COLLECTION_PATH_RELATIVE_TO_BINARY_PATH // the compile-time option represents a usual path // (be it absolute or relative) - return(QUOTE(QET_COMMON_TBT_PATH)); + return(resolveConfiguredDataPath(QUOTE(QET_COMMON_TBT_PATH))); #else /* the compile-time option represents a path relative * to the directory that contains the executable binary @@ -1261,7 +1304,7 @@ QString QETApp::languagesPath() * l'option de compilation represente * un chemin absolu ou relatif classique */ - return(QUOTE(QET_LANG_PATH)); + return(resolveConfiguredDataPath(QUOTE(QET_LANG_PATH))); #else /* the compilation option represents a path relative * to the folder containing the executable binary