summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/widgets/doc/src/basiclayouts.qdoc22
-rw-r--r--examples/widgets/doc/src/borderlayout.qdoc11
-rw-r--r--examples/widgets/doc/src/dynamiclayouts.qdoc12
-rw-r--r--examples/widgets/doc/src/flowlayout.qdoc17
-rw-r--r--mkspecs/features/create_cmake.prf4
-rw-r--r--mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in13
-rw-r--r--mkspecs/features/qt_installs.prf2
-rw-r--r--mkspecs/features/wayland-scanner.prf2
-rw-r--r--qmake/library/qmakeevaluator.cpp20
-rw-r--r--qmake/library/qmakeevaluator.h2
-rw-r--r--qmake/project.cpp2
-rw-r--r--src/corelib/arch/qatomic_bootstrap.h8
-rw-r--r--src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp2
-rw-r--r--src/corelib/global/qglobal.h10
-rw-r--r--src/corelib/global/qlogging.cpp3
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm28
-rw-r--r--src/corelib/io/qloggingcategory.cpp36
-rw-r--r--src/corelib/io/qloggingcategory.h35
-rw-r--r--src/corelib/io/qprocess.cpp164
-rw-r--r--src/corelib/io/qprocess_p.h28
-rw-r--r--src/corelib/io/qprocess_unix.cpp59
-rw-r--r--src/corelib/io/qprocess_win.cpp160
-rw-r--r--src/corelib/io/qprocess_wince.cpp16
-rw-r--r--src/corelib/io/qwindowspipereader.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp58
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h2
-rw-r--r--src/corelib/plugin/qlibrary.cpp35
-rw-r--r--src/corelib/plugin/qlibrary_p.h6
-rw-r--r--src/corelib/plugin/qpluginloader.cpp7
-rw-r--r--src/corelib/tools/qringbuffer_p.h2
-rw-r--r--src/corelib/tools/qsimd_p.h4
-rw-r--r--src/dbus/qdbusconnection_p.h2
-rw-r--r--src/dbus/qdbusintegrator.cpp9
-rw-r--r--src/gui/animation/qguivariantanimation.cpp2
-rw-r--r--src/gui/image/qgifhandler.cpp2
-rw-r--r--src/gui/image/qicon.cpp119
-rw-r--r--src/gui/image/qicon_p.h10
-rw-r--r--src/gui/image/qimage.cpp274
-rw-r--r--src/gui/image/qpixmap.cpp1
-rw-r--r--src/gui/image/qpixmap_raster.cpp6
-rw-r--r--src/gui/kernel/qguiapplication.cpp10
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp78
-rw-r--r--src/gui/painting/qpaintengine.cpp2
-rw-r--r--src/gui/painting/qpaintengineex.cpp4
-rw-r--r--src/gui/text/qfontmetrics.cpp6
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp2
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp44
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h3
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp12
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h3
-rw-r--r--src/network/kernel/qhostaddress.h4
-rw-r--r--src/network/socket/qlocalsocket_win.cpp12
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp7
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp21
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h3
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp12
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp17
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h5
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp29
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h10
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm70
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h2
-rw-r--r--src/plugins/platforms/windows/qplatformfunctions_wince.h9
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp258
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp6
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro1
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp3
-rw-r--r--src/sql/kernel/qsqldatabase.cpp6
-rw-r--r--src/sql/kernel/qsqldatabase.h7
-rw-r--r--src/tools/moc/moc.cpp2
-rw-r--r--src/widgets/doc/snippets/qstyleplugin/main.cpp2
-rw-r--r--src/widgets/doc/src/qtwidgets-index.qdoc1
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/layout.qdoc10
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp8
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp5
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp12
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp1
-rw-r--r--src/widgets/widgets/qcombobox.cpp45
-rw-r--r--src/widgets/widgets/qcombobox_p.h1
-rw-r--r--src/widgets/widgets/qfontcombobox.cpp2
-rw-r--r--src/widgets/widgets/qmainwindow.cpp9
-rw-r--r--src/widgets/widgets/qstackedwidget.cpp2
-rw-r--r--tests/auto/corelib/io/qdebug/qdebug.pro2
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp40
-rw-r--r--tests/auto/corelib/io/qprocess/test/test.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp2
-rw-r--r--tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp7
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.cpp59
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp125
-rw-r--r--tests/auto/gui/image/qpixmap/tst_qpixmap.cpp15
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp38
-rw-r--r--tests/auto/other/other.pro3
-rw-r--r--tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro4
-rw-r--r--tests/auto/other/qprocess_and_guieventloop/test.pro5
-rw-r--r--tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp89
-rw-r--r--tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp58
-rw-r--r--tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro4
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp6
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp63
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp37
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp43
108 files changed, 1676 insertions, 915 deletions
diff --git a/examples/widgets/doc/src/basiclayouts.qdoc b/examples/widgets/doc/src/basiclayouts.qdoc
index d219b7bff3..0066317165 100644
--- a/examples/widgets/doc/src/basiclayouts.qdoc
+++ b/examples/widgets/doc/src/basiclayouts.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -28,31 +28,35 @@
/*!
\example layouts/basiclayouts
\title Basic Layouts Example
+ \brief Shows how to use the standard layout managers.
- \brief The Basic Layouts example shows how to use the standard layout
- managers that are available in Qt: QBoxLayout, QGridLayout and
- QFormLayout.
+ \e{Basic Layouts} shows how to use the standard layout managers that are
+ available in Qt: QBoxLayout, QGridLayout, and QFormLayout.
\image basiclayouts-example.png Screenshot of the Basic Layouts example
The QBoxLayout class lines up widgets horizontally or vertically.
QHBoxLayout and QVBoxLayout are convenience subclasses of QBoxLayout.
QGridLayout lays out widgets in cells by dividing the available space
- into rows and columns. QFormLayout, on the other hand, lays out its
+ into rows and columns. QFormLayout, on the other hand, sets its
children in a two-column form with labels in the left column and
input fields in the right column.
+ For more information, visit the \l{Layout Management} page.
+
+ \include examples-run.qdocinc
+
\section1 Dialog Class Definition
\snippet layouts/basiclayouts/dialog.h 0
The \c Dialog class inherits QDialog. It is a custom widget that
displays its child widgets using the geometry managers:
- QHBoxLayout, QVBoxLayout, QGridLayout and QFormLayout.
+ QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout.
- We declare four private functions to simplify the class
- constructor: The \c createMenu(), \c createHorizontalGroupBox(),
- \c createGridGroupBox() and \c createFormGroupBox() functions create
+ There are four private functions to simplify the class
+ constructor: the \c createMenu(), \c createHorizontalGroupBox(),
+ \c createGridGroupBox(), and \c createFormGroupBox() functions create
several widgets that the example uses to demonstrate how the layout
affects their appearances.
diff --git a/examples/widgets/doc/src/borderlayout.qdoc b/examples/widgets/doc/src/borderlayout.qdoc
index 8a2958ee80..03a2bf1672 100644
--- a/examples/widgets/doc/src/borderlayout.qdoc
+++ b/examples/widgets/doc/src/borderlayout.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -28,9 +28,14 @@
/*!
\example layouts/borderlayout
\title Border Layout Example
+ \brief Shows how to arrange child widgets along a border.
- \brief The Border Layout example shows how to create a custom layout that arranges
- child widgets according to a simple set of rules.
+ \e{Border Layout} implements a layout that arranges child widgets to
+ surround the main area.
\image borderlayout-example.png
+
+ For more information, visit the \l{Layout Management} page.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/widgets/doc/src/dynamiclayouts.qdoc b/examples/widgets/doc/src/dynamiclayouts.qdoc
index 5590ec61f1..497a0d23fd 100644
--- a/examples/widgets/doc/src/dynamiclayouts.qdoc
+++ b/examples/widgets/doc/src/dynamiclayouts.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -28,7 +28,13 @@
/*!
\example layouts/dynamiclayouts
\title Dynamic Layouts Example
+ \brief Shows how to re-orient widgets in running applications.
- \brief The Dynamic Layouts example shows how to move widgets around in
- existing layouts.
+ \e{Dynamic Layouts} implements dynamically placed widgets within running
+ applications. The widget placement depends on whether \c Horizontal or \c
+ Vertical is chosen.
+
+ For more information, visit the \l{Layout Management} page.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/widgets/doc/src/flowlayout.qdoc b/examples/widgets/doc/src/flowlayout.qdoc
index b482edf946..84de22416c 100644
--- a/examples/widgets/doc/src/flowlayout.qdoc
+++ b/examples/widgets/doc/src/flowlayout.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -28,18 +28,19 @@
/*!
\example layouts/flowlayout
\title Flow Layout Example
+ \brief Shows how to arrange widgets for different window sizes.
- \brief The Flow Layout example demonstrates a custom layout that arranges child
- widgets from left to right and top to bottom in a top-level widget.
+ \e{Flow Layout} implements a layout that handles different window sizes. The
+ widget placement changes depending on the width of the application window.
\image flowlayout-example.png Screenshot of the Flow Layout example
- The items are first laid out horizontally and then vertically when each line
- in the layout runs out of space.
-
The Flowlayout class mainly uses QLayout and QWidgetItem, while the
- Window uses QWidget and QLabel. We will only document the definition
- and implementation of \c FlowLayout below.
+ Window uses QWidget and QLabel.
+
+ For more information, visit the \l{Layout Management} page.
+
+ \include examples-run.qdocinc
\section1 FlowLayout Class Definition
diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf
index aee3e79765..abd8009288 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -166,8 +166,6 @@ contains(CONFIG, plugin) {
return()
}
-contains($$list(network sql widgets gui), $$MODULE): CMAKE_LOAD_PLUGINS = true
-
unix:contains(QT_CONFIG, reduce_relocations):CMAKE_ADD_FPIE_FLAGS = "true"
CMAKE_MKSPEC = $$[QMAKE_XSPEC]
@@ -293,3 +291,5 @@ exists($$cmake_macros_file.input) {
}
cmake_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5$${CMAKE_MODULE_NAME}
+
+!exists($$MODULE_BASE_INDIR/tests/auto/cmake): error("Missing CMake tests.")
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index dce981e059..d1dfeed535 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -283,7 +283,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!ENDIF // CMAKE_DEBUG_TYPE
-!!IF !isEmpty(CMAKE_LOAD_PLUGINS)
+ file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")
macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties Plugin Configuration PLUGIN_LOCATION)
set_property(TARGET Qt5::${Plugin} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
@@ -299,11 +299,12 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
)
endmacro()
- file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")
- foreach(pluginTarget ${pluginTargets})
- include(${pluginTarget})
- endforeach()
-!!ENDIF
+ if (pluginTargets)
+ foreach(pluginTarget ${pluginTargets})
+ include(${pluginTarget})
+ endforeach()
+ endif()
+
!!IF !isEmpty(CMAKE_MODULE_EXTRAS)
include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake\")
diff --git a/mkspecs/features/qt_installs.prf b/mkspecs/features/qt_installs.prf
index 7d2280e75a..3a5dbb6274 100644
--- a/mkspecs/features/qt_installs.prf
+++ b/mkspecs/features/qt_installs.prf
@@ -22,7 +22,7 @@
target.path = $$[QT_HOST_LIBS]
else: \
target.path = $$[QT_INSTALL_LIBS]
- target.CONFIG = no_dll
+ !static: target.CONFIG = no_dll
INSTALLS += target
}
diff --git a/mkspecs/features/wayland-scanner.prf b/mkspecs/features/wayland-scanner.prf
index 3a9d8cafbd..5a97d98373 100644
--- a/mkspecs/features/wayland-scanner.prf
+++ b/mkspecs/features/wayland-scanner.prf
@@ -32,6 +32,7 @@ qt_install_headers {
!isEmpty(header_files_client) {
wayland_generated_client_headers.files = $$header_files_client
wayland_generated_client_headers.path = $$private_headers.path
+ wayland_generated_client_headers.CONFIG = no_check_exist
INSTALLS += wayland_generated_client_headers
WAYLAND_CLIENT_HEADER_DEST = $$header_dest/
WAYLAND_CLIENT_INCLUDE_DIR = $$MODULE_INCNAME/private
@@ -41,6 +42,7 @@ qt_install_headers {
!isEmpty(header_files_server) {
wayland_generated_server_headers.files = $$header_files_server
wayland_generated_server_headers.path = $$private_headers.path
+ wayland_generated_server_headers.CONFIG = no_check_exist
INSTALLS += wayland_generated_server_headers
WAYLAND_SERVER_HEADER_DEST = $$header_dest/
WAYLAND_SERVER_INCLUDE_DIR = $$MODULE_INCNAME/private
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 2ea5ffd45e..8e1296e1e8 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -208,17 +208,17 @@ QMakeEvaluator::~QMakeEvaluator()
{
}
-void QMakeEvaluator::initFrom(const QMakeEvaluator &other)
+void QMakeEvaluator::initFrom(const QMakeEvaluator *other)
{
- Q_ASSERT_X(&other, "QMakeEvaluator::visitProFile", "Project not prepared");
- m_functionDefs = other.m_functionDefs;
- m_valuemapStack = other.m_valuemapStack;
+ Q_ASSERT_X(other, "QMakeEvaluator::visitProFile", "Project not prepared");
+ m_functionDefs = other->m_functionDefs;
+ m_valuemapStack = other->m_valuemapStack;
m_valuemapInited = true;
- m_qmakespec = other.m_qmakespec;
- m_qmakespecName = other.m_qmakespecName;
- m_mkspecPaths = other.m_mkspecPaths;
- m_featureRoots = other.m_featureRoots;
- m_dirSep = other.m_dirSep;
+ m_qmakespec = other->m_qmakespec;
+ m_qmakespecName = other->m_qmakespecName;
+ m_mkspecPaths = other->m_mkspecPaths;
+ m_featureRoots = other->m_featureRoots;
+ m_dirSep = other->m_dirSep;
}
//////// Evaluator tools /////////
@@ -1355,7 +1355,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
return ReturnFalse;
#endif
- initFrom(*baseEnv->evaluator);
+ initFrom(baseEnv->evaluator);
} else {
if (!m_valuemapInited)
loadDefaults();
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index de13033481..f322a48011 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -167,7 +167,7 @@ public:
bool prepareProject(const QString &inDir);
bool loadSpecInternal();
bool loadSpec();
- void initFrom(const QMakeEvaluator &other);
+ void initFrom(const QMakeEvaluator *other);
void setupProject();
void evaluateCommand(const QString &cmds, const QString &where);
void applyExtraConfigs();
diff --git a/qmake/project.cpp b/qmake/project.cpp
index 9f75d1da27..f3d22dfb2c 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -60,7 +60,7 @@ QMakeProject::QMakeProject()
QMakeProject::QMakeProject(QMakeProject *p)
: QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler)
{
- initFrom(*p);
+ initFrom(p);
}
bool QMakeProject::boolRet(VisitReturn vr)
diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h
index 7f17387c9c..1ab901d826 100644
--- a/src/corelib/arch/qatomic_bootstrap.h
+++ b/src/corelib/arch/qatomic_bootstrap.h
@@ -67,8 +67,10 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return --_q_value != 0;
}
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW
{
+ if (currentValue)
+ *currentValue = _q_value;
if (_q_value == expectedValue) {
_q_value = newValue;
return true;
@@ -83,8 +85,8 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return tmp;
}
- static
- T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ template <typename AdditiveType> static
+ T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW
{
T returnValue = _q_value;
_q_value += valueToAdd;
diff --git a/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp b/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp
index aae4f4bd00..b86f0bbf68 100644
--- a/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_plugins-howto.cpp
@@ -42,7 +42,7 @@
class MyStylePlugin : public QStylePlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json)
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json")
public:
QStyle *create(const QString &key);
};
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 707e46dd40..f610cfab8c 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -45,11 +45,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "5.3.1"
+#define QT_VERSION_STR "5.3.2"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x050301
+#define QT_VERSION 0x050302
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -59,7 +59,11 @@
#include <QtCore/qconfig.h>
#include <QtCore/qfeatures.h>
#endif
-#define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1500 /* VS2008 */
+# define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE)
+#else
+# define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
+#endif
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
# define QT_NO_UNSHARABLE_CONTAINERS
#endif
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 4a602e4b2b..ff4372a049 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1443,8 +1443,7 @@ void qErrnoWarning(int code, const char *msg, ...)
\since 5.0
Installs a Qt message \a handler which has been defined
- previously. Returns a pointer to the previous message handler
- (which may be 0).
+ previously. Returns a pointer to the previous message handler.
The message handler is a function that prints out debug messages,
warnings, critical and fatal error messages. The Qt library (debug
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index 981d663694..085396da6d 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -64,6 +64,25 @@
QT_BEGIN_NAMESPACE
+namespace {
+class RaiiAutoreleasePool
+{
+ Q_DISABLE_COPY(RaiiAutoreleasePool)
+
+public:
+ RaiiAutoreleasePool()
+ : pool([[NSAutoreleasePool alloc] init])
+ {}
+
+ ~RaiiAutoreleasePool()
+ { [pool release]; }
+
+private:
+ NSAutoreleasePool *pool;
+};
+#define Q_AUTORELEASE_POOL(pool) RaiiAutoreleasePool pool; Q_UNUSED(pool);
+}
+
static void callBackFunction(ConstFSEventStreamRef streamRef,
void *clientCallBackInfo,
size_t numEvents,
@@ -71,6 +90,8 @@ static void callBackFunction(ConstFSEventStreamRef streamRef,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
+ Q_AUTORELEASE_POOL(pool)
+
char **paths = static_cast<char **>(eventPaths);
QFseventsFileSystemWatcherEngine *engine = static_cast<QFseventsFileSystemWatcherEngine *>(clientCallBackInfo);
engine->processEvent(streamRef, numEvents, paths, eventFlags, eventIds);
@@ -283,6 +304,7 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString path
void QFseventsFileSystemWatcherEngine::restartStream()
{
+ Q_AUTORELEASE_POOL(pool)
QMutexLocker locker(&lock);
stopStream();
startStream();
@@ -313,6 +335,8 @@ QFseventsFileSystemWatcherEngine::QFseventsFileSystemWatcherEngine(QObject *pare
QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
+ Q_AUTORELEASE_POOL(pool)
+
if (stream)
FSEventStreamStop(stream);
@@ -327,6 +351,8 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
+ Q_AUTORELEASE_POOL(pool)
+
if (stream) {
DEBUG("Flushing, last id is %llu", FSEventStreamGetLatestEventId(stream));
FSEventStreamFlushSync(stream);
@@ -413,6 +439,8 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
QStringList *files,
QStringList *directories)
{
+ Q_AUTORELEASE_POOL(pool)
+
QMutexLocker locker(&lock);
bool needsRestart = false;
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 518052e537..45fab11939 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -50,6 +50,18 @@ const char qtDefaultCategoryName[] = "default";
Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
(qtDefaultCategoryName))
+#ifndef Q_ATOMIC_INT8_IS_SUPPORTED
+static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
+{
+ const int bit = 1 << shift;
+
+ if (enable)
+ atomic->fetchAndOrRelaxed(bit);
+ else
+ atomic->fetchAndAndRelaxed(~bit);
+}
+#endif
+
/*!
\class QLoggingCategory
\inmodule QtCore
@@ -171,13 +183,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
*/
QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
- name(0),
- enabledDebug(true),
- enabledWarning(true),
- enabledCritical(true)
+ name(0)
{
Q_UNUSED(d);
Q_UNUSED(placeholder);
+ enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
const bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
@@ -249,9 +259,9 @@ QLoggingCategory::~QLoggingCategory()
bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
{
switch (msgtype) {
- case QtDebugMsg: return enabledDebug;
- case QtWarningMsg: return enabledWarning;
- case QtCriticalMsg: return enabledCritical;
+ case QtDebugMsg: return isDebugEnabled();
+ case QtWarningMsg: return isWarningEnabled();
+ case QtCriticalMsg: return isCriticalEnabled();
case QtFatalMsg: return true;
}
return false;
@@ -270,9 +280,15 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
switch (type) {
- case QtDebugMsg: enabledDebug = enable; break;
- case QtWarningMsg: enabledWarning = enable; break;
- case QtCriticalMsg: enabledCritical = enable; break;
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ case QtDebugMsg: bools.enabledDebug.store(enable); break;
+ case QtWarningMsg: bools.enabledWarning.store(enable); break;
+ case QtCriticalMsg: bools.enabledCritical.store(enable); break;
+#else
+ case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break;
+ case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break;
+ case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break;
+#endif
case QtFatalMsg: break;
}
}
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 4aec8e63bf..573af2105c 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -57,10 +57,15 @@ public:
bool isEnabled(QtMsgType type) const;
void setEnabled(QtMsgType type, bool enable);
- bool isDebugEnabled() const { return enabledDebug; }
- bool isWarningEnabled() const { return enabledWarning; }
- bool isCriticalEnabled() const { return enabledCritical; }
-
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ bool isDebugEnabled() const { return bools.enabledDebug.load(); }
+ bool isWarningEnabled() const { return bools.enabledWarning.load(); }
+ bool isCriticalEnabled() const { return bools.enabledCritical.load(); }
+#else
+ bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; }
+ bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; }
+ bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; }
+#endif
const char *categoryName() const { return name; }
// allows usage of both factory method and variable in qCX macros
@@ -78,10 +83,24 @@ private:
void *d; // reserved for future use
const char *name;
- bool enabledDebug;
- bool enabledWarning;
- bool enabledCritical;
- bool placeholder[5]; // reserve for future use
+#ifdef Q_BIG_ENDIAN
+ enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16 };
+#else
+ enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8 };
+#endif
+
+ struct AtomicBools {
+#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
+ QBasicAtomicInteger<bool> enabledDebug;
+ QBasicAtomicInteger<bool> enabledWarning;
+ QBasicAtomicInteger<bool> enabledCritical;
+#endif
+ };
+ union {
+ AtomicBools bools;
+ QBasicAtomicInt enabled;
+ };
+ bool placeholder[4]; // reserve for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 9f9cba81ab..b03e96d0f6 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -819,9 +820,6 @@ QProcessPrivate::QProcessPrivate()
emittedBytesWritten = false;
#ifdef Q_OS_WIN
notifier = 0;
- stdoutReader = 0;
- stderrReader = 0;
- pipeWriter = 0;
processFinishedNotifier = 0;
#endif // Q_OS_WIN
#ifdef Q_OS_UNIX
@@ -889,9 +887,9 @@ void QProcessPrivate::cleanup()
notifier = 0;
}
#endif
- destroyChannel(&stdoutChannel);
- destroyChannel(&stderrChannel);
- destroyChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
+ closeChannel(&stdinChannel);
destroyPipe(childStartedPipe);
destroyPipe(deathPipe);
#ifdef Q_OS_UNIX
@@ -901,49 +899,63 @@ void QProcessPrivate::cleanup()
/*!
\internal
+ Returns true if we emitted readyRead().
*/
-bool QProcessPrivate::_q_canReadStandardOutput()
+bool QProcessPrivate::tryReadFromChannel(Channel *channel)
{
Q_Q(QProcess);
- qint64 available = bytesAvailableFromStdout();
- if (available == 0) {
- if (stdoutChannel.notifier)
- stdoutChannel.notifier->setEnabled(false);
- destroyChannel(&stdoutChannel);
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available");
-#endif
+ if (channel->pipe[0] == INVALID_Q_PIPE)
return false;
- }
- char *ptr = outputReadBuffer.reserve(available);
- qint64 readBytes = readFromStdout(ptr, available);
+ qint64 available = bytesAvailableInChannel(channel);
+ if (available == 0)
+ available = 1; // always try to read at least one byte
+
+ char *ptr = channel->buffer.reserve(available);
+ qint64 readBytes = readFromChannel(channel, ptr, available);
+ if (readBytes <= 0)
+ channel->buffer.chop(available);
+ if (readBytes == -2) {
+ // EWOULDBLOCK
+ return false;
+ }
if (readBytes == -1) {
processError = QProcess::ReadError;
q->setErrorString(QProcess::tr("Error reading from process"));
emit q->error(processError);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process");
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process", channel - &stdinChannel);
+#endif
+ return false;
+ }
+ if (readBytes == 0) {
+ // EOF
+ if (channel->notifier)
+ channel->notifier->setEnabled(false);
+ closeChannel(channel);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel);
#endif
return false;
}
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
+ qDebug("QProcessPrivate::tryReadFromChannel(%d), read %d bytes from the process' output", channel - &stdinChannel
int(readBytes));
#endif
- if (stdoutChannel.closed) {
- outputReadBuffer.chop(readBytes);
+ if (channel->closed) {
+ channel->buffer.chop(readBytes);
return false;
}
- outputReadBuffer.chop(available - readBytes);
+ channel->buffer.chop(available - readBytes);
bool didRead = false;
+ bool isStdout = channel == &stdoutChannel;
if (readBytes == 0) {
- if (stdoutChannel.notifier)
- stdoutChannel.notifier->setEnabled(false);
- } else if (processChannel == QProcess::StandardOutput) {
+ if (channel->notifier)
+ channel->notifier->setEnabled(false);
+ } else if ((processChannel == QProcess::StandardOutput) == isStdout) {
didRead = true;
if (!emittedReadyRead) {
emittedReadyRead = true;
@@ -951,53 +963,27 @@ bool QProcessPrivate::_q_canReadStandardOutput()
emittedReadyRead = false;
}
}
- emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
+ if (isStdout)
+ emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
+ else
+ emit q->readyReadStandardError(QProcess::QPrivateSignal());
return didRead;
}
/*!
\internal
*/
-bool QProcessPrivate::_q_canReadStandardError()
+bool QProcessPrivate::_q_canReadStandardOutput()
{
- Q_Q(QProcess);
- qint64 available = bytesAvailableFromStderr();
- if (available == 0) {
- if (stderrChannel.notifier)
- stderrChannel.notifier->setEnabled(false);
- destroyChannel(&stderrChannel);
- return false;
- }
-
- char *ptr = errorReadBuffer.reserve(available);
- qint64 readBytes = readFromStderr(ptr, available);
- if (readBytes == -1) {
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
- }
- if (stderrChannel.closed) {
- errorReadBuffer.chop(readBytes);
- return false;
- }
-
- errorReadBuffer.chop(available - readBytes);
+ return tryReadFromChannel(&stdoutChannel);
+}
- bool didRead = false;
- if (readBytes == 0) {
- if (stderrChannel.notifier)
- stderrChannel.notifier->setEnabled(false);
- } else if (processChannel == QProcess::StandardError) {
- didRead = true;
- if (!emittedReadyRead) {
- emittedReadyRead = true;
- emit q->readyRead();
- emittedReadyRead = false;
- }
- }
- emit q->readyReadStandardError(QProcess::QPrivateSignal());
- return didRead;
+/*!
+ \internal
+*/
+bool QProcessPrivate::_q_canReadStandardError()
+{
+ return tryReadFromChannel(&stderrChannel);
}
/*!
@@ -1009,17 +995,17 @@ bool QProcessPrivate::_q_canWrite()
if (stdinChannel.notifier)
stdinChannel.notifier->setEnabled(false);
- if (writeBuffer.isEmpty()) {
+ if (stdinChannel.buffer.isEmpty()) {
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
#endif
return false;
}
- qint64 written = writeToStdin(writeBuffer.readPointer(),
- writeBuffer.nextDataBlockSize());
+ qint64 written = writeToStdin(stdinChannel.buffer.readPointer(),
+ stdinChannel.buffer.nextDataBlockSize());
if (written < 0) {
- destroyChannel(&stdinChannel);
+ closeChannel(&stdinChannel);
processError = QProcess::WriteError;
q->setErrorString(QProcess::tr("Error writing to process"));
emit q->error(processError);
@@ -1031,16 +1017,16 @@ bool QProcessPrivate::_q_canWrite()
#endif
if (written != 0) {
- writeBuffer.free(written);
+ stdinChannel.buffer.free(written);
if (!emittedBytesWritten) {
emittedBytesWritten = true;
emit q->bytesWritten(written);
emittedBytesWritten = false;
}
}
- if (stdinChannel.notifier && !writeBuffer.isEmpty())
+ if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty())
stdinChannel.notifier->setEnabled(true);
- if (writeBuffer.isEmpty() && stdinChannel.closed)
+ if (stdinChannel.buffer.isEmpty() && stdinChannel.closed)
closeWriteChannel();
return true;
}
@@ -1163,7 +1149,7 @@ void QProcessPrivate::closeWriteChannel()
// instead.
flushPipeWriter();
#endif
- destroyChannel(&stdinChannel);
+ closeChannel(&stdinChannel);
}
/*!
@@ -1308,10 +1294,10 @@ void QProcess::setReadChannel(ProcessChannel channel)
QByteArray buf = d->buffer.readAll();
if (d->processChannel == QProcess::StandardOutput) {
for (int i = buf.size() - 1; i >= 0; --i)
- d->outputReadBuffer.ungetChar(buf.at(i));
+ d->stdoutChannel.buffer.ungetChar(buf.at(i));
} else {
for (int i = buf.size() - 1; i >= 0; --i)
- d->errorReadBuffer.ungetChar(buf.at(i));
+ d->stderrChannel.buffer.ungetChar(buf.at(i));
}
}
d->processChannel = channel;
@@ -1359,7 +1345,7 @@ void QProcess::closeWriteChannel()
{
Q_D(QProcess);
d->stdinChannel.closed = true; // closing
- if (d->writeBuffer.isEmpty())
+ if (d->stdinChannel.buffer.isEmpty())
d->closeWriteChannel();
}
@@ -1589,8 +1575,8 @@ bool QProcess::canReadLine() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
return readBuffer->canReadLine() || QIODevice::canReadLine();
}
@@ -1618,8 +1604,8 @@ bool QProcess::atEnd() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
}
@@ -1636,8 +1622,8 @@ qint64 QProcess::bytesAvailable() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
#if defined QPROCESS_DEBUG
qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
(d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
@@ -1650,7 +1636,7 @@ qint64 QProcess::bytesAvailable() const
qint64 QProcess::bytesToWrite() const
{
Q_D(const QProcess);
- qint64 size = d->writeBuffer.size();
+ qint64 size = d->stdinChannel.buffer.size();
#ifdef Q_OS_WIN
size += d->pipeWriterBytesToWrite();
#endif
@@ -1897,8 +1883,8 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
if (!maxlen)
return 0;
QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
- ? &d->errorReadBuffer
- : &d->outputReadBuffer;
+ ? &d->stderrChannel.buffer
+ : &d->stdoutChannel.buffer;
if (maxlen == 1 && !readBuffer->isEmpty()) {
int c = readBuffer->getChar();
@@ -1961,7 +1947,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
}
if (len == 1) {
- d->writeBuffer.putChar(*data);
+ d->stdinChannel.buffer.putChar(*data);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
#if defined QPROCESS_DEBUG
@@ -1971,7 +1957,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
return 1;
}
- char *dest = d->writeBuffer.reserve(len);
+ char *dest = d->stdinChannel.buffer.reserve(len);
memcpy(dest, data, len);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
@@ -2112,8 +2098,8 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
- outputReadBuffer.clear();
- errorReadBuffer.clear();
+ stdoutChannel.buffer.clear();
+ stderrChannel.buffer.clear();
if (stdinChannel.type != QProcessPrivate::Channel::Normal)
mode &= ~QIODevice::WriteOnly; // not open for writing
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 5d65b2a068..6cd9047c04 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -253,6 +253,9 @@ public:
{
pipe[0] = INVALID_Q_PIPE;
pipe[1] = INVALID_Q_PIPE;
+#ifdef Q_OS_WIN
+ reader = 0;
+#endif
}
void clear();
@@ -282,6 +285,13 @@ public:
QString file;
QProcessPrivate *process;
QSocketNotifier *notifier;
+#ifdef Q_OS_WIN
+ union {
+ QWindowsPipeReader *reader;
+ QWindowsPipeWriter *writer;
+ };
+#endif
+ QRingBuffer buffer;
Q_PIPE pipe[2];
unsigned type : 2;
@@ -316,8 +326,10 @@ public:
Channel stdinChannel;
Channel stdoutChannel;
Channel stderrChannel;
- bool createChannel(Channel &channel);
+ bool openChannel(Channel &channel);
+ void closeChannel(Channel *channel);
void closeWriteChannel();
+ bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr
QString program;
QStringList arguments;
@@ -326,14 +338,9 @@ public:
#endif
QProcessEnvironment environment;
- QRingBuffer outputReadBuffer;
- QRingBuffer errorReadBuffer;
- QRingBuffer writeBuffer;
-
Q_PIPE childStartedPipe[2];
Q_PIPE deathPipe[2];
void destroyPipe(Q_PIPE pipe[2]);
- void destroyChannel(Channel *channel);
QSocketNotifier *startupSocketNotifier;
QSocketNotifier *deathNotifier;
@@ -341,9 +348,6 @@ public:
#ifdef Q_OS_WIN
// the wonderful windows notifier
QTimer *notifier;
- QWindowsPipeReader *stdoutReader;
- QWindowsPipeReader *stderrReader;
- QWindowsPipeWriter *pipeWriter;
QWinEventNotifier *processFinishedNotifier;
#endif
@@ -383,10 +387,8 @@ public:
bool waitForFinished(int msecs = 30000);
bool waitForWrite(int msecs = 30000);
- qint64 bytesAvailableFromStdout() const;
- qint64 bytesAvailableFromStderr() const;
- qint64 readFromStdout(char *data, qint64 maxlen);
- qint64 readFromStderr(char *data, qint64 maxlen);
+ qint64 bytesAvailableInChannel(const Channel *channel) const;
+ qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
qint64 writeToStdin(const char *data, qint64 maxlen);
void cleanup();
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 8674371baa..2269740a2f 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -377,7 +377,7 @@ void QProcessPrivate::destroyPipe(int *pipe)
}
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
destroyPipe(channel->pipe);
}
@@ -387,7 +387,7 @@ void QProcessPrivate::destroyChannel(Channel *channel)
This function must be called in order: stdin, stdout, stderr
*/
-bool QProcessPrivate::createChannel(Channel &channel)
+bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@@ -573,9 +573,9 @@ void QProcessPrivate::startProcess()
processManager()->start();
// Initialize pipes
- if (!createChannel(stdinChannel) ||
- !createChannel(stdoutChannel) ||
- !createChannel(stderrChannel) ||
+ if (!openChannel(stdinChannel) ||
+ !openChannel(stdoutChannel) ||
+ !openChannel(stderrChannel) ||
qt_create_pipe(childStartedPipe) != 0 ||
qt_create_pipe(deathPipe) != 0) {
processError = QProcess::FailedToStart;
@@ -963,47 +963,32 @@ bool QProcessPrivate::processStarted()
return i <= 0;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
int nbytes = 0;
qint64 available = 0;
- if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
+ if (::ioctl(channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0)
available = (qint64) nbytes;
#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);
+ qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %lld", channel - &stdinChannel, available);
#endif
return available;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
+qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
- int nbytes = 0;
- qint64 available = 0;
- if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
- available = (qint64) nbytes;
-#if defined (QPROCESS_DEBUG)
- qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);
-#endif
- return available;
-}
-
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
- data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
-#endif
- return bytesRead;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
-{
- qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
+ int save_errno = errno;
+ qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld",
+ channel - &stdinChannel,
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
+ errno = save_errno;
#endif
+ if (bytesRead == -1 && errno == EWOULDBLOCK)
+ return -2;
return bytesRead;
}
@@ -1126,7 +1111,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (stderrChannel.pipe[0] != -1)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@@ -1188,7 +1173,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QList<QSocketNotifier *> notifiers = defaultNotifiers();
#endif
- while (!writeBuffer.isEmpty()) {
+ while (!stdinChannel.buffer.isEmpty()) {
fd_set fdread;
fd_set fdwrite;
@@ -1207,7 +1192,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@@ -1282,7 +1267,7 @@ bool QProcessPrivate::waitForFinished(int msecs)
if (processState == QProcess::Running)
add_fd(nfds, deathPipe[0], &fdread);
- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
+ if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index d7050034bd..7b3f1f8f58 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -158,7 +158,7 @@ static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
This function must be called in order: stdin, stdout, stderr
*/
-bool QProcessPrivate::createChannel(Channel &channel)
+bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@@ -180,34 +180,31 @@ bool QProcessPrivate::createChannel(Channel &channel)
&channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS);
}
} else {
- QWindowsPipeReader *pipeReader = 0;
if (&channel == &stdoutChannel) {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedOutputChannel) {
- if (!stdoutReader) {
- stdoutReader = new QWindowsPipeReader(q);
- q->connect(stdoutReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
+ if (!stdoutChannel.reader) {
+ stdoutChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
}
- pipeReader = stdoutReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_OUTPUT_HANDLE);
}
} else /* if (&channel == &stderrChannel) */ {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedErrorChannel) {
- if (!stderrReader) {
- stderrReader = new QWindowsPipeReader(q);
- q->connect(stderrReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
+ if (!stderrChannel.reader) {
+ stderrChannel.reader = new QWindowsPipeReader(q);
+ q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
}
- pipeReader = stderrReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_ERROR_HANDLE);
}
}
- if (pipeReader) {
+ if (channel.reader) {
qt_create_pipe(channel.pipe, false);
- pipeReader->setHandle(channel.pipe[0]);
- pipeReader->startAsyncRead();
+ channel.reader->setHandle(channel.pipe[0]);
+ channel.reader->startAsyncRead();
}
}
@@ -332,25 +329,15 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
}
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
if (channel == &stdinChannel) {
- if (pipeWriter) {
- delete pipeWriter;
- pipeWriter = 0;
- }
- } else if (channel == &stdoutChannel) {
- if (stdoutReader) {
- stdoutReader->stop();
- stdoutReader->deleteLater();
- stdoutReader = 0;
- }
- } else if (channel == &stderrChannel) {
- if (stderrReader) {
- stderrReader->stop();
- stderrReader->deleteLater();
- stderrReader = 0;
- }
+ delete stdinChannel.writer;
+ stdinChannel.writer = 0;
+ } else if (channel->reader) {
+ channel->reader->stop();
+ channel->reader->deleteLater();
+ channel->reader = 0;
}
destroyPipe(channel->pipe);
}
@@ -486,9 +473,9 @@ void QProcessPrivate::startProcess()
q->setProcessState(QProcess::Starting);
- if (!createChannel(stdinChannel) ||
- !createChannel(stdoutChannel) ||
- !createChannel(stderrChannel))
+ if (!openChannel(stdinChannel) ||
+ !openChannel(stdoutChannel) ||
+ !openChannel(stderrChannel))
return;
QString args = qt_create_commandline(program, arguments);
@@ -577,47 +564,25 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
- if (stdoutChannel.pipe[0] == INVALID_Q_PIPE)
- return 0;
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ Q_ASSERT(channel->reader);
- if (!stdoutReader)
- return 0;
-
- DWORD bytesAvail = stdoutReader->bytesAvailable();
+ DWORD bytesAvail = channel->reader->bytesAvailable();
#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
+ qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %d", channel - &stdinChannel, bytesAvail);
#endif
return bytesAvail;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
+qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
- if (stderrChannel.pipe[0] == INVALID_Q_PIPE)
- return 0;
-
- if (!stderrReader)
- return 0;
-
- DWORD bytesAvail = stderrReader->bytesAvailable();
-#if defined QPROCESS_DEBUG
- qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
-#endif
- return bytesAvail;
+ Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
+ Q_ASSERT(channel->reader);
+ return channel->reader->read(data, maxlen);
}
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- return stdoutReader ? stdoutReader->read(data, maxlen) : 0;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
-{
- return stderrReader ? stderrReader->read(data, maxlen) : 0;
-}
-
-
static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
{
DWORD currentProcId = 0;
@@ -659,20 +624,20 @@ bool QProcessPrivate::waitForStarted(int)
bool QProcessPrivate::drainOutputPipes()
{
- if (!stdoutReader && !stderrReader)
+ if (!stdoutChannel.reader && !stderrChannel.reader)
return false;
bool someReadyReadEmitted = false;
forever {
bool readyReadEmitted = false;
bool readOperationActive = false;
- if (stdoutReader) {
- readyReadEmitted |= stdoutReader->waitForReadyRead(0);
- readOperationActive = stdoutReader && stdoutReader->isReadOperationActive();
+ if (stdoutChannel.reader) {
+ readyReadEmitted |= stdoutChannel.reader->waitForReadyRead(0);
+ readOperationActive = stdoutChannel.reader && stdoutChannel.reader->isReadOperationActive();
}
- if (stderrReader) {
- readyReadEmitted |= stderrReader->waitForReadyRead(0);
- readOperationActive |= stderrReader && stderrReader->isReadOperationActive();
+ if (stderrChannel.reader) {
+ readyReadEmitted |= stderrChannel.reader->waitForReadyRead(0);
+ readOperationActive |= stderrChannel.reader && stderrChannel.reader->isReadOperationActive();
}
someReadyReadEmitted |= readyReadEmitted;
if (!readOperationActive || !readyReadEmitted)
@@ -690,13 +655,13 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
- if (pipeWriter && pipeWriter->waitForWrite(0))
+ if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
- if ((stdoutReader && stdoutReader->waitForReadyRead(0))
- || (stderrReader && stderrReader->waitForReadyRead(0)))
+ if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
+ || (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)))
return true;
if (!pid)
@@ -726,12 +691,12 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
forever {
// Check if we have any data pending: the pipe writer has
// bytes waiting to written, or it has written data since the
- // last time we called pipeWriter->waitForWrite().
- bool pendingDataInPipe = pipeWriter && (pipeWriter->bytesToWrite() || pipeWriter->hadWritten());
+ // last time we called stdinChannel.writer->waitForWrite().
+ bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
// If we don't have pending data, and our write buffer is
// empty, we fail.
- if (!pendingDataInPipe && writeBuffer.isEmpty())
+ if (!pendingDataInPipe && stdinChannel.buffer.isEmpty())
return false;
// If we don't have pending data and we do have data in our
@@ -746,21 +711,21 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
// written. This will succeed if either the pipe writer has
// already written the data, or if it manages to write data
// within the given timeout. If the write buffer was non-empty
- // and the pipeWriter is now dead, that means _q_canWrite()
+ // and the stdinChannel.writer is now dead, that means _q_canWrite()
// destroyed the writer after it successfully wrote the last
// batch.
- if (!pipeWriter || pipeWriter->waitForWrite(0))
+ if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))
return true;
// If we wouldn't write anything, check if we can read stdout.
- if (bytesAvailableFromStdout() != 0) {
- _q_canReadStandardOutput();
+ if (bytesAvailableInChannel(&stdoutChannel) != 0) {
+ tryReadFromChannel(&stdoutChannel);
timer.resetIncrements();
}
// Check if we can read stderr.
- if (bytesAvailableFromStderr() != 0) {
- _q_canReadStandardError();
+ if (bytesAvailableInChannel(&stderrChannel) != 0) {
+ tryReadFromChannel(&stderrChannel);
timer.resetIncrements();
}
@@ -795,13 +760,13 @@ bool QProcessPrivate::waitForFinished(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- if (!writeBuffer.isEmpty() && !_q_canWrite())
+ if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
- if (pipeWriter && pipeWriter->waitForWrite(0))
+ if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
- if (stdoutReader && stdoutReader->waitForReadyRead(0))
+ if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
- if (stderrReader && stderrReader->waitForReadyRead(0))
+ if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
if (!pid) {
@@ -837,33 +802,32 @@ void QProcessPrivate::findExitCode()
void QProcessPrivate::flushPipeWriter()
{
- if (pipeWriter && pipeWriter->bytesToWrite() > 0) {
- pipeWriter->waitForWrite(ULONG_MAX);
- }
+ if (stdinChannel.writer && stdinChannel.writer->bytesToWrite() > 0)
+ stdinChannel.writer->waitForWrite(ULONG_MAX);
}
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
{
- return pipeWriter ? pipeWriter->bytesToWrite() : qint64(0);
+ return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
}
qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
Q_Q(QProcess);
- if (!pipeWriter) {
- pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
- pipeWriter->start();
+ if (!stdinChannel.writer) {
+ stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
+ stdinChannel.writer->start();
}
- return pipeWriter->write(data, maxlen);
+ return stdinChannel.writer->write(data, maxlen);
}
bool QProcessPrivate::waitForWrite(int msecs)
{
Q_Q(QProcess);
- if (!pipeWriter || pipeWriter->waitForWrite(msecs))
+ if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(msecs))
return true;
processError = QProcess::Timedout;
@@ -875,7 +839,7 @@ void QProcessPrivate::_q_notified()
{
notifier->stop();
- if (!writeBuffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0)))
+ if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0)))
_q_canWrite();
if (processState != QProcess::NotRunning)
diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp
index ad9a328133..e0bee48598 100644
--- a/src/corelib/io/qprocess_wince.cpp
+++ b/src/corelib/io/qprocess_wince.cpp
@@ -62,7 +62,7 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
Q_UNUSED(pipe);
}
-void QProcessPrivate::destroyChannel(Channel *channel)
+void QProcessPrivate::closeChannel(Channel *channel)
{
Q_UNUSED(channel);
}
@@ -174,22 +174,12 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
+qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *) const
{
return 0;
}
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
-{
- return 0;
-}
-
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- return -1;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+qint64 QProcessPrivate::readFromChannel(const Channel *, char *data, qint64 maxlen)
{
return -1;
}
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 7dd2125e70..d8a3ec9b42 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -132,7 +132,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
{
if (pipeBroken && actualReadBufferSize == 0)
- return -1; // signal EOF
+ return 0; // signal EOF
qint64 readSoFar;
// If startAsyncRead() has read data, copy it to its destination.
@@ -159,6 +159,8 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
emitReadyReadTimer->stop();
if (!readSequenceStarted)
startAsyncRead();
+ if (readSoFar == 0)
+ return -2; // signal EWOULDBLOCK
}
return readSoFar;
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 64ad2ff0d3..f38ac7bf26 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -325,8 +325,6 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
{
if (internalHwnd)
DestroyWindow(internalHwnd);
- QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
- UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
}
void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
@@ -486,10 +484,26 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
#endif
}
-static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
+// Provide class name and atom for the message window used by
+// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads.
+struct QWindowsMessageWindowClassContext
+{
+ QWindowsMessageWindowClassContext();
+ ~QWindowsMessageWindowClassContext();
+
+ ATOM atom;
+ wchar_t *className;
+};
+
+QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext()
+ : atom(0), className(0)
{
// make sure that multiple Qt's can coexist in the same process
- QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
+ const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget")
+ + QString::number(quintptr(qt_internal_proc));
+ className = new wchar_t[qClassName.size() + 1];
+ qClassName.toWCharArray(className);
+ className[qClassName.size()] = 0;
WNDCLASS wc;
wc.style = 0;
@@ -501,16 +515,37 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
- wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16());
+ wc.lpszClassName = className;
+ atom = RegisterClass(&wc);
+ if (!atom) {
+ qErrnoWarning("%s: RegisterClass() failed", Q_FUNC_INFO, qPrintable(qClassName));
+ delete [] className;
+ className = 0;
+ }
+}
+
+QWindowsMessageWindowClassContext::~QWindowsMessageWindowClassContext()
+{
+ if (className) {
+ UnregisterClass(className, qWinAppInst());
+ delete [] className;
+ }
+}
+
+Q_GLOBAL_STATIC(QWindowsMessageWindowClassContext, qWindowsMessageWindowClassContext)
- RegisterClass(&wc);
+static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
+{
+ QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
+ if (!ctx->atom)
+ return 0;
#ifdef Q_OS_WINCE
HWND parent = 0;
#else
HWND parent = HWND_MESSAGE;
#endif
- HWND wnd = CreateWindow(wc.lpszClassName, // classname
- wc.lpszClassName, // window name
+ HWND wnd = CreateWindow(ctx->className, // classname
+ ctx->className, // window name
0, // style
0, 0, 0, 0, // geometry
parent, // parent
@@ -519,7 +554,8 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
0); // windows creation data.
if (!wnd) {
- qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
+ qErrnoWarning("%s: CreateWindow() for QEventDispatcherWin32 internal window failed", Q_FUNC_INFO);
+ return 0;
}
#ifdef GWLP_USERDATA
@@ -620,7 +656,9 @@ void QEventDispatcherWin32::createInternalHwnd()
// setup GetMessage hook needed to drive our posted events
d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
if (!d->getMessageHook) {
- qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
+ int errorCode = GetLastError();
+ qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s",
+ errorCode, qPrintable(qt_error_string(errorCode)));
}
#endif
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index de6f65ab7d..de95fcc313 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -622,7 +622,7 @@ namespace QtPrivate {
static char test(...);
enum {
Ok = sizeof(test(dummy<Functor>())) == sizeof(int),
- Value = Ok ? sizeof...(ArgList) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
+ Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
};
};
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 9736950c89..50281b632a 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -359,7 +359,7 @@ class QLibraryStore
{
public:
inline ~QLibraryStore();
- static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version);
+ static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints);
static inline void releaseLibrary(QLibraryPrivate *lib);
static inline void cleanup();
@@ -438,17 +438,21 @@ QLibraryStore *QLibraryStore::instance()
return qt_library_data;
}
-inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version)
+inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version,
+ QLibrary::LoadHints loadHints)
{
QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance();
// check if this library is already loaded
QLibraryPrivate *lib = 0;
- if (Q_LIKELY(data))
+ if (Q_LIKELY(data)) {
lib = data->libraryMap.value(fileName);
+ if (lib)
+ lib->mergeLoadHints(loadHints);
+ }
if (!lib)
- lib = new QLibraryPrivate(fileName, version);
+ lib = new QLibraryPrivate(fileName, version, loadHints);
// track this library
if (Q_LIKELY(data))
@@ -479,21 +483,34 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
delete lib;
}
-QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
+QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
- loadHints(0),
+ loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
-{ }
+{
+ if (canonicalFileName.isEmpty())
+ errorString = QLibrary::tr("The shared library was not found.");
+}
-QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
+QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version,
+ QLibrary::LoadHints loadHints)
{
- return QLibraryStore::findOrCreate(fileName, version);
+ return QLibraryStore::findOrCreate(fileName, version, loadHints);
}
QLibraryPrivate::~QLibraryPrivate()
{
}
+void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
+{
+ // if the library is already loaded, we can't change the load hints
+ if (pHnd)
+ return;
+
+ loadHints = lh;
+}
+
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
{
if (!pHnd)
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index 20b0c7e20f..e58d18e87b 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -94,7 +94,8 @@ public:
void release();
QFunctionPointer resolve(const char *);
- static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
+ static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
+ QLibrary::LoadHints loadHints = 0);
static QStringList suffixes_sys(const QString &fullVersion);
static QStringList prefixes_sys();
@@ -117,8 +118,9 @@ public:
}
private:
- explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version);
+ explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints);
~QLibraryPrivate();
+ void mergeLoadHints(QLibrary::LoadHints loadHints);
bool load_sys();
bool unload_sys();
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index e4a1d725ec..2c139669e6 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -352,11 +352,8 @@ void QPluginLoader::setFileName(const QString &fileName)
else
fn = locatePlugin(fileName);
- d = QLibraryPrivate::findOrCreate(fn);
- d->loadHints = lh;
- if (fn.isEmpty())
- d->errorString = QLibrary::tr("The shared library was not found.");
- else
+ d = QLibraryPrivate::findOrCreate(fn, QString(), lh);
+ if (!fn.isEmpty())
d->updatePluginState();
#else
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index b17c6d2f40..5d25b0add1 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -90,7 +90,7 @@ public:
// special case: it is in the first buffer
int nextDataBlockSizeValue = nextDataBlockSize();
- if (pos - head < nextDataBlockSizeValue) {
+ if (pos < nextDataBlockSizeValue) {
length = nextDataBlockSizeValue - pos;
return buffers.at(0).constData() + head + pos;
}
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index f4ca971567..e1c22bac71 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -139,8 +139,10 @@
|| (defined(Q_CC_CLANG) && (__clang_major__ * 100 + __clang_minor__ >= 208)) \
|| defined(Q_CC_INTEL))
# define QT_COMPILER_SUPPORTS_X86INTRIN
-# ifndef Q_CC_INTEL
+# ifdef Q_CC_INTEL
// The Intel compiler has no <x86intrin.h> -- all intrinsics are in <immintrin.h>;
+# include <immintrin.h>
+# else
// GCC 4.4 and Clang 2.8 added a few more intrinsics there
# include <x86intrin.h>
# endif
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index f2590f9c54..fd4ced078d 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -256,7 +256,7 @@ private:
void deliverCall(QObject *object, int flags, const QDBusMessage &msg,
const QVector<int> &metaTypes, int slotIdx);
- bool isServiceRegisteredByThread(const QString &serviceName) const;
+ bool isServiceRegisteredByThread(const QString &serviceName);
QString getNameOwnerNoCache(const QString &service);
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 260c188a41..499e9dbd82 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -2487,12 +2487,15 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName)
serviceNames.removeAll(serviceName);
}
-bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const
+bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName)
{
if (!serviceName.isEmpty() && serviceName == baseService)
return true;
- QStringList copy = serviceNames;
- return copy.contains(serviceName);
+ if (serviceName == dbusServiceString())
+ return false;
+
+ QDBusReadLocker locker(UnregisterServiceAction, this);
+ return serviceNames.contains(serviceName);
}
void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEvent *ev)
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
index 34abbca282..2cd31696ba 100644
--- a/src/gui/animation/qguivariantanimation.cpp
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -64,7 +64,7 @@ template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,con
return QQuaternion::slerp(f, t, progress);
}
-static void qRegisterGuiGetInterpolator()
+void qRegisterGuiGetInterpolator()
{
qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
qRegisterAnimationInterpolator<QVector2D>(_q_interpolateVariant<QVector2D>);
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
index 19b838240f..91588edd50 100644
--- a/src/gui/image/qgifhandler.cpp
+++ b/src/gui/image/qgifhandler.cpp
@@ -674,7 +674,7 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCo
return;
qint64 oldPos = device->pos();
- if (!device->seek(0))
+ if (device->isSequential() || !device->seek(0))
return;
int colorCount = 0;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 0a4b50bbea..8172ecbb48 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -363,44 +363,93 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon
}
}
-void QPixmapIconEngine::addFile(const QString &fileName, const QSize &_size, QIcon::Mode mode, QIcon::State state)
+// Read out original image depth as set by ICOReader
+static inline int origIcoDepth(const QImage &image)
{
- if (!fileName.isEmpty()) {
- QString abs = fileName;
- if (fileName.at(0) != QLatin1Char(':'))
- abs = QFileInfo(fileName).absoluteFilePath();
- QImageReader reader(abs);
-
- do {
- QSize size = _size;
- QPixmap pixmap;
-
- for (int i = 0; i < pixmaps.count(); ++i) {
- if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
- QPixmapIconEngineEntry *pe = &pixmaps[i];
- if (size == QSize()) {
- pixmap.convertFromImage(reader.read());
- size = pixmap.size();
- }
- if (pe->size == QSize() && pe->pixmap.isNull()) {
- pe->pixmap = QPixmap(pe->fileName);
- // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
- // but be used as a 1x pixmap by QIcon.
- pe->pixmap.setDevicePixelRatio(1.0);
- pe->size = pe->pixmap.size();
- }
- if (pe->size == size) {
- pe->pixmap = pixmap;
- pe->fileName = abs;
- return;
- }
- }
+ const QString s = image.text(QStringLiteral("_q_icoOrigDepth"));
+ return s.isEmpty() ? 32 : s.toInt();
+}
+
+static inline int findBySize(const QList<QImage> &images, const QSize &size)
+{
+ for (int i = 0; i < images.size(); ++i) {
+ if (images.at(i).size() == size)
+ return i;
+ }
+ return -1;
+}
+
+// Convenience class providing a bool read() function.
+namespace {
+class ImageReader
+{
+public:
+ ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
+
+ QByteArray format() const { return m_reader.format(); }
+
+ bool read(QImage *image)
+ {
+ if (m_atEnd)
+ return false;
+ *image = m_reader.read();
+ if (!image->size().isValid()) {
+ m_atEnd = true;
+ return false;
+ }
+ m_atEnd = !m_reader.jumpToNextImage();
+ return true;
+ }
+
+private:
+ QImageReader m_reader;
+ bool m_atEnd;
+};
+} // namespace
+
+void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ if (fileName.isEmpty())
+ return;
+ const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath();
+ const bool ignoreSize = !size.isValid();
+ ImageReader imageReader(abs);
+ const QByteArray format = imageReader.format();
+ if (format.isEmpty()) // Device failed to open or unsupported format.
+ return;
+ QImage image;
+ if (format != "ico") {
+ if (ignoreSize) { // No size specified: Add all images.
+ while (imageReader.read(&image))
+ pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
+ } else {
+ // Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
+ while (imageReader.read(&image) && image.size() != size) {}
+ pixmaps += image.size() == size ?
+ QPixmapIconEngineEntry(abs, image, mode, state) : QPixmapIconEngineEntry(abs, size, mode, state);
+ }
+ return;
+ }
+ // Special case for reading Windows ".ico" files. Historically (QTBUG-39287),
+ // these files may contain low-resolution images. As this information is lost,
+ // ICOReader sets the original format as an image text key value. Read all matching
+ // images into a list trying to find the highest quality per size.
+ QList<QImage> icoImages;
+ while (imageReader.read(&image)) {
+ if (ignoreSize || image.size() == size) {
+ const int position = findBySize(icoImages, image.size());
+ if (position >= 0) { // Higher quality available? -> replace.
+ if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
+ icoImages[position] = image;
+ } else {
+ icoImages.append(image);
}
- QPixmapIconEngineEntry e(abs, size, mode, state);
- e.pixmap = pixmap;
- pixmaps += e;
- } while (reader.jumpToNextImage());
+ }
}
+ foreach (const QImage &i, icoImages)
+ pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
+ if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
+ pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
}
QString QPixmapIconEngine::key() const
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index a46cc310ad..68cd4a5452 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -89,6 +89,7 @@ struct QPixmapIconEngineEntry
:pixmap(pm), size(pm.size()), mode(m), state(s){}
QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
:fileName(file), size(sz), mode(m), state(s){}
+ QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off);
QPixmap pixmap;
QString fileName;
QSize size;
@@ -97,7 +98,14 @@ struct QPixmapIconEngineEntry
bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
};
-
+inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
+ : fileName(file), size(image.size()), mode(m), state(s)
+{
+ pixmap.convertFromImage(image);
+ // Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
+ // but be used as a 1x pixmap by QIcon.
+ pixmap.setDevicePixelRatio(1.0);
+}
class QPixmapIconEngine : public QIconEngine {
public:
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 3998bbf3ff..273c1c922e 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1662,11 +1662,14 @@ void QImage::fill(uint pixel)
return;
}
- if (d->format == Format_RGB32 || d->format == Format_RGBX8888)
+ if (d->format == Format_RGB32)
pixel |= 0xff000000;
-
- if (d->format == Format_RGBX8888 || d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied)
- pixel = ARGB2RGBA(pixel);
+ if (d->format == Format_RGBX8888)
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ pixel |= 0xff000000;
+#else
+ pixel |= 0x000000ff;
+#endif
qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
@@ -1716,22 +1719,27 @@ void QImage::fill(const QColor &color)
if (!d)
return;
- if (d->depth == 32) {
- uint pixel = color.rgba();
- if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied)
- pixel = qPremultiply(pixel);
- fill((uint) pixel);
-
- } else if (d->format == QImage::Format_RGB16) {
+ switch (d->format) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ fill(color.rgba());
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ fill(qPremultiply(color.rgba()));
+ break;
+ case QImage::Format_RGBX8888:
+ fill(ARGB2RGBA(color.rgba() | 0xff000000));
+ break;
+ case QImage::Format_RGBA8888:
+ fill(ARGB2RGBA(color.rgba()));
+ break;
+ case QImage::Format_RGBA8888_Premultiplied:
+ fill(ARGB2RGBA(qPremultiply(color.rgba())));
+ break;
+ case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
-
- } else if (d->depth == 1) {
- if (color == Qt::color1)
- fill((uint) 1);
- else
- fill((uint) 0);
-
- } else if (d->depth == 8) {
+ break;
+ case QImage::Format_Indexed8: {
uint pixel = 0;
for (int i=0; i<d->colortable.size(); ++i) {
if (color.rgba() == d->colortable.at(i)) {
@@ -1740,20 +1748,24 @@ void QImage::fill(const QColor &color)
}
}
fill(pixel);
-
- } else {
+ break;
+ }
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ if (color == Qt::color1)
+ fill((uint) 1);
+ else
+ fill((uint) 0);
+ break;
+ default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), color);
- }
-
+ }}
}
-
-
-
/*!
Inverts all pixel values in the image.
@@ -2685,13 +2697,6 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
return maskImage;
}
-
-/*
- This code is contributed by Philipp Lang,
- GeneriCom Software Germany (www.generi.com)
- under the terms of the QPL, Version 1.0
-*/
-
/*!
\fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const
Returns a mirror of the image, mirrored in the horizontal and/or
@@ -2703,61 +2708,108 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
\sa {QImage#Image Transformations}{Image Transformations}
*/
-template<typename T>
-inline void mirrored_helper_loop(int w, int h, int dxi, int dxs, int dyi, int dy, const uchar* sdata, uchar* ddata, int sbpl, int dbpl)
+template<class T> inline void do_mirror_data(QImageData *dst, QImageData *src,
+ int dstX0, int dstY0,
+ int dstXIncr, int dstYIncr,
+ int w, int h)
{
- for (int sy = 0; sy < h; sy++, dy += dyi) {
- const T* ssl = (T*)(sdata + sy*sbpl);
- T* dsl = (T*)(ddata + dy*dbpl);
- int dx = dxs;
- for (int sx = 0; sx < w; sx++, dx += dxi)
- dsl[dx] = ssl[sx];
+ if (dst == src) {
+ // When mirroring in-place, stop in the middle for one of the directions, since we
+ // are swapping the bytes instead of merely copying.
+ const int srcXEnd = dstX0 ? w / 2 : w;
+ const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h;
+ for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
+ for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
+ std::swap(srcPtr[srcX], dstPtr[dstX]);
+ }
+ } else {
+ for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
+ for (int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
+ dstPtr[dstX] = srcPtr[srcX];
+ }
}
}
-template<typename T>
-inline void mirrored_helper_loop_inplace(int w, int h, int dxi, int dxs, int dyi, int dy, uchar* sdata, int sbpl)
+inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical)
{
- for (int sy = 0; sy < h; sy++, dy += dyi) {
- T* ssl = (T*)(sdata + sy*sbpl);
- T* dsl = (T*)(sdata + dy*sbpl);
- int dx = dxs;
- for (int sx = 0; sx < w; sx++, dx += dxi)
- std::swap(dsl[dx], ssl[sx]);
+ Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
+ int w = src->width;
+ int h = src->height;
+ int depth = src->depth;
+
+ if (src->depth == 1) {
+ w = (w + 7) / 8; // byte aligned width
+ depth = 8;
}
-}
-inline void mirror_horizonal_bitmap(int w, int h, int dxs, uchar* data, int bpl, bool monolsb)
-{
- int shift = w % 8;
- const uchar* bitflip = qt_get_bitflip_array();
- for (int y = h-1; y >= 0; y--) {
- quint8* a0 = (quint8*)(data + y*bpl);
- // Swap bytes
- quint8* a = a0+dxs;
- while (a >= a0) {
- *a = bitflip[*a];
- a--;
- }
- // Shift bits if unaligned
- if (shift != 0) {
- a = a0+dxs;
- quint8 c = 0;
- if (monolsb) {
- while (a >= a0) {
- quint8 nc = *a << shift;
- *a = (*a >> (8-shift)) | c;
- --a;
- c = nc;
- }
- } else {
- while (a >= a0) {
- quint8 nc = *a >> shift;
- *a = (*a << (8-shift)) | c;
- --a;
- c = nc;
+ int dstX0 = 0, dstXIncr = 1;
+ int dstY0 = 0, dstYIncr = 1;
+ if (horizontal) {
+ // 0 -> w-1, 1 -> w-2, 2 -> w-3, ...
+ dstX0 = w - 1;
+ dstXIncr = -1;
+ }
+ if (vertical) {
+ // 0 -> h-1, 1 -> h-2, 2 -> h-3, ...
+ dstY0 = h - 1;
+ dstYIncr = -1;
+ }
+
+ switch (depth) {
+ case 32:
+ do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 24:
+ do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 16:
+ do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ case 8:
+ do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+
+ // The bytes are now all in the correct place. In addition, the bits in the individual
+ // bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image.
+ if (horizontal && dst->depth == 1) {
+ Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
+ const int shift = 8 - (dst->width % 8);
+ const uchar *bitflip = qt_get_bitflip_array();
+ for (int y = 0; y < h; ++y) {
+ uchar *begin = dst->data + y * dst->bytes_per_line;
+ uchar *end = begin + dst->bytes_per_line;
+ for (uchar *p = begin; p < end; ++p) {
+ *p = bitflip[*p];
+ // When the data is non-byte aligned, an extra bit shift (of the number of
+ // unused bits at the end) is needed for the entire scanline.
+ if (shift != 8 && p != begin) {
+ if (dst->format == QImage::Format_Mono) {
+ for (int i = 0; i < shift; ++i) {
+ p[-1] <<= 1;
+ p[-1] |= (*p & (128 >> i)) >> (7 - i);
+ }
+ } else {
+ for (int i = 0; i < shift; ++i) {
+ p[-1] >>= 1;
+ p[-1] |= (*p & (1 << i)) << (7 - i);
+ }
+ }
}
}
+ if (shift != 8) {
+ if (dst->format == QImage::Format_Mono)
+ end[-1] <<= shift;
+ else
+ end[-1] >>= shift;
+ }
}
}
}
@@ -2773,8 +2825,6 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return *this;
- int w = d->width;
- int h = d->height;
// Create result image, copy colormap
QImage result(d->width, d->height, d->format);
QIMAGE_SANITYCHECK_MEMORY(result);
@@ -2787,29 +2837,8 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
result.d->has_alpha_clut = d->has_alpha_clut;
result.d->devicePixelRatio = d->devicePixelRatio;
- if (d->depth == 1)
- w = (w+7)/8;
- int dxi = horizontal ? -1 : 1;
- int dxs = horizontal ? w-1 : 0;
- int dyi = vertical ? -1 : 1;
- int dys = vertical ? h-1 : 0;
-
- // 1 bit, 8 bit
- if (d->depth == 1 || d->depth == 8)
- mirrored_helper_loop<quint8>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 16 bit
- else if (d->depth == 16)
- mirrored_helper_loop<quint16>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 24 bit
- else if (d->depth == 24)
- mirrored_helper_loop<quint24>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
- // 32 bit
- else if (d->depth == 32)
- mirrored_helper_loop<quint32>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
-
- // special handling of 1 bit images for horizontal mirroring
- if (horizontal && d->depth == 1)
- mirror_horizonal_bitmap(d->width, d->height, dxs, result.d->data, result.d->bytes_per_line, d->format == Format_MonoLSB);
+ do_mirror(result.d, d, horizontal, vertical);
+
return result;
}
@@ -2818,45 +2847,12 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
*/
void QImage::mirrored_inplace(bool horizontal, bool vertical)
{
- if (!d)
- return;
-
- if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
+ if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return;
detach();
- int w = d->width;
- int h = d->height;
-
- if (d->depth == 1)
- w = (w+7)/8;
- int dxi = horizontal ? -1 : 1;
- int dxs = horizontal ? w-1 : 0;
- int dyi = vertical ? -1 : 1;
- int dys = vertical ? h-1 : 0;
-
- if (vertical)
- h = h/2;
- else if (horizontal)
- w = w/2;
-
- // 1 bit, 8 bit
- if (d->depth == 1 || d->depth == 8)
- mirrored_helper_loop_inplace<quint8>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 16 bit
- else if (d->depth == 16)
- mirrored_helper_loop_inplace<quint16>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 24 bit
- else if (d->depth == 24)
- mirrored_helper_loop_inplace<quint24>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
- // 32 bit
- else if (d->depth == 32)
- mirrored_helper_loop_inplace<quint32>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
-
- // special handling of 1 bit images for horizontal mirroring
- if (horizontal && d->depth == 1)
- mirror_horizonal_bitmap(d->width, d->height, dxs, d->data, d->bytes_per_line, d->format == Format_MonoLSB);
+ do_mirror(d, d, horizontal, vertical);
}
/*!
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 86c4dfbdca..c6d8d19bb1 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1098,6 +1098,7 @@ bool QPixmap::isDetached() const
*/
bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
{
+ detach();
if (image.isNull() || !data)
*this = QPixmap::fromImage(image, flags);
else
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 1465fea8b9..d879a5cb61 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -363,10 +363,12 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
}
is_null = (w <= 0 || h <= 0);
- image.d->devicePixelRatio = sourceImage.devicePixelRatio();
+ if (image.d)
+ image.d->devicePixelRatio = sourceImage.devicePixelRatio();
//ensure the pixmap and the image resulting from toImage() have the same cacheKey();
setSerialNumber(image.cacheKey() >> 32);
- setDetachNumber(image.d->detach_no);
+ if (image.d)
+ setDetachNumber(image.d->detach_no);
}
QImage* QRasterPlatformPixmap::buffer()
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 8ccff4321d..f429ad2229 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -171,6 +171,7 @@ bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
extern void qRegisterGuiVariant();
+extern void qRegisterGuiGetInterpolator();
extern void qInitDrawhelperAsm();
extern void qInitImageConversions();
@@ -489,6 +490,12 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\li \c{-platformtheme} \e platformTheme, specifies the platform theme.
Overridden by the \c QT_QPA_PLATFORMTHEME environment variable.
+
+ \li \c{-plugin} \e plugin, specifies additional plugins to load. The argument
+ may appear multiple times.
+
+ Overridden by the \c QT_QPA_GENERIC_PLUGINS environment variable.
+
\li \c{-qmljsdebugger=}, activates the QML/JS debugger with a specified port.
The value must be of format \c{port:1234}\e{[,block]}, where
\e block is optional
@@ -1274,6 +1281,9 @@ void QGuiApplicationPrivate::init()
// trigger registering of QVariant's GUI types
qRegisterGuiVariant();
+ // trigger registering of animation interpolators
+ qRegisterGuiGetInterpolator();
+
QWindowSystemInterfacePrivate::eventTime.start();
is_app_running = true;
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index a0d1775040..bc4a714c6c 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -283,46 +283,48 @@ static int qt_gl_resolve_features()
QSurfaceFormat format = QOpenGLContext::currentContext()->format();
QOpenGLExtensionMatcher extensions;
- // Recognize features by extension name.
- if (extensions.match("GL_ARB_multitexture"))
- features |= QOpenGLFunctions::Multitexture;
- if (extensions.match("GL_ARB_shader_objects"))
- features |= QOpenGLFunctions::Shaders;
- if (extensions.match("GL_EXT_framebuffer_object") ||
- extensions.match("GL_ARB_framebuffer_object"))
- features |= QOpenGLFunctions::Framebuffers;
- if (extensions.match("GL_EXT_blend_color"))
- features |= QOpenGLFunctions::BlendColor;
- if (extensions.match("GL_EXT_blend_equation_separate"))
- features |= QOpenGLFunctions::BlendEquationSeparate;
- if (extensions.match("GL_EXT_blend_func_separate"))
- features |= QOpenGLFunctions::BlendFuncSeparate;
- if (extensions.match("GL_EXT_blend_subtract"))
- features |= QOpenGLFunctions::BlendSubtract;
- if (extensions.match("GL_ARB_texture_compression"))
- features |= QOpenGLFunctions::CompressedTextures;
- if (extensions.match("GL_ARB_multisample"))
- features |= QOpenGLFunctions::Multisample;
- if (extensions.match("GL_ARB_texture_non_power_of_two"))
- features |= QOpenGLFunctions::NPOTTextures |
- QOpenGLFunctions::NPOTTextureRepeat;
-
- // assume version 2.0 or higher
- features |= QOpenGLFunctions::BlendColor |
- QOpenGLFunctions::BlendEquation |
- QOpenGLFunctions::Multitexture |
- QOpenGLFunctions::CompressedTextures |
- QOpenGLFunctions::Multisample |
- QOpenGLFunctions::BlendFuncSeparate |
- QOpenGLFunctions::Buffers |
- QOpenGLFunctions::Shaders |
- QOpenGLFunctions::StencilSeparate |
- QOpenGLFunctions::BlendEquationSeparate |
- QOpenGLFunctions::NPOTTextures |
- QOpenGLFunctions::NPOTTextureRepeat;
-
if (format.majorVersion() >= 3)
features |= QOpenGLFunctions::Framebuffers;
+ else if (extensions.match("GL_EXT_framebuffer_object") ||
+ extensions.match("GL_ARB_framebuffer_object"))
+ features |= QOpenGLFunctions::Framebuffers;
+
+ if (format.majorVersion() >= 2) {
+ features |= QOpenGLFunctions::BlendColor |
+ QOpenGLFunctions::BlendEquation |
+ QOpenGLFunctions::BlendSubtract |
+ QOpenGLFunctions::Multitexture |
+ QOpenGLFunctions::CompressedTextures |
+ QOpenGLFunctions::Multisample |
+ QOpenGLFunctions::BlendFuncSeparate |
+ QOpenGLFunctions::Buffers |
+ QOpenGLFunctions::Shaders |
+ QOpenGLFunctions::StencilSeparate |
+ QOpenGLFunctions::BlendEquationSeparate |
+ QOpenGLFunctions::NPOTTextures |
+ QOpenGLFunctions::NPOTTextureRepeat;
+ } else {
+ // Recognize features by extension name.
+ if (extensions.match("GL_ARB_multitexture"))
+ features |= QOpenGLFunctions::Multitexture;
+ if (extensions.match("GL_ARB_shader_objects"))
+ features |= QOpenGLFunctions::Shaders;
+ if (extensions.match("GL_EXT_blend_color"))
+ features |= QOpenGLFunctions::BlendColor;
+ if (extensions.match("GL_EXT_blend_equation_separate"))
+ features |= QOpenGLFunctions::BlendEquationSeparate;
+ if (extensions.match("GL_EXT_blend_subtract"))
+ features |= QOpenGLFunctions::BlendSubtract;
+ if (extensions.match("GL_EXT_blend_func_separate"))
+ features |= QOpenGLFunctions::BlendFuncSeparate;
+ if (extensions.match("GL_ARB_texture_compression"))
+ features |= QOpenGLFunctions::CompressedTextures;
+ if (extensions.match("GL_ARB_multisample"))
+ features |= QOpenGLFunctions::Multisample;
+ if (extensions.match("GL_ARB_texture_non_power_of_two"))
+ features |= QOpenGLFunctions::NPOTTextures |
+ QOpenGLFunctions::NPOTTextureRepeat;
+ }
const QPair<int, int> version = format.version();
if (version < qMakePair(3, 0)
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index acab08e794..ba20186d00 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -761,7 +761,7 @@ void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
bool((painter()->renderHints() & QPainter::TextAntialiasing)
&& !(painter()->font().styleStrategy() & QFont::NoAntialias)));
painter()->translate(p.x(), p.y());
- painter()->fillPath(path, state->pen().brush());
+ painter()->fillPath(path, painter()->pen().brush());
painter()->restore();
}
}
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index e75a59cc91..8487cf2394 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
@@ -830,6 +830,8 @@ void QPaintEngineEx::drawEllipse(const QRectF &r)
int point_count = 0;
x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
+ if (point_count == 0)
+ return;
QVectorPath vp((qreal *) pts, point_count + 1, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
draw(vp);
}
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 7868fd23d1..f6ab123739 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -295,8 +295,7 @@ int QFontMetrics::descent() const
/*!
Returns the height of the font.
- This is always equal to ascent()+descent()+1 (the 1 is for the
- base line).
+ This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/
@@ -1159,8 +1158,7 @@ qreal QFontMetricsF::descent() const
/*!
Returns the height of the font.
- This is always equal to ascent()+descent()+1 (the 1 is for the
- base line).
+ This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 3c5e1e80a8..b4aaca0851 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -338,7 +338,7 @@ void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QStrin
void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
QAuthenticator *authenticator)
{
- manager->proxyAuthenticationRequired(proxy, synchronous, authenticator, &reply->lastProxyAuthentication);
+ manager->proxyAuthenticationRequired(QUrl(), proxy, synchronous, authenticator, &reply->lastProxyAuthentication);
}
#endif
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 473acc5f22..cc61f27cfb 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -99,13 +99,13 @@ bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString&
bool retValue = false;
SecProtocolType protocolType = kSecProtocolTypeAny;
if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeFTP;
+ protocolType = kSecProtocolTypeFTPProxy;
} else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
|| scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeHTTP;
+ protocolType = kSecProtocolTypeHTTPProxy;
} else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
|| scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeHTTPS;
+ protocolType = kSecProtocolTypeHTTPSProxy;
}
QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
err = SecKeychainFindInternetPassword(NULL,
@@ -1392,21 +1392,6 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
}
}
-#ifndef QT_NO_NETWORKPROXY
-#if defined(Q_OS_MACX)
- //now we try to get the username and password from keychain
- //if not successful signal will be emitted
- QString username;
- QString password;
- if (getProxyAuth(proxy.hostName(),reply->request().url().scheme(),username,password)) {
- authenticator->setUser(username);
- authenticator->setPassword(password);
- authenticationManager->cacheProxyCredentials(proxy, authenticator);
- return;
- }
-#endif
-#endif //QT_NO_NETWORKPROXY
-
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
if (synchronous)
@@ -1419,7 +1404,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
}
#ifndef QT_NO_NETWORKPROXY
-void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
+void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url,
+ const QNetworkProxy &proxy,
bool synchronous,
QAuthenticator *authenticator,
QNetworkProxy *lastProxyAuthentication)
@@ -1435,6 +1421,26 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkPro
}
}
+#if defined(Q_OS_OSX)
+ //now we try to get the username and password from keychain
+ //if not successful signal will be emitted
+ QString username;
+ QString password;
+ if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
+ // only cache the system credentials if they are correct (or if they have changed)
+ // to not run into an endless loop in case they are wrong
+ QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
+ if (!priv->hasFailed || cred.user != username || cred.password != password) {
+ authenticator->setUser(username);
+ authenticator->setPassword(password);
+ authenticationManager->cacheProxyCredentials(proxy, authenticator);
+ return;
+ }
+ }
+#else
+ Q_UNUSED(url);
+#endif
+
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
if (synchronous)
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 292755e7eb..9528330aae 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -113,7 +113,8 @@ public:
const QAuthenticator *auth = 0);
#ifndef QT_NO_NETWORKPROXY
- void proxyAuthenticationRequired(const QNetworkProxy &proxy,
+ void proxyAuthenticationRequired(const QUrl &url,
+ const QNetworkProxy &proxy,
bool synchronous,
QAuthenticator *authenticator,
QNetworkProxy *lastProxyAuthentication);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index f043307c10..56105a544b 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -975,6 +975,9 @@ void QNetworkReplyHttpImplPrivate::initCacheSaveDevice()
cacheSaveDevice = managerPrivate->networkCache->prepare(metaData);
+ if (cacheSaveDevice)
+ q->connect(cacheSaveDevice, SIGNAL(aboutToClose()), SLOT(_q_cacheSaveDeviceAboutToClose()));
+
if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) {
if (cacheSaveDevice && !cacheSaveDevice->isOpen())
qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- "
@@ -1220,7 +1223,7 @@ void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetwork
void QNetworkReplyHttpImplPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
QAuthenticator *authenticator)
{
- managerPrivate->proxyAuthenticationRequired(proxy, synchronous, authenticator, &lastProxyAuthentication);
+ managerPrivate->proxyAuthenticationRequired(request.url(), proxy, synchronous, authenticator, &lastProxyAuthentication);
}
#endif
@@ -1708,6 +1711,13 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingDataFinished()
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
+void QNetworkReplyHttpImplPrivate::_q_cacheSaveDeviceAboutToClose()
+{
+ // do not keep a dangling pointer to the device around (device
+ // is closing because e.g. QAbstractNetworkCache::remove() was called).
+ cacheSaveDevice = 0;
+}
+
void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
{
Q_Q(QNetworkReplyHttpImpl);
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index aa2d6f0ec9..d21659ce82 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -130,6 +130,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
+ Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
#ifndef QT_NO_SSL
@@ -179,6 +180,8 @@ public:
void _q_bufferOutgoingData();
void _q_bufferOutgoingDataFinished();
+ void _q_cacheSaveDeviceAboutToClose();
+
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index 49032850be..d27a326fb9 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -85,7 +85,7 @@ public:
explicit QHostAddress(quint32 ip4Addr);
explicit QHostAddress(quint8 *ip6Addr);
explicit QHostAddress(const Q_IPV6ADDR &ip6Addr);
- explicit QHostAddress(const sockaddr *sockaddr);
+ explicit QHostAddress(const sockaddr *address);
explicit QHostAddress(const QString &address);
QHostAddress(const QHostAddress &copy);
QHostAddress(SpecialAddress address);
@@ -97,7 +97,7 @@ public:
void setAddress(quint32 ip4Addr);
void setAddress(quint8 *ip6Addr);
void setAddress(const Q_IPV6ADDR &ip6Addr);
- void setAddress(const sockaddr *sockaddr);
+ void setAddress(const sockaddr *address);
bool setAddress(const QString &address);
QAbstractSocket::NetworkLayerProtocol protocol() const;
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 96c6c0f6ea..6fef819eee 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -202,7 +202,17 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize)
if (!maxSize)
return 0;
- return d->pipeReader->read(data, maxSize);
+ qint64 ret = d->pipeReader->read(data, maxSize);
+
+ // QWindowsPipeReader::read() returns error codes that don't match what we need
+ switch (ret) {
+ case 0: // EOF -> transform to error
+ return -1;
+ case -2: // EWOULDBLOCK -> no error, just no bytes
+ return 0;
+ default:
+ return ret;
+ }
}
qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 77bb727a51..505d6cc42b 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -517,6 +517,8 @@ void ICOReader::read16_24_32BMP(QImage & image)
}
}
+static const char icoOrigDepthKey[] = "_q_icoOrigDepth";
+
QImage ICOReader::iconAt(int index)
{
QImage img;
@@ -535,7 +537,9 @@ QImage ICOReader::iconAt(int index)
if (isPngImage) {
iod->seek(iconEntry.dwImageOffset);
- return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png");
+ QImage image = QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png");
+ image.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount));
+ return image;
}
BMP_INFOHDR header;
@@ -598,6 +602,7 @@ QImage ICOReader::iconAt(int index)
}
}
}
+ img.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount));
}
}
}
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index ea0b5261c4..395bb5b090 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -111,21 +111,17 @@ void TableGenerator::findComposeFile()
}
// check for the system provided compose files
if (!found && cleanState()) {
- QByteArray loc = locale().toUpper().toUtf8();
- QString table = readLocaleMappings(loc);
- if (table.isEmpty())
- table = readLocaleMappings(readLocaleAliases(loc));
-
+ QString table = composeTableForLocale();
if (cleanState()) {
if (table.isEmpty())
// no table mappings for the system's locale in the compose.dir
m_state = UnsupportedLocale;
else
- found = processFile(systemComposeDir() + QLatin1String("/") + table);
+ found = processFile(systemComposeDir() + QLatin1Char('/') + table);
#ifdef DEBUG_GENERATOR
if (found)
qDebug() << "Using Compose file from: " <<
- systemComposeDir() + QLatin1String("/") + table;
+ systemComposeDir() + QLatin1Char('/') + table;
#endif
}
}
@@ -137,6 +133,15 @@ void TableGenerator::findComposeFile()
m_state = MissingComposeFile;
}
+QString TableGenerator::composeTableForLocale()
+{
+ QByteArray loc = locale().toUpper().toUtf8();
+ QString table = readLocaleMappings(loc);
+ if (table.isEmpty())
+ table = readLocaleMappings(readLocaleAliases(loc));
+ return table;
+}
+
bool TableGenerator::findSystemComposeDir()
{
bool found = false;
@@ -311,7 +316,7 @@ void TableGenerator::parseIncludeInstruction(QString line)
// expand substitutions if present
line.replace(QLatin1String("%H"), QString(qgetenv("HOME")));
- line.replace(QLatin1String("%L"), locale());
+ line.replace(QLatin1String("%L"), systemComposeDir() + QLatin1Char('/') + composeTableForLocale());
line.replace(QLatin1String("%S"), systemComposeDir());
processFile(line);
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
index 248c09f3ea..6ce89cfe77 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
@@ -118,13 +118,14 @@ protected:
void findComposeFile();
bool findSystemComposeDir();
QString systemComposeDir();
+ QString composeTableForLocale();
ushort keysymToUtf8(quint32 sym);
QString readLocaleMappings(const QByteArray &locale);
QByteArray readLocaleAliases(const QByteArray &locale);
void initPossibleLocations();
- bool cleanState() const { return ((m_state & NoErrors) == NoErrors); }
+ bool cleanState() const { return m_state == NoErrors; }
QString locale() const;
private:
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index f711a68a71..948b012399 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -549,7 +549,7 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
}
static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
- jint /*widthPixels*/, jint /*heightPixels*/,
+ jint widthPixels, jint heightPixels,
jint desktopWidthPixels, jint desktopHeightPixels,
jdouble xdpi, jdouble ydpi, jdouble scaledDensity)
{
@@ -558,13 +558,17 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
m_scaledDensity = scaledDensity;
if (!m_androidPlatformIntegration) {
- QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,desktopHeightPixels,
- qRound(double(desktopWidthPixels) / xdpi * 25.4),
- qRound(double(desktopHeightPixels) / ydpi * 25.4));
+ QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,
+ desktopHeightPixels,
+ qRound(double(desktopWidthPixels) / xdpi * 25.4),
+ qRound(double(desktopHeightPixels) / ydpi * 25.4),
+ widthPixels,
+ heightPixels);
} else {
m_androidPlatformIntegration->setDisplayMetrics(qRound(double(desktopWidthPixels) / xdpi * 25.4),
qRound(double(desktopHeightPixels) / ydpi * 25.4));
m_androidPlatformIntegration->setDesktopSize(desktopWidthPixels, desktopHeightPixels);
+ m_androidPlatformIntegration->setScreenSize(widthPixels, heightPixels);
}
}
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 213b1bb7e6..d6d7d3b173 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -74,6 +74,8 @@ QT_BEGIN_NAMESPACE
int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320;
int QAndroidPlatformIntegration::m_defaultGeometryHeight = 455;
+int QAndroidPlatformIntegration::m_defaultScreenWidth = 320;
+int QAndroidPlatformIntegration::m_defaultScreenHeight = 455;
int QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth = 50;
int QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight = 71;
@@ -121,7 +123,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_primaryScreen = new QAndroidPlatformScreen();
screenAdded(m_primaryScreen);
m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight));
- m_primaryScreen->setGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight));
+ m_primaryScreen->setAvailableGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight));
+ m_primaryScreen->setSize(QSize(m_defaultScreenWidth, m_defaultScreenHeight));
m_mainThread = QThread::currentThread();
QtAndroid::setAndroidPlatformIntegration(this);
@@ -312,12 +315,14 @@ QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString &
return 0;
}
-void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh)
+void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int screenWidth, int screenHeight)
{
m_defaultGeometryWidth = gw;
m_defaultGeometryHeight = gh;
m_defaultPhysicalSizeWidth = sw;
m_defaultPhysicalSizeHeight = sh;
+ m_defaultScreenWidth = screenWidth;
+ m_defaultScreenHeight = screenHeight;
}
void QAndroidPlatformIntegration::setDefaultDesktopSize(int gw, int gh)
@@ -345,7 +350,7 @@ QPlatformAccessibility *QAndroidPlatformIntegration::accessibility() const
void QAndroidPlatformIntegration::setDesktopSize(int width, int height)
{
if (m_primaryScreen)
- QMetaObject::invokeMethod(m_primaryScreen, "setGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height)));
+ QMetaObject::invokeMethod(m_primaryScreen, "setAvailableGeometry", Qt::AutoConnection, Q_ARG(QRect, QRect(0,0,width, height)));
}
void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height)
@@ -354,4 +359,10 @@ void QAndroidPlatformIntegration::setDisplayMetrics(int width, int height)
QMetaObject::invokeMethod(m_primaryScreen, "setPhysicalSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
}
+void QAndroidPlatformIntegration::setScreenSize(int width, int height)
+{
+ if (m_primaryScreen)
+ QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h
index f8fa1a91dd..ce31516ace 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/qandroidplatformintegration.h
@@ -86,6 +86,7 @@ public:
virtual void setDesktopSize(int width, int height);
virtual void setDisplayMetrics(int width, int height);
+ void setScreenSize(int width, int height);
bool isVirtualDesktop() { return true; }
QPlatformFontDatabase *fontDatabase() const;
@@ -108,7 +109,7 @@ public:
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
- static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh);
+ static void setDefaultDisplayMetrics(int gw, int gh, int sw, int sh, int width, int height);
static void setDefaultDesktopSize(int gw, int gh);
static void setScreenOrientation(Qt::ScreenOrientation currentOrientation,
Qt::ScreenOrientation nativeOrientation);
@@ -135,6 +136,8 @@ private:
static int m_defaultGeometryHeight;
static int m_defaultPhysicalSizeWidth;
static int m_defaultPhysicalSizeHeight;
+ static int m_defaultScreenWidth;
+ static int m_defaultScreenHeight;
static Qt::ScreenOrientation m_orientation;
static Qt::ScreenOrientation m_nativeOrientation;
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 11472ce1da..714a670134 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -86,7 +86,8 @@ private:
QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
{
- m_geometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight);
+ m_availableGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight);
+ m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight);
// Raster only apps should set QT_ANDROID_RASTER_IMAGE_DEPTH to 16
// is way much faster than 32
if (qgetenv("QT_ANDROID_RASTER_IMAGE_DEPTH").toInt() == 16) {
@@ -204,7 +205,7 @@ void QAndroidPlatformScreen::scheduleUpdate()
void QAndroidPlatformScreen::setDirty(const QRect &rect)
{
- QRect intersection = rect.intersected(m_geometry);
+ QRect intersection = rect.intersected(m_availableGeometry);
m_dirtyRect |= intersection;
scheduleUpdate();
}
@@ -214,15 +215,21 @@ void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
m_physicalSize = size;
}
-void QAndroidPlatformScreen::setGeometry(const QRect &rect)
+void QAndroidPlatformScreen::setSize(const QSize &size)
+{
+ m_size = size;
+ QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry());
+}
+
+void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
{
QMutexLocker lock(&m_surfaceMutex);
- if (m_geometry == rect)
+ if (m_availableGeometry == rect)
return;
- QRect oldGeometry = m_geometry;
+ QRect oldGeometry = m_availableGeometry;
- m_geometry = rect;
+ m_availableGeometry = rect;
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry());
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
resizeMaximizedWindows();
@@ -231,9 +238,11 @@ void QAndroidPlatformScreen::setGeometry(const QRect &rect)
QList<QWindow *> windows = QGuiApplication::allWindows();
for (int i = 0; i < windows.size(); ++i) {
QWindow *w = windows.at(i);
- QRect geometry = w->handle()->geometry();
- if (geometry.width() > 0 && geometry.height() > 0)
- QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry));
+ if (w->handle()) {
+ QRect geometry = w->handle()->geometry();
+ if (geometry.width() > 0 && geometry.height() > 0)
+ QWindowSystemInterface::handleExposeEvent(w, QRegion(geometry));
+ }
}
}
@@ -271,7 +280,7 @@ void QAndroidPlatformScreen::doRedraw()
QMutexLocker lock(&m_surfaceMutex);
if (m_id == -1 && m_rasterSurfaces) {
- m_id = QtAndroid::createSurface(this, m_geometry, true, m_depth);
+ m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth);
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index 96a91fbf06..cd9cf2ca71 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -66,7 +66,8 @@ public:
QAndroidPlatformScreen();
~QAndroidPlatformScreen();
- QRect geometry() const { return m_geometry; }
+ QRect geometry() const { return QRect(QPoint(), m_size); }
+ QRect availableGeometry() const { return m_availableGeometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
@@ -87,7 +88,8 @@ public:
public slots:
void setDirty(const QRect &rect);
void setPhysicalSize(const QSize &size);
- void setGeometry(const QRect &rect);
+ void setAvailableGeometry(const QRect &rect);
+ void setSize(const QSize &size);
protected:
typedef QList<QAndroidPlatformWindow *> WindowStackType;
@@ -95,7 +97,7 @@ protected:
QRect m_dirtyRect;
QTimer m_redrawTimer;
- QRect m_geometry;
+ QRect m_availableGeometry;
int m_depth;
QImage::Format m_format;
QSizeF m_physicalSize;
@@ -114,6 +116,7 @@ private:
QAtomicInt m_rasterSurfaces = 0;
ANativeWindow* m_nativeSurface = nullptr;
QWaitCondition m_surfaceWaitCondition;
+ QSize m_size;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index e7f8992c6d..4328487f63 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -870,6 +870,9 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
return;
}
+ if (cleanupModalSessionsNeeded && currentExecIsNSAppRun)
+ cleanupModalSessions();
+
if (processEventsCalled > 0 && interrupt) {
if (currentExecIsNSAppRun) {
// The event dispatcher has been interrupted. But since
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 7e146c5f58..37a0c1feb1 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -54,6 +54,8 @@ class QCocoaBackingStore;
class QCocoaGLContext;
QT_END_NAMESPACE
+Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper);
+
@interface QNSView : NSView <NSTextInputClient> {
QCocoaBackingStore* m_backingStore;
QPoint m_backingStoreOffset;
@@ -72,6 +74,7 @@ QT_END_NAMESPACE
QCocoaGLContext *m_glContext;
bool m_shouldSetGLContextinDrawRect;
NSString *m_inputSource;
+ QNSViewMouseMoveHelper *m_mouseMoveHelper;
}
- (id)init;
@@ -102,9 +105,10 @@ QT_END_NAMESPACE
- (void)mouseDown:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
-- (void)mouseMoved:(NSEvent *)theEvent;
-- (void)mouseEntered:(NSEvent *)theEvent;
-- (void)mouseExited:(NSEvent *)theEvent;
+- (void)mouseMovedImpl:(NSEvent *)theEvent;
+- (void)mouseEnteredImpl:(NSEvent *)theEvent;
+- (void)mouseExitedImpl:(NSEvent *)theEvent;
+- (void)cursorUpdateImpl:(NSEvent *)theEvent;
- (void)rightMouseDown:(NSEvent *)theEvent;
- (void)rightMouseDragged:(NSEvent *)theEvent;
- (void)rightMouseUp:(NSEvent *)theEvent;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 24a9f6fff0..4a744245f0 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -75,6 +75,53 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (CGFloat)deviceDeltaZ;
@end
+@interface QNSViewMouseMoveHelper : NSObject
+{
+ QNSView *view;
+}
+
+- (id)initWithView:(QNSView *)theView;
+
+- (void)mouseMoved:(NSEvent *)theEvent;
+- (void)mouseEntered:(NSEvent *)theEvent;
+- (void)mouseExited:(NSEvent *)theEvent;
+- (void)cursorUpdate:(NSEvent *)theEvent;
+
+@end
+
+@implementation QNSViewMouseMoveHelper
+
+- (id)initWithView:(QNSView *)theView
+{
+ self = [super init];
+ if (self) {
+ view = theView;
+ }
+ return self;
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ [view mouseMovedImpl:theEvent];
+}
+
+- (void)mouseEntered:(NSEvent *)theEvent
+{
+ [view mouseEnteredImpl:theEvent];
+}
+
+- (void)mouseExited:(NSEvent *)theEvent
+{
+ [view mouseExitedImpl:theEvent];
+}
+
+- (void)cursorUpdate:(NSEvent *)theEvent
+{
+ [view cursorUpdateImpl:theEvent];
+}
+
+@end
+
@implementation QNSView
+ (void)initialize
@@ -100,6 +147,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
currentCustomDragTypes = 0;
m_sendUpAsRightButton = false;
m_inputSource = 0;
+ m_mouseMoveHelper = [[QNSViewMouseMoveHelper alloc] initWithView:self];
if (!touchDevice) {
touchDevice = new QTouchDevice;
@@ -119,6 +167,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_subscribesForGlobalFrameNotifications = false;
[m_inputSource release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [m_mouseMoveHelper release];
delete currentCustomDragTypes;
@@ -753,13 +802,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
| NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate;
NSTrackingArea *ta = [[[NSTrackingArea alloc] initWithRect:[self frame]
options:trackingOptions
- owner:self
+ owner:m_mouseMoveHelper
userInfo:nil]
autorelease];
[self addTrackingArea:ta];
}
--(void)cursorUpdate:(NSEvent *)theEvent
+-(void)cursorUpdateImpl:(NSEvent *)theEvent
{
Q_UNUSED(theEvent)
// Set the cursor manually if there is no NSWindow.
@@ -776,10 +825,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
[self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor];
}
-- (void)mouseMoved:(NSEvent *)theEvent
+- (void)mouseMovedImpl:(NSEvent *)theEvent
{
if (m_window->flags() & Qt::WindowTransparentForInput)
- return [super mouseMoved:theEvent];
+ return;
QPointF windowPoint;
QPointF screenPoint;
@@ -806,12 +855,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
[self handleMouseEvent: theEvent];
}
-- (void)mouseEntered:(NSEvent *)theEvent
+- (void)mouseEnteredImpl:(NSEvent *)theEvent
{
+ Q_UNUSED(theEvent)
m_platformWindow->m_windowUnderMouse = true;
if (m_window->flags() & Qt::WindowTransparentForInput)
- return [super mouseEntered:theEvent];
+ return;
// Top-level windows generate enter events for sub-windows.
if (!m_platformWindow->m_nsWindow)
@@ -824,13 +874,13 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
}
-- (void)mouseExited:(NSEvent *)theEvent
+- (void)mouseExitedImpl:(NSEvent *)theEvent
{
+ Q_UNUSED(theEvent);
m_platformWindow->m_windowUnderMouse = false;
if (m_window->flags() & Qt::WindowTransparentForInput)
- return [super mouseExited:theEvent];
- Q_UNUSED(theEvent);
+ return;
// Top-level windows generate leave events for sub-windows.
if (!m_platformWindow->m_nsWindow)
@@ -1316,7 +1366,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
QChar ch = QChar::ReplacementCharacter;
int keyCode = Qt::Key_unknown;
if ([characters length] != 0) {
- if ((modifiers & Qt::MetaModifier) && ([charactersIgnoringModifiers length] != 0))
+ if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
else
ch = QChar([characters characterAtIndex:0]);
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
index 9c922dce36..9c42fdc631 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.h
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.h
@@ -329,7 +329,7 @@ public:
private:
static BSTR relationToBSTR(QAccessible::Relation relation)
{
- wchar_t *constRelationString = 0;
+ const wchar_t *constRelationString = 0;
switch (relation) {
case QAccessible::Label:
constRelationString = IA2_RELATION_LABEL_FOR;
diff --git a/src/plugins/platforms/windows/qplatformfunctions_wince.h b/src/plugins/platforms/windows/qplatformfunctions_wince.h
index 65ce466086..921e64d64c 100644
--- a/src/plugins/platforms/windows/qplatformfunctions_wince.h
+++ b/src/plugins/platforms/windows/qplatformfunctions_wince.h
@@ -271,14 +271,19 @@ typedef struct tagTTPOLYCURVE
#define WM_DRAWCLIPBOARD 0x0308
#endif
+#include <QFileInfo>
+
inline bool IsIconic( HWND /*hWnd*/ )
{
return false;
}
-inline int AddFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*res*/)
+inline int AddFontResourceExW( LPCWSTR name, DWORD /*fl*/, PVOID /*res*/)
{
- return 0;
+ QString fName = QString::fromWCharArray(name);
+ QFileInfo fileinfo(fName);
+ fName = fileinfo.absoluteFilePath();
+ return AddFontResource((LPCWSTR)fName.utf16());
}
inline bool RemoveFontResourceExW( LPCWSTR /*name*/, DWORD /*fl*/, PVOID /*pdv*/)
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index cc0597b72d..4633378342 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -178,10 +178,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
// since we do not want to ignore mouse events coming from a tablet.
const quint64 extraInfo = GetMessageExtraInfo();
if ((extraInfo & signatureMask) == miWpSignature) {
- source = Qt::MouseEventSynthesizedBySystem;
- const bool fromTouch = extraInfo & 0x80; // (else: Tablet PC)
- if (fromTouch && !passSynthesizedMouseEvents)
- return false;
+ if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen.
+ source = Qt::MouseEventSynthesizedBySystem;
+ if (!passSynthesizedMouseEvents)
+ return false;
+ }
}
#endif // !Q_OS_WINCE
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 1b72bb0da1..7f23c84cb9 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1028,6 +1028,15 @@ void QXcbEventReader::registerForEvents()
connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents()));
}
+void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher)
+{
+ // flush the xcb connection before the EventDispatcher is going to block
+ // In the non-threaded case processXcbEvents is called before going to block,
+ // which flushes the connection.
+ if (m_xcb_poll_for_queued_event)
+ connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush()));
+}
+
void QXcbEventReader::run()
{
xcb_generic_event_t *event;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index f96541318c..0bfc2f8f76 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -311,6 +311,8 @@ public:
void start();
+ void registerEventDispatcher(QAbstractEventDispatcher *dispatcher);
+
signals:
void eventPending();
@@ -410,7 +412,6 @@ public:
void sync();
- void flush() { xcb_flush(m_connection); }
void handleXcbError(xcb_generic_error_t *error);
void handleXcbEvent(xcb_generic_event_t *event);
@@ -464,8 +465,11 @@ public:
void handleEnterEvent(const xcb_enter_notify_event_t *);
#endif
+ QXcbEventReader *eventReader() const { return m_reader; }
+
public slots:
void syncWindow(QXcbWindow *window);
+ void flush() { xcb_flush(m_connection); }
private slots:
void processXcbEvents();
@@ -496,8 +500,10 @@ private:
#ifdef XCB_USE_XINPUT2
void initializeXInput2();
void finalizeXInput2();
+ void xi2SetupDevices();
XInput2DeviceData *deviceForId(int id);
void xi2HandleEvent(xcb_ge_event_t *event);
+ void xi2HandleHierachyEvent(void *event);
int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
#ifndef QT_NO_TABLETEVENT
struct TabletData {
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index eb7b220c43..a574dcae6c 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -73,10 +73,6 @@ void QXcbConnection::initializeXInput2()
{
debug_xinput = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT");
debug_xinput_devices = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES");
-#ifndef QT_NO_TABLETEVENT
- m_tabletData.clear();
-#endif
- m_scrollingDevices.clear();
Display *xDisplay = static_cast<Display *>(m_xlib_display);
if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
int xiMajor = 2;
@@ -97,126 +93,146 @@ void QXcbConnection::initializeXInput2()
#else
qDebug("XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor);
#endif
- int deviceCount = 0;
- XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
- for (int i = 0; i < deviceCount; ++i) {
- // Only non-master pointing devices are relevant here.
- if (devices[i].use != XISlavePointer)
- continue;
- if (Q_UNLIKELY(debug_xinput_devices))
- qDebug() << "input device "<< devices[i].name;
+ }
+
+ xi2SetupDevices();
+ }
+}
+
+void QXcbConnection::xi2SetupDevices()
+{
+#ifndef QT_NO_TABLETEVENT
+ m_tabletData.clear();
+#endif
+ m_scrollingDevices.clear();
+
+ if (!m_xi2Enabled)
+ return;
+
+ Display *xDisplay = static_cast<Display *>(m_xlib_display);
+ int deviceCount = 0;
+ XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
+ for (int i = 0; i < deviceCount; ++i) {
+ // Only non-master pointing devices are relevant here.
+ if (devices[i].use != XISlavePointer)
+ continue;
+ if (Q_UNLIKELY(debug_xinput_devices))
+ qDebug() << "input device "<< devices[i].name;
#ifndef QT_NO_TABLETEVENT
- TabletData tabletData;
+ TabletData tabletData;
#endif
- ScrollingDevice scrollingDevice;
- for (int c = 0; c < devices[i].num_classes; ++c) {
- switch (devices[i].classes[c]->type) {
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]);
- const int valuatorAtom = qatom(vci->label);
- if (Q_UNLIKELY(debug_xinput_devices))
- qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
+ ScrollingDevice scrollingDevice;
+ for (int c = 0; c < devices[i].num_classes; ++c) {
+ switch (devices[i].classes[c]->type) {
+ case XIValuatorClass: {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]);
+ const int valuatorAtom = qatom(vci->label);
+ if (Q_UNLIKELY(debug_xinput_devices))
+ qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
#ifndef QT_NO_TABLETEVENT
- if (valuatorAtom < QXcbAtom::NAtoms) {
- TabletData::ValuatorClassInfo info;
- info.minVal = vci->min;
- info.maxVal = vci->max;
- info.number = vci->number;
- tabletData.valuatorInfo[valuatorAtom] = info;
- }
+ if (valuatorAtom < QXcbAtom::NAtoms) {
+ TabletData::ValuatorClassInfo info;
+ info.minVal = vci->min;
+ info.maxVal = vci->max;
+ info.number = vci->number;
+ tabletData.valuatorInfo[valuatorAtom] = info;
+ }
#endif // QT_NO_TABLETEVENT
- if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
- scrollingDevice.lastScrollPosition.setX(vci->value);
- else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
- scrollingDevice.lastScrollPosition.setY(vci->value);
- break;
- }
+ if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ scrollingDevice.lastScrollPosition.setX(vci->value);
+ else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ scrollingDevice.lastScrollPosition.setY(vci->value);
+ break;
+ }
#ifdef XCB_USE_XINPUT21
- case XIScrollClass: {
- XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]);
- if (sci->scroll_type == XIScrollTypeVertical) {
- scrollingDevice.orientations |= Qt::Vertical;
- scrollingDevice.verticalIndex = sci->number;
- scrollingDevice.verticalIncrement = sci->increment;
- }
- else if (sci->scroll_type == XIScrollTypeHorizontal) {
- scrollingDevice.orientations |= Qt::Horizontal;
- scrollingDevice.horizontalIndex = sci->number;
- scrollingDevice.horizontalIncrement = sci->increment;
- }
- break;
- }
- case XIButtonClass: {
- XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]);
- if (bci->num_buttons >= 5) {
- Atom label4 = bci->labels[3];
- Atom label5 = bci->labels[4];
- if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown))
- scrollingDevice.legacyOrientations |= Qt::Vertical;
- }
- if (bci->num_buttons >= 7) {
- Atom label6 = bci->labels[5];
- Atom label7 = bci->labels[6];
- if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
- scrollingDevice.legacyOrientations |= Qt::Horizontal;
- }
- break;
- }
-#endif
- default:
- break;
- }
+ case XIScrollClass: {
+ XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]);
+ if (sci->scroll_type == XIScrollTypeVertical) {
+ scrollingDevice.orientations |= Qt::Vertical;
+ scrollingDevice.verticalIndex = sci->number;
+ scrollingDevice.verticalIncrement = sci->increment;
}
- bool isTablet = false;
-#ifndef QT_NO_TABLETEVENT
- // If we have found the valuators which we expect a tablet to have, assume it's a tablet.
- if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) {
- tabletData.deviceId = devices[i].deviceid;
- tabletData.pointerType = QTabletEvent::Pen;
- if (QByteArray(devices[i].name).toLower().contains("eraser"))
- tabletData.pointerType = QTabletEvent::Eraser;
- m_tabletData.append(tabletData);
- isTablet = true;
- if (Q_UNLIKELY(debug_xinput_devices))
- qDebug() << " it's a tablet with pointer type" << tabletData.pointerType;
+ else if (sci->scroll_type == XIScrollTypeHorizontal) {
+ scrollingDevice.orientations |= Qt::Horizontal;
+ scrollingDevice.horizontalIndex = sci->number;
+ scrollingDevice.horizontalIncrement = sci->increment;
+ }
+ break;
+ }
+ case XIButtonClass: {
+ XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]);
+ if (bci->num_buttons >= 5) {
+ Atom label4 = bci->labels[3];
+ Atom label5 = bci->labels[4];
+ if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp) && (!label5 || qatom(label5) == QXcbAtom::ButtonWheelDown))
+ scrollingDevice.legacyOrientations |= Qt::Vertical;
}
+ if (bci->num_buttons >= 7) {
+ Atom label6 = bci->labels[5];
+ Atom label7 = bci->labels[6];
+ if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
+ scrollingDevice.legacyOrientations |= Qt::Horizontal;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+ bool isTablet = false;
+#ifndef QT_NO_TABLETEVENT
+ // If we have found the valuators which we expect a tablet to have, assume it's a tablet.
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure)) {
+ tabletData.deviceId = devices[i].deviceid;
+ tabletData.pointerType = QTabletEvent::Pen;
+ if (QByteArray(devices[i].name).toLower().contains("eraser"))
+ tabletData.pointerType = QTabletEvent::Eraser;
+ m_tabletData.append(tabletData);
+ isTablet = true;
+ if (Q_UNLIKELY(debug_xinput_devices))
+ qDebug() << " it's a tablet with pointer type" << tabletData.pointerType;
+ }
#endif // QT_NO_TABLETEVENT
#ifdef XCB_USE_XINPUT21
- if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
- scrollingDevice.deviceId = devices[i].deviceid;
- // Only use legacy wheel button events when we don't have real scroll valuators.
- scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
- m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
- if (Q_UNLIKELY(debug_xinput_devices))
- qDebug() << " it's a scrolling device";
- }
+ if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
+ scrollingDevice.deviceId = devices[i].deviceid;
+ // Only use legacy wheel button events when we don't have real scroll valuators.
+ scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
+ m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
+ if (Q_UNLIKELY(debug_xinput_devices))
+ qDebug() << " it's a scrolling device";
+ }
#endif
- if (!isTablet) {
- XInput2DeviceData *dev = deviceForId(devices[i].deviceid);
- if (Q_UNLIKELY(debug_xinput_devices)) {
- if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
- qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d",
- dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
- dev->qtTouchDevice->maximumTouchPoints());
- else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
- qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f",
- dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
- dev->qtTouchDevice->maximumTouchPoints(),
- dev->size.width(), dev->size.height());
- }
- }
+ if (!isTablet) {
+ XInput2DeviceData *dev = deviceForId(devices[i].deviceid);
+ if (Q_UNLIKELY(debug_xinput_devices)) {
+ if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
+ qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints());
+ else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
+ qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints(),
+ dev->size.width(), dev->size.height());
}
- XIFreeDeviceInfo(devices);
}
}
+ XIFreeDeviceInfo(devices);
}
void QXcbConnection::finalizeXInput2()
{
+ foreach (XInput2DeviceData *dev, m_touchDevices) {
+ if (dev->xiDeviceInfo)
+ XIFreeDeviceInfo(dev->xiDeviceInfo);
+ delete dev;
+ }
}
void QXcbConnection::xi2Select(xcb_window_t window)
@@ -303,6 +319,16 @@ void QXcbConnection::xi2Select(xcb_window_t window)
#else
Q_UNUSED(xiBitMask);
#endif
+
+ {
+ // Listen for hotplug events
+ XIEventMask xiEventMask;
+ bitMask = XI_HierarchyChangedMask;
+ xiEventMask.deviceid = XIAllDevices;
+ xiEventMask.mask_len = sizeof(bitMask);
+ xiEventMask.mask = xiBitMask;
+ XISelectEvents(xDisplay, window, &xiEventMask, 1);
+ }
}
XInput2DeviceData *QXcbConnection::deviceForId(int id)
@@ -326,10 +352,10 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id)
if (Q_UNLIKELY(debug_xinput_devices))
qDebug(" has touch class with mode %d", tci->mode);
switch (tci->mode) {
- case XIModeRelative:
+ case XIDependentTouch:
type = QTouchDevice::TouchPad;
break;
- case XIModeAbsolute:
+ case XIDirectTouch:
type = QTouchDevice::TouchScreen;
break;
}
@@ -372,6 +398,7 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id)
m_touchDevices[id] = dev;
} else {
m_touchDevices.remove(id);
+ XIFreeDeviceInfo(dev->xiDeviceInfo);
delete dev;
dev = 0;
}
@@ -402,6 +429,10 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ if (xiEvent->evtype == XI_HierarchyChanged) {
+ xi2HandleHierachyEvent(xiEvent);
+ return;
+ }
#ifndef QT_NO_TABLETEVENT
for (int i = 0; i < m_tabletData.count(); ++i) {
if (m_tabletData.at(i).deviceId == xiEvent->deviceid) {
@@ -561,6 +592,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
}
}
+void QXcbConnection::xi2HandleHierachyEvent(void *event)
+{
+ xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event);
+ // We only care about hotplugged devices
+ if (!(xiEvent->flags & (XISlaveRemoved | XISlaveAdded)))
+ return;
+ xi2SetupDevices();
+ // Reselect events for all event-listening windows.
+ Q_FOREACH (xcb_window_t window, m_mapper.keys()) {
+ xi2Select(window);
+ }
+}
+
void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
{
#ifdef XCB_USE_XINPUT21
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index ddb164bf07..1b1c20f02c 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -303,7 +303,10 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const
{
- return createUnixEventDispatcher();
+ QAbstractEventDispatcher *dispatcher = createUnixEventDispatcher();
+ for (int i = 0; i < m_connections.size(); i++)
+ m_connections[i]->eventReader()->registerEventDispatcher(dispatcher);
+ return dispatcher;
}
void QXcbIntegration::initialize()
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 9f19841437..01e78465b6 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -106,6 +106,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
qDebug(" root ID........: %x", screen()->root);
#endif
+ QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs(
+ xcb_get_window_attributes_reply(xcb_connection(),
+ xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL));
+ const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask;
+
const quint32 mask = XCB_CW_EVENT_MASK;
const quint32 values[] = {
// XCB_CW_EVENT_MASK
@@ -113,6 +118,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
| XCB_EVENT_MASK_LEAVE_WINDOW
| XCB_EVENT_MASK_PROPERTY_CHANGE
| XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification).
+ | existingEventMask // don't overwrite the event mask on the root window
};
xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values);
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index a52aaa4a2e..4d76e4d449 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -109,7 +109,6 @@ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB
CONFIG += qpa/genericunixfontdatabase
contains(QT_CONFIG, dbus) {
-DEFINES += XCB_USE_IBUS
QT += dbus
LIBS += -ldbus-1
}
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index 2c75ab7016..915d8380c7 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -252,6 +252,9 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize,
if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) {
PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data());
DEVMODE *devMode = info->pDevMode;
+ if (!devMode)
+ return margins;
+
HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode);
if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) {
devMode->dmPaperSize = 0;
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index f8ecabee8f..84e01fce49 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -107,7 +107,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QLatin1String("/sqldrivers")))
#endif
-QT_STATIC_CONST_IMPL char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
+#if !defined(Q_CC_MSVC) || _MSC_VER >= 1900
+// ### Qt6: remove the #ifdef
+const
+#endif
+char *QSqlDatabase::defaultConnection = const_cast<char *>("qt_sql_default_connection");
typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;
diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h
index 7249e223a5..ffc10cdd30 100644
--- a/src/sql/kernel/qsqldatabase.h
+++ b/src/sql/kernel/qsqldatabase.h
@@ -113,7 +113,12 @@ public:
QSqlDriver* driver() const;
- QT_STATIC_CONST char *defaultConnection;
+ static
+#if !defined(Q_CC_MSVC) || _MSC_VER >= 1900
+ // ### Qt6: remove the #ifdef
+ const
+#endif
+ char *defaultConnection;
static QSqlDatabase addDatabase(const QString& type,
const QString& connectionName = QLatin1String(defaultConnection));
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index ea4838c8f2..f5700899fa 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -788,7 +788,7 @@ void Moc::parse()
if (!def.hasQObject && !def.hasQGadget)
- error("Class declarations lacks Q_OBJECT macro.");
+ error("Class declaration lacks Q_OBJECT macro.");
// Add meta tags to the plugin meta data:
if (!def.pluginData.iid.isEmpty())
diff --git a/src/widgets/doc/snippets/qstyleplugin/main.cpp b/src/widgets/doc/snippets/qstyleplugin/main.cpp
index 4cf20ab960..e1a0d1b626 100644
--- a/src/widgets/doc/snippets/qstyleplugin/main.cpp
+++ b/src/widgets/doc/snippets/qstyleplugin/main.cpp
@@ -45,7 +45,7 @@
class MyStylePlugin : public QStylePlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json)
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json")
public:
MyStylePlugin(QObject *parent = 0);
diff --git a/src/widgets/doc/src/qtwidgets-index.qdoc b/src/widgets/doc/src/qtwidgets-index.qdoc
index 859a0ef933..bc74f43b35 100644
--- a/src/widgets/doc/src/qtwidgets-index.qdoc
+++ b/src/widgets/doc/src/qtwidgets-index.qdoc
@@ -139,6 +139,7 @@ interfaces
\section2 Examples
\list
\li \l{Qt Widgets Examples}
+ \li \l{Layout Examples}
\endlist
\section1 API Reference
diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
index 99d512b507..f581df4cb3 100644
--- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
@@ -386,5 +386,13 @@
then set it. (This does not only apply to layouts, you should do
the same if you implement your own resizeEvent(), for example.)
\endlist
-*/
+ \section1 Layout Examples
+
+ Many Qt Widgets \l{Qt Widgets Examples}{examples} already use layouts,
+ however, several examples exist to showcase various layouts.
+
+ \list
+ \li \l{Layout Examples}
+ \endlist
+*/
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index d4edc63403..e327a8737a 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -9911,7 +9911,7 @@ void QGraphicsTextItem::setDefaultTextColor(const QColor &col)
}
/*!
- Returns the default text color that is used to for unformatted text.
+ Returns the default text color that is used for unformatted text.
*/
QColor QGraphicsTextItem::defaultTextColor() const
{
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 65e435fbdc..7396808442 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -2912,7 +2912,13 @@ void QWidget::showNormal()
This is the case if neither the widget itself nor every parent up
to but excluding \a ancestor has been explicitly disabled.
- isEnabledTo(0) is equivalent to isEnabled().
+ isEnabledTo(0) returns false if this widget or any if its ancestors
+ was explicitly disabled.
+
+ The word ancestor here means a parent widget within the same window.
+
+ Therefore isEnabledTo(0) stops at this widget's window, unlike
+ isEnabled() which also takes parent windows into considerations.
\sa setEnabled(), enabled
*/
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index e5f552679c..17ed4ca477 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -779,7 +779,10 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
}
}
- if (isMove) {
+ // generate a move event for QWidgets without window handles. QWidgets with native
+ // window handles already receive a move event from
+ // QGuiApplicationPrivate::processGeometryChangeEvent.
+ if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
QMoveEvent e(q->pos(), oldPos);
QApplication::sendEvent(q, &e);
}
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 35a526e77d..fc328e7af0 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -591,24 +591,16 @@ void QWidgetWindow::updateNormalGeometry()
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
- // If the widget's position already matches that of the event, this is a
- // result of call to QWidget::move(), which already sends an event.
- const bool spontaneous = m_widget->geometry().topLeft() != event->pos();
updateGeometry();
- if (spontaneous)
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::sendSpontaneousEvent(m_widget, event);
}
void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
{
QSize oldSize = m_widget->data->crect.size();
- // If the widget's size already matches that of the event, this is a
- // result of call to QWidget::resize(), which already sends an event.
- const bool spontaneous = oldSize != event->size();
updateGeometry();
- if (spontaneous)
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::sendSpontaneousEvent(m_widget, event);
if (m_widget->d_func()->paintOnScreen()) {
QRegion updateRegion(geometry());
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 94f8e36235..60bfc8e075 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -2697,6 +2697,7 @@ void QStyleSheetStyle::polish(QWidget *w)
styleSheetCaches->styleRulesCache.remove(w);
styleSheetCaches->hasStyleRuleCache.remove(w);
styleSheetCaches->renderRulesCache.remove(w);
+ styleSheetCaches->styleSheetCache.remove(w);
}
setGeometry(w);
setProperties(w);
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index f857f4eac0..eae0cbbd06 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1085,6 +1085,19 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
lineEdit->setPalette(q->palette());
}
+void QComboBoxPrivate::updateFocusPolicy()
+{
+#ifdef Q_OS_OSX
+ Q_Q(QComboBox);
+
+ // See comment in QComboBoxPrivate::init()
+ if (q->isEditable())
+ q->setFocusPolicy(Qt::WheelFocus);
+ else
+ q->setFocusPolicy(Qt::TabFocus);
+#endif
+}
+
/*!
Initialize \a option with the values from this QComboBox. This method
is useful for subclasses when they need a QStyleOptionComboBox, but don't want
@@ -1691,10 +1704,6 @@ void QComboBox::setEditable(bool editable)
}
QLineEdit *le = new QLineEdit(this);
setLineEdit(le);
-#ifdef Q_OS_MAC
- // See comment in QComboBoxPrivate::init()
- setFocusPolicy(Qt::WheelFocus);
-#endif
} else {
if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
d->viewContainer()->updateScrollers();
@@ -1704,12 +1713,10 @@ void QComboBox::setEditable(bool editable)
d->lineEdit->hide();
d->lineEdit->deleteLater();
d->lineEdit = 0;
-#ifdef Q_OS_MAC
- // See comment in QComboBoxPrivate::init()
- setFocusPolicy(Qt::TabFocus);
-#endif
}
+ d->updateFocusPolicy();
+
d->viewContainer()->updateTopBottomMargin();
if (!testAttribute(Qt::WA_Resized))
adjustSize();
@@ -1743,6 +1750,7 @@ void QComboBox::setLineEdit(QLineEdit *edit)
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString)));
d->lineEdit->setFrame(false);
d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
+ d->updateFocusPolicy();
d->lineEdit->setFocusProxy(this);
d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
#ifndef QT_NO_COMPLETER
@@ -2055,7 +2063,7 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
if (indexChanged)
currentIndex = QPersistentModelIndex(normalized);
if (lineEdit) {
- QString newText = q->itemText(normalized.row());
+ const QString newText = itemText(normalized);
if (lineEdit->text() != newText)
lineEdit->setText(newText);
updateLineEditGeometry();
@@ -2377,6 +2385,16 @@ QSize QComboBox::sizeHint() const
}
#ifdef Q_OS_OSX
+
+namespace {
+struct IndexSetter {
+ int index;
+ QComboBox *cb;
+
+ void operator()(void) { cb->setCurrentIndex(index); }
+};
+}
+
/*!
* \internal
*
@@ -2391,13 +2409,6 @@ bool QComboBoxPrivate::showNativePopup()
if (QPlatformMenu *menu = theme->createPlatformMenu()) {
int itemsCount = q->count();
- struct IndexSetter {
- int index;
- QComboBox *cb;
-
- void operator()(void) { cb->setCurrentIndex(index); }
- };
-
QList<QPlatformMenuItem *> items;
items.reserve(itemsCount);
QPlatformMenuItem *currentItem = 0;
diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h
index dceffe8d35..fb1ed71ee6 100644
--- a/src/widgets/widgets/qcombobox_p.h
+++ b/src/widgets/widgets/qcombobox_p.h
@@ -376,6 +376,7 @@ public:
void keyboardSearchString(const QString &text);
void modelChanged();
void updateViewContainerPaletteAndOpacity();
+ void updateFocusPolicy();
#ifdef Q_OS_OSX
bool showNativePopup();
diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp
index 40ca73904c..db01543629 100644
--- a/src/widgets/widgets/qfontcombobox.cpp
+++ b/src/widgets/widgets/qfontcombobox.cpp
@@ -548,7 +548,7 @@ bool QFontComboBox::event(QEvent *e)
if (e->type() == QEvent::Resize) {
QListView *lview = qobject_cast<QListView*>(view());
if (lview) {
- setFixedWidth(qMin(width() * 5 / 3,
+ lview->window()->setFixedWidth(qMin(width() * 5 / 3,
QApplication::desktop()->availableGeometry(lview).width()));
}
}
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 358569a5e4..36ca90ba00 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -1226,7 +1226,9 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
/*!
Saves the current state of this mainwindow's toolbars and
- dockwidgets. The \a version number is stored as part of the data.
+ dockwidgets. This includes the corner settings which can
+ be set with setCorner(). The \a version number is stored
+ as part of the data.
The \l{QObject::objectName}{objectName} property is used
to identify each QToolBar and QDockWidget. You should make sure
@@ -1255,8 +1257,9 @@ QByteArray QMainWindow::saveState(int version) const
/*!
Restores the \a state of this mainwindow's toolbars and
- dockwidgets. The \a version number is compared with that stored
- in \a state. If they do not match, the mainwindow's state is left
+ dockwidgets. Also restores the corner settings too. The
+ \a version number is compared with that stored in \a state.
+ If they do not match, the mainwindow's state is left
unchanged, and this function returns \c false; otherwise, the state
is restored, and this function returns \c true.
diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp
index 4b7170a596..6dbc7c8fad 100644
--- a/src/widgets/widgets/qstackedwidget.cpp
+++ b/src/widgets/widgets/qstackedwidget.cpp
@@ -91,7 +91,7 @@ public:
the list using the addWidget() function, or inserted at a given
index using the insertWidget() function. The removeWidget()
function removes a widget from the stacked widget. The number of
- widgets contained in the stacked widget, can
+ widgets contained in the stacked widget can
be obtained using the count() function.
The widget() function returns the widget at a given index
diff --git a/tests/auto/corelib/io/qdebug/qdebug.pro b/tests/auto/corelib/io/qdebug/qdebug.pro
index 820c17fc69..5e902bb105 100644
--- a/tests/auto/corelib/io/qdebug/qdebug.pro
+++ b/tests/auto/corelib/io/qdebug/qdebug.pro
@@ -1,5 +1,5 @@
CONFIG += testcase parallel_test
TARGET = tst_qdebug
-QT = core testlib
+QT = core testlib concurrent
SOURCES = tst_qdebug.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 80144dba20..8fd830a839 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -44,6 +44,9 @@
#include <QtCore/QtDebug>
#include <QtTest/QtTest>
+#include <QtConcurrentRun>
+#include <QFutureSynchronizer>
+
class tst_QDebug: public QObject
{
Q_OBJECT
@@ -59,6 +62,7 @@ private slots:
void qDebugQLatin1String() const;
void textStreamModifiers() const;
void defaultMessagehandler() const;
+ void threadSafety() const;
};
void tst_QDebug::assignment() const
@@ -305,5 +309,41 @@ void tst_QDebug::defaultMessagehandler() const
QVERIFY(same);
}
+QMutex s_mutex;
+QStringList s_messages;
+QSemaphore s_sema;
+
+static void threadSafeMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ QMutexLocker lock(&s_mutex);
+ s_messages.append(msg);
+ Q_UNUSED(type);
+ Q_UNUSED(context);
+}
+
+static void doDebug() // called in each thread
+{
+ s_sema.acquire();
+ qDebug() << "doDebug";
+}
+
+void tst_QDebug::threadSafety() const
+{
+ MessageHandlerSetter mhs(threadSafeMessageHandler);
+ const int numThreads = 10;
+ QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
+ QFutureSynchronizer<void> sync;
+ for (int i = 0; i < numThreads; ++i) {
+ sync.addFuture(QtConcurrent::run(&doDebug));
+ }
+ s_sema.release(numThreads);
+ sync.waitForFinished();
+ QMutexLocker lock(&s_mutex);
+ QCOMPARE(s_messages.count(), numThreads);
+ for (int i = 0; i < numThreads; ++i) {
+ QCOMPARE(s_messages.at(i), QStringLiteral("doDebug"));
+ }
+}
+
QTEST_MAIN(tst_QDebug);
#include "tst_qdebug.moc"
diff --git a/tests/auto/corelib/io/qprocess/test/test.pro b/tests/auto/corelib/io/qprocess/test/test.pro
index 79ea53cc6b..90afeddaa0 100644
--- a/tests/auto/corelib/io/qprocess/test/test.pro
+++ b/tests/auto/corelib/io/qprocess/test/test.pro
@@ -2,7 +2,6 @@ CONFIG += testcase
CONFIG += parallel_test
CONFIG -= app_bundle debug_and_release_target
QT = core testlib network
-embedded: QT += gui
SOURCES = ../tst_qprocess.cpp
TARGET = ../tst_qprocess
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index b67166272b..82a0f3f832 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -1953,7 +1953,7 @@ void tst_QProcess::setStandardOutputFile2()
process.start("testProcessEcho2/testProcessEcho2");
process.write(testdata, sizeof testdata);
QPROCESS_VERIFY(process,waitForFinished());
- QVERIFY(!process.bytesAvailable());
+ QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
QVERIFY(!QFileInfo(QProcess::nullDevice()).isFile());
}
diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
index 6780493206..285cc3042a 100644
--- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
+++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp
@@ -111,6 +111,13 @@ void tst_QRingBuffer::readPointerAtPositionWithHead()
buf2 = ringBuffer.readPointerAtPosition(0, length);
QCOMPARE(length, qint64(0));
QVERIFY(buf2 == 0);
+
+ // check buffer with 2 blocks
+ memcpy(ringBuffer.reserve(4), "0123", 4);
+ ringBuffer.append(QByteArray("45678", 5));
+ ringBuffer.free(3);
+ buf2 = ringBuffer.readPointerAtPosition(1, length);
+ QCOMPARE(length, qint64(5));
}
void tst_QRingBuffer::readPointerAtPositionEmptyRead()
diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp
index 0f642bcc10..524f0a30ed 100644
--- a/tests/auto/gui/image/qicon/tst_qicon.cpp
+++ b/tests/auto/gui/image/qicon/tst_qicon.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
@@ -55,6 +55,7 @@ public:
tst_QIcon();
private slots:
+ void initTestCase();
void actualSize_data(); // test with 1 pixmap
void actualSize();
void actualSize2_data(); // test with 2 pixmaps with different aspect ratio
@@ -79,6 +80,10 @@ private slots:
private:
bool haveImageFormat(QByteArray const&);
+ const QString m_pngImageFileName;
+ const QString m_pngRectFileName;
+ const QString m_sourceFileName;
+
const static QIcon staticIcon;
};
@@ -92,9 +97,19 @@ bool tst_QIcon::haveImageFormat(QByteArray const& desiredFormat)
}
tst_QIcon::tst_QIcon()
+ : m_pngImageFileName(QFINDTESTDATA("image.png"))
+ , m_pngRectFileName(QFINDTESTDATA("rect.png"))
+ , m_sourceFileName(QFINDTESTDATA(__FILE__))
{
}
+void tst_QIcon::initTestCase()
+{
+ QVERIFY(!m_pngImageFileName.isEmpty());
+ QVERIFY(!m_pngRectFileName.isEmpty());
+ QVERIFY(!m_sourceFileName.isEmpty());
+}
+
void tst_QIcon::actualSize_data()
{
QTest::addColumn<QString>("source");
@@ -115,14 +130,13 @@ void tst_QIcon::actualSize_data()
QTest::newRow("resource9") << ":/rect.png" << QSize( 15, 50) << QSize( 15, 30);
QTest::newRow("resource10") << ":/rect.png" << QSize( 25, 50) << QSize( 20, 40);
- const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/";
- QTest::newRow("external0") << prefix + "image.png" << QSize(128, 128) << QSize(128, 128);
- QTest::newRow("external1") << prefix + "image.png" << QSize( 64, 64) << QSize( 64, 64);
- QTest::newRow("external2") << prefix + "image.png" << QSize( 32, 64) << QSize( 32, 32);
- QTest::newRow("external3") << prefix + "image.png" << QSize( 16, 64) << QSize( 16, 16);
- QTest::newRow("external4") << prefix + "image.png" << QSize( 16, 128) << QSize( 16, 16);
- QTest::newRow("external5") << prefix + "image.png" << QSize( 128, 16) << QSize( 16, 16);
- QTest::newRow("external6") << prefix + "image.png" << QSize( 150, 150) << QSize( 128, 128);
+ QTest::newRow("external0") << m_pngImageFileName << QSize(128, 128) << QSize(128, 128);
+ QTest::newRow("external1") << m_pngImageFileName << QSize( 64, 64) << QSize( 64, 64);
+ QTest::newRow("external2") << m_pngImageFileName << QSize( 32, 64) << QSize( 32, 32);
+ QTest::newRow("external3") << m_pngImageFileName << QSize( 16, 64) << QSize( 16, 16);
+ QTest::newRow("external4") << m_pngImageFileName << QSize( 16, 128) << QSize( 16, 16);
+ QTest::newRow("external5") << m_pngImageFileName << QSize(128, 16) << QSize( 16, 16);
+ QTest::newRow("external6") << m_pngImageFileName << QSize(150, 150) << QSize(128, 128);
// rect image
QTest::newRow("external7") << ":/rect.png" << QSize( 20, 40) << QSize( 20, 40);
QTest::newRow("external8") << ":/rect.png" << QSize( 10, 20) << QSize( 10, 20);
@@ -170,10 +184,8 @@ void tst_QIcon::actualSize2_data()
void tst_QIcon::actualSize2()
{
QIcon icon;
- const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/";
-
- icon.addPixmap(QPixmap(prefix + "image.png"));
- icon.addPixmap(QPixmap(prefix + "rect.png"));
+ icon.addPixmap(m_pngImageFileName);
+ icon.addPixmap(m_pngRectFileName);
QFETCH(QSize, argument);
QFETCH(QSize, result);
@@ -209,14 +221,13 @@ void tst_QIcon::isNull() {
QVERIFY(!iconNoFileSuffix.isNull());
QVERIFY(!iconNoFileSuffix.actualSize(QSize(32, 32)).isValid());
- const QString prefix = QFileInfo(QFINDTESTDATA("icons")).absolutePath() + "/";
// test string constructor with existing file but unsupported format
- QIcon iconUnsupportedFormat = QIcon(prefix + "tst_qicon.cpp");
+ QIcon iconUnsupportedFormat = QIcon(m_sourceFileName);
QVERIFY(!iconUnsupportedFormat.isNull());
QVERIFY(!iconUnsupportedFormat.actualSize(QSize(32, 32)).isValid());
// test string constructor with existing file and supported format
- QIcon iconSupportedFormat = QIcon(prefix + "image.png");
+ QIcon iconSupportedFormat = QIcon(m_pngImageFileName);
QVERIFY(!iconSupportedFormat.isNull());
QVERIFY(iconSupportedFormat.actualSize(QSize(32, 32)).isValid());
}
@@ -347,7 +358,7 @@ void tst_QIcon::bestMatch()
void tst_QIcon::cacheKey()
{
- QIcon icon1("image.png");
+ QIcon icon1(m_pngImageFileName);
qint64 icon1_key = icon1.cacheKey();
QIcon icon2 = icon1;
@@ -363,7 +374,7 @@ void tst_QIcon::detach()
img.fill(0xffff0000);
QIcon icon1(QPixmap::fromImage(img));
QIcon icon2 = icon1;
- icon2.addFile(QFINDTESTDATA("image.png"), QSize(64, 64));
+ icon2.addFile(m_pngImageFileName, QSize(64, 64));
QImage img1 = icon1.pixmap(64, 64).toImage();
QImage img2 = icon2.pixmap(64, 64).toImage();
@@ -415,11 +426,11 @@ void tst_QIcon::availableSizes()
{
{
QIcon icon;
- icon.addFile("image.png", QSize(32,32));
- icon.addFile("image.png", QSize(64,64));
- icon.addFile("image.png", QSize(128,128));
- icon.addFile("image.png", QSize(256,256), QIcon::Disabled);
- icon.addFile("image.png", QSize(16,16), QIcon::Normal, QIcon::On);
+ icon.addFile(m_pngImageFileName, QSize(32,32));
+ icon.addFile(m_pngImageFileName, QSize(64,64));
+ icon.addFile(m_pngImageFileName, QSize(128,128));
+ icon.addFile(m_pngImageFileName, QSize(256,256), QIcon::Disabled);
+ icon.addFile(m_pngImageFileName, QSize(16,16), QIcon::Normal, QIcon::On);
QList<QSize> availableSizes = icon.availableSizes();
QCOMPARE(availableSizes.size(), 3);
@@ -542,7 +553,7 @@ static inline bool operator<(const QSize &lhs, const QSize &rhs)
#ifndef QT_NO_WIDGETS
void tst_QIcon::task184901_badCache()
{
- QPixmap pm(QFINDTESTDATA("image.png"));
+ QPixmap pm(m_pngImageFileName);
QIcon icon(pm);
//the disabled icon must have an effect (grayed)
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 95a9b142ec..6c496ba6d4 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -146,6 +146,9 @@ private slots:
void fillRGB888();
+ void fillPixel_data();
+ void fillPixel();
+
void rgbSwapped_data();
void rgbSwapped();
@@ -2054,6 +2057,42 @@ void tst_QImage::fillRGB888()
}
}
+void tst_QImage::fillPixel_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<uint>("color");
+ QTest::addColumn<uint>("pixelValue");
+
+ QTest::newRow("RGB16, transparent") << QImage::Format_RGB16 << 0x0u << 0xff000000u;
+ QTest::newRow("RGB32, transparent") << QImage::Format_RGB32 << 0x0u << 0xff000000u;
+ QTest::newRow("RGBx8888, transparent") << QImage::Format_RGBX8888 << 0x0u << 0xff000000u;
+ QTest::newRow("ARGB32, transparent") << QImage::Format_ARGB32 << 0x0u << 0x00000000u;
+ QTest::newRow("ARGB32pm, transparent") << QImage::Format_ARGB32_Premultiplied << 0x0u << 0x00000000u;
+ QTest::newRow("RGBA8888pm, transparent") << QImage::Format_RGBA8888_Premultiplied << 0x0u << 0x00000000u;
+
+ QTest::newRow("RGB16, red") << QImage::Format_RGB16 << (uint)qConvertRgb32To16(0xffff0000) << 0xffff0000u;
+ QTest::newRow("RGB32, red") << QImage::Format_RGB32 << 0xffff0000u << 0xffff0000u;
+ QTest::newRow("ARGB32, red") << QImage::Format_ARGB32 << 0xffff0000u << 0xffff0000u;
+ QTest::newRow("RGBA8888, red") << QImage::Format_RGBA8888 << 0xff0000ffu << 0xffff0000u;
+
+ QTest::newRow("RGB32, semi-red") << QImage::Format_RGB32 << 0x80ff0000u << 0xffff0000u;
+ QTest::newRow("ARGB32, semi-red") << QImage::Format_ARGB32 << 0x80ff0000u << 0x80ff0000u;
+ QTest::newRow("ARGB32pm, semi-red") << QImage::Format_ARGB32 << 0x80800000u << 0x80800000u;
+ QTest::newRow("RGBA8888pm, semi-red") << QImage::Format_RGBA8888_Premultiplied << 0x80000080u << 0x80800000u;
+}
+
+void tst_QImage::fillPixel()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(uint, color);
+ QFETCH(uint, pixelValue);
+
+ QImage image(1, 1, format);
+
+ image.fill(color);
+ QCOMPARE(image.pixel(0, 0), pixelValue);
+}
+
void tst_QImage::rgbSwapped_data()
{
QTest::addColumn<QImage::Format>("format");
@@ -2124,35 +2163,56 @@ void tst_QImage::mirrored_data()
QTest::addColumn<QImage::Format>("format");
QTest::addColumn<bool>("swap_vertical");
QTest::addColumn<bool>("swap_horizontal");
-
- QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false;
- QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false;
- QTest::newRow("Format_ARGB32_Premultiplied, vertical") << QImage::Format_ARGB32_Premultiplied << true << false;
- QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false;
- QTest::newRow("Format_ARGB8565_Premultiplied, vertical") << QImage::Format_ARGB8565_Premultiplied << true << false;
- QTest::newRow("Format_ARGB6666_Premultiplied, vertical") << QImage::Format_ARGB6666_Premultiplied << true << false;
- QTest::newRow("Format_ARGB4444_Premultiplied, vertical") << QImage::Format_ARGB4444_Premultiplied << true << false;
- QTest::newRow("Format_RGB666, vertical") << QImage::Format_RGB666 << true << false;
- QTest::newRow("Format_RGB555, vertical") << QImage::Format_RGB555 << true << false;
- QTest::newRow("Format_ARGB8555_Premultiplied, vertical") << QImage::Format_ARGB8555_Premultiplied << true << false;
- QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false;
- QTest::newRow("Format_RGB444, vertical") << QImage::Format_RGB444 << true << false;
- QTest::newRow("Format_RGBX8888, vertical") << QImage::Format_RGBX8888 << true << false;
- QTest::newRow("Format_RGBA8888_Premultiplied, vertical") << QImage::Format_RGBA8888_Premultiplied << true << false;
- QTest::newRow("Format_Indexed8, vertical") << QImage::Format_Indexed8 << true << false;
- QTest::newRow("Format_Mono, vertical") << QImage::Format_Mono << true << false;
-
- QTest::newRow("Format_ARGB32_Premultiplied, horizontal") << QImage::Format_ARGB32_Premultiplied << false << true;
- QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true;
- QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true;
- QTest::newRow("Format_Indexed8, horizontal") << QImage::Format_Indexed8 << false << true;
- QTest::newRow("Format_Mono, horizontal") << QImage::Format_Mono << false << true;
-
- QTest::newRow("Format_ARGB32_Premultiplied, horizontal+vertical") << QImage::Format_ARGB32_Premultiplied << true << true;
- QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true;
- QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true;
- QTest::newRow("Format_Indexed8, horizontal+vertical") << QImage::Format_Indexed8 << true << true;
- QTest::newRow("Format_Mono, horizontal+vertical") << QImage::Format_Mono << true << true;
+ QTest::addColumn<int>("width");
+ QTest::addColumn<int>("height");
+
+ QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB32_Premultiplied, vertical") << QImage::Format_ARGB32_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB8565_Premultiplied, vertical") << QImage::Format_ARGB8565_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB6666_Premultiplied, vertical") << QImage::Format_ARGB6666_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB4444_Premultiplied, vertical") << QImage::Format_ARGB4444_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_RGB666, vertical") << QImage::Format_RGB666 << true << false << 16 << 16;
+ QTest::newRow("Format_RGB555, vertical") << QImage::Format_RGB555 << true << false << 16 << 16;
+ QTest::newRow("Format_ARGB8555_Premultiplied, vertical") << QImage::Format_ARGB8555_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false << 16 << 16;
+ QTest::newRow("Format_RGB444, vertical") << QImage::Format_RGB444 << true << false << 16 << 16;
+ QTest::newRow("Format_RGBX8888, vertical") << QImage::Format_RGBX8888 << true << false << 16 << 16;
+ QTest::newRow("Format_RGBA8888_Premultiplied, vertical") << QImage::Format_RGBA8888_Premultiplied << true << false << 16 << 16;
+ QTest::newRow("Format_Indexed8, vertical") << QImage::Format_Indexed8 << true << false << 16 << 16;
+ QTest::newRow("Format_Mono, vertical") << QImage::Format_Mono << true << false << 16 << 16;
+ QTest::newRow("Format_MonoLSB, vertical") << QImage::Format_MonoLSB << true << false << 16 << 16;
+
+ QTest::newRow("Format_ARGB32_Premultiplied, horizontal") << QImage::Format_ARGB32_Premultiplied << false << true << 16 << 16;
+ QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true << 16 << 16;
+ QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true << 16 << 16;
+ QTest::newRow("Format_Indexed8, horizontal") << QImage::Format_Indexed8 << false << true << 16 << 16;
+ QTest::newRow("Format_Mono, horizontal") << QImage::Format_Mono << false << true << 16 << 16;
+ QTest::newRow("Format_MonoLSB, horizontal") << QImage::Format_MonoLSB << false << true << 16 << 16;
+
+ QTest::newRow("Format_ARGB32_Premultiplied, horizontal+vertical") << QImage::Format_ARGB32_Premultiplied << true << true << 16 << 16;
+ QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true << 16 << 16;
+ QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true << 16 << 16;
+ QTest::newRow("Format_Indexed8, horizontal+vertical") << QImage::Format_Indexed8 << true << true << 16 << 16;
+ QTest::newRow("Format_Mono, horizontal+vertical") << QImage::Format_Mono << true << true << 16 << 16;
+ QTest::newRow("Format_MonoLSB, horizontal+vertical") << QImage::Format_MonoLSB << true << true << 16 << 16;
+
+ QTest::newRow("Format_RGB32, vertical") << QImage::Format_RGB32 << true << false << 8 << 16;
+ QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false << 16 << 8;
+ QTest::newRow("Format_Mono, vertical, non-aligned") << QImage::Format_Mono << true << false << 19 << 25;
+ QTest::newRow("Format_MonoLSB, vertical, non-aligned") << QImage::Format_MonoLSB << true << false << 19 << 25;
+
+ // Non-aligned horizontal 1-bit needs special handling so test this.
+ QTest::newRow("Format_Mono, horizontal, non-aligned") << QImage::Format_Mono << false << true << 13 << 17;
+ QTest::newRow("Format_Mono, horizontal, non-aligned") << QImage::Format_Mono << false << true << 19 << 25;
+ QTest::newRow("Format_Mono, horizontal+vertical, non-aligned") << QImage::Format_Mono << true << true << 25 << 47;
+ QTest::newRow("Format_Mono, horizontal+vertical, non-aligned") << QImage::Format_Mono << true << true << 21 << 16;
+
+ QTest::newRow("Format_MonoLSB, horizontal, non-aligned") << QImage::Format_MonoLSB << false << true << 13 << 17;
+ QTest::newRow("Format_MonoLSB, horizontal, non-aligned") << QImage::Format_MonoLSB << false << true << 19 << 25;
+ QTest::newRow("Format_MonoLSB, horizontal+vertical, non-aligned") << QImage::Format_MonoLSB << true << true << 25 << 47;
+ QTest::newRow("Format_MonoLSB, horizontal+vertical, non-aligned") << QImage::Format_MonoLSB << true << true << 21 << 16;
}
void tst_QImage::mirrored()
@@ -2160,11 +2220,14 @@ void tst_QImage::mirrored()
QFETCH(QImage::Format, format);
QFETCH(bool, swap_vertical);
QFETCH(bool, swap_horizontal);
+ QFETCH(int, width);
+ QFETCH(int, height);
- QImage image(16, 16, format);
+ QImage image(width, height, format);
switch (format) {
case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
for (int i = 0; i < image.height(); ++i) {
ushort* scanLine = (ushort*)image.scanLine(i);
*scanLine = (i % 2) ? 0x5555U : 0xCCCCU;
@@ -2201,7 +2264,7 @@ void tst_QImage::mirrored()
QCOMPARE(image, imageMirroredTwice);
- if (format != QImage::Format_Mono)
+ if (format != QImage::Format_Mono && format != QImage::Format_MonoLSB)
QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.byteCount()), 0);
else {
for (int i = 0; i < image.height(); ++i)
diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
index 79dc3f311a..b9d0adcd21 100644
--- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
@@ -91,6 +91,7 @@ private slots:
void convertFromImage_data();
void convertFromImage();
+ void convertFromImageShouldDetach();
void testMetrics();
@@ -343,6 +344,20 @@ void tst_QPixmap::convertFromImage()
QCOMPARE(pix, res);
}
+void tst_QPixmap::convertFromImageShouldDetach()
+{
+ const QString prefix = QFINDTESTDATA("convertFromImage");
+ QImage img1;
+ QImage img2;
+ QVERIFY(img1.load(prefix + "/task31722_0/img1.png"));
+ QVERIFY(img2.load(prefix + "/task31722_0/img2.png"));
+ QPixmap pix = QPixmap::fromImage(img1);
+ QPixmap pix1 = pix;
+ pix.convertFromImage(img2);
+ QCOMPARE(pix, QPixmap::fromImage(img2));
+ QCOMPARE(pix1, QPixmap::fromImage(img1)); // unchanged
+}
+
void tst_QPixmap::scroll_data()
{
QTest::addColumn<QImage>("input");
diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
index 44edcc66c0..4740b92b84 100644
--- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
+++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
@@ -62,6 +62,7 @@ public slots:
void cleanupTestCase();
void init();
void cleanup();
+ void accessAfterRemoveReadyReadSlot();
private slots:
void qnetworkdiskcache_data();
@@ -74,6 +75,7 @@ private slots:
void data();
void metaData();
void remove();
+ void accessAfterRemove(); // QTBUG-17400
void setCacheDirectory_data();
void setCacheDirectory();
void updateMetaData();
@@ -89,6 +91,8 @@ private slots:
private:
QTemporaryDir tempDir;
+ QUrl url; // used by accessAfterRemove()
+ QNetworkDiskCache *diskCache; // used by accessAfterRemove()
};
// FIXME same as in tst_qnetworkreply.cpp .. could be unified
@@ -370,6 +374,40 @@ void tst_QNetworkDiskCache::remove()
QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2);
}
+void tst_QNetworkDiskCache::accessAfterRemove() // QTBUG-17400
+{
+ QByteArray data("HTTP/1.1 200 OK\r\n"
+ "Content-Length: 1\r\n"
+ "\r\n"
+ "a");
+
+ MiniHttpServer server(data);
+
+ QNetworkAccessManager *manager = new QNetworkAccessManager();
+ SubQNetworkDiskCache subCache;
+ subCache.setCacheDirectory(QLatin1String("cacheDir"));
+ diskCache = &subCache;
+ manager->setCache(&subCache);
+
+ url = QUrl("http://127.0.0.1:" + QString::number(server.serverPort()));
+ QNetworkRequest request(url);
+
+ QNetworkReply *reply = manager->get(request);
+ connect(reply, SIGNAL(readyRead()), this, SLOT(accessAfterRemoveReadyReadSlot()));
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ reply->deleteLater();
+ manager->deleteLater();
+}
+
+void tst_QNetworkDiskCache::accessAfterRemoveReadyReadSlot()
+{
+ diskCache->remove(url); // this used to cause a crash later on
+}
+
void tst_QNetworkDiskCache::setCacheDirectory_data()
{
QTest::addColumn<QString>("cacheDir");
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index e6017168d0..407237e519 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -23,6 +23,7 @@ SUBDIRS=\
qobjectperformance \
qobjectrace \
qsharedpointer_and_qwidget \
+ qprocess_and_guieventloop \
qtokenautomaton \
windowsmobile \
@@ -71,3 +72,5 @@ wince*|!contains(QT_CONFIG, accessibility): SUBDIRS -= qaccessibility
!embedded|wince*: SUBDIRS -= \
qdirectpainter
+winrt: SUBDIRS -= \
+ qprocess_and_guieventloop
diff --git a/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro b/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro
new file mode 100644
index 0000000000..e349fe5b11
--- /dev/null
+++ b/tests/auto/other/qprocess_and_guieventloop/qprocess_and_guieventloop.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ write-read-write
+SUBDIRS += test.pro
diff --git a/tests/auto/other/qprocess_and_guieventloop/test.pro b/tests/auto/other/qprocess_and_guieventloop/test.pro
new file mode 100644
index 0000000000..54d6f194b0
--- /dev/null
+++ b/tests/auto/other/qprocess_and_guieventloop/test.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+CONFIG += parallel_test
+QT = core gui testlib
+SOURCES = tst_qprocess_and_guieventloop.cpp
+TARGET = tst_qprocess_and_guieventloop
diff --git a/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp
new file mode 100644
index 0000000000..42153c6c80
--- /dev/null
+++ b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Intel Corporation
+** 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 <QtGui/QGuiApplication>
+#include <QtTest/QtTest>
+#include <QtCore/QProcess>
+
+class tst_QProcess_and_GuiEventLoop : public QObject
+{
+ Q_OBJECT
+private slots:
+ void waitForAndEventLoop();
+};
+
+
+void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop()
+{
+ // based on testcase provided in QTBUG-39488
+ QByteArray msg = "Hello World";
+
+ QProcess process;
+ process.start("write-read-write/write-read-write", QStringList() << msg);
+ QVERIFY(process.waitForStarted(5000));
+ QVERIFY(process.waitForReadyRead(5000));
+ QCOMPARE(process.readAll().trimmed(), msg);
+
+ // run the GUI event dispatcher once
+ QSignalSpy spy(&process, SIGNAL(readyRead()));
+ qApp->processEvents(QEventLoop::AllEvents, 100);
+
+ // we mustn't have read anything in the event loop
+ QCOMPARE(spy.count(), 0);
+
+ // ensure the process hasn't died
+ QVERIFY(!process.waitForFinished(250));
+
+ // we mustn't have read anything during waitForFinished either
+ QCOMPARE(spy.count(), 0);
+
+ // release the child for the second write
+ process.write("\n");
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(int(process.exitStatus()), int(QProcess::NormalExit));
+ QCOMPARE(process.exitCode(), 0);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(process.readAll().trimmed(), msg);
+}
+
+QTEST_MAIN(tst_QProcess_and_GuiEventLoop)
+
+#include "tst_qprocess_and_guieventloop.moc"
diff --git a/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp b/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp
new file mode 100644
index 0000000000..e8fc3b5cff
--- /dev/null
+++ b/tests/auto/other/qprocess_and_guieventloop/write-read-write/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Intel Corporation
+** 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 <stdio.h>
+
+int main(int argc, char **argv)
+{
+ const char *msg = argv[1];
+ char buf[2];
+
+ puts(msg);
+ fflush(stdout);
+
+ // wait for a newline
+ fgets(buf, sizeof buf, stdin);
+
+ puts(msg);
+ fflush(stdout);
+ return 0;
+}
diff --git a/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro b/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro
new file mode 100644
index 0000000000..e236e05c7d
--- /dev/null
+++ b/tests/auto/other/qprocess_and_guieventloop/write-read-write/write-read-write.pro
@@ -0,0 +1,4 @@
+SOURCES = main.cpp
+CONFIG -= qt app_bundle
+CONFIG += console
+DESTDIR = ./
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 04140fa4a1..2e1504383f 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -1828,6 +1828,12 @@ void tst_Moc::warnings_data()
<< QString("IGNORE_ALL_STDOUT")
<< QString(":3: Warning: Macro argument mismatch.\n:4: Warning: Macro argument mismatch.");
+ QTest::newRow("Class declaration lacks Q_OBJECT macro.")
+ << QByteArray("class X : public QObject \n { \n public slots: \n void foo() {} \n };")
+ << QStringList()
+ << 1
+ << QString()
+ << QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro.");
}
void tst_Moc::warnings()
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 73bec9a6b9..eac8ab2236 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -262,7 +262,6 @@ private slots:
void optimizedResizeMove();
void optimizedResize_topLevel();
void resizeEvent();
- void moveEvent();
void task110173();
void testDeletionInEventHandlers();
@@ -1211,6 +1210,12 @@ void tst_QWidget::isEnabledTo()
QVERIFY( !childWidget->isEnabledTo( testWidget ) );
QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
+
+ QMainWindow* childDialog = new QMainWindow(testWidget);
+ testWidget->setEnabled(false);
+ QVERIFY(!childDialog->isEnabled());
+ QVERIFY(childDialog->isEnabledTo(0));
+ testWidget->setEnabled(true);
}
void tst_QWidget::visible()
@@ -2109,53 +2114,41 @@ void tst_QWidget::showFullScreen()
class ResizeWidget : public QWidget {
public:
- ResizeWidget(QWidget *p = 0)
- : QWidget(p)
- , m_spontaneousResizeEventCount(0)
- , m_synthesizedResizeEventCount(0)
- , m_spontaneousMoveEventCount(0)
- , m_synthesizedMoveEventCount(0)
+ ResizeWidget(QWidget *p = 0) : QWidget(p)
{
setObjectName(QLatin1String("ResizeWidget"));
setWindowTitle(objectName());
+ m_resizeEventCount = 0;
}
protected:
void resizeEvent(QResizeEvent *e){
QCOMPARE(size(), e->size());
- (e->spontaneous() ? m_spontaneousResizeEventCount : m_synthesizedResizeEventCount)++;
- }
- void moveEvent(QMoveEvent *e)
- {
- (e->spontaneous() ? m_spontaneousMoveEventCount : m_synthesizedMoveEventCount)++;
+ ++m_resizeEventCount;
}
public:
- int m_spontaneousResizeEventCount;
- int m_synthesizedResizeEventCount;
- int m_spontaneousMoveEventCount;
- int m_synthesizedMoveEventCount;
+ int m_resizeEventCount;
};
void tst_QWidget::resizeEvent()
{
+ QSKIP("QTBUG-30744");
+
{
QWidget wParent;
wParent.resize(200, 200);
ResizeWidget wChild(&wParent);
wParent.show();
QTest::qWaitForWindowExposed(&wParent);
- QCOMPARE (wChild.m_synthesizedResizeEventCount, 1); // initial resize event before paint
- QCOMPARE (wChild.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
wParent.hide();
QSize safeSize(640,480);
if (wChild.size() == safeSize)
safeSize.setWidth(639);
wChild.resize(safeSize);
- QCOMPARE (wChild.m_synthesizedResizeEventCount, 1);
- QCOMPARE (wChild.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wChild.m_resizeEventCount, 1);
wParent.show();
- QCOMPARE (wChild.m_synthesizedResizeEventCount, 2);
- QCOMPARE (wChild.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wChild.m_resizeEventCount, 2);
}
{
@@ -2163,39 +2156,19 @@ void tst_QWidget::resizeEvent()
wTopLevel.resize(200, 200);
wTopLevel.show();
QTest::qWaitForWindowExposed(&wTopLevel);
- const int synthesizedResizeEventCountAfterShow = wTopLevel.m_synthesizedResizeEventCount;
- QCOMPARE (synthesizedResizeEventCountAfterShow, 1); // initial resize event before paint for toplevels
- QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
wTopLevel.hide();
QSize safeSize(640,480);
if (wTopLevel.size() == safeSize)
safeSize.setWidth(639);
wTopLevel.resize(safeSize);
- QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow);
- QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1);
wTopLevel.show();
QTest::qWaitForWindowExposed(&wTopLevel);
-#ifdef Q_OS_OSX
- QEXPECT_FAIL("", "QTBUG-30744", Abort);
-#endif
- QCOMPARE (wTopLevel.m_synthesizedResizeEventCount, synthesizedResizeEventCountAfterShow + 1);
- QCOMPARE (wTopLevel.m_spontaneousResizeEventCount, 0);
+ QCOMPARE (wTopLevel.m_resizeEventCount, 2);
}
}
-void tst_QWidget::moveEvent()
-{
- ResizeWidget wTopLevel;
- wTopLevel.resize(200, 200);
- centerOnScreen(&wTopLevel);
- wTopLevel.show();
- QTest::qWaitForWindowExposed(&wTopLevel);
- const int synthesizedMoveEventCountAfterShow = wTopLevel.m_synthesizedMoveEventCount;
- wTopLevel.move(wTopLevel.pos() + QPoint(20, 20));
- QTRY_COMPARE (wTopLevel.m_synthesizedMoveEventCount, synthesizedMoveEventCountAfterShow + 1);
- QCOMPARE (wTopLevel.m_spontaneousMoveEventCount, 0);
-}
-
void tst_QWidget::showMinimized()
{
QWidget plain;
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 14d59d3630..b1e43b69ad 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -106,7 +106,7 @@ private slots:
void changeStyleInChangeEvent();
void QTBUG15910_crashNullWidget();
void QTBUG36933_brokenPseudoClassLookup();
-
+ void styleSheetChangeBeforePolish();
//at the end because it mess with the style.
void widgetStyle();
void appStyle();
@@ -147,7 +147,7 @@ tst_QStyleSheetStyle::~tst_QStyleSheetStyle()
void tst_QStyleSheetStyle::numinstances()
{
- QWidget w;
+ /*QWidget w;
w.resize(200, 200);
centerOnScreen(&w);
QCommonStyle *style = new QCommonStyle;
@@ -180,7 +180,7 @@ void tst_QStyleSheetStyle::numinstances()
c.setStyle(style);
QCOMPARE(QStyleSheetStyle::numinstances, 2);
w.setStyleSheet("");
- QCOMPARE(QStyleSheetStyle::numinstances, 0);
+ QCOMPARE(QStyleSheetStyle::numinstances, 0);*/
}
void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet()
@@ -351,7 +351,7 @@ void tst_QStyleSheetStyle::repolish()
void tst_QStyleSheetStyle::widgetStyle()
{
- qApp->setStyleSheet("");
+ /*qApp->setStyleSheet("");
QWidget *window1 = new QWidget;
window1->setObjectName("window1");
@@ -488,12 +488,12 @@ void tst_QStyleSheetStyle::widgetStyle()
delete widget2;
delete window2;
delete style1;
- delete style2;
+ delete style2;*/
}
void tst_QStyleSheetStyle::appStyle()
{
- qApp->setStyleSheet("");
+ /* qApp->setStyleSheet("");
// qApp style can never be 0
QVERIFY(QApplication::style() != 0);
QPointer<QStyle> style1 = QStyleFactory::create("Windows");
@@ -531,7 +531,7 @@ void tst_QStyleSheetStyle::appStyle()
QVERIFY(qApp->style() == style1);
qApp->setStyleSheet("");
- QVERIFY(qApp->style() == style1);
+ QVERIFY(qApp->style() == style1);*/
}
void tst_QStyleSheetStyle::dynamicProperty()
@@ -1754,6 +1754,29 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup()
QVERIFY(testForColors(image, QColor(0xFF, 0x00, 0x00)));
}
+void tst_QStyleSheetStyle::styleSheetChangeBeforePolish()
+{
+ QWidget widget;
+ QVBoxLayout *vbox = new QVBoxLayout(&widget);
+ QFrame *frame = new QFrame(&widget);
+ frame->setFixedSize(200, 200);
+ frame->setStyleSheet("background-color: #FF0000;");
+ frame->setStyleSheet("background-color: #00FF00;");
+ vbox->addWidget(frame);
+ QFrame *frame2 = new QFrame(&widget);
+ frame2->setFixedSize(200, 200);
+ frame2->setStyleSheet("background-color: #FF0000;");
+ frame2->setStyleSheet("background-color: #00FF00;");
+ vbox->addWidget(frame);
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+ QImage image(frame->size(), QImage::Format_ARGB32);
+ frame->render(&image);
+ QVERIFY(testForColors(image, QColor(0x00, 0xFF, 0x00)));
+ QImage image2(frame2->size(), QImage::Format_ARGB32);
+ frame2->render(&image2);
+ QVERIFY(testForColors(image2, QColor(0x00, 0xFF, 0x00)));
+}
QTEST_MAIN(tst_QStyleSheetStyle)
#include "tst_qstylesheetstyle.moc"
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index abc0129f8b..c38c254b9a 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
@@ -72,6 +72,7 @@
#include <qstylefactory.h>
#include <qabstractitemview.h>
#include <qstyleditemdelegate.h>
+#include <qstandarditemmodel.h>
#include <qproxystyle.h>
static inline void setFrameless(QWidget *w)
@@ -163,6 +164,7 @@ private slots:
void itemData();
void task_QTBUG_31146_popupCompletion();
void keyboardSelection();
+ void setCustomModelAndView();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@@ -1580,6 +1582,45 @@ void tst_QComboBox::setModel()
QVERIFY(box.model() != oldModel);
}
+void tst_QComboBox::setCustomModelAndView()
+{
+ // QTBUG-27597, ensure the correct text is returned when using custom view and a tree model.
+ QComboBox combo;
+ combo.setWindowTitle("QTBUG-27597, setCustomModelAndView");
+ combo.setEditable(true);
+ combo.setMinimumWidth(400);
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ combo.move(availableGeometry.center() - QPoint(200, 20));
+
+ QStandardItemModel *model = new QStandardItemModel(0, 1, &combo);
+
+ QStandardItem *item = new QStandardItem(QStringLiteral("Item1"));
+ item->appendRow(new QStandardItem(QStringLiteral("Item11")));
+ model->appendRow(item);
+
+ item = new QStandardItem(QStringLiteral("Item2"));
+ model->appendRow(item);
+ const QString subItem21Text = QStringLiteral("Item21");
+ QStandardItem *subItem = new QStandardItem(subItem21Text);
+ item->appendRow(subItem);
+
+ QTreeView* view = new QTreeView(&combo);
+ view->setHeaderHidden(true);
+ view->setSelectionMode(QAbstractItemView::SingleSelection);
+ view->setModel(model);
+ view->expandAll();
+ combo.setModel(model);
+ combo.setView(view);
+ combo.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&combo));
+ combo.showPopup();
+ QTRY_VERIFY(combo.view()->isVisible());
+ const QRect subItemRect = view->visualRect(model->indexFromItem(subItem));
+ QWidget *window = view->window();
+ QTest::mouseClick(window->windowHandle(), Qt::LeftButton, 0, view->mapTo(window, subItemRect.center()));
+ QTRY_COMPARE(combo.currentText(), subItem21Text);
+}
+
void tst_QComboBox::modelDeleted()
{
QComboBox box;