From c908fc4448989d0319f86da35c8fa66ad1440fa2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 Feb 2012 08:40:48 +0100 Subject: Add QPlatformServices class. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add QPlatformServices as back-end for QDesktopServices. - Bring back UNIX/Linux desktop detection in platformsupport as a generic implementation. - Add Windows implementation. Reviewed-by: Morten Johan Sorvig Reviewed-by: Samuel Rødal Reviewed-by: Anselmo Lacerda S. de Melo Change-Id: If94bb65755df4f849edd83c57143ee2c73002137 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowsintegration.cpp | 7 + .../platforms/windows/qwindowsintegration.h | 1 + src/plugins/platforms/windows/qwindowsservices.cpp | 154 +++++++++++++++++++++ src/plugins/platforms/windows/qwindowsservices.h | 58 ++++++++ src/plugins/platforms/windows/windows.pro | 7 +- src/plugins/platforms/xcb/qxcbintegration.cpp | 10 +- src/plugins/platforms/xcb/qxcbintegration.h | 4 + 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/plugins/platforms/windows/qwindowsservices.cpp create mode 100644 src/plugins/platforms/windows/qwindowsservices.h (limited to 'src/plugins') 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 -- cgit v1.2.3