diff options
Diffstat (limited to 'src/tools/qtpaths')
-rw-r--r-- | src/tools/qtpaths/CMakeLists.txt | 33 | ||||
-rw-r--r-- | src/tools/qtpaths/qtpaths.cpp | 356 |
2 files changed, 389 insertions, 0 deletions
diff --git a/src/tools/qtpaths/CMakeLists.txt b/src/tools/qtpaths/CMakeLists.txt new file mode 100644 index 0000000000..d64caeb3c2 --- /dev/null +++ b/src/tools/qtpaths/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## qtpaths App: +##################################################################### + +qt_get_tool_target_name(target_name qtpaths) +qt_internal_add_tool(${target_name} + TRY_RUN + TARGET_DESCRIPTION "Qt tool that provides the standard paths of the Qt framework" + TOOLS_TARGET Core + INSTALL_VERSIONED_LINK + SOURCES + qtpaths.cpp + DEFINES + QTPATHS_VERSION_STR="2.0" +) +qt_internal_return_unless_building_tools() + +## Scopes: +##################################################################### + +qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_settings + LIBRARIES + QtLibraryInfo +) + +if(WIN32 AND TARGET ${target_name}) + set_target_properties(${target_name} PROPERTIES + WIN32_EXECUTABLE FALSE + ) +endif() diff --git a/src/tools/qtpaths/qtpaths.cpp b/src/tools/qtpaths/qtpaths.cpp new file mode 100644 index 0000000000..71f9fe4349 --- /dev/null +++ b/src/tools/qtpaths/qtpaths.cpp @@ -0,0 +1,356 @@ +// Copyright (C) 2016 Sune Vuorela <sune@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QCoreApplication> +#include <QCommandLineParser> +#include <QStandardPaths> +#include <QHash> +#include <QLibraryInfo> + +#include <algorithm> + +#include <stdio.h> + +#if QT_CONFIG(settings) +# include <private/qlibraryinfo_p.h> +# include <qmakelibraryinfo.h> +# include <propertyprinter.h> +# include <property.h> +#endif + +QT_USE_NAMESPACE + +/** + * Prints the string on stdout and appends a newline + * \param string printable string + */ +static void message(const QString &string) +{ + fprintf(stdout, "%s\n", qPrintable(string)); +} + +/** + * Writes error message and exits 1 + * \param message to write + */ +Q_NORETURN static void error(const QString &message) +{ + fprintf(stderr, "%s\n", qPrintable(message)); + ::exit(EXIT_FAILURE); +} + +class StringEnum { +public: + const char *stringvalue; + QStandardPaths::StandardLocation enumvalue; + bool hasappname; + + /** + * Replace application name by generic name if requested + */ + QString mapName(const QString &s) const + { + return hasappname ? QString(s).replace("qtpaths", "<APPNAME>") : s; + } +}; + +static const StringEnum lookupTableData[] = { + { "AppConfigLocation", QStandardPaths::AppConfigLocation, true }, + { "AppDataLocation", QStandardPaths::AppDataLocation, true }, + { "AppLocalDataLocation", QStandardPaths::AppLocalDataLocation, true }, + { "ApplicationsLocation", QStandardPaths::ApplicationsLocation, false }, + { "CacheLocation", QStandardPaths::CacheLocation, true }, + { "ConfigLocation", QStandardPaths::ConfigLocation, false }, + { "DesktopLocation", QStandardPaths::DesktopLocation, false }, + { "DocumentsLocation", QStandardPaths::DocumentsLocation, false }, + { "DownloadLocation", QStandardPaths::DownloadLocation, false }, + { "FontsLocation", QStandardPaths::FontsLocation, false }, + { "GenericCacheLocation", QStandardPaths::GenericCacheLocation, false }, + { "GenericConfigLocation", QStandardPaths::GenericConfigLocation, false }, + { "GenericDataLocation", QStandardPaths::GenericDataLocation, false }, + { "GenericStateLocation", QStandardPaths::GenericStateLocation, false }, + { "HomeLocation", QStandardPaths::HomeLocation, false }, + { "MoviesLocation", QStandardPaths::MoviesLocation, false }, + { "MusicLocation", QStandardPaths::MusicLocation, false }, + { "PicturesLocation", QStandardPaths::PicturesLocation, false }, + { "PublicShareLocation", QStandardPaths::PublicShareLocation, false }, + { "RuntimeLocation", QStandardPaths::RuntimeLocation, false }, + { "StateLocation", QStandardPaths::StateLocation, true }, + { "TemplatesLocation", QStandardPaths::TemplatesLocation, false }, + { "TempLocation", QStandardPaths::TempLocation, false } +}; + +/** + * \return available types as a QStringList. + */ +static QStringList types() +{ + QStringList typelist; + for (const StringEnum &se : lookupTableData) + typelist << QString::fromLatin1(se.stringvalue); + std::sort(typelist.begin(), typelist.end()); + return typelist; +} + +/** + * Tries to parse the location string into a reference to a StringEnum entry or alternatively + * calls \ref error with a error message + */ +static const StringEnum &parseLocationOrError(const QString &locationString) +{ + for (const StringEnum &se : lookupTableData) + if (locationString == QLatin1StringView(se.stringvalue)) + return se; + + QString message = QStringLiteral("Unknown location: %1"); + error(message.arg(locationString)); +} + +/** + * searches for exactly one remaining argument and returns it. + * If not found, \ref error is called with a error message. + * \param parser to ask for remaining arguments + * \return one extra argument + */ +static QString searchStringOrError(QCommandLineParser *parser) +{ + int positionalArgumentCount = parser->positionalArguments().size(); + if (positionalArgumentCount != 1) + error(QStringLiteral("Exactly one argument needed as searchitem")); + return parser->positionalArguments().constFirst(); +} + +int main(int argc, char **argv) +{ + QString qtconfManualPath; + QCoreApplication app(argc, argv); + app.setApplicationVersion(QTPATHS_VERSION_STR); + +#ifdef Q_OS_WIN + const QLatin1Char pathsep(';'); +#else + const QLatin1Char pathsep(':'); +#endif + + QCommandLineParser parser; + parser.setApplicationDescription(QStringLiteral("Command line client to QStandardPaths and QLibraryInfo")); + parser.addPositionalArgument(QStringLiteral("[name]"), QStringLiteral("Name of file or directory")); + parser.addPositionalArgument(QStringLiteral("[properties]"), QStringLiteral("List of the Qt properties to query by the --qt-query argument.")); + parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + parser.addHelpOption(); + parser.addVersionOption(); + + //setting up options + QCommandLineOption types(QStringLiteral("types"), QStringLiteral("Available location types.")); + parser.addOption(types); + + QCommandLineOption paths(QStringLiteral("paths"), QStringLiteral("Find paths for <type>."), QStringLiteral("type")); + parser.addOption(paths); + + QCommandLineOption writablePath(QStringLiteral("writable-path"), + QStringLiteral("Find writable path for <type>."), QStringLiteral("type")); + parser.addOption(writablePath); + + QCommandLineOption locateDir(QStringList() << QStringLiteral("locate-dir") << QStringLiteral("locate-directory"), + QStringLiteral("Locate directory [name] in <type>."), QStringLiteral("type")); + parser.addOption(locateDir); + + QCommandLineOption locateDirs(QStringList() << QStringLiteral("locate-dirs") << QStringLiteral("locate-directories"), + QStringLiteral("Locate directories [name] in all paths for <type>."), QStringLiteral("type")); + parser.addOption(locateDirs); + + QCommandLineOption locateFile(QStringLiteral("locate-file"), + QStringLiteral("Locate file [name] for <type>."), QStringLiteral("type")); + parser.addOption(locateFile); + + QCommandLineOption locateFiles(QStringLiteral("locate-files"), + QStringLiteral("Locate files [name] in all paths for <type>."), QStringLiteral("type")); + parser.addOption(locateFiles); + + QCommandLineOption findExe(QStringList() << QStringLiteral("find-exe") << QStringLiteral("find-executable"), + QStringLiteral("Find executable with [name].")); + parser.addOption(findExe); + + QCommandLineOption display(QStringList() << QStringLiteral("display"), + QStringLiteral("Prints user readable name for <type>."), QStringLiteral("type")); + parser.addOption(display); + + QCommandLineOption testmode(QStringList() << QStringLiteral("testmode") << QStringLiteral("test-mode"), + QStringLiteral("Use paths specific for unit testing.")); + parser.addOption(testmode); + + QCommandLineOption qtversion(QStringLiteral("qt-version"), QStringLiteral("Qt version.")); + qtversion.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(qtversion); + + QCommandLineOption installprefix(QStringLiteral("install-prefix"), QStringLiteral("Installation prefix for Qt.")); + installprefix.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(installprefix); + + QCommandLineOption bindir(QStringList() << QStringLiteral("binaries-dir") << QStringLiteral("binaries-directory"), + QStringLiteral("Location of Qt executables.")); + bindir.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(bindir); + + QCommandLineOption plugindir(QStringList() << QStringLiteral("plugin-dir") << QStringLiteral("plugin-directory"), + QStringLiteral("Location of Qt plugins.")); + plugindir.setFlags(QCommandLineOption::HiddenFromHelp); + parser.addOption(plugindir); + + QCommandLineOption query( + QStringList() << QStringLiteral("qt-query") << QStringLiteral("query"), + QStringLiteral("List of Qt properties. Can be used standalone or with the " + "--query-format and --qtconf options.")); + parser.addOption(query); + + QCommandLineOption queryformat(QStringLiteral("query-format"), + QStringLiteral("Output format for --qt-query.\nSupported formats: qmake (default), json"), + QStringLiteral("format")); + queryformat.setDefaultValue("qmake"); + parser.addOption(queryformat); + + QCommandLineOption qtconf(QStringLiteral("qtconf"), + QStringLiteral("Path to qt.conf file that will be used to override the queried Qt properties."), + QStringLiteral("path")); + parser.addOption(qtconf); + + parser.process(app); + + QStandardPaths::setTestModeEnabled(parser.isSet(testmode)); + +#if QT_CONFIG(settings) + if (parser.isSet(qtconf)) { + qtconfManualPath = parser.value(qtconf); + QLibraryInfoPrivate::setQtconfManualPath(&qtconfManualPath); + } +#endif + + QStringList results; + if (parser.isSet(qtversion)) { + QString qtversionstring = QString::fromLatin1(QT_VERSION_STR); + results << qtversionstring; + } + + if (parser.isSet(installprefix)) { + QString path = QLibraryInfo::path(QLibraryInfo::PrefixPath); + results << path; + } + + if (parser.isSet(bindir)) { + QString path = QLibraryInfo::path(QLibraryInfo::BinariesPath); + results << path; + } + + if (parser.isSet(plugindir)) { + QString path = QLibraryInfo::path(QLibraryInfo::PluginsPath); + results << path; + } + + if (parser.isSet(types)) { + QStringList typesList = ::types(); + results << typesList.join('\n'); + } + + QT_WARNING_PUSH +#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1300 && Q_CC_GNU < 1500 + QT_WARNING_DISABLE_GCC("-Wdangling-reference") +#endif + if (parser.isSet(display)) { + const StringEnum &location = parseLocationOrError(parser.value(display)); + QString text = QStandardPaths::displayName(location.enumvalue); + results << location.mapName(text); + } + + if (parser.isSet(paths)) { + const StringEnum &location = parseLocationOrError(parser.value(paths)); + QStringList paths = QStandardPaths::standardLocations(location.enumvalue); + results << location.mapName(paths.join(pathsep)); + } + + if (parser.isSet(writablePath)) { + const StringEnum &location = parseLocationOrError(parser.value(writablePath)); + QString path = QStandardPaths::writableLocation(location.enumvalue); + results << location.mapName(path); + } + + if (parser.isSet(findExe)) { + QString searchitem = searchStringOrError(&parser); + QString path = QStandardPaths::findExecutable(searchitem); + results << path; + } + + if (parser.isSet(locateDir)) { + const StringEnum &location = parseLocationOrError(parser.value(locateDir)); + QString searchitem = searchStringOrError(&parser); + QString path = QStandardPaths::locate(location.enumvalue, searchitem, QStandardPaths::LocateDirectory); + results << location.mapName(path); + } + + if (parser.isSet(locateFile)) { + const StringEnum &location = parseLocationOrError(parser.value(locateFile)); + QString searchitem = searchStringOrError(&parser); + QString path = QStandardPaths::locate(location.enumvalue, searchitem, QStandardPaths::LocateFile); + results << location.mapName(path); + } + + if (parser.isSet(locateDirs)) { + const StringEnum &location = parseLocationOrError(parser.value(locateDirs)); + QString searchitem = searchStringOrError(&parser); + QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateDirectory); + results << location.mapName(paths.join(pathsep)); + } + + if (parser.isSet(locateFiles)) { + const StringEnum &location = parseLocationOrError(parser.value(locateFiles)); + QString searchitem = searchStringOrError(&parser); + QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateFile); + results << location.mapName(paths.join(pathsep)); + } + QT_WARNING_POP + +#if !QT_CONFIG(settings) + if (parser.isSet(query) || parser.isSet(qtconf) || parser.isSet(queryformat)) { + error(QStringLiteral("--qt-query, --qtconf and --query-format options are not supported. The 'settings' feature is missing.")); + } +#else + if (parser.isSet(query)) { + if (!results.isEmpty()) { + QString errorMessage = QStringLiteral("Several options given, only one is supported at a time."); + error(errorMessage); + } + + PropertyPrinter printer; + if (parser.isSet(queryformat)) { + QString formatValue = parser.value(queryformat); + if (formatValue == "json") { + printer = jsonPropertyPrinter; + } else if (formatValue != "qmake") { + QString errorMessage = QStringLiteral("Invalid output format %1. Supported formats: qmake, json").arg(formatValue); + error(errorMessage); + } + } + + QStringList optionProperties = parser.positionalArguments(); + QMakeProperty prop; + if (printer) { + return prop.queryProperty(optionProperties, printer); + } + return prop.queryProperty(optionProperties); + } else if (parser.isSet(queryformat)) { + error(QStringLiteral("--query-format is set, but --qt-query is not requested.")); + } +#endif + + if (results.isEmpty()) { + parser.showHelp(); + } else if (results.size() == 1) { + const QString &item = results.constFirst(); + message(item); + if (item.isEmpty()) + return EXIT_FAILURE; + } else { + QString errorMessage = QStringLiteral("Several options given, only one is supported at a time."); + error(errorMessage); + } + return EXIT_SUCCESS; +} |