Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qdesktopservices.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
// Qt-Security score:significant reason:default
4
5
#
include
"qdesktopservices.h"
6
7
#
ifndef
QT_NO_DESKTOPSERVICES
8
9
#
include
<
qdebug
.
h
>
10
11
#
include
<
qstandardpaths
.
h
>
12
#
include
<
qhash
.
h
>
13
#
include
<
qobject
.
h
>
14
#
include
<
qcoreapplication
.
h
>
15
#
include
<
private
/
qguiapplication_p
.
h
>
16
#
include
<
qurl
.
h
>
17
#
include
<
qmutex
.
h
>
18
#
include
<
qpa
/
qplatformservices
.
h
>
19
#
include
<
qpa
/
qplatformintegration
.
h
>
20
#
include
<
qdir
.
h
>
21
22
QT_BEGIN_NAMESPACE
23
24
class
QOpenUrlHandlerRegistry
25
{
26
public
:
27
QOpenUrlHandlerRegistry
() =
default
;
28
29
QRecursiveMutex
mutex
;
30
31
struct
Handler
32
{
33
QObject *
receiver
;
34
QByteArray
name
;
35
};
36
typedef
QHash
<
QString
,
Handler
>
HandlerHash
;
37
HandlerHash
handlers
;
38
};
39
40
Q_GLOBAL_STATIC(
QOpenUrlHandlerRegistry
, handlerRegistry)
41
42
/*!
43
\class QDesktopServices
44
\brief The QDesktopServices class provides methods for accessing common desktop services.
45
\since 4.2
46
\ingroup desktop
47
\inmodule QtGui
48
49
Many desktop environments provide services that can be used by applications to
50
perform common tasks, such as opening a web page, in a way that is both consistent
51
and takes into account the user's application preferences.
52
53
This class contains functions that provide simple interfaces to these services
54
that indicate whether they succeeded or failed.
55
56
The openUrl() function is used to open files located at arbitrary URLs in external
57
applications. For URLs that correspond to resources on the local filing system
58
(where the URL scheme is "file"), a suitable application will be used to open the
59
file; otherwise, a web browser will be used to fetch and display the file.
60
61
The user's desktop settings control whether certain executable file types are
62
opened for browsing, or if they are executed instead. Some desktop environments
63
are configured to prevent users from executing files obtained from non-local URLs,
64
or to ask the user's permission before doing so.
65
66
\section1 URL Handlers
67
68
The behavior of the openUrl() function can be customized for individual URL
69
schemes to allow applications to override the default handling behavior for
70
certain types of URLs.
71
72
The dispatch mechanism allows only one custom handler to be used for each URL
73
scheme; this is set using the setUrlHandler() function. Each handler is
74
implemented as a slot which accepts only a single QUrl argument.
75
76
The existing handlers for each scheme can be removed with the
77
unsetUrlHandler() function. This returns the handling behavior for the given
78
scheme to the default behavior.
79
80
This system makes it easy to implement a help system, for example. Help could be
81
provided in labels and text browsers using \uicontrol{help://myapplication/mytopic}
82
URLs, and by registering a handler it becomes possible to display the help text
83
inside the application:
84
85
\snippet code/src_gui_util_qdesktopservices.cpp 0
86
\snippet code/src_gui_util_qdesktopservices.cpp setUrlHandler
87
88
If inside the handler you decide that you can't open the requested
89
URL, you can just call QDesktopServices::openUrl() again with the
90
same argument, and it will try to open the URL using the
91
appropriate mechanism for the user's desktop environment.
92
93
Combined with platform specific settings, the schemes registered by the
94
openUrl() function can also be exposed to other applications, opening up
95
for application deep linking or a very basic URL-based IPC mechanism.
96
97
\sa QSystemTrayIcon, QProcess, QStandardPaths
98
*/
99
100
/*!
101
Opens the given \a url in the appropriate Web browser for the user's desktop
102
environment, and returns \c true if successful; otherwise returns \c false.
103
104
If the URL is a reference to a local file (i.e., the URL scheme is "file") then
105
it will be opened with a suitable application instead of a Web browser.
106
107
The following example opens a file on the Windows file system residing on a path
108
that contains spaces:
109
110
\snippet code/src_gui_util_qdesktopservices.cpp 2
111
112
If a \c mailto URL is specified, the user's e-mail client will be used to open a
113
composer window containing the options specified in the URL, similar to the way
114
\c mailto links are handled by a Web browser.
115
116
For example, the following URL contains a recipient (\c{user@foo.com}), a
117
subject (\c{Test}), and a message body (\c{Just a test}):
118
119
\snippet code/src_gui_util_qdesktopservices.cpp 1
120
121
\warning Although many e-mail clients can send attachments and are
122
Unicode-aware, the user may have configured their client without these features.
123
Also, certain e-mail clients (e.g., Lotus Notes) have problems with long URLs.
124
125
\warning A return value of \c true indicates that the application has successfully requested
126
the operating system to open the URL in an external application. The external application may
127
still fail to launch or fail to open the requested URL. This result will not be reported back
128
to the application.
129
130
\warning URLs passed to this function on iOS will not load unless their schemes are
131
listed in the \c LSApplicationQueriesSchemes key of the application's Info.plist file.
132
For more information, see the Apple Developer Documentation for
133
\l {iOS: canOpenURL:}{canOpenURL:}.
134
For example, the following lines enable URLs with the HTTPS scheme:
135
136
\snippet code/src_gui_util_qdesktopservices.cpp 3
137
138
\note For Android Nougat (SDK 24) and above, URLs with a \c file scheme
139
are opened using \l {Android: FileProvider}{FileProvider} which tries to
140
obtain a shareable \c content scheme URI first. For that reason, Qt for
141
Android defines a file provider with the authority
142
\c ${applicationId}.qtprovider, with \c applicationId being the app's
143
package name to avoid name conflicts. If the application declares a file
144
provider of its own, Qt uses that one in preference, which lets the
145
application decide which directories may be shared. For more information,
146
also see \l {Android: Setting up file sharing}{Setting up file sharing}.
147
148
\sa setUrlHandler()
149
*/
150
bool
QDesktopServices::openUrl(
const
QUrl &url)
151
{
152
QOpenUrlHandlerRegistry *registry = handlerRegistry();
153
QMutexLocker locker(®istry->mutex);
154
static
bool
insideOpenUrlHandler =
false
;
155
156
if
(!insideOpenUrlHandler) {
157
QOpenUrlHandlerRegistry::HandlerHash::ConstIterator handler = registry->handlers.constFind(url.scheme());
158
if
(handler != registry->handlers.constEnd()) {
159
insideOpenUrlHandler =
true
;
160
bool
result = QMetaObject::invokeMethod(handler->receiver, handler->name.constData(), Qt::DirectConnection, Q_ARG(QUrl, url));
161
insideOpenUrlHandler =
false
;
162
return
result;
// ### support bool slot return type
163
}
164
}
165
if
(!url.isValid())
166
return
false
;
167
168
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
169
if
(Q_UNLIKELY(!platformIntegration)) {
170
QCoreApplication *application = QCoreApplication::instance();
171
if
(Q_UNLIKELY(!application))
172
qWarning(
"QDesktopServices::openUrl: Please instantiate the QGuiApplication object "
173
"first"
);
174
else
if
(Q_UNLIKELY(!qobject_cast<QGuiApplication *>(application)))
175
qWarning(
"QDesktopServices::openUrl: Application is not a GUI application"
);
176
return
false
;
177
}
178
179
QPlatformServices *platformServices = platformIntegration->services();
180
if
(!platformServices) {
181
qWarning(
"The platform plugin does not support services."
);
182
return
false
;
183
}
184
// We only use openDocument if there is no fragment or query for the URL to
185
// avoid it being lost when using openDocument
186
if
(url.isLocalFile() && !url.hasFragment() && !url.hasQuery())
187
return
platformServices->openDocument(url);
188
return
platformServices->openUrl(url);
189
}
190
191
/*!
192
Sets the handler for the given \a scheme to be the handler \a method provided by
193
the \a receiver object.
194
195
This function provides a way to customize the behavior of openUrl(). If openUrl()
196
is called with a URL with the specified \a scheme then the given \a method on the
197
\a receiver object is called instead of QDesktopServices launching an external
198
application.
199
200
The provided method must be implemented as a slot that only accepts a single QUrl
201
argument.
202
203
\snippet code/src_gui_util_qdesktopservices.cpp 0
204
205
If setUrlHandler() is used to set a new handler for a scheme which already
206
has a handler, the existing handler is simply replaced with the new one.
207
Since QDesktopServices does not take ownership of handlers, no objects are
208
deleted when a handler is replaced.
209
210
Note that the handler will always be called from within the same thread that
211
calls QDesktopServices::openUrl().
212
213
You must call unsetUrlHandler() before destroying the handler object, so
214
the destruction of the handler object does not overlap with concurrent
215
invocations of openUrl() using it.
216
217
\target configuring qdesktopservices url handler on ios and macos
218
\section1 iOS and \macos
219
220
To use this function for receiving data from other apps on iOS/\macos
221
you also need to add the custom scheme to the \c CFBundleURLSchemes
222
list in your Info.plist file:
223
224
\snippet code/src_gui_util_qdesktopservices.cpp 4
225
226
For more information, see the Apple Developer Documentation for
227
\l {iOS: Defining a Custom URL Scheme for Your App}{Defining a Custom URL Scheme for Your App}.
228
\warning It is not possible to claim support for some well known URL schemes, including http and
229
https. This is only allowed for Universal Links.
230
231
To claim support for http and https the above entry in the Info.plist file
232
is not allowed. This is only possible when you add your domain to the
233
Entitlements file:
234
235
\snippet code/src_gui_util_qdesktopservices.cpp 7
236
237
iOS/\macos will search for /.well-known/apple-app-site-association on your domain,
238
when the application is installed. If you want to listen to
239
\c{https://your.domain.com/help?topic=ABCDEF} you need to provide the following
240
content there:
241
242
\snippet code/src_gui_util_qdesktopservices.cpp 8
243
244
For more information, see the Apple Developer Documentation for
245
\l {iOS: Supporting Associated Domains}{Supporting Associated Domains}.
246
247
\target configuring qdesktopservices url handler on android
248
\section1 Android
249
250
To use this function for receiving data from other apps on Android, you
251
need to add one or more intent filter to the \c activity in your app manifest:
252
253
\snippet code/src_gui_util_qdesktopservices.cpp 9
254
255
For more information, see the Android Developer Documentation for
256
\l {Android: Create Deep Links to App Content}{Create Deep Links to App Content}.
257
258
To immediately open the corresponding content in your Android app, without
259
requiring the user to select the app, you need to verify your link. To
260
enable the verification, add an additional parameter to your intent filter:
261
262
\snippet code/src_gui_util_qdesktopservices.cpp 10
263
264
Android will look for \c{https://your.domain.com/.well-known/assetlinks.json},
265
when the application is installed. If you want to listen to
266
\c{https://your.domain.com:1337/help}, you need to provide the following
267
content there:
268
269
\snippet code/src_gui_util_qdesktopservices.cpp 11
270
271
For more information, see the Android Developer Documentation for
272
\l {Android: Verify Android App Links}{Verify Android App Links}.
273
274
\sa openUrl(), unsetUrlHandler()
275
*/
276
void
QDesktopServices::setUrlHandler(
const
QString &scheme, QObject *receiver,
const
char
*method)
277
{
278
QOpenUrlHandlerRegistry *registry = handlerRegistry();
279
QMutexLocker locker(®istry->mutex);
280
if
(!receiver) {
281
registry->handlers.remove(scheme.toLower());
282
return
;
283
}
284
QOpenUrlHandlerRegistry::Handler h;
285
h.receiver = receiver;
286
h.name = method;
287
registry->handlers.insert(scheme.toLower(), h);
288
}
289
290
/*!
291
Removes a previously set URL handler for the specified \a scheme.
292
293
Call this function before the handler object that was registered for \a scheme
294
is destroyed, to prevent concurrent openUrl() calls from continuing to call
295
the destroyed handler object.
296
297
\sa setUrlHandler()
298
*/
299
void
QDesktopServices::unsetUrlHandler(
const
QString &scheme)
300
{
301
setUrlHandler(scheme,
nullptr
,
nullptr
);
302
}
303
304
QT_END_NAMESPACE
305
306
#
endif
// QT_NO_DESKTOPSERVICES
QOpenUrlHandlerRegistry
Definition
qdesktopservices.cpp:25
QOpenUrlHandlerRegistry::mutex
QRecursiveMutex mutex
Definition
qdesktopservices.cpp:29
QOpenUrlHandlerRegistry::HandlerHash
QHash< QString, Handler > HandlerHash
Definition
qdesktopservices.cpp:36
QOpenUrlHandlerRegistry::handlers
HandlerHash handlers
Definition
qdesktopservices.cpp:37
QOpenUrlHandlerRegistry::QOpenUrlHandlerRegistry
QOpenUrlHandlerRegistry()=default
QRecursiveMutex
\inmodule QtCore
Definition
qmutex.h:343
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QOpenUrlHandlerRegistry::Handler
Definition
qdesktopservices.cpp:32
QOpenUrlHandlerRegistry::Handler::receiver
QObject * receiver
Definition
qdesktopservices.cpp:33
QOpenUrlHandlerRegistry::Handler::name
QByteArray name
Definition
qdesktopservices.cpp:34
qtbase
src
gui
util
qdesktopservices.cpp
Generated on
for Qt by
1.18.0