Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/gui/util/qdesktopservices.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||
2 | ** | - | ||||||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||
5 | ** | - | ||||||
6 | ** This file is part of the QtGui module of the Qt Toolkit. | - | ||||||
7 | ** | - | ||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||
9 | ** Commercial License Usage | - | ||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||
16 | ** | - | ||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||
24 | ** | - | ||||||
25 | ** GNU General Public License Usage | - | ||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||
35 | ** | - | ||||||
36 | ** $QT_END_LICENSE$ | - | ||||||
37 | ** | - | ||||||
38 | ****************************************************************************/ | - | ||||||
39 | - | |||||||
40 | #include "qdesktopservices.h" | - | ||||||
41 | - | |||||||
42 | #ifndef QT_NO_DESKTOPSERVICES | - | ||||||
43 | - | |||||||
44 | #include <qdebug.h> | - | ||||||
45 | - | |||||||
46 | #include <qstandardpaths.h> | - | ||||||
47 | #include <qhash.h> | - | ||||||
48 | #include <qobject.h> | - | ||||||
49 | #include <qcoreapplication.h> | - | ||||||
50 | #include <private/qguiapplication_p.h> | - | ||||||
51 | #include <qurl.h> | - | ||||||
52 | #include <qmutex.h> | - | ||||||
53 | #include <qpa/qplatformservices.h> | - | ||||||
54 | #include <qpa/qplatformintegration.h> | - | ||||||
55 | #include <qdir.h> | - | ||||||
56 | - | |||||||
57 | QT_BEGIN_NAMESPACE | - | ||||||
58 | - | |||||||
59 | class QOpenUrlHandlerRegistry : public QObject | - | ||||||
60 | { | - | ||||||
61 | Q_OBJECT | - | ||||||
62 | public: | - | ||||||
63 | inline QOpenUrlHandlerRegistry() : mutex(QMutex::Recursive) {} never executed: end of block | 0 | ||||||
64 | - | |||||||
65 | QMutex mutex; | - | ||||||
66 | - | |||||||
67 | struct Handler | - | ||||||
68 | { | - | ||||||
69 | QObject *receiver; | - | ||||||
70 | QByteArray name; | - | ||||||
71 | }; | - | ||||||
72 | typedef QHash<QString, Handler> HandlerHash; | - | ||||||
73 | HandlerHash handlers; | - | ||||||
74 | - | |||||||
75 | public Q_SLOTS: | - | ||||||
76 | void handlerDestroyed(QObject *handler); | - | ||||||
77 | - | |||||||
78 | }; | - | ||||||
79 | - | |||||||
80 | Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry) never executed: end of block never executed: guard.store(QtGlobalStatic::Destroyed); never executed: return &holder.value;
| 0 | ||||||
81 | - | |||||||
82 | void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) | - | ||||||
83 | { | - | ||||||
84 | HandlerHash::Iterator it = handlers.begin(); | - | ||||||
85 | while (it != handlers.end()) {
| 0 | ||||||
86 | if (it->receiver == handler) {
| 0 | ||||||
87 | it = handlers.erase(it); | - | ||||||
88 | } else { never executed: end of block | 0 | ||||||
89 | ++it; | - | ||||||
90 | } never executed: end of block | 0 | ||||||
91 | } | - | ||||||
92 | } never executed: end of block | 0 | ||||||
93 | - | |||||||
94 | /*! | - | ||||||
95 | \class QDesktopServices | - | ||||||
96 | \brief The QDesktopServices class provides methods for accessing common desktop services. | - | ||||||
97 | \since 4.2 | - | ||||||
98 | \ingroup desktop | - | ||||||
99 | \inmodule QtGui | - | ||||||
100 | - | |||||||
101 | Many desktop environments provide services that can be used by applications to | - | ||||||
102 | perform common tasks, such as opening a web page, in a way that is both consistent | - | ||||||
103 | and takes into account the user's application preferences. | - | ||||||
104 | - | |||||||
105 | This class contains functions that provide simple interfaces to these services | - | ||||||
106 | that indicate whether they succeeded or failed. | - | ||||||
107 | - | |||||||
108 | The openUrl() function is used to open files located at arbitrary URLs in external | - | ||||||
109 | applications. For URLs that correspond to resources on the local filing system | - | ||||||
110 | (where the URL scheme is "file"), a suitable application will be used to open the | - | ||||||
111 | file; otherwise, a web browser will be used to fetch and display the file. | - | ||||||
112 | - | |||||||
113 | The user's desktop settings control whether certain executable file types are | - | ||||||
114 | opened for browsing, or if they are executed instead. Some desktop environments | - | ||||||
115 | are configured to prevent users from executing files obtained from non-local URLs, | - | ||||||
116 | or to ask the user's permission before doing so. | - | ||||||
117 | - | |||||||
118 | \section1 URL Handlers | - | ||||||
119 | - | |||||||
120 | The behavior of the openUrl() function can be customized for individual URL | - | ||||||
121 | schemes to allow applications to override the default handling behavior for | - | ||||||
122 | certain types of URLs. | - | ||||||
123 | - | |||||||
124 | The dispatch mechanism allows only one custom handler to be used for each URL | - | ||||||
125 | scheme; this is set using the setUrlHandler() function. Each handler is | - | ||||||
126 | implemented as a slot which accepts only a single QUrl argument. | - | ||||||
127 | - | |||||||
128 | The existing handlers for each scheme can be removed with the | - | ||||||
129 | unsetUrlHandler() function. This returns the handling behavior for the given | - | ||||||
130 | scheme to the default behavior. | - | ||||||
131 | - | |||||||
132 | This system makes it easy to implement a help system, for example. Help could be | - | ||||||
133 | provided in labels and text browsers using \uicontrol{help://myapplication/mytopic} | - | ||||||
134 | URLs, and by registering a handler it becomes possible to display the help text | - | ||||||
135 | inside the application: | - | ||||||
136 | - | |||||||
137 | \snippet code/src_gui_util_qdesktopservices.cpp 0 | - | ||||||
138 | - | |||||||
139 | If inside the handler you decide that you can't open the requested | - | ||||||
140 | URL, you can just call QDesktopServices::openUrl() again with the | - | ||||||
141 | same argument, and it will try to open the URL using the | - | ||||||
142 | appropriate mechanism for the user's desktop environment. | - | ||||||
143 | - | |||||||
144 | \note Since Qt 5, storageLocation() and displayName() are replaced by functionality | - | ||||||
145 | provided by the QStandardPaths class. | - | ||||||
146 | - | |||||||
147 | \sa QSystemTrayIcon, QProcess, QStandardPaths | - | ||||||
148 | */ | - | ||||||
149 | - | |||||||
150 | /*! | - | ||||||
151 | Opens the given \a url in the appropriate Web browser for the user's desktop | - | ||||||
152 | environment, and returns \c true if successful; otherwise returns \c false. | - | ||||||
153 | - | |||||||
154 | If the URL is a reference to a local file (i.e., the URL scheme is "file") then | - | ||||||
155 | it will be opened with a suitable application instead of a Web browser. | - | ||||||
156 | - | |||||||
157 | The following example opens a file on the Windows file system residing on a path | - | ||||||
158 | that contains spaces: | - | ||||||
159 | - | |||||||
160 | \snippet code/src_gui_util_qdesktopservices.cpp 2 | - | ||||||
161 | - | |||||||
162 | If a \c mailto URL is specified, the user's e-mail client will be used to open a | - | ||||||
163 | composer window containing the options specified in the URL, similar to the way | - | ||||||
164 | \c mailto links are handled by a Web browser. | - | ||||||
165 | - | |||||||
166 | For example, the following URL contains a recipient (\c{user@foo.com}), a | - | ||||||
167 | subject (\c{Test}), and a message body (\c{Just a test}): | - | ||||||
168 | - | |||||||
169 | \snippet code/src_gui_util_qdesktopservices.cpp 1 | - | ||||||
170 | - | |||||||
171 | \warning Although many e-mail clients can send attachments and are | - | ||||||
172 | Unicode-aware, the user may have configured their client without these features. | - | ||||||
173 | Also, certain e-mail clients (e.g., Lotus Notes) have problems with long URLs. | - | ||||||
174 | - | |||||||
175 | \warning A return value of \c true indicates that the application has successfully requested | - | ||||||
176 | the operating system to open the URL in an external application. The external application may | - | ||||||
177 | still fail to launch or fail to open the requested URL. This result will not be reported back | - | ||||||
178 | to the application. | - | ||||||
179 | - | |||||||
180 | \sa setUrlHandler() | - | ||||||
181 | */ | - | ||||||
182 | bool QDesktopServices::openUrl(const QUrl &url) | - | ||||||
183 | { | - | ||||||
184 | QOpenUrlHandlerRegistry *registry = handlerRegistry(); | - | ||||||
185 | QMutexLocker locker(®istry->mutex); | - | ||||||
186 | static bool insideOpenUrlHandler = false; | - | ||||||
187 | - | |||||||
188 | if (!insideOpenUrlHandler) {
| 0 | ||||||
189 | QOpenUrlHandlerRegistry::HandlerHash::ConstIterator handler = registry->handlers.constFind(url.scheme()); | - | ||||||
190 | if (handler != registry->handlers.constEnd()) {
| 0 | ||||||
191 | insideOpenUrlHandler = true; | - | ||||||
192 | bool result = QMetaObject::invokeMethod(handler->receiver, handler->name.constData(), Qt::DirectConnection, Q_ARG(QUrl, url)); | - | ||||||
193 | insideOpenUrlHandler = false; | - | ||||||
194 | return result; // ### support bool slot return type never executed: return result; | 0 | ||||||
195 | } | - | ||||||
196 | } never executed: end of block | 0 | ||||||
197 | if (!url.isValid())
| 0 | ||||||
198 | return false; never executed: return false; | 0 | ||||||
199 | - | |||||||
200 | QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration(); | - | ||||||
201 | if (!platformIntegration)
| 0 | ||||||
202 | return false; never executed: return false; | 0 | ||||||
203 | - | |||||||
204 | QPlatformServices *platformServices = platformIntegration->services(); | - | ||||||
205 | if (!platformServices) {
| 0 | ||||||
206 | qWarning("The platform plugin does not support services."); | - | ||||||
207 | return false; never executed: return false; | 0 | ||||||
208 | } | - | ||||||
209 | return url.scheme() == QLatin1String("file") ? never executed: return url.scheme() == QLatin1String("file") ? platformServices->openDocument(url) : platformServices->openUrl(url); | 0 | ||||||
210 | platformServices->openDocument(url) : platformServices->openUrl(url); never executed: return url.scheme() == QLatin1String("file") ? platformServices->openDocument(url) : platformServices->openUrl(url); | 0 | ||||||
211 | } | - | ||||||
212 | - | |||||||
213 | /*! | - | ||||||
214 | Sets the handler for the given \a scheme to be the handler \a method provided by | - | ||||||
215 | the \a receiver object. | - | ||||||
216 | - | |||||||
217 | This function provides a way to customize the behavior of openUrl(). If openUrl() | - | ||||||
218 | is called with a URL with the specified \a scheme then the given \a method on the | - | ||||||
219 | \a receiver object is called instead of QDesktopServices launching an external | - | ||||||
220 | application. | - | ||||||
221 | - | |||||||
222 | The provided method must be implemented as a slot that only accepts a single QUrl | - | ||||||
223 | argument. | - | ||||||
224 | - | |||||||
225 | If setUrlHandler() is used to set a new handler for a scheme which already | - | ||||||
226 | has a handler, the existing handler is simply replaced with the new one. | - | ||||||
227 | Since QDesktopServices does not take ownership of handlers, no objects are | - | ||||||
228 | deleted when a handler is replaced. | - | ||||||
229 | - | |||||||
230 | Note that the handler will always be called from within the same thread that | - | ||||||
231 | calls QDesktopServices::openUrl(). | - | ||||||
232 | - | |||||||
233 | \sa openUrl(), unsetUrlHandler() | - | ||||||
234 | */ | - | ||||||
235 | void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, const char *method) | - | ||||||
236 | { | - | ||||||
237 | QOpenUrlHandlerRegistry *registry = handlerRegistry(); | - | ||||||
238 | QMutexLocker locker(®istry->mutex); | - | ||||||
239 | if (!receiver) {
| 0 | ||||||
240 | registry->handlers.remove(scheme.toLower()); | - | ||||||
241 | return; never executed: return; | 0 | ||||||
242 | } | - | ||||||
243 | QOpenUrlHandlerRegistry::Handler h; | - | ||||||
244 | h.receiver = receiver; | - | ||||||
245 | h.name = method; | - | ||||||
246 | registry->handlers.insert(scheme.toLower(), h); | - | ||||||
247 | QObject::connect(receiver, SIGNAL(destroyed(QObject*)), | - | ||||||
248 | registry, SLOT(handlerDestroyed(QObject*))); | - | ||||||
249 | } never executed: end of block | 0 | ||||||
250 | - | |||||||
251 | /*! | - | ||||||
252 | Removes a previously set URL handler for the specified \a scheme. | - | ||||||
253 | - | |||||||
254 | \sa setUrlHandler() | - | ||||||
255 | */ | - | ||||||
256 | void QDesktopServices::unsetUrlHandler(const QString &scheme) | - | ||||||
257 | { | - | ||||||
258 | setUrlHandler(scheme, 0, 0); | - | ||||||
259 | } never executed: end of block | 0 | ||||||
260 | - | |||||||
261 | /*! | - | ||||||
262 | \enum QDesktopServices::StandardLocation | - | ||||||
263 | \since 4.4 | - | ||||||
264 | \obsolete | - | ||||||
265 | Use QStandardPaths::StandardLocation (see storageLocation() for porting notes) | - | ||||||
266 | - | |||||||
267 | This enum describes the different locations that can be queried by | - | ||||||
268 | QDesktopServices::storageLocation and QDesktopServices::displayName. | - | ||||||
269 | - | |||||||
270 | \value DesktopLocation Returns the user's desktop directory. | - | ||||||
271 | \value DocumentsLocation Returns the user's document. | - | ||||||
272 | \value FontsLocation Returns the user's fonts. | - | ||||||
273 | \value ApplicationsLocation Returns the user's applications. | - | ||||||
274 | \value MusicLocation Returns the users music. | - | ||||||
275 | \value MoviesLocation Returns the user's movies. | - | ||||||
276 | \value PicturesLocation Returns the user's pictures. | - | ||||||
277 | \value TempLocation Returns the system's temporary directory. | - | ||||||
278 | \value HomeLocation Returns the user's home directory. | - | ||||||
279 | \value DataLocation Returns a directory location where persistent | - | ||||||
280 | application data can be stored. QCoreApplication::applicationName | - | ||||||
281 | and QCoreApplication::organizationName should work on all | - | ||||||
282 | platforms. | - | ||||||
283 | \value CacheLocation Returns a directory location where user-specific | - | ||||||
284 | non-essential (cached) data should be written. | - | ||||||
285 | - | |||||||
286 | \sa storageLocation(), displayName() | - | ||||||
287 | */ | - | ||||||
288 | - | |||||||
289 | /*! | - | ||||||
290 | \fn QString QDesktopServices::storageLocation(StandardLocation type) | - | ||||||
291 | \obsolete | - | ||||||
292 | Use QStandardPaths::writableLocation() | - | ||||||
293 | - | |||||||
294 | \note when porting QDesktopServices::DataLocation to QStandardPaths::DataLocation, | - | ||||||
295 | a different path will be returned. | - | ||||||
296 | - | |||||||
297 | \c{QDesktopServices::DataLocation} was \c{GenericDataLocation + "/data/organization/application"}, | - | ||||||
298 | while QStandardPaths::DataLocation is \c{GenericDataLocation + "/organization/application"}. | - | ||||||
299 | - | |||||||
300 | Also note that \c{application} could be empty in Qt 4, if QCoreApplication::setApplicationName() | - | ||||||
301 | wasn't called, while in Qt 5 it defaults to the name of the executable. | - | ||||||
302 | - | |||||||
303 | Therefore, if you still need to access the Qt 4 path (for example for data migration to Qt 5), replace | - | ||||||
304 | \code | - | ||||||
305 | QDesktopServices::storageLocation(QDesktopServices::DataLocation) | - | ||||||
306 | \endcode | - | ||||||
307 | with | - | ||||||
308 | \code | - | ||||||
309 | QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + | - | ||||||
310 | "/data/organization/application" | - | ||||||
311 | \endcode | - | ||||||
312 | (assuming an organization name and an application name were set). | - | ||||||
313 | */ | - | ||||||
314 | - | |||||||
315 | /*! | - | ||||||
316 | \fn QString QDesktopServices::displayName(StandardLocation type) | - | ||||||
317 | \obsolete | - | ||||||
318 | Use QStandardPaths::displayName() | - | ||||||
319 | */ | - | ||||||
320 | - | |||||||
321 | extern Q_CORE_EXPORT QString qt_applicationName_noFallback(); | - | ||||||
322 | - | |||||||
323 | QString QDesktopServices::storageLocationImpl(QStandardPaths::StandardLocation type) | - | ||||||
324 | { | - | ||||||
325 | if (type == QStandardPaths::AppLocalDataLocation) {
| 0 | ||||||
326 | // Preserve Qt 4 compatibility: | - | ||||||
327 | // * QCoreApplication::applicationName() must default to empty | - | ||||||
328 | // * Unix data location is under the "data/" subdirectory | - | ||||||
329 | const QString compatAppName = qt_applicationName_noFallback(); | - | ||||||
330 | const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); | - | ||||||
331 | const QString organizationName = QCoreApplication::organizationName(); | - | ||||||
332 | #if defined(Q_OS_WIN) || defined(Q_OS_MAC) | - | ||||||
333 | QString result = baseDir; | - | ||||||
334 | if (!organizationName.isEmpty()) | - | ||||||
335 | result += QLatin1Char('/') + organizationName; | - | ||||||
336 | if (!compatAppName.isEmpty()) | - | ||||||
337 | result += QLatin1Char('/') + compatAppName; | - | ||||||
338 | return result; | - | ||||||
339 | #elif defined(Q_OS_UNIX) | - | ||||||
340 | return baseDir + QLatin1String("/data/") never executed: return baseDir + QLatin1String("/data/") + organizationName + QLatin1Char('/') + compatAppName; | 0 | ||||||
341 | + organizationName + QLatin1Char('/') + compatAppName; never executed: return baseDir + QLatin1String("/data/") + organizationName + QLatin1Char('/') + compatAppName; | 0 | ||||||
342 | #endif | - | ||||||
343 | } | - | ||||||
344 | return QStandardPaths::writableLocation(type); never executed: return QStandardPaths::writableLocation(type); | 0 | ||||||
345 | } | - | ||||||
346 | - | |||||||
347 | QT_END_NAMESPACE | - | ||||||
348 | - | |||||||
349 | #include "qdesktopservices.moc" | - | ||||||
350 | - | |||||||
351 | #endif // QT_NO_DESKTOPSERVICES | - | ||||||
Source code | Switch to Preprocessed file |