Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qgenericunixservices.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QtGui/private/qtguiglobal_p.h>
6#include "qguiapplication.h"
7#include "qwindow.h"
8#include <QtGui/qpa/qplatformwindow_p.h>
9#include <QtGui/qpa/qplatformwindow.h>
10#include <QtGui/qpa/qplatformnativeinterface.h>
11
12#include <QtCore/QDebug>
13#include <QtCore/QFile>
14#if QT_CONFIG(process)
15# include <QtCore/QProcess>
16#endif
17#if QT_CONFIG(settings)
18#include <QtCore/QSettings>
19#endif
20#include <QtCore/QStandardPaths>
21#include <QtCore/QUrl>
22
23#if QT_CONFIG(dbus)
24// These QtCore includes are needed for xdg-desktop-portal support
25#include <QtCore/private/qcore_unix_p.h>
26
27#include <QtCore/QFileInfo>
28#include <QtCore/QUrlQuery>
29
30#include <QtDBus/QDBusConnection>
31#include <QtDBus/QDBusMessage>
32#include <QtDBus/QDBusPendingCall>
33#include <QtDBus/QDBusPendingCallWatcher>
34#include <QtDBus/QDBusPendingReply>
35#include <QtDBus/QDBusUnixFileDescriptor>
36
37#include <fcntl.h>
38
39#endif // QT_CONFIG(dbus)
40
41#include <stdlib.h>
42
44
45using namespace Qt::StringLiterals;
46
47#if QT_CONFIG(multiprocess)
48
49enum { debug = 0 };
50
51static inline QByteArray detectDesktopEnvironment()
52{
53 const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
54 if (!xdgCurrentDesktop.isEmpty())
55 return xdgCurrentDesktop.toUpper(); // KDE, GNOME, UNITY, LXDE, MATE, XFCE...
56
57 // Classic fallbacks
58 if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION"))
59 return QByteArrayLiteral("KDE");
60 if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID"))
61 return QByteArrayLiteral("GNOME");
62
63 // Fallback to checking $DESKTOP_SESSION (unreliable)
64 QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
65
66 // This can be a path in /usr/share/xsessions
67 int slash = desktopSession.lastIndexOf('/');
68 if (slash != -1) {
69#if QT_CONFIG(settings)
70 QSettings desktopFile(QFile::decodeName(desktopSession + ".desktop"), QSettings::IniFormat);
71 desktopFile.beginGroup(QStringLiteral("Desktop Entry"));
72 QByteArray desktopName = desktopFile.value(QStringLiteral("DesktopNames")).toByteArray();
73 if (!desktopName.isEmpty())
74 return desktopName;
75#endif
76
77 // try decoding just the basename
78 desktopSession = desktopSession.mid(slash + 1);
79 }
80
81 if (desktopSession == "gnome")
82 return QByteArrayLiteral("GNOME");
83 else if (desktopSession == "xfce")
84 return QByteArrayLiteral("XFCE");
85 else if (desktopSession == "kde")
86 return QByteArrayLiteral("KDE");
87
88 return QByteArrayLiteral("UNKNOWN");
89}
90
91static inline bool checkExecutable(const QString &candidate, QString *result)
92{
94 return !result->isEmpty();
95}
96
97static inline bool detectWebBrowser(const QByteArray &desktop,
98 bool checkBrowserVariable,
99 QString *browser)
100{
101 const char *browsers[] = {"google-chrome", "firefox", "mozilla", "opera"};
102
103 browser->clear();
104 if (checkExecutable(QStringLiteral("xdg-open"), browser))
105 return true;
106
107 if (checkBrowserVariable) {
108 QByteArray browserVariable = qgetenv("DEFAULT_BROWSER");
109 if (browserVariable.isEmpty())
110 browserVariable = qgetenv("BROWSER");
111 if (!browserVariable.isEmpty() && checkExecutable(QString::fromLocal8Bit(browserVariable), browser))
112 return true;
113 }
114
115 if (desktop == QByteArray("KDE")) {
116 if (checkExecutable(QStringLiteral("kde-open5"), browser))
117 return true;
118 // Konqueror launcher
119 if (checkExecutable(QStringLiteral("kfmclient"), browser)) {
120 browser->append(" exec"_L1);
121 return true;
122 }
123 } else if (desktop == QByteArray("GNOME")) {
124 if (checkExecutable(QStringLiteral("gnome-open"), browser))
125 return true;
126 }
127
128 for (size_t i = 0; i < sizeof(browsers)/sizeof(char *); ++i)
129 if (checkExecutable(QLatin1StringView(browsers[i]), browser))
130 return true;
131 return false;
132}
133
134static inline bool launch(const QString &launcher, const QUrl &url,
135 const QString &xdgActivationToken)
136{
137 if (!xdgActivationToken.isEmpty()) {
138 qputenv("XDG_ACTIVATION_TOKEN", xdgActivationToken.toUtf8());
139 }
140
141 const QString command = launcher + u' ' + QLatin1StringView(url.toEncoded());
142 if (debug)
143 qDebug("Launching %s", qPrintable(command));
144#if !QT_CONFIG(process)
145 const bool ok = ::system(qPrintable(command + " &"_L1));
146#else
147 QStringList args = QProcess::splitCommand(command);
148 bool ok = false;
149 if (!args.isEmpty()) {
151 ok = QProcess::startDetached(program, args);
152 }
153#endif
154 if (!ok)
155 qWarning("Launch failed (%s)", qPrintable(command));
156
157 qunsetenv("XDG_ACTIVATION_TOKEN");
158
159 return ok;
160}
161
162#if QT_CONFIG(dbus)
163static inline bool checkNeedPortalSupport()
164{
165 return QFileInfo::exists("/.flatpak-info"_L1) || qEnvironmentVariableIsSet("SNAP");
166}
167
168static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url, const QString &parentWindow,
169 const QString &xdgActivationToken)
170{
171 // DBus signature:
172 // OpenFile (IN s parent_window,
173 // IN h fd,
174 // IN a{sv} options,
175 // OUT o handle)
176 // Options:
177 // handle_token (s) - A string that will be used as the last element of the @handle.
178 // writable (b) - Whether to allow the chosen application to write to the file.
179
180 const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
181 if (fd != -1) {
182 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
183 "/org/freedesktop/portal/desktop"_L1,
184 "org.freedesktop.portal.OpenURI"_L1,
185 "OpenFile"_L1);
186
187 QDBusUnixFileDescriptor descriptor;
188 descriptor.giveFileDescriptor(fd);
189
190 QVariantMap options = {};
191
192 if (!xdgActivationToken.isEmpty()) {
193 options.insert("activation_token"_L1, xdgActivationToken);
194 }
195
196 message << parentWindow << QVariant::fromValue(descriptor) << options;
197
199 }
200
202}
203
204static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url, const QString &parentWindow,
205 const QString &xdgActivationToken)
206{
207 // DBus signature:
208 // OpenURI (IN s parent_window,
209 // IN s uri,
210 // IN a{sv} options,
211 // OUT o handle)
212 // Options:
213 // handle_token (s) - A string that will be used as the last element of the @handle.
214 // writable (b) - Whether to allow the chosen application to write to the file.
215 // This key only takes effect the uri points to a local file that is exported in the document portal,
216 // and the chosen application is sandboxed itself.
217
218 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
219 "/org/freedesktop/portal/desktop"_L1,
220 "org.freedesktop.portal.OpenURI"_L1,
221 "OpenURI"_L1);
222 // FIXME parent_window_id and handle writable option
223 QVariantMap options;
224
225 if (!xdgActivationToken.isEmpty()) {
226 options.insert("activation_token"_L1, xdgActivationToken);
227 }
228
229 message << parentWindow << url.toString() << options;
230
232}
233
234static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url, const QString &parentWindow,
235 const QString &xdgActivationToken)
236{
237 // DBus signature:
238 // ComposeEmail (IN s parent_window,
239 // IN a{sv} options,
240 // OUT o handle)
241 // Options:
242 // address (s) - The email address to send to.
243 // subject (s) - The subject for the email.
244 // body (s) - The body for the email.
245 // attachment_fds (ah) - File descriptors for files to attach.
246
247 QUrlQuery urlQuery(url);
248 QVariantMap options;
249 options.insert("address"_L1, url.path());
250 options.insert("subject"_L1, urlQuery.queryItemValue("subject"_L1));
251 options.insert("body"_L1, urlQuery.queryItemValue("body"_L1));
252
253 // O_PATH seems to be present since Linux 2.6.39, which is not case of RHEL 6
254#ifdef O_PATH
256 const QStringList attachmentUris = urlQuery.allQueryItemValues("attachment"_L1);
257
258 for (const QString &attachmentUri : attachmentUris) {
259 const int fd = qt_safe_open(QFile::encodeName(attachmentUri), O_PATH);
260 if (fd != -1) {
261 QDBusUnixFileDescriptor descriptor(fd);
262 attachments << descriptor;
264 }
265 }
266
267 options.insert("attachment_fds"_L1, QVariant::fromValue(attachments));
268#endif
269
270 if (!xdgActivationToken.isEmpty()) {
271 options.insert("activation_token"_L1, xdgActivationToken);
272 }
273
274 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
275 "/org/freedesktop/portal/desktop"_L1,
276 "org.freedesktop.portal.Email"_L1,
277 "ComposeEmail"_L1);
278
279 message << parentWindow << options;
280
282}
283
284namespace {
285struct XDGDesktopColor
286{
287 double r = 0;
288 double g = 0;
289 double b = 0;
290
291 QColor toQColor() const
292 {
293 constexpr auto rgbMax = 255;
294 return { static_cast<int>(r * rgbMax), static_cast<int>(g * rgbMax),
295 static_cast<int>(b * rgbMax) };
296 }
297};
298
299const QDBusArgument &operator>>(const QDBusArgument &argument, XDGDesktopColor &myStruct)
300{
302 argument >> myStruct.r >> myStruct.g >> myStruct.b;
304 return argument;
305}
306
307class XdgDesktopPortalColorPicker : public QPlatformServiceColorPicker
308{
310public:
311 XdgDesktopPortalColorPicker(const QString &parentWindowId, QWindow *parent)
312 : QPlatformServiceColorPicker(parent), m_parentWindowId(parentWindowId)
313 {
314 }
315
316 void pickColor() override
317 {
318 // DBus signature:
319 // PickColor (IN s parent_window,
320 // IN a{sv} options
321 // OUT o handle)
322 // Options:
323 // handle_token (s) - A string that will be used as the last element of the @handle.
324
326 "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
327 "org.freedesktop.portal.Screenshot"_L1, "PickColor"_L1);
328 message << m_parentWindowId << QVariantMap();
329
331 auto watcher = new QDBusPendingCallWatcher(pendingCall, this);
334 watcher->deleteLater();
336 if (reply.isError()) {
337 qWarning("DBus call to pick color failed: %s",
338 qPrintable(reply.error().message()));
339 Q_EMIT colorPicked({});
340 } else {
342 "org.freedesktop.portal.Desktop"_L1, reply.value().path(),
343 "org.freedesktop.portal.Request"_L1, "Response"_L1, this,
344 // clang-format off
345 SLOT(gotColorResponse(uint,QVariantMap))
346 // clang-format on
347 );
348 }
349 });
350 }
351
352private Q_SLOTS:
353 void gotColorResponse(uint result, const QVariantMap &map)
354 {
355 if (result != 0)
356 return;
357 XDGDesktopColor color{};
358 map.value(u"color"_s).value<QDBusArgument>() >> color;
359 Q_EMIT colorPicked(color.toQColor());
360 deleteLater();
361 }
362
363private:
364 const QString m_parentWindowId;
365};
366} // namespace
367
368#endif // QT_CONFIG(dbus)
369
371{
372#if QT_CONFIG(dbus)
373 if (qEnvironmentVariableIntValue("QT_NO_XDG_DESKTOP_PORTAL") > 0) {
374 return;
375 }
377 "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
378 "org.freedesktop.DBus.Properties"_L1, "Get"_L1);
379 message << "org.freedesktop.portal.Screenshot"_L1
380 << "version"_L1;
381
383 auto watcher = new QDBusPendingCallWatcher(pendingCall);
386 watcher->deleteLater();
388 if (!reply.isError() && reply.value().toUInt() >= 2)
389 m_hasScreenshotPortalWithColorPicking = true;
390 });
391
392#endif
393}
394
396{
397#if QT_CONFIG(dbus)
398 // Make double sure that we are in a wayland environment. In particular check
399 // WAYLAND_DISPLAY so also XWayland apps benefit from portal-based color picking.
400 // Outside wayland we'll rather rely on other means than the XDG desktop portal.
401 if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")
402 || QGuiApplication::platformName().startsWith("wayland"_L1)) {
403 return new XdgDesktopPortalColorPicker(portalWindowIdentifier(parent), parent);
404 }
405 return nullptr;
406#else
408 return nullptr;
409#endif
410}
411
413{
414 static const QByteArray result = detectDesktopEnvironment();
415 return result;
416}
417
418template<typename F>
419void runWithXdgActivationToken(F &&functionToCall)
420{
421 QWindow *window = qGuiApp->focusWindow();
422
423 if (!window) {
424 return;
425 }
426
427 auto waylandApp = dynamic_cast<QNativeInterface::QWaylandApplication *>(
428 qGuiApp->platformNativeInterface());
429 auto waylandWindow =
430 dynamic_cast<QNativeInterface::Private::QWaylandWindow *>(window->handle());
431
432 if (!waylandWindow || !waylandApp) {
433 return;
434 }
435
436 waylandWindow->requestXdgActivationToken(waylandApp->lastInputSerial());
437 QObject::connect(waylandWindow,
438 &QNativeInterface::Private::QWaylandWindow::xdgActivationTokenCreated,
439 waylandWindow, functionToCall, Qt::SingleShotConnection);
440}
441
443{
444 auto openUrlInternal = [this](const QUrl &url, const QString &xdgActivationToken) {
445 if (url.scheme() == "mailto"_L1) {
446# if QT_CONFIG(dbus)
448 const QString parentWindow = QGuiApplication::focusWindow()
450 : QString();
451 QDBusError error = xdgDesktopPortalSendEmail(url, parentWindow, xdgActivationToken);
452 if (!error.isValid())
453 return true;
454
455 // service not running, fall back
456 }
457# endif
458 return openDocument(url);
459 }
460
461# if QT_CONFIG(dbus)
463 const QString parentWindow = QGuiApplication::focusWindow()
465 : QString();
466 QDBusError error = xdgDesktopPortalOpenUrl(url, parentWindow, xdgActivationToken);
467 if (!error.isValid())
468 return true;
469 }
470# endif
471
472 if (m_webBrowser.isEmpty()
473 && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
474 qWarning("Unable to detect a web browser to launch '%s'", qPrintable(url.toString()));
475 return false;
476 }
477 return launch(m_webBrowser, url, xdgActivationToken);
478 };
479
480 if (QGuiApplication::platformName().startsWith("wayland"_L1)) {
481 runWithXdgActivationToken(
482 [openUrlInternal, url](const QString &token) { openUrlInternal(url, token); });
483
484 return true;
485
486 } else {
487 return openUrlInternal(url, QString());
488 }
489}
490
492{
493 auto openDocumentInternal = [this](const QUrl &url, const QString &xdgActivationToken) {
494
495# if QT_CONFIG(dbus)
497 const QString parentWindow = QGuiApplication::focusWindow()
499 : QString();
500 QDBusError error = xdgDesktopPortalOpenFile(url, parentWindow, xdgActivationToken);
501 if (!error.isValid())
502 return true;
503 }
504# endif
505
506 if (m_documentLauncher.isEmpty()
507 && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) {
508 qWarning("Unable to detect a launcher for '%s'", qPrintable(url.toString()));
509 return false;
510 }
511 return launch(m_documentLauncher, url, xdgActivationToken);
512 };
513
514 if (QGuiApplication::platformName().startsWith("wayland"_L1)) {
515 runWithXdgActivationToken([openDocumentInternal, url](const QString &token) {
516 openDocumentInternal(url, token);
517 });
518
519 return true;
520 } else {
521 return openDocumentInternal(url, QString());
522 }
523}
524
525#else
527
529{
530 return QByteArrayLiteral("UNKNOWN");
531}
532
534{
535 Q_UNUSED(url);
536 qWarning("openUrl() not supported on this platform");
537 return false;
538}
539
541{
542 Q_UNUSED(url);
543 qWarning("openDocument() not supported on this platform");
544 return false;
545}
546
548{
550 return nullptr;
551}
552
553#endif // QT_NO_MULTIPROCESS
554
556{
558 return QString();
559}
560
562{
563 switch (capability) {
565 return m_hasScreenshotPortalWithColorPicking;
566 }
567 return false;
568}
569
571{
572#if QT_CONFIG(dbus)
573 if (qGuiApp->desktopFileName().isEmpty()) {
574 qWarning("QGuiApplication::desktopFileName() is empty");
575 return;
576 }
577
578
579 const QString launcherUrl = QStringLiteral("application://") + qGuiApp->desktopFileName() + QStringLiteral(".desktop");
580 const qint64 count = qBound(0, number, 9999);
581 QVariantMap dbusUnityProperties;
582
583 if (count > 0) {
584 dbusUnityProperties[QStringLiteral("count")] = count;
585 dbusUnityProperties[QStringLiteral("count-visible")] = true;
586 } else {
587 dbusUnityProperties[QStringLiteral("count-visible")] = false;
588 }
589
590 auto signal = QDBusMessage::createSignal(QStringLiteral("/com/canonical/unity/launcherentry/")
591 + qGuiApp->applicationName(), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"));
592
593 signal.setArguments({launcherUrl, dbusUnityProperties});
594
596#else
598#endif
599}
600
602
603#include "qgenericunixservices.moc"
\inmodule QtCore
Definition qbytearray.h:57
QByteArray toUpper() const &
Definition qbytearray.h:194
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
qsizetype lastIndexOf(char c, qsizetype from=-1) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
\inmodule QtDBus
void beginStructure()
Opens a new D-Bus structure suitable for appending new arguments.
void endStructure()
Closes a D-Bus structure opened with beginStructure().
bool send(const QDBusMessage &message) const
Sends the message over this connection, without waiting for a reply.
QDBusMessage call(const QDBusMessage &message, QDBus::CallMode mode=QDBus::Block, int timeout=-1) const
Sends the message over this connection and blocks, waiting for a reply, for at most timeout milliseco...
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
Connects the signal specified by the service, path, interface and name parameters to the slot slot in...
static QDBusConnection sessionBus()
Returns a QDBusConnection object opened with the session bus.
QDBusPendingCall asyncCall(const QDBusMessage &message, int timeout=-1) const
\inmodule QtDBus
Definition qdbuserror.h:21
\inmodule QtDBus
static QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
Constructs a new DBus message with the given path, interface and name, representing a signal emission...
static QDBusMessage createError(const QString &name, const QString &msg)
Constructs a new DBus message representing an error, with the given name and msg.
static QDBusMessage createMethodCall(const QString &destination, const QString &path, const QString &interface, const QString &method)
Constructs a new DBus message representing a method call.
void finished(QDBusPendingCallWatcher *self=nullptr)
This signal is emitted when the pending call has finished and its reply is available.
\inmodule QtDBus
\inmodule QtDBus
void giveFileDescriptor(int fileDescriptor)
bool exists() const
Returns true if the file exists; otherwise returns false.
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
bool openDocument(const QUrl &url) override
bool hasCapability(Capability capability) const override
virtual QString portalWindowIdentifier(QWindow *window)
void setApplicationBadge(qint64 number)
QPlatformServiceColorPicker * colorPicker(QWindow *parent=nullptr) override
bool openUrl(const QUrl &url) override
QByteArray desktopEnvironment() const override
QPlatformServices::desktopEnvironment returns the active desktop environment.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
QString platformName
The name of the underlying platform plugin.
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
value_type takeFirst()
Definition qlist.h:549
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
virtual void pickColor()=0
Capability
Capabilities are used to determine a specific platform service's availability.
\inmodule QtCore
Definition qsettings.h:30
static QString findExecutable(const QString &executableName, const QStringList &paths=QStringList())
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString & append(QChar c)
Definition qstring.cpp:3227
QByteArray toUtf8() const &
Definition qstring.h:563
\inmodule QtCore
Definition qurlquery.h:20
\inmodule QtCore
Definition qurl.h:94
QByteArray toEncoded(FormattingOptions options=FullyEncoded) const
Returns the encoded representation of the URL if it's valid; otherwise an empty QByteArray is returne...
Definition qurl.cpp:2964
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
\inmodule QtGui
Definition qwindow.h:63
QMap< QString, QString > map
[6]
auto signal
Token token
Definition keywords.cpp:444
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
@ SingleShotConnection
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
QMap< QString, QVariant > QVariantMap
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
static int qt_safe_close(int fd)
DBusConnection const char DBusError * error
static bool checkNeedPortalSupport()
#define qGuiApp
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
#define SLOT(a)
Definition qobjectdefs.h:51
GLboolean GLboolean GLboolean b
GLboolean r
[2]
GLenum GLenum GLsizei count
GLsizei const GLenum * attachments
GLuint program
GLuint GLsizei const GLchar * message
GLboolean GLboolean g
GLuint64 GLenum GLint fd
GLuint64EXT * result
[6]
#define O_PATH
static QString checkExecutable(const QString &path)
#define qPrintable(string)
Definition qstring.h:1391
#define QStringLiteral(str)
bool qputenv(const char *varName, QByteArrayView raw)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
Q_CORE_EXPORT bool qunsetenv(const char *varName)
#define Q_OBJECT
#define Q_EMIT
#define Q_SLOTS
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
QFutureWatcher< int > watcher
QUrl url("example.com")
[constructor-url-reference]
QDataStream & operator>>(QDataStream &in, MyClass &myObj)
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkReply * reply
QDBusArgument argument
QJSValueList args
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent