diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index a71387287ff..4d0ce966970 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -516,12 +516,27 @@ QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo /*! \since 6.0 Returns the path specified by \a p. + + If there is more than one path listed in qt.conf, it will + only return the first one. + \sa paths */ QString QLibraryInfo::path(LibraryPath p) { return QLibraryInfoPrivate::path(p); } +/*! + \since 6.8 + Returns all paths specificied by \a p. + + \sa path + */ +QStringList QLibraryInfo::paths(LibraryPath p) +{ + return QLibraryInfoPrivate::paths(p); +} + static QString normalizePath(QString ret) { @@ -573,6 +588,64 @@ static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc) } #endif // settings +QStringList QLibraryInfoPrivate::paths(QLibraryInfo::LibraryPath p, + QLibraryInfoPrivate::UsageMode usageMode) +{ + const QLibraryInfo::LibraryPath loc = p; + QList ret; + bool fromConf = false; +#if QT_CONFIG(settings) + if (havePaths()) { + fromConf = true; + + QVariant value = libraryPathToValue(loc); + if (value.isValid()) { + + if (auto *asList = get_if>(&value)) + ret = std::move(*asList); + else + ret = QList({ std::move(value).toString()}); + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + ret[i] = normalizePath(ret[i]); + } + } +#endif // settings + + if (!fromConf) { + QString noConfResult; + if (loc == QLibraryInfo::PrefixPath) { + noConfResult = getPrefix(usageMode); + } else if (int(loc) <= qt_configure_strs.count()) { + noConfResult = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); +#ifndef Q_OS_WIN // On Windows we use the registry + } else if (loc == QLibraryInfo::SettingsPath) { + // Use of volatile is a hack to discourage compilers from calling + // strlen(), in the inlined fromLocal8Bit(const char *)'s body, at + // compile-time, as Qt installers binary-patch the path, replacing + // the dummy path seen at compile-time, typically changing length. + const char *volatile path = QT_CONFIGURE_SETTINGS_PATH; + noConfResult = QString::fromLocal8Bit(path); +#endif + } + if (!noConfResult.isEmpty()) + ret.push_back(std::move(noConfResult)); + } + if (ret.isEmpty()) + return ret; + + QString baseDir; + if (loc == QLibraryInfo::PrefixPath) { + baseDir = prefixFromAppDirHelper(); + } else { + // we make any other path absolute to the prefix directory + baseDir = QLibraryInfoPrivate::path(QLibraryInfo::PrefixPath, usageMode); + } + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + if (QDir::isRelativePath(ret[i])) + ret[i] = QDir::cleanPath(baseDir + u'/' + std::move(ret[i])); + return ret; +} + /* Returns the path specified by \a p. @@ -581,49 +654,7 @@ static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc) */ QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode) { - const QLibraryInfo::LibraryPath loc = p; - QString ret; - bool fromConf = false; -#if QT_CONFIG(settings) - if (havePaths()) { - fromConf = true; - - QVariant value = libraryPathToValue(loc); - if (value.isValid()) { - ret = std::move(value).toString(); - ret = normalizePath(std::move(ret)); - } - } -#endif // settings - - if (!fromConf) { - if (loc == QLibraryInfo::PrefixPath) { - ret = getPrefix(usageMode); - } else if (int(loc) <= qt_configure_strs.count()) { - ret = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); -#ifndef Q_OS_WIN // On Windows we use the registry - } else if (loc == QLibraryInfo::SettingsPath) { - // Use of volatile is a hack to discourage compilers from calling - // strlen(), in the inlined fromLocal8Bit(const char *)'s body, at - // compile-time, as Qt installers binary-patch the path, replacing - // the dummy path seen at compile-time, typically changing length. - const char *volatile path = QT_CONFIGURE_SETTINGS_PATH; - ret = QString::fromLocal8Bit(path); -#endif - } - } - - if (!ret.isEmpty() && QDir::isRelativePath(ret)) { - QString baseDir; - if (loc == QLibraryInfo::PrefixPath) { - baseDir = prefixFromAppDirHelper(); - } else { - // we make any other path absolute to the prefix directory - baseDir = path(QLibraryInfo::PrefixPath, usageMode); - } - ret = QDir::cleanPath(baseDir + u'/' + ret); - } - return ret; + return paths(p, usageMode).value(0, QString()); } /*! diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index d4e8f8b0506..6cac6c83b03 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -42,6 +42,7 @@ public: SettingsPath = 100 }; static QString path(LibraryPath p); + static QStringList paths(LibraryPath p); #if QT_DEPRECATED_SINCE(6, 0) using LibraryLocation = LibraryPath; QT_DEPRECATED_VERSION_X_6_0("Use path()") diff --git a/src/corelib/global/qlibraryinfo_p.h b/src/corelib/global/qlibraryinfo_p.h index 4b471b932e5..b9ca6b4d18d 100644 --- a/src/corelib/global/qlibraryinfo_p.h +++ b/src/corelib/global/qlibraryinfo_p.h @@ -50,6 +50,7 @@ public: }; static QString path(QLibraryInfo::LibraryPath p, UsageMode usageMode = RegularUsage); + static QList paths(QLibraryInfo::LibraryPath p, UsageMode usageMode = RegularUsage); }; QT_END_NAMESPACE diff --git a/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt b/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt index 18642c6838c..33198dd3f04 100644 --- a/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt +++ b/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt @@ -14,4 +14,10 @@ qt_internal_add_test(tst_qlibraryinfo SOURCES tst_qlibraryinfo.cpp ) -qt_add_resources(tst_qlibraryinfo "qtconffiles" PREFIX "/" FILES empty.qt.conf partial.qt.conf) +qt_add_resources(tst_qlibraryinfo "qtconffiles" + PREFIX "/" + FILES + empty.qt.conf + partial.qt.conf + list.qt.conf +) diff --git a/tests/auto/corelib/global/qlibraryinfo/list.qt.conf b/tests/auto/corelib/global/qlibraryinfo/list.qt.conf new file mode 100644 index 00000000000..9271b414ca3 --- /dev/null +++ b/tests/auto/corelib/global/qlibraryinfo/list.qt.conf @@ -0,0 +1,2 @@ +[Paths] +Documentation = "/path/to/mydoc","/path/to/anotherdoc","relativePath" diff --git a/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp b/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp index 1224652bf19..63b5cddcb02 100644 --- a/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp +++ b/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp @@ -15,6 +15,7 @@ private slots: void cleanup(); void path_data(); void path(); + void paths(); }; void tst_QLibraryInfo::initTestCase() @@ -59,6 +60,24 @@ void tst_QLibraryInfo::path() QString value = QLibraryInfo::path(path); QCOMPARE(value, expected); + // check consistency with paths + auto values = QLibraryInfo::paths(path); + QVERIFY(!values.isEmpty()); + QCOMPARE(values.first(), expected); +} + +void tst_QLibraryInfo::paths() +{ + QString qtConfPath(u":/list.qt.conf"); + QLibraryInfoPrivate::setQtconfManualPath(&qtConfPath); + QLibraryInfoPrivate::reload(); + + QList values = QLibraryInfo::paths(QLibraryInfo::DocumentationPath); + QCOMPARE(values.length(), 3); + QCOMPARE(values[0], "/path/to/mydoc"); + QCOMPARE(values[1], "/path/to/anotherdoc"); + QString baseDir = QCoreApplication::applicationDirPath(); + QCOMPARE(values[2], baseDir + "/relativePath"); } QTEST_GUILESS_MAIN(tst_QLibraryInfo)