diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 7b01ba14cd..9c5f3b10da 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -55,7 +55,8 @@ HEADERS += \ kernel/qtouchdevice.h \ kernel/qtouchdevice_p.h \ kernel/qplatformsharedgraphicscache_qpa.h \ - kernel/qplatformdialoghelper_qpa.h + kernel/qplatformdialoghelper_qpa.h \ + kernel/qplatformservices_qpa.h SOURCES += \ kernel/qclipboard_qpa.cpp \ @@ -97,7 +98,8 @@ SOURCES += \ kernel/qstylehints.cpp \ kernel/qtouchdevice.cpp \ kernel/qplatformsharedgraphicscache_qpa.cpp \ - kernel/qplatformdialoghelper_qpa.cpp + kernel/qplatformdialoghelper_qpa.cpp \ + kernel/qplatformservices_qpa.cpp contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, egl) { HEADERS += \ diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp index e867e4e588..1336a1a9a2 100644 --- a/src/gui/kernel/qplatformintegration_qpa.cpp +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -107,6 +107,11 @@ QPlatformNativeInterface * QPlatformIntegration::nativeInterface() const return 0; } +QPlatformServices *QPlatformIntegration::services() const +{ + return 0; +} + /*! \class QPlatformIntegration \since 4.8 diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h index efaf495b81..bd9ecd54dc 100644 --- a/src/gui/kernel/qplatformintegration_qpa.h +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -66,6 +66,7 @@ class QPlatformAccessibility; class QPlatformTheme; class QPlatformDialogHelper; class QPlatformSharedGraphicsCache; +class QPlatformServices; class Q_GUI_EXPORT QPlatformIntegration { @@ -106,6 +107,8 @@ public: // Access native handles. The window handle is already available from Wid; virtual QPlatformNativeInterface *nativeInterface() const; + virtual QPlatformServices *services() const; + enum StyleHint { CursorFlashTime, KeyboardInputInterval, diff --git a/src/gui/kernel/qplatformservices_qpa.cpp b/src/gui/kernel/qplatformservices_qpa.cpp new file mode 100644 index 0000000000..7993a82f4e --- /dev/null +++ b/src/gui/kernel/qplatformservices_qpa.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformservices_qpa.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QPlatformServices + \since 5.0 + \internal + \preliminary + \ingroup qpa + + \brief The QPlatformServices provides the backend for desktop-related functionality. +*/ + +bool QPlatformServices::openUrl(const QUrl &url) +{ + qWarning("This plugin does not support QPlatformServices::openUrl() for '%s'.", + qPrintable(url.toString())); + return false; +} + +bool QPlatformServices::openDocument(const QUrl &url) +{ + qWarning("This plugin does not support QPlatformServices::openDocument() for '%s'.", + qPrintable(url.toString())); + return false; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qdesktopservices_qpa.cpp b/src/gui/kernel/qplatformservices_qpa.h similarity index 83% rename from src/gui/util/qdesktopservices_qpa.cpp rename to src/gui/kernel/qplatformservices_qpa.h index b94267e72e..aff2e5d6fe 100644 --- a/src/gui/util/qdesktopservices_qpa.cpp +++ b/src/gui/kernel/qplatformservices_qpa.h @@ -39,23 +39,27 @@ ** ****************************************************************************/ -#include -#include +#ifndef QPLATFORMSERVICES_QPA_H +#define QPLATFORMSERVICES_QPA_H + +#include + +QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -static bool launchWebBrowser(const QUrl &url) -{ - Q_UNUSED(url); - qWarning("QDesktopServices::launchWebBrowser not implemented"); - return false; -} +class QUrl; -static bool openDocument(const QUrl &file) +class Q_GUI_EXPORT QPlatformServices { - Q_UNUSED(file); - qWarning("QDesktopServices::openDocument not implemented"); - return false; -} +public: + virtual ~QPlatformServices() { } + + virtual bool openUrl(const QUrl &url); + virtual bool openDocument(const QUrl &url); +}; QT_END_NAMESPACE +QT_END_HEADER + +#endif // QPLATFORMSERVICES_QPA_H diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 0f1312e02d..13e2585b88 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -45,14 +45,14 @@ #include -#include "qdesktopservices_qpa.cpp" - #include #include #include #include +#include #include #include +#include QT_BEGIN_NAMESPACE @@ -185,14 +185,15 @@ bool QDesktopServices::openUrl(const QUrl &url) return result; // ### support bool slot return type } } - - bool result; - if (url.scheme() == QLatin1String("file")) - result = openDocument(url); - else - result = launchWebBrowser(url); - - return result; + if (!url.isValid()) + return false; + QPlatformServices *platformServices = QGuiApplicationPrivate::platformIntegration()->services(); + if (!platformServices) { + qWarning("%s: The platform plugin does not support services.", Q_FUNC_INFO); + return false; + } + return url.scheme() == QStringLiteral("file") ? + platformServices->openDocument(url) : platformServices->openUrl(url); } /*! diff --git a/src/gui/util/qdesktopservices_mac.cpp b/src/gui/util/qdesktopservices_mac.cpp deleted file mode 100644 index 84c7156ef3..0000000000 --- a/src/gui/util/qdesktopservices_mac.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT_NO_DESKTOPSERVICES - -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -/* - Translates a QDesktopServices::StandardLocation into the mac equivalent. -*/ -OSType translateLocation(QDesktopServices::StandardLocation type) -{ - switch (type) { - case QDesktopServices::DesktopLocation: - return kDesktopFolderType; break; - - case QDesktopServices::DocumentsLocation: - return kDocumentsFolderType; break; - - case QDesktopServices::FontsLocation: - // There are at least two different font directories on the mac: /Library/Fonts and ~/Library/Fonts. - // To select a specific one we have to specify a different first parameter when calling FSFindFolder. - return kFontsFolderType; break; - - case QDesktopServices::ApplicationsLocation: - return kApplicationsFolderType; break; - - case QDesktopServices::MusicLocation: - return kMusicDocumentsFolderType; break; - - case QDesktopServices::MoviesLocation: - return kMovieDocumentsFolderType; break; - - case QDesktopServices::PicturesLocation: - return kPictureDocumentsFolderType; break; - - case QDesktopServices::TempLocation: - return kTemporaryFolderType; break; - - case QDesktopServices::DataLocation: - return kApplicationSupportFolderType; break; - - case QDesktopServices::CacheLocation: - return kCachedDataFolderType; break; - - default: - return kDesktopFolderType; break; - } -} - -static bool lsOpen(const QUrl &url) -{ - if (!url.isValid() || url.scheme().isEmpty()) - return false; - - QCFType cfUrl = CFURLCreateWithString(0, QCFString(QString::fromLatin1(url.toEncoded())), 0); - if (cfUrl == 0) - return false; - - const OSStatus err = LSOpenCFURLRef(cfUrl, 0); - return (err == noErr); -} - -static bool launchWebBrowser(const QUrl &url) -{ - return lsOpen(url); -} - -static bool openDocument(const QUrl &file) -{ - if (!file.isValid()) - return false; - - // LSOpen does not work in this case, use QProcess open instead. - return QProcess::startDetached(QLatin1String("open"), QStringList() << file.toLocalFile()); -} - -QT_END_NAMESPACE - -#endif // QT_NO_DESKTOPSERVICES diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp deleted file mode 100644 index 88f245d6f6..0000000000 --- a/src/gui/util/qdesktopservices_win.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#if !defined(Q_OS_WINCE) -# include -#else -# include -# if !defined(STANDARDSHELL_UI_MODEL) -# include -# endif -#endif - -#ifndef CSIDL_MYMUSIC -#define CSIDL_MYMUSIC 13 -#define CSIDL_MYVIDEO 14 -#endif - -#ifndef QT_NO_DESKTOPSERVICES - -QT_BEGIN_NAMESPACE - -static bool openDocument(const QUrl &file) -{ - if (!file.isValid()) - return false; - QString filePath = file.toLocalFile(); - if (filePath.isEmpty()) - filePath = file.toString(); - quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t*)filePath.utf16(), 0, 0, SW_SHOWNORMAL); - return (returnValue > 32); //ShellExecute returns a value greater than 32 if successful -} - -static QString expandEnvStrings(const QString &command) -{ -#if defined(Q_OS_WINCE) - return command; -#else - wchar_t buffer[MAX_PATH]; - if (ExpandEnvironmentStrings((wchar_t*)command.utf16(), buffer, MAX_PATH)) - return QString::fromWCharArray(buffer); - else - return command; -#endif -} - -static bool launchWebBrowser(const QUrl &url) -{ - if (url.scheme() == QLatin1String("mailto")) { - //Retrieve the commandline for the default mail client - //the default key used below is the command line for the mailto: shell command - DWORD bufferSize = sizeof(wchar_t) * MAX_PATH; - long returnValue = -1; - QString command; - - HKEY handle; - LONG res; - wchar_t keyValue[MAX_PATH] = {0}; - QString keyName(QLatin1String("mailto")); - - //Check if user has set preference, otherwise use default. - res = RegOpenKeyEx(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice", - 0, KEY_READ, &handle); - if (res == ERROR_SUCCESS) { - returnValue = RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast(keyValue), &bufferSize); - if (!returnValue) - keyName = QString::fromUtf16((const ushort*)keyValue); - RegCloseKey(handle); - } - keyName += QLatin1String("\\Shell\\Open\\Command"); - res = RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle); - if (res != ERROR_SUCCESS) - return false; - - bufferSize = sizeof(wchar_t) * MAX_PATH; - returnValue = RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast(keyValue), &bufferSize); - if (!returnValue) - command = QString::fromRawData((QChar*)keyValue, bufferSize); - RegCloseKey(handle); - - if (returnValue) - return false; - - command = expandEnvStrings(command); - command = command.trimmed(); - //Make sure the path for the process is in quotes - int index = -1 ; - if (command[0]!= QLatin1Char('\"')) { - index = command.indexOf(QLatin1String(".exe "), 0, Qt::CaseInsensitive); - command.insert(index+4, QLatin1Char('\"')); - command.insert(0, QLatin1Char('\"')); - } - //pass the url as the parameter - index = command.lastIndexOf(QLatin1String("%1")); - if (index != -1){ - command.replace(index, 2, url.toString()); - } - //start the process - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - returnValue = CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - - if (!returnValue) - return false; - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return true; - } - - if (!url.isValid()) - return false; - - if (url.scheme().isEmpty()) - return openDocument(url); - - quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t *)QString::fromUtf8(url.toEncoded().constData()).utf16(), - 0, 0, SW_SHOWNORMAL); - return (returnValue > 32); -} - -QT_END_NAMESPACE - -#endif // QT_NO_DESKTOPSERVICES diff --git a/src/gui/util/qdesktopservices_x11.cpp b/src/gui/util/qdesktopservices_x11.cpp deleted file mode 100644 index 73cf47a1db..0000000000 --- a/src/gui/util/qdesktopservices_x11.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdesktopservices.h" - -#ifndef QT_NO_DESKTOPSERVICES - -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -inline static bool launch(const QUrl &url, const QString &client) -{ -#if !defined(QT_NO_PROCESS) - return (QProcess::startDetached(client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData()))); -#else - return (::system((client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData())).toLocal8Bit().constData()) != -1); -#endif -} - -static bool openDocument(const QUrl &url) -{ - if (!url.isValid()) - return false; - - if (launch(url, QLatin1String("xdg-open"))) - return true; - - // Use the X11->desktopEnvironment value if X11 is non-NULL, - // otherwise just attempt to launch command regardless of the desktop environment - if ((!X11 || (X11 && X11->desktopEnvironment == DE_GNOME)) && launch(url, QLatin1String("gnome-open"))) { - return true; - } else { - if ((!X11 || (X11 && X11->desktopEnvironment == DE_KDE)) && launch(url, QLatin1String("kfmclient exec"))) - return true; - } - - if (launch(url, QLatin1String("firefox"))) - return true; - if (launch(url, QLatin1String("mozilla"))) - return true; - if (launch(url, QLatin1String("netscape"))) - return true; - if (launch(url, QLatin1String("opera"))) - return true; - - return false; -} - -static bool launchWebBrowser(const QUrl &url) -{ - if (!url.isValid()) - return false; - if (url.scheme() == QLatin1String("mailto")) - return openDocument(url); - - if (launch(url, QLatin1String("xdg-open"))) - return true; - if (launch(url, QString::fromLocal8Bit(getenv("DEFAULT_BROWSER")))) - return true; - if (launch(url, QString::fromLocal8Bit(getenv("BROWSER")))) - return true; - - // Use the X11->desktopEnvironment value if X11 is non-NULL, - // otherwise just attempt to launch command regardless of the desktop environment - if ((!X11 || (X11 && X11->desktopEnvironment == DE_GNOME)) && launch(url, QLatin1String("gnome-open"))) { - return true; - } else { - if ((!X11 || (X11 && X11->desktopEnvironment == DE_KDE)) && launch(url, QLatin1String("kfmclient openURL"))) - return true; - } - - if (launch(url, QLatin1String("firefox"))) - return true; - if (launch(url, QLatin1String("mozilla"))) - return true; - if (launch(url, QLatin1String("netscape"))) - return true; - if (launch(url, QLatin1String("opera"))) - return true; - return false; -} - -QT_END_NAMESPACE - -#endif // QT_NO_DESKTOPSERVICES diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 64decd0392..4c02a8ff57 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -34,3 +34,4 @@ include(glxconvenience/glxconvenience.pri) #include(printersupport/printersupport.pri) include(inputcontext/inputcontext.pri) include(udev/udev.pri) +include(services/services.pri) diff --git a/src/platformsupport/services/genericunix/genericunix.pri b/src/platformsupport/services/genericunix/genericunix.pri new file mode 100644 index 0000000000..6afafa31d0 --- /dev/null +++ b/src/platformsupport/services/genericunix/genericunix.pri @@ -0,0 +1,2 @@ +HEADERS += $$PWD/qgenericunixservices_p.h +SOURCES += $$PWD/qgenericunixservices.cpp diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp new file mode 100644 index 0000000000..3c10fb63f6 --- /dev/null +++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgenericunixservices_p.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +enum { debug = 0 }; + +static inline QGenericUnixServices::DesktopEnvironment detectDesktopEnvironment() +{ + if (!qgetenv("KDE_FULL_SESSION").isEmpty()) + return QGenericUnixServices::DE_KDE; + // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it + if (qgetenv("DESKTOP_SESSION") == "gnome" || !qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) + return QGenericUnixServices::DE_GNOME; + return QGenericUnixServices::DE_UNKNOWN; +} + +static inline bool checkExecutable(const QString &candidate, QString *result) +{ + *result = QStandardPaths::findExecutable(candidate); + return !result->isEmpty(); +} + +static inline bool detectWebBrowser(QGenericUnixServices::DesktopEnvironment desktop, + bool checkBrowserVariable, + QString *browser) +{ + const char *browsers[] = {"google-chrome", "firefox", "mozilla", "opera"}; + + browser->clear(); + if (checkExecutable(QStringLiteral("xdg-open"), browser)) + return true; + + if (checkBrowserVariable) { + QByteArray browserVariable = qgetenv("DEFAULT_BROWSER"); + if (browserVariable.isEmpty()) + browserVariable = qgetenv("BROWSER"); + if (!browserVariable.isEmpty() && checkExecutable(QString::fromLocal8Bit(browserVariable), browser)) + return true; + } + + switch (desktop) { + case QGenericUnixServices::DE_UNKNOWN: + break; + case QGenericUnixServices::DE_KDE: + // Konqueror launcher + if (checkExecutable(QStringLiteral("kfmclient"), browser)) { + browser->append(QStringLiteral(" exec")); + return true; + } + case QGenericUnixServices::DE_GNOME: + if (checkExecutable(QStringLiteral("gnome-open"), browser)) + return true; + break; + } + + for (size_t i = 0; i < sizeof(browsers)/sizeof(char *); ++i) + if (checkExecutable(QLatin1String(browsers[i]), browser)) + return true; + return false; +} + +static inline bool launch(const QString &launcher, const QUrl &url) +{ + const QString command = launcher + QLatin1Char(' ') + QLatin1String(url.toEncoded()); + if (debug) + qDebug("Launching %s", qPrintable(command)); +#if defined(QT_NO_PROCESS) + const bool ok = ::system(qPrintable(command + QStringLiteral(" &"))); +#else + const bool ok = QProcess::startDetached(command); +#endif + if (!ok) + qWarning("Launch failed (%s)", qPrintable(command)); + return ok; +} + +QGenericUnixServices::QGenericUnixServices() : + m_desktopEnvironment(detectDesktopEnvironment()) +{ +} + +bool QGenericUnixServices::openUrl(const QUrl &url) +{ + if (url.scheme() == QStringLiteral("mailto")) + return openDocument(url); + + if (m_webBrowser.isEmpty() && !detectWebBrowser(m_desktopEnvironment, true, &m_webBrowser)) { + qWarning("%s: Unable to detect a web browser to launch '%s'", Q_FUNC_INFO, qPrintable(url.toString())); + return false; + } + return launch(m_webBrowser, url); +} + +bool QGenericUnixServices::openDocument(const QUrl &url) +{ + if (m_documentLauncher.isEmpty() && !detectWebBrowser(m_desktopEnvironment, false, &m_documentLauncher)) { + qWarning("%s: Unable to detect a launcher for '%s'", Q_FUNC_INFO, qPrintable(url.toString())); + return false; + } + return launch(m_documentLauncher, url); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/services/genericunix/qgenericunixservices_p.h b/src/platformsupport/services/genericunix/qgenericunixservices_p.h new file mode 100644 index 0000000000..48b790a5b8 --- /dev/null +++ b/src/platformsupport/services/genericunix/qgenericunixservices_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGENERICUNIXDESKTOPSERVICES_H +#define QGENERICUNIXDESKTOPSERVICES_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGenericUnixServices : public QPlatformServices +{ +public: + enum DesktopEnvironment { + DE_UNKNOWN, + DE_KDE, + DE_GNOME + }; + + QGenericUnixServices(); + + virtual bool openUrl(const QUrl &url); + virtual bool openDocument(const QUrl &url); + +private: + const DesktopEnvironment m_desktopEnvironment; + QString m_webBrowser; + QString m_documentLauncher; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICUNIXDESKTOPSERVICES_H diff --git a/src/platformsupport/services/services.pri b/src/platformsupport/services/services.pri new file mode 100644 index 0000000000..adee852626 --- /dev/null +++ b/src/platformsupport/services/services.pri @@ -0,0 +1,3 @@ +unix:!mac { + include($$PWD/genericunix/genericunix.pri) +} diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 2771ec7e8a..3e98be4741 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -46,6 +46,7 @@ #include "qwindowsglcontext.h" #include "qwindowsscreen.h" #include "qwindowstheme.h" +#include "qwindowsservices.h" #ifndef QT_NO_FREETYPE #include "qwindowsfontdatabase_ft.h" #endif @@ -162,6 +163,7 @@ struct QWindowsIntegrationPrivate QWindowsInputContext m_inputContext; QWindowsAccessibility m_accessibility; QWindowsTheme m_theme; + QWindowsServices m_services; }; QWindowsIntegrationPrivate::QWindowsIntegrationPrivate() @@ -339,4 +341,9 @@ QPlatformTheme *QWindowsIntegration::platformTheme() const return &d->m_theme; } +QPlatformServices *QWindowsIntegration::services() const +{ + return &d->m_services; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index a96605f259..ba5fafbbb5 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -70,6 +70,7 @@ public: virtual QPlatformNativeInterface *nativeInterface() const; virtual QPlatformFontDatabase *fontDatabase() const; virtual QPlatformTheme *platformTheme() const; + QPlatformServices *services() const; virtual QVariant styleHint(StyleHint hint) const; static QWindowsIntegration *instance(); diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp new file mode 100644 index 0000000000..5cc4ce93af --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsservices.h" +#include "qtwindows_additional.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +enum { debug = 0 }; + +static inline bool shellExecute(const QString &file) +{ + const int result = (int)ShellExecute(0, 0, (wchar_t*)file.utf16(), 0, 0, SW_SHOWNORMAL); + // ShellExecute returns a value greater than 32 if successful + if (result <= 32) { + qWarning("ShellExecute '%s' failed (error %0x).", qPrintable(file), result); + return false; + } + return true; +} + +// Retrieve the commandline for the default mail client. It contains a +// placeholder %1 for the URL. The default key used below is the +// command line for the mailto: shell command. +static inline QString mailCommand() +{ + enum { BufferSize = sizeof(wchar_t) * MAX_PATH }; + + const wchar_t mailUserKey[] = L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice"; + + wchar_t command[MAX_PATH] = {0}; + // Check if user has set preference, otherwise use default. + HKEY handle; + QString keyName; + if (!RegOpenKeyEx(HKEY_CURRENT_USER, mailUserKey, 0, KEY_READ, &handle)) { + DWORD bufferSize = BufferSize; + if (!RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast(command), &bufferSize)) + keyName = QString::fromWCharArray(command); + RegCloseKey(handle); + } + if (keyName.isEmpty()) + keyName = QStringLiteral("mailto"); + keyName += QStringLiteral("\\Shell\\Open\\Command"); + if (debug) + qDebug() << __FUNCTION__ << "keyName=" << keyName; + command[0] = 0; + if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle)) { + DWORD bufferSize = BufferSize; + RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast(command), &bufferSize); + RegCloseKey(handle); + } + if (!command[0]) + return QString(); + wchar_t expandedCommand[MAX_PATH] = {0}; + return ExpandEnvironmentStrings(command, expandedCommand, MAX_PATH) ? + QString::fromWCharArray(expandedCommand) : QString::fromWCharArray(command); +} + +static inline bool launchMail(const QUrl &url) +{ + QString command = mailCommand(); + if (command.isEmpty()) { + qWarning("Cannot launch '%s': There is no mail program installed."); + return false; + } + //Make sure the path for the process is in quotes + const QChar doubleQuote = QLatin1Char('"'); + if (!command.startsWith(doubleQuote)) { + const int exeIndex = command.indexOf(QStringLiteral(".exe "), 0, Qt::CaseInsensitive); + if (exeIndex != -1) { + command.insert(exeIndex + 4, doubleQuote); + command.prepend(doubleQuote); + } + } + // Pass the url as the parameter. Should use QProcess::startDetached(), + // but that cannot handle a Windows command line [yet]. + command.replace(QStringLiteral("%1"), url.toString()); + if (debug) + qDebug() << __FUNCTION__ << "Launching" << command; + //start the process + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + if (!CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + qErrnoWarning("Unable to launch '%s'", qPrintable(command)); + return false; + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; +} + +bool QWindowsServices::openUrl(const QUrl &url) +{ + const QString scheme = url.scheme(); + if (scheme.isEmpty()) + return openDocument(url); + if (scheme == QStringLiteral("mailto") && launchMail(url)) + return true; + return shellExecute(QLatin1String(url.toEncoded())); +} + +bool QWindowsServices::openDocument(const QUrl &url) +{ + return shellExecute(url.isLocalFile() ? url.toLocalFile() : url.toString()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsservices.h b/src/plugins/platforms/windows/qwindowsservices.h new file mode 100644 index 0000000000..d979ed1af1 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsservices.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSDESKTOPSERVICES_H +#define QWINDOWSDESKTOPSERVICES_H + +#include + +QT_BEGIN_NAMESPACE + +class QWindowsServices : public QPlatformServices +{ +public: + bool openUrl(const QUrl &url); + bool openDocument(const QUrl &url); +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSDESKTOPSERVICES_H diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 01976a9936..58a117b8af 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -13,6 +13,7 @@ LIBS *= -lOpenGL32 -lGdi32 -lUser32 -lOle32 -lWinspool -lImm32 -lWinmm -lOleaut win32-g++: LIBS *= -luuid # For the dialog helpers: LIBS *= -lshlwapi -lShell32 +LIBS *= -lAdvapi32 DEFINES *= QT_NO_CAST_FROM_ASCII @@ -46,7 +47,8 @@ SOURCES += \ qwindowsinputcontext.cpp \ qwindowsaccessibility.cpp \ qwindowstheme.cpp \ - qwindowsdialoghelpers.cpp + qwindowsdialoghelpers.cpp \ + qwindowsservices.cpp HEADERS += \ qwindowsnativeimage.h \ @@ -73,7 +75,8 @@ HEADERS += \ qwindowsinputcontext.h \ qwindowsaccessibility.h \ qwindowstheme.h \ - qwindowsdialoghelpers.h + qwindowsdialoghelpers.h \ + qwindowsservices.h # Enable access to HB_Face in harfbuzz includes included by qfontengine_p.h. DEFINES *= QT_COMPILES_IN_HARFBUZZ diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 40359169ca..0f7648a21b 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -53,6 +53,8 @@ #include #include +#include +#include #include @@ -84,7 +86,8 @@ QT_BEGIN_NAMESPACE QXcbIntegration::QXcbIntegration(const QStringList ¶meters) - : m_eventDispatcher(createUnixEventDispatcher()) + : m_eventDispatcher(createUnixEventDispatcher()), + m_services(new QGenericUnixServices) { QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher); @@ -268,4 +271,9 @@ QPlatformSharedGraphicsCache *QXcbIntegration::createPlatformSharedGraphicsCache } #endif +QPlatformServices *QXcbIntegration::services() const +{ + return m_services.data(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index eefecd509b..77d0e4903c 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -81,6 +81,8 @@ public: QPlatformSharedGraphicsCache *createPlatformSharedGraphicsCache(const char *cacheId) const; #endif + QPlatformServices *services() const; + private: QList m_connections; @@ -95,6 +97,8 @@ private: #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) QScopedPointer m_sharedGraphicsCache; #endif + + QScopedPointer m_services; }; QT_END_NAMESPACE