Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtpaths.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Sune Vuorela <sune@kde.org>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include <QCoreApplication>
5#include <QCommandLineParser>
6#include <QStandardPaths>
7#include <QHash>
8#include <QLibraryInfo>
9
10#include <algorithm>
11
12#include <stdio.h>
13
14#if QT_CONFIG(settings)
15# include <private/qlibraryinfo_p.h>
16# include <qmakelibraryinfo.h>
17# include <propertyprinter.h>
18# include <property.h>
19#endif
20
22
23/**
24 * Prints the string on stdout and appends a newline
25 * \param string printable string
26 */
27static void message(const QString &string)
28{
29 fprintf(stdout, "%s\n", qPrintable(string));
30}
31
32/**
33 * Writes error message and exits 1
34 * \param message to write
35 */
36Q_NORETURN static void error(const QString &message)
37{
38 fprintf(stderr, "%s\n", qPrintable(message));
39 ::exit(EXIT_FAILURE);
40}
41
43public:
44 const char *stringvalue;
47
48 /**
49 * Replace application name by generic name if requested
50 */
51 QString mapName(const QString &s) const
52 {
53 return hasappname ? QString(s).replace("qtpaths", "<APPNAME>") : s;
54 }
55};
56
57static const StringEnum lookupTableData[] = {
58 { "AppConfigLocation", QStandardPaths::AppConfigLocation, true },
59 { "AppDataLocation", QStandardPaths::AppDataLocation, true },
60 { "AppLocalDataLocation", QStandardPaths::AppLocalDataLocation, true },
61 { "ApplicationsLocation", QStandardPaths::ApplicationsLocation, false },
62 { "CacheLocation", QStandardPaths::CacheLocation, true },
63 { "ConfigLocation", QStandardPaths::ConfigLocation, false },
64 { "DesktopLocation", QStandardPaths::DesktopLocation, false },
65 { "DocumentsLocation", QStandardPaths::DocumentsLocation, false },
66 { "DownloadLocation", QStandardPaths::DownloadLocation, false },
67 { "FontsLocation", QStandardPaths::FontsLocation, false },
68 { "GenericCacheLocation", QStandardPaths::GenericCacheLocation, false },
69 { "GenericConfigLocation", QStandardPaths::GenericConfigLocation, false },
70 { "GenericDataLocation", QStandardPaths::GenericDataLocation, false },
71 { "GenericStateLocation", QStandardPaths::GenericStateLocation, false },
72 { "HomeLocation", QStandardPaths::HomeLocation, false },
73 { "MoviesLocation", QStandardPaths::MoviesLocation, false },
74 { "MusicLocation", QStandardPaths::MusicLocation, false },
75 { "PicturesLocation", QStandardPaths::PicturesLocation, false },
76 { "PublicShareLocation", QStandardPaths::PublicShareLocation, false },
77 { "RuntimeLocation", QStandardPaths::RuntimeLocation, false },
78 { "StateLocation", QStandardPaths::StateLocation, true },
79 { "TemplatesLocation", QStandardPaths::TemplatesLocation, false },
80 { "TempLocation", QStandardPaths::TempLocation, false }
81};
82
83/**
84 * \return available types as a QStringList.
85 */
87{
88 QStringList typelist;
89 for (const StringEnum &se : lookupTableData)
90 typelist << QString::fromLatin1(se.stringvalue);
91 std::sort(typelist.begin(), typelist.end());
92 return typelist;
93}
94
95/**
96 * Tries to parse the location string into a reference to a StringEnum entry or alternatively
97 * calls \ref error with a error message
98 */
99static const StringEnum &parseLocationOrError(const QString &locationString)
100{
101 for (const StringEnum &se : lookupTableData)
102 if (locationString == QLatin1StringView(se.stringvalue))
103 return se;
104
105 QString message = QStringLiteral("Unknown location: %1");
106 error(message.arg(locationString));
107}
108
109/**
110 * searches for exactly one remaining argument and returns it.
111 * If not found, \ref error is called with a error message.
112 * \param parser to ask for remaining arguments
113 * \return one extra argument
114 */
115static QString searchStringOrError(QCommandLineParser *parser)
116{
117 int positionalArgumentCount = parser->positionalArguments().size();
118 if (positionalArgumentCount != 1)
119 error(QStringLiteral("Exactly one argument needed as searchitem"));
120 return parser->positionalArguments().constFirst();
121}
122
123int main(int argc, char **argv)
124{
125 QString qtconfManualPath;
126 QCoreApplication app(argc, argv);
127 app.setApplicationVersion(QTPATHS_VERSION_STR);
128
129#ifdef Q_OS_WIN
130 const QLatin1Char pathsep(';');
131#else
132 const QLatin1Char pathsep(':');
133#endif
134
135 QCommandLineParser parser;
136 parser.setApplicationDescription(QStringLiteral("Command line client to QStandardPaths and QLibraryInfo"));
137 parser.addPositionalArgument(QStringLiteral("[name]"), QStringLiteral("Name of file or directory"));
138 parser.addPositionalArgument(QStringLiteral("[properties]"), QStringLiteral("List of the Qt properties to query by the --qt-query argument."));
139 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
140 parser.addHelpOption();
141 parser.addVersionOption();
142
143 //setting up options
144 QCommandLineOption types(QStringLiteral("types"), QStringLiteral("Available location types."));
145 parser.addOption(types);
146
147 QCommandLineOption paths(QStringLiteral("paths"), QStringLiteral("Find paths for <type>."), QStringLiteral("type"));
148 parser.addOption(paths);
149
150 QCommandLineOption writablePath(QStringLiteral("writable-path"),
151 QStringLiteral("Find writable path for <type>."), QStringLiteral("type"));
152 parser.addOption(writablePath);
153
154 QCommandLineOption locateDir(QStringList() << QStringLiteral("locate-dir") << QStringLiteral("locate-directory"),
155 QStringLiteral("Locate directory [name] in <type>."), QStringLiteral("type"));
156 parser.addOption(locateDir);
157
158 QCommandLineOption locateDirs(QStringList() << QStringLiteral("locate-dirs") << QStringLiteral("locate-directories"),
159 QStringLiteral("Locate directories [name] in all paths for <type>."), QStringLiteral("type"));
160 parser.addOption(locateDirs);
161
162 QCommandLineOption locateFile(QStringLiteral("locate-file"),
163 QStringLiteral("Locate file [name] for <type>."), QStringLiteral("type"));
164 parser.addOption(locateFile);
165
166 QCommandLineOption locateFiles(QStringLiteral("locate-files"),
167 QStringLiteral("Locate files [name] in all paths for <type>."), QStringLiteral("type"));
168 parser.addOption(locateFiles);
169
170 QCommandLineOption findExe(QStringList() << QStringLiteral("find-exe") << QStringLiteral("find-executable"),
171 QStringLiteral("Find executable with [name]."));
172 parser.addOption(findExe);
173
174 QCommandLineOption display(QStringList() << QStringLiteral("display"),
175 QStringLiteral("Prints user readable name for <type>."), QStringLiteral("type"));
176 parser.addOption(display);
177
178 QCommandLineOption testmode(QStringList() << QStringLiteral("testmode") << QStringLiteral("test-mode"),
179 QStringLiteral("Use paths specific for unit testing."));
180 parser.addOption(testmode);
181
182 QCommandLineOption qtversion(QStringLiteral("qt-version"), QStringLiteral("Qt version."));
183 qtversion.setFlags(QCommandLineOption::HiddenFromHelp);
184 parser.addOption(qtversion);
185
186 QCommandLineOption installprefix(QStringLiteral("install-prefix"), QStringLiteral("Installation prefix for Qt."));
187 installprefix.setFlags(QCommandLineOption::HiddenFromHelp);
188 parser.addOption(installprefix);
189
190 QCommandLineOption bindir(QStringList() << QStringLiteral("binaries-dir") << QStringLiteral("binaries-directory"),
191 QStringLiteral("Location of Qt executables."));
192 bindir.setFlags(QCommandLineOption::HiddenFromHelp);
193 parser.addOption(bindir);
194
195 QCommandLineOption plugindir(QStringList() << QStringLiteral("plugin-dir") << QStringLiteral("plugin-directory"),
196 QStringLiteral("Location of Qt plugins."));
197 plugindir.setFlags(QCommandLineOption::HiddenFromHelp);
198 parser.addOption(plugindir);
199
200 QCommandLineOption query(
201 QStringList() << QStringLiteral("qt-query") << QStringLiteral("query"),
202 QStringLiteral("List of Qt properties. Can be used standalone or with the "
203 "--query-format and --qtconf options."));
204 parser.addOption(query);
205
206 QCommandLineOption queryformat(QStringLiteral("query-format"),
207 QStringLiteral("Output format for --qt-query.\nSupported formats: qmake (default), json"),
208 QStringLiteral("format"));
209 queryformat.setDefaultValue("qmake");
210 parser.addOption(queryformat);
211
212 QCommandLineOption qtconf(QStringLiteral("qtconf"),
213 QStringLiteral("Path to qt.conf file that will be used to override the queried Qt properties."),
214 QStringLiteral("path"));
215 parser.addOption(qtconf);
216
217 parser.process(app);
218
219 QStandardPaths::setTestModeEnabled(parser.isSet(testmode));
220
221#if QT_CONFIG(settings)
222 if (parser.isSet(qtconf)) {
223 qtconfManualPath = parser.value(qtconf);
224 QLibraryInfoPrivate::setQtconfManualPath(&qtconfManualPath);
225 }
226#endif
227
228 QStringList results;
229 if (parser.isSet(qtversion)) {
230 QString qtversionstring = QString::fromLatin1(QT_VERSION_STR);
231 results << qtversionstring;
232 }
233
234 if (parser.isSet(installprefix)) {
235 QString path = QLibraryInfo::path(QLibraryInfo::PrefixPath);
236 results << path;
237 }
238
239 if (parser.isSet(bindir)) {
240 QString path = QLibraryInfo::path(QLibraryInfo::BinariesPath);
241 results << path;
242 }
243
244 if (parser.isSet(plugindir)) {
245 QString path = QLibraryInfo::path(QLibraryInfo::PluginsPath);
246 results << path;
247 }
248
249 if (parser.isSet(types)) {
250 QStringList typesList = ::types();
251 results << typesList.join('\n');
252 }
253
254 if (parser.isSet(display)) {
255 const StringEnum location = parseLocationOrError(parser.value(display));
256 QString text = QStandardPaths::displayName(location.enumvalue);
257 results << location.mapName(text);
258 }
259
260 if (parser.isSet(paths)) {
261 const StringEnum location = parseLocationOrError(parser.value(paths));
262 QStringList paths = QStandardPaths::standardLocations(location.enumvalue);
263 results << location.mapName(paths.join(pathsep));
264 }
265
266 if (parser.isSet(writablePath)) {
267 const StringEnum location = parseLocationOrError(parser.value(writablePath));
268 QString path = QStandardPaths::writableLocation(location.enumvalue);
269 results << location.mapName(path);
270 }
271
272 if (parser.isSet(findExe)) {
273 QString searchitem = searchStringOrError(&parser);
274 QString path = QStandardPaths::findExecutable(searchitem);
275 results << path;
276 }
277
278 if (parser.isSet(locateDir)) {
279 const StringEnum location = parseLocationOrError(parser.value(locateDir));
280 QString searchitem = searchStringOrError(&parser);
281 QString path = QStandardPaths::locate(location.enumvalue, searchitem, QStandardPaths::LocateDirectory);
282 results << location.mapName(path);
283 }
284
285 if (parser.isSet(locateFile)) {
286 const StringEnum location = parseLocationOrError(parser.value(locateFile));
287 QString searchitem = searchStringOrError(&parser);
288 QString path = QStandardPaths::locate(location.enumvalue, searchitem, QStandardPaths::LocateFile);
289 results << location.mapName(path);
290 }
291
292 if (parser.isSet(locateDirs)) {
293 const StringEnum location = parseLocationOrError(parser.value(locateDirs));
294 QString searchitem = searchStringOrError(&parser);
295 QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateDirectory);
296 results << location.mapName(paths.join(pathsep));
297 }
298
299 if (parser.isSet(locateFiles)) {
300 const StringEnum location = parseLocationOrError(parser.value(locateFiles));
301 QString searchitem = searchStringOrError(&parser);
302 QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateFile);
303 results << location.mapName(paths.join(pathsep));
304 }
305
306#if !QT_CONFIG(settings)
307 if (parser.isSet(query) || parser.isSet(qtconf) || parser.isSet(queryformat)) {
308 error(QStringLiteral("--qt-query, --qtconf and --query-format options are not supported. The 'settings' feature is missing."));
309 }
310#else
311 if (parser.isSet(query)) {
312 if (!results.isEmpty()) {
313 QString errorMessage = QStringLiteral("Several options given, only one is supported at a time.");
314 error(errorMessage);
315 }
316
317 PropertyPrinter printer;
318 if (parser.isSet(queryformat)) {
319 QString formatValue = parser.value(queryformat);
320 if (formatValue == "json") {
321 printer = jsonPropertyPrinter;
322 } else if (formatValue != "qmake") {
323 QString errorMessage = QStringLiteral("Invalid output format %1. Supported formats: qmake, json").arg(formatValue);
324 error(errorMessage);
325 }
326 }
327
328 QStringList optionProperties = parser.positionalArguments();
329 QMakeProperty prop;
330 if (printer) {
331 return prop.queryProperty(optionProperties, printer);
332 }
333 return prop.queryProperty(optionProperties);
334 } else if (parser.isSet(queryformat)) {
335 error(QStringLiteral("--query-format is set, but --qt-query is not requested."));
336 }
337#endif
338
339 if (results.isEmpty()) {
340 parser.showHelp();
341 } else if (results.size() == 1) {
342 const QString &item = results.constFirst();
343 message(item);
344 if (item.isEmpty())
345 return EXIT_FAILURE;
346 } else {
347 QString errorMessage = QStringLiteral("Several options given, only one is supported at a time.");
348 error(errorMessage);
349 }
350 return EXIT_SUCCESS;
351}
bool hasappname
Definition qtpaths.cpp:46
QStandardPaths::StandardLocation enumvalue
Definition qtpaths.cpp:45
const char * stringvalue
Definition qtpaths.cpp:44
QString mapName(const QString &s) const
Definition qtpaths.cpp:51
static QStringList types()
Definition qtpaths.cpp:86
static Q_NORETURN void error(const QString &message)
Definition qtpaths.cpp:36
static const StringEnum & parseLocationOrError(const QString &locationString)
Definition qtpaths.cpp:99
static const StringEnum lookupTableData[]
Definition qtpaths.cpp:57
static QString searchStringOrError(QCommandLineParser *parser)
Definition qtpaths.cpp:115
static QT_USE_NAMESPACE void message(const QString &string)
Definition qtpaths.cpp:27
int main(int argc, char *argv[])
[ctor_close]