summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/qpa/egl-x11/egl-x11.cpp62
-rw-r--r--config.tests/qpa/egl-x11/egl-x11.pro12
-rwxr-xr-xconfigure31
-rw-r--r--examples/widgets/mainwindows/mainwindow/colorswatch.cpp2
-rw-r--r--examples/widgets/mainwindows/mainwindow/colorswatch.h2
-rw-r--r--mkspecs/features/moc.prf2
-rw-r--r--mkspecs/features/qt.prf2
-rw-r--r--mkspecs/features/win32/windeployqt.prf19
-rw-r--r--mkspecs/winphone-x86-msvc2012/qmake.conf2
-rw-r--r--mkspecs/winrt-arm-msvc2012/qmake.conf1
-rw-r--r--mkspecs/winrt-arm-msvc2013/qmake.conf1
-rw-r--r--mkspecs/winrt-x64-msvc2012/qmake.conf1
-rw-r--r--mkspecs/winrt-x64-msvc2013/qmake.conf1
-rw-r--r--mkspecs/winrt-x86-msvc2012/qmake.conf3
-rw-r--r--mkspecs/winrt-x86-msvc2013/qmake.conf3
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp40
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.h1
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp2
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp6
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h20
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp17
-rw-r--r--qmake/generators/win32/msvc_vcproj.h1
-rw-r--r--src/corelib/codecs/qutfcodec.cpp17
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp72
-rw-r--r--src/corelib/global/qlogging.cpp2
-rw-r--r--src/corelib/global/qprocessordetection.h5
-rw-r--r--src/corelib/io/qloggingcategory.cpp14
-rw-r--r--src/corelib/io/qloggingregistry.cpp8
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2
-rw-r--r--src/corelib/thread/qthread_win.cpp8
-rw-r--r--src/corelib/tools/qdatetime.cpp12
-rw-r--r--src/corelib/tools/qstring.cpp182
-rw-r--r--src/corelib/tools/qstring.h7
-rw-r--r--src/corelib/tools/qstringbuilder.h9
-rw-r--r--src/corelib/tools/qstringiterator.qdoc328
-rw-r--r--src/corelib/tools/qstringiterator_p.h233
-rw-r--r--src/corelib/tools/tools.pri1
-rw-r--r--src/gui/image/qimage.cpp8
-rw-r--r--src/gui/image/qimage_conversions.cpp26
-rw-r--r--src/gui/image/qimage_sse2.cpp2
-rw-r--r--src/gui/image/qpixmap_blitter.cpp2
-rw-r--r--src/gui/image/qpixmap_raster.cpp2
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qplatformwindow.cpp12
-rw-r--r--src/gui/kernel/qplatformwindow.h1
-rw-r--r--src/gui/kernel/qwindow.cpp17
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/gui/opengl/opengl.pri6
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp10
-rw-r--r--src/gui/opengl/qopengltexture.cpp39
-rw-r--r--src/gui/opengl/qopengltexture.h3
-rw-r--r--src/gui/opengl/qopengltextureblitter.cpp394
-rw-r--r--src/gui/opengl/qopengltextureblitter_p.h86
-rw-r--r--src/gui/opengl/qopengltexturehelper.cpp34
-rw-r--r--src/gui/opengl/qopengltexturehelper_p.h4
-rw-r--r--src/gui/painting/qcolor.cpp55
-rw-r--r--src/gui/painting/qdrawhelper.cpp30
-rw-r--r--src/gui/painting/qdrawhelper_p.h35
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp38
-rw-r--r--src/gui/painting/qpainter.cpp7
-rw-r--r--src/gui/painting/qrgb.h43
-rw-r--r--src/gui/text/qdistancefield.cpp14
-rw-r--r--src/gui/text/qfont.cpp4
-rw-r--r--src/gui/text/qfontdatabase.h2
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp17
-rw-r--r--src/gui/text/qfontengine.cpp82
-rw-r--r--src/gui/text/qfontengine_ft.cpp19
-rw-r--r--src/gui/text/qfontmetrics.cpp161
-rw-r--r--src/gui/text/qfontsubset.cpp18
-rw-r--r--src/gui/text/qharfbuzzng.cpp23
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp6
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qrawfont.cpp17
-rw-r--r--src/gui/text/qtextengine.cpp134
-rw-r--r--src/gui/text/qtextengine_p.h6
-rw-r--r--src/gui/text/qtextlayout.cpp11
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp10
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp6
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp17
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp13
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h2
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm4
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp29
-rw-r--r--src/plugins/bearer/connman/connman.pro2
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.cpp401
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.h24
-rw-r--r--src/plugins/bearer/connman/qconnmanservice_linux.cpp866
-rw-r--r--src/plugins/bearer/connman/qconnmanservice_linux_p.h207
-rw-r--r--src/plugins/bearer/connman/qofonoservice_linux.cpp899
-rw-r--r--src/plugins/bearer/connman/qofonoservice_linux_p.h220
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h33
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm25
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm15
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm50
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm6
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_stub.cpp2
-rw-r--r--src/plugins/platforms/ios/ios.pro5
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h14
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm146
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm139
-rw-r--r--src/plugins/platforms/ios/quiview.h78
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm557
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.cpp36
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.h15
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp29
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp23
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp101
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp5
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro2
-rw-r--r--src/printsupport/dialogs/qprintpreviewdialog.cpp11
-rw-r--r--src/printsupport/printsupport.pro1
-rw-r--r--src/widgets/kernel/qapplication.cpp3
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp29
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h1
-rw-r--r--tests/auto/corelib/codecs/utf8/tst_utf8.cpp4
-rw-r--r--tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp34
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp116
-rw-r--r--tests/auto/corelib/tools/qstringiterator/qstringiterator.pro5
-rw-r--r--tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp675
-rw-r--r--tests/auto/corelib/tools/tools.pro1
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp119
-rw-r--r--tests/manual/cocoa/qmaccocoaviewcontainer/main.mm1
-rw-r--r--tests/manual/manual.pro2
-rw-r--r--tests/manual/qopengltextureblitter/main.cpp53
-rw-r--r--tests/manual/qopengltextureblitter/qopengltextureblitter.pro12
-rw-r--r--tests/manual/qopengltextureblitter/qopengltextureblitwindow.cpp167
-rw-r--r--tests/manual/qopengltextureblitter/qopengltextureblitwindow.h69
-rw-r--r--tools/configure/configureapp.cpp14
-rw-r--r--tools/configure/configureapp.h1
148 files changed, 4993 insertions, 2921 deletions
diff --git a/config.tests/qpa/egl-x11/egl-x11.cpp b/config.tests/qpa/egl-x11/egl-x11.cpp
new file mode 100644
index 0000000000..f5c2ae7260
--- /dev/null
+++ b/config.tests/qpa/egl-x11/egl-x11.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <EGL/egl.h>
+#include <xcb/xcb.h>
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+
+// Check if EGL is compatible with X. Some EGL implementations, typically on
+// embedded devices, are not intended to be used together with X. EGL support
+// has to be disabled in plugins like xcb in this case since the native display,
+// window and pixmap types will be different than what an X-based platform
+// plugin would expect.
+
+int main(int, char **)
+{
+ Display *dpy = EGL_DEFAULT_DISPLAY;
+ EGLNativeDisplayType egldpy = XOpenDisplay("");
+ dpy = egldpy;
+ EGLNativeWindowType w = XCreateWindow(dpy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ XDestroyWindow(dpy, w);
+ XCloseDisplay(dpy);
+ return 0;
+}
diff --git a/config.tests/qpa/egl-x11/egl-x11.pro b/config.tests/qpa/egl-x11/egl-x11.pro
new file mode 100644
index 0000000000..c4e94ca40c
--- /dev/null
+++ b/config.tests/qpa/egl-x11/egl-x11.pro
@@ -0,0 +1,12 @@
+SOURCES = egl-x11.cpp
+
+for(p, QMAKE_LIBDIR_EGL) {
+ exists($$p):LIBS += -L$$p
+}
+
+!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL
+!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL
+
+CONFIG -= qt
+
+LIBS += -lxcb -lX11 -lX11-xcb
diff --git a/configure b/configure
index 529471d0c4..dc23bb4eb6 100755
--- a/configure
+++ b/configure
@@ -613,6 +613,7 @@ CFG_OPENVG_LC_INCLUDES=no
CFG_OPENVG_SHIVA=auto
CFG_OPENVG_ON_OPENGL=auto
CFG_EGL=auto
+CFG_EGL_X=auto
CFG_FONTCONFIG=auto
CFG_FREETYPE=auto
CFG_HARFBUZZ=no
@@ -780,6 +781,8 @@ QT_LIBS_GLIB=
# default qpa platform
QT_QPA_DEFAULT_PLATFORM=
+# default print support plugin
+QT_PRINTSUPPORT_DEFAULT_PLUGIN=
# Android vars
CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT
@@ -1473,6 +1476,7 @@ while [ "$#" -gt 0 ]; do
egl)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_EGL="$VAL"
+ CFG_EGL_X="$VAL"
else
UNKNOWN_OPT=yes
fi
@@ -5366,6 +5370,11 @@ if [ "$CFG_EGL" != "no" ]; then
fi # detect EGL support
if compileTest qpa/egl "EGL" $QMAKE_CFLAGS_EGL $QMAKE_LIBS_EGL; then
CFG_EGL=yes
+ if compileTest qpa/egl-x11 "EGL-X11" $QMAKE_CFLAGS_EGL $QMAKE_LIBS_EGL; then
+ CFG_EGL_X=yes
+ else
+ CFG_EGL_X=no
+ fi
elif [ "$CFG_EGL" = "yes" ]; then
echo " The EGL functionality test failed; EGL is required by some QPA plugins to manage contexts & surfaces."
echo " You might need to modify the include and library search paths by editing"
@@ -5373,6 +5382,7 @@ if [ "$CFG_EGL" != "no" ]; then
exit 1
else
CFG_EGL=no
+ CFG_EGL_X=no
fi
fi
@@ -5427,6 +5437,15 @@ if [ -z "$QT_QPA_DEFAULT_PLATFORM" ]; then
fi
fi
+# Determine print support plugin belonging to the default QPA platform
+if [ "$QT_QPA_DEFAULT_PLATFORM" = "cocoa" ]; then
+ QT_PRINTSUPPORT_DEFAULT_PLUGIN=cocoaprintersupport
+elif [ "$QT_QPA_DEFAULT_PLATFORM" = "windows" ]; then
+ QT_PRINTSUPPORT_DEFAULT_PLUGIN=windowsprintersupport
+elif [ "$QT_QPA_DEFAULT_PLATFORM" = "xcb" ]; then
+ QT_PRINTSUPPORT_DEFAULT_PLUGIN=cupsprintersupport
+fi
+
if [ -n "$QMAKE_CFLAGS_XCB" ] || [ -n "$QMAKE_LIBS_XCB" ]; then
QMakeVar set QMAKE_CFLAGS_XCB "$QMAKE_CFLAGS_XCB"
QMakeVar set QMAKE_LIBS_XCB "$QMAKE_LIBS_XCB"
@@ -5752,6 +5771,13 @@ else
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EGL"
fi
+# enable egl on X
+if [ "$CFG_EGL_X" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG egl_x11"
+else
+ QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EGL_X11"
+fi
+
# enable eglfs
if [ "$CFG_EGLFS" = "yes" ]; then
QT_CONFIG="$QT_CONFIG eglfs"
@@ -6412,6 +6438,7 @@ EOF
fi
echo "#define QT_QPA_DEFAULT_PLATFORM_NAME \"$QT_QPA_DEFAULT_PLATFORM\"" >>"$outpath/src/corelib/global/qconfig.h.new"
+echo "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"QT_PRINTSUPPORT_DEFAULT_PLUGIN\"" >>"$outpath/src/corelib/global/qconfig.h.new"
# avoid unecessary rebuilds by copying only if qconfig.h has changed
if cmp -s "$outpath/src/corelib/global/qconfig.h" "$outpath/src/corelib/global/qconfig.h.new"; then
@@ -6499,6 +6526,7 @@ EOF
if [ "$CFG_SHARED" = "no" ]; then
echo "QT_DEFAULT_QPA_PLUGIN = q$QT_QPA_DEFAULT_PLATFORM" >> "$QTCONFIG.tmp"
+ echo "QT_DEFAULT_PRINTSUPPORTPLUGIN = $QT_PRINTSUPPORT_DEFAULT_PLUGIN" >> "$QTCONFIG.tmp"
echo >> "$QTCONFIG.tmp"
fi
@@ -6775,6 +6803,9 @@ report_support " getifaddrs ..........." "$CFG_GETIFADDRS"
report_support " IPv6 ifname .........." "$CFG_IPV6IFNAME"
report_support " OpenSSL .............." "$CFG_OPENSSL" yes "loading libraries at run-time" linked "linked to the libraries"
report_support " NIS ...................." "$CFG_NIS"
+report_support " EGL ...................." "$CFG_EGL"
+report_support " EGL on X ..............." "$CFG_EGL_X"
+report_support " GLX ...................." "$CFG_XCB_GLX"
report_support " OpenGL ................." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.x"
report_support " OpenVG ................." "$CFG_OPENVG-$CFG_OPENVG_SHIVA" yes-yes "ShivaVG" yes-no "native"
report_support " PCRE ..................." "$CFG_PCRE" yes "system library" qt "bundled copy"
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
index 00a35afa4c..b39c45118c 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
@@ -636,7 +636,7 @@ void BlueTitleBar::paintEvent(QPaintEvent*)
centerPm.height(), centerPm);
}
-void BlueTitleBar::mousePressEvent(QMouseEvent *event)
+void BlueTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
QPoint pos = event->pos();
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.h b/examples/widgets/mainwindows/mainwindow/colorswatch.h
index 11f924ddb7..b83a6ba76a 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.h
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.h
@@ -124,7 +124,7 @@ public:
QSize minimumSizeHint() const;
protected:
void paintEvent(QPaintEvent *event);
- void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
public slots:
void updateMask();
diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf
index 100edc2d98..c0b5682446 100644
--- a/mkspecs/features/moc.prf
+++ b/mkspecs/features/moc.prf
@@ -8,6 +8,8 @@ isEmpty(QMAKE_EXT_CPP_MOC):QMAKE_EXT_CPP_MOC = .moc
MOC_INCLUDEPATH =
for (inc, INCLUDEPATH): \
MOC_INCLUDEPATH += $$absolute_path($$inc, $$_PRO_FILE_PWD_)
+!no_include_pwd:!isEqual(OUT_PWD, $$_PRO_FILE_PWD_): \
+ MOC_INCLUDEPATH += .
MOC_INCLUDEPATH = $$QMAKESPEC $$_PRO_FILE_PWD_ $$MOC_INCLUDEPATH $$QMAKE_DEFAULT_INCDIRS
# On Windows, put the includes into a .inc file which moc will read, if the project
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 83a8778654..fb83e59e65 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -172,6 +172,8 @@ contains(QT_CONFIG, static) {
else: \
QTPLUGIN += $$QT_DEFAULT_QPA_PLUGIN
}
+ needs_printsupport_plugin: \
+ QTPLUGIN += $$QT_DEFAULT_PRINTSUPPORTPLUGIN
import_plugins:!isEmpty(QTPLUGIN) {
IMPORT_FILE_CONT = \
"// This file is autogenerated by qmake. It imports static plugin classes for" \
diff --git a/mkspecs/features/win32/windeployqt.prf b/mkspecs/features/win32/windeployqt.prf
new file mode 100644
index 0000000000..f49df47ffe
--- /dev/null
+++ b/mkspecs/features/win32/windeployqt.prf
@@ -0,0 +1,19 @@
+# Extra target for running windeployqt
+qtPrepareTool(QMAKE_WINDEPLOYQT, windeployqt)
+build_pass {
+ load(resolve_target)
+
+ isEmpty(WINDEPLOYQT_OPTIONS): WINDEPLOYQT_OPTIONS = -qmldir $$shell_quote($$shell_path($$_PRO_FILE_PWD_))
+ WINDEPLOYQT_TARGET = $$shell_quote($$shell_path($$QMAKE_RESOLVED_TARGET))
+ WINDEPLOYQT_OUTPUT = $$shell_quote($$shell_path($$dirname(QMAKE_RESOLVED_TARGET)/$$basename(TARGET).windeployqt))
+ windeployqt.target = windeployqt
+ windeployqt.commands = $$QMAKE_WINDEPLOYQT $$WINDEPLOYQT_OPTIONS -list target $$WINDEPLOYQT_TARGET > $$WINDEPLOYQT_OUTPUT
+
+ windeployqt_clean.commands = if exist $$WINDEPLOYQT_OUTPUT for /f %i in ($$WINDEPLOYQT_OUTPUT) do $$QMAKE_DEL_FILE %~fi && $$QMAKE_DEL_DIR %~pi
+ QMAKE_EXTRA_TARGETS += windeployqt_clean
+ DISTCLEAN_DEPS += windeployqt_clean
+ QMAKE_DISTCLEAN += $$WINDEPLOYQT_OUTPUT
+} else {
+ windeployqt.CONFIG += recursive
+}
+QMAKE_EXTRA_TARGETS += windeployqt
diff --git a/mkspecs/winphone-x86-msvc2012/qmake.conf b/mkspecs/winphone-x86-msvc2012/qmake.conf
index 1329370900..4b8a92ea3b 100644
--- a/mkspecs/winphone-x86-msvc2012/qmake.conf
+++ b/mkspecs/winphone-x86-msvc2012/qmake.conf
@@ -13,7 +13,7 @@ QMAKE_LFLAGS += /MACHINE:X86
QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib
-VCPROJ_ARCH = x86
+VCPROJ_ARCH = Win32
MSVC_VER = 11.0
WINSDK_VER = 8.0
WINTARGET_VER = WP80
diff --git a/mkspecs/winrt-arm-msvc2012/qmake.conf b/mkspecs/winrt-arm-msvc2012/qmake.conf
index 41594a3547..b2603cfb2f 100644
--- a/mkspecs/winrt-arm-msvc2012/qmake.conf
+++ b/mkspecs/winrt-arm-msvc2012/qmake.conf
@@ -17,3 +17,4 @@ MSVC_VER = 11.0
WINSDK_VER = 8.0
WINTARGET_VER = win8
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = arm
diff --git a/mkspecs/winrt-arm-msvc2013/qmake.conf b/mkspecs/winrt-arm-msvc2013/qmake.conf
index 83ab228d7f..d1ab60723d 100644
--- a/mkspecs/winrt-arm-msvc2013/qmake.conf
+++ b/mkspecs/winrt-arm-msvc2013/qmake.conf
@@ -19,3 +19,4 @@ MSVC_VER = 12.0
WINSDK_VER = 8.1
WINTARGET_VER = winv6.3
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = arm
diff --git a/mkspecs/winrt-x64-msvc2012/qmake.conf b/mkspecs/winrt-x64-msvc2012/qmake.conf
index f6e360ae12..a0c64c695f 100644
--- a/mkspecs/winrt-x64-msvc2012/qmake.conf
+++ b/mkspecs/winrt-x64-msvc2012/qmake.conf
@@ -17,3 +17,4 @@ MSVC_VER = 11.0
WINSDK_VER = 8.0
WINTARGET_VER = win8
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x64
diff --git a/mkspecs/winrt-x64-msvc2013/qmake.conf b/mkspecs/winrt-x64-msvc2013/qmake.conf
index 2c01450ed4..594d0dafd0 100644
--- a/mkspecs/winrt-x64-msvc2013/qmake.conf
+++ b/mkspecs/winrt-x64-msvc2013/qmake.conf
@@ -19,3 +19,4 @@ MSVC_VER = 12.0
WINSDK_VER = 8.1
WINTARGET_VER = winv6.3
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x64
diff --git a/mkspecs/winrt-x86-msvc2012/qmake.conf b/mkspecs/winrt-x86-msvc2012/qmake.conf
index 664212624c..6e6ea4664d 100644
--- a/mkspecs/winrt-x86-msvc2012/qmake.conf
+++ b/mkspecs/winrt-x86-msvc2012/qmake.conf
@@ -12,8 +12,9 @@ QMAKE_LFLAGS += /SAFESEH /MACHINE:X86
QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib
-VCPROJ_ARCH = x86
+VCPROJ_ARCH = Win32
MSVC_VER = 11.0
WINSDK_VER = 8.0
WINTARGET_VER = win8
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x86
diff --git a/mkspecs/winrt-x86-msvc2013/qmake.conf b/mkspecs/winrt-x86-msvc2013/qmake.conf
index 384b51a1e6..77b906c7d3 100644
--- a/mkspecs/winrt-x86-msvc2013/qmake.conf
+++ b/mkspecs/winrt-x86-msvc2013/qmake.conf
@@ -14,8 +14,9 @@ QMAKE_LFLAGS += /SAFESEH /MACHINE:X86
QMAKE_LIBS += windowscodecs.lib kernel32.lib ole32.lib
-VCPROJ_ARCH = x86
+VCPROJ_ARCH = Win32
MSVC_VER = 12.0
WINSDK_VER = 8.1
WINTARGET_VER = winv6.3
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
+WINRT_MANIFEST.architecture = x86
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index f37c3180f4..4f946001bf 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -774,6 +774,10 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
write(xml, config.preLink);
xml << closetag();
+
+ // windeployqt
+ if (!config.windeployqt.ExcludedFromBuild)
+ write(xml, config.windeployqt);
}
// The file filters are added in a separate file for MSBUILD.
@@ -1734,6 +1738,42 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
// SmartDevice deployment not supported in VS 2010
}
+void VCXProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool)
+{
+ const QString name = QStringLiteral("WinDeployQt_") + tool.config->Name;
+ xml << tag("Target")
+ << attrTag(_Name, name)
+ << attrTag("Condition", generateCondition(*tool.config))
+ << attrTag("Inputs", "$(OutDir)\\$(TargetName).exe")
+ << attrTag("Outputs", tool.Record)
+ << tag(_Message)
+ << attrTag("Text", tool.CommandLine)
+ << closetag()
+ << tag("Exec")
+ << attrTag("Command", tool.CommandLine)
+ << closetag()
+ << closetag()
+ << tag("Target")
+ << attrTag(_Name, QStringLiteral("PopulateWinDeployQtItems_") + tool.config->Name)
+ << attrTag("Condition", generateCondition(*tool.config))
+ << attrTag("AfterTargets", "Link")
+ << attrTag("DependsOnTargets", name)
+ << tag("ReadLinesFromFile")
+ << attrTag("File", tool.Record)
+ << tag("Output")
+ << attrTag("TaskParameter", "Lines")
+ << attrTag("ItemName", "DeploymentItems")
+ << closetag()
+ << closetag()
+ << tag(_ItemGroup)
+ << tag("None")
+ << attrTag("Include", "@(DeploymentItems)")
+ << attrTagT("DeploymentContent", _True)
+ << closetag()
+ << closetag()
+ << closetag();
+}
+
void VCXProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
{
xml << tag("PropertyGroup")
diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h
index 7fb83233f4..2f02e66eb9 100644
--- a/qmake/generators/win32/msbuild_objectmodel.h
+++ b/qmake/generators/win32/msbuild_objectmodel.h
@@ -174,6 +174,7 @@ public:
void write(XmlOutput &, const VCResourceCompilerTool &);
void write(XmlOutput &, const VCEventTool &);
void write(XmlOutput &, const VCDeploymentTool &);
+ void write(XmlOutput &, const VCWinDeployQtTool &);
void write(XmlOutput &, const VCConfiguration &);
void write(XmlOutput &, VCFilter &);
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index acccdc1bdc..24465ad152 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -123,6 +123,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
} else if (arch == QStringLiteral("x64")) {
compiler = QStringLiteral("x86_amd64");
compilerArch = QStringLiteral("amd64");
+ } else {
+ arch = QStringLiteral("x86");
}
const QString msvcVer = project->first("MSVC_VER").toQString();
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 3217500916..1a92b79a09 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -2794,6 +2794,12 @@ void VCProjectWriter::write(XmlOutput &xml, const VCDeploymentTool &tool)
<< closetag(tool.DeploymentTag);
}
+void VCProjectWriter::write(XmlOutput &xml, const VCWinDeployQtTool &tool)
+{
+ Q_UNUSED(xml);
+ Q_UNUSED(tool);
+}
+
void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool)
{
xml << tag(_Configuration)
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 7c51f6a67a..0aa5736d2a 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -860,6 +860,24 @@ public:
~VCPreLinkEventTool(){}
};
+class VCWinDeployQtTool : public VCToolBase
+{
+public:
+ VCWinDeployQtTool() {}
+ ~VCWinDeployQtTool() {}
+
+protected:
+ bool parseOption(const char *) { return false; }
+
+public:
+ // Variables
+ QString Record;
+ QString CommandLine;
+ bool ExcludedFromBuild;
+
+ VCConfiguration * config;
+};
+
class VCConfiguration
{
public:
@@ -900,6 +918,7 @@ public:
VCDeploymentTool deployment;
VCPreLinkEventTool preLink;
VCResourceCompilerTool resource;
+ VCWinDeployQtTool windeployqt;
};
struct VCFilterFile
@@ -1156,6 +1175,7 @@ public:
virtual void write(XmlOutput &, const VCResourceCompilerTool &);
virtual void write(XmlOutput &, const VCEventTool &);
virtual void write(XmlOutput &, const VCDeploymentTool &);
+ virtual void write(XmlOutput &, const VCWinDeployQtTool &);
virtual void write(XmlOutput &, const VCConfiguration &);
virtual void write(XmlOutput &, VCFilter &);
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 829be89097..ce9dc6d9ec 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -1021,6 +1021,7 @@ void VcprojGenerator::initConfiguration()
if ((!project->isHostBuild() && !project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"))
|| conf.WinRT)
initDeploymentTool();
+ initWinDeployQtTool();
initPreLinkEventTools();
if (!isDebug)
@@ -1323,6 +1324,22 @@ void VcprojGenerator::initDeploymentTool()
}
}
+void VcprojGenerator::initWinDeployQtTool()
+{
+ VCConfiguration &conf = vcProject.Configuration;
+ conf.windeployqt.ExcludedFromBuild = true;
+ if (project->isActiveConfig("windeployqt")) {
+ conf.windeployqt.Record = QStringLiteral("$(TargetName).windeployqt.$(Platform).$(Configuration)");
+ conf.windeployqt.CommandLine =
+ MakefileGenerator::shellQuote(QDir::toNativeSeparators(project->first("QMAKE_WINDEPLOYQT").toQString()))
+ + QLatin1Char(' ') + project->values("WINDEPLOYQT_OPTIONS").join(QLatin1Char(' '))
+ + QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\" \"$(OutDir)\\$(TargetName).exe\" > ")
+ + MakefileGenerator::shellQuote(conf.windeployqt.Record);
+ conf.windeployqt.config = &vcProject.Configuration;
+ conf.windeployqt.ExcludedFromBuild = false;
+ }
+}
+
void VcprojGenerator::initPreLinkEventTools()
{
VCConfiguration &conf = vcProject.Configuration;
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index d531085307..4a25d11766 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -109,6 +109,7 @@ protected:
void initPreBuildEventTools();
void initPostBuildEventTools();
void initDeploymentTool();
+ void initWinDeployQtTool();
void initPreLinkEventTools();
void initRootFiles();
void initSourceFiles();
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index 20bacb1584..a5d16b0b54 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -46,6 +46,7 @@
#include "qchar.h"
#include "private/qsimd_p.h"
+#include "private/qstringiterator_p.h"
QT_BEGIN_NAMESPACE
@@ -503,21 +504,21 @@ QByteArray QUtf32::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conv
}
data += 4;
}
+
+ QStringIterator i(uc, uc + len);
if (endian == BigEndianness) {
- for (int i = 0; i < len; ++i) {
- uint cp = uc[i].unicode();
- if (uc[i].isHighSurrogate() && i < len - 1)
- cp = QChar::surrogateToUcs4(cp, uc[++i].unicode());
+ while (i.hasNext()) {
+ uint cp = i.next();
+
*(data++) = cp >> 24;
*(data++) = (cp >> 16) & 0xff;
*(data++) = (cp >> 8) & 0xff;
*(data++) = cp & 0xff;
}
} else {
- for (int i = 0; i < len; ++i) {
- uint cp = uc[i].unicode();
- if (uc[i].isHighSurrogate() && i < len - 1)
- cp = QChar::surrogateToUcs4(cp, uc[++i].unicode());
+ while (i.hasNext()) {
+ uint cp = i.next();
+
*(data++) = cp & 0xff;
*(data++) = (cp >> 8) & 0xff;
*(data++) = (cp >> 16) & 0xff;
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
new file mode 100644
index 0000000000..178c6feb0a
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QString>
+#include <QStringIterator>
+#include <QDebug>
+
+int main()
+{
+
+{
+//! [0]
+QString string(QStringLiteral("a string"));
+QStringIterator i(string);
+//! [0]
+
+//! [1]
+// will print 97, 32, 115, 116, etc.;
+// that is, the decimal value of the code points in the Unicode string "a string"
+while (i.hasNext())
+ qDebug() << i.next();
+//! [1]
+}
+
+{
+//! [2]
+QString string(QStringLiteral("𝄞 is the G clef"));
+QStringIterator i(string);
+qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF)
+qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE)
+qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I)
+//! [2]
+}
+
+}
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 10b0d63fb0..64dd544cf0 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -322,6 +322,8 @@ void QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc,
const char *msg, ...) const
{
const QLoggingCategory &cat = (*catFunc)();
+ if (!cat.isDebugEnabled())
+ return;
QMessageLogContext ctxt;
ctxt.copy(context);
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index a5eff7c7ce..cf7ee1b7aa 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -331,8 +331,7 @@
the size of the register). On some architectures where a pointer could be
smaller than the register, the macro is defined above.
- Try our best to define it to a literal, so it can be used in the preprocessor,
- but fall back to sizeof(void*) on practically every 32-bit build.
+ Falls back to QT_POINTER_SIZE if not set explicitly for the platform.
*/
#ifndef Q_PROCESSOR_WORDSIZE
# ifdef __SIZEOF_POINTER__
@@ -341,7 +340,7 @@
# elif defined(_LP64) || defined(__LP64__) || defined(WIN64) || defined(_WIN64)
# define Q_PROCESSOR_WORDSIZE 8
# else
-# define Q_PROCESSOR_WORDSIZE sizeof(void*)
+# define Q_PROCESSOR_WORDSIZE QT_POINTER_SIZE
# endif
#endif
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index de77dd9a6e..5fa346dce5 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -83,9 +83,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
\section1 Default category configuration
- In the default configuration \l isWarningEnabled() and \l isCriticalEnabled()
- will return \c true. \l isDebugEnabled() will return \c true only
- for the \c "default" category.
+ In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
+ \l isCriticalEnabled() will return \c true.
\section1 Changing the configuration of a category
@@ -111,21 +110,20 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
name(0),
- enabledDebug(false),
+ enabledDebug(true),
enabledWarning(true),
enabledCritical(true)
{
Q_UNUSED(d);
Q_UNUSED(placeholder);
- bool isDefaultCategory
+ const bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
+ // normalize "default" category name, so that we can just do
+ // pointer comparison in QLoggingRegistry::updateCategory
if (isDefaultCategory) {
- // normalize default category names, so that we can just do
- // pointer comparison in QLoggingRegistry::updateCategory
name = qtDefaultCategoryName;
- enabledDebug = true;
} else {
name = category;
}
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index a82e6f65f4..fd25ff697e 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -283,9 +283,13 @@ QLoggingRegistry *QLoggingRegistry::instance()
*/
void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
{
- // QLoggingCategory() normalizes all "default" strings
+ // QLoggingCategory() normalizes "default" strings
// to qtDefaultCategoryName
- bool debug = (cat->categoryName() == qtDefaultCategoryName);
+ bool debug = true;
+ char c;
+ if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.'))
+ debug = false;
+
bool warning = true;
bool critical = true;
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 3118034b88..d5d964eaec 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -186,6 +186,8 @@ void QCoreApplicationPrivate::processCommandLineArguments()
continue;
}
QByteArray arg = argv[i];
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
if (arg.startsWith("-qmljsdebugger=")) {
qmljs_debug_arguments = QString::fromLocal8Bit(arg.right(arg.length() - 15));
} else if (arg == "-qmljsdebugger" && i < argc - 1) {
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 03c5b943d6..db5c13157c 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -442,7 +442,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
#ifndef Q_OS_WINRT
CloseHandle(d->handle);
#else
- CloseHandle(d->handle->native_handle());
+ d->handle->detach();
delete d->handle;
#endif
d->handle = 0;
@@ -642,8 +642,6 @@ void QThread::terminate()
TerminateThread(d->handle, 0);
#else // !Q_OS_WINRT
qWarning("QThread::terminate: Terminate is not supported on WinRT");
- CloseHandle(d->handle->native_handle());
- d->handle = 0;
#endif // Q_OS_WINRT
QThreadPrivate::finish(this, false);
}
@@ -683,7 +681,8 @@ bool QThread::wait(unsigned long time)
}
#else // !Q_OS_WINRT
if (d->handle->joinable()) {
- switch (WaitForSingleObjectEx(d->handle->native_handle(), time, FALSE)) {
+ HANDLE handle = d->handle->native_handle();
+ switch (WaitForSingleObjectEx(handle, time, FALSE)) {
case WAIT_OBJECT_0:
ret = true;
d->handle->join();
@@ -712,6 +711,7 @@ bool QThread::wait(unsigned long time)
#ifndef Q_OS_WINRT
CloseHandle(d->handle);
#else
+ d->handle->detach();
delete d->handle;
#endif
d->handle = 0;
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 6d2cba7703..e38a5f569a 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -2208,7 +2208,17 @@ static int qt_timezone()
time_t clock = time(NULL);
struct tm t;
localtime_r(&clock, &t);
- return t.tm_gmtoff;
+ // QTBUG-36080 Workaround for systems without the POSIX timezone
+ // variable. This solution is not very efficient but fixing it is up to
+ // the libc implementations.
+ //
+ // tm_gmtoff has some important differences compared to the timezone
+ // variable:
+ // - It returns the number of seconds east of UTC, and we want the
+ // number of seconds west of UTC.
+ // - It also takes DST into account, so we need to adjust it to always
+ // get the Standard Time offset.
+ return -t.tm_gmtoff + (t.tm_isdst ? SECS_PER_HOUR : 0L);
#else
return timezone;
#endif // Q_OS_WIN
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index f5e25f1de9..9f939dd795 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -54,6 +54,7 @@
#include <qlist.h>
#include "qlocale.h"
#include "qlocale_p.h"
+#include "qstringbuilder.h"
#include "qstringmatcher.h"
#include "qvarlengtharray.h"
#include "qtools_p.h"
@@ -76,6 +77,7 @@
#include "qchar.cpp"
#include "qstringmatcher.cpp"
+#include "qstringiterator_p.h"
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -188,6 +190,16 @@ template <uint MaxCount> struct UnrollTailLoop
return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
}
+
+ template <typename Functor>
+ static inline void exec(int count, Functor code)
+ {
+ /* equivalent to:
+ * for (int i = 0; i < count; ++i)
+ * code(i);
+ */
+ exec(count, 0, [=](int i) -> bool { code(i); return false; }, [](int) { return 0; });
+ }
};
template <> template <typename RetType, typename Functor1, typename Functor2>
inline RetType UnrollTailLoop<0>::exec(int, RetType returnIfExited, Functor1, Functor2, int)
@@ -205,25 +217,29 @@ static void qt_from_latin1(ushort *dst, const char *str, size_t size)
* The same method gives no improvement with NEON.
*/
#if defined(__SSE2__)
- if (size >= 16) {
- int chunkCount = size >> 4; // divided by 16
+ const char *e = str + size;
+ qptrdiff offset = 0;
+
+ // we're going to read str[offset..offset+15] (16 bytes)
+ for ( ; str + offset + 15 < e; offset += 16) {
const __m128i nullMask = _mm_set1_epi32(0);
- for (int i = 0; i < chunkCount; ++i) {
- const __m128i chunk = _mm_loadu_si128((__m128i*)str); // load
- str += 16;
+ const __m128i chunk = _mm_loadu_si128((__m128i*)(str + offset)); // load
- // unpack the first 8 bytes, padding with zeros
- const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
- _mm_storeu_si128((__m128i*)dst, firstHalf); // store
- dst += 8;
+ // unpack the first 8 bytes, padding with zeros
+ const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + offset), firstHalf); // store
- // unpack the last 8 bytes, padding with zeros
- const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
- _mm_storeu_si128((__m128i*)dst, secondHalf); // store
- dst += 8;
- }
- size = size % 16;
+ // unpack the last 8 bytes, padding with zeros
+ const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
+ _mm_storeu_si128((__m128i*)(dst + offset + 8), secondHalf); // store
}
+
+ size = size % 16;
+ dst += offset;
+ str += offset;
+# ifdef Q_COMPILER_LAMBDA
+ return UnrollTailLoop<15>::exec(size, [=](int i) { dst[i] = (uchar)str[i]; });
+# endif
#endif
#if defined(__mips_dsp)
if (size > 20)
@@ -293,61 +309,62 @@ static inline __m128i mergeQuestionMarks(__m128i chunk)
static void qt_to_latin1(uchar *dst, const ushort *src, int length)
{
- if (length) {
#if defined(__SSE2__)
- if (length >= 16) {
- const int chunkCount = length >> 4; // divided by 16
+ uchar *e = dst + length;
+ qptrdiff offset = 0;
- for (int i = 0; i < chunkCount; ++i) {
- __m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
- chunk1 = mergeQuestionMarks(chunk1);
- src += 8;
+ // we're going to write to dst[offset..offset+15] (16 bytes)
+ for ( ; dst + offset + 15 < e; offset += 16) {
+ __m128i chunk1 = _mm_loadu_si128((__m128i*)(src + offset)); // load
+ chunk1 = mergeQuestionMarks(chunk1);
- __m128i chunk2 = _mm_loadu_si128((__m128i*)src); // load
- chunk2 = mergeQuestionMarks(chunk2);
- src += 8;
+ __m128i chunk2 = _mm_loadu_si128((__m128i*)(src + offset + 8)); // load
+ chunk2 = mergeQuestionMarks(chunk2);
- // pack the two vector to 16 x 8bits elements
- const __m128i result = _mm_packus_epi16(chunk1, chunk2);
+ // pack the two vector to 16 x 8bits elements
+ const __m128i result = _mm_packus_epi16(chunk1, chunk2);
+ _mm_storeu_si128((__m128i*)(dst + offset), result); // store
+ }
- _mm_storeu_si128((__m128i*)dst, result); // store
- dst += 16;
- }
- length = length % 16;
- }
+ length = length % 16;
+ dst += offset;
+ src += offset;
+
+# ifdef Q_COMPILER_LAMBDA
+ return UnrollTailLoop<15>::exec(length, [=](int i) { dst[i] = (src[i]>0xff) ? '?' : (uchar) src[i]; });
+# endif
#elif defined(__ARM_NEON__)
- // Refer to the documentation of the SSE2 implementation
- // this use eactly the same method as for SSE except:
- // 1) neon has unsigned comparison
- // 2) packing is done to 64 bits (8 x 8bits component).
- if (length >= 16) {
- const int chunkCount = length >> 3; // divided by 8
- const uint16x8_t questionMark = vdupq_n_u16('?'); // set
- const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set
- for (int i = 0; i < chunkCount; ++i) {
- uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
- src += 8;
-
- const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
- const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
- const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
- chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
- const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing
- vst1_u8(dst, result); // store
- dst += 8;
- }
- length = length % 8;
+ // Refer to the documentation of the SSE2 implementation
+ // this use eactly the same method as for SSE except:
+ // 1) neon has unsigned comparison
+ // 2) packing is done to 64 bits (8 x 8bits component).
+ if (length >= 16) {
+ const int chunkCount = length >> 3; // divided by 8
+ const uint16x8_t questionMark = vdupq_n_u16('?'); // set
+ const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set
+ for (int i = 0; i < chunkCount; ++i) {
+ uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
+ src += 8;
+
+ const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
+ const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
+ const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
+ chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
+ const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing
+ vst1_u8(dst, result); // store
+ dst += 8;
}
+ length = length % 8;
+ }
#endif
#if defined(__mips_dsp)
- qt_toLatin1_mips_dsp_asm(dst, src, length);
+ qt_toLatin1_mips_dsp_asm(dst, src, length);
#else
- while (length--) {
- *dst++ = (*src>0xff) ? '?' : (uchar) *src;
- ++src;
- }
-#endif
+ while (length--) {
+ *dst++ = (*src>0xff) ? '?' : (uchar) *src;
+ ++src;
}
+#endif
}
// Unicode case-insensitive comparison
@@ -1325,21 +1342,13 @@ const QString::Null QString::null = { };
int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
{
- int i = 0;
- const ushort *const e = uc + length;
- while (uc < e) {
- uint u = *uc;
- if (QChar::isHighSurrogate(u) && uc + 1 < e) {
- ushort low = uc[1];
- if (QChar::isLowSurrogate(low)) {
- ++uc;
- u = QChar::surrogateToUcs4(u, low);
- }
- }
- out[i++] = u;
- ++uc;
- }
- return i;
+ int count = 0;
+
+ QStringIterator i(reinterpret_cast<const QChar *>(uc), reinterpret_cast<const QChar *>(uc + length));
+ while (i.hasNext())
+ out[count++] = i.next();
+
+ return count;
}
/*! \fn int QString::toWCharArray(wchar_t *array) const
@@ -4315,8 +4324,12 @@ QByteArray QString::toUtf8_helper(const QString &str)
Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
- UCS-4 is a Unicode codec and is lossless. All characters from this string
- can be encoded in UCS-4. The vector is not null terminated.
+ UCS-4 is a Unicode codec and therefore it is lossless. All characters from
+ this string will be encoded in UCS-4. Any invalid sequence of code units in
+ this string is replaced by the Unicode's replacement character
+ (QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
+
+ The returned vector is not NUL terminated.
\sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray()
*/
@@ -9529,8 +9542,12 @@ QByteArray QStringRef::toUtf8() const
Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
- UCS-4 is a Unicode codec and is lossless. All characters from this string
- can be encoded in UCS-4.
+ UCS-4 is a Unicode codec and therefore it is lossless. All characters from
+ this string will be encoded in UCS-4. Any invalid sequence of code units in
+ this string is replaced by the Unicode's replacement character
+ (QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
+
+ The returned vector is not NUL terminated.
\sa toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec
*/
@@ -9987,4 +10004,13 @@ QString QString::toHtmlEscaped() const
\endlist
*/
+
+/*!
+ \internal
+ */
+void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out)
+{
+ qt_from_latin1(reinterpret_cast<ushort *>(out), a, uint(len));
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 0b7ca1f444..8fb817d519 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -505,6 +505,13 @@ public:
static QString fromUcs4(const uint *, int size = -1);
static QString fromRawData(const QChar *, int size);
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ static QString fromUtf16(const char16_t *str, int size = -1)
+ { return fromUtf16(reinterpret_cast<const ushort *>(str), size); }
+ static QString fromUcs4(const char32_t *str, int size = -1)
+ { return fromUcs4(reinterpret_cast<const uint *>(str), size); }
+#endif
+
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED static inline QString fromAscii(const char *str, int size = -1)
{ return fromLatin1(str, size); }
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 489357f5fd..f0670999d7 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -65,6 +65,7 @@ protected:
{
*out++ = QLatin1Char(a);
}
+ static void appendLatin1To(const char *a, int len, QChar *out);
};
template <typename T> struct QConcatenable {};
@@ -222,7 +223,7 @@ template <> struct QConcatenable<QCharRef> : private QAbstractConcatenable
{ *out++ = QChar(c); }
};
-template <> struct QConcatenable<QLatin1String>
+template <> struct QConcatenable<QLatin1String> : private QAbstractConcatenable
{
typedef QLatin1String type;
typedef QString ConvertTo;
@@ -230,10 +231,8 @@ template <> struct QConcatenable<QLatin1String>
static int size(const QLatin1String a) { return a.size(); }
static inline void appendTo(const QLatin1String a, QChar *&out)
{
- if (a.data()) {
- for (const char *s = a.data(); *s; )
- *out++ = QLatin1Char(*s++);
- }
+ appendLatin1To(a.latin1(), a.size(), out);
+ out += a.size();
}
static inline void appendTo(const QLatin1String a, char *&out)
{
diff --git a/src/corelib/tools/qstringiterator.qdoc b/src/corelib/tools/qstringiterator.qdoc
new file mode 100644
index 0000000000..510d5fbccf
--- /dev/null
+++ b/src/corelib/tools/qstringiterator.qdoc
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QStringIterator
+ \since 5.3
+ \inmodule QtCore
+ \ingroup tools
+
+ \internal
+
+ \brief The QStringIterator class provides a Unicode-aware iterator over QString.
+
+ \reentrant
+
+ QStringIterator is a Java-like, bidirectional, const iterator over the contents of a
+ QString. Unlike QString's own iterators, which manage the individual UTF-16 code units,
+ QStringIterator is Unicode-aware: it will transparently handle the \e{surrogate pairs}
+ that may be present in a QString, and return the individual Unicode code points.
+
+ You can create a QStringIterator that iterates over a given
+ QString by passing the string to the QStringIterator's constructor:
+
+ \snippet code/src_corelib_tools_qstringiterator.cpp 0
+
+ A newly created QStringIterator will point before the first position in the
+ string. It is possible to check whether the iterator can be advanced by
+ calling hasNext(), and actually advance it (and obtain the next code point)
+ by calling next():
+
+ \snippet code/src_corelib_tools_qstringiterator.cpp 1
+
+ Similarly, the hasPrevious() and previous() functions can be used to iterate backwards.
+
+ The peekNext() and peekPrevious() functions will return the code point
+ respectively after and behind the iterator's current position, but unlike
+ next() and previous() they will not move the iterator.
+ Similarly, the advance() and recede() functions will move the iterator
+ respectively after and behind the iterator's current position, but they
+ will not return the code point the iterator has moved through.
+
+ \section1 Unicode handling
+
+ QString and all of its functions work in terms of UTF-16 code units. Unicode code points
+ that fall outside the Basic Multilingual Plane (U+10000 to U+10FFFF) will therefore
+ be represented by \e{surrogate pairs} in a QString, that is, a sequence of two
+ UTF-16 code units that encode a single code point.
+
+ QStringIterator will automatically handle surrogate pairs inside a QString,
+ and return the correctly decoded code point, while also moving the iterator by
+ the right amount of code units to match the decoded code points.
+
+ For instance:
+
+ \snippet code/src_corelib_tools_qstringiterator.cpp 2
+
+ If the iterator is not able to decode the next code point (or the previous
+ one, when iterating backwards), then it will return \c{0xFFFD}, that is,
+ Unicode's replacement character (see QChar::ReplacementCharacter).
+ It is possible to make QStringIterator return another value when it encounters
+ a decoding problem; please refer to the each function documentation for
+ more details.
+
+ \section1 Unchecked iteration
+
+ It is possible to optimize iterating over a QString contents by skipping
+ some checks. This is in general not safe to do, because a QString is allowed
+ to contain malformed UTF-16 data; however, if we can trust a given QString,
+ then we can use the optimized \e{unchecked} functions.
+
+ QStringIterator provides the \e{unchecked} counterparts for next(),
+ peekNext(), advance(), previous(), peekPrevious(), and recede():
+ they're called, respectively,
+ nextUnchecked(), peekNextUnchecked(), advanceUnchecked(),
+ previousUnchecked(), peekPreviousUnchecked(), recedeUnchecked().
+ The counterparts work exactly like the original ones,
+ but they're faster as they're allowed to make certain assumptions about
+ the string contents.
+
+ \note please be extremely careful when using QStringIterator's unchecked functions,
+ as using them on a string containing malformed data leads to undefined behavior.
+
+ \sa QString, QChar
+*/
+
+/*!
+ \fn QStringIterator::QStringIterator(const QString &string)
+
+ Constructs an iterator over the contents of \a string. The iterator will point
+ before the first position in the string.
+
+ The string \a string must remain valid while the iterator is being used.
+*/
+
+/*!
+ \fn QStringIterator::QStringIterator(const QChar *begin, const QChar *end)
+
+ Constructs an iterator which iterates over the range from \a begin to \a end.
+ The iterator will point before \a begin.
+
+ The range from \a begin to \a end must remain valid while the iterator is being used.
+*/
+
+/*!
+ \fn QString::const_iterator QStringIterator::position() const
+
+ Returns the current position of the iterator.
+*/
+
+/*!
+ \fn void QStringIterator::setPosition(QString::const_iterator position)
+
+ Sets the iterator's current position to \a position, which must be inside
+ of the iterable range.
+*/
+
+/*!
+ \fn bool QStringIterator::hasNext() const
+
+ Returns true if the iterator has not reached the end of the valid iterable range
+ and therefore can move forward; false otherwise.
+
+ \sa next()
+*/
+
+/*!
+ \fn void QStringIterator::advance()
+
+ Advances the iterator by one Unicode code point.
+
+ \note calling this function when the iterator is past the end of the iterable range
+ leads to undefined behavior.
+
+ \sa next(), hasNext()
+*/
+
+/*!
+ \fn void QStringIterator::advanceUnchecked()
+
+ Advances the iterator by one Unicode code point.
+
+ \note calling this function when the iterator is past the end of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa advance(), next(), hasNext()
+*/
+
+/*!
+ \fn uint QStringIterator::peekNextUnchecked() const
+
+ Returns the Unicode code point that is immediately after the iterator's current
+ position. The current position is not changed.
+
+ \note calling this function when the iterator is past the end of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa peekNext(), next(), hasNext()
+*/
+
+/*!
+ \fn uint QStringIterator::peekNext(uint invalidAs = QChar::ReplacementCharacter) const
+
+ Returns the Unicode code point that is immediately after the iterator's current
+ position. The current position is not changed.
+
+ If the iterator is not able to decode the UTF-16 data after the iterator's current
+ position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
+ which corresponds to \c{U+FFFD}).
+
+ \note calling this function when the iterator is past the end of the iterable range
+ leads to undefined behavior.
+
+ \sa next(), hasNext()
+*/
+
+/*!
+ \fn uint QStringIterator::nextUnchecked()
+
+ Advances the iterator's current position by one Unicode code point,
+ and returns the Unicode code point that gets pointed by the iterator.
+
+ \note calling this function when the iterator is past the end of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa next(), hasNext()
+*/
+
+/*!
+ \fn uint QStringIterator::next(uint invalidAs = QChar::ReplacementCharacter)
+
+ Advances the iterator's current position by one Unicode code point,
+ and returns the Unicode code point that gets pointed by the iterator.
+
+ If the iterator is not able to decode the UTF-16 data at the iterator's current
+ position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
+ which corresponds to \c{U+FFFD}).
+
+ \note calling this function when the iterator is past the end of the iterable range
+ leads to undefined behavior.
+
+ \sa peekNext(), hasNext()
+*/
+
+
+/*!
+ \fn bool QStringIterator::hasPrevious() const
+
+ Returns true if the iterator is after the beginning of the valid iterable range
+ and therefore can move backwards; false otherwise.
+
+ \sa previous()
+*/
+
+/*!
+ \fn void QStringIterator::recede()
+
+ Moves the iterator back by one Unicode code point.
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ leads to undefined behavior.
+
+ \sa previous(), hasPrevious()
+*/
+
+/*!
+ \fn void QStringIterator::recedeUnchecked()
+
+ Moves the iterator back by one Unicode code point.
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa recede(), previous(), hasPrevious()
+*/
+
+/*!
+ \fn uint QStringIterator::peekPreviousUnchecked() const
+
+ Returns the Unicode code point that is immediately before the iterator's current
+ position. The current position is not changed.
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa previous(), hasPrevious()
+*/
+
+/*!
+ \fn uint QStringIterator::peekPrevious(uint invalidAs = QChar::ReplacementCharacter) const
+
+ Returns the Unicode code point that is immediately before the iterator's current
+ position. The current position is not changed.
+
+ If the iterator is not able to decode the UTF-16 data before the iterator's current
+ position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
+ which corresponds to \c{U+FFFD}).
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ leads to undefined behavior.
+
+ \sa previous(), hasPrevious()
+*/
+
+/*!
+ \fn uint QStringIterator::previousUnchecked()
+
+ Moves the iterator's current position back by one Unicode code point,
+ and returns the Unicode code point that gets pointed by the iterator.
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ or on a QString containing malformed UTF-16 data leads to undefined behavior.
+
+ \sa previous(), hasPrevious()
+*/
+
+/*!
+ \fn uint QStringIterator::previous(uint invalidAs = QChar::ReplacementCharacter)
+
+ Moves the iterator's current position back by one Unicode code point,
+ and returns the Unicode code point that gets pointed by the iterator.
+
+ If the iterator is not able to decode the UTF-16 data at the iterator's current
+ position, this function returns \a invalidAs (by default, QChar::ReplacementCharacter,
+ which corresponds to \c{U+FFFD}).
+
+ \note calling this function when the iterator is before the beginning of the iterable range
+ leads to undefined behavior.
+
+ \sa peekPrevious(), hasPrevious()
+*/
diff --git a/src/corelib/tools/qstringiterator_p.h b/src/corelib/tools/qstringiterator_p.h
new file mode 100644
index 0000000000..c3986f0477
--- /dev/null
+++ b/src/corelib/tools/qstringiterator_p.h
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGITERATOR_H
+#define QSTRINGITERATOR_H
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStringIterator
+{
+ QString::const_iterator i, pos, e;
+
+public:
+ inline explicit QStringIterator(const QString &string)
+ : i(string.constBegin()),
+ pos(string.constBegin()),
+ e(string.constEnd())
+ {
+ }
+
+ inline explicit QStringIterator(const QChar *begin, const QChar *end)
+ : i(begin),
+ pos(begin),
+ e(end)
+ {
+ }
+
+ inline QString::const_iterator position() const
+ {
+ return pos;
+ }
+
+ inline void setPosition(QString::const_iterator position)
+ {
+ Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
+ pos = position;
+ }
+
+ // forward iteration
+
+ inline bool hasNext() const
+ {
+ return pos < e;
+ }
+
+ inline void advance()
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
+ if (Q_LIKELY(pos != e && pos->isLowSurrogate()))
+ ++pos;
+ }
+ }
+
+ inline void advanceUnchecked()
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ if (Q_UNLIKELY((pos++)->isHighSurrogate()))
+ ++pos;
+ }
+
+ inline uint peekNextUnchecked() const
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ if (Q_UNLIKELY(pos->isHighSurrogate()))
+ return QChar::surrogateToUcs4(pos[0], pos[1]);
+
+ return pos->unicode();
+ }
+
+ inline uint peekNext(uint invalidAs = QChar::ReplacementCharacter) const
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ if (Q_UNLIKELY(pos->isSurrogate())) {
+ if (Q_LIKELY(pos->isHighSurrogate())) {
+ const QChar *low = pos + 1;
+ if (Q_LIKELY(low != e && low->isLowSurrogate()))
+ return QChar::surrogateToUcs4(*pos, *low);
+ }
+ return invalidAs;
+ }
+
+ return pos->unicode();
+ }
+
+ inline uint nextUnchecked()
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ const QChar cur = *pos++;
+ if (Q_UNLIKELY(cur.isHighSurrogate()))
+ return QChar::surrogateToUcs4(cur, *pos++);
+ return cur.unicode();
+ }
+
+ inline uint next(uint invalidAs = QChar::ReplacementCharacter)
+ {
+ Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
+
+ const QChar uc = *pos++;
+ if (Q_UNLIKELY(uc.isSurrogate())) {
+ if (Q_LIKELY(uc.isHighSurrogate() && pos < e && pos->isLowSurrogate()))
+ return QChar::surrogateToUcs4(uc, *pos++);
+ return invalidAs;
+ }
+
+ return uc.unicode();
+ }
+
+ // backwards iteration
+
+ inline bool hasPrevious() const
+ {
+ return pos > i;
+ }
+
+ inline void recede()
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
+ const QChar *high = pos - 1;
+ if (Q_LIKELY(high != i - 1 && high->isHighSurrogate()))
+ --pos;
+ }
+ }
+
+ inline void recedeUnchecked()
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ if (Q_UNLIKELY((--pos)->isLowSurrogate()))
+ --pos;
+ }
+
+ inline uint peekPreviousUnchecked() const
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ if (Q_UNLIKELY(pos[-1].isLowSurrogate()))
+ return QChar::surrogateToUcs4(pos[-2], pos[-1]);
+ return pos[-1].unicode();
+ }
+
+ inline uint peekPrevious(uint invalidAs = QChar::ReplacementCharacter) const
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ if (Q_UNLIKELY(pos[-1].isSurrogate())) {
+ if (Q_LIKELY(pos[-1].isLowSurrogate())) {
+ const QChar *high = pos - 2;
+ if (Q_LIKELY(high != i - 1 && high->isHighSurrogate()))
+ return QChar::surrogateToUcs4(*high, pos[-1]);
+ }
+ return invalidAs;
+ }
+
+ return pos[-1].unicode();
+ }
+
+ inline uint previousUnchecked()
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ const QChar cur = *--pos;
+ if (Q_UNLIKELY(cur.isLowSurrogate()))
+ return QChar::surrogateToUcs4(*--pos, cur);
+ return cur.unicode();
+ }
+
+ inline uint previous(uint invalidAs = QChar::ReplacementCharacter)
+ {
+ Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
+
+ const QChar uc = *--pos;
+ if (Q_UNLIKELY(uc.isSurrogate())) {
+ if (Q_LIKELY(uc.isLowSurrogate() && pos > i && pos[-1].isHighSurrogate()))
+ return QChar::surrogateToUcs4(*--pos, uc);
+ return invalidAs;
+ }
+
+ return uc.unicode();
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGITERATOR_H
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index ba995b047d..4ebd6ccd66 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -56,6 +56,7 @@ HEADERS += \
tools/qstack.h \
tools/qstring.h \
tools/qstringbuilder.h \
+ tools/qstringiterator_p.h \
tools/qstringlist.h \
tools/qstringmatcher.h \
tools/qtextboundaryfinder.h \
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index f549a04dfb..48c262ae7a 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1719,7 +1719,7 @@ void QImage::fill(const QColor &color)
if (d->depth == 32) {
uint pixel = color.rgba();
if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied)
- pixel = PREMUL(pixel);
+ pixel = qPremultiply(pixel);
fill((uint) pixel);
} else if (d->format == QImage::Format_RGB16) {
@@ -2204,17 +2204,17 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_RGB32:
//make sure alpha is 255, we depend on it in qdrawhelper for cases
// when image is set as a texture pattern on a qbrush
- ((uint *)s)[x] = uint(255 << 24) | index_or_rgb;
+ ((uint *)s)[x] = 0xff000000 | index_or_rgb;
return;
case Format_ARGB32:
case Format_ARGB32_Premultiplied:
((uint *)s)[x] = index_or_rgb;
return;
case Format_RGB16:
- ((quint16 *)s)[x] = qConvertRgb32To16(INV_PREMUL(index_or_rgb));
+ ((quint16 *)s)[x] = qConvertRgb32To16(qUnpremultiply(index_or_rgb));
return;
case Format_RGBX8888:
- ((uint *)s)[x] = ARGB2RGBA(index_or_rgb | 0xff000000);
+ ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
return;
case Format_RGBA8888:
case Format_RGBA8888_Premultiplied:
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 9b79f4ccc0..e856959d51 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -77,7 +77,7 @@ static const uchar bitflip[256] = {
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
};
-const uchar *qt_get_bitflip_array() // called from QPixmap code
+const uchar *qt_get_bitflip_array()
{
return bitflip;
}
@@ -187,7 +187,7 @@ static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = PREMUL(*src_data);
+ *dest_data = qPremultiply(*src_data);
++src_data;
++dest_data;
}
@@ -304,7 +304,7 @@ static void convert_ARGB_to_RGBA_PM(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const quint32 *end = src_data + src->width;
while (src_data < end) {
- *dest_data = ARGB2RGBA(PREMUL(*src_data));
+ *dest_data = ARGB2RGBA(qPremultiply(*src_data));
++src_data;
++dest_data;
}
@@ -376,7 +376,7 @@ static void convert_RGBA_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const quint32 *end = src_data + src->width;
while (src_data < end) {
- *dest_data = PREMUL(RGBA2ARGB(*src_data));
+ *dest_data = qPremultiply(RGBA2ARGB(*src_data));
++src_data;
++dest_data;
}
@@ -395,7 +395,7 @@ static bool convert_RGBA_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversio
for (int i = 0; i < data->height; ++i) {
const QRgb *end = rgb_data + data->width;
while (rgb_data < end) {
- *rgb_data = PREMUL(RGBA2ARGB(*rgb_data));
+ *rgb_data = qPremultiply(RGBA2ARGB(*rgb_data));
++rgb_data;
}
rgb_data += pad;
@@ -429,7 +429,7 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve
data->colortable[i] = qRgb(i, i, i);
} else {
for (int i = 0; i < data->colortable.size(); ++i)
- data->colortable[i] = PREMUL(data->colortable.at(i));
+ data->colortable[i] = qPremultiply(data->colortable.at(i));
// Fill the rest of the table in case src_data > colortable.size()
const int oldSize = data->colortable.size();
@@ -604,7 +604,7 @@ static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = INV_PREMUL(*src_data);
+ *dest_data = qUnpremultiply(*src_data);
++src_data;
++dest_data;
}
@@ -628,7 +628,7 @@ static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = 0xff000000 | INV_PREMUL(*src_data);
+ *dest_data = 0xff000000 | qUnpremultiply(*src_data);
++src_data;
++dest_data;
}
@@ -652,7 +652,7 @@ static void convert_ARGB_PM_to_RGBx(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = ARGB2RGBA(0xff000000 | INV_PREMUL(*src_data));
+ *dest_data = ARGB2RGBA(0xff000000 | qUnpremultiply(*src_data));
++src_data;
++dest_data;
}
@@ -676,7 +676,7 @@ static void convert_ARGB_PM_to_RGBA(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = ARGB2RGBA(INV_PREMUL(*src_data));
+ *dest_data = ARGB2RGBA(qUnpremultiply(*src_data));
++src_data;
++dest_data;
}
@@ -748,7 +748,7 @@ static void convert_RGBA_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt:
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = INV_PREMUL(RGBA2ARGB(*src_data));
+ *dest_data = qUnpremultiply(RGBA2ARGB(*src_data));
++src_data;
++dest_data;
}
@@ -772,7 +772,7 @@ static void convert_RGBA_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::
for (int i = 0; i < src->height; ++i) {
const QRgb *end = src_data + src->width;
while (src_data < end) {
- *dest_data = 0xff000000 | INV_PREMUL(RGBA2ARGB(*src_data));
+ *dest_data = 0xff000000 | qUnpremultiply(RGBA2ARGB(*src_data));
++src_data;
++dest_data;
}
@@ -862,7 +862,7 @@ static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format f
} else if (format == QImage::Format_ARGB32_Premultiplied) {
// check if the color table has alpha
for (int i = 0; i < colorTable.size(); ++i)
- colorTable[i] = PREMUL(colorTable.at(i));
+ colorTable[i] = qPremultiply(colorTable.at(i));
}
return colorTable;
}
diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp
index 0d6eac4ea2..037846c9aa 100644
--- a/src/gui/image/qimage_sse2.cpp
+++ b/src/gui/image/qimage_sse2.cpp
@@ -94,7 +94,7 @@ bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionF
if (*p < 0x00ffffff)
*p = 0;
else if (*p < 0xff000000)
- *p = PREMUL(*p);
+ *p = qPremultiply(*p);
}
d = reinterpret_cast<__m128i*>(p+pad);
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 4c1b30a6d8..839a7a709f 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -148,7 +148,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color)
m_alpha = true;
}
- uint pixel = PREMUL(color.rgba());
+ uint pixel = qPremultiply(color.rgba());
const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()];
Q_ASSERT(layout->convertFromARGB32PM);
layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0);
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 37259adcd2..1465fea8b9 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -208,7 +208,7 @@ void QRasterPlatformPixmap::fill(const QColor &color)
}
}
}
- pixel = PREMUL(color.rgba());
+ pixel = qPremultiply(color.rgba());
const QPixelLayout *layout = &qPixelLayouts[image.format()];
layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0);
} else {
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 76cebcb00c..f0431ebd9d 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1019,6 +1019,8 @@ void QGuiApplicationPrivate::createPlatformIntegration()
continue;
}
QByteArray arg = argv[i];
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
if (arg == "-platformpluginpath") {
if (++i < argc)
platformPluginPath = QLatin1String(argv[i]);
@@ -1099,6 +1101,8 @@ void QGuiApplicationPrivate::init()
continue;
}
QByteArray arg = argv[i];
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
if (arg == "-plugin") {
if (++i < argc)
pluginList << argv[i];
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index fe29627c5a..2364f465b6 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -127,6 +127,18 @@ QRect QPlatformWindow::geometry() const
return d->rect;
}
+/*!
+ Returns the geometry of a window in 'normal' state
+ (neither maximized, fullscreen nor minimized) for saving geometries to
+ application settings.
+
+ \since 5.3
+*/
+QRect QPlatformWindow::normalGeometry() const
+{
+ return QRect();
+}
+
QMargins QPlatformWindow::frameMargins() const
{
return QMargins();
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 7dfbae036f..0adeb223f1 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -84,6 +84,7 @@ public:
virtual void setGeometry(const QRect &rect);
virtual QRect geometry() const;
+ virtual QRect normalGeometry() const;
virtual QMargins frameMargins() const;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 8ec74fdf31..42f61399d9 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -163,9 +163,7 @@ QWindow::QWindow(QScreen *targetScreen)
//if your applications aborts here, then chances are your creating a QWindow before the
//screen list is populated.
Q_ASSERT(d->screen);
-
- connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*)));
- QGuiApplicationPrivate::window_list.prepend(this);
+ d->init();
}
/*!
@@ -188,8 +186,7 @@ QWindow::QWindow(QWindow *parent)
d->screen = parent->screen();
if (!d->screen)
d->screen = QGuiApplication::primaryScreen();
- connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*)));
- QGuiApplicationPrivate::window_list.prepend(this);
+ d->init();
}
/*!
@@ -214,8 +211,7 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
d->screen = parent->screen();
if (!d->screen)
d->screen = QGuiApplication::primaryScreen();
- connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*)));
- QGuiApplicationPrivate::window_list.prepend(this);
+ d->init();
}
/*!
@@ -233,6 +229,13 @@ QWindow::~QWindow()
destroy();
}
+void QWindowPrivate::init()
+{
+ Q_Q(QWindow);
+ QObject::connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*)));
+ QGuiApplicationPrivate::window_list.prepend(q);
+}
+
/*!
\enum QWindow::Visibility
\since 5.1
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 8ebbf5d508..4305edea51 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -108,6 +108,8 @@ public:
{
}
+ void init();
+
void maybeQuitOnLastWindowClosed();
#ifndef QT_NO_CURSOR
void setCursor(const QCursor *c = 0);
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index d249b855f5..cadba26797 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -31,7 +31,8 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
opengl/qopenglversionfunctions.h \
opengl/qopenglversionfunctionsfactory_p.h \
opengl/qopenglvertexarrayobject.h \
- opengl/qopengldebug.h
+ opengl/qopengldebug.h \
+ opengl/qopengltextureblitter_p.h
SOURCES += opengl/qopengl.cpp \
opengl/qopenglfunctions.cpp \
@@ -51,7 +52,8 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
opengl/qopenglversionfunctions.cpp \
opengl/qopenglversionfunctionsfactory.cpp \
opengl/qopenglvertexarrayobject.cpp \
- opengl/qopengldebug.cpp
+ opengl/qopengldebug.cpp \
+ opengl/qopengltextureblitter.cpp
!wince* {
HEADERS += opengl/qopengltexture.h \
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
index 9c4fbbe013..9c312808a2 100644
--- a/src/gui/opengl/qopenglgradientcache.cpp
+++ b/src/gui/opengl/qopenglgradientcache.cpp
@@ -168,7 +168,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
qreal incr = 1.0 / qreal(size);
qreal fpos = 1.5 * incr;
- colorTable[pos++] = ARGB2RGBA(PREMUL(current_color));
+ colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));
while (fpos <= s.first().first) {
colorTable[pos] = colorTable[pos - 1];
@@ -177,13 +177,13 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
}
if (colorInterpolation)
- current_color = PREMUL(current_color);
+ current_color = qPremultiply(current_color);
for (int i = 0; i < s.size() - 1; ++i) {
qreal delta = 1/(s[i+1].first - s[i].first);
uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
if (colorInterpolation)
- next_color = PREMUL(next_color);
+ next_color = qPremultiply(next_color);
while (fpos < s[i+1].first && pos < size) {
int dist = int(256 * ((fpos - s[i].first) * delta));
@@ -191,7 +191,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
if (colorInterpolation)
colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
else
- colorTable[pos] = ARGB2RGBA(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
++pos;
fpos += incr;
}
@@ -200,7 +200,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
Q_ASSERT(s.size() > 0);
- uint last_color = ARGB2RGBA(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
+ uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 1d16c3ecaa..9a9f277b1b 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -319,15 +319,21 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
return;
case QOpenGLTexture::Target1D:
- for (int level = 0; level < mipLevels; ++level)
- texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
- mipLevelSize(level, dimensions[0]),
- 0,
- QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ if (features.testFlag(QOpenGLTexture::Texture1D)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ 0,
+ QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
+ } else {
+ qWarning("1D textures are not supported");
+ return;
+ }
break;
case QOpenGLTexture::Target1DArray:
- if (features.testFlag(QOpenGLTexture::TextureArrays)) {
+ if (features.testFlag(QOpenGLTexture::Texture1D)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
for (int level = 0; level < mipLevels; ++level)
texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
mipLevelSize(level, dimensions[0]),
@@ -335,7 +341,7 @@ void QOpenGLTexturePrivate::allocateMutableStorage()
0,
QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0);
} else {
- qWarning("Array textures are not supported");
+ qWarning("1D array textures are not supported");
return;
}
break;
@@ -433,16 +439,22 @@ void QOpenGLTexturePrivate::allocateImmutableStorage()
return;
case QOpenGLTexture::Target1D:
- texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
- dimensions[0]);
+ if (features.testFlag(QOpenGLTexture::Texture1D)) {
+ texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0]);
+ } else {
+ qWarning("1D textures are not supported");
+ return;
+ }
break;
case QOpenGLTexture::Target1DArray:
- if (features.testFlag(QOpenGLTexture::TextureArrays)) {
+ if (features.testFlag(QOpenGLTexture::Texture1D)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
dimensions[0], layers);
} else {
- qWarning("Array textures are not supported");
+ qWarning("1D array textures are not supported");
return;
}
break;
@@ -1356,6 +1368,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
\value NPOTTextures Basic support for non-power-of-two textures
\value NPOTTextureRepeat Full support for non-power-of-two textures including texture
repeat modes
+ \value Texture1D Support for the 1 dimensional texture target
*/
/*!
@@ -2427,6 +2440,10 @@ bool QOpenGLTexture::hasFeature(Feature feature)
supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
break;
+ case Texture1D:
+ supported = f.version() >= qMakePair(1, 1);
+ break;
+
case MaxFeatureFlag:
break;
}
diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h
index bb632454ad..0c272456f6 100644
--- a/src/gui/opengl/qopengltexture.h
+++ b/src/gui/opengl/qopengltexture.h
@@ -404,8 +404,9 @@ public:
AnisotropicFiltering = 0x00000400,
NPOTTextures = 0x00000800,
NPOTTextureRepeat = 0x00001000,
+ Texture1D = 0x00002000,
#ifndef Q_QDOC
- MaxFeatureFlag = 0x00002000
+ MaxFeatureFlag = 0x00004000
#endif
};
Q_DECLARE_FLAGS(Features, Feature)
diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp
new file mode 100644
index 0000000000..1fbdd20207
--- /dev/null
+++ b/src/gui/opengl/qopengltextureblitter.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltextureblitter_p.h"
+
+#include <QtGui/QOpenGLBuffer>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLVertexArrayObject>
+#include <QtGui/QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+static const char vertex_shader150[] =
+ "#version 150 core\n"
+ "in vec3 vertexCoord;"
+ "in vec2 textureCoord;"
+ "out vec2 uv;"
+ "uniform mat4 vertexTransform;"
+ "uniform mat3 textureTransform;"
+ "void main() {"
+ " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
+ " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
+ "}";
+
+static const char fragment_shader150[] =
+ "#version 150 core\n"
+ "in vec2 uv;"
+ "out vec4 fragcolor;"
+ "uniform sampler2D textureSampler;"
+ "uniform bool swizzle;"
+ "void main() {"
+ " if (swizzle) {"
+ " fragcolor = texture(textureSampler, uv).bgra;"
+ " } else {"
+ " fragcolor = texture(textureSampler,uv);"
+ " }"
+ "}";
+
+static const char vertex_shader[] =
+ "attribute highp vec3 vertexCoord;"
+ "attribute highp vec2 textureCoord;"
+ "varying highp vec2 uv;"
+ "uniform highp mat4 vertexTransform;"
+ "uniform highp mat3 textureTransform;"
+ "void main() {"
+ " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
+ " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
+ "}";
+
+static const char fragment_shader[] =
+ "varying highp vec2 uv;"
+ "uniform sampler2D textureSampler;"
+ "uniform bool swizzle;"
+ "void main() {"
+ " if (swizzle) {"
+ " gl_FragColor = texture2D(textureSampler, uv).bgra;"
+ " } else {"
+ " gl_FragColor = texture2D(textureSampler,uv);"
+ " }"
+ "}";
+
+static const GLfloat vertex_buffer_data[] = {
+ -1,-1, 0,
+ -1, 1, 0,
+ 1,-1, 0,
+ -1, 1, 0,
+ 1,-1, 0,
+ 1, 1, 0
+};
+
+static const GLfloat texture_buffer_data[] = {
+ 0, 0,
+ 0, 1,
+ 1, 0,
+ 0, 1,
+ 1, 0,
+ 1, 1
+};
+
+class TextureBinder
+{
+public:
+ TextureBinder(GLuint textureId)
+ {
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ }
+ ~TextureBinder()
+ {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+};
+
+class QOpenGLTextureBlitterPrivate
+{
+public:
+ enum TextureMatrixUniform {
+ User,
+ Identity,
+ IdentityFlipped
+ };
+
+ QOpenGLTextureBlitterPrivate()
+ : program(0)
+ , vertexCoordAttribPos(0)
+ , vertexTransformUniformPos(0)
+ , textureCoordAttribPos(0)
+ , textureTransformUniformPos(0)
+ , swizzle(false)
+ , swizzleOld(false)
+ , textureMatrixUniformState(User)
+ , vao(new QOpenGLVertexArrayObject())
+ { }
+
+ void blit(GLuint texture, const QMatrix4x4 &vertexTransform, const QMatrix3x3 &textureTransform);
+ void blit(GLuint texture, const QMatrix4x4 &vertexTransform, QOpenGLTextureBlitter::Origin origin);
+
+ void prepareProgram(const QMatrix4x4 &vertexTransform)
+ {
+ vertexBuffer.bind();
+ program->setAttributeBuffer(vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
+ program->enableAttributeArray(vertexCoordAttribPos);
+ vertexBuffer.release();
+
+ program->setUniformValue(vertexTransformUniformPos, vertexTransform);
+
+ textureBuffer.bind();
+ program->setAttributeBuffer(textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
+ program->enableAttributeArray(textureCoordAttribPos);
+ textureBuffer.release();
+
+ if (swizzle != swizzleOld) {
+ program->setUniformValue(swizzleUniformPos, swizzle);
+ swizzleOld = swizzle;
+ }
+ }
+
+ QOpenGLBuffer vertexBuffer;
+ QOpenGLBuffer textureBuffer;
+ QScopedPointer<QOpenGLShaderProgram> program;
+ GLuint vertexCoordAttribPos;
+ GLuint vertexTransformUniformPos;
+ GLuint textureCoordAttribPos;
+ GLuint textureTransformUniformPos;
+ GLuint swizzleUniformPos;
+ bool swizzle;
+ bool swizzleOld;
+ TextureMatrixUniform textureMatrixUniformState;
+ QScopedPointer<QOpenGLVertexArrayObject> vao;
+};
+
+void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
+ const QMatrix4x4 &vertexTransform,
+ const QMatrix3x3 &textureTransform)
+{
+ TextureBinder binder(texture);
+ prepareProgram(vertexTransform);
+
+ program->setUniformValue(textureTransformUniformPos, textureTransform);
+ textureMatrixUniformState = User;
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
+ const QMatrix4x4 &vertexTransform,
+ QOpenGLTextureBlitter::Origin origin)
+{
+ TextureBinder binder(texture);
+ prepareProgram(vertexTransform);
+
+ if (origin == QOpenGLTextureBlitter::OriginTopLeft) {
+ if (textureMatrixUniformState != IdentityFlipped) {
+ QMatrix3x3 flipped;
+ flipped(1,1) = -1;
+ program->setUniformValue(textureTransformUniformPos, flipped);
+ textureMatrixUniformState = IdentityFlipped;
+ }
+ } else if (textureMatrixUniformState != Identity) {
+ program->setUniformValue(textureTransformUniformPos, QMatrix3x3());
+ textureMatrixUniformState = Identity;
+ }
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+QOpenGLTextureBlitter::QOpenGLTextureBlitter()
+ : d_ptr(new QOpenGLTextureBlitterPrivate)
+{
+}
+
+QOpenGLTextureBlitter::~QOpenGLTextureBlitter()
+{
+}
+
+bool QOpenGLTextureBlitter::create()
+{
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext)
+ return false;
+
+ Q_D(QOpenGLTextureBlitter);
+
+ d->vao->create();
+ d->vao->bind();
+
+ if (d->program)
+ return true;
+
+ d->program.reset(new QOpenGLShaderProgram());
+
+ QSurfaceFormat format = currentContext->format();
+
+ if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) {
+ d->program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader150);
+ d->program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader150);
+ } else {
+ d->program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader);
+ d->program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader);
+ }
+ d->program->link();
+ if (!d->program->isLinked()) {
+ qWarning() << Q_FUNC_INFO << "Could not link shader program:\n" << d->program->log();
+ return false;
+ }
+
+ d->program->bind();
+
+ d->vertexBuffer.create();
+ d->vertexBuffer.bind();
+ d->vertexBuffer.allocate(vertex_buffer_data, sizeof(vertex_buffer_data) * sizeof(vertex_buffer_data[0]));
+ d->vertexBuffer.release();
+
+ d->textureBuffer.create();
+ d->textureBuffer.bind();
+ d->textureBuffer.allocate(texture_buffer_data, sizeof(texture_buffer_data) * sizeof(texture_buffer_data[0]));
+ d->textureBuffer.release();
+
+ d->vertexCoordAttribPos = d->program->attributeLocation("vertexCoord");
+ d->vertexTransformUniformPos = d->program->uniformLocation("vertexTransform");
+ d->textureCoordAttribPos = d->program->attributeLocation("textureCoord");
+ d->textureTransformUniformPos = d->program->uniformLocation("textureTransform");
+ d->swizzleUniformPos = d->program->uniformLocation("swizzle");
+
+ d->program->setUniformValue(d->swizzleUniformPos,false);
+
+ d->vao->release();
+
+ return true;
+}
+
+void QOpenGLTextureBlitter::destroy()
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->program.reset();
+ d->vertexBuffer.destroy();
+ d->textureBuffer.destroy();
+ d->vao.reset();
+}
+
+void QOpenGLTextureBlitter::bind()
+{
+ Q_D(QOpenGLTextureBlitter);
+
+ d->vao->bind();
+
+ d->program->bind();
+
+ d->vertexBuffer.bind();
+ d->program->setAttributeBuffer(d->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
+ d->program->enableAttributeArray(d->vertexCoordAttribPos);
+ d->vertexBuffer.release();
+
+ d->textureBuffer.bind();
+ d->program->setAttributeBuffer(d->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
+ d->program->enableAttributeArray(d->textureCoordAttribPos);
+ d->textureBuffer.release();
+}
+
+void QOpenGLTextureBlitter::release()
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->program->release();
+ d->vao->release();
+}
+
+void QOpenGLTextureBlitter::setSwizzleRB(bool swizzle)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->swizzle = swizzle;
+}
+
+void QOpenGLTextureBlitter::blit(GLuint texture,
+ const QMatrix4x4 &targetTransform,
+ Origin sourceOrigin)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->blit(texture,targetTransform, sourceOrigin);
+}
+
+void QOpenGLTextureBlitter::blit(GLuint texture,
+ const QMatrix4x4 &targetTransform,
+ const QMatrix3x3 &sourceTransform)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->blit(texture, targetTransform, sourceTransform);
+}
+
+QMatrix4x4 QOpenGLTextureBlitter::targetTransform(const QRectF &target,
+ const QRect &viewport,
+ Origin origin)
+{
+ qreal x_scale = target.size().width() / viewport.width();
+ qreal y_scale = target.size().height() / viewport.height();
+
+ const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();
+ qreal x_translate = ((relative_to_viewport.x() / viewport.width()) + (x_scale / 2)) * 2 - 1;
+ qreal y_translate = ((relative_to_viewport.y() / viewport.height()) + (y_scale / 2)) * 2 - 1;
+
+ if (origin == OriginTopLeft) {
+ y_translate = -y_translate;
+ }
+
+ QMatrix4x4 vertexMatrix;
+
+ vertexMatrix.translate(x_translate, y_translate);
+ vertexMatrix.scale(x_scale, y_scale);
+ return vertexMatrix;
+}
+
+QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(const QRectF &subTexture,
+ const QSize &textureSize,
+ Origin origin)
+{
+ qreal x_scale = subTexture.width() / textureSize.width();
+ qreal y_scale = subTexture.height() / textureSize.height();
+
+ const QPointF topLeft = subTexture.topLeft();
+ qreal x_translate = topLeft.x() / textureSize.width();
+ qreal y_translate = topLeft.y() / textureSize.height();
+
+ if (origin == OriginTopLeft) {
+ y_translate += (y_translate * 2) + y_scale;
+ y_scale = y_scale - 1;
+ }
+
+ QMatrix3x3 matrix;
+ matrix(0,2) = x_translate;
+ matrix(1,2) = y_translate;
+
+ matrix(0,0) = x_scale;
+ matrix(1,1) = y_scale;
+
+ return matrix;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengltextureblitter_p.h b/src/gui/opengl/qopengltextureblitter_p.h
new file mode 100644
index 0000000000..5164d8630e
--- /dev/null
+++ b/src/gui/opengl/qopengltextureblitter_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLTEXTUREBLITTER_P_H
+#define QOPENGLTEXTUREBLITTER_P_H
+
+#include <QtGui/qopengl.h>
+#include <QtGui/QMatrix3x3>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLTextureBlitterPrivate;
+
+
+class Q_GUI_EXPORT QOpenGLTextureBlitter
+{
+public:
+ QOpenGLTextureBlitter();
+ ~QOpenGLTextureBlitter();
+
+ enum Origin {
+ OriginBottomLeft,
+ OriginTopLeft
+ };
+
+ bool create();
+ void destroy();
+
+ void bind();
+ void release();
+
+ void setSwizzleRB(bool swizzle);
+
+ void blit(GLuint texture, const QMatrix4x4 &targetTransform, Origin sourceOrigin);
+ void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform);
+
+ static QMatrix4x4 targetTransform(const QRectF &target, const QRect &viewport, Origin origin);
+ static QMatrix3x3 sourceTransform(const QRectF &subTexture, const QSize &textureSize, Origin origin);
+
+private:
+ Q_DISABLE_COPY(QOpenGLTextureBlitter);
+ Q_DECLARE_PRIVATE(QOpenGLTextureBlitter);
+ QScopedPointer<QOpenGLTextureBlitterPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif //QOPENGLTEXTUREBLITTER_P_H
diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp
index 4da9b3f164..4f8762483f 100644
--- a/src/gui/opengl/qopengltexturehelper.cpp
+++ b/src/gui/opengl/qopengltexturehelper.cpp
@@ -119,15 +119,6 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
CompressedTextureImage1D = &QOpenGLTextureHelper::qt_CompressedTextureImage1D;
CompressedTextureImage2D = &QOpenGLTextureHelper::qt_CompressedTextureImage2D;
CompressedTextureImage3D = &QOpenGLTextureHelper::qt_CompressedTextureImage3D;
-#if defined(QT_OPENGL_ES_2)
- if (context->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"))) {
- TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexImage3DOES")));
- TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3DOES")));
- CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3DOES")));
- CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3DOES")));
- }
-#endif
-
#if !defined(QT_OPENGL_ES_2)
}
#endif
@@ -148,6 +139,9 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
}
#endif
+ // wglGetProcAddress should not be used to (and indeed will not) load OpenGL <= 1.1 functions.
+ // Hence, we resolve them "the hard way"
+
#if defined(Q_OS_WIN) && !defined(QT_OPENGL_ES_2)
HMODULE handle = GetModuleHandleA("opengl32.dll");
@@ -200,18 +194,30 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
TexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage1D")));
#endif
- // OpenGL 1.2
- TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexImage3D")));
- TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3D")));
+#if defined(QT_OPENGL_ES_2)
+ if (context->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"))) {
+ TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexImage3DOES")));
+ TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3DOES")));
+ CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3DOES")));
+ CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3DOES")));
+ } else
+#endif
+ {
+ // OpenGL 1.2
+ TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexImage3D")));
+ TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3D")));
+
+ // OpenGL 1.3
+ CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3D")));
+ CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3D")));
+ }
// OpenGL 1.3
GetCompressedTexImage = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glGetCompressedTexImage")));
CompressedTexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage1D")));
CompressedTexSubImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage2D")));
- CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3D")));
CompressedTexImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage1D")));
CompressedTexImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage2D")));
- CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3D")));
ActiveTexture = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress(QByteArrayLiteral("glActiveTexture")));
// OpenGL 3.0
diff --git a/src/gui/opengl/qopengltexturehelper_p.h b/src/gui/opengl/qopengltexturehelper_p.h
index 1cb2592a42..cce0c092fd 100644
--- a/src/gui/opengl/qopengltexturehelper_p.h
+++ b/src/gui/opengl/qopengltexturehelper_p.h
@@ -695,7 +695,9 @@ public:
}
private:
- // Typedefs and pointers to member functions used to switch between EXT_direct_state_access and our own emulated DSA
+ // Typedefs and pointers to member functions used to switch between EXT_direct_state_access and our own emulated DSA.
+ // The argument match the corresponding GL function, but there's an extra "GLenum bindingTarget" which gets used with
+ // the DSA emulation -- it contains the right GL_BINDING_TEXTURE_X to use.
typedef void (QOpenGLTextureHelper::*TextureParameteriMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param);
typedef void (QOpenGLTextureHelper::*TextureParameterivMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params);
typedef void (QOpenGLTextureHelper::*TextureParameterfMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param);
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 706273c151..b9d3ca888e 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -2499,6 +2499,41 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
}
#endif // QT_NO_DATASTREAM
+// A table of precalculated results of 0x00ff00ff/alpha use by qUnpremultiply:
+const uint qt_inv_premul_factor[256] = {
+ 0, 16711935, 8355967, 5570645, 4177983, 3342387, 2785322, 2387419,
+ 2088991, 1856881, 1671193, 1519266, 1392661, 1285533, 1193709, 1114129,
+ 1044495, 983055, 928440, 879575, 835596, 795806, 759633, 726605,
+ 696330, 668477, 642766, 618960, 596854, 576273, 557064, 539094,
+ 522247, 506422, 491527, 477483, 464220, 451673, 439787, 428511,
+ 417798, 407608, 397903, 388649, 379816, 371376, 363302, 355573,
+ 348165, 341059, 334238, 327685, 321383, 315319, 309480, 303853,
+ 298427, 293191, 288136, 283253, 278532, 273966, 269547, 265268,
+ 261123, 257106, 253211, 249431, 245763, 242201, 238741, 235379,
+ 232110, 228930, 225836, 222825, 219893, 217038, 214255, 211543,
+ 208899, 206320, 203804, 201348, 198951, 196611, 194324, 192091,
+ 189908, 187774, 185688, 183647, 181651, 179698, 177786, 175915,
+ 174082, 172287, 170529, 168807, 167119, 165464, 163842, 162251,
+ 160691, 159161, 157659, 156186, 154740, 153320, 151926, 150557,
+ 149213, 147893, 146595, 145321, 144068, 142837, 141626, 140436,
+ 139266, 138115, 136983, 135869, 134773, 133695, 132634, 131590,
+ 130561, 129549, 128553, 127572, 126605, 125653, 124715, 123792,
+ 122881, 121984, 121100, 120229, 119370, 118524, 117689, 116866,
+ 116055, 115254, 114465, 113686, 112918, 112160, 111412, 110675,
+ 109946, 109228, 108519, 107818, 107127, 106445, 105771, 105106,
+ 104449, 103800, 103160, 102527, 101902, 101284, 100674, 100071,
+ 99475, 98887, 98305, 97730, 97162, 96600, 96045, 95496,
+ 94954, 94417, 93887, 93362, 92844, 92331, 91823, 91322,
+ 90825, 90334, 89849, 89368, 88893, 88422, 87957, 87497,
+ 87041, 86590, 86143, 85702, 85264, 84832, 84403, 83979,
+ 83559, 83143, 82732, 82324, 81921, 81521, 81125, 80733,
+ 80345, 79961, 79580, 79203, 78829, 78459, 78093, 77729,
+ 77370, 77013, 76660, 76310, 75963, 75619, 75278, 74941,
+ 74606, 74275, 73946, 73620, 73297, 72977, 72660, 72346,
+ 72034, 71725, 71418, 71114, 70813, 70514, 70218, 69924,
+ 69633, 69344, 69057, 68773, 68491, 68211, 67934, 67659,
+ 67386, 67116, 66847, 66581, 66317, 66055, 65795, 65537
+};
/*****************************************************************************
QColor global functions (documentation only)
@@ -2581,6 +2616,26 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
*/
/*!
+ \fn QRgb qPremultiply(QRgb rgb)
+ \since 5.3
+ \relates QColor
+
+ Converts an unpremultiplied ARGB quadruplet \a rgb into a premultiplied ARGB quadruplet.
+
+ \sa qUnpremultiply()
+*/
+
+/*!
+ \fn QRgb qUnpremultiply(QRgb rgb)
+ \since 5.3
+ \relates QColor
+
+ Converts a premultiplied ARGB quadruplet \a rgb into an unpremultiplied ARGB quadruplet.
+
+ \sa qPremultiply()
+*/
+
+/*!
\fn QColor QColor::convertTo(Spec colorSpec) const
Creates a copy of \e this color in the format specified by \a colorSpec.
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 1851734bbc..52a6b5d211 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -255,7 +255,7 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *
Q_CONSTEXPR uchar blueRightShift = 8 - blueWidth<Format>();
for (int i = 0; i < count; ++i) {
- const uint color = INV_PREMUL(src[i]);
+ const uint color = qUnpremultiply(src[i]);
const uint red = ((color >> redRightShift) & redMask) << redShift<Format>();
const uint green = ((color >> greenRightShift) & greenMask) << greenShift<Format>();
const uint blue = ((color >> blueRightShift) & blueMask) << blueShift<Format>();
@@ -387,7 +387,7 @@ static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src,
red = (red << redLeftShift) | (red >> redRightShift);
green = (green << greenLeftShift) | (green >> greenRightShift);
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = PREMUL((alpha << 24) | (red << 16) | (green << 8) | blue);
+ buffer[i] = qPremultiply((alpha << 24) | (red << 16) | (green << 8) | blue);
}
}
return buffer;
@@ -446,7 +446,7 @@ static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src
if (!layout->premultiplied) {
for (int i = 0; i < count; ++i)
- buffer[i] = INV_PREMUL(src[i]);
+ buffer[i] = qUnpremultiply(src[i]);
src = buffer;
}
for (int i = 0; i < count; ++i) {
@@ -505,7 +505,7 @@ static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qConvertRgb32To16(INV_PREMUL(src[i]));
+ buffer[i] = qConvertRgb32To16(qUnpremultiply(src[i]));
return buffer;
}
#endif
@@ -515,7 +515,7 @@ static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint
const QPixelLayout *, const QRgb *clut)
{
for (int i = 0; i < count; ++i)
- buffer[i] = PREMUL(clut[src[i]]);
+ buffer[i] = qPremultiply(clut[src[i]]);
return buffer;
}
@@ -529,7 +529,7 @@ static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = PREMUL(src[i]);
+ buffer[i] = qPremultiply(src[i]);
return buffer;
}
@@ -545,7 +545,7 @@ static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uin
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = PREMUL(RGBA2ARGB(src[i]));
+ buffer[i] = qPremultiply(RGBA2ARGB(src[i]));
return buffer;
}
@@ -553,7 +553,7 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = INV_PREMUL(src[i]);
+ buffer[i] = qUnpremultiply(src[i]);
return buffer;
}
@@ -569,7 +569,7 @@ static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const u
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(INV_PREMUL(src[i]));
+ buffer[i] = ARGB2RGBA(qUnpremultiply(src[i]));
return buffer;
}
@@ -585,7 +585,7 @@ static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(0xff000000 | INV_PREMUL(src[i]));
+ buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i]));
return buffer;
}
@@ -853,9 +853,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
*/
static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf)
{
- QRgb color_0 = PREMUL(rbuf->destColor0);
- QRgb color_1 = PREMUL(rbuf->destColor1);
- color = PREMUL(color);
+ QRgb color_0 = qPremultiply(rbuf->destColor0);
+ QRgb color_1 = qPremultiply(rbuf->destColor1);
+ color = qPremultiply(color);
int r = qRed(color);
int g = qGreen(color);
@@ -6250,7 +6250,7 @@ static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer,
quint32 color)
{
qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()),
- INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine());
+ qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine());
}
static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer,
@@ -6266,7 +6266,7 @@ static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer,
quint32 color)
{
qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()),
- ARGB2RGBA(INV_PREMUL(color)), x, y, width, height, rasterBuffer->bytesPerLine());
+ ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine());
}
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 0f98b07229..bbeb73f0af 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -599,14 +599,6 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
return (uint(t)) | (uint(t >> 24));
}
-static Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
- t &= 0x000000ff00ff00ff;
- return (uint(t)) | (uint(t >> 24)) | (a << 24);
-}
-
#else // 32-bit versions
static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
@@ -639,20 +631,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
# pragma pop
#endif
-static Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- uint t = (x & 0xff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
- t &= 0xff00ff;
-
- x = ((x >> 8) & 0xff) * a;
- x = (x + ((x >> 8) & 0xff) + 0x80);
- x &= 0xff00;
- x |= t | (a << 24);
- return x;
-}
#endif
+
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
@@ -691,17 +672,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
return t;
}
-static Q_ALWAYS_INLINE uint INV_PREMUL(uint p) {
- const uint alpha = qAlpha(p);
- if (alpha == 255)
- return p;
- if (alpha == 0)
- return 0;
- // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
- const uint invAlpha = 0x00ff00ffU / alpha;
- // We add 0x8000 to get even rounding. The rounding also ensures that PREMUL(INV_PREMUL(p)) == p for all p.
- return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha);
-}
+// FIXME: Remove when all Qt modules have stopped using PREMUL and INV_PREMUL
+#define PREMUL(x) qPremultiply(x)
+#define INV_PREMUL(p) qUnpremultiply(p)
struct quint24 {
quint24(uint value);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index bdd0d9cd4c..9a2e49618c 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1823,7 +1823,7 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
+ d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
if ((d->solid_color_filler.solid.color & 0xff000000) == 0
&& s->composition_mode == QPainter::CompositionMode_SourceOver) {
return;
@@ -2272,7 +2272,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
| ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00);
break;
default:
- d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity));
+ d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity));
break;
}
@@ -3662,7 +3662,7 @@ QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB);
QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied);
- QRgb fg = PREMUL(color.rgba());
+ QRgb fg = qPremultiply(color.rgba());
QRgb bg = 0;
int height = sourceImage.height();
@@ -3702,8 +3702,8 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
- destColor0 = PREMUL(image->colorTable()[0]);
- destColor1 = PREMUL(image->colorTable()[1]);
+ destColor0 = qPremultiply(image->colorTable()[0]);
+ destColor1 = qPremultiply(image->colorTable()[1]);
}
return format;
@@ -4260,8 +4260,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
}
if (colorInterpolation) {
- first_color = PREMUL(first_color);
- second_color = PREMUL(second_color);
+ first_color = qPremultiply(first_color);
+ second_color = qPremultiply(second_color);
}
int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1));
@@ -4282,7 +4282,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = first_color;
else
- colorTable[i] = PREMUL(first_color);
+ colorTable[i] = qPremultiply(first_color);
}
if (i < second_index) {
@@ -4311,7 +4311,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = color;
else
- colorTable[i] = PREMUL(color);
+ colorTable[i] = qPremultiply(color);
}
}
@@ -4319,7 +4319,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = second_color;
else
- colorTable[i] = PREMUL(second_color);
+ colorTable[i] = qPremultiply(second_color);
}
return;
@@ -4327,7 +4327,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
if (stopCount == 1) {
- current_color = PREMUL(current_color);
+ current_color = qPremultiply(current_color);
for (int i = 0; i < size; ++i)
colorTable[i] = current_color;
return;
@@ -4344,7 +4344,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1)
// Up to first point
- colorTable[pos++] = PREMUL(current_color);
+ colorTable[pos++] = qPremultiply(current_color);
while (dpos <= begin_pos) {
colorTable[pos] = colorTable[pos - 1];
++pos;
@@ -4366,8 +4366,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity);
if (colorInterpolation) {
- current_color = PREMUL(current_color);
- next_color = PREMUL(next_color);
+ current_color = qPremultiply(current_color);
+ next_color = qPremultiply(next_color);
}
qreal diff = stops[current_stop+1].first - stops[current_stop].first;
@@ -4384,7 +4384,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
else
- colorTable[pos] = PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+ colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
++pos;
dpos += incr;
@@ -4408,8 +4408,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation) {
if (skip != 1)
- current_color = PREMUL(current_color);
- next_color = PREMUL(next_color);
+ current_color = qPremultiply(current_color);
+ next_color = qPremultiply(next_color);
}
qreal diff = stops[current_stop+1].first - stops[current_stop].first;
@@ -4421,7 +4421,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
}
// After last point
- current_color = PREMUL(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity));
+ current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity));
while (pos < size - 1) {
colorTable[pos] = current_color;
++pos;
@@ -4455,7 +4455,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
type = Solid;
QColor c = qbrush_color(brush);
QRgb rgba = c.rgba();
- solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha));
+ solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha));
if ((solid.color & 0xff000000) == 0
&& compositionMode == QPainter::CompositionMode_SourceOver) {
type = None;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 2944130eaa..1fc044aa44 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5845,11 +5845,8 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
int numGlyphs = len;
QVarLengthGlyphLayoutArray glyphs(len);
QFontEngine *fontEngine = d->state->font.d->engineForScript(QChar::Script_Common);
- if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
- glyphs.resize(numGlyphs);
- if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
- Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
- }
+ if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
+ Q_UNREACHABLE();
QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
drawTextItem(p, gf);
diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h
index 3c2bc5b97a..d8e19302d1 100644
--- a/src/gui/painting/qrgb.h
+++ b/src/gui/painting/qrgb.h
@@ -43,6 +43,7 @@
#define QRGB_H
#include <QtCore/qglobal.h>
+#include <QtCore/qprocessordetection.h>
QT_BEGIN_NAMESPACE
@@ -79,6 +80,48 @@ inline Q_DECL_CONSTEXPR int qGray(QRgb rgb) // convert RGB to gra
inline Q_DECL_CONSTEXPR bool qIsGray(QRgb rgb)
{ return qRed(rgb) == qGreen(rgb) && qRed(rgb) == qBlue(rgb); }
+
+#if Q_PROCESSOR_WORDSIZE == 8 // 64-bit version
+inline QRgb qPremultiply(QRgb x)
+{
+ const uint a = qAlpha(x);
+ quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
+ t &= 0x000000ff00ff00ff;
+ return (uint(t)) | (uint(t >> 24)) | (a << 24);
+}
+#else // 32-bit version
+inline QRgb qPremultiply(QRgb x)
+{
+ const uint a = qAlpha(x);
+ uint t = (x & 0xff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a;
+ x = (x + ((x >> 8) & 0xff) + 0x80);
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+#endif
+
+Q_GUI_EXPORT extern const uint qt_inv_premul_factor[];
+
+inline QRgb qUnpremultiply(QRgb p)
+{
+ const uint alpha = qAlpha(p);
+ // Alpha 255 and 0 are the two most common values, which makes them beneficial to short-cut.
+ if (alpha == 255)
+ return p;
+ if (alpha == 0)
+ return 0;
+ // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
+ const uint invAlpha = qt_inv_premul_factor[alpha];
+ // We add 0x8000 to get even rounding. The rounding also ensures that qPremultiply(qUnpremultiply(p)) == p for all p.
+ return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha);
+}
+
QT_END_NAMESPACE
#endif // QRGB_H
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index e584b66a25..f2b88c4692 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -739,13 +739,19 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
if (!fe)
return false;
- QGlyphLayout glyphs;
+ const QChar uc(QLatin1Char('O'));
+
glyph_t glyph;
- glyphs.glyphs = &glyph;
+
+ QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
int numGlyphs = 1;
- QChar uc = QLatin1Char('O');
- fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly);
+
+ if (!fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(numGlyphs == 1);
+
QImage im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
Q_ASSERT(fe->ref.load() == 0);
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index f2951611ff..12761d0d3e 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2533,7 +2533,9 @@ bool QFontInfo::fixedPitch() const
QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
QGlyphLayoutArray<2> g;
int l = 2;
- engine->stringToCMap(ch, 2, &g, &l, 0);
+ if (!engine->stringToCMap(ch, 2, &g, &l, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(l == 2);
engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
engine->fontDef.fixedPitchComputed = true;
}
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 708b8cbd58..9986ef6c60 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -167,8 +167,6 @@ private:
friend class QFontPrivate;
friend class QFontDialog;
friend class QFontDialogPrivate;
- friend class QFontEngineMultiXLFD;
- friend class QFontEngineMultiQWS;
friend class QFontEngineMultiQPA;
QFontDatabasePrivate *d;
diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp
index 6f4971e267..1972f5d58c 100644
--- a/src/gui/text/qfontdatabase_qpa.cpp
+++ b/src/gui/text/qfontdatabase_qpa.cpp
@@ -182,10 +182,17 @@ QFontEngine *loadSingleEngine(int script,
QFontCache::Key key(def,script);
QFontEngine *engine = QFontCache::instance()->findEngine(key);
if (!engine) {
- engine = pfdb->fontEngine(def, QChar::Script(script), size->handle);
+ engine = pfdb->fontEngine(def, size->handle);
if (engine) {
- QFontCache::Key key(def,script);
- QFontCache::instance()->instance()->insertEngine(key,engine);
+ // Also check for OpenType tables when using complex scripts
+ if (!engine->supportsScript(QChar::Script(script))) {
+ qWarning(" OpenType support missing for script %d", script);
+ if (engine->ref.load() == 0)
+ delete engine;
+ return 0;
+ }
+
+ QFontCache::instance()->insertEngine(key, engine);
}
}
return engine;
@@ -221,10 +228,10 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
pfMultiEngine->setFallbackFamiliesList(fallbacks);
engine = pfMultiEngine;
- // Cache Multi font engine as well in case we got the FT single
+ // Cache Multi font engine as well in case we got the single
// font engine when we are actually looking for a Multi one
QFontCache::Key key(request, script, 1);
- QFontCache::instance()->instance()->insertEngine(key, engine);
+ QFontCache::instance()->insertEngine(key, engine);
}
return engine;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 71866119d4..14ce5d2396 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -48,6 +48,7 @@
#include "qvarlengtharray.h"
#include <qmath.h>
#include <qendian.h>
+#include <private/qstringiterator_p.h>
#ifdef QT_ENABLE_HARFBUZZ_NG
# include "qharfbuzzng_p.h"
@@ -395,23 +396,39 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
QFixed QFontEngine::xHeight() const
{
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
QChar x((ushort)'x');
- stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
- glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.height;
}
QFixed QFontEngine::averageCharWidth() const
{
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
QChar x((ushort)'x');
- stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
- glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.xoff;
}
@@ -470,11 +487,22 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
++current;
if (glyphs.justifications[i].nKashidas) {
QChar ch(0x640); // Kashida character
- QGlyphLayoutArray<8> g;
- int nglyphs = 7;
- stringToCMap(&ch, 1, &g, &nglyphs, 0);
+
+ glyph_t kashidaGlyph;
+ QFixed kashidaWidth;
+
+ QGlyphLayout g;
+ g.numGlyphs = 1;
+ g.glyphs = &kashidaGlyph;
+ g.advances = &kashidaWidth;
+
+ int nglyphs = 1;
+ if (!stringToCMap(&ch, 1, &g, &nglyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
- xpos -= g.advances[0];
+ xpos -= kashidaWidth;
QFixed gpos_x = xpos + glyphs.offsets[i].x;
QFixed gpos_y = ypos + glyphs.offsets[i].y;
@@ -486,7 +514,7 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
}
positions[current].x = gpos_x;
positions[current].y = gpos_y;
- glyphs_out[current] = g.glyphs[0];
+ glyphs_out[current] = kashidaGlyph;
++current;
}
} else {
@@ -1348,14 +1376,12 @@ bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
}
int ucs4Length = 0;
- for (int i = 0; i < len; ++i) {
- if (str[i].isHighSurrogate() && i + 1 < len && str[i + 1].isLowSurrogate())
- ++ucs4Length;
- ++ucs4Length;
+ QStringIterator it(str, str + len);
+ while (it.hasNext()) {
+ it.advance();
+ glyphs->glyphs[ucs4Length++] = 0;
}
- memset(glyphs->glyphs, 0, ucs4Length * sizeof(glyph_t));
-
*nglyphs = ucs4Length;
glyphs->numGlyphs = ucs4Length;
@@ -1547,9 +1573,10 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
if (!(flags & GlyphIndicesOnly))
glyphs->advances[glyph_pos] = QFixed();
int num = 2;
- QGlyphLayout offs = glyphs->mid(glyph_pos, num);
- engine->stringToCMap(str + i, surrogate ? 2 : 1, &offs, &num, flags);
- Q_ASSERT(num == 1); // surrogates only give 1 glyph
+ QGlyphLayout g = glyphs->mid(glyph_pos, num);
+ if (!engine->stringToCMap(str + i, surrogate ? 2 : 1, &g, &num, flags))
+ Q_UNREACHABLE();
+ Q_ASSERT(num == 1);
if (glyphs->glyphs[glyph_pos]) {
// set the high byte to indicate which engine the glyph came from
glyphs->glyphs[glyph_pos] |= (x << 24);
@@ -1860,16 +1887,11 @@ bool QFontEngineMulti::canRender(const QChar *string, int len)
QGlyphLayout g;
g.numGlyphs = nglyphs;
g.glyphs = glyphs.data();
- if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly)) {
- glyphs.resize(nglyphs);
- g.numGlyphs = nglyphs;
- g.glyphs = glyphs.data();
- if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
- Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
- }
+ if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
+ Q_UNREACHABLE();
for (int i = 0; i < nglyphs; i++) {
- if (g.glyphs[i] == 0)
+ if (glyphs[i] == 0)
return false;
}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 5499757c3b..665932e4a5 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1283,13 +1283,22 @@ qreal QFontEngineFT::minRightBearing() const
{
if (rbearing == SHRT_MIN) {
lbearing = rbearing = 0;
- const QChar *ch = (const QChar *)(const void*)char_table;
- QGlyphLayoutArray<char_table_entries> glyphs;
+
+ const QChar *ch = reinterpret_cast<const QChar *>(char_table);
+
+ glyph_t glyphs[char_table_entries];
+
+ QGlyphLayout g;
+ g.glyphs = glyphs;
+ g.numGlyphs = char_table_entries;
int ng = char_table_entries;
- stringToCMap(ch, char_table_entries, &glyphs, &ng, GlyphIndicesOnly);
+ if (!stringToCMap(ch, char_table_entries, &g, &ng, GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(ng == char_table_entries);
+
while (--ng) {
- if (glyphs.glyphs[ng]) {
- glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs.glyphs[ng]);
+ if (glyphs[ng]) {
+ glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs[ng]);
lbearing = qMin(lbearing, gi.x);
rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
}
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 08105834ea..2f4709afe4 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -458,12 +458,19 @@ int QFontMetrics::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- // ### can nglyphs != 1 happen at all? Not currently I think
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
qreal lb;
- engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ engine->getGlyphBearings(glyph, &lb);
return qRound(lb);
}
@@ -493,12 +500,19 @@ int QFontMetrics::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- // ### can nglyphs != 1 happen at all? Not currently I think
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
qreal rb;
- engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ engine->getGlyphBearings(glyph, 0, &rb);
return qRound(rb);
}
@@ -538,11 +552,8 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
int numGlyphs = len;
QVarLengthGlyphLayoutArray glyphs(numGlyphs);
QFontEngine *engine = d->engineForScript(QChar::Script_Common);
- if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0)) {
- glyphs.resize(numGlyphs);
- if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
- Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
- }
+ if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
+ Q_UNREACHABLE();
QFixed width;
for (int i = 0; i < numGlyphs; ++i)
@@ -594,10 +605,20 @@ int QFontMetrics::width(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
- return qRound(glyphs.advances[0]);
+ QFixed advance;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyph_t glyph;
+ glyphs.glyphs = &glyph;
+ glyphs.advances = &advance;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ return qRound(advance);
}
/*! \obsolete
@@ -639,10 +660,20 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
- width = qRound(glyphs.advances[0]);
+ QFixed advance;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyph_t glyph;
+ glyphs.glyphs = &glyph;
+ glyphs.advances = &advance;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ width = qRound(advance);
}
return width;
}
@@ -708,10 +739,18 @@ QRect QFontMetrics::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ glyph_metrics_t gm = engine->boundingBox(glyph);
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}
@@ -1326,12 +1365,19 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- // ### can nglyphs != 1 happen at all? Not currently I think
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
qreal lb;
- engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ engine->getGlyphBearings(glyph, &lb);
return lb;
}
@@ -1361,12 +1407,19 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- // ### can nglyphs != 1 happen at all? Not currently I think
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
qreal rb;
- engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ engine->getGlyphBearings(glyph, 0, &rb);
return rb;
}
@@ -1431,10 +1484,20 @@ qreal QFontMetricsF::width(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
- return glyphs.advances[0].toReal();
+ QFixed advance;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyph_t glyph;
+ glyphs.glyphs = &glyph;
+ glyphs.advances = &advance;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ return advance.toReal();
}
/*!
@@ -1496,10 +1559,18 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
- QGlyphLayoutArray<10> glyphs;
- int nglyphs = 9;
- engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+
+ int nglyphs = 1;
+ if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ glyph_metrics_t gm = engine->boundingBox(glyph);
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
}
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 152e15a54d..2109b16bb5 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -201,12 +201,22 @@ static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
QVector<int> QFontSubset::getReverseMap() const
{
QVector<int> reverseMap(0x10000, 0);
- QGlyphLayoutArray<10> glyphs;
+
+ glyph_t glyph;
+
+ QGlyphLayout glyphs;
+ glyphs.glyphs = &glyph;
+ glyphs.numGlyphs = 1;
+
for (uint uc = 0; uc < 0x10000; ++uc) {
QChar ch(uc);
- int nglyphs = 10;
- fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
- int idx = glyph_indices.indexOf(glyphs.glyphs[0]);
+
+ int nglyphs = 1;
+ if (!fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ int idx = glyph_indices.indexOf(glyph);
if (idx >= 0 && !reverseMap.at(idx))
reverseMap[idx] = uc;
}
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 010f955c60..9f77083102 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -397,13 +397,7 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
QFontEngine *fe = (QFontEngine *)font_data;
Q_ASSERT(fe);
- glyph_t glyphs[2] = { 0, 0 };
-
- QGlyphLayout g;
- g.numGlyphs = 2;
- g.glyphs = glyphs;
-
- QChar chars[4];
+ QChar chars[2];
int numChars = 0;
if (Q_UNLIKELY(QChar::requiresSurrogates(unicode))) {
chars[numChars++] = QChar(QChar::highSurrogate(unicode));
@@ -422,11 +416,14 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
}
#endif
- int numGlyphs = g.numGlyphs;
- bool ok = fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly);
- Q_ASSERT(ok); Q_UNUSED(ok)
+ QGlyphLayout g;
+ g.numGlyphs = numChars;
+ g.glyphs = glyph;
- *glyph = g.glyphs[0];
+ int numGlyphs = numChars;
+ if (!fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
+ Q_ASSERT(numGlyphs == 1);
return true;
}
@@ -448,7 +445,7 @@ _hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
fe->recalcAdvances(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
- return g.advances[0].value();
+ return advance.value();
}
static hb_position_t
@@ -497,7 +494,7 @@ _hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
fe->doKerning(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
- return g.advances[0].value();
+ return advance.value();
}
static hb_position_t
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 37610a9099..7936831e13 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -289,13 +289,11 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine
Returns the font engine that can be used to render the font described by
the font definition, \a fontDef, in the specified \a script.
*/
-QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle)
+QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
- Q_UNUSED(script);
- Q_UNUSED(handle);
QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
- //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script;
+ //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family;
return engine;
}
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index 6053f11051..5f2c9a74ba 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -97,7 +97,7 @@ public:
virtual ~QPlatformFontDatabase();
virtual void populateFontDatabase();
virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual void releaseHandle(void *handle);
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index e26f7cdc93..449278df06 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -479,16 +479,8 @@ QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
QGlyphLayout glyphs;
glyphs.numGlyphs = numGlyphs;
glyphs.glyphs = glyphIndexes.data();
- if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
- glyphIndexes.resize(numGlyphs);
-
- glyphs.numGlyphs = numGlyphs;
- glyphs.glyphs = glyphIndexes.data();
- if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
- Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
- return QVector<quint32>();
- }
- }
+ if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
+ Q_UNREACHABLE();
glyphIndexes.resize(numGlyphs);
return glyphIndexes;
@@ -565,10 +557,11 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
if (!d->isValid() || numGlyphs <= 0)
return false;
+ QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
+
QGlyphLayout glyphs;
glyphs.glyphs = const_cast<glyph_t *>(glyphIndexes);
glyphs.numGlyphs = numGlyphs;
- QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
glyphs.advances = tmpAdvances.data();
bool design = layoutFlags & UseDesignMetrics;
@@ -578,7 +571,7 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
d->fontEngine->doKerning(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
for (int i=0; i<numGlyphs; ++i)
- advances[i] = QPointF(glyphs.advances[i].toReal(), 0.0);
+ advances[i] = QPointF(tmpAdvances[i].toReal(), 0.0);
return true;
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 2893d8b9b2..8a1096c269 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -932,18 +932,8 @@ void QTextEngine::shapeText(int item) const
int nGlyphs = initialGlyphs.numGlyphs;
QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
- if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
- nGlyphs = qMax(nGlyphs, itemLength); // ### needed for QFontEngine::stringToCMap() to not fail twice
- if (!ensureSpace(nGlyphs)) {
- Q_UNREACHABLE(); // ### report OOM error somehow
- return;
- }
- initialGlyphs = availableGlyphs(&si);
- if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
- Q_UNREACHABLE(); // ### if this happens there is a bug in the fontengine
- return;
- }
- }
+ if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
+ Q_UNREACHABLE();
uint lastEngine = 0;
for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
@@ -1393,9 +1383,9 @@ void QTextEngine::shape(int item) const
if (layoutData->items[item].analysis.flags == QScriptAnalysis::Object) {
ensureSpace(1);
if (block.docHandle()) {
- QTextFormat format = formats()->format(formatIndex(&layoutData->items[item]));
docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)),
- layoutData->items[item].position + block.position(), format);
+ layoutData->items[item].position + block.position(),
+ format(&layoutData->items[item]));
}
} else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) {
// set up at least the ascent/descent/leading of the script item for the tab
@@ -1427,7 +1417,7 @@ void QTextEngine::invalidate()
minWidth = 0;
maxWidth = 0;
if (specialData)
- specialData->resolvedFormatIndices.clear();
+ specialData->resolvedFormats.clear();
resetFontEngineCache();
}
@@ -1501,8 +1491,18 @@ void QTextEngine::itemize() const
{
QVarLengthArray<uchar> scripts(length);
QUnicodeTools::initScripts(string, length, scripts.data());
- for (int i = 0; i < length; ++i)
- analysis[i].script = scripts.at(i);
+ for (int i = 0; i < length; ++i) {
+ ushort script = scripts.at(i);
+ switch (script) {
+ case QChar::Script_Hiragana:
+ case QChar::Script_Katakana:
+ script = QChar::Script_Han;
+ break;
+ default:
+ break;
+ }
+ analysis[i].script = script;
+ }
}
const ushort *uc = string;
@@ -1596,10 +1596,9 @@ void QTextEngine::itemize() const
#ifndef QT_NO_RAWFONT
if (useRawFont && specialData) {
int lastIndex = 0;
- const QTextFormatCollection *collection = formats();
for (int i = 0; i < specialData->addFormats.size(); ++i) {
const QTextLayout::FormatRange &range = specialData->addFormats.at(i);
- const QTextCharFormat format = collection->charFormat(specialData->addFormatIndices.at(i));
+ const QTextCharFormat &format = range.format;
if (format.hasProperty(QTextFormat::FontCapitalization)) {
itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase);
itemizer.generate(range.start, range.length, format.fontCapitalization());
@@ -1996,11 +1995,22 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
if (type >= QGlyphAttributes::Arabic_Normal) {
QChar ch(0x640); // Kashida character
- QGlyphLayoutArray<8> glyphs;
- int nglyphs = 7;
- fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
- if (glyphs.glyphs[0] != 0 && glyphs.advances[0].value() != 0) {
- point->kashidaWidth = glyphs.advances[0];
+
+ glyph_t kashidaGlyph;
+ QFixed kashidaWidth;
+
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &kashidaGlyph;
+ glyphs.advances = &kashidaWidth;
+
+ int nglyphs = 1;
+ if (!fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nglyphs == 1);
+
+ if (kashidaGlyph != 0 && kashidaWidth != 0) {
+ point->kashidaWidth = kashidaWidth;
} else {
point->type = QGlyphAttributes::NoJustification;
point->kashidaWidth = 0;
@@ -2360,8 +2370,12 @@ void QTextEngine::freeMemory()
int QTextEngine::formatIndex(const QScriptItem *si) const
{
- if (specialData && !specialData->resolvedFormatIndices.isEmpty())
- return specialData->resolvedFormatIndices.at(si - &layoutData->items[0]);
+ if (specialData && !specialData->resolvedFormats.isEmpty()) {
+ QTextFormatCollection *collection = formats();
+ Q_ASSERT(collection);
+ return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
+ }
+
QTextDocumentPrivate *p = block.docHandle();
if (!p)
return -1;
@@ -2474,23 +2488,6 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
clearLineData();
}
-QList<QTextLayout::FormatRange> QTextEngine::additionalFormats() const
-{
- QList<QTextLayout::FormatRange> formatList;
- if (!specialData)
- return formatList;
-
- formatList = specialData->addFormats;
- if (!specialData->addFormatIndices.isEmpty()) {
- const QTextFormatCollection *formats = this->formats();
- Q_ASSERT(formats);
- for (int i = 0; i < specialData->addFormatIndices.size(); ++i)
- formatList[i].format = formats->charFormat(specialData->addFormatIndices.at(i));
- }
-
- return formatList;
-}
-
void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList)
{
if (formatList.isEmpty()) {
@@ -2501,7 +2498,6 @@ void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &fo
specialData = 0;
} else {
specialData->addFormats.clear();
- specialData->addFormatIndices.clear();
}
} else {
if (!specialData) {
@@ -2516,19 +2512,17 @@ void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &fo
void QTextEngine::indexAdditionalFormats()
{
- specialData->addFormatIndices.resize(specialData->addFormats.count());
-
- QTextFormatCollection *formats = this->formats();
-
- if (!formats) {
+ QTextFormatCollection *collection = formats();
+ if (!collection) {
Q_ASSERT(!block.docHandle());
specialData->formats.reset(new QTextFormatCollection);
- formats = specialData->formats.data();
+ collection = specialData->formats.data();
}
+ // replace with shared copies
for (int i = 0; i < specialData->addFormats.count(); ++i) {
- specialData->addFormatIndices[i] = formats->indexForFormat(specialData->addFormats.at(i).format);
- specialData->addFormats[i].format = QTextCharFormat();
+ QTextCharFormat &format = specialData->addFormats[i].format;
+ format = collection->charFormat(collection->indexForFormat(format));
}
}
@@ -2648,10 +2642,10 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (feForEllipsis->type() == QFontEngine::Mac)
feForEllipsis = fe;
- if (feForEllipsis->canRender(&ellipsisChar, 1)) {
- int nGlyphs = 1;
- feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0);
- }
+ int nGlyphs = 1;
+ if (!feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0))
+ Q_UNREACHABLE();
+ Q_ASSERT(nGlyphs == 1);
}
if (ellipsisGlyph.glyphs[0]) {
@@ -2663,8 +2657,9 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
QGlyphLayoutArray<3> glyphs;
int nGlyphs = 3;
if (!fe->stringToCMap(dotDotDot.constData(), 3, &glyphs, &nGlyphs, 0))
- // should never happen...
- return layoutData->string;
+ Q_UNREACHABLE();
+ Q_ASSERT(nGlyphs == 3);
+
for (int i = 0; i < nGlyphs; ++i)
ellipsisWidth += glyphs.advances[i];
ellipsisText = dotDotDot;
@@ -2944,14 +2939,12 @@ public:
void QTextEngine::resolveAdditionalFormats() const
{
if (!specialData || specialData->addFormats.isEmpty()
- || !specialData->resolvedFormatIndices.isEmpty())
+ || !specialData->resolvedFormats.isEmpty())
return;
QTextFormatCollection *collection = formats();
- specialData->resolvedFormatIndices.clear();
- QVector<int> indices(layoutData->items.count());
-
+ specialData->resolvedFormats.resize(layoutData->items.count());
QVarLengthArray<int, 64> addFormatSortedByStart;
addFormatSortedByStart.reserve(specialData->addFormats.count());
@@ -2987,21 +2980,22 @@ void QTextEngine::resolveAdditionalFormats() const
currentFormats.remove(currentFormatIterator - currentFormats.begin());
++endIt;
}
- QTextCharFormat format;
+
+ QTextCharFormat &format = specialData->resolvedFormats[i];
if (block.docHandle()) {
// when we have a docHandle, formatIndex might still return a valid index based
// on the preeditPosition. for all other cases, we cleared the resolved format indices
format = collection->charFormat(formatIndex(si));
}
-
- foreach (int cur, currentFormats) {
- Q_ASSERT(specialData->addFormats.at(cur).start <= si->position
- && specialData->addFormats.at(cur).start + specialData->addFormats.at(cur).length >= end);
- format.merge(collection->format(specialData->addFormatIndices.at(cur)));
+ if (!currentFormats.isEmpty()) {
+ foreach (int cur, currentFormats) {
+ const QTextLayout::FormatRange &range = specialData->addFormats.at(cur);
+ Q_ASSERT(range.start <= si->position && range.start + range.length >= end);
+ format.merge(range.format);
+ }
+ format = collection->charFormat(collection->indexForFormat(format)); // get shared copy
}
- indices[i] = collection->indexForFormat(format);
}
- specialData->resolvedFormatIndices = indices;
}
QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line)
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index d399123609..1616a78937 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -603,7 +603,8 @@ public:
void setPreeditArea(int position, const QString &text);
inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->addFormats.isEmpty()); }
- QList<QTextLayout::FormatRange> additionalFormats() const;
+ inline QList<QTextLayout::FormatRange> additionalFormats() const
+ { return specialData ? specialData->addFormats : QList<QTextLayout::FormatRange>(); }
void setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList);
private:
@@ -613,8 +614,7 @@ private:
int preeditPosition;
QString preeditText;
QList<QTextLayout::FormatRange> addFormats;
- QVector<int> addFormatIndices;
- QVector<int> resolvedFormatIndices;
+ QVector<QTextCharFormat> resolvedFormats;
// only used when no docHandle is available
QScopedPointer<QTextFormatCollection> formats;
};
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index c6e5160edc..0c9866c6cf 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -239,9 +239,7 @@ int QTextInlineObject::formatIndex() const
*/
QTextFormat QTextInlineObject::format() const
{
- if (!eng->block.docHandle())
- return QTextFormat();
- return eng->formats()->format(eng->formatIndex(&eng->layoutData->items[itm]));
+ return eng->format(&eng->layoutData->items[itm]);
}
/*!
@@ -1812,9 +1810,10 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.whiteSpaceOrObject = true;
lbh.tmpData.length++;
- QTextFormat format = eng->formats()->format(eng->formatIndex(&eng->layoutData->items[item]));
- if (eng->block.docHandle())
- eng->docLayout()->positionInlineObject(QTextInlineObject(item, eng), eng->block.position() + current.position, format);
+ if (eng->block.docHandle()) {
+ QTextInlineObject inlineObject(item, eng);
+ eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format());
+ }
lbh.tmpData.textWidth += current.width;
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp
index e0df4ccdf6..6160554472 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp
@@ -184,7 +184,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
qreal incr = 1.0 / qreal(size);
qreal fpos = 1.5 * incr;
- colorTable[pos++] = qtToGlColor(PREMUL(current_color));
+ colorTable[pos++] = qtToGlColor(qPremultiply(current_color));
while (fpos <= s.first().first) {
colorTable[pos] = colorTable[pos - 1];
@@ -193,13 +193,13 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
}
if (colorInterpolation)
- current_color = PREMUL(current_color);
+ current_color = qPremultiply(current_color);
for (int i = 0; i < s.size() - 1; ++i) {
qreal delta = 1/(s[i+1].first - s[i].first);
uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
if (colorInterpolation)
- next_color = PREMUL(next_color);
+ next_color = qPremultiply(next_color);
while (fpos < s[i+1].first && pos < size) {
int dist = int(256 * ((fpos - s[i].first) * delta));
@@ -207,7 +207,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
if (colorInterpolation)
colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
else
- colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ colorTable[pos] = qtToGlColor(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
++pos;
fpos += incr;
}
@@ -216,7 +216,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
Q_ASSERT(s.size() > 0);
- uint last_color = qtToGlColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
+ uint last_color = qtToGlColor(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index f51e471560..e561a6bc55 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -41,7 +41,7 @@
#include <QByteArray>
-#if (defined(Q_OS_UNIX) && !defined(Q_OS_QNX))
+#ifdef Q_OS_LINUX
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <private/qmath_p.h>
@@ -433,7 +433,7 @@ void q_printEglConfig(EGLDisplay display, EGLConfig config)
qWarning("\n");
}
-#if (defined(Q_OS_UNIX) && !defined(Q_OS_QNX))
+#ifdef Q_OS_LINUX
QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize)
{
@@ -535,6 +535,6 @@ int q_screenDepthFromFb(int framebufferDevice)
return depth;
}
-#endif // Q_OS_UNIX
+#endif // Q_OS_LINUX
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
index 33f3601b97..1ed5ede3e8 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
@@ -113,27 +113,18 @@ void QBasicFontDatabase::populateFontDatabase()
}
}
-QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *usrPtr)
+QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
- QFontEngineFT *engine;
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
- engine = new QFontEngineFT(fontDef);
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;
- if (!engine->init(fid,antialias,format)) {
- delete engine;
- engine = 0;
- return engine;
- }
- if (engine->invalid()) {
- delete engine;
- engine = 0;
- } else if (!engine->supportsScript(script)) {
- qWarning(" OpenType support missing for script %d", int(script));
+
+ QFontEngineFT *engine = new QFontEngineFT(fontDef);
+ if (!engine->init(fid, antialias, format) || engine->invalid()) {
delete engine;
engine = 0;
}
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
index 4d6fd2ceeb..45d7218ece 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h
@@ -58,7 +58,7 @@ class QBasicFontDatabase : public QPlatformFontDatabase
{
public:
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index c1ffa1b4fa..8b16e7520a 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -516,7 +516,7 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine,
return new QFontEngineMultiFontConfig(fontEngine, script);
}
-QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr)
+QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
if (!usrPtr)
return 0;
@@ -652,16 +652,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc
FcPatternDestroy(pattern);
- if (!engine->init(fid,antialias,format)) {
- delete engine;
- engine = 0;
- return engine;
- }
- if (engine->invalid()) {
- delete engine;
- engine = 0;
- } else if (!engine->supportsScript(script)) {
- qWarning(" OpenType support missing for script %d", int(script));
+ if (!engine->init(fid, antialias, format) || engine->invalid()) {
delete engine;
engine = 0;
}
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
index 6d6dae680e..9f1fd28144 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
@@ -52,7 +52,7 @@ class QFontconfigDatabase : public QBasicFontDatabase
public:
void populateFontDatabase();
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
QString resolveFontFamilyAlias(const QString &family) const;
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 473fdf895a..ab2e9c1f1a 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -278,10 +278,8 @@ void QCoreTextFontDatabase::releaseHandle(void *handle)
CFRelease(CTFontDescriptorRef(handle));
}
-QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr)
+QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
- Q_UNUSED(script);
-
qreal scaledPointSize = f.pixelSize;
// When 96 DPI is forced, the Mac plugin will use DPI 72 for some
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index ce2eba41d0..1560d36644 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -72,7 +72,7 @@ public:
QCoreTextFontDatabase();
~QCoreTextFontDatabase();
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 11d9377db7..4630b12a57 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -39,6 +39,10 @@
**
****************************************************************************/
+// We have to include this before the X11 headers dragged in by
+// qglxconvenience_p.h.
+#include <QtCore/QByteArray>
+
#include "qglxconvenience_p.h"
#include <QtCore/QVector>
@@ -116,6 +120,27 @@ QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat &format, int drawableBit)
{
+ // Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
+ // This is most useful with drivers that only support OpenGL 1.
+ // We need OpenGL 2, but the user probably doesn't want
+ // LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
+ static bool checkedForceSoftwareOpenGL = false;
+ static bool forceSoftwareOpenGL = false;
+ if (!checkedForceSoftwareOpenGL) {
+ // If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
+ // We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
+ // get inherited by other processes, of course only if it wasn't
+ // already set before.
+ if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
+ && !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
+ forceSoftwareOpenGL = true;
+
+ checkedForceSoftwareOpenGL = true;
+ }
+
+ if (forceSoftwareOpenGL)
+ qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+
bool reduced = true;
GLXFBConfig chosenConfig = 0;
QSurfaceFormat reducedFormat = format;
@@ -159,6 +184,10 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat
reducedFormat = qglx_reduceSurfaceFormat(reducedFormat,&reduced);
}
+ // unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
+ if (forceSoftwareOpenGL)
+ qunsetenv("LIBGL_ALWAYS_SOFTWARE");
+
return chosenConfig;
}
diff --git a/src/plugins/bearer/connman/connman.pro b/src/plugins/bearer/connman/connman.pro
index cccdff0fdb..0da2dfacf6 100644
--- a/src/plugins/bearer/connman/connman.pro
+++ b/src/plugins/bearer/connman/connman.pro
@@ -5,6 +5,8 @@ PLUGIN_CLASS_NAME = QConnmanEnginePlugin
load(qt_plugin)
QT = core network-private dbus
+CONFIG += link_pkgconfig
+packagesExist(connectionagent) { DEFINES += QT_HAS_CONNECTIONAGENT }
HEADERS += qconnmanservice_linux_p.h \
qofonoservice_linux_p.h \
diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp
index eac0d2b813..aee56eb034 100644
--- a/src/plugins/bearer/connman/qconnmanengine.cpp
+++ b/src/plugins/bearer/connman/qconnmanengine.cpp
@@ -41,7 +41,6 @@
#include "qconnmanengine.h"
#include "qconnmanservice_linux_p.h"
-#include "qofonoservice_linux_p.h"
#include "../qnetworksession_impl.h"
#include <QtNetwork/private/qnetworkconfiguration_p.h>
@@ -55,7 +54,11 @@
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
-
+#ifdef QT_HAS_CONNECTIONAGENT
+#include <sys/inotify.h>
+#include <fcntl.h>
+#include <qcore_unix_p.h>
+#endif
#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
@@ -63,7 +66,10 @@ QT_BEGIN_NAMESPACE
QConnmanEngine::QConnmanEngine(QObject *parent)
: QBearerEngineImpl(parent),
- connmanManager(new QConnmanManagerInterface(this))
+ connmanManager(new QConnmanManagerInterface(this)),
+ ofonoManager(new QOfonoManagerInterface(this)),
+ ofonoNetwork(0),
+ ofonoContextManager(0)
{
qDBusRegisterMetaType<ConnmanMap>();
qDBusRegisterMetaType<ConnmanMapList>();
@@ -72,6 +78,9 @@ QConnmanEngine::QConnmanEngine(QObject *parent)
QConnmanEngine::~QConnmanEngine()
{
+#ifdef QT_HAS_CONNECTIONAGENT
+ qt_safe_close(inotifyFileDescriptor);
+#endif
}
bool QConnmanEngine::connmanAvailable() const
@@ -82,26 +91,56 @@ bool QConnmanEngine::connmanAvailable() const
void QConnmanEngine::initialize()
{
- connect(connmanManager,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(propertyChangedContext(QString,QString,QDBusVariant)));
+ QMutexLocker locker(&mutex);
+ connect(ofonoManager,SIGNAL(modemChanged()),this,SLOT(changedModem()));
+
+ ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this);
+ ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this);
+ connect(ofonoContextManager,SIGNAL(roamingAllowedChanged(bool)),this,SLOT(reEvaluateCellular()));
connect(connmanManager,SIGNAL(servicesChanged(ConnmanMapList, QList<QDBusObjectPath>)),
this, SLOT(updateServices(ConnmanMapList, QList<QDBusObjectPath>)));
- foreach (const QString &techPath, connmanManager->getTechnologies()) {
- QConnmanTechnologyInterface *tech;
- tech = new QConnmanTechnologyInterface(techPath, this);
+ connect(connmanManager,SIGNAL(servicesReady(QStringList)),this,SLOT(servicesReady(QStringList)));
+ connect(connmanManager,SIGNAL(scanFinished()),this,SLOT(finishedScan()));
- connect(tech,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(technologyPropertyChangedContext(QString,QString,QDBusVariant)));
+ foreach (const QString &servPath, connmanManager->getServices()) {
+ addServiceConfiguration(servPath);
+ }
+ Q_EMIT updateCompleted();
+#ifdef QT_HAS_CONNECTIONAGENT
+ QSettings confFile(QStringLiteral("nemomobile"),QStringLiteral("connectionagent"));
+
+ inotifyFileDescriptor = ::inotify_init();
+ inotifyWatcher = ::inotify_add_watch(inotifyFileDescriptor, QFile::encodeName(confFile.fileName()), IN_MODIFY);
+ if (inotifyWatcher > 0) {
+ QSocketNotifier *notifier = new QSocketNotifier(inotifyFileDescriptor, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(inotifyActivated()));
}
+#endif
+}
- foreach (const QString &servPath, connmanManager->getServices()) {
+void QConnmanEngine::changedModem()
+{
+ QMutexLocker locker(&mutex);
+ if (ofonoNetwork)
+ delete ofonoNetwork;
+
+ ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this);
+
+ if (ofonoContextManager)
+ delete ofonoContextManager;
+ ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this);
+}
+
+void QConnmanEngine::servicesReady(const QStringList &list)
+{
+ QMutexLocker locker(&mutex);
+ foreach (const QString &servPath, list) {
addServiceConfiguration(servPath);
}
- // Get current list of access points.
- getConfigurations();
+ Q_EMIT updateCompleted();
}
QList<QNetworkConfigurationPrivate *> QConnmanEngine::getConfigurations()
@@ -129,13 +168,6 @@ QList<QNetworkConfigurationPrivate *> QConnmanEngine::getConfigurations()
return fetchedConfigurations;
}
-void QConnmanEngine::doRequestUpdate()
-{
- connmanManager->requestScan("");
- getConfigurations();
- emit updateCompleted();
-}
-
QString QConnmanEngine::getInterfaceFromId(const QString &id)
{
QMutexLocker locker(&mutex);
@@ -151,24 +183,25 @@ bool QConnmanEngine::hasIdentifier(const QString &id)
void QConnmanEngine::connectToId(const QString &id)
{
QMutexLocker locker(&mutex);
- QString servicePath = serviceFromId(id);
- QConnmanServiceInterface serv(servicePath);
- if(!serv.isValid()) {
+
+ QConnmanServiceInterface *serv = connmanServiceInterfaces.value(id);
+
+ if (!serv->isValid()) {
emit connectionError(id, QBearerEngineImpl::InterfaceLookupError);
} else {
- serv.connect();
+ serv->connect();
}
}
void QConnmanEngine::disconnectFromId(const QString &id)
{
QMutexLocker locker(&mutex);
- QString servicePath = serviceFromId(id);
- QConnmanServiceInterface serv(servicePath);
- if(!serv.isValid()) {
+ QConnmanServiceInterface *serv = connmanServiceInterfaces.value(id);
+
+ if (!serv->isValid()) {
emit connectionError(id, DisconnectionError);
} else {
- serv.disconnect();
+ serv->disconnect();
}
}
@@ -178,31 +211,32 @@ void QConnmanEngine::requestUpdate()
QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
}
+void QConnmanEngine::doRequestUpdate()
+{
+ connmanManager->requestScan("wifi");
+}
+
+void QConnmanEngine::finishedScan()
+{
+}
+
void QConnmanEngine::updateServices(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed)
{
+ QMutexLocker locker(&mutex);
+
foreach (const QDBusObjectPath &objectPath, removed) {
- removeConfiguration(QString::number(qHash(objectPath.path())));
+ removeConfiguration(objectPath.path());
}
foreach (const ConnmanMap &connmanMap, changed) {
- const QString id = QString::number(qHash(connmanMap.objectPath.path()));
+ const QString id = connmanMap.objectPath.path();
if (accessPointConfigurations.contains(id)) {
- configurationChange(id);
+ configurationChange(connmanServiceInterfaces.value(id));
} else {
addServiceConfiguration(connmanMap.objectPath.path());
}
}
-}
-
-QString QConnmanEngine::serviceFromId(const QString &id)
-{
- QMutexLocker locker(&mutex);
- foreach (const QString &service, serviceNetworks) {
- if (id == QString::number(qHash(service)))
- return service;
- }
-
- return QString();
+ Q_EMIT updateCompleted();
}
QNetworkSession::State QConnmanEngine::sessionStateForId(const QString &id)
@@ -211,25 +245,24 @@ QNetworkSession::State QConnmanEngine::sessionStateForId(const QString &id)
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
- if (!ptr)
+ if (!ptr || !ptr->isValid)
return QNetworkSession::Invalid;
- if (!ptr->isValid) {
- return QNetworkSession::Invalid;
+ QString service = id;
+ QConnmanServiceInterface *serv = connmanServiceInterfaces.value(service);
- }
- QString service = serviceFromId(id);
- QConnmanServiceInterface serv(service);
- QString servState = serv.getState();
+ QString servState = serv->state();
- if(serv.isFavorite() && (servState == "idle" || servState == "failure")) {
+ if (serv->favorite() && (servState == QLatin1String("idle") || servState == QLatin1String("failure"))) {
return QNetworkSession::Disconnected;
}
- if(servState == "association" || servState == "configuration" || servState == "login") {
+ if (servState == QLatin1String("association") || servState == QLatin1String("configuration")
+ || servState == QLatin1String("ready")) {
return QNetworkSession::Connecting;
}
- if(servState == "ready" || servState == "online") {
+
+ if (servState == QLatin1String("online")) {
return QNetworkSession::Connected;
}
@@ -300,88 +333,36 @@ QNetworkSessionPrivate *QConnmanEngine::createSessionBackend()
QNetworkConfigurationPrivatePointer QConnmanEngine::defaultConfiguration()
{
- return QNetworkConfigurationPrivatePointer();
-}
-
-void QConnmanEngine::propertyChangedContext(const QString &path,const QString &item, const QDBusVariant &value)
-{
- Q_UNUSED(path);
-
- QMutexLocker locker(&mutex);
- if(item == "Services") {
- QDBusArgument arg = qvariant_cast<QDBusArgument>(value.variant());
- QStringList list = qdbus_cast<QStringList>(arg);
-
- if(list.count() > accessPointConfigurations.count()) {
- foreach (const QString &service, list) {
- addServiceConfiguration(service);
- }
- }
- }
-
- if(item == "Technologies") {
- QDBusArgument arg = qvariant_cast<QDBusArgument>(value.variant());
- QStringList newlist = qdbus_cast<QStringList>(arg);
- if(newlist.count() > 0) {
- QMap<QString,QConnmanTechnologyInterface *> oldtech = technologies;
-
- foreach (const QString &listPath, newlist) {
- if(!oldtech.contains(listPath)) {
- QConnmanTechnologyInterface *tech;
- tech = new QConnmanTechnologyInterface(listPath,this);
- connect(tech,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(technologyPropertyChangedContext(QString,QString,QDBusVariant)));
- technologies.insert(listPath, tech);
- }
- }
- }
- }
- if(item == "State") {
-// qDebug() << value.variant();
- }
-}
-
-void QConnmanEngine::servicePropertyChangedContext(const QString &path,const QString &item, const QDBusVariant &value)
-{
- QMutexLocker locker(&mutex);
- if(item == "State") {
- configurationChange(QString::number(qHash(path)));
-
- if(value.variant().toString() == "failure") {
- QConnmanServiceInterface serv(path);
- emit connectionError(QString::number(qHash(path)), ConnectError);
+ const QMutexLocker locker(&mutex);
+ Q_FOREACH (const QString &servPath, connmanManager->getServices()) {
+ if (connmanServiceInterfaces.contains(servPath)) {
+ if (accessPointConfigurations.contains(servPath))
+ return accessPointConfigurations.value(servPath);
}
}
+ return QNetworkConfigurationPrivatePointer();
}
-void QConnmanEngine::technologyPropertyChangedContext(const QString & path, const QString &item, const QDBusVariant &value)
+void QConnmanEngine::serviceStateChanged(const QString &state)
{
- if(item == "State") {
- if(value.variant().toString() == "offline") {
- QConnmanTechnologyInterface tech(path);
- disconnect(&tech,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(technologyPropertyChangedContext(QString,QString,QDBusVariant)));
+ QConnmanServiceInterface *service = qobject_cast<QConnmanServiceInterface *>(sender());
+ configurationChange(service);
- technologies.remove(path);
- }
+ if (state == QStringLiteral("failure")) {
+ emit connectionError(service->path(), ConnectError);
}
}
-void QConnmanEngine::configurationChange(const QString &id)
+void QConnmanEngine::configurationChange(QConnmanServiceInterface *serv)
{
QMutexLocker locker(&mutex);
+ QString id = serv->path();
if (accessPointConfigurations.contains(id)) {
bool changed = false;
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
-
- QString servicePath = serviceFromId(id);
- QConnmanServiceInterface *serv;
- serv = new QConnmanServiceInterface(servicePath);
- QString networkName = serv->getName();
-
- QNetworkConfiguration::StateFlags curState = getStateForService(servicePath);
-
+ QString networkName = serv->name();
+ QNetworkConfiguration::StateFlags curState = getStateForService(serv->path());
ptr->mutex.lock();
if (!ptr->isValid) {
@@ -414,26 +395,31 @@ void QConnmanEngine::configurationChange(const QString &id)
QNetworkConfiguration::StateFlags QConnmanEngine::getStateForService(const QString &service)
{
QMutexLocker locker(&mutex);
- QConnmanServiceInterface serv(service);
+ QConnmanServiceInterface *serv = connmanServiceInterfaces.value(service);
+ QString state = serv->state();
+
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
- if (serv.getType() == "cellular") {
- if (serv.isSetupRequired() || !serv.isAutoConnect() || (serv.isRoaming() && isAlwaysAskRoaming())) {
- flag = ( flag | QNetworkConfiguration::Defined);
+
+ if (serv->type() == QLatin1String("cellular")) {
+
+ if (!serv->autoConnect()
+ || (serv->roaming()
+ && (isAlwaysAskRoaming() || !isRoamingAllowed(serv->path())))) {
+ flag = (flag | QNetworkConfiguration::Defined);
} else {
- flag = ( flag | QNetworkConfiguration::Discovered);
+ flag = (flag | QNetworkConfiguration::Discovered);
}
} else {
- if (serv.isFavorite()) {
- if (serv.isAutoConnect()) {
- flag = ( flag | QNetworkConfiguration::Discovered);
+ if (serv->favorite()) {
+ if (serv->autoConnect()) {
+ flag = (flag | QNetworkConfiguration::Discovered);
}
} else {
flag = QNetworkConfiguration::Undefined;
}
}
-
- if (serv.getState() == "ready" || serv.getState() == "online") {
- flag = ( flag | QNetworkConfiguration::Active);
+ if (state == QLatin1String("online")) {
+ flag = (flag | QNetworkConfiguration::Active);
}
return flag;
@@ -441,51 +427,35 @@ QNetworkConfiguration::StateFlags QConnmanEngine::getStateForService(const QStri
QNetworkConfiguration::BearerType QConnmanEngine::typeToBearer(const QString &type)
{
- if (type == "wifi")
+ if (type == QLatin1String("wifi"))
return QNetworkConfiguration::BearerWLAN;
- if (type == "ethernet")
+ if (type == QLatin1String("ethernet"))
return QNetworkConfiguration::BearerEthernet;
- if (type == "bluetooth")
+ if (type == QLatin1String("bluetooth"))
return QNetworkConfiguration::BearerBluetooth;
- if (type == "cellular") {
+ if (type == QLatin1String("cellular")) {
return ofonoTechToBearerType(type);
}
- if (type == "wimax")
+ if (type == QLatin1String("wimax"))
return QNetworkConfiguration::BearerWiMAX;
-// if(type == "gps")
-// if(type == "vpn")
-
return QNetworkConfiguration::BearerUnknown;
}
QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QString &/*type*/)
{
- QOfonoManagerInterface ofonoManager(this);
- QOfonoNetworkRegistrationInterface ofonoNetwork(ofonoManager.currentModem().path(),this);
-
- if(ofonoNetwork.isValid()) {
- foreach (const QDBusObjectPath &op,ofonoNetwork.getOperators() ) {
- QOfonoNetworkOperatorInterface opIface(op.path(),this);
-
- foreach (const QString &opTech, opIface.getTechnologies()) {
-
- if(opTech == "gsm") {
- return QNetworkConfiguration::Bearer2G;
- }
- if(opTech == "edge"){
- return QNetworkConfiguration::BearerCDMA2000; //wrong, I know
- }
- if(opTech == "umts"){
- return QNetworkConfiguration::BearerWCDMA;
- }
- if(opTech == "hspa"){
- return QNetworkConfiguration::BearerHSPA;
- }
- if(opTech == "lte"){
- return QNetworkConfiguration::BearerWiMAX; //not exact
- }
- }
+ if (ofonoNetwork) {
+ QString currentTechnology = ofonoNetwork->getTechnology();
+ if (currentTechnology == QLatin1String("gsm")) {
+ return QNetworkConfiguration::Bearer2G;
+ } else if (currentTechnology == QLatin1String("edge")) {
+ return QNetworkConfiguration::BearerCDMA2000; //wrong, I know
+ } else if (currentTechnology == QLatin1String("umts")) {
+ return QNetworkConfiguration::BearerWCDMA;
+ } else if (currentTechnology == QLatin1String("hspa")) {
+ return QNetworkConfiguration::BearerHSPA;
+ } else if (currentTechnology == QLatin1String("lte")) {
+ return QNetworkConfiguration::BearerWiMAX; //not exact
}
}
return QNetworkConfiguration::BearerUnknown;
@@ -493,12 +463,9 @@ QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QS
bool QConnmanEngine::isRoamingAllowed(const QString &context)
{
- QOfonoManagerInterface ofonoManager(this);
- QString modemPath = ofonoManager.currentModem().path();
- QOfonoDataConnectionManagerInterface dc(modemPath,this);
- foreach (const QDBusObjectPath &dcPath,dc.getPrimaryContexts()) {
- if(dcPath.path().contains(context.section("_",-1))) {
- return dc.isRoamingAllowed();
+ foreach (const QString &dcPath, ofonoContextManager->contexts()) {
+ if (dcPath.contains(context.section("_",-1))) {
+ return ofonoContextManager->roamingAllowed();
}
}
return false;
@@ -510,14 +477,11 @@ void QConnmanEngine::removeConfiguration(const QString &id)
if (accessPointConfigurations.contains(id)) {
- QString service = serviceFromId(id);
- QConnmanServiceInterface serv(service);
-
- disconnect(&serv,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(servicePropertyChangedContext(QString,QString,QDBusVariant)));
-
- serviceNetworks.removeOne(service);
-
+ disconnect(connmanServiceInterfaces.value(id),SIGNAL(stateChanged(QString)),
+ this,SLOT(serviceStateChanged(QString)));
+ serviceNetworks.removeOne(id);
+ QConnmanServiceInterface *service = connmanServiceInterfaces.take(id);
+ delete service;
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id);
foundConfigurations.removeOne(ptr.data());
locker.unlock();
@@ -529,35 +493,32 @@ void QConnmanEngine::removeConfiguration(const QString &id)
void QConnmanEngine::addServiceConfiguration(const QString &servicePath)
{
QMutexLocker locker(&mutex);
- QConnmanServiceInterface *serv;
- serv = new QConnmanServiceInterface(servicePath);
+ if (!connmanServiceInterfaces.contains(servicePath)) {
+ QConnmanServiceInterface *serv = new QConnmanServiceInterface(servicePath);
+ connmanServiceInterfaces.insert(serv->path(),serv);
+ }
- const QString id = QString::number(qHash(servicePath));
+ if (!accessPointConfigurations.contains(servicePath)) {
- if (!accessPointConfigurations.contains(id)) {
serviceNetworks.append(servicePath);
- connect(serv,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SLOT(servicePropertyChangedContext(QString,QString,QDBusVariant)));
+ connect(connmanServiceInterfaces.value(servicePath),SIGNAL(stateChanged(QString)),
+ this,SLOT(serviceStateChanged(QString)));
+
QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
+ QConnmanServiceInterface *service = connmanServiceInterfaces.value(servicePath);
- QString networkName = serv->getName();
+ QString networkName = service->name();
- const QString connectionType = serv->getType();
- if (connectionType == "ethernet") {
+ const QString connectionType = service->type();
+ if (connectionType == QLatin1String("ethernet")) {
cpPriv->bearerType = QNetworkConfiguration::BearerEthernet;
- } else if (connectionType == "wifi") {
+ } else if (connectionType == QLatin1String("wifi")) {
cpPriv->bearerType = QNetworkConfiguration::BearerWLAN;
- } else if (connectionType == "cellular") {
- cpPriv->bearerType = ofonoTechToBearerType("cellular");
- if(servicePath.isEmpty()) {
- networkName = serv->getAPN();
- if(networkName.isEmpty()) {
- networkName = serv->getName();
- }
- }
- cpPriv->roamingSupported = isRoamingAllowed(servicePath);
- } else if (connectionType == "wimax") {
+ } else if (connectionType == QLatin1String("cellular")) {
+ cpPriv->bearerType = ofonoTechToBearerType(QLatin1String("cellular"));
+ cpPriv->roamingSupported = service->roaming() && isRoamingAllowed(servicePath);
+ } else if (connectionType == QLatin1String("wimax")) {
cpPriv->bearerType = QNetworkConfiguration::BearerWiMAX;
} else {
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
@@ -565,10 +526,10 @@ void QConnmanEngine::addServiceConfiguration(const QString &servicePath)
cpPriv->name = networkName;
cpPriv->isValid = true;
- cpPriv->id = id;
+ cpPriv->id = servicePath;
cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
- if(serv->getSecurity() == "none") {
+ if (service->security() == QStringLiteral("none")) {
cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
} else {
cpPriv->purpose = QNetworkConfiguration::PrivatePurpose;
@@ -578,13 +539,16 @@ void QConnmanEngine::addServiceConfiguration(const QString &servicePath)
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
- foundConfigurations.append(cpPriv);
- configInterfaces[cpPriv->id] = serv->getInterface();
+ if (connectionType == QLatin1String("cellular")) {
+ foundConfigurations.append(cpPriv);
+ } else {
+ foundConfigurations.prepend(cpPriv);
+ }
+ configInterfaces[cpPriv->id] = service->serviceInterface();
locker.unlock();
- emit configurationAdded(ptr);
+ Q_EMIT configurationAdded(ptr);
locker.relock();
- emit updateCompleted();
}
}
@@ -595,10 +559,39 @@ bool QConnmanEngine::requiresPolling() const
bool QConnmanEngine::isAlwaysAskRoaming()
{
- QSettings confFile(QStringLiteral("nemomobile"), QStringLiteral("connectionagent"));
+#ifdef QT_HAS_CONNECTIONAGENT
+ QSettings confFile(QStringLiteral("nemomobile"),QStringLiteral("connectionagent"));
confFile.beginGroup(QStringLiteral("Connectionagent"));
return confFile.value(QStringLiteral("askForRoaming")).toBool();
+#else
+ return false;
+#endif
}
+
+void QConnmanEngine::reEvaluateCellular()
+{
+ Q_FOREACH (const QString &servicePath, connmanManager->getServices()) {
+ if (servicePath.contains("cellular") && accessPointConfigurations.contains(servicePath)) {
+ configurationChange(connmanServiceInterfaces.value(servicePath));
+ }
+ }
+}
+
+void QConnmanEngine::inotifyActivated()
+{
+#ifdef QT_HAS_CONNECTIONAGENT
+
+ char buffer[1024];
+ int len = qt_safe_read(inotifyFileDescriptor, (void *)buffer, sizeof(buffer));
+ if (len > 0) {
+ struct inotify_event *event = (struct inotify_event *)buffer;
+ if (event->wd == inotifyWatcher && (event->mask & IN_MODIFY) == 0) {
+ QTimer::singleShot(1000, this, SLOT(reEvaluateCellular())); //give this time to finish write
+ }
+ }
+#endif
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/plugins/bearer/connman/qconnmanengine.h b/src/plugins/bearer/connman/qconnmanengine.h
index 49a1a91d29..4a4e91659b 100644
--- a/src/plugins/bearer/connman/qconnmanengine.h
+++ b/src/plugins/bearer/connman/qconnmanengine.h
@@ -56,6 +56,7 @@
#include "../qbearerengine_impl.h"
#include "qconnmanservice_linux_p.h"
+#include "qofonoservice_linux_p.h"
#include <QMap>
#include <QVariant>
@@ -91,28 +92,32 @@ public:
virtual quint64 bytesReceived(const QString &id);
virtual quint64 startTime(const QString &id);
-
virtual QNetworkConfigurationManager::Capabilities capabilities() const;
virtual QNetworkConfigurationPrivatePointer defaultConfiguration();
- void configurationChange(const QString &id);
QList<QNetworkConfigurationPrivate *> getConfigurations();
-
private Q_SLOTS:
void doRequestUpdate();
- void servicePropertyChangedContext(const QString &,const QString &,const QDBusVariant &);
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
- void technologyPropertyChangedContext(const QString &,const QString &, const QDBusVariant &);
void updateServices(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed);
+ void servicesReady(const QStringList &);
+ void finishedScan();
+ void changedModem();
+ void serviceStateChanged(const QString &state);
+ void configurationChange(QConnmanServiceInterface * service);
+ void reEvaluateCellular();
+ void inotifyActivated();
private:
QConnmanManagerInterface *connmanManager;
+ QOfonoManagerInterface *ofonoManager;
+ QOfonoNetworkRegistrationInterface *ofonoNetwork;
+ QOfonoDataConnectionManagerInterface *ofonoContextManager;
+
QList<QNetworkConfigurationPrivate *> foundConfigurations;
- QString serviceFromId(const QString &id);
QString networkFromId(const QString &id);
QNetworkConfiguration::StateFlags getStateForService(const QString &service);
@@ -130,6 +135,11 @@ private:
QNetworkConfiguration::BearerType ofonoTechToBearerType(const QString &type);
bool isRoamingAllowed(const QString &context);
bool isAlwaysAskRoaming();
+ QMap <QString,QConnmanServiceInterface *> connmanServiceInterfaces;
+
+ int inotifyWatcher;
+ int inotifyFileDescriptor;
+
protected:
bool requiresPolling() const;
};
diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp
index 6d9ee265c6..46b24f77dd 100644
--- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp
+++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp
@@ -75,708 +75,380 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, ConnmanMap &map)
}
QConnmanManagerInterface::QConnmanManagerInterface( QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
- QLatin1String(CONNMAN_MANAGER_PATH),
+ : QDBusAbstractInterface(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
CONNMAN_MANAGER_INTERFACE,
QDBusConnection::systemBus(), parent)
{
qDBusRegisterMetaType<ConnmanMap>();
qDBusRegisterMetaType<ConnmanMapList>();
-}
-QConnmanManagerInterface::~QConnmanManagerInterface()
-{
-}
+ QList<QVariant> argumentList;
+ QDBusPendingReply<QVariantMap> props_reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this);
-void QConnmanManagerInterface::connectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- if(!connection().connect(QLatin1String(CONNMAN_SERVICE),
- QLatin1String(CONNMAN_MANAGER_PATH),
- QLatin1String(CONNMAN_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
- qWarning() << "PropertyChanged not connected";
- }
- }
+ QObject::connect(watcher,SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(propertiesReply(QDBusPendingCallWatcher*)));
- static const QMetaMethod stateChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::stateChanged);
- if (signal == stateChangedSignal) {
- if (!connection().connect(QLatin1String(CONNMAN_SERVICE),
- QLatin1String(CONNMAN_MANAGER_PATH),
- QLatin1String(CONNMAN_MANAGER_INTERFACE),
- QLatin1String("StateChanged"),
- this,SIGNAL(stateChanged(QString)))) {
- qWarning() << "StateChanged not connected";
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
+ QStringLiteral(CONNMAN_SERVICE_INTERFACE),
+ QStringLiteral("PropertyChanged"),
+ this,SLOT(changedProperty(QString,QDBusVariant)));
- }
- }
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QConnmanDBusHelper *helper;
- helper = new QConnmanDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- QLatin1String(CONNMAN_MANAGER_PATH),
- QLatin1String(CONNMAN_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
+ QStringLiteral(CONNMAN_SERVICE_INTERFACE),
+ QStringLiteral("TechnologyAdded"),
+ this,SLOT(technologyAdded(QDBusObjectPath,QVariantMap)));
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
- }
- static const QMetaMethod servicesChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::servicesChanged);
- if (signal == servicesChangedSignal) {
- if (!connection().connect(QLatin1String(CONNMAN_SERVICE),
- QLatin1String(CONNMAN_MANAGER_PATH),
- QLatin1String(CONNMAN_MANAGER_INTERFACE),
- QLatin1String("ServicesChanged"),
- this,SLOT(onServicesChanged(ConnmanMapList, QList<QDBusObjectPath>)))) {
- qWarning() << "servicesChanged not connected";
- }
- }
-}
-
-void QConnmanManagerInterface::onServicesChanged(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed)
-{
- emit servicesChanged(changed, removed);
-}
-
-
-void QConnmanManagerInterface::disconnectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
- }
-}
-
-QVariant QConnmanManagerInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << "does not contain" << property;
- }
- return var;
-}
-
-QVariantMap QConnmanManagerInterface::getProperties()
-{
- if(this->isValid()) {
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
- } else return QVariantMap();
-}
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
+ QStringLiteral(CONNMAN_SERVICE_INTERFACE),
+ QStringLiteral("TechnologyRemoved"),
+ this,SLOT(technologyRemoved(QDBusObjectPath)));
-QString QConnmanManagerInterface::getState()
-{
- QDBusReply<QString > reply = this->call("GetState");
- return reply.value();
-}
+ QList<QVariant> argumentList2;
+ QDBusPendingReply<ConnmanMapList> serv_reply = asyncCallWithArgumentList(QLatin1String("GetServices"), argumentList2);
+ QDBusPendingCallWatcher *watcher2 = new QDBusPendingCallWatcher(serv_reply, this);
-bool QConnmanManagerInterface::setProperty(const QString &name, const QDBusVariant &value)
-{
- Q_UNUSED(name);
- Q_UNUSED(value);
- return false;
-}
+ QObject::connect(watcher2,SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(servicesReply(QDBusPendingCallWatcher*)));
-QDBusObjectPath QConnmanManagerInterface::createProfile(const QString &/*name*/)
-{
- return QDBusObjectPath();
}
-bool QConnmanManagerInterface::removeProfile(QDBusObjectPath /*path*/)
+QConnmanManagerInterface::~QConnmanManagerInterface()
{
- return false;
}
-bool QConnmanManagerInterface::requestScan(const QString &type)
+void QConnmanManagerInterface::changedProperty(const QString &name, const QDBusVariant &value)
{
- QDBusReply<QString> reply = this->call(QLatin1String("RequestScan"), QVariant::fromValue(type));
-
- bool ok = true;
- if(reply.error().type() == QDBusError::InvalidArgs) {
- qWarning() << reply.error().message();
- ok = false;
- }
- return ok;
+ propertiesCacheMap[name] = value.variant();
}
-bool QConnmanManagerInterface::enableTechnology(const QString &type)
+void QConnmanManagerInterface::propertiesReply(QDBusPendingCallWatcher *call)
{
- QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("EnableTechnology"), QVariant::fromValue(type));
- bool ok = true;
- if(reply.error().type() == QDBusError::InvalidArgs) {
- qWarning() << reply.error().message();
- ok = false;
- }
- return ok;
-}
+ QDBusPendingReply<QVariantMap> props_reply = *call;
-bool QConnmanManagerInterface::disableTechnology(const QString &type)
-{
- QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("DisableTechnology"), QVariant::fromValue(type));
- bool ok = true;
- if(reply.error().type() == QDBusError::InvalidArgs) {
- qWarning() << reply.error().message();
- ok = false;
+ if (props_reply.isError()) {
+ qDebug() << props_reply.error().message();
+ } else {
+ propertiesCacheMap = props_reply.value();
}
- return ok;
+ call->deleteLater();
}
-QDBusObjectPath QConnmanManagerInterface::connectService(QVariantMap &map)
+void QConnmanManagerInterface::servicesReply(QDBusPendingCallWatcher *call)
{
- QDBusReply<QDBusObjectPath > reply = this->call(QLatin1String("ConnectService"), QVariant::fromValue(map));
- if(!reply.isValid()) {
- qDebug() << reply.error().message();
+ QDBusPendingReply<ConnmanMapList> serv_reply = *call;
+ if (serv_reply.isError()) {
+ qDebug() << serv_reply.error().message();
+ } else {
+ servicesList.clear(); //connman list changes order
+ ConnmanMap connmanobj;
+ Q_FOREACH (connmanobj, serv_reply.value()) {
+ servicesList << connmanobj.objectPath.path();
+ }
+ Q_EMIT servicesReady(servicesList);
}
- return reply;
+ call->deleteLater();
}
-void QConnmanManagerInterface::registerAgent(QDBusObjectPath &/*path*/)
-{
-}
-
-void QConnmanManagerInterface::unregisterAgent(QDBusObjectPath /*path*/)
+void QConnmanManagerInterface::connectNotify(const QMetaMethod &signal)
{
-}
-
-void QConnmanManagerInterface::registerCounter(const QString &path, quint32 interval)
-{ QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("RegisterCounter"),
- QVariant::fromValue(path),
- QVariant::fromValue(interval));
- if(reply.error().type() == QDBusError::InvalidArgs) {
- qWarning() << reply.error().message();
+ static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::propertyChanged);
+ if (signal == propertyChangedSignal) {
+ if (!connection().connect(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
+ QStringLiteral(CONNMAN_MANAGER_INTERFACE),
+ QStringLiteral("PropertyChanged"),
+ this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
+ qWarning() << "PropertyChanged not connected";
+ }
}
-}
-void QConnmanManagerInterface::unregisterCounter(const QString &path)
-{ QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("UnregisterCounter"),
- QVariant::fromValue(path));
- if(reply.error().type() == QDBusError::InvalidArgs) {
- qWarning() << reply.error().message();
+ static const QMetaMethod servicesChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::servicesChanged);
+ if (signal == servicesChangedSignal) {
+ if (!connection().connect(QStringLiteral(CONNMAN_SERVICE),
+ QStringLiteral(CONNMAN_MANAGER_PATH),
+ QStringLiteral(CONNMAN_MANAGER_INTERFACE),
+ QStringLiteral("ServicesChanged"),
+ this,SLOT(onServicesChanged(ConnmanMapList, QList<QDBusObjectPath>)))) {
+ qWarning() << "servicesChanged not connected";
+ }
}
}
-QString QConnmanManagerInterface::requestSession(const QString &bearerName)
-{
- QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("RequestSession"),
- QVariant::fromValue(bearerName));
- return QString();
-}
-
-void QConnmanManagerInterface::releaseSession()
-{
- QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("ReleaseSession"));
-}
-
-
-QDBusObjectPath QConnmanManagerInterface::lookupService(const QString &service)
+void QConnmanManagerInterface::onServicesChanged(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed)
{
- QDBusReply<QDBusObjectPath > reply = this->call(QLatin1String("LookupService"), QVariant::fromValue(service));
- if(!reply.isValid()) {
- qDebug() << reply.error().message();
+ ConnmanMap connmanobj;
+ servicesList.clear(); //connman list changes order
+ Q_FOREACH (connmanobj, changed) {
+ const QString svcPath(connmanobj.objectPath.path());
+ servicesList << svcPath;
}
- return reply;
-}
-// properties
-
-QStringList QConnmanManagerInterface::getAvailableTechnologies()
-{
- QVariant var = getProperty("AvailableTechnologies");
- return qdbus_cast<QStringList>(var);
+ Q_EMIT servicesChanged(changed, removed);
}
-QStringList QConnmanManagerInterface::getEnabledTechnologies()
+QVariant QConnmanManagerInterface::getProperty(const QString &property)
{
- QVariant var = getProperty("EnabledTechnologies");
- return qdbus_cast<QStringList>(var);
+ QVariant var;
+ var = propertiesCacheMap.value(property);
+ return var;
}
-QStringList QConnmanManagerInterface::getConnectedTechnologies()
+QVariantMap QConnmanManagerInterface::getProperties()
{
- QVariant var = getProperty("ConnectedTechnologies");
- return qdbus_cast<QStringList>(var);
+ if (propertiesCacheMap.isEmpty()) {
+ QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ propertiesCacheMap = reply.value();
+ }
+ }
+ return propertiesCacheMap;
}
-QString QConnmanManagerInterface::getDefaultTechnology()
+QString QConnmanManagerInterface::getState()
{
- QVariant var = getProperty("DefaultTechnology");
- return qdbus_cast<QString>(var);
+ return getProperty(QStringLiteral("State")).toString();
}
bool QConnmanManagerInterface::getOfflineMode()
{
- QVariant var = getProperty("OfflineMode");
+ QVariant var = getProperty(QStringLiteral("OfflineMode"));
return qdbus_cast<bool>(var);
}
-QString QConnmanManagerInterface::getActiveProfile()
-{
- QVariant var = getProperty("ActiveProfile");
- return qdbus_cast<QString>(var);
-}
-
-QStringList QConnmanManagerInterface::getProfiles()
-{
- QVariant var = getProperty("Profiles");
- return qdbus_cast<QStringList>(var);
-}
-
QStringList QConnmanManagerInterface::getTechnologies()
{
- QStringList list;
- QDBusReply<ConnmanMapList> replyList = this->call(QLatin1String("GetTechnologies"));
- if (replyList.isValid()) {
- Q_FOREACH (ConnmanMap map, replyList.value()) {
- list << map.objectPath.path();
- }
- } else {
- // try for older version
- QVariant var = getProperty("Technologies");
- if (!var.isNull()) {
- list = qdbus_cast<QStringList>(var);
+ if (technologiesMap.isEmpty()) {
+ QDBusPendingReply<ConnmanMapList> reply = call(QLatin1String("GetTechnologies"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ Q_FOREACH (ConnmanMap map, reply.value()) {
+ if (!technologiesMap.contains(map.objectPath.path())) {
+ technologyAdded(map.objectPath, map.propertyMap);
+ }
+ }
}
}
- return list;
+ return technologiesMap.keys();
}
QStringList QConnmanManagerInterface::getServices()
{
- QStringList list;
- QDBusReply<ConnmanMapList> replyList = this->call(QLatin1String("GetServices"));
- if (replyList.isValid()) {
- Q_FOREACH (ConnmanMap map, replyList.value()) {
- list << map.objectPath.path();
- }
- } else {
- QVariant var = getProperty("Services");
- if (!var.isNull()) {
- list = qdbus_cast<QStringList>(var);
+ if (servicesList.isEmpty()) {
+ QDBusPendingReply<ConnmanMapList> reply = call(QLatin1String("GetServices"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ Q_FOREACH (ConnmanMap map, reply.value()) {
+ servicesList << map.objectPath.path();
+ }
}
}
- return list;
+ return servicesList;
}
-QString QConnmanManagerInterface::getPathForTechnology(const QString &name)
+void QConnmanManagerInterface::requestScan(const QString &type)
{
- foreach (const QString &path, getTechnologies()) {
- if(path.contains(name)) {
- return path;
+ Q_FOREACH (QConnmanTechnologyInterface *tech, technologiesMap) {
+ if (tech->type() == type) {
+ tech->scan();
}
}
- return "";
-}
-
-
-//////////////////////////
-QConnmanProfileInterface::QConnmanProfileInterface(const QString &dbusPathName,QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
- dbusPathName,
- CONNMAN_PROFILE_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QConnmanProfileInterface::~QConnmanProfileInterface()
-{
}
-void QConnmanProfileInterface::connectNotify(const QMetaMethod &signal)
+void QConnmanManagerInterface::technologyAdded(const QDBusObjectPath &path, const QVariantMap &)
{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanProfileInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- this->path(),
- QLatin1String(CONNMAN_PROFILE_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)));
+ if (!technologiesList.contains(path.path())) {
+ technologiesList << path.path();
+ QConnmanTechnologyInterface *tech;
+ tech = new QConnmanTechnologyInterface(path.path(),this);
+ technologiesMap.insert(path.path(),tech);
+ connect(tech,SIGNAL(scanFinished()),this,SIGNAL(scanFinished()));
}
}
-void QConnmanProfileInterface::disconnectNotify(const QMetaMethod &signal)
+void QConnmanManagerInterface::technologyRemoved(const QDBusObjectPath &path)
{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanProfileInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
+ if (technologiesList.contains(path.path())) {
+ technologiesList.removeOne(path.path());
+ QConnmanTechnologyInterface * tech = technologiesMap.take(path.path());
+ delete tech;
}
}
-QVariantMap QConnmanProfileInterface::getProperties()
+QConnmanServiceInterface::QConnmanServiceInterface(const QString &dbusPathName,QObject *parent)
+ : QDBusAbstractInterface(QStringLiteral(CONNMAN_SERVICE),
+ dbusPathName,
+ CONNMAN_SERVICE_INTERFACE,
+ QDBusConnection::systemBus(), parent)
{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
+ QList<QVariant> argumentList;
+ QDBusPendingReply<QVariantMap> props_reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
-QVariant QConnmanProfileInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- }
- return var;
-}
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this);
-// properties
-QString QConnmanProfileInterface::getName()
-{
+ QObject::connect(watcher,SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(propertiesReply(QDBusPendingCallWatcher*)));
- QVariant var = getProperty("Name");
- return qdbus_cast<QString>(var);
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ path(),
+ QStringLiteral(CONNMAN_SERVICE_INTERFACE),
+ QStringLiteral("PropertyChanged"),
+ this,SLOT(changedProperty(QString,QDBusVariant)));
}
-bool QConnmanProfileInterface::isOfflineMode()
-{
- QVariant var = getProperty("OfflineMode");
- return qdbus_cast<bool>(var);
-}
-
-QStringList QConnmanProfileInterface::getServices()
+QConnmanServiceInterface::~QConnmanServiceInterface()
{
- QVariant var = getProperty("Services");
- return qdbus_cast<QStringList>(var);
}
-
-///////////////////////////
-QConnmanServiceInterface::QConnmanServiceInterface(const QString &dbusPathName,QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
- dbusPathName,
- CONNMAN_SERVICE_INTERFACE,
- QDBusConnection::systemBus(), parent)
+QVariantMap QConnmanServiceInterface::getProperties()
{
+ if (propertiesCacheMap.isEmpty()) {
+ QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ propertiesCacheMap = reply.value();
+ Q_EMIT propertiesReady();
+ }
+ }
+ return propertiesCacheMap;
}
-QConnmanServiceInterface::~QConnmanServiceInterface()
+void QConnmanServiceInterface::propertiesReply(QDBusPendingCallWatcher *call)
{
+ QDBusPendingReply<QVariantMap> props_reply = *call;
+ if (props_reply.isError()) {
+ qDebug() << props_reply.error().message();
+ return;
+ }
+ propertiesCacheMap = props_reply.value();
+ Q_EMIT propertiesReady();
}
void QConnmanServiceInterface::connectNotify(const QMetaMethod &signal)
{
static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanServiceInterface::propertyChanged);
if (signal == propertyChangedSignal) {
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- this->path(),
- QLatin1String(CONNMAN_SERVICE_INTERFACE),
- QLatin1String("PropertyChanged"),
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ path(),
+ QStringLiteral(CONNMAN_SERVICE_INTERFACE),
+ QStringLiteral("PropertyChanged"),
this,SIGNAL(propertyChanged(QString,QDBusVariant)));
}
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QConnmanServiceInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QConnmanDBusHelper *helper;
- helper = new QConnmanDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- this->path(),
- QLatin1String(CONNMAN_SERVICE_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
- }
-}
-
-void QConnmanServiceInterface::disconnectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanServiceInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
- }
}
-QVariantMap QConnmanServiceInterface::getProperties()
+void QConnmanServiceInterface::changedProperty(const QString &name, const QDBusVariant &value)
{
- if(this->isValid()) {
- QDBusReply<QVariantMap> reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
- }
- else
- return QVariantMap();
+ propertiesCacheMap[name] = value.variant();
+ if (name == QStringLiteral("State"))
+ Q_EMIT stateChanged(value.variant().toString());
}
QVariant QConnmanServiceInterface::getProperty(const QString &property)
{
QVariant var;
QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- }
+ var = map.value(property);
return var;
}
void QConnmanServiceInterface::connect()
{
- this->asyncCall(QLatin1String("Connect"));
+ asyncCall(QLatin1String("Connect"));
}
void QConnmanServiceInterface::disconnect()
{
- QDBusReply<QVariantMap> reply = this->call(QLatin1String("Disconnect"));
+ asyncCall(QLatin1String("Disconnect"));
}
void QConnmanServiceInterface::remove()
{
- QDBusReply<QVariantMap> reply = this->call(QLatin1String("Remove"));
+ asyncCall(QLatin1String("Remove"));
}
// properties
-QString QConnmanServiceInterface::getState()
+QString QConnmanServiceInterface::state()
{
- QVariant var = getProperty("State");
+ QVariant var = getProperty(QStringLiteral("State"));
return qdbus_cast<QString>(var);
}
-QString QConnmanServiceInterface::getError()
+QString QConnmanServiceInterface::lastError()
{
- QVariant var = getProperty("Error");
+ QVariant var = getProperty(QStringLiteral("Error"));
return qdbus_cast<QString>(var);
}
-QString QConnmanServiceInterface::getName()
+QString QConnmanServiceInterface::name()
{
- QVariant var = getProperty("Name");
+ QVariant var = getProperty(QStringLiteral("Name"));
return qdbus_cast<QString>(var);
}
-QString QConnmanServiceInterface::getType()
+QString QConnmanServiceInterface::type()
{
- QVariant var = getProperty("Type");
+ QVariant var = getProperty(QStringLiteral("Type"));
return qdbus_cast<QString>(var);
}
-QString QConnmanServiceInterface::getMode()
+QString QConnmanServiceInterface::security()
{
- QVariant var = getProperty("Mode");
+ QVariant var = getProperty(QStringLiteral("Security"));
return qdbus_cast<QString>(var);
}
-QString QConnmanServiceInterface::getSecurity()
+bool QConnmanServiceInterface::favorite()
{
- QVariant var = getProperty("Security");
- return qdbus_cast<QString>(var);
-}
-
-QString QConnmanServiceInterface::getPassphrase()
-{
- QVariant var = getProperty("Passphrase");
- return qdbus_cast<QString>(var);
-}
-
-bool QConnmanServiceInterface::isPassphraseRequired()
-{
- QVariant var = getProperty("PassphraseRequired");
- return qdbus_cast<bool>(var);
-}
-
-quint8 QConnmanServiceInterface::getSignalStrength()
-{
- QVariant var = getProperty("Strength");
- return qdbus_cast<quint8>(var);
-}
-
-bool QConnmanServiceInterface::isFavorite()
-{
- QVariant var = getProperty("Favorite");
+ QVariant var = getProperty(QStringLiteral("Favorite"));
return qdbus_cast<bool>(var);
}
-bool QConnmanServiceInterface::isImmutable()
+bool QConnmanServiceInterface::autoConnect()
{
- QVariant var = getProperty("Immutable");
+ QVariant var = getProperty(QStringLiteral("AutoConnect"));
return qdbus_cast<bool>(var);
}
-bool QConnmanServiceInterface::isAutoConnect()
+bool QConnmanServiceInterface::roaming()
{
- QVariant var = getProperty("AutoConnect");
+ QVariant var = getProperty(QStringLiteral("Roaming"));
return qdbus_cast<bool>(var);
}
-bool QConnmanServiceInterface::isSetupRequired()
-{
- QVariant var = getProperty("SetupRequired");
- return qdbus_cast<bool>(var);
-}
-
-QString QConnmanServiceInterface::getAPN()
-{
- QVariant var = getProperty("APN");
- return qdbus_cast<QString>(var);
-}
-
-QString QConnmanServiceInterface::getMCC()
-{
- QVariant var = getProperty("MCC");
- return qdbus_cast<QString>(var);
-}
-
-QString QConnmanServiceInterface::getMNC()
-{
- QVariant var = getProperty("MNC");
- return qdbus_cast<QString>(var);
-}
-
-bool QConnmanServiceInterface::isRoaming()
-{
- QVariant var = getProperty("Roaming");
- return qdbus_cast<bool>(var);
-}
-
-QStringList QConnmanServiceInterface::getNameservers()
-{
- QVariant var = getProperty("NameServers");
- return qdbus_cast<QStringList>(var);
-}
-
-QStringList QConnmanServiceInterface::getDomains()
-{
- QVariant var = getProperty("Domains");
- return qdbus_cast<QStringList>(var);
-}
-
-QVariantMap QConnmanServiceInterface::getIPv4()
+QVariantMap QConnmanServiceInterface::ethernet()
{
- QVariant var = getProperty("IPv4");
+ QVariant var = getProperty(QStringLiteral("Ethernet"));
return qdbus_cast<QVariantMap >(var);
}
-QVariantMap QConnmanServiceInterface::getIPv4Configuration()
-{
- QVariant var = getProperty("IPv4.Configuration");
- return qdbus_cast<QVariantMap >(var);
-}
-
-QVariantMap QConnmanServiceInterface::getProxy()
-{
- QVariant var = getProperty("Proxy");
- return qdbus_cast<QVariantMap >(var);
-}
-
-QVariantMap QConnmanServiceInterface::getEthernet()
-{
- QVariant var = getProperty("Ethernet");
- return qdbus_cast<QVariantMap >(var);
-}
-
-QString QConnmanServiceInterface::getMethod()
-{
- QVariant var;
- QVariantMap map = getEthernet();
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "Method") {
- return it.value().toString();
- }
- }
- return QString();
-}
-
-QString QConnmanServiceInterface::getInterface()
-{
- QVariant var;
- QVariantMap map = getEthernet();
-
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "Interface") {
- return it.value().toString();
- }
- }
-
- return QString();
-}
-
-QString QConnmanServiceInterface::getMacAddress()
-{
- QVariant var;
- QVariantMap map = getEthernet();
-
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "Address") {
- return it.value().toString();
- }
- }
- return QString();
-}
-
-quint16 QConnmanServiceInterface::getMtu()
-{
- quint16 mtu=0;
- QVariant var;
- QVariantMap map = getEthernet();
-
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "MTU") {
- return it.value().toUInt();
- }
- }
- return mtu;
-}
-
-quint16 QConnmanServiceInterface::getSpeed()
+QString QConnmanServiceInterface::serviceInterface()
{
- quint16 speed=0;
- QVariant var;
- QVariantMap map = getEthernet();
-
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "Speed") {
- return it.value().toUInt();
- }
- }
- return speed;
+ QVariantMap map = ethernet();
+ return map.value(QStringLiteral("Interface")).toString();
}
-QString QConnmanServiceInterface::getDuplex()
-{
- QVariant var;
- QVariantMap map = getEthernet();
-
- QMapIterator<QString,QVariant> it(map);
- while(it.hasNext()) {
- it.next();
- if(it.key() == "Duplex") {
- return it.value().toString();
- }
- }
- return QString();
-}
-
-
bool QConnmanServiceInterface::isOfflineMode()
{
- QVariant var = getProperty("OfflineMode");
+ QVariant var = getProperty(QStringLiteral("OfflineMode"));
return qdbus_cast<bool>(var);
}
-QStringList QConnmanServiceInterface::getServices()
+QStringList QConnmanServiceInterface::services()
{
- QVariant var = getProperty("Services");
+ QVariant var = getProperty(QStringLiteral("Services"));
return qdbus_cast<QStringList>(var);
}
-
//////////////////////////
QConnmanTechnologyInterface::QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
+ : QDBusAbstractInterface(QStringLiteral(CONNMAN_SERVICE),
dbusPathName,
CONNMAN_TECHNOLOGY_INTERFACE,
QDBusConnection::systemBus(), parent)
@@ -791,154 +463,52 @@ void QConnmanTechnologyInterface::connectNotify(const QMetaMethod &signal)
{
static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanTechnologyInterface::propertyChanged);
if (signal == propertyChangedSignal) {
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- this->path(),
- QLatin1String(CONNMAN_TECHNOLOGY_INTERFACE),
- QLatin1String("PropertyChanged"),
+ QDBusConnection::systemBus().connect(QStringLiteral(CONNMAN_SERVICE),
+ path(),
+ QStringLiteral(CONNMAN_TECHNOLOGY_INTERFACE),
+ QStringLiteral("PropertyChanged"),
this,SIGNAL(propertyChanged(QString,QDBusVariant)));
}
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QConnmanTechnologyInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QConnmanDBusHelper *helper;
- helper = new QConnmanDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
- this->path(),
- QLatin1String(CONNMAN_TECHNOLOGY_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
- }
}
-void QConnmanTechnologyInterface::disconnectNotify(const QMetaMethod &signal)
+QVariantMap QConnmanTechnologyInterface::properties()
{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanTechnologyInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
+ if (propertiesMap.isEmpty()) {
+ QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
+ reply.waitForFinished();
+ propertiesMap = reply.value();
}
-}
-
-QVariantMap QConnmanTechnologyInterface::getProperties()
-{
- QDBusReply<QVariantMap> reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
+ return propertiesMap;
}
QVariant QConnmanTechnologyInterface::getProperty(const QString &property)
{
QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- }
+ QVariantMap map = properties();
+ var = map.value(property);
return var;
}
-// properties
-QString QConnmanTechnologyInterface::getState()
-{
- QVariant var = getProperty("State");
- return qdbus_cast<QString>(var);
-}
-
-QString QConnmanTechnologyInterface::getName()
-{
- QVariant var = getProperty("Name");
- return qdbus_cast<QString>(var);
-}
-
-QString QConnmanTechnologyInterface::getType()
+QString QConnmanTechnologyInterface::type()
{
- QVariant var = getProperty("Type");
+ QVariant var = getProperty(QStringLiteral("Type"));
return qdbus_cast<QString>(var);
}
-
-//////////////////////////////////
-QConnmanAgentInterface::QConnmanAgentInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
- dbusPathName,
- CONNMAN_AGENT_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QConnmanAgentInterface::~QConnmanAgentInterface()
-{
-}
-
-void QConnmanAgentInterface::connectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-}
-
-void QConnmanAgentInterface::disconnectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-}
-
-
-void QConnmanAgentInterface::release()
-{
-}
-
-void QConnmanAgentInterface::reportError(QDBusObjectPath &/*path*/, const QString &/*error*/)
-{
-}
-
-void QConnmanAgentInterface::cancel()
-{
-}
-
-
-/////////////////////////////////////////
-QConnmanCounterInterface::QConnmanCounterInterface(const QString &dbusPathName,QObject *parent)
- : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
- dbusPathName,
- CONNMAN_COUNTER_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QConnmanCounterInterface::~QConnmanCounterInterface()
-{
-}
-
-quint32 QConnmanCounterInterface::getReceivedByteCount()
-{
- return 0;
-}
-
-quint32 QConnmanCounterInterface::getTransmittedByteCount()
-{
- return 0;
-}
-
-quint64 QConnmanCounterInterface::getTimeOnline()
-{
- return 0;
-}
-
-/////////////////////////////////////////
-QConnmanDBusHelper::QConnmanDBusHelper(QObject * parent)
- : QObject(parent)
-{
-}
-
-QConnmanDBusHelper::~QConnmanDBusHelper()
+void QConnmanTechnologyInterface::scan()
{
+ QDBusPendingReply<> reply = asyncCall(QLatin1String("Scan"));
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(scanReply(QDBusPendingCallWatcher*)));
}
-void QConnmanDBusHelper::propertyChanged(const QString &item, const QDBusVariant &var)
+void QConnmanTechnologyInterface::scanReply(QDBusPendingCallWatcher *call)
{
- QDBusMessage msg = this->message();
- Q_EMIT propertyChangedContext(msg.path() ,item, var);
+ Q_EMIT scanFinished();
+ call->deleteLater();
}
-/////////////////
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/plugins/bearer/connman/qconnmanservice_linux_p.h b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
index 6996fef5a7..250f90e2d0 100644
--- a/src/plugins/bearer/connman/qconnmanservice_linux_p.h
+++ b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
@@ -73,19 +73,9 @@
#define CONNMAN_SERVICE "net.connman"
#define CONNMAN_PATH "/net/connman"
-
-#define CONNMAN_DEBUG_INTERFACE CONNMAN_SERVICE ".Debug"
-#define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error"
-#define CONNMAN_AGENT_INTERFACE CONNMAN_SERVICE ".Agent"
-#define CONNMAN_COUNTER_INTERFACE CONNMAN_SERVICE ".Counter"
-
-#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
-#define CONNMAN_MANAGER_PATH "/"
-
-#define CONNMAN_TASK_INTERFACE CONNMAN_SERVICE ".Task"
-#define CONNMAN_PROFILE_INTERFACE CONNMAN_SERVICE ".Profile"
-#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
-#define CONNMAN_PROVIDER_INTERFACE CONNMAN_SERVICE ".Provider"
+#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
+#define CONNMAN_MANAGER_PATH "/"
+#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology"
#endif
@@ -108,6 +98,9 @@ QT_BEGIN_NAMESPACE
QDBusArgument &operator<<(QDBusArgument &argument, const ConnmanMap &obj);
const QDBusArgument &operator>>(const QDBusArgument &argument, ConnmanMap &obj);
+class QConnmanTechnologyInterface;
+class QConnmanServiceInterface;
+
class QConnmanManagerInterface : public QDBusAbstractInterface
{
Q_OBJECT
@@ -117,39 +110,16 @@ public:
QConnmanManagerInterface( QObject *parent = 0);
~QConnmanManagerInterface();
- QDBusObjectPath path() const;
-
+ QDBusObjectPath path() const;
QVariantMap getProperties();
- bool setProperty(const QString &name, const QDBusVariant &value);
- QDBusObjectPath createProfile(const QString &name);
- bool removeProfile(QDBusObjectPath path);
- bool requestScan(const QString &type);
- bool enableTechnology(const QString &type);
- bool disableTechnology(const QString &type);
- QDBusObjectPath connectService(QVariantMap &map);
- void registerAgent(QDBusObjectPath &path);
- void unregisterAgent(QDBusObjectPath path);
- void registerCounter(const QString &path, quint32 interval);
- void unregisterCounter(const QString &path);
-
- QString requestSession(const QString &bearerName);
- void releaseSession();
-
- // properties
+
QString getState();
- QStringList getAvailableTechnologies();
- QStringList getEnabledTechnologies();
- QStringList getConnectedTechnologies();
- QString getDefaultTechnology();
bool getOfflineMode();
- QString getActiveProfile();
- QStringList getProfiles();
- QStringList getTechnologies();
+ QStringList getTechnologies();
QStringList getServices();
- QDBusObjectPath lookupService(const QString &);
-
- QString getPathForTechnology(const QString &tech);
+ void requestScan(const QString &type);
+ QHash<QString, QConnmanTechnologyInterface *> technologiesMap;
Q_SIGNALS:
void propertyChanged(const QString &, const QDBusVariant &value);
@@ -157,41 +127,28 @@ Q_SIGNALS:
void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
void servicesChanged(const ConnmanMapList&, const QList<QDBusObjectPath> &);
+ void servicesReady(const QStringList &);
+ void scanFinished();
+
protected:
void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
QVariant getProperty(const QString &);
+private:
+ QVariantMap propertiesCacheMap;
+ QStringList servicesList;
+ QStringList technologiesList;
+
private slots:
void onServicesChanged(const ConnmanMapList&, const QList<QDBusObjectPath> &);
+ void changedProperty(const QString &, const QDBusVariant &value);
-};
-
-class QConnmanProfileInterfacePrivate;
-class QConnmanProfileInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
+ void propertiesReply(QDBusPendingCallWatcher *call);
+ void servicesReply(QDBusPendingCallWatcher *call);
- explicit QConnmanProfileInterface(const QString &dbusPathName,QObject *parent = 0);
- ~QConnmanProfileInterface();
+ void technologyAdded(const QDBusObjectPath &technology, const QVariantMap &properties);
+ void technologyRemoved(const QDBusObjectPath &technology);
- QVariantMap getProperties();
-// properties
- QString getName();
- bool isOfflineMode();
- QStringList getServices();
-
-Q_SIGNALS:
- void propertyChanged(const QString &, const QDBusVariant &value);
-private:
- QConnmanProfileInterfacePrivate *d;
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
};
class QConnmanServiceInterface : public QDBusAbstractInterface
@@ -208,52 +165,37 @@ public:
void connect();
void disconnect();
void remove();
- // void moveBefore(QDBusObjectPath &service);
- // void moveAfter(QDBusObjectPath &service);
// properties
- QString getState();
- QString getError();
- QString getName();
- QString getType();
- QString getMode();
- QString getSecurity();
- QString getPassphrase();
- bool isPassphraseRequired();
- quint8 getSignalStrength();
- bool isFavorite();
- bool isImmutable();
- bool isAutoConnect();
- bool isSetupRequired();
- QString getAPN();
- QString getMCC();
- QString getMNC();
- bool isRoaming();
- QStringList getNameservers();
- QStringList getDomains();
- QVariantMap getIPv4();
- QVariantMap getIPv4Configuration();
- QVariantMap getProxy();
- QVariantMap getEthernet();
-
- QString getMethod();
- QString getInterface();
- QString getMacAddress();
- quint16 getMtu();
- quint16 getSpeed();
- QString getDuplex();
+ QString state();
+ QString lastError();
+ QString name();
+ QString type();
+ QString security();
+ bool favorite();
+ bool autoConnect();
+ bool roaming();
+ QVariantMap ethernet();
+ QString serviceInterface();
bool isOfflineMode();
- QStringList getServices();
+ QStringList services();
Q_SIGNALS:
void propertyChanged(const QString &, const QDBusVariant &value);
void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
+ void propertiesReady();
+ void stateChanged(const QString &state);
protected:
void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
QVariant getProperty(const QString &);
+private:
+ QVariantMap propertiesCacheMap;
+private slots:
+ void propertiesReply(QDBusPendingCallWatcher *call);
+ void changedProperty(const QString &, const QDBusVariant &value);
+
};
class QConnmanTechnologyInterface : public QDBusAbstractInterface
@@ -265,72 +207,21 @@ public:
explicit QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent = 0);
~QConnmanTechnologyInterface();
- QVariantMap getProperties();
-// properties
- QString getState();
- QString getName();
- QString getType();
+ QString type();
+ void scan();
Q_SIGNALS:
void propertyChanged(const QString &, const QDBusVariant &value);
void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
+ void scanFinished();
protected:
void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
QVariant getProperty(const QString &);
-
-};
-
-class QConnmanAgentInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-
- explicit QConnmanAgentInterface(const QString &dbusPathName,QObject *parent = 0);
- ~QConnmanAgentInterface();
-
- void release();
- void reportError(QDBusObjectPath &path, const QString &error);
-// dict requestInput(QDBusObjectPath &path, dict fields);
- void cancel();
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
-};
-
-class QConnmanCounterInterfacePrivate;
-class QConnmanCounterInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-
- explicit QConnmanCounterInterface(const QString &dbusPathName, QObject *parent = 0);
- ~QConnmanCounterInterface();
-
-// void release();
- QString getInterface();
- quint32 getReceivedByteCount();
- quint32 getTransmittedByteCount();
- quint64 getTimeOnline();
-
private:
- QConnmanCounterInterfacePrivate *d;
-};
-
-class QConnmanDBusHelper: public QObject, protected QDBusContext
- {
- Q_OBJECT
- public:
- QConnmanDBusHelper(QObject *parent = 0);
- ~QConnmanDBusHelper();
+ QVariantMap properties();
+ QVariantMap propertiesMap;
+ void scanReply(QDBusPendingCallWatcher *call);
- public slots:
- void propertyChanged(const QString &, const QDBusVariant &);
-
-Q_SIGNALS:
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
};
QT_END_NAMESPACE
diff --git a/src/plugins/bearer/connman/qofonoservice_linux.cpp b/src/plugins/bearer/connman/qofonoservice_linux.cpp
index 1983276d94..f5da52a341 100644
--- a/src/plugins/bearer/connman/qofonoservice_linux.cpp
+++ b/src/plugins/bearer/connman/qofonoservice_linux.cpp
@@ -75,256 +75,133 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, ObjectPathPropert
QT_BEGIN_NAMESPACE
QOfonoManagerInterface::QOfonoManagerInterface( QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
- QLatin1String(OFONO_MANAGER_PATH),
+ : QDBusAbstractInterface(QStringLiteral(OFONO_SERVICE),
+ QStringLiteral(OFONO_MANAGER_PATH),
OFONO_MANAGER_INTERFACE,
QDBusConnection::systemBus(), parent)
{
qDBusRegisterMetaType<ObjectPathProperties>();
qDBusRegisterMetaType<PathPropertiesList>();
+
+ QDBusConnection::systemBus().connect(QStringLiteral(OFONO_SERVICE),
+ QStringLiteral(OFONO_MANAGER_PATH),
+ QStringLiteral(OFONO_MANAGER_INTERFACE),
+ QStringLiteral("ModemAdded"),
+ this,SLOT(modemAdded(QDBusObjectPath, QVariantMap)));
+ QDBusConnection::systemBus().connect(QStringLiteral(OFONO_SERVICE),
+ QStringLiteral(OFONO_MANAGER_PATH),
+ QStringLiteral(OFONO_MANAGER_INTERFACE),
+ QStringLiteral("ModemRemoved"),
+ this,SLOT(modemRemoved(QDBusObjectPath)));
}
QOfonoManagerInterface::~QOfonoManagerInterface()
{
}
-QList <QDBusObjectPath> QOfonoManagerInterface::getModems()
+QStringList QOfonoManagerInterface::getModems()
{
- QList <QDBusObjectPath> modemList;
- QList<QVariant> argumentList;
- QDBusReply<PathPropertiesList > reply = this->asyncCallWithArgumentList(QLatin1String("GetModems"), argumentList);
- if (reply.isValid()) {
- foreach (ObjectPathProperties modem, reply.value()) {
- modemList << modem.path;
+ if (modemList.isEmpty()) {
+ QList<QVariant> argumentList;
+ QDBusPendingReply<PathPropertiesList> reply = asyncCallWithArgumentList(QLatin1String("GetModems"), argumentList);
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ foreach (ObjectPathProperties modem, reply.value()) {
+ modemList << modem.path.path();
+ }
+ } else {
+ qDebug() << reply.error().message();
}
}
return modemList;
}
-QDBusObjectPath QOfonoManagerInterface::currentModem()
+QString QOfonoManagerInterface::currentModem()
{
- QList<QDBusObjectPath> modems = getModems();
- foreach (const QDBusObjectPath &modem, modems) {
- QOfonoModemInterface device(modem.path());
+ QStringList modems = getModems();
+ foreach (const QString &modem, modems) {
+ QOfonoModemInterface device(modem);
if (device.isPowered() && device.isOnline())
return modem;
}
- return QDBusObjectPath();
-}
-
-
-void QOfonoManagerInterface::connectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoManagerInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- QLatin1String(OFONO_MANAGER_PATH),
- QLatin1String(OFONO_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
- qWarning() << "PropertyCHanged not connected";
- }
- }
-
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoManagerInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QOfonoDBusHelper *helper;
- helper = new QOfonoDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
- QLatin1String(OFONO_MANAGER_PATH),
- QLatin1String(OFONO_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)));
- }
+ return QString();
}
-void QOfonoManagerInterface::disconnectNotify(const QMetaMethod &signal)
+void QOfonoManagerInterface::modemAdded(const QDBusObjectPath &path, const QVariantMap &/*var*/)
{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoManagerInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
+ if (!modemList.contains(path.path())) {
+ modemList << path.path();
+ Q_EMIT modemChanged();
}
}
-QVariant QOfonoManagerInterface::getProperty(const QString &property)
+void QOfonoManagerInterface::modemRemoved(const QDBusObjectPath &path)
{
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- return map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
+ if (modemList.contains(path.path())) {
+ modemList.removeOne(path.path());
+ Q_EMIT modemChanged();
}
- return QVariant();
-}
-
-QVariantMap QOfonoManagerInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- if (reply.isValid())
- return reply.value();
- else
- return QVariantMap();
-}
-
-QOfonoDBusHelper::QOfonoDBusHelper(QObject * parent)
- : QObject(parent)
-{
-}
-
-QOfonoDBusHelper::~QOfonoDBusHelper()
-{
-}
-
-void QOfonoDBusHelper::propertyChanged(const QString &item, const QDBusVariant &var)
-{
- QDBusMessage msg = this->message();
- Q_EMIT propertyChangedContext(msg.path() ,item, var);
}
QOfonoModemInterface::QOfonoModemInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
+ : QDBusAbstractInterface(QStringLiteral(OFONO_SERVICE),
dbusPathName,
OFONO_MODEM_INTERFACE,
QDBusConnection::systemBus(), parent)
{
+ QDBusConnection::systemBus().connect(QStringLiteral(OFONO_SERVICE),
+ path(),
+ OFONO_MODEM_INTERFACE,
+ QStringLiteral("PropertyChanged"),
+ this,SLOT(propertyChanged(QString,QDBusVariant)));
}
QOfonoModemInterface::~QOfonoModemInterface()
{
}
-bool QOfonoModemInterface::isPowered()
+void QOfonoModemInterface::propertyChanged(const QString &name,const QDBusVariant &value)
{
- QVariant var = getProperty("Powered");
- return qdbus_cast<bool>(var);
+ propertiesMap[name] = value.variant();
}
-bool QOfonoModemInterface::isOnline()
+bool QOfonoModemInterface::isPowered()
{
- QVariant var = getProperty("Online");
+ QVariant var = getProperty(QStringLiteral("Powered"));
return qdbus_cast<bool>(var);
}
-QString QOfonoModemInterface::getName()
-{
- QVariant var = getProperty("Name");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoModemInterface::getManufacturer()
-{
- QVariant var = getProperty("Manufacturer");
- return qdbus_cast<QString>(var);
-
-}
-
-QString QOfonoModemInterface::getModel()
-{
-
- QVariant var = getProperty("Model");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoModemInterface::getRevision()
-{
- QVariant var = getProperty("Revision");
- return qdbus_cast<QString>(var);
-
-}
-QString QOfonoModemInterface::getSerial()
-{
- QVariant var = getProperty("Serial");
- return qdbus_cast<QString>(var);
-
-}
-
-QStringList QOfonoModemInterface::getFeatures()
-{
- //sms, sim
- QVariant var = getProperty("Features");
- return qdbus_cast<QStringList>(var);
-}
-
-QStringList QOfonoModemInterface::getInterfaces()
-{
- QVariant var = getProperty("Interfaces");
- return qdbus_cast<QStringList>(var);
-}
-
-QString QOfonoModemInterface::defaultInterface()
+bool QOfonoModemInterface::isOnline()
{
- foreach (const QString &modem,getInterfaces()) {
- return modem;
- }
- return QString();
+ QVariant var = getProperty(QStringLiteral("Online"));
+ return qdbus_cast<bool>(var);
}
-
-void QOfonoModemInterface::connectNotify(const QMetaMethod &signal)
+QVariantMap QOfonoModemInterface::getProperties()
{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoModemInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_MODEM_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
- qWarning() << "PropertyCHanged not connected";
- }
+ if (propertiesMap.isEmpty()) {
+ QList<QVariant> argumentList;
+ QDBusPendingReply<QVariantMap> reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ if (!reply.isError()) {
+ propertiesMap = reply.value();
}
-
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoModemInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QOfonoDBusHelper *helper;
- helper = new QOfonoDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_MODEM_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
- }}
-
-void QOfonoModemInterface::disconnectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoModemInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
}
-}
-
-QVariantMap QOfonoModemInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
+ return propertiesMap;
}
QVariant QOfonoModemInterface::getProperty(const QString &property)
{
QVariant var;
QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
+ var = map.value(property);
return var;
}
QOfonoNetworkRegistrationInterface::QOfonoNetworkRegistrationInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
+ : QDBusAbstractInterface(QStringLiteral(OFONO_SERVICE),
dbusPathName,
OFONO_NETWORK_REGISTRATION_INTERFACE,
QDBusConnection::systemBus(), parent)
@@ -335,337 +212,33 @@ QOfonoNetworkRegistrationInterface::~QOfonoNetworkRegistrationInterface()
{
}
-QString QOfonoNetworkRegistrationInterface::getStatus()
-{
- /*
- "unregistered" Not registered to any network
- "registered" Registered to home network
- "searching" Not registered, but searching
- "denied" Registration has been denied
- "unknown" Status is unknown
- "roaming" Registered, but roaming*/
- QVariant var = getProperty("Status");
- return qdbus_cast<QString>(var);
-}
-
-quint16 QOfonoNetworkRegistrationInterface::getLac()
-{
- QVariant var = getProperty("LocationAreaCode");
- return var.value<quint16>();
-}
-
-
-quint32 QOfonoNetworkRegistrationInterface::getCellId()
-{
- QVariant var = getProperty("CellId");
- return var.value<quint32>();
-}
-
QString QOfonoNetworkRegistrationInterface::getTechnology()
{
- // "gsm", "edge", "umts", "hspa","lte"
- QVariant var = getProperty("Technology");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoNetworkRegistrationInterface::getOperatorName()
-{
- QVariant var = getProperty("Name");
+ QVariant var = getProperty(QStringLiteral("Technology"));
return qdbus_cast<QString>(var);
}
-int QOfonoNetworkRegistrationInterface::getSignalStrength()
-{
- QVariant var = getProperty("Strength");
- return qdbus_cast<int>(var);
-
-}
-
-QString QOfonoNetworkRegistrationInterface::getBaseStation()
-{
- QVariant var = getProperty("BaseStation");
- return qdbus_cast<QString>(var);
-}
-
-QList <QDBusObjectPath> QOfonoNetworkRegistrationInterface::getOperators()
-{
- QList <QDBusObjectPath> operatorList;
- QList<QVariant> argumentList;
- QDBusReply<PathPropertiesList > reply = this->asyncCallWithArgumentList(QLatin1String("GetOperators"),
- argumentList);
- if (reply.isValid()) {
- foreach (ObjectPathProperties netop, reply.value()) {
- operatorList << netop.path;
- }
- }
- return operatorList;
-}
-
-void QOfonoNetworkRegistrationInterface::connectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoNetworkRegistrationInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_NETWORK_REGISTRATION_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
- qWarning() << "PropertyCHanged not connected";
- }
- }
-
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoNetworkRegistrationInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QOfonoDBusHelper *helper;
- helper = new QOfonoDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_NETWORK_REGISTRATION_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
- }
-}
-
-void QOfonoNetworkRegistrationInterface::disconnectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoNetworkRegistrationInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
- }
-}
-
QVariant QOfonoNetworkRegistrationInterface::getProperty(const QString &property)
{
QVariant var;
QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
+ var = map.value(property);
return var;
}
QVariantMap QOfonoNetworkRegistrationInterface::getProperties()
{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
-
-
-
-QOfonoNetworkOperatorInterface::QOfonoNetworkOperatorInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
- dbusPathName,
- OFONO_NETWORK_OPERATOR_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QOfonoNetworkOperatorInterface::~QOfonoNetworkOperatorInterface()
-{
-}
-
-QString QOfonoNetworkOperatorInterface::getName()
-{
- QVariant var = getProperty("Name");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoNetworkOperatorInterface::getStatus()
-{
- // "unknown", "available", "current" and "forbidden"
- QVariant var = getProperty("Status");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoNetworkOperatorInterface::getMcc()
-{
- QVariant var = getProperty("MobileCountryCode");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoNetworkOperatorInterface::getMnc()
-{
- QVariant var = getProperty("MobileNetworkCode");
- return qdbus_cast<QString>(var);
-}
-
-QStringList QOfonoNetworkOperatorInterface::getTechnologies()
-{
- QVariant var = getProperty("Technologies");
- return qdbus_cast<QStringList>(var);
-}
-
-void QOfonoNetworkOperatorInterface::connectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoNetworkOperatorInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-// if (!connection().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_NETWORK_OPERATOR_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
-// qWarning() << "PropertyCHanged not connected";
-// }
-// }
-
-// static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoNetworkOperatorInterface::propertyChangedContext);
-// if (signal == propertyChangedContextSignal) {
-// QOfonoDBusHelper *helper;
-// helper = new QOfonoDBusHelper(this);
-
-// QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_NETWORK_OPERATOR_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
-// QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
-// this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
-// }
-}
-
-void QOfonoNetworkOperatorInterface::disconnectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoNetworkOperatorInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-
-// }
-}
-
-QVariant QOfonoNetworkOperatorInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
- return var;
-}
-
-QVariantMap QOfonoNetworkOperatorInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
-
-QOfonoSimInterface::QOfonoSimInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
- dbusPathName,
- OFONO_SIM_MANAGER_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QOfonoSimInterface::~QOfonoSimInterface()
-{
-}
-
-bool QOfonoSimInterface::isPresent()
-{
- QVariant var = getProperty("Present");
- return qdbus_cast<bool>(var);
-}
-
-QString QOfonoSimInterface::getHomeMcc()
-{
- QVariant var = getProperty("MobileCountryCode");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoSimInterface::getHomeMnc()
-{
- QVariant var = getProperty("MobileNetworkCode");
- return qdbus_cast<QString>(var);
-}
-
-// QStringList subscriberNumbers();
-// QMap<QString,QString> serviceNumbers();
-QString QOfonoSimInterface::pinRequired()
-{
- QVariant var = getProperty("PinRequired");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoSimInterface::lockedPins()
-{
- QVariant var = getProperty("LockedPins");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoSimInterface::cardIdentifier()
-{
- QVariant var = getProperty("CardIdentifier");
- return qdbus_cast<QString>(var);
-}
-
-void QOfonoSimInterface::connectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoSimInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-// if (!connection().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_SIM_MANAGER_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
-// qWarning() << "PropertyCHanged not connected";
-// }
-// }
-
-// static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoSimInterface::propertyChangedContext);
-// if (signal == propertyChangedContextSignal) {
-// QOfonoDBusHelper *helper;
-// helper = new QOfonoDBusHelper(this);
-
-// QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_SIM_MANAGER_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
-// QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
-// this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
-// }
-}
-
-void QOfonoSimInterface::disconnectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoSimInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-
-// }
-}
-
-QVariant QOfonoSimInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
+ if (propertiesMap.isEmpty()) {
+ QList<QVariant> argumentList;
+ QDBusPendingReply<QVariantMap> reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ propertiesMap = reply.value();
+ } else {
+ qDebug() << reply.error().message();
+ }
}
- return var;
-}
-
-QVariantMap QOfonoSimInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
+ return propertiesMap;
}
QOfonoDataConnectionManagerInterface::QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent)
@@ -674,340 +247,62 @@ QOfonoDataConnectionManagerInterface::QOfonoDataConnectionManagerInterface(const
OFONO_DATA_CONNECTION_MANAGER_INTERFACE,
QDBusConnection::systemBus(), parent)
{
+ QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
+ path(),
+ QLatin1String(OFONO_MODEM_INTERFACE),
+ QLatin1String("PropertyChanged"),
+ this,SLOT(propertyChanged(QString,QDBusVariant)));
}
QOfonoDataConnectionManagerInterface::~QOfonoDataConnectionManagerInterface()
{
}
-QList<QDBusObjectPath> QOfonoDataConnectionManagerInterface::getPrimaryContexts()
+QStringList QOfonoDataConnectionManagerInterface::contexts()
{
- QList <QDBusObjectPath> contextList;
- QList<QVariant> argumentList;
- QDBusReply<PathPropertiesList > reply = this->asyncCallWithArgumentList(QLatin1String("GetContexts"),
- argumentList);
- if (reply.isValid()) {
- foreach (ObjectPathProperties context, reply.value()) {
- contextList << context.path;
+ if (contextList.isEmpty()) {
+ QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ foreach (ObjectPathProperties context, reply.value()) {
+ contextList << context.path.path();
+ }
}
}
return contextList;
}
-bool QOfonoDataConnectionManagerInterface::isAttached()
-{
- QVariant var = getProperty("Attached");
- return qdbus_cast<bool>(var);
-}
-
-bool QOfonoDataConnectionManagerInterface::isRoamingAllowed()
+bool QOfonoDataConnectionManagerInterface::roamingAllowed()
{
- QVariant var = getProperty("RoamingAllowed");
+ QVariant var = getProperty(QStringLiteral("RoamingAllowed"));
return qdbus_cast<bool>(var);
}
-bool QOfonoDataConnectionManagerInterface::isPowered()
-{
- QVariant var = getProperty("Powered");
- return qdbus_cast<bool>(var);
-}
-
-void QOfonoDataConnectionManagerInterface::connectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoDataConnectionManagerInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-// if (!connection().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_DATA_CONNECTION_MANAGER_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
-// qWarning() << "PropertyCHanged not connected";
-// }
-// }
-
-// static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoDataConnectionManagerInterface::propertyChangedContext);
-// if (signal == propertyChangedContextSignal) {
-// QOfonoDBusHelper *helper;
-// helper = new QOfonoDBusHelper(this);
-
-// QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_DATA_CONNECTION_MANAGER_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
-// QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
-// this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
-// }
-}
-
-void QOfonoDataConnectionManagerInterface::disconnectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoDataConnectionManagerInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-
-// }
-}
-
QVariant QOfonoDataConnectionManagerInterface::getProperty(const QString &property)
{
QVariant var;
QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
+ var = map.value(property);
return var;
}
QVariantMap QOfonoDataConnectionManagerInterface::getProperties()
{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
-
-QOfonoConnectionContextInterface::QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
- dbusPathName,
- OFONO_DATA_CONTEXT_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QOfonoConnectionContextInterface::~QOfonoConnectionContextInterface()
-{
-}
-
-bool QOfonoConnectionContextInterface::isActive()
-{
- QVariant var = getProperty("Active");
- return qdbus_cast<bool>(var);
-}
-
-QString QOfonoConnectionContextInterface::getApName()
-{
- QVariant var = getProperty("AccessPointName");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoConnectionContextInterface::getType()
-{
- QVariant var = getProperty("Type");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoConnectionContextInterface::getName()
-{
- QVariant var = getProperty("Name");
- return qdbus_cast<QString>(var);
-}
-
-QVariantMap QOfonoConnectionContextInterface::getSettings()
-{
- QVariant var = getProperty("Settings");
- return qdbus_cast<QVariantMap>(var);
-}
-
-QString QOfonoConnectionContextInterface::getInterface()
-{
- QVariant var = getProperty("Interface");
- return qdbus_cast<QString>(var);
-}
-
-QString QOfonoConnectionContextInterface::getAddress()
-{
- QVariant var = getProperty("Address");
- return qdbus_cast<QString>(var);
-}
-
-bool QOfonoConnectionContextInterface::setActive(bool on)
-{
-// this->setProperty("Active", QVariant(on));
-
- return setProp("Active", QVariant::fromValue(on));
-}
-
-bool QOfonoConnectionContextInterface::setApn(const QString &name)
-{
- return setProp("AccessPointName", QVariant::fromValue(name));
-}
-
-void QOfonoConnectionContextInterface::connectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoConnectionContextInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-// if (!connection().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_DATA_CONTEXT_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
-// qWarning() << "PropertyCHanged not connected";
-// }
-// }
-
-// static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoConnectionContextInterface::propertyChangedContext);
-// if (signal == propertyChangedContextSignal) {
-// QOfonoDBusHelper *helper;
-// helper = new QOfonoDBusHelper(this);
-
-// QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
-// this->path(),
-// QLatin1String(OFONO_DATA_CONTEXT_INTERFACE),
-// QLatin1String("PropertyChanged"),
-// helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
-// QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
-// this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)), Qt::UniqueConnection);
-// }
-}
-
-void QOfonoConnectionContextInterface::disconnectNotify(const QMetaMethod &signal)
-{
- Q_UNUSED(signal);
-// static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoConnectionContextInterface::propertyChanged);
-// if (signal == propertyChangedSignal) {
-
-// }
-}
-
-QVariant QOfonoConnectionContextInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
- return var;
-}
-
-QVariantMap QOfonoConnectionContextInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
-
-bool QOfonoConnectionContextInterface::setProp(const QString &property, const QVariant &var)
-{
- QList<QVariant> args;
- args << QVariant::fromValue(property) << QVariant::fromValue(QDBusVariant(var));
-
- QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,
- QLatin1String("SetProperty"),
- args);
- bool ok = true;
- if (reply.type() != QDBusMessage::ReplyMessage) {
- qWarning() << reply.errorMessage();
- ok = false;
- }
- qWarning() << reply.errorMessage();
- return ok;
-}
-
-QOfonoSmsInterface::QOfonoSmsInterface(const QString &dbusPathName, QObject *parent)
- : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE),
- dbusPathName,
- OFONO_SMS_MANAGER_INTERFACE,
- QDBusConnection::systemBus(), parent)
-{
-}
-
-QOfonoSmsInterface::~QOfonoSmsInterface()
-{
-}
-
-void QOfonoSmsInterface::connectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoSmsInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_SMS_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
- qWarning() << "PropertyCHanged not connected";
- }
- }
-
- static const QMetaMethod propertyChangedContextSignal = QMetaMethod::fromSignal(&QOfonoSmsInterface::propertyChangedContext);
- if (signal == propertyChangedContextSignal) {
- QOfonoDBusHelper *helper;
- helper = new QOfonoDBusHelper(this);
-
- QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_SMS_MANAGER_INTERFACE),
- QLatin1String("PropertyChanged"),
- helper,SLOT(propertyChanged(QString,QDBusVariant)));
-
-
- QObject::connect(helper,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)),
- this,SIGNAL(propertyChangedContext(QString,QString,QDBusVariant)));
- }
-
- static const QMetaMethod immediateMessageSignal = QMetaMethod::fromSignal(&QOfonoSmsInterface::immediateMessage);
- if (signal == immediateMessageSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_SMS_MANAGER_INTERFACE),
- QLatin1String("ImmediateMessage"),
- this,SIGNAL(immediateMessage(QString,QVariantMap)))) {
- qWarning() << "PropertyCHanged not connected";
- }
- }
-
- static const QMetaMethod incomingMessageSignal = QMetaMethod::fromSignal(&QOfonoSmsInterface::incomingMessage);
- if (signal == incomingMessageSignal) {
- if (!connection().connect(QLatin1String(OFONO_SERVICE),
- this->path(),
- QLatin1String(OFONO_SMS_MANAGER_INTERFACE),
- QLatin1String("IncomingMessage"),
- this,SIGNAL(incomingMessage(QString,QVariantMap)))) {
- qWarning() << "PropertyCHanged not connected";
+ if (propertiesMap.isEmpty()) {
+ QList<QVariant> argumentList;
+ QDBusPendingReply<QVariantMap> reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList);
+ if (!reply.isError()) {
+ propertiesMap = reply.value();
}
}
+ return propertiesMap;
}
-void QOfonoSmsInterface::disconnectNotify(const QMetaMethod &signal)
-{
- static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QOfonoSmsInterface::propertyChanged);
- if (signal == propertyChangedSignal) {
-
- }
-}
-
-QVariant QOfonoSmsInterface::getProperty(const QString &property)
-{
- QVariant var;
- QVariantMap map = getProperties();
- if (map.contains(property)) {
- var = map.value(property);
- } else {
- qDebug() << Q_FUNC_INFO << "does not contain" << property;
- }
- return var;
-}
-
-QVariantMap QOfonoSmsInterface::getProperties()
-{
- QDBusReply<QVariantMap > reply = this->call(QLatin1String("GetProperties"));
- return reply.value();
-}
-
-void QOfonoSmsInterface::sendMessage(const QString &to, const QString &message)
+void QOfonoDataConnectionManagerInterface::propertyChanged(const QString &name, const QDBusVariant &value)
{
- QDBusReply<QString> reply = this->call(QLatin1String("SendMessage"),
- QVariant::fromValue(to),
- QVariant::fromValue(message));
- if (reply.error().type() == QDBusError::InvalidArgs)
- qWarning("%s", qPrintable(reply.error().message()));
+ propertiesMap[name] = value.variant();
+ if (name == QStringLiteral("RoamingAllowed"))
+ Q_EMIT roamingAllowedChanged(value.variant().toBool());
}
QT_END_NAMESPACE
diff --git a/src/plugins/bearer/connman/qofonoservice_linux_p.h b/src/plugins/bearer/connman/qofonoservice_linux_p.h
index 4802e0dc70..8fea465fd0 100644
--- a/src/plugins/bearer/connman/qofonoservice_linux_p.h
+++ b/src/plugins/bearer/connman/qofonoservice_linux_p.h
@@ -71,18 +71,10 @@
#define OFONO_SERVICE "org.ofono"
#define OFONO_MANAGER_INTERFACE "org.ofono.Manager"
#define OFONO_MANAGER_PATH "/"
+
#define OFONO_MODEM_INTERFACE "org.ofono.Modem"
#define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration"
-#define OFONO_NETWORK_OPERATOR_INTERFACE "org.ofono.NetworkOperator"
#define OFONO_DATA_CONNECTION_MANAGER_INTERFACE "org.ofono.ConnectionManager"
-#define OFONO_SIM_MANAGER_INTERFACE "org.ofono.SimManager"
-#define OFONO_DATA_CONTEXT_INTERFACE "org.ofono.ConnectionContext"
-
-#define OFONO_SMS_MANAGER_INTERFACE "org.ofono.SmsManager"
-#define OFONO_PHONEBOOK_INTERFACE "org.ofono.Phonebook"
-#define OFONO_MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
-
-
QT_BEGIN_NAMESPACE
@@ -108,35 +100,15 @@ public:
QOfonoManagerInterface( QObject *parent = 0);
~QOfonoManagerInterface();
- QDBusObjectPath path() const;
-
- QVariantMap getProperties();
- bool setProperty(const QString &name, const QDBusVariant &value);
- QList <QDBusObjectPath> getModems();
- QDBusObjectPath currentModem();
-
-Q_SIGNALS:
- void propertyChanged(const QString &, const QDBusVariant &value);
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
-
-};
-
-
-class QOfonoDBusHelper: public QObject, protected QDBusContext
- {
- Q_OBJECT
- public:
- QOfonoDBusHelper(QObject *parent = 0);
- ~QOfonoDBusHelper();
-
- public slots:
- void propertyChanged(const QString &, const QDBusVariant &);
- Q_SIGNALS:
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
+ QStringList getModems();
+ QString currentModem();
+signals:
+ void modemChanged();
+private:
+ QStringList modemList;
+private slots:
+ void modemAdded(const QDBusObjectPath &path, const QVariantMap &var);
+ void modemRemoved(const QDBusObjectPath &path);
};
class QOfonoModemInterface : public QDBusAbstractInterface
@@ -148,27 +120,13 @@ public:
explicit QOfonoModemInterface(const QString &dbusModemPathName, QObject *parent = 0);
~QOfonoModemInterface();
- QVariantMap getProperties();
- //properties
bool isPowered();
bool isOnline();
- QString getName();
- QString getManufacturer();
- QString getModel();
- QString getRevision();
- QString getSerial();
-
- QStringList getFeatures(); //sms, sim
- QStringList getInterfaces();
- QString defaultInterface();
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
+private:
+ QVariantMap getProperties();
+ QVariantMap propertiesMap;
QVariant getProperty(const QString &);
-Q_SIGNALS:
void propertyChanged(const QString &, const QDBusVariant &value);
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
};
@@ -181,80 +139,16 @@ public:
explicit QOfonoNetworkRegistrationInterface(const QString &dbusModemPathName, QObject *parent = 0);
~QOfonoNetworkRegistrationInterface();
- QVariantMap getProperties();
-
- //properties
- QString getStatus();
- quint16 getLac();
- quint32 getCellId();
QString getTechnology();
- QString getOperatorName();
- int getSignalStrength();
- QString getBaseStation();
- QList <QDBusObjectPath> getOperators();
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
-Q_SIGNALS:
- void propertyChanged(const QString &, const QDBusVariant &value);
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
-
-};
-
-class QOfonoNetworkOperatorInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-//modem or operator paths
- explicit QOfonoNetworkOperatorInterface(const QString &dbusPathName, QObject *parent = 0);
- ~QOfonoNetworkOperatorInterface();
-
- QVariantMap getProperties();
-
- //properties
- QString getName();
- QString getStatus();// "unknown", "available", "current" and "forbidden"
- QString getMcc();
- QString getMnc();
- QStringList getTechnologies();
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
-};
-
-class QOfonoSimInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-
- explicit QOfonoSimInterface(const QString &dbusModemPathName, QObject *parent = 0);
- ~QOfonoSimInterface();
+private:
QVariantMap getProperties();
-
- //properties
- bool isPresent();
- QString getHomeMcc();
- QString getHomeMnc();
-// QStringList subscriberNumbers();
-// QMap<QString,QString> serviceNumbers();
- QString pinRequired();
- QString lockedPins();
- QString cardIdentifier();
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
QVariant getProperty(const QString &);
+ QVariantMap propertiesMap;
+Q_SIGNALS:
+ void propertyChanged(const QString &, const QDBusVariant &value);
};
-
class QOfonoDataConnectionManagerInterface : public QDBusAbstractInterface
{
Q_OBJECT
@@ -264,82 +158,20 @@ public:
explicit QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent = 0);
~QOfonoDataConnectionManagerInterface();
+ QStringList contexts();
+ bool roamingAllowed();
+Q_SIGNALS:
+ void roamingAllowedChanged(bool);
+private:
QVariantMap getProperties();
-
- //properties
- QList<QDBusObjectPath> getPrimaryContexts();
- bool isAttached();
- bool isRoamingAllowed();
- bool isPowered();
-
- bool setPower(bool on);
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
-};
-
-
-class QOfonoConnectionContextInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-
- explicit QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent = 0);
- ~QOfonoConnectionContextInterface();
-
- QVariantMap getProperties();
-
- //properties
- bool isActive();
- QString getApName();
- QString getType();
- QString getName();
- QVariantMap getSettings();
- QString getInterface();
- QString getAddress();
-
- bool setActive(bool on);
- bool setApn(const QString &name);
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
- QVariant getProperty(const QString &);
- bool setProp(const QString &, const QVariant &var);
-};
-
-class QOfonoSmsInterface : public QDBusAbstractInterface
-{
- Q_OBJECT
-
-public:
-
- explicit QOfonoSmsInterface(const QString &dbusModemPathName, QObject *parent = 0);
- ~QOfonoSmsInterface();
-
- QVariantMap getProperties();
- void sendMessage(const QString &to, const QString &message);
-
- //properties
- QString serviceCenterAddress();
- bool useDeliveryReports();
- QString bearer();
-
-protected:
- void connectNotify(const QMetaMethod &signal);
- void disconnectNotify(const QMetaMethod &signal);
+ QVariantMap propertiesMap;
QVariant getProperty(const QString &);
-
-Q_SIGNALS:
+ QStringList contextList;
+private slots:
void propertyChanged(const QString &, const QDBusVariant &value);
- void propertyChangedContext(const QString &,const QString &,const QDBusVariant &);
- void immediateMessage(const QString &message, const QVariantMap &info);
- void incomingMessage(const QString &message, const QVariantMap &info);
};
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index f59a80d74e..dd86a80d23 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -338,6 +338,7 @@ void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w,
if (m_nativeSurface)
ANativeWindow_release(m_nativeSurface);
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
+ QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
} else {
if (m_nativeSurface) {
ANativeWindow_release(m_nativeSurface);
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index ee69cd7d86..29eed73535 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -75,7 +75,9 @@
#include "qcocoaeventdispatcher.h"
#include "qcocoaautoreleasepool.h"
+#include "qcocoawindow.h"
+#include "qcocoahelpers.h"
#include "qguiapplication.h"
#include "qevent.h"
#include "qhash.h"
@@ -95,11 +97,6 @@ QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
-enum {
- QtCocoaEventSubTypeWakeup = SHRT_MAX,
- QtCocoaEventSubTypePostMessage = SHRT_MAX-1
-};
-
static inline CFRunLoopRef mainRunLoop()
{
return CFRunLoopGetMain();
@@ -625,7 +622,7 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
if (!info.session) {
QCocoaAutoReleasePool pool;
- NSWindow *nswindow = static_cast<NSWindow *>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("nswindow", info.window));
+ NSWindow *nswindow = static_cast<QCocoaWindow *>(info.window->handle())->nativeWindow();
if (!nswindow)
continue;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 4b637a707d..6f76892d93 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -42,6 +42,7 @@
#include "qcocoaglcontext.h"
#include "qcocoawindow.h"
#include "qcocoaautoreleasepool.h"
+#include "qcocoahelpers.h"
#include <qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtPlatformSupport/private/cglconvenience_p.h>
@@ -151,6 +152,11 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
[m_context setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
+
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
+ [m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
+
updateSurfaceFormat();
}
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 64e1640a69..419bf631aa 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -162,6 +162,39 @@ CGContextRef qt_mac_cg_context(QPaintDevice *pdev);
CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy);
QImage qt_mac_toQImage(CGImageRef image);
+template<typename T>
+T qt_mac_resolveOption(const T &fallback, const QByteArray &environment)
+{
+ // check for environment variable
+ if (!environment.isEmpty()) {
+ QByteArray env = qgetenv(environment);
+ if (!env.isEmpty())
+ return T(env.toInt()); // works when T is bool, int.
+ }
+
+ return fallback;
+}
+
+template<typename T>
+T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &property, const QByteArray &environment)
+{
+ // check for environment variable
+ if (!environment.isEmpty()) {
+ QByteArray env = qgetenv(environment);
+ if (!env.isEmpty())
+ return T(env.toInt()); // works when T is bool, int.
+ }
+
+ // check for window property
+ if (window && !property.isNull()) {
+ QVariant windowProperty = window->property(property);
+ if (windowProperty.isValid())
+ return windowProperty.value<T>();
+ }
+
+ // return default value.
+ return fallback;
+}
QT_END_NAMESPACE
#endif //QCOCOAHELPERS_H
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
index 79b1c0856f..f119699004 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
@@ -43,6 +43,7 @@
#include "qcocoainputcontext.h"
#include "qcocoanativeinterface.h"
#include "qcocoaautoreleasepool.h"
+#include "qcocoawindow.h"
#include <QtCore/QRect>
#include <QtGui/QGuiApplication>
@@ -98,13 +99,12 @@ void QCocoaInputContext::reset()
{
QPlatformInputContext::reset();
- if (!mWindow) return;
+ if (!mWindow)
+ return;
- QCocoaNativeInterface *nativeInterface = qobject_cast<QCocoaNativeInterface *>(QGuiApplication::platformNativeInterface());
- if (!nativeInterface) return;
-
- QNSView *view = static_cast<QNSView *>(nativeInterface->nativeResourceForWindow("nsview", mWindow));
- if (!view) return;
+ QNSView *view = static_cast<QCocoaWindow *>(mWindow->handle())->qtView();
+ if (!view)
+ return;
QCocoaAutoReleasePool pool;
NSInputManager *currentIManager = [NSInputManager currentInputManager];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 8babfcf8ae..b1b73e5f08 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -134,6 +134,9 @@ public:
void updateScreens();
QCocoaScreen *screenAtIndex(int index);
+ void setToolbar(QWindow *window, NSToolbar *toolbar);
+ NSToolbar *toolbar(QWindow *window) const;
+ void clearToolbars();
private:
static QCocoaIntegration *mInstance;
@@ -150,6 +153,8 @@ private:
QScopedPointer<QCocoaNativeInterface> mNativeInterface;
QScopedPointer<QCocoaServices> mServices;
QScopedPointer<QCocoaKeyMapper> mKeyboardMapper;
+
+ QHash<QWindow *, NSToolbar *> mToolbars;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index e8cf5ca69b..0c1ddf9ad8 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -301,6 +301,8 @@ QCocoaIntegration::~QCocoaIntegration()
while (!mScreens.isEmpty()) {
delete mScreens.takeLast();
}
+
+ clearToolbars();
}
QCocoaIntegration *QCocoaIntegration::instance()
@@ -466,4 +468,27 @@ QList<int> QCocoaIntegration::possibleKeys(const QKeyEvent *event) const
return mKeyboardMapper->possibleKeys(event);
}
+void QCocoaIntegration::setToolbar(QWindow *window, NSToolbar *toolbar)
+{
+ if (NSToolbar *prevToolbar = mToolbars.value(window))
+ [prevToolbar release];
+
+ [toolbar retain];
+ mToolbars.insert(window, toolbar);
+}
+
+NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const
+{
+ return mToolbars.value(window);
+}
+
+void QCocoaIntegration::clearToolbars()
+{
+ QHash<QWindow *, NSToolbar *>::const_iterator it = mToolbars.constBegin();
+ while (it != mToolbars.constEnd()) {
+ [it.value() release];
+ }
+ mToolbars.clear();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 4bcb348acb..bf7e85619a 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -135,6 +135,11 @@ private:
// Request a unified title and toolbar look for the window.
static void setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness);
+
+ // Sets a NSToolbar instance for the given QWindow. The
+ // toolbar will be attached to the native NSWindow when
+ // that is created;
+ static void setNSToolbar(QWindow *window, void *nsToolbar);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index eb520b97c9..85ce96a8b6 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -47,6 +47,7 @@
#include "qmacmime.h"
#include "qcocoahelpers.h"
#include "qcocoaapplication.h"
+#include "qcocoaintegration.h"
#include <qbytearray.h>
#include <qwindow.h>
@@ -125,6 +126,8 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setEmbeddedInForeignView);
if (resource.toLower() == "setcontentborderthickness")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderThickness);
+ if (resource.toLower() == "setnstoolbar")
+ return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar);
return 0;
}
@@ -285,4 +288,16 @@ void QCocoaNativeInterface::setContentBorderThickness(QWindow *window, int topTh
cocoaWindow->setContentBorderThickness(topThickness, bottomThickness);
}
+void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
+{
+ if (!window)
+ return;
+
+ QCocoaIntegration::instance()->setToolbar(window, static_cast<NSToolbar *>(nsToolbar));
+
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ if (cocoaWindow)
+ cocoaWindow->updateNSToolbar();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 7b9768fcd9..256f5ee6fb 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -129,6 +129,8 @@ public:
NSView *contentView() const;
void setContentView(NSView *contentView);
+ QNSView *qtView() const;
+ NSWindow *nativeWindow() const;
void setEmbeddedInForeignView(bool subwindow);
@@ -162,6 +164,7 @@ public:
void registerTouch(bool enable);
void setContentBorderThickness(int topThickness, int bottomThickness);
void applyContentBorderThickness(NSWindow *window);
+ void updateNSToolbar();
qreal devicePixelRatio() const;
bool isWindowExposable();
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 70a08bbea5..d71fe1ee18 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -45,6 +45,7 @@
#include "qcocoaeventdispatcher.h"
#include "qcocoaglcontext.h"
#include "qcocoahelpers.h"
+#include "qcocoanativeinterface.h"
#include "qnsview.h"
#include <QtCore/qfileinfo.h>
#include <QtCore/private/qcore_mac_p.h>
@@ -250,9 +251,15 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
// problem, except if the appilcation wants to have a "custom" viewport.
// (like the hellogl example)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7
- && tlw->surfaceType() == QSurface::OpenGLSurface)
- [m_contentView setWantsBestResolutionOpenGLSurface:YES];
+ && tlw->surfaceType() == QSurface::OpenGLSurface) {
+ BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface",
+ "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
+ [m_contentView setWantsBestResolutionOpenGLSurface:enable];
+ }
#endif
+ BOOL enable = qt_mac_resolveOption(NO, tlw, "_q_mac_wantsLayer",
+ "QT_MAC_WANTS_LAYER");
+ [m_contentView setWantsLayer:enable];
}
setGeometry(tlw->geometry());
recreateWindow(parent());
@@ -527,11 +534,13 @@ void QCocoaWindow::setVisible(bool visible)
if (m_glContext)
m_glContext->windowWasHidden();
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- Q_ASSERT(cocoaEventDispatcher != 0);
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
+ if (cocoaEventDispatcher)
+ cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
if (m_nsWindow) {
if (m_hasModalSession) {
- cocoaEventDispatcherPrivate->endModalSession(window());
+ if (cocoaEventDispatcherPrivate)
+ cocoaEventDispatcherPrivate->endModalSession(window());
m_hasModalSession = false;
} else {
if ([m_nsWindow isSheet])
@@ -539,7 +548,8 @@ void QCocoaWindow::setVisible(bool visible)
}
hide();
- if (m_nsWindow == [NSApp keyWindow] && !cocoaEventDispatcherPrivate->currentModalSession()) {
+ if (m_nsWindow == [NSApp keyWindow]
+ && !(cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->currentModalSession())) {
// Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher
// (e.g., when show()-ing a modal QDialog instead of exec()-ing it), it can happen that
// the current NSWindow is still key after being ordered out. Then, after checking we
@@ -933,6 +943,16 @@ void QCocoaWindow::setContentView(NSView *contentView)
recreateWindow(parent()); // Adds the content view to parent NSView
}
+QNSView *QCocoaWindow::qtView() const
+{
+ return m_qtView;
+}
+
+NSWindow *QCocoaWindow::nativeWindow() const
+{
+ return m_nsWindow;
+}
+
void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
{
m_contentViewIsToBeEmbedded = embedded;
@@ -1100,6 +1120,11 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
const qreal opacity = qt_window_private(window())->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
+
+ // top-level QWindows may have an attached NSToolBar, call
+ // update function which will attach to the NSWindow.
+ if (!parentWindow)
+ updateNSToolbar();
}
void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child)
@@ -1365,6 +1390,19 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
}
}
+void QCocoaWindow::updateNSToolbar()
+{
+ if (!m_nsWindow)
+ return;
+
+ NSToolbar *toolbar = QCocoaIntegration::instance()->toolbar(window());
+
+ if ([m_nsWindow toolbar] == toolbar)
+ return;
+
+ [m_nsWindow setToolbar: toolbar];
+ [m_nsWindow setShowsToolbarButton:YES];
+}
qreal QCocoaWindow::devicePixelRatio() const
{
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 58c732de98..9920d428e9 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -1383,6 +1383,12 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
[self tryToPerform:aSelector with:self];
}
+- (void)cancelOperation:(id)sender
+{
+ if (!m_platformWindow || m_platformWindow->windowShouldBehaveAsPanel())
+ [super cancelOperation:sender];
+}
+
- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
{
Q_UNUSED(replacementRange)
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
index dbfd8d99dc..dfb766db32 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
@@ -44,10 +44,12 @@
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtCore/QRegularExpression>
+#if defined(Q_OS_LINUX)
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
+#endif
#include <private/qcore_unix_p.h>
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index 1dfb07ba08..175cc3f8bd 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -36,5 +36,8 @@ HEADERS = \
qiosinputcontext.h \
qiostheme.h \
qiosglobal.h \
- qiosservices.h
+ qiosservices.h \
+ quiview.h
+OTHER_FILES = \
+ quiview_textinput.mm
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 533ba686e1..aec1686b93 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE
@class QIOSKeyboardListener;
+@class QUIView;
class QIOSInputContext : public QPlatformInputContext
{
@@ -64,14 +65,19 @@ public:
void setFocusObject(QObject *object);
void focusWindowChanged(QWindow *focusWindow);
- void scrollRootView();
+ void cursorRectangleChanged();
+ void scrollToCursor();
+ void scroll(int y);
+
+ void update(Qt::InputMethodQueries);
+ void reset();
+ void commit();
private:
QIOSKeyboardListener *m_keyboardListener;
- UIView<UIKeyInput> *m_focusView;
- QTransform m_inputItemTransform;
+ QUIView *m_focusView;
bool m_hasPendingHideRequest;
- bool m_inSetFocusObject;
+ QObject *m_focusObject;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 39a22f367e..15f5082f62 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -42,6 +42,7 @@
#include "qiosglobal.h"
#include "qiosinputcontext.h"
#include "qioswindow.h"
+#include "quiview.h"
#include <QGuiApplication>
@interface QIOSKeyboardListener : NSObject {
@@ -49,6 +50,7 @@
QIOSInputContext *m_context;
BOOL m_keyboardVisible;
BOOL m_keyboardVisibleAndDocked;
+ BOOL m_ignoreKeyboardChanges;
QRectF m_keyboardRect;
QRectF m_keyboardEndRect;
NSTimeInterval m_duration;
@@ -66,6 +68,7 @@
m_context = context;
m_keyboardVisible = NO;
m_keyboardVisibleAndDocked = NO;
+ m_ignoreKeyboardChanges = NO;
m_duration = 0;
m_curve = UIViewAnimationCurveEaseOut;
m_viewController = 0;
@@ -128,6 +131,8 @@
- (void) keyboardDidChangeFrame:(NSNotification *)notification
{
+ if (m_ignoreKeyboardChanges)
+ return;
m_keyboardRect = [self getKeyboardRect:notification];
m_context->emitKeyboardRectChanged();
@@ -140,11 +145,13 @@
// If the keyboard was visible and docked from before, this is just a geometry
// change (normally caused by an orientation change). In that case, update scroll:
if (m_keyboardVisibleAndDocked)
- m_context->scrollRootView();
+ m_context->scrollToCursor();
}
- (void) keyboardWillShow:(NSNotification *)notification
{
+ if (m_ignoreKeyboardChanges)
+ return;
// Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked.
m_keyboardVisibleAndDocked = YES;
m_keyboardEndRect = [self getKeyboardRect:notification];
@@ -152,15 +159,17 @@
m_duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
m_curve = UIViewAnimationCurve([notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
}
- m_context->scrollRootView();
+ m_context->scrollToCursor();
}
- (void) keyboardWillHide:(NSNotification *)notification
{
+ if (m_ignoreKeyboardChanges)
+ return;
// Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
m_keyboardVisibleAndDocked = NO;
m_keyboardEndRect = [self getKeyboardRect:notification];
- m_context->scrollRootView();
+ m_context->scroll(0);
}
@end
@@ -170,10 +179,10 @@ QIOSInputContext::QIOSInputContext()
, m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
, m_focusView(0)
, m_hasPendingHideRequest(false)
- , m_inSetFocusObject(false)
+ , m_focusObject(0)
{
if (isQtApplication())
- connect(qGuiApp->inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QIOSInputContext::scrollRootView);
+ connect(qGuiApp->inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QIOSInputContext::cursorRectangleChanged);
connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSInputContext::focusWindowChanged);
}
@@ -216,76 +225,101 @@ bool QIOSInputContext::isInputPanelVisible() const
return m_keyboardListener->m_keyboardVisible;
}
-void QIOSInputContext::setFocusObject(QObject *)
+void QIOSInputContext::setFocusObject(QObject *focusObject)
{
- m_inputItemTransform = qApp->inputMethod()->inputItemTransform();
+ m_focusObject = focusObject;
- if (!m_focusView || !m_focusView.isFirstResponder)
+ if (!focusObject || !m_focusView || !m_focusView.isFirstResponder) {
+ scroll(0);
return;
+ }
- // Since m_focusView is the first responder, it means that the keyboard is open and we
- // should update keyboard layout. But there seem to be no way to tell it to reread the
- // UITextInputTraits from m_focusView. To work around that, we quickly resign first
- // responder status just to reassign it again. To not remove the focusObject in the same
- // go, we need to call the super implementation of resignFirstResponder. Since the call
- // will cause a 'keyboardWillHide' notification to be sendt, we also block scrollRootView
- // to avoid artifacts:
- m_inSetFocusObject = true;
- SEL sel = @selector(resignFirstResponder);
- [[m_focusView superclass] instanceMethodForSelector:sel](m_focusView, sel);
- m_inSetFocusObject = false;
- [m_focusView becomeFirstResponder];
+ reset();
+
+ if (m_keyboardListener->m_keyboardVisibleAndDocked)
+ scrollToCursor();
}
void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
{
- UIView<UIKeyInput> *view = reinterpret_cast<UIView<UIKeyInput> *>(focusWindow->handle()->winId());
+ QUIView *view = focusWindow ? reinterpret_cast<QUIView *>(focusWindow->handle()->winId()) : 0;
if ([m_focusView isFirstResponder])
[view becomeFirstResponder];
[m_focusView release];
m_focusView = [view retain];
+
+ if (view.window != m_keyboardListener->m_viewController.view)
+ scroll(0);
}
-void QIOSInputContext::scrollRootView()
+void QIOSInputContext::cursorRectangleChanged()
{
- // Scroll the root view (screen) if:
- // - our backend controls the root view controller on the main screen (no hybrid app)
- // - the focus object is on the same screen as the keyboard.
- // - the first responder is a QUIView, and not some other foreign UIView.
- // - the keyboard is docked. Otherwise the user can move the keyboard instead.
- // - the inputItem has not been moved/scrolled
- if (!isQtApplication() || !m_focusView || m_inSetFocusObject)
+ if (!m_keyboardListener->m_keyboardVisibleAndDocked)
return;
- if (m_inputItemTransform != qApp->inputMethod()->inputItemTransform()) {
- // The inputItem has moved since the last scroll update. To avoid competing
- // with the application where the cursor/inputItem should be, we bail:
+ // Check if the cursor has changed position inside the input item. Since
+ // qApp->inputMethod()->cursorRectangle() will also change when the input item
+ // itself moves, we need to ask the focus object for ImCursorRectangle:
+ static QPoint prevCursor;
+ QInputMethodQueryEvent queryEvent(Qt::ImCursorRectangle);
+ QCoreApplication::sendEvent(m_focusObject, &queryEvent);
+ QPoint cursor = queryEvent.value(Qt::ImCursorRectangle).toRect().topLeft();
+ if (cursor != prevCursor)
+ scrollToCursor();
+ prevCursor = cursor;
+}
+
+void QIOSInputContext::scrollToCursor()
+{
+ if (!isQtApplication() || !m_focusView)
return;
- }
UIView *view = m_keyboardListener->m_viewController.view;
- qreal scrollTo = 0;
-
- if (m_focusView.isFirstResponder
- && m_keyboardListener->m_keyboardVisibleAndDocked
- && m_focusView.window == view.window) {
- QRectF cursorRect = qGuiApp->inputMethod()->cursorRectangle();
- cursorRect.translate(m_focusView.qwindow->geometry().topLeft());
- qreal keyboardY = m_keyboardListener->m_keyboardEndRect.y();
- int statusBarY = qGuiApp->primaryScreen()->availableGeometry().y();
- const int margin = 20;
-
- if (cursorRect.bottomLeft().y() > keyboardY - margin)
- scrollTo = qMin(view.bounds.size.height - keyboardY, cursorRect.y() - statusBarY - margin);
- }
+ if (view.window != m_focusView.window)
+ return;
- if (scrollTo != view.bounds.origin.y) {
- // Scroll the view the same way a UIScrollView works: by changing bounds.origin:
- CGRect newBounds = view.bounds;
- newBounds.origin.y = scrollTo;
- [UIView animateWithDuration:m_keyboardListener->m_duration delay:0
- options:m_keyboardListener->m_curve
- animations:^{ view.bounds = newBounds; }
- completion:0];
- }
+ const int margin = 20;
+ QRectF translatedCursorPos = qApp->inputMethod()->cursorRectangle();
+ translatedCursorPos.translate(m_focusView.qwindow->geometry().topLeft());
+ qreal keyboardY = m_keyboardListener->m_keyboardEndRect.y();
+ int statusBarY = qGuiApp->primaryScreen()->availableGeometry().y();
+
+ scroll((translatedCursorPos.bottomLeft().y() < keyboardY - margin) ? 0
+ : qMin(view.bounds.size.height - keyboardY, translatedCursorPos.y() - statusBarY - margin));
}
+
+void QIOSInputContext::scroll(int y)
+{
+ // Scroll the view the same way a UIScrollView
+ // works: by changing bounds.origin:
+ UIView *view = m_keyboardListener->m_viewController.view;
+ if (y == view.bounds.origin.y)
+ return;
+
+ CGRect newBounds = view.bounds;
+ newBounds.origin.y = y;
+ [UIView animateWithDuration:m_keyboardListener->m_duration delay:0
+ options:m_keyboardListener->m_curve
+ animations:^{ view.bounds = newBounds; }
+ completion:0];
+}
+
+void QIOSInputContext::update(Qt::InputMethodQueries query)
+{
+ [m_focusView updateInputMethodWithQuery:query];
+}
+
+void QIOSInputContext::reset()
+{
+ // Since the call to reset will cause a 'keyboardWillHide'
+ // notification to be sendt, we block keyboard nofifications to avoid artifacts:
+ m_keyboardListener->m_ignoreKeyboardChanges = true;
+ [m_focusView reset];
+ m_keyboardListener->m_ignoreKeyboardChanges = false;
+}
+
+void QIOSInputContext::commit()
+{
+ [m_focusView commit];
+}
+
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 15a52e89ec..41a253e605 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -41,6 +41,7 @@
#include "qiosglobal.h"
#include "qioswindow.h"
+#include "quiview.h"
#include "qioscontext.h"
#include "qiosinputcontext.h"
#include "qiosscreen.h"
@@ -58,33 +59,19 @@
#include <QtDebug>
-@interface QUIView : UIView <UIKeyInput>
-{
-@public
- UITextAutocapitalizationType autocapitalizationType;
- UITextAutocorrectionType autocorrectionType;
- BOOL enablesReturnKeyAutomatically;
- UIKeyboardAppearance keyboardAppearance;
- UIKeyboardType keyboardType;
- UIReturnKeyType returnKeyType;
- BOOL secureTextEntry;
- QIOSWindow *m_qioswindow;
- QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
- int m_nextTouchId;
-}
-
-@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
-@property(nonatomic) UITextAutocorrectionType autocorrectionType;
-@property(nonatomic) BOOL enablesReturnKeyAutomatically;
-@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
-@property(nonatomic) UIKeyboardType keyboardType;
-@property(nonatomic) UIReturnKeyType returnKeyType;
-@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
-
-@end
+// Include category as an alternative to using -ObjC (Apple QA1490)
+#include "quiview_textinput.mm"
@implementation QUIView
+@synthesize autocapitalizationType;
+@synthesize autocorrectionType;
+@synthesize enablesReturnKeyAutomatically;
+@synthesize keyboardAppearance;
+@synthesize keyboardType;
+@synthesize returnKeyType;
+@synthesize secureTextEntry;
+
+ (Class)layerClass
{
return [CAEAGLLayer class];
@@ -112,6 +99,7 @@
self.hidden = YES;
self.multipleTouchEnabled = YES;
+ m_inSendEventToFocusObject = NO;
}
return self;
@@ -314,109 +302,6 @@
QWindowSystemInterface::flushWindowSystemEvents();
}
-@synthesize autocapitalizationType;
-@synthesize autocorrectionType;
-@synthesize enablesReturnKeyAutomatically;
-@synthesize keyboardAppearance;
-@synthesize keyboardType;
-@synthesize returnKeyType;
-@synthesize secureTextEntry;
-
-- (BOOL)canBecomeFirstResponder
-{
- return YES;
-}
-
-- (BOOL)becomeFirstResponder
-{
- // Note: QIOSInputContext controls our first responder status based on
- // whether or not the keyboard should be open or closed.
- [self updateTextInputTraits];
- return [super becomeFirstResponder];
-}
-
-- (BOOL)resignFirstResponder
-{
- // Resigning first responed status means that the virtual keyboard was closed, or
- // some other view became first responder. In either case we clear the focus object to
- // avoid blinking cursors in line edits etc:
- if (m_qioswindow)
- static_cast<QWindowPrivate *>(QObjectPrivate::get(m_qioswindow->window()))->clearFocusObject();
- return [super resignFirstResponder];
-}
-
-- (BOOL)hasText
-{
- return YES;
-}
-
-- (void)insertText:(NSString *)text
-{
- QString string = QString::fromUtf8([text UTF8String]);
- int key = 0;
- if ([text isEqualToString:@"\n"]) {
- key = (int)Qt::Key_Return;
- if (self.returnKeyType == UIReturnKeyDone)
- [self resignFirstResponder];
- }
-
- // Send key event to window system interface
- QWindowSystemInterface::handleKeyEvent(
- 0, QEvent::KeyPress, key, Qt::NoModifier, string, false, int(string.length()));
- QWindowSystemInterface::handleKeyEvent(
- 0, QEvent::KeyRelease, key, Qt::NoModifier, string, false, int(string.length()));
-}
-
-- (void)deleteBackward
-{
- // Send key event to window system interface
- QWindowSystemInterface::handleKeyEvent(
- 0, QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier);
- QWindowSystemInterface::handleKeyEvent(
- 0, QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
-}
-
-- (void)updateTextInputTraits
-{
- // Ask the current focus object what kind of input it
- // expects, and configure the keyboard appropriately:
- QObject *focusObject = QGuiApplication::focusObject();
- if (!focusObject)
- return;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
- if (!QCoreApplication::sendEvent(focusObject, &queryEvent))
- return;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return;
-
- Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
-
- self.returnKeyType = (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone;
- self.secureTextEntry = BOOL(hints & Qt::ImhHiddenText);
- self.autocorrectionType = (hints & Qt::ImhNoPredictiveText) ?
- UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault;
-
- if (hints & Qt::ImhUppercaseOnly)
- self.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
- else if (hints & Qt::ImhNoAutoUppercase)
- self.autocapitalizationType = UITextAutocapitalizationTypeNone;
- else
- self.autocapitalizationType = UITextAutocapitalizationTypeSentences;
-
- if (hints & Qt::ImhUrlCharactersOnly)
- self.keyboardType = UIKeyboardTypeURL;
- else if (hints & Qt::ImhEmailCharactersOnly)
- self.keyboardType = UIKeyboardTypeEmailAddress;
- else if (hints & Qt::ImhDigitsOnly)
- self.keyboardType = UIKeyboardTypeNumberPad;
- else if (hints & Qt::ImhFormattedNumbersOnly)
- self.keyboardType = UIKeyboardTypeDecimalPad;
- else if (hints & Qt::ImhDialableCharactersOnly)
- self.keyboardType = UIKeyboardTypeNumberPad;
- else
- self.keyboardType = UIKeyboardTypeDefault;
-}
-
@end
@implementation UIView (QIOS)
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
new file mode 100644
index 0000000000..575dedab89
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import <UIKit/UIKit.h>
+#include "qioswindow.h"
+
+@interface QUIView : UIView
+{
+@public
+ UITextAutocapitalizationType autocapitalizationType;
+ UITextAutocorrectionType autocorrectionType;
+ BOOL enablesReturnKeyAutomatically;
+ UIKeyboardAppearance keyboardAppearance;
+ UIKeyboardType keyboardType;
+ UIReturnKeyType returnKeyType;
+ BOOL secureTextEntry;
+ QIOSWindow *m_qioswindow;
+ QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ int m_nextTouchId;
+ QString m_markedText;
+ BOOL m_inSendEventToFocusObject;
+}
+
+@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;
+@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
+@property(nonatomic) UITextAutocorrectionType autocorrectionType;
+@property(nonatomic) UITextSpellCheckingType spellCheckingType;
+@property(nonatomic) BOOL enablesReturnKeyAutomatically;
+@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
+@property(nonatomic) UIKeyboardType keyboardType;
+@property(nonatomic) UIReturnKeyType returnKeyType;
+@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
+
+@end
+
+@interface QUIView (TextInput) <UITextInput>
+- (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query;
+- (void)reset;
+- (void)commit;
+@end
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
new file mode 100644
index 0000000000..d0088d415a
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -0,0 +1,557 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtextformat.h>
+
+class StaticVariables
+{
+public:
+ QInputMethodQueryEvent inputMethodQueryEvent;
+ QTextCharFormat markedTextFormat;
+
+ StaticVariables() : inputMethodQueryEvent(Qt::ImQueryInput)
+ {
+ // There seems to be no way to query how the preedit text
+ // should be drawn. So we need to hard-code the color.
+ QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
+ if (iosVersion < QSysInfo::MV_IOS_7_0)
+ markedTextFormat.setBackground(QColor(235, 239, 247));
+ else
+ markedTextFormat.setBackground(QColor(206, 221, 238));
+ }
+};
+
+Q_GLOBAL_STATIC(StaticVariables, staticVariables);
+
+// -------------------------------------------------------------------------
+
+@interface QUITextPosition : UITextPosition
+{
+}
+
+@property (nonatomic) NSUInteger index;
++ (QUITextPosition *)positionWithIndex:(NSUInteger)index;
+
+@end
+
+@implementation QUITextPosition
+
++ (QUITextPosition *)positionWithIndex:(NSUInteger)index
+{
+ QUITextPosition *pos = [[QUITextPosition alloc] init];
+ pos.index = index;
+ return [pos autorelease];
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+@interface QUITextRange : UITextRange
+{
+}
+
+@property (nonatomic) NSRange range;
++ (QUITextRange *)rangeWithNSRange:(NSRange)range;
+
+@end
+
+@implementation QUITextRange
+
++ (QUITextRange *)rangeWithNSRange:(NSRange)nsrange
+{
+ QUITextRange *range = [[QUITextRange alloc] init];
+ range.range = nsrange;
+ return [range autorelease];
+}
+
+- (UITextPosition *)start
+{
+ return [QUITextPosition positionWithIndex:self.range.location];
+}
+
+- (UITextPosition *)end
+{
+ return [QUITextPosition positionWithIndex:(self.range.location + self.range.length)];
+}
+
+- (NSRange) range
+{
+ return _range;
+}
+
+-(BOOL)isEmpty
+{
+ return (self.range.length == 0);
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+@implementation QUIView (TextInput)
+
+- (BOOL)canBecomeFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)becomeFirstResponder
+{
+ // Note: QIOSInputContext controls our first responder status based on
+ // whether or not the keyboard should be open or closed.
+ [self updateTextInputTraits];
+ return [super becomeFirstResponder];
+}
+
+- (BOOL)resignFirstResponder
+{
+ // Resigning first responed status means that the virtual keyboard was closed, or
+ // some other view became first responder. In either case we clear the focus object to
+ // avoid blinking cursors in line edits etc:
+ if (m_qioswindow)
+ static_cast<QWindowPrivate *>(QObjectPrivate::get(m_qioswindow->window()))->clearFocusObject();
+ return [super resignFirstResponder];
+}
+
+- (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query
+{
+ Q_UNUSED(query);
+
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+
+ if (!m_inSendEventToFocusObject) {
+ if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition))
+ [self.inputDelegate selectionWillChange:id<UITextInput>(self)];
+ if (query & Qt::ImSurroundingText)
+ [self.inputDelegate textWillChange:id<UITextInput>(self)];
+ }
+
+ // Note that we ignore \a query, and instead update using Qt::ImQueryInput. This enables us to just
+ // store the event without copying out the result from the event each time. Besides, we seem to be
+ // called with Qt::ImQueryInput when only changing selection, and always if typing text. So there would
+ // not be any performance gain by only updating \a query.
+ staticVariables()->inputMethodQueryEvent = QInputMethodQueryEvent(Qt::ImQueryInput);
+ QCoreApplication::sendEvent(focusObject, &staticVariables()->inputMethodQueryEvent);
+
+ if (!m_inSendEventToFocusObject) {
+ if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition))
+ [self.inputDelegate selectionDidChange:id<UITextInput>(self)];
+ if (query & Qt::ImSurroundingText)
+ [self.inputDelegate textDidChange:id<UITextInput>(self)];
+ }
+}
+
+- (void)sendEventToFocusObject:(QEvent &)e
+{
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+
+ // While sending the event, we will receive back updateInputMethodWithQuery calls.
+ // To not confuse iOS, we cannot not call textWillChange/textDidChange at that
+ // point since it will cause spell checking etc to fail. So we use a guard.
+ m_inSendEventToFocusObject = YES;
+ QCoreApplication::sendEvent(focusObject, &e);
+ m_inSendEventToFocusObject = NO;
+}
+
+- (void)reset
+{
+ [self.inputDelegate textWillChange:id<UITextInput>(self)];
+ [self setMarkedText:@"" selectedRange:NSMakeRange(0, 0)];
+ [self updateInputMethodWithQuery:Qt::ImQueryInput];
+
+ if ([self isFirstResponder]) {
+ // There seem to be no way to inform that the keyboard needs to update (since
+ // text input traits might have changed). As a work-around, we quickly resign
+ // first responder status just to reassign it again:
+ [super resignFirstResponder];
+ [self updateTextInputTraits];
+ [super becomeFirstResponder];
+ }
+ [self.inputDelegate textDidChange:id<UITextInput>(self)];
+}
+
+- (void)commit
+{
+ [self.inputDelegate textWillChange:id<UITextInput>(self)];
+ [self unmarkText];
+ [self.inputDelegate textDidChange:id<UITextInput>(self)];
+}
+
+- (QVariant)imValue:(Qt::InputMethodQuery)query
+{
+ return staticVariables()->inputMethodQueryEvent.value(query);
+}
+
+-(id<UITextInputTokenizer>)tokenizer
+{
+ return [[[UITextInputStringTokenizer alloc] initWithTextInput:id<UITextInput>(self)] autorelease];
+}
+
+-(UITextPosition *)beginningOfDocument
+{
+ return [QUITextPosition positionWithIndex:0];
+}
+
+-(UITextPosition *)endOfDocument
+{
+ int endPosition = [self imValue:Qt::ImSurroundingText].toString().length();
+ return [QUITextPosition positionWithIndex:endPosition];
+}
+
+- (void)setSelectedTextRange:(UITextRange *)range
+{
+ QUITextRange *r = static_cast<QUITextRange *>(range);
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, r.range.location, r.range.length, 0);
+ QInputMethodEvent e(m_markedText, attrs);
+ [self sendEventToFocusObject:e];
+}
+
+- (UITextRange *)selectedTextRange {
+ int cursorPos = [self imValue:Qt::ImCursorPosition].toInt();
+ int anchorPos = [self imValue:Qt::ImAnchorPosition].toInt();
+ return [QUITextRange rangeWithNSRange:NSMakeRange(cursorPos, (anchorPos - cursorPos))];
+}
+
+- (NSString *)textInRange:(UITextRange *)range
+{
+ int s = static_cast<QUITextPosition *>([range start]).index;
+ int e = static_cast<QUITextPosition *>([range end]).index;
+ return [self imValue:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString();
+}
+
+- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
+{
+ Q_UNUSED(selectedRange);
+
+ m_markedText = markedText ? QString::fromNSString(markedText) : QString();
+
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, markedText.length, staticVariables()->markedTextFormat);
+ QInputMethodEvent e(m_markedText, attrs);
+ [self sendEventToFocusObject:e];
+}
+
+- (void)unmarkText
+{
+ if (m_markedText.isEmpty())
+ return;
+
+ QInputMethodEvent e;
+ e.setCommitString(m_markedText);
+ [self sendEventToFocusObject:e];
+
+ m_markedText.clear();
+}
+
+- (NSComparisonResult)comparePosition:(UITextPosition *)position toPosition:(UITextPosition *)other
+{
+ int p = static_cast<QUITextPosition *>(position).index;
+ int o = static_cast<QUITextPosition *>(other).index;
+ if (p > o)
+ return NSOrderedAscending;
+ else if (p < o)
+ return NSOrderedDescending;
+ return NSOrderedSame;
+}
+
+- (UITextRange *)markedTextRange {
+ return m_markedText.isEmpty() ? nil : [QUITextRange rangeWithNSRange:NSMakeRange(0, m_markedText.length())];
+}
+
+- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition
+{
+ int f = static_cast<QUITextPosition *>(fromPosition).index;
+ int t = static_cast<QUITextPosition *>(toPosition).index;
+ return [QUITextRange rangeWithNSRange:NSMakeRange(f, t - f)];
+}
+
+- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset
+{
+ int p = static_cast<QUITextPosition *>(position).index;
+ return [QUITextPosition positionWithIndex:p + offset];
+}
+
+- (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset
+{
+ int p = static_cast<QUITextPosition *>(position).index;
+ return [QUITextPosition positionWithIndex:(direction == UITextLayoutDirectionRight ? p + offset : p - offset)];
+}
+
+- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction
+{
+ NSRange r = static_cast<QUITextRange *>(range).range;
+ if (direction == UITextLayoutDirectionRight)
+ return [QUITextPosition positionWithIndex:r.location + r.length];
+ return [QUITextPosition positionWithIndex:r.location];
+}
+
+- (NSInteger)offsetFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition
+{
+ int f = static_cast<QUITextPosition *>(fromPosition).index;
+ int t = static_cast<QUITextPosition *>(toPosition).index;
+ return t - f;
+}
+
+- (UIView *)textInputView
+{
+ // iOS expects rects we return from other UITextInput methods
+ // to be relative to the view this method returns.
+ // Since QInputMethod returns rects relative to the top level
+ // QWindow, that is also the view we need to return.
+ QPlatformWindow *topLevel = m_qioswindow;
+ while (QPlatformWindow *p = topLevel->parent())
+ topLevel = p;
+ return reinterpret_cast<UIView *>(topLevel->winId());
+}
+
+- (CGRect)firstRectForRange:(UITextRange *)range
+{
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return CGRectZero;
+
+ // Using a work-around to get the current rect until
+ // a better API is in place:
+ if (!m_markedText.isEmpty())
+ return CGRectZero;
+
+ int cursorPos = [self imValue:Qt::ImCursorPosition].toInt();
+ int anchorPos = [self imValue:Qt::ImAnchorPosition].toInt();
+
+ NSRange r = static_cast<QUITextRange*>(range).range;
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, r.location, 0, 0);
+ QInputMethodEvent e(m_markedText, attrs);
+ [self sendEventToFocusObject:e];
+ QRectF startRect = qApp->inputMethod()->cursorRectangle();
+
+ attrs = QList<QInputMethodEvent::Attribute>();
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, r.location + r.length, 0, 0);
+ e = QInputMethodEvent(m_markedText, attrs);
+ [self sendEventToFocusObject:e];
+ QRectF endRect = qApp->inputMethod()->cursorRectangle();
+
+ if (cursorPos != int(r.location + r.length) || cursorPos != anchorPos) {
+ attrs = QList<QInputMethodEvent::Attribute>();
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, cursorPos, (cursorPos - anchorPos), 0);
+ e = QInputMethodEvent(m_markedText, attrs);
+ [self sendEventToFocusObject:e];
+ }
+
+ return toCGRect(startRect.united(endRect));
+}
+
+- (CGRect)caretRectForPosition:(UITextPosition *)position
+{
+ Q_UNUSED(position);
+ // Assume for now that position is always the same as
+ // cursor index until a better API is in place:
+ QRectF cursorRect = qApp->inputMethod()->cursorRectangle();
+ return toCGRect(cursorRect);
+}
+
+- (void)replaceRange:(UITextRange *)range withText:(NSString *)text
+{
+ [self setSelectedTextRange:range];
+
+ QInputMethodEvent e;
+ e.setCommitString(QString::fromNSString(text));
+ [self sendEventToFocusObject:e];
+}
+
+- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
+{
+ Q_UNUSED(writingDirection);
+ Q_UNUSED(range);
+ // Writing direction is handled by QLocale
+}
+
+- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+{
+ Q_UNUSED(position);
+ Q_UNUSED(direction);
+ if (QLocale::system().textDirection() == Qt::RightToLeft)
+ return UITextWritingDirectionRightToLeft;
+ return UITextWritingDirectionLeftToRight;
+}
+
+- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction
+{
+ int p = static_cast<QUITextPosition *>(position).index;
+ if (direction == UITextLayoutDirectionLeft)
+ return [QUITextRange rangeWithNSRange:NSMakeRange(0, p)];
+ int l = [self imValue:Qt::ImSurroundingText].toString().length();
+ return [QUITextRange rangeWithNSRange:NSMakeRange(p, l - p)];
+}
+
+- (UITextPosition *)closestPositionToPoint:(CGPoint)point
+{
+ // No API in Qt for determining this. Use sensible default instead:
+ Q_UNUSED(point);
+ return [QUITextPosition positionWithIndex:[self imValue:Qt::ImCursorPosition].toInt()];
+}
+
+- (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range
+{
+ // No API in Qt for determining this. Use sensible default instead:
+ Q_UNUSED(point);
+ Q_UNUSED(range);
+ return [QUITextPosition positionWithIndex:[self imValue:Qt::ImCursorPosition].toInt()];
+}
+
+- (UITextRange *)characterRangeAtPoint:(CGPoint)point
+{
+ // No API in Qt for determining this. Use sensible default instead:
+ Q_UNUSED(point);
+ return [QUITextRange rangeWithNSRange:NSMakeRange([self imValue:Qt::ImCursorPosition].toInt(), 0)];
+}
+
+- (void)setMarkedTextStyle:(NSDictionary *)style
+{
+ Q_UNUSED(style);
+ // No-one is going to change our style. If UIKit itself did that
+ // it would be very welcome, since then we knew how to style marked
+ // text instead of just guessing...
+}
+
+- (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+{
+ Q_UNUSED(position);
+ Q_UNUSED(direction);
+
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return [NSDictionary dictionary];
+
+ // Assume position is the same as the cursor for now. QInputMethodQueryEvent with Qt::ImFont
+ // needs to be extended to take an extra position argument before this can be fully correct.
+ QInputMethodQueryEvent e(Qt::ImFont);
+ QCoreApplication::sendEvent(focusObject, &e);
+ QFont qfont = qvariant_cast<QFont>(e.value(Qt::ImFont));
+ UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()];
+ return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey];
+}
+
+-(NSDictionary *)markedTextStyle
+{
+ return [NSDictionary dictionary];
+}
+
+- (BOOL)hasText
+{
+ return YES;
+}
+
+- (void)insertText:(NSString *)text
+{
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+
+ if ([text isEqualToString:@"\n"] && self.returnKeyType == UIReturnKeyDone)
+ [self resignFirstResponder];
+
+ QInputMethodEvent e;
+ e.setCommitString(QString::fromNSString(text));
+ [self sendEventToFocusObject:e];
+}
+
+- (void)deleteBackward
+{
+ // Since we're posting im events directly to the focus object, we should do the
+ // same for key events. Otherwise they might end up in a different place or out
+ // of sync with im events.
+ QKeyEvent press(QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier);
+ QKeyEvent release(QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
+ [self sendEventToFocusObject:press];
+ [self sendEventToFocusObject:release];
+}
+
+- (void)updateTextInputTraits
+{
+ // Ask the current focus object what kind of input it
+ // expects, and configure the keyboard appropriately:
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
+ if (!QCoreApplication::sendEvent(focusObject, &queryEvent))
+ return;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return;
+
+ Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
+
+ self.returnKeyType = (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone;
+ self.secureTextEntry = BOOL(hints & Qt::ImhHiddenText);
+ self.autocorrectionType = (hints & Qt::ImhNoPredictiveText) ?
+ UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault;
+ self.spellCheckingType = (hints & Qt::ImhNoPredictiveText) ?
+ UITextSpellCheckingTypeNo : UITextSpellCheckingTypeDefault;
+
+ if (hints & Qt::ImhUppercaseOnly)
+ self.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
+ else if (hints & Qt::ImhNoAutoUppercase)
+ self.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ else
+ self.autocapitalizationType = UITextAutocapitalizationTypeSentences;
+
+ if (hints & Qt::ImhUrlCharactersOnly)
+ self.keyboardType = UIKeyboardTypeURL;
+ else if (hints & Qt::ImhEmailCharactersOnly)
+ self.keyboardType = UIKeyboardTypeEmailAddress;
+ else if (hints & Qt::ImhDigitsOnly)
+ self.keyboardType = UIKeyboardTypeNumberPad;
+ else if (hints & Qt::ImhFormattedNumbersOnly)
+ self.keyboardType = UIKeyboardTypeDecimalPad;
+ else if (hints & Qt::ImhDialableCharactersOnly)
+ self.keyboardType = UIKeyboardTypeNumberPad;
+ else
+ self.keyboardType = UIKeyboardTypeDefault;
+}
+
+@end
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
index 63c6d08bdc..868886a0dd 100644
--- a/src/plugins/platforms/kms/qkmsintegration.cpp
+++ b/src/plugins/platforms/kms/qkmsintegration.cpp
@@ -66,9 +66,28 @@ QT_BEGIN_NAMESPACE
QKmsIntegration::QKmsIntegration()
: QPlatformIntegration(),
m_fontDatabase(new QGenericUnixFontDatabase()),
- m_nativeInterface(new QKmsNativeInterface)
+ m_nativeInterface(new QKmsNativeInterface),
+ m_vtHandler(0),
+ m_deviceDiscovery(0)
{
- setenv("EGL_PLATFORM", "drm",1);
+}
+
+QKmsIntegration::~QKmsIntegration()
+{
+ delete m_deviceDiscovery;
+ foreach (QKmsDevice *device, m_devices) {
+ delete device;
+ }
+ foreach (QPlatformScreen *screen, m_screens) {
+ delete screen;
+ }
+ delete m_fontDatabase;
+ delete m_vtHandler;
+}
+
+void QKmsIntegration::initialize()
+{
+ qputenv("EGL_PLATFORM", "drm");
m_vtHandler = new QFbVtHandler;
m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_DRM | QDeviceDiscovery::Device_DRM_PrimaryGPU, 0);
@@ -88,19 +107,6 @@ QKmsIntegration::QKmsIntegration()
#endif
}
-QKmsIntegration::~QKmsIntegration()
-{
- delete m_deviceDiscovery;
- foreach (QKmsDevice *device, m_devices) {
- delete device;
- }
- foreach (QPlatformScreen *screen, m_screens) {
- delete screen;
- }
- delete m_fontDatabase;
- delete m_vtHandler;
-}
-
void QKmsIntegration::addDevice(const QString &deviceNode)
{
m_devices.append(new QKmsDevice(deviceNode, this));
diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h
index bba4f53d7c..3d3f1722e9 100644
--- a/src/plugins/platforms/kms/qkmsintegration.h
+++ b/src/plugins/platforms/kms/qkmsintegration.h
@@ -60,16 +60,17 @@ public:
QKmsIntegration();
~QKmsIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const;
+ void initialize() Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
- QPlatformWindow *createPlatformWindow(QWindow *window) const;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformFontDatabase *fontDatabase() const;
- QAbstractEventDispatcher *createEventDispatcher() const;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
- QPlatformNativeInterface *nativeInterface() const;
+ QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
void addScreen(QKmsScreen *screen);
QObject *createDevice(const char *);
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 8380aba13b..b69ec1e30f 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -969,7 +969,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (lParam & ENDSESSION_LOGOFF)
fflush(NULL);
- return !sessionManager->wasCanceled();
+ *result = sessionManager->wasCanceled() ? 0 : 1;
+ return true;
}
case QtWindows::EndSessionApplicationEvent: {
QWindowsSessionManager *sessionManager = platformSessionManager();
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 2abfb426cc..f0770d7d18 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -502,11 +502,31 @@ template <class BaseClass>
QWindowsDialogHelperBase<BaseClass>::QWindowsDialogHelperBase() :
m_nativeDialog(0),
m_ownerWindow(0),
- m_timerId(0)
+ m_timerId(0),
+ m_thread(0)
{
}
template <class BaseClass>
+void QWindowsDialogHelperBase<BaseClass>::cleanupThread()
+{
+ if (m_thread) { // Thread may be running if the dialog failed to close.
+ if (m_thread->isRunning())
+ m_thread->wait(500);
+ if (m_thread->isRunning()) {
+ m_thread->terminate();
+ m_thread->wait(300);
+ if (m_thread->isRunning())
+ qCCritical(lcQpaDialogs) <<__FUNCTION__ << "Failed to terminate thread.";
+ else
+ qCWarning(lcQpaDialogs) << __FUNCTION__ << "Thread terminated.";
+ }
+ delete m_thread;
+ m_thread = 0;
+ }
+}
+
+template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() const
{
if (m_nativeDialog.isNull()) {
@@ -559,7 +579,6 @@ void QWindowsDialogThread::run()
{
qCDebug(lcQpaDialogs) << '>' << __FUNCTION__;
m_dialog->exec(m_owner);
- deleteLater();
qCDebug(lcQpaDialogs) << '<' << __FUNCTION__;
}
@@ -587,6 +606,7 @@ bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
// a subsequent call to exec() may follow. So, start an idle timer
// which will start the dialog thread. If exec() is then called, the
// timer is stopped and dialog->exec() is called directly.
+ cleanupThread();
if (modal) {
m_timerId = this->startTimer(0);
} else {
@@ -599,8 +619,9 @@ template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::startDialogThread()
{
Q_ASSERT(!m_nativeDialog.isNull());
- QWindowsDialogThread *thread = new QWindowsDialogThread(m_nativeDialog, m_ownerWindow);
- thread->start();
+ Q_ASSERT(!m_thread);
+ m_thread = new QWindowsDialogThread(m_nativeDialog, m_ownerWindow);
+ m_thread->start();
stopTimer();
}
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 1501b02bd9..bcf9f544b5 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
class QFileDialog;
class QDialog;
+class QThread;
class QWindowsNativeDialogBase;
namespace QWindowsDialogs
@@ -68,6 +69,7 @@ class QWindowsDialogHelperBase : public BaseClass
Q_DISABLE_COPY(QWindowsDialogHelperBase)
public:
typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
+ ~QWindowsDialogHelperBase() { cleanupThread(); }
virtual void exec();
virtual bool show(Qt::WindowFlags windowFlags,
@@ -88,10 +90,12 @@ private:
inline QWindowsNativeDialogBase *ensureNativeDialog();
inline void startDialogThread();
inline void stopTimer();
+ void cleanupThread();
QWindowsNativeDialogBasePtr m_nativeDialog;
HWND m_ownerWindow;
int m_timerId;
+ QThread *m_thread;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 8f3ccdc0be..60c3daff23 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -673,14 +673,6 @@ QWindowsOleDropTarget::Release(void)
return m_refs;
}
-QWindow *QWindowsOleDropTarget::findDragOverWindow(const POINTL &pt) const
-{
- if (QWindowsWindow *child =
- QWindowsWindow::baseWindowOf(m_window)->childAtScreenPoint(QPoint(pt.x, pt.y)))
- return child->window();
- return m_window;
-}
-
void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
const QPoint &point, LPDWORD pdwEffect)
{
@@ -735,10 +727,9 @@ QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
dh->DragOver(reinterpret_cast<POINT*>(&pt), *pdwEffect);
- QWindow *dragOverWindow = findDragOverWindow(pt);
- qCDebug(lcQpaMime) << __FUNCTION__ << "widget=" << dragOverWindow << " key=" << grfKeyState
+ qCDebug(lcQpaMime) << __FUNCTION__ << "m_window" << m_window << "key=" << grfKeyState
<< "pt=" << pt.x << pt.y;
- const QPoint tmpPoint = QWindowsGeometryHint::mapFromGlobal(dragOverWindow, QPoint(pt.x,pt.y));
+ const QPoint tmpPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
// see if we should compress this event
if ((tmpPoint == m_lastPoint || m_answerRect.contains(tmpPoint))
&& m_lastKeyState == grfKeyState) {
@@ -747,7 +738,7 @@ QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
return NOERROR;
}
- handleDrag(dragOverWindow, grfKeyState, tmpPoint, pdwEffect);
+ handleDrag(m_window, grfKeyState, tmpPoint, pdwEffect);
return NOERROR;
}
@@ -774,12 +765,10 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
dh->Drop(pDataObj, reinterpret_cast<POINT*>(&pt), *pdwEffect);
- QWindow *dropWindow = findDragOverWindow(pt);
-
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window
- << " on " << dropWindow << " keys=" << grfKeyState << " pt=" << pt.x << ',' << pt.y;
+ << "keys=" << grfKeyState << "pt=" << pt.x << ',' << pt.y;
- m_lastPoint = QWindowsGeometryHint::mapFromGlobal(dropWindow, QPoint(pt.x,pt.y));
+ m_lastPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
// grfKeyState does not all ways contain button state in the drop so if
// it doesn't then use the last known button state;
if ((grfKeyState & KEY_STATE_BUTTON_MASK) == 0)
@@ -789,7 +778,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const QPlatformDropQtResponse response =
- QWindowSystemInterface::handleDrop(dropWindow, windowsDrag->dropData(), m_lastPoint,
+ QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(), m_lastPoint,
translateToQDragDropActions(*pdwEffect));
if (response.isAccepted()) {
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 33da4d6cc5..4f758fbf3f 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -74,7 +74,6 @@ public:
STDMETHOD(Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
private:
- inline QWindow *findDragOverWindow(const POINTL &pt) const;
void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect);
ULONG m_refs;
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index c273219181..3bd24fdaab 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -1038,12 +1038,12 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
removeApplicationFonts();
}
-QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle)
+QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
- QFontEngine *fe = QWindowsFontDatabase::createEngine(script, fontDef,
+ QFontEngine *fe = QWindowsFontDatabase::createEngine(QChar::Script_Common, fontDef,
0, QWindowsContext::instance()->defaultDPI(), false,
QStringList(), sharedFontData());
- qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << script << fe << handle;
+ qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle;
return fe;
}
@@ -1746,14 +1746,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ
QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, stockFont, lf, data);
if (preferClearTypeAA)
few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
-
- // Also check for OpenType tables when using complex scripts
- if (!few->supportsScript(QChar::Script(script))) {
- qWarning(" OpenType support missing for script %d", int(script));
- delete few;
- return 0;
- }
-
few->initFontInfo(request, fontHdc, dpi);
fe = few;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index 7dfcfbc2b5..1e13fc2559 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -78,7 +78,7 @@ public:
~QWindowsFontDatabase();
virtual void populateFontDatabase();
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index c4fc2f4759..c9160e4a75 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -422,10 +422,10 @@ void QWindowsFontDatabaseFT::populate(const QString &family)
ReleaseDC(0, dummy);
}
-QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle)
+QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle)
{
- QFontEngine *fe = QBasicFontDatabase::fontEngine(fontDef, script, handle);
- qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.family << script << fe << handle;
+ QFontEngine *fe = QBasicFontDatabase::fontEngine(fontDef, handle);
+ qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.family << fe << handle;
return fe;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 9544974ad1..bad6c54bf4 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -52,7 +52,7 @@ class QWindowsFontDatabaseFT : public QBasicFontDatabase
{
public:
void populateFontDatabase();
- QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index b046879314..9bfe4e6e26 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -988,7 +988,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
if (dummyWindow)
DestroyWindow(dummyWindow);
- qCDebug(lcQpaGl()) << __FUNCTION__ << this << (tryExtensions ? "ARB" : "GDI")
+ qCDebug(lcQpaGl) << __FUNCTION__ << this << (tryExtensions ? "ARB" : "GDI")
<< " requested: " << context->format()
<< "\n obtained #" << m_pixelFormat << (m_extensionsUsed ? "ARB" : "GDI") << m_obtainedFormat
<< "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInternal
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 5b6fced031..256967d25f 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -882,20 +882,8 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
setFlag(OpenGL_ES2);
#endif
}
- if (aWindow->isTopLevel()) {
- switch (type) {
- case Qt::Window:
- case Qt::Dialog:
- case Qt::Sheet:
- case Qt::Drawer:
- case Qt::Popup:
- case Qt::Tool:
- registerDropSite();
- break;
- default:
- break;
- }
- }
+ updateDropSite();
+
#ifndef Q_OS_WINCE
if (QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) {
if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, 0)) {
@@ -944,7 +932,7 @@ void QWindowsWindow::destroyWindow()
context->clearWindowUnderMouse();
if (hasMouseCapture())
setMouseGrabEnabled(false);
- unregisterDropSite();
+ setDropSiteEnabled(false);
#ifdef QT_OPENGL_ES_2
if (m_eglSurface) {
qCDebug(lcQpaGl) << __FUNCTION__ << "Freeing EGL surface " << m_eglSurface << window();
@@ -967,31 +955,44 @@ void QWindowsWindow::destroyWindow()
}
}
-void QWindowsWindow::registerDropSite()
+void QWindowsWindow::updateDropSite()
{
-#ifndef QT_NO_CLIPBOARD
-# ifndef QT_NO_DRAGANDDROP
- if (m_data.hwnd && !m_dropTarget) {
- m_dropTarget = new QWindowsOleDropTarget(window());
- RegisterDragDrop(m_data.hwnd, m_dropTarget);
- CoLockObjectExternal(m_dropTarget, true, true);
+ bool enabled = false;
+ if (window()->isTopLevel()) {
+ switch (window()->type()) {
+ case Qt::Window:
+ case Qt::Dialog:
+ case Qt::Sheet:
+ case Qt::Drawer:
+ case Qt::Popup:
+ case Qt::Tool:
+ enabled = true;
+ break;
+ default:
+ break;
+ }
}
-# endif // !QT_NO_DRAGANDDROP
-#endif // !QT_NO_CLIPBOARD
+ setDropSiteEnabled(enabled);
}
-void QWindowsWindow::unregisterDropSite()
+void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
{
-#ifndef QT_NO_CLIPBOARD
-# ifndef QT_NO_DRAGANDDROP
- if (m_data.hwnd && m_dropTarget) {
+ if (isDropSiteEnabled() == dropEnabled)
+ return;
+ qCDebug(lcQpaMime) << __FUNCTION__ << window() << dropEnabled;
+#if !defined(QT_NO_CLIPBOARD) && !defined(QT_NO_DRAGANDDROP)
+ if (dropEnabled) {
+ Q_ASSERT(m_data.hwnd);
+ m_dropTarget = new QWindowsOleDropTarget(window());
+ RegisterDragDrop(m_data.hwnd, m_dropTarget);
+ CoLockObjectExternal(m_dropTarget, true, true);
+ } else {
m_dropTarget->Release();
CoLockObjectExternal(m_dropTarget, false, true);
RevokeDragDrop(m_data.hwnd);
m_dropTarget = 0;
}
-# endif // !QT_NO_DRAGANDDROP
-#endif // !QT_NO_CLIPBOARD
+#endif // !QT_NO_CLIPBOARD && !QT_NO_DRAGANDDROP
}
// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
@@ -1188,7 +1189,7 @@ void QWindowsWindow::setParent(const QPlatformWindow *newParent)
setParent_sys(newParent);
}
-void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
+void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
{
// Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels
HWND oldParentHWND = GetAncestor(m_data.hwnd, GA_PARENT);
@@ -1217,8 +1218,11 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
// WS_CHILD/WS_POPUP must be manually set/cleared in addition
// to dialog frames, etc (see SetParent() ) if the top level state changes.
// Force toplevel state as QWindow::isTopLevel cannot be relied upon here.
- if (wasTopLevel != isTopLevel)
+ if (wasTopLevel != isTopLevel) {
+ setDropSiteEnabled(false);
setWindowFlags_sys(window()->flags(), unsigned(isTopLevel ? WindowCreationData::ForceTopLevel : WindowCreationData::ForceChild));
+ updateDropSite();
+ }
}
}
@@ -1234,6 +1238,28 @@ void QWindowsWindow::handleCompositionSettingsChanged()
applyBlurBehindWindow(handle());
}
+static QRect normalFrameGeometry(HWND hwnd)
+{
+#ifndef Q_OS_WINCE
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(WINDOWPLACEMENT);
+ if (GetWindowPlacement(hwnd, &wp))
+ return qrectFromRECT(wp.rcNormalPosition);
+#else
+ Q_UNUSED(hwnd)
+#endif
+ return QRect();
+}
+
+QRect QWindowsWindow::normalGeometry() const
+{
+ // Check for fake 'fullscreen' mode.
+ const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen;
+ const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
+ const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
+ return frame.isValid() ? frame.marginsRemoved(margins) : frame;
+}
+
void QWindowsWindow::setGeometry(const QRect &rectIn)
{
QRect rect = rectIn;
@@ -1436,8 +1462,10 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
const QRect oldGeometry = geometry();
if (m_data.flags != flags) {
m_data.flags = flags;
- if (m_data.hwnd)
+ if (m_data.hwnd) {
m_data = setWindowFlags_sys(flags);
+ updateDropSite();
+ }
}
// When switching to a frameless window, geometry
// may change without a WM_MOVE. Report change manually.
@@ -1593,10 +1621,9 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
m_savedStyle = style();
#ifndef Q_OS_WINCE
if (oldState == Qt::WindowMinimized) {
- WINDOWPLACEMENT wp;
- wp.length = sizeof(WINDOWPLACEMENT);
- if (GetWindowPlacement(m_data.hwnd, &wp))
- m_savedFrameGeometry = qrectFromRECT(wp.rcNormalPosition);
+ const QRect nf = normalFrameGeometry(m_data.hwnd);
+ if (nf.isValid())
+ m_savedFrameGeometry = nf;
} else {
#endif
m_savedFrameGeometry = frameGeometry_sys();
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 3a9516e0e5..1d515fd2fe 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -162,6 +162,7 @@ public:
virtual QSurfaceFormat format() const { return m_format; }
virtual void setGeometry(const QRect &rect);
virtual QRect geometry() const { return m_data.geometry; }
+ QRect normalGeometry() const Q_DECL_OVERRIDE;
virtual void setVisible(bool visible);
bool isVisible() const;
@@ -277,11 +278,12 @@ private:
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
inline bool isFullScreen_sys() const;
inline void setWindowState_sys(Qt::WindowState newState);
- inline void setParent_sys(const QPlatformWindow *parent) const;
+ inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
void destroyWindow();
- void registerDropSite();
- void unregisterDropSite();
+ inline bool isDropSiteEnabled() const { return m_dropTarget != 0; }
+ void setDropSiteEnabled(bool enabled);
+ void updateDropSite();
void handleGeometryChange();
void handleWindowStateChange(Qt::WindowState state);
inline void destroyIcon();
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index ecbf28bab9..1803282071 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -145,18 +145,15 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
if (argc) {
int j = 1;
for (int i = 1; i < argc; i++) {
- char *arg = argv[i];
- if (arg) {
- if (!strcmp(arg, "-display") && i < argc - 1) {
- displayName = argv[++i];
- arg = 0;
- } else if (!strcmp(arg, "-name") && i < argc - 1) {
- m_instanceName = argv[++i];
- arg = 0;
- }
- }
- if (arg)
- argv[j++] = arg;
+ QByteArray arg(argv[i]);
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
+ if (arg == "-display" && i < argc - 1)
+ displayName = argv[++i];
+ else if (arg == "-name" && i < argc - 1)
+ m_instanceName = argv[++i];
+ else
+ argv[j++] = argv[i];
}
argc = j;
} // argc
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3d79f742b3..58abc7abfe 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1375,6 +1375,7 @@ void QXcbWindow::requestActivateWindow()
updateNetWmUserTime(connection()->time());
if (window()->isTopLevel()
+ && !(window()->flags() & Qt::X11BypassWindowManagerHint)
&& connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
xcb_client_message_event_t event;
@@ -1390,10 +1391,10 @@ void QXcbWindow::requestActivateWindow()
event.data.data32[4] = 0;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ } else {
+ Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
}
- Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
-
connection()->sync();
}
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index 67f2d8a911..4727262f3f 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -90,7 +90,7 @@ contains(QT_CONFIG, opengl) {
DEFINES += XCB_HAS_XCB_GLX
LIBS += -lxcb-glx
}
- } else:contains(QT_CONFIG, egl) {
+ } else:contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) {
DEFINES += XCB_USE_EGL
CONFIG += egl
HEADERS += qxcbeglsurface.h
diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp
index 4692fb5c3c..c0c8a759aa 100644
--- a/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -65,6 +65,15 @@
#ifndef QT_NO_PRINTPREVIEWDIALOG
+static void initResources()
+{
+ static bool resourcesInitialized = false;
+ if (!resourcesInitialized) {
+ Q_INIT_RESOURCE(qprintdialog);
+ resourcesInitialized = true;
+ }
+}
+
QT_BEGIN_NAMESPACE
namespace {
@@ -217,6 +226,8 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
{
Q_Q(QPrintPreviewDialog);
+ initResources();
+
if (_printer) {
preview = new QPrintPreviewWidget(_printer, q);
printer = _printer;
diff --git a/src/printsupport/printsupport.pro b/src/printsupport/printsupport.pro
index ee4f9f72df..a92d36f7bc 100644
--- a/src/printsupport/printsupport.pro
+++ b/src/printsupport/printsupport.pro
@@ -1,6 +1,7 @@
TARGET = QtPrintSupport
QT = core-private gui-private widgets-private
+MODULE_CONFIG = needs_printsupport_plugin
DEFINES += QT_NO_USING_NAMESPACE
QMAKE_DOCS = $$PWD/doc/qtprintsupport.qdocconf
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 1f84a4b5c4..fdf0fcdbdb 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -446,7 +446,8 @@ void QApplicationPrivate::process_cmdline()
continue;
}
QByteArray arg = argv[i];
- arg = arg;
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
QString s;
if (arg == "-qdevel" || arg == "-qdebug") {
// obsolete argument
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index c7f8e18118..672c4156cd 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -50,6 +50,7 @@
#include <private/qwidgetbackingstore_p.h>
#include <qpa/qwindowsysteminterface_p.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformwindow.h>
#include <private/qgesturemanager_p.h>
QT_BEGIN_NAMESPACE
@@ -547,6 +548,24 @@ void QWidgetWindow::updateGeometry()
m_widget->data->fstrut_dirty = false;
}
+Qt::WindowState effectiveState(Qt::WindowStates state);
+
+// Store normal geometry used for saving application settings.
+void QWidgetWindow::updateNormalGeometry()
+{
+ QTLWExtra *tle = m_widget->d_func()->maybeTopData();
+ if (!tle)
+ return;
+ // Ask platform window, default to widget geometry.
+ QRect normalGeometry;
+ if (const QPlatformWindow *pw = handle())
+ normalGeometry = pw->normalGeometry();
+ if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
+ normalGeometry = m_widget->geometry();
+ if (normalGeometry.isValid())
+ tle->normalGeometry = normalGeometry;
+}
+
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
updateGeometry();
@@ -692,8 +711,6 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
}
-Qt::WindowState effectiveState(Qt::WindowStates state);
-
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
{
// QWindow does currently not know 'active'.
@@ -712,16 +729,12 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
widgetState |= Qt::WindowMinimized;
break;
case Qt::WindowMaximized:
- if (effectiveState(widgetState) == Qt::WindowNoState)
- if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
- tle->normalGeometry = m_widget->geometry();
+ updateNormalGeometry();
widgetState |= Qt::WindowMaximized;
widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
break;
case Qt::WindowFullScreen:
- if (effectiveState(widgetState) == Qt::WindowNoState)
- if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
- tle->normalGeometry = m_widget->geometry();
+ updateNormalGeometry();
widgetState |= Qt::WindowFullScreen;
widgetState &= ~(Qt::WindowMinimized);
break;
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
index ffde44dd27..8d6f14a669 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -104,6 +104,7 @@ private slots:
private:
void updateGeometry();
+ void updateNormalGeometry();
enum FocusWidgets {
FirstFocusWidget,
diff --git a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
index e18f6f73b9..b00fd0dfd4 100644
--- a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
+++ b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
@@ -53,7 +53,11 @@ public:
// test data:
QTextCodec *codec;
QString (*from8BitPtr)(const char *, int);
+#ifdef Q_COMPILER_REF_QUALIFIERS
+ QByteArray (QString:: *to8Bit)() const &;
+#else
QByteArray (QString:: *to8Bit)() const;
+#endif
inline QString from8Bit(const QByteArray &ba)
{ return from8BitPtr(ba.constData(), ba.length()); }
diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
index 26f10385b3..47a5d6044e 100644
--- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
+++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
@@ -271,8 +271,8 @@ private slots:
QCOMPARE(defaultCategory.isEnabled(QtCriticalMsg), true);
QLoggingCategory customCategory("custom");
- QCOMPARE(customCategory.isDebugEnabled(), false);
- QCOMPARE(customCategory.isEnabled(QtDebugMsg), false);
+ QCOMPARE(customCategory.isDebugEnabled(), true);
+ QCOMPARE(customCategory.isEnabled(QtDebugMsg), true);
QCOMPARE(customCategory.isWarningEnabled(), true);
QCOMPARE(customCategory.isEnabled(QtWarningMsg), true);
QCOMPARE(customCategory.isCriticalEnabled(), true);
@@ -309,7 +309,7 @@ private slots:
QLoggingCategory cat("custom");
QCOMPARE(customCategoryFilterArgs, QStringList() << "custom");
- QVERIFY(cat.isDebugEnabled());
+ QVERIFY(!cat.isDebugEnabled());
customCategoryFilterArgs.clear();
// install default filter
@@ -319,7 +319,7 @@ private slots:
QCOMPARE(customCategoryFilterArgs.size(), 0);
QVERIFY(QLoggingCategory::defaultCategory()->isDebugEnabled());
- QVERIFY(!cat.isDebugEnabled());
+ QVERIFY(cat.isDebugEnabled());
// install default filter
currentFilter =
@@ -328,7 +328,7 @@ private slots:
QCOMPARE(customCategoryFilterArgs.size(), 0);
QVERIFY(QLoggingCategory::defaultCategory()->isDebugEnabled());
- QVERIFY(!cat.isDebugEnabled());
+ QVERIFY(cat.isDebugEnabled());
}
void qDebugMacros()
@@ -397,8 +397,12 @@ private slots:
QLoggingCategory customCategory("custom");
// Check custom debug
logMessage.clear();
+ buf = QStringLiteral("custom.debug: Check debug with no filter active");
+ qCDebug(customCategory, "Check debug with no filter active");
+ QCOMPARE(logMessage, buf);
+
qCDebug(customCategory) << "Check debug with no filter active";
- QCOMPARE(logMessage, QString());
+ QCOMPARE(logMessage, buf);
// Check custom warning
buf = QStringLiteral("custom.warning: Check warning with no filter active");
@@ -414,16 +418,16 @@ private slots:
QLoggingCategory::installFilter(customCategoryFilter);
// Check custom debug
- buf = QStringLiteral("custom.debug: Check debug with filter active");
+ logMessage.clear();
qCDebug(customCategory) << "Check debug with filter active";
- QCOMPARE(logMessage, buf);
+ QCOMPARE(logMessage, QString());
// Check different macro/category variants
buf = QStringLiteral("tst.log.debug: Check debug with no filter active");
qCDebug(TST_LOG) << "Check debug with no filter active";
- QCOMPARE(logMessage, buf);
+ QCOMPARE(logMessage, QString());
qCDebug(TST_LOG, "Check debug with no filter active");
- QCOMPARE(logMessage, buf);
+ QCOMPARE(logMessage, QString());
buf = QStringLiteral("tst.log.warning: Check warning with no filter active");
qCWarning(TST_LOG) << "Check warning with no filter active";
QCOMPARE(logMessage, buf);
@@ -441,8 +445,9 @@ private slots:
// Check custom debug
logMessage.clear();
+ buf = QStringLiteral("custom.debug: Check debug with no filter active");
qCDebug(customCategory) << "Check debug with no filter active";
- QCOMPARE(logMessage, QString());
+ QCOMPARE(logMessage, buf);
}
void checkLegacyMessageLogger()
@@ -477,11 +482,11 @@ private slots:
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
// Check category debug
- logMessage = "should not change";
- buf = logMessage;
+ buf = QStringLiteral("tst.log.debug: Check category Debug with no log active");
qCDebug(TST_LOG) << "Check category Debug with no log active";
QCOMPARE(logMessage, buf);
+
// Check default warning
buf = QStringLiteral("tst.log.warning: Check category Warning with no log active");
qCWarning(TST_LOG) << "Check category Warning with no log active";
@@ -763,8 +768,7 @@ private slots:
{
// "" -> custom category
QLoggingCategory mycategoryobject1("");
- logMessage = "no change";
- QString buf = QStringLiteral("no change");
+ QString buf = QStringLiteral(".debug: My Category Object");
qCDebug(mycategoryobject1) << "My Category Object";
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index b201028aad..629a095f9d 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -223,6 +223,8 @@ private slots:
void split_regexp();
void fromUtf16_data();
void fromUtf16();
+ void fromUtf16_char16_data();
+ void fromUtf16_char16();
void latin1String();
void nanAndInf();
void compare_data();
@@ -3968,14 +3970,15 @@ void tst_QString::fromAscii()
void tst_QString::fromUcs4()
{
+ const uint *null = 0;
QString s;
- s = QString::fromUcs4( 0 );
+ s = QString::fromUcs4( null );
QVERIFY( s.isNull() );
QCOMPARE( s.size(), 0 );
- s = QString::fromUcs4( 0, 0 );
+ s = QString::fromUcs4( null, 0 );
QVERIFY( s.isNull() );
QCOMPARE( s.size(), 0 );
- s = QString::fromUcs4( 0, 5 );
+ s = QString::fromUcs4( null, 5 );
QVERIFY( s.isNull() );
QCOMPARE( s.size(), 0 );
@@ -3996,20 +3999,98 @@ void tst_QString::fromUcs4()
s = QString::fromUcs4( &smp, 1 );
QVERIFY( !s.isNull() );
QCOMPARE( s.size(), 2 );
+
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ static const char32_t str1[] = U"Hello Unicode World";
+ s = QString::fromUcs4(str1, sizeof(str1) / sizeof(str1[0]) - 1);
+ QCOMPARE(s, QString("Hello Unicode World"));
+
+ s = QString::fromUcs4(str1);
+ QCOMPARE(s, QString("Hello Unicode World"));
+
+ s = QString::fromUcs4(str1, 5);
+ QCOMPARE(s, QString("Hello"));
+
+ s = QString::fromUcs4(U"\u221212\U000020AC\U00010000");
+ QCOMPARE(s, QString::fromUtf8("\342\210\222" "12" "\342\202\254" "\360\220\200\200"));
+#endif
}
void tst_QString::toUcs4()
{
QString s;
+ QVector<uint> ucs4;
QCOMPARE( s.toUcs4().size(), 0 );
- QChar bmp = QLatin1Char('a');
+ static const QChar bmp = QLatin1Char('a');
s = QString(&bmp, 1);
- QCOMPARE( s.toUcs4().size(), 1 );
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 1 );
+ QCOMPARE( ucs4.at(0), 0x0061u );
+
+#define QSTRING_FROM_QCHARARRAY(x) (QString((x), sizeof(x)/sizeof((x)[0])))
+
+ static const QChar smp[] = { QChar::highSurrogate(0x10000), QChar::lowSurrogate(0x10000) };
+ s = QSTRING_FROM_QCHARARRAY(smp);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 1 );
+ QCOMPARE( ucs4.at(0), 0x10000u );
+
+ static const QChar smp2[] = { QChar::highSurrogate(0x10000), QChar::lowSurrogate(0x10000), QChar::highSurrogate(0x10000), QChar::lowSurrogate(0x10000) };
+ s = QSTRING_FROM_QCHARARRAY(smp2);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 2 );
+ QCOMPARE( ucs4.at(0), 0x10000u );
+ QCOMPARE( ucs4.at(1), 0x10000u );
+
+ static const QChar invalid_01[] = { QChar(0xd800) };
+ s = QSTRING_FROM_QCHARARRAY(invalid_01);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 1 );
+ QCOMPARE( ucs4.at(0), 0xFFFDu );
+
+ static const QChar invalid_02[] = { QChar(0xdc00) };
+ s = QSTRING_FROM_QCHARARRAY(invalid_02);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 1 );
+ QCOMPARE( ucs4.at(0), 0xFFFDu );
+
+ static const QChar invalid_03[] = { QLatin1Char('a'), QChar(0xd800), QLatin1Char('b') };
+ s = QSTRING_FROM_QCHARARRAY(invalid_03);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 3 );
+ QCOMPARE( ucs4.at(0), 0x0061u );
+ QCOMPARE( ucs4.at(1), 0xFFFDu );
+ QCOMPARE( ucs4.at(2), 0x0062u );
+
+ static const QChar invalid_04[] = { QLatin1Char('a'), QChar(0xdc00), QLatin1Char('b') };
+ s = QSTRING_FROM_QCHARARRAY(invalid_04);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 3 );
+ QCOMPARE( ucs4.at(0), 0x0061u );
+ QCOMPARE( ucs4.at(1), 0xFFFDu );
+ QCOMPARE( ucs4.at(2), 0x0062u );
+
+ static const QChar invalid_05[] = { QLatin1Char('a'), QChar(0xd800), QChar(0xd800), QLatin1Char('b') };
+ s = QSTRING_FROM_QCHARARRAY(invalid_05);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 4 );
+ QCOMPARE( ucs4.at(0), 0x0061u );
+ QCOMPARE( ucs4.at(1), 0xFFFDu );
+ QCOMPARE( ucs4.at(2), 0xFFFDu );
+ QCOMPARE( ucs4.at(3), 0x0062u );
+
+ static const QChar invalid_06[] = { QLatin1Char('a'), QChar(0xdc00), QChar(0xdc00), QLatin1Char('b') };
+ s = QSTRING_FROM_QCHARARRAY(invalid_06);
+ ucs4 = s.toUcs4();
+ QCOMPARE( ucs4.size(), 4 );
+ QCOMPARE( ucs4.at(0), 0x0061u );
+ QCOMPARE( ucs4.at(1), 0xFFFDu );
+ QCOMPARE( ucs4.at(2), 0xFFFDu );
+ QCOMPARE( ucs4.at(3), 0x0062u );
+
+#undef QSTRING_FROM_QCHARARRAY
- QChar smp[] = { QChar::highSurrogate(0x10000), QChar::lowSurrogate(0x10000) };
- s = QString(smp, 2);
- QCOMPARE( s.toUcs4().size(), 1 );
}
void tst_QString::arg()
@@ -4991,6 +5072,25 @@ void tst_QString::fromUtf16()
QCOMPARE(QString::fromUtf16(ucs2.utf16(), len), res);
}
+void tst_QString::fromUtf16_char16_data()
+{
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ fromUtf16_data();
+#else
+ QSKIP("Compiler does not support C++11 unicode strings");
+#endif
+}
+
+void tst_QString::fromUtf16_char16()
+{
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ QFETCH(QString, ucs2);
+ QFETCH(QString, res);
+ QFETCH(int, len);
+
+ QCOMPARE(QString::fromUtf16(reinterpret_cast<const char16_t *>(ucs2.utf16()), len), res);
+#endif
+}
void tst_QString::latin1String()
{
diff --git a/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro b/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro
new file mode 100644
index 0000000000..e5e625d520
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringiterator/qstringiterator.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qstringiterator
+QT = core core-private testlib
+SOURCES = tst_qstringiterator.cpp
+
diff --git a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp b/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
new file mode 100644
index 0000000000..d06d052676
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
@@ -0,0 +1,675 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QString>
+#include <private/qstringiterator_p.h>
+
+class tst_QStringIterator : public QObject
+{
+ Q_OBJECT
+private slots:
+ void sweep_data();
+ void sweep();
+
+ void position();
+};
+
+void tst_QStringIterator::sweep_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("sweep_00") << QString::fromUtf8("", 0) << true << 0;
+ QTest::newRow("sweep_01") << QString::fromUtf8("a", 1) << true << 1;
+ QTest::newRow("sweep_02") << QString::fromUtf8("a string", 8) << true << 8;
+ QTest::newRow("sweep_03") << QString::fromUtf8("\xc3\xa0\xc3\xa8\xc3\xac\xc3\xb2\xc3\xb9", 10) << true << 5;
+ QTest::newRow("sweep_04") << QString::fromUtf8("\xc3\x9f\xe2\x80\x94\xc2\xa1", 7) << true << 3;
+ QTest::newRow("sweep_05") << QString::fromUtf8("\xe6\xb0\xb4\xe6\xb0\xb5\xe6\xb0\xb6\xe6\xb0\xb7\xe6\xb0\xb8\xe6\xb0\xb9", 18) << true << 6;
+ QTest::newRow("sweep_06") << QString::fromUtf8("\xf0\x9f\x98\x81\xf0\x9f\x98\x82\x61\x62\x63\xf0\x9f\x98\x83\xc4\x91\xc3\xa8\xef\xac\x80\xf0\x9f\x98\x84\xf0\x9f\x98\x85", 30) << true << 11;
+ QTest::newRow("sweep_07") << QString::fromUtf8("\xf0\x9f\x82\xaa\xf0\x9f\x82\xab\xf0\x9f\x82\xad\xf0\x9f\x82\xae\xf0\x9f\x82\xa1\x20\x52\x4f\x59\x41\x4c\x20\x46\x4c\x55\x53\x48\x20\x4f\x46\x20\x53\x50\x41\x44\x45\x53", 42) << true << 27;
+ QTest::newRow("sweep_08") << QString::fromUtf8("abc\0def", 7) << true << 7;
+ QTest::newRow("sweep_09") << QString::fromUtf8("\xc3\xa0\xce\xb2\xc3\xa7\xf0\x9f\x80\xb9\xf0\x9f\x80\xb8\x00\xf0\x9f\x80\xb1\x00\xf0\x9f\x80\xb3\xf0\x9f\x81\x85\xe1\xb8\x8a\xc4\x99\xc6\x92", 35) << true << 13;
+
+ QTest::newRow("sweep_invalid_00") << QString(QChar(0xd800)) << false << 1;
+ QTest::newRow("sweep_invalid_01") << QString(QChar(0xdc00)) << false << 1;
+ QTest::newRow("sweep_invalid_02") << QString(QChar(0xdbff)) << false << 1;
+ QTest::newRow("sweep_invalid_03") << QString(QChar(0xdfff)) << false << 1;
+
+#define QSTRING_FROM_QCHARARRAY(x) (QString((x), sizeof(x)/sizeof((x)[0])))
+
+ static const QChar invalid_04[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xd800)
+ };
+ QTest::newRow("sweep_invalid_04") << QSTRING_FROM_QCHARARRAY(invalid_04) << false << 8;
+
+ static const QChar invalid_05[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xd800), QLatin1Char('x')
+ };
+ QTest::newRow("sweep_invalid_05") << QSTRING_FROM_QCHARARRAY(invalid_05) << false << 9;
+
+ static const QChar invalid_06[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xdc00)
+ };
+ QTest::newRow("sweep_invalid_06") << QSTRING_FROM_QCHARARRAY(invalid_06) << false << 8;
+
+ static const QChar invalid_07[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xdc00), QLatin1Char('x')
+ };
+ QTest::newRow("sweep_invalid_07") << QSTRING_FROM_QCHARARRAY(invalid_07) << false << 9;
+
+ static const QChar invalid_08[] = {
+ QChar(0xd800),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_08") << QSTRING_FROM_QCHARARRAY(invalid_08) << false << 8;
+
+ static const QChar invalid_09[] = {
+ QChar(0xdc00),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_09") << QSTRING_FROM_QCHARARRAY(invalid_09) << false << 8;
+
+ static const QChar invalid_10[] = {
+ QChar(0xd800), QChar(0xd800),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_10") << QSTRING_FROM_QCHARARRAY(invalid_10) << false << 9;
+
+ static const QChar invalid_11[] = {
+ QChar(0xdc00), QChar(0xd800),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_11") << QSTRING_FROM_QCHARARRAY(invalid_11) << false << 9;
+
+ static const QChar invalid_12[] = {
+ QChar(0xdc00), QChar(0xdc00),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_12") << QSTRING_FROM_QCHARARRAY(invalid_12) << false << 9;
+
+ static const QChar invalid_13[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xd800)
+ };
+ QTest::newRow("sweep_invalid_13") << QSTRING_FROM_QCHARARRAY(invalid_13) << false << 9;
+
+ static const QChar invalid_14[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xd800), QLatin1Char('x')
+ };
+ QTest::newRow("sweep_invalid_14") << QSTRING_FROM_QCHARARRAY(invalid_14) << false << 10;
+
+ static const QChar invalid_15[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xdc00)
+ };
+ QTest::newRow("sweep_invalid_15") << QSTRING_FROM_QCHARARRAY(invalid_15) << false << 9;
+
+ static const QChar invalid_16[] = {
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d'), QChar(0xdc00), QLatin1Char('x')
+ };
+ QTest::newRow("sweep_invalid_16") << QSTRING_FROM_QCHARARRAY(invalid_16) << false << 10;
+
+ static const QChar invalid_17[] = {
+ QChar(0xd800),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_17") << QSTRING_FROM_QCHARARRAY(invalid_17) << false << 9;
+
+ static const QChar invalid_18[] = {
+ QChar(0xdc00),
+ QLatin1Char('i'), QLatin1Char('n'), QLatin1Char('v'),
+ QChar(0xd800), QChar(0xdf00), // U+10300 OLD ITALIC LETTER A
+ QLatin1Char('a'), QLatin1Char('l'), QLatin1Char('i'),
+ QLatin1Char('d')
+ };
+ QTest::newRow("sweep_invalid_18") << QSTRING_FROM_QCHARARRAY(invalid_18) << false << 9;
+
+#undef QSTRING_FROM_QCHARARRAY
+}
+
+void tst_QStringIterator::sweep()
+{
+ QFETCH(QString, string);
+ QFETCH(bool, valid);
+
+ QStringIterator i(string);
+ int count = 0;
+ QString rebuiltString;
+
+ while (i.hasNext()) {
+ const uint peekedCodePoint = i.peekNext(~0u);
+ const uint codePoint = i.next(~0u);
+
+ QVERIFY(peekedCodePoint == codePoint);
+
+ if (codePoint == ~0u)
+ rebuiltString += *(i.position() - 1);
+ else
+ rebuiltString += QString::fromUcs4(&codePoint, 1);
+
+ ++count;
+ }
+
+ QTEST(count, "count");
+ QTEST(rebuiltString, "string");
+ rebuiltString.clear();
+
+ while (i.hasPrevious()) {
+ const uint peekedCodePoint = i.peekPrevious(~0u);
+ const uint codePoint = i.previous(~0u);
+
+ QVERIFY(peekedCodePoint == codePoint);
+
+ --count;
+ }
+
+ QCOMPARE(count, 0);
+
+ while (i.hasNext()) {
+ i.advance();
+ ++count;
+ }
+
+ QTEST(count, "count");
+
+ while (i.hasPrevious()) {
+ i.recede();
+ --count;
+ }
+
+ QCOMPARE(count, 0);
+
+ if (valid) {
+ while (i.hasNext()) {
+ const uint peekedCodePoint = i.peekNextUnchecked();
+ const uint codePoint = i.nextUnchecked();
+
+ QVERIFY(peekedCodePoint == codePoint);
+ QVERIFY(codePoint <= 0x10FFFFu);
+ rebuiltString += QString::fromUcs4(&codePoint, 1);
+ ++count;
+ }
+
+ QTEST(count, "count");
+ QTEST(rebuiltString, "string");
+
+ while (i.hasPrevious()) {
+ const uint peekedCodePoint = i.peekPreviousUnchecked();
+ const uint codePoint = i.previousUnchecked();
+
+ QVERIFY(peekedCodePoint == codePoint);
+
+ --count;
+ }
+
+ QCOMPARE(count, 0);
+
+ while (i.hasNext()) {
+ i.advanceUnchecked();
+ ++count;
+ }
+
+ QTEST(count, "count");
+
+ while (i.hasPrevious()) {
+ i.recedeUnchecked();
+ --count;
+ }
+
+ QCOMPARE(count, 0);
+ }
+}
+
+void tst_QStringIterator::position()
+{
+ static const QChar stringData[] =
+ {
+ // codeunit count: 0
+ QLatin1Char('a'), QLatin1Char('b'), QLatin1Char('c'),
+ // codeunit count: 3
+ QChar(0x00A9), // U+00A9 COPYRIGHT SIGN
+ // codeunit count: 4
+ QChar(0x00AE), // U+00AE REGISTERED SIGN
+ // codeunit count: 5
+ QLatin1Char('d'), QLatin1Char('e'), QLatin1Char('f'),
+ // codeunit count: 8
+ QLatin1Char('\0'),
+ // codeunit count: 9
+ QLatin1Char('g'), QLatin1Char('h'), QLatin1Char('i'),
+ // codeunit count: 12
+ QChar(0xD834), QChar(0xDD1E), // U+1D11E MUSICAL SYMBOL G CLEF
+ // codeunit count: 14
+ QChar(0xD834), QChar(0xDD21), // U+1D121 MUSICAL SYMBOL C CLEF
+ // codeunit count: 16
+ QLatin1Char('j'),
+ // codeunit count: 17
+ QChar(0xD800), // stray high surrogate
+ // codeunit count: 18
+ QLatin1Char('k'),
+ // codeunit count: 19
+ QChar(0xDC00), // stray low surrogate
+ // codeunit count: 20
+ QLatin1Char('l'),
+ // codeunit count: 21
+ QChar(0xD800), QChar(0xD800), // two high surrogates
+ // codeunit count: 23
+ QLatin1Char('m'),
+ // codeunit count: 24
+ QChar(0xDC00), QChar(0xDC00), // two low surrogates
+ // codeunit count: 26
+ QLatin1Char('n'),
+ // codeunit count: 27
+ QChar(0xD800), QChar(0xD800), QChar(0xDC00), // stray high surrogate followed by valid pair
+ // codeunit count: 30
+ QLatin1Char('o'),
+ // codeunit count: 31
+ QChar(0xDC00), QChar(0xD800), QChar(0xDC00), // stray low surrogate followed by valid pair
+ // codeunit count: 34
+ QLatin1Char('p')
+ // codeunit count: 35
+ };
+
+ const QString string(stringData, sizeof(stringData) / sizeof(stringData[0]));
+ QStringIterator i(string);
+
+ QCOMPARE(i.position(), string.constBegin());
+ QVERIFY(i.hasNext());
+ QVERIFY(!i.hasPrevious());
+
+ i.setPosition(string.constEnd());
+ QCOMPARE(i.position(), string.constEnd());
+ QVERIFY(!i.hasNext());
+ QVERIFY(i.hasPrevious());
+
+#define QCHAR_UNICODE_VALUE(x) ((uint)(QChar(x).unicode()))
+
+ const QString::const_iterator begin = string.constBegin();
+ i.setPosition(begin);
+ QCOMPARE(i.position(), begin);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('a')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('a')));
+
+ QCOMPARE(i.position(), begin + 1);
+
+ i.setPosition(begin + 2);
+ QCOMPARE(i.position(), begin + 2);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('c')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('c')));
+
+ QCOMPARE(i.position(), begin + 3);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(0x00A9));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(0x00A9));
+
+ QCOMPARE(i.position(), begin + 4);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(0x00AE));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(0x00AE));
+
+ QCOMPARE(i.position(), begin + 5);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(0x00AE));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(0x00AE));
+
+ QCOMPARE(i.position(), begin + 4);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(0x00A9));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(0x00A9));
+
+ QCOMPARE(i.position(), begin + 3);
+
+ i.setPosition(begin + 8);
+ QCOMPARE(i.position(), begin + 8);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
+
+ QCOMPARE(i.position(), begin + 9);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
+
+ QCOMPARE(i.position(), begin + 10);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('g')));
+
+ QCOMPARE(i.position(), begin + 9);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('\0')));
+
+ QCOMPARE(i.position(), begin + 8);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('f')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('f')));
+
+ QCOMPARE(i.position(), begin + 7);
+
+ i.advanceUnchecked();
+ i.advanceUnchecked();
+ i.advanceUnchecked();
+ i.advanceUnchecked();
+ i.advanceUnchecked();
+
+ QCOMPARE(i.position(), begin + 12);
+ QCOMPARE(i.peekNext(), 0x1D11Eu);
+ QCOMPARE(i.next(), 0x1D11Eu);
+
+ QCOMPARE(i.position(), begin + 14);
+ QCOMPARE(i.peekNext(), 0x1D121u);
+ QCOMPARE(i.next(), 0x1D121u);
+
+ QCOMPARE(i.position(), begin + 16);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+
+ QCOMPARE(i.position(), begin + 17);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+
+ QCOMPARE(i.position(), begin + 16);
+ QCOMPARE(i.peekPrevious(), 0x1D121u);
+ QCOMPARE(i.previous(), 0x1D121u);
+
+ QCOMPARE(i.position(), begin + 14);
+ QCOMPARE(i.peekPrevious(), 0x1D11Eu);
+ QCOMPARE(i.previous(), 0x1D11Eu);
+
+ QCOMPARE(i.position(), begin + 12);
+
+
+ i.setPosition(begin + 13);
+ QCOMPARE(i.position(), begin + 13);
+
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 14);
+ QCOMPARE(i.peekNext(), 0x1D121u);
+ QCOMPARE(i.next(), 0x1D121u);
+
+ QCOMPARE(i.position(), begin + 16);
+
+
+ i.setPosition(begin + 15);
+ QCOMPARE(i.position(), begin + 15);
+
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 14);
+ QCOMPARE(i.peekPrevious(), 0x1D11Eu);
+ QCOMPARE(i.previous(), 0x1D11Eu);
+
+ QCOMPARE(i.position(), begin + 12);
+
+ i.advanceUnchecked();
+ i.advanceUnchecked();
+
+ QCOMPARE(i.position(), begin + 16);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+
+ QCOMPARE(i.position(), begin + 17);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 18);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
+
+ QCOMPARE(i.position(), begin + 19);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 20);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
+
+ QCOMPARE(i.position(), begin + 21);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 22);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 23);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
+
+ QCOMPARE(i.position(), begin + 24);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 25);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 26);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
+
+ QCOMPARE(i.position(), begin + 27);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 28);
+ QCOMPARE(i.peekNext(), 0x10000u);
+ QCOMPARE(i.next(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 30);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+
+ QCOMPARE(i.position(), begin + 31);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 32);
+ QCOMPARE(i.peekNext(), 0x10000u);
+ QCOMPARE(i.next(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 34);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+
+ QVERIFY(!i.hasNext());
+
+ QCOMPARE(i.position(), begin + 35);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+
+ QCOMPARE(i.position(), begin + 34);
+ QCOMPARE(i.peekPrevious(), 0x10000u);
+ QCOMPARE(i.previous(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 32);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 31);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+
+ QCOMPARE(i.position(), begin + 30);
+ QCOMPARE(i.peekPrevious(), 0x10000u);
+ QCOMPARE(i.previous(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 28);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 27);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('n')));
+
+ QCOMPARE(i.position(), begin + 26);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 25);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 24);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('m')));
+
+ QCOMPARE(i.position(), begin + 23);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 22);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 21);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('l')));
+
+ QCOMPARE(i.position(), begin + 20);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 19);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('k')));
+
+ QCOMPARE(i.position(), begin + 18);
+ QCOMPARE(i.peekPrevious(), 0xFFFDu);
+ QCOMPARE(i.previous(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 17);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('j')));
+
+ i.setPosition(begin + 29);
+ QCOMPARE(i.position(), begin + 29);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 30);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+
+ QCOMPARE(i.position(), begin + 31);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('o')));
+
+ QCOMPARE(i.position(), begin + 30);
+ QCOMPARE(i.peekPrevious(), 0x10000u);
+ QCOMPARE(i.previous(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 28);
+
+ i.setPosition(begin + 33);
+ QCOMPARE(i.position(), begin + 33);
+ QCOMPARE(i.peekNext(), 0xFFFDu);
+ QCOMPARE(i.next(), 0xFFFDu);
+
+ QCOMPARE(i.position(), begin + 34);
+ QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+ QCOMPARE(i.next(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+
+ QCOMPARE(i.position(), begin + 35);
+ QCOMPARE(i.peekPrevious(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+ QCOMPARE(i.previous(), QCHAR_UNICODE_VALUE(QLatin1Char('p')));
+
+ QCOMPARE(i.position(), begin + 34);
+ QCOMPARE(i.peekPrevious(), 0x10000u);
+ QCOMPARE(i.previous(), 0x10000u);
+
+ QCOMPARE(i.position(), begin + 32);
+
+
+ i.setPosition(begin + 16);
+ QCOMPARE(i.position(), begin + 16);
+
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ QCOMPARE(i.position(), begin + 12);
+
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ QCOMPARE(i.position(), begin + 8);
+
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ i.recedeUnchecked();
+ QCOMPARE(i.position(), begin + 2);
+
+#undef QCHAR_UNICODE_VALUE
+}
+
+QTEST_APPLESS_MAIN(tst_QStringIterator)
+
+#include "tst_qstringiterator.moc"
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index 286afdfd18..bf2f222769 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -44,6 +44,7 @@ SUBDIRS=\
qstring \
qstring_no_cast_from_bytearray \
qstringbuilder \
+ qstringiterator \
qstringlist \
qstringmatcher \
qstringref \
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 38b629cad7..ecbe774f22 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -4816,73 +4816,68 @@ static inline QByteArray msgRgbMismatch(unsigned actual, unsigned expected)
QByteArrayLiteral(" != 0x") + QByteArray::number(expected, 16);
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
-QT_BEGIN_NAMESPACE
-extern Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
-QT_END_NAMESPACE
-
-// grabs the window *without including any overlapping windows*
-static QPixmap grabWindow(QWindow *window, int x, int y, int width, int height)
-{
- const HWND hwnd = (HWND)window->winId();
-
- // Create and setup bitmap
- const HDC displayDc = ::GetDC(0);
- const HDC bitmapDc = ::CreateCompatibleDC(displayDc);
- const HBITMAP bitmap = ::CreateCompatibleBitmap(displayDc, width, height);
- const HGDIOBJ oldBitmap = ::SelectObject(bitmapDc, bitmap);
-
- // copy data
- const HDC windowDc = ::GetDC(hwnd);
- ::BitBlt(bitmapDc, 0, 0, width, height, windowDc, x, y, SRCCOPY);
-
- // clean up all but bitmap
- ::ReleaseDC(hwnd, windowDc);
- ::SelectObject(bitmapDc, oldBitmap);
- ::DeleteDC(bitmapDc);
-
- const QPixmap pixmap = qt_pixmapFromWinHBITMAP(bitmap);
-
- ::DeleteObject(bitmap);
- ::ReleaseDC(0, displayDc);
-
- return pixmap;
-}
-#else
-// fallback for other platforms.
static QPixmap grabWindow(QWindow *window, int x, int y, int width, int height)
{
QScreen *screen = window->screen();
return screen ? screen->grabWindow(window->winId(), x, y, width, height) : QPixmap();
}
-#endif //defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
-
-#define VERIFY_COLOR(child, region, color) do { \
- const QRegion r = QRegion(region); \
- QWindow *window = child.window()->windowHandle(); \
- Q_ASSERT(window); \
- const QPoint offset = child.mapTo(child.window(), QPoint(0,0)); \
- for (int i = 0; i < r.rects().size(); ++i) { \
- const QRect rect = r.rects().at(i).translated(offset); \
- for (int t = 0; t < 5; t++) { \
- const QPixmap pixmap = grabWindow(window, \
- rect.left(), rect.top(), \
- rect.width(), rect.height()); \
- QCOMPARE(pixmap.size(), rect.size()); \
- QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
- expectedPixmap.detach(); \
- expectedPixmap.fill(color); \
- QImage image = pixmap.toImage(); \
- uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
- uint firstPixel = image.pixel(0,0) | alphaCorrection; \
- if ( firstPixel != QColor(color).rgb() && t < 4 ) \
- { QTest::qWait(200); continue; } \
- QVERIFY2(firstPixel == QColor(color).rgb(), msgRgbMismatch(firstPixel, QColor(color).rgb())); \
- QCOMPARE(pixmap, expectedPixmap); \
- break; \
- } \
- } \
-} while (0)
+
+#define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__)
+
+bool verifyColor(QWidget &child, const QRegion &region, const QColor &color, unsigned int callerLine)
+{
+ const QRegion r = QRegion(region);
+ QWindow *window = child.window()->windowHandle();
+ Q_ASSERT(window);
+ const QPoint offset = child.mapTo(child.window(), QPoint(0,0));
+ bool grabBackingStore = false;
+ for (int i = 0; i < r.rects().size(); ++i) {
+ QRect rect = r.rects().at(i).translated(offset);
+ for (int t = 0; t < 6; t++) {
+ const QPixmap pixmap = grabBackingStore
+ ? child.grab(rect)
+ : grabWindow(window, rect.left(), rect.top(), rect.width(), rect.height());
+ if (!QTest::qCompare(pixmap.size(), rect.size(), "pixmap.size()", "rect.size()", __FILE__, callerLine))
+ return false;
+ QPixmap expectedPixmap(pixmap); /* ensure equal formats */
+ expectedPixmap.detach();
+ expectedPixmap.fill(color);
+ QImage image = pixmap.toImage();
+ uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0;
+ uint firstPixel = image.pixel(0,0) | alphaCorrection;
+ if (t < 5) {
+ /* Normal run.
+ If it succeeds: return success
+ If it fails: do not return, but wait a bit and reiterate (retry)
+ */
+ if (firstPixel == QColor(color).rgb()
+ && image == expectedPixmap.toImage()) {
+ return true;
+ } else {
+ if (t == 4) {
+ grabBackingStore = true;
+ rect = r.rects().at(i);
+ } else {
+ QTest::qWait(200);
+ }
+ }
+ } else {
+ // Last run, report failure if it still fails
+ if (!QTest::qVerify(firstPixel == QColor(color).rgb(),
+ "firstPixel == QColor(color).rgb()",
+ qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())),
+ __FILE__, callerLine))
+ return false;
+ if (!QTest::qVerify(image == expectedPixmap.toImage(),
+ "image == expectedPixmap.toImage()",
+ "grabbed pixmap differs from expected pixmap",
+ __FILE__, callerLine))
+ return false;
+ }
+ }
+ }
+ return true;
+}
void tst_QWidget::popupEnterLeave()
{
diff --git a/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm b/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
index d276961b93..6919562ddc 100644
--- a/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
+++ b/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
@@ -42,6 +42,7 @@
#import "TestMouseMovedNSView.h"
#include <QtGui>
+#include <QtWidgets>
#include <QMacCocoaViewContainer>
class MyWidget : public QWidget
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 381922288f..c9072c4e9e 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -47,6 +47,8 @@ unc
!contains(QT_CONFIG, openssl):!contains(QT_CONFIG, openssl-linked):SUBDIRS -= qssloptions
+contains(QT_CONFIG, opengl):SUBDIRS += qopengltextureblitter
+
win32 {
SUBDIRS -= network_remote_stresstest network_stresstest
# disable some tests on wince because of missing dependencies
diff --git a/tests/manual/qopengltextureblitter/main.cpp b/tests/manual/qopengltextureblitter/main.cpp
new file mode 100644
index 0000000000..3e9c30932a
--- /dev/null
+++ b/tests/manual/qopengltextureblitter/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltextureblitwindow.h"
+#include <QtGui/QGuiApplication>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QOpenGLTextureBlitWindow window;
+ window.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/qopengltextureblitter/qopengltextureblitter.pro b/tests/manual/qopengltextureblitter/qopengltextureblitter.pro
new file mode 100644
index 0000000000..95f1c14e5a
--- /dev/null
+++ b/tests/manual/qopengltextureblitter/qopengltextureblitter.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+TARGET = qopengltextureblitter
+INCLUDEPATH += .
+
+QT+=gui-private
+# Input
+HEADERS += \
+ qopengltextureblitwindow.h
+
+SOURCES += \
+ main.cpp \
+ qopengltextureblitwindow.cpp
diff --git a/tests/manual/qopengltextureblitter/qopengltextureblitwindow.cpp b/tests/manual/qopengltextureblitter/qopengltextureblitwindow.cpp
new file mode 100644
index 0000000000..0dac669887
--- /dev/null
+++ b/tests/manual/qopengltextureblitter/qopengltextureblitwindow.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltextureblitwindow.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QOpenGLTexture>
+#include <QtGui/QMatrix4x4>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+QOpenGLTextureBlitWindow::QOpenGLTextureBlitWindow()
+ : QWindow()
+ , m_context(new QOpenGLContext(this))
+{
+ resize(500,500);
+ setSurfaceType(OpenGLSurface);
+ QSurfaceFormat surfaceFormat = format();
+ if (QCoreApplication::arguments().contains(QStringLiteral("-coreprofile"))) {
+ surfaceFormat.setVersion(3,2);
+ surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
+ }
+
+ setFormat(surfaceFormat);
+ create();
+ m_context->setFormat(surfaceFormat);
+ m_context->create();
+
+ m_context->makeCurrent(this);
+
+ m_blitter.create();
+}
+
+void QOpenGLTextureBlitWindow::render()
+{
+ m_context->makeCurrent(this);
+
+ QRect viewport(0,0,dWidth(),dHeight());
+ glViewport(0,0,dWidth(), dHeight());
+
+ glClearColor(0.f, .6f, .0f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ QOpenGLTexture texture(m_image);
+ texture.create();
+
+ QRectF topLeft(QPointF(0,0), QPointF(dWidth()/2.0, dHeight()/2.0));
+ QRectF topRight(QPointF(dWidth()/2.0,0), QPointF(dWidth(), dHeight()/2.0));
+ QRectF bottomLeft(QPointF(0, dHeight()/2.0), QPointF(dWidth() /2.0, dHeight()));
+ QRectF bottomRight(QPoint(dWidth()/2.0, dHeight()/2.0), QPointF(dWidth(), dHeight()));
+
+ QOpenGLTextureBlitter::Origin topLeftOrigin = QOpenGLTextureBlitter::OriginTopLeft;
+ QOpenGLTextureBlitter::Origin bottomLeftOrigin = QOpenGLTextureBlitter::OriginBottomLeft;
+ QMatrix4x4 topRightVertexFlipped = QOpenGLTextureBlitter::targetTransform(topRight, viewport, topLeftOrigin);
+ QMatrix4x4 bottomLeftVertex = QOpenGLTextureBlitter::targetTransform(bottomLeft, viewport, topLeftOrigin);
+ QMatrix4x4 bottomRightVertexFlipped = QOpenGLTextureBlitter::targetTransform(bottomRight, viewport, topLeftOrigin);
+
+ QMatrix3x3 texTopLeft = QOpenGLTextureBlitter::sourceTransform(topLeft, m_image.size(), topLeftOrigin);
+ QMatrix3x3 texTopRight = QOpenGLTextureBlitter::sourceTransform(topRight, m_image.size(), topLeftOrigin);
+ QMatrix3x3 texBottomLeft = QOpenGLTextureBlitter::sourceTransform(bottomLeft, m_image.size(), topLeftOrigin);
+ QMatrix3x3 texBottomRight = QOpenGLTextureBlitter::sourceTransform(bottomRight, m_image.size(), bottomLeftOrigin);
+
+ QSizeF subSize(topLeft.width()/2, topLeft.height()/2);
+ QRectF subTopLeft(topLeft.topLeft(), subSize);
+ QRectF subTopRight(QPointF(topLeft.topLeft().x() + topLeft.width() / 2, topLeft.topLeft().y()),subSize);
+ QRectF subBottomLeft(QPointF(topLeft.topLeft().x(), topLeft.topLeft().y() + topLeft.height() / 2), subSize);
+ QRectF subBottomRight(QPointF(topLeft.topLeft().x() + topLeft.width() / 2, topLeft.topLeft().y() + topLeft.height() / 2), subSize);
+
+ QMatrix4x4 subTopLeftVertex = QOpenGLTextureBlitter::targetTransform(subTopLeft, viewport, topLeftOrigin);
+ QMatrix4x4 subTopRightVertex = QOpenGLTextureBlitter::targetTransform(subTopRight, viewport, topLeftOrigin);
+ QMatrix4x4 subBottomLeftVertex = QOpenGLTextureBlitter::targetTransform(subBottomLeft, viewport, topLeftOrigin);
+ QMatrix4x4 subBottomRightVertex = QOpenGLTextureBlitter::targetTransform(subBottomRight, viewport, topLeftOrigin);
+
+ m_blitter.bind();
+ m_blitter.blit(texture.textureId(), subTopLeftVertex, texBottomRight);
+ m_blitter.blit(texture.textureId(), subTopRightVertex, texBottomLeft);
+ m_blitter.blit(texture.textureId(), subBottomLeftVertex, texTopRight);
+ m_blitter.blit(texture.textureId(), subBottomRightVertex, texTopLeft);
+
+ m_blitter.blit(texture.textureId(), topRightVertexFlipped, topLeftOrigin);
+ m_blitter.blit(texture.textureId(), bottomLeftVertex, bottomLeftOrigin);
+
+ m_blitter.setSwizzleRB(true);
+ m_blitter.blit(texture.textureId(), bottomRightVertexFlipped, texTopLeft);
+ m_blitter.setSwizzleRB(false);
+ m_blitter.release();
+
+ m_context->swapBuffers(this);
+}
+
+
+void QOpenGLTextureBlitWindow::exposeEvent(QExposeEvent *event)
+{
+ Q_UNUSED(event);
+ render();
+}
+
+void QOpenGLTextureBlitWindow::resizeEvent(QResizeEvent *event)
+{
+ Q_UNUSED(event);
+ m_image = QImage(size() * devicePixelRatio(), QImage::Format_ARGB32_Premultiplied);
+
+ m_image.fill(Qt::gray);
+
+ QPainter p(&m_image);
+
+ QPen pen(Qt::red);
+ pen.setWidth(5);
+ p.setPen(pen);
+
+ QFont font = p.font();
+ font.setPixelSize(qMin(m_image.height(), m_image.width()) / 20);
+ p.setFont(font);
+
+ int dx = dWidth() / 5;
+ int dy = dHeight() / 5;
+ for (int y = 0; y < 5; y++) {
+ for (int x = 0; x < 5; x++) {
+ QRect textRect(x * dx, y*dy, dx,dy);
+ QString text = QString("[%1,%2]").arg(x).arg(y);
+ p.drawText(textRect,text);
+ }
+ }
+
+ p.drawRect(QRectF(2.5,2.5,dWidth() - 5, dHeight() - 5));
+
+}
+
diff --git a/tests/manual/qopengltextureblitter/qopengltextureblitwindow.h b/tests/manual/qopengltextureblitter/qopengltextureblitwindow.h
new file mode 100644
index 0000000000..855e173b1a
--- /dev/null
+++ b/tests/manual/qopengltextureblitter/qopengltextureblitwindow.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLTEXTUREBLITWINDOW_H
+#define QOPENGLTEXTUREBLITWINDOW_H
+
+#include <QtGui/QWindow>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/private/qopengltextureblitter_p.h>
+
+class QOpenGLTextureBlitWindow : public QWindow
+{
+ Q_OBJECT
+public:
+ QOpenGLTextureBlitWindow();
+
+ void render();
+protected:
+ void exposeEvent(QExposeEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+private:
+ qreal dWidth() const { return width() * devicePixelRatio(); }
+ qreal dHeight() const { return height() * devicePixelRatio(); }
+
+ QScopedPointer<QOpenGLContext> m_context;
+ QOpenGLTextureBlitter m_blitter;
+ QImage m_image;
+};
+
+#endif
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index c9ca0fc597..c6d1002f23 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -3291,8 +3291,10 @@ void Configure::generateQConfigPri()
if (!dictionary["QT_NAMESPACE"].isEmpty())
configStream << "#namespaces" << endl << "QT_NAMESPACE = " << dictionary["QT_NAMESPACE"] << endl;
- if (dictionary[ "SHARED" ] == "no")
- configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl;
+ if (dictionary[ "SHARED" ] == "no") {
+ configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl
+ << "QT_DEFAULT_PRINTSUPPORTPLUGIN = " << qpaPrintSupportPluginName() << endl;
+ }
if (!configStream.flush())
dictionary[ "DONE" ] = "error";
@@ -3474,7 +3476,8 @@ void Configure::generateConfigfiles()
for (int i = 0; i < qconfigList.count(); ++i)
tmpStream << addDefine(qconfigList.at(i));
- tmpStream<<"#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\""<<endl;
+ tmpStream << "#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\"" << endl
+ << "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"" << qpaPrintSupportPluginName() << "\"" << endl;
if (!tmpStream.flush())
dictionary[ "DONE" ] = "error";
@@ -4405,6 +4408,11 @@ QString Configure::qpaPlatformName() const
}
}
+QString Configure::qpaPrintSupportPluginName() const
+{
+ return platform() == WINDOWS ? QStringLiteral("windowsprintersupport") : QString();
+}
+
int Configure::platform() const
{
const QString qMakeSpec = dictionary.value("QMAKESPEC");
diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h
index 3e0e691dab..36668f18ba 100644
--- a/tools/configure/configureapp.h
+++ b/tools/configure/configureapp.h
@@ -100,6 +100,7 @@ public:
int platform() const;
QString platformName() const;
QString qpaPlatformName() const;
+ QString qpaPrintSupportPluginName() const;
private:
bool checkAngleAvailability(QString *errorMessage = 0) const;