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