src/gui/util/qdesktopservices.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    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 #if defined(Q_WS_QWS)
       
    49 #include "qdesktopservices_qws.cpp"
       
    50 #elif defined(Q_WS_X11)
       
    51 #include "qdesktopservices_x11.cpp"
       
    52 #elif defined(Q_WS_WIN)
       
    53 #include "qdesktopservices_win.cpp"
       
    54 #elif defined(Q_WS_MAC)
       
    55 #include "qdesktopservices_mac.cpp"
       
    56 #elif defined(Q_OS_SYMBIAN)
       
    57 #include "qdesktopservices_s60.cpp"
       
    58 #endif
       
    59 
       
    60 #include <qhash.h>
       
    61 #include <qobject.h>
       
    62 #include <qcoreapplication.h>
       
    63 #include <qurl.h>
       
    64 #include <qmutex.h>
       
    65 
       
    66 QT_BEGIN_NAMESPACE
       
    67 
       
    68 class QOpenUrlHandlerRegistry : public QObject
       
    69 {
       
    70     Q_OBJECT
       
    71 public:
       
    72     inline QOpenUrlHandlerRegistry() : mutex(QMutex::Recursive) {}
       
    73 
       
    74     QMutex mutex;
       
    75 
       
    76     struct Handler
       
    77     {
       
    78         QObject *receiver;
       
    79         QByteArray name;
       
    80     };
       
    81     typedef QHash<QString, Handler> HandlerHash;
       
    82     HandlerHash handlers;
       
    83 
       
    84 public Q_SLOTS:
       
    85     void handlerDestroyed(QObject *handler);
       
    86 
       
    87 };
       
    88 
       
    89 Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry)
       
    90 
       
    91 void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
       
    92 {
       
    93     HandlerHash::Iterator it = handlers.begin();
       
    94     while (it != handlers.end()) {
       
    95         if (it->receiver == handler) {
       
    96             it = handlers.erase(it);
       
    97         } else {
       
    98             ++it;
       
    99         }
       
   100     }
       
   101 }
       
   102 
       
   103 /*!
       
   104     \class QDesktopServices
       
   105     \brief The QDesktopServices class provides methods for accessing common desktop services.
       
   106     \since 4.2
       
   107     \ingroup desktop
       
   108 
       
   109     Many desktop environments provide services that can be used by applications to
       
   110     perform common tasks, such as opening a web page, in a way that is both consistent
       
   111     and takes into account the user's application preferences.
       
   112 
       
   113     This class contains functions that provide simple interfaces to these services
       
   114     that indicate whether they succeeded or failed.
       
   115 
       
   116     The openUrl() function is used to open files located at arbitrary URLs in external
       
   117     applications. For URLs that correspond to resources on the local filing system
       
   118     (where the URL scheme is "file"), a suitable application will be used to open the
       
   119     file; otherwise, a web browser will be used to fetch and display the file.
       
   120 
       
   121     The user's desktop settings control whether certain executable file types are
       
   122     opened for browsing, or if they are executed instead. Some desktop environments
       
   123     are configured to prevent users from executing files obtained from non-local URLs,
       
   124     or to ask the user's permission before doing so.
       
   125 
       
   126     \section1 URL Handlers
       
   127 
       
   128     The behavior of the openUrl() function can be customized for individual URL
       
   129     schemes to allow applications to override the default handling behavior for
       
   130     certain types of URLs.
       
   131 
       
   132     The dispatch mechanism allows only one custom handler to be used for each URL
       
   133     scheme; this is set using the setUrlHandler() function. Each handler is
       
   134     implemented as a slot which accepts only a single QUrl argument.
       
   135 
       
   136     The existing handlers for each scheme can be removed with the
       
   137     unsetUrlHandler() function. This returns the handling behavior for the given
       
   138     scheme to the default behavior.
       
   139 
       
   140     This system makes it easy to implement a help system, for example. Help could be
       
   141     provided in labels and text browsers using \gui{help://myapplication/mytopic}
       
   142     URLs, and by registering a handler it becomes possible to display the help text
       
   143     inside the application:
       
   144 
       
   145     \snippet doc/src/snippets/code/src_gui_util_qdesktopservices.cpp 0
       
   146 
       
   147     If inside the handler you decide that you can't open the requested
       
   148     URL, you can just call QDesktopServices::openUrl() again with the
       
   149     same argument, and it will try to open the URL using the
       
   150     appropriate mechanism for the user's desktop environment.
       
   151 
       
   152     \sa QSystemTrayIcon, QProcess
       
   153 */
       
   154 
       
   155 /*!
       
   156     Opens the given \a url in the appropriate Web browser for the user's desktop
       
   157     environment, and returns true if successful; otherwise returns false.
       
   158 
       
   159     If the URL is a reference to a local file (i.e., the URL scheme is "file") then
       
   160     it will be opened with a suitable application instead of a Web browser.
       
   161 
       
   162     The following example opens a file on the Windows file system residing on a path
       
   163     that contains spaces:
       
   164 
       
   165     \snippet doc/src/snippets/code/src_gui_util_qdesktopservices.cpp 2
       
   166 
       
   167     If a \c mailto URL is specified, the user's e-mail client will be used to open a
       
   168     composer window containing the options specified in the URL, similar to the way
       
   169     \c mailto links are handled by a Web browser.
       
   170 
       
   171     For example, the following URL contains a recipient (\c{user@foo.com}), a
       
   172     subject (\c{Test}), and a message body (\c{Just a test}):
       
   173 
       
   174     \snippet doc/src/snippets/code/src_gui_util_qdesktopservices.cpp 1
       
   175 
       
   176     \warning Although many e-mail clients can send attachments and are
       
   177     Unicode-aware, the user may have configured their client without these features.
       
   178     Also, certain e-mail clients (e.g., Lotus Notes) have problems with long URLs.
       
   179 
       
   180     \sa setUrlHandler()
       
   181 */
       
   182 bool QDesktopServices::openUrl(const QUrl &url)
       
   183 {
       
   184     QOpenUrlHandlerRegistry *registry = handlerRegistry();
       
   185     QMutexLocker locker(&registry->mutex);
       
   186     static bool insideOpenUrlHandler = false;
       
   187 
       
   188     if (!insideOpenUrlHandler) {
       
   189         QOpenUrlHandlerRegistry::HandlerHash::ConstIterator handler = registry->handlers.constFind(url.scheme());
       
   190         if (handler != registry->handlers.constEnd()) {
       
   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
       
   195         }
       
   196     }
       
   197 
       
   198     bool result;
       
   199     if (url.scheme() == QLatin1String("file"))
       
   200         result = openDocument(url);
       
   201     else
       
   202         result = launchWebBrowser(url);
       
   203 
       
   204     return result;
       
   205 }
       
   206 
       
   207 /*!
       
   208     Sets the handler for the given \a scheme to be the handler \a method provided by
       
   209     the \a receiver object.
       
   210 
       
   211     This function provides a way to customize the behavior of openUrl(). If openUrl()
       
   212     is called with a URL with the specified \a scheme then the given \a method on the
       
   213     \a receiver object is called instead of QDesktopServices launching an external
       
   214     application.
       
   215 
       
   216     The provided method must be implemented as a slot that only accepts a single QUrl
       
   217     argument.
       
   218 
       
   219     If setUrlHandler() is used to set a new handler for a scheme which already
       
   220     has a handler, the existing handler is simply replaced with the new one.
       
   221     Since QDesktopServices does not take ownership of handlers, no objects are
       
   222     deleted when a handler is replaced.
       
   223 
       
   224     Note that the handler will always be called from within the same thread that
       
   225     calls QDesktopServices::openUrl().
       
   226 
       
   227     \sa openUrl(), unsetUrlHandler()
       
   228 */
       
   229 void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, const char *method)
       
   230 {
       
   231     QOpenUrlHandlerRegistry *registry = handlerRegistry();
       
   232     QMutexLocker locker(&registry->mutex);
       
   233     if (!receiver) {
       
   234         registry->handlers.remove(scheme);
       
   235         return;
       
   236     }
       
   237     QOpenUrlHandlerRegistry::Handler h;
       
   238     h.receiver = receiver;
       
   239     h.name = method;
       
   240     registry->handlers.insert(scheme, h);
       
   241     QObject::connect(receiver, SIGNAL(destroyed(QObject*)),
       
   242                      registry, SLOT(handlerDestroyed(QObject*)));
       
   243 }
       
   244 
       
   245 /*!
       
   246     Removes a previously set URL handler for the specified \a scheme.
       
   247 
       
   248     \sa setUrlHandler()
       
   249 */
       
   250 void QDesktopServices::unsetUrlHandler(const QString &scheme)
       
   251 {
       
   252     setUrlHandler(scheme, 0, 0);
       
   253 }
       
   254 
       
   255 /*!
       
   256     \enum QDesktopServices::StandardLocation
       
   257     \since 4.4
       
   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     \since 4.4
       
   284 
       
   285     Returns the default system directory where files of \a type belong, or an empty string
       
   286     if the location cannot be determined.
       
   287 
       
   288     \note The storage location returned can be a directory that does not exist; i.e., it
       
   289     may need to be created by the system or the user.
       
   290 
       
   291     \note On Symbian OS, ApplicationsLocation always point /sys/bin folder on the same drive
       
   292     with executable. FontsLocation always points to folder on ROM drive. Symbian OS does not
       
   293     have desktop concept, DesktopLocation returns same path as DocumentsLocation.
       
   294     Rest of the standard locations point to folder on same drive with executable, except
       
   295     that if executable is in ROM the folder from C drive is returned.
       
   296 
       
   297     \note On Mac OS X, DataLocation does not include QCoreApplication::organizationName.
       
   298     Use code like this to add it:
       
   299 
       
   300     \code
       
   301     QString location = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
       
   302     #ifdef Q_WS_MAC
       
   303         location.insert(location.count() - QCoreApplication::applicationName().count(),
       
   304             QCoreApplication::organizationName() + "/");
       
   305     #endif
       
   306     \endcode
       
   307 */
       
   308 
       
   309 /*!
       
   310     \fn QString QDesktopServices::displayName(StandardLocation type)
       
   311 
       
   312     Returns a localized display name for the given location \a type or
       
   313     an empty QString if no relevant location can be found.
       
   314 */
       
   315 
       
   316 QT_END_NAMESPACE
       
   317 
       
   318 #include "qdesktopservices.moc"
       
   319 
       
   320 #endif // QT_NO_DESKTOPSERVICES