diff --git a/configure b/configure
index ad0f29579b..7cbd11d98d 100755
--- a/configure
+++ b/configure
@@ -617,7 +617,7 @@ CFG_EGL=auto
CFG_EGL_X=auto
CFG_FONTCONFIG=auto
CFG_FREETYPE=auto
-CFG_HARFBUZZ=auto
+CFG_HARFBUZZ=qt
CFG_SQL_AVAILABLE=
QT_ALL_BUILD_PARTS=" libs tools examples tests "
QT_DEFAULT_BUILD_PARTS="libs tools examples"
@@ -2357,13 +2357,14 @@ Third Party Libraries:
+ -system-freetype.... Use the libfreetype provided by the system (enabled if -fontconfig is active).
See http://www.freetype.org
- * -no-harfbuzz ....... Do not compile HarfBuzz-NG support.
- -qt-harfbuzz ....... (experimental) Use HarfBuzz-NG bundled with Qt
+ -no-harfbuzz ....... Do not compile HarfBuzz-NG support.
+ * -qt-harfbuzz ....... Use HarfBuzz-NG bundled with Qt to do text shaping.
+ It can still be disabled by setting
+ the QT_HARFBUZZ environment variable to "old".
+ -system-harfbuzz ... Use HarfBuzz-NG from the operating system
to do text shaping. It can still be disabled
- by setting QT_HARFBUZZ environment variable to "old".
- -system-harfbuzz ... (experimental) Use HarfBuzz-NG from the operating system
- to do text shaping. It can still be disabled
- by setting QT_HARFBUZZ environment variable to "old".
+ by setting the QT_HARFBUZZ environment variable to "old".
+ See http://www.harfbuzz.org
-no-openssl ........ Do not compile support for OpenSSL.
+ -openssl ........... Enable run-time OpenSSL support.
@@ -5301,18 +5302,22 @@ if [ "$CFG_FREETYPE" = "auto" ]; then
fi
# harfbuzz support
-[ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=yes
-[ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=no # disable auto-detection on non-Mac for now
-if [ "$CFG_HARFBUZZ" = "auto" ]; then
- if compileTest unix/harfbuzz "HarfBuzz"; then
- CFG_HARFBUZZ=system
- else
- CFG_HARFBUZZ=yes
+if [ "$CFG_HARFBUZZ" = "system" ]; then
+ if ! compileTest unix/harfbuzz "HarfBuzz"; then
+ if [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
+ echo " HarfBuzz system library support cannot be enabled due to functionality tests!"
+ echo " Turn on verbose messaging (-v) to $0 to see the final report."
+ echo " If you believe this message is in error you may use the continue"
+ echo " switch (-continue) to $0 to continue."
+ exit 101
+ else
+ CFG_HARFBUZZ=qt
+ fi
fi
fi
-if [ "$XPLATFORM_MAC" = "yes" -a "$CFG_HARFBUZZ" = "system" ]; then
+if [ "$XPLATFORM_MAC" = "yes" -a "$CFG_HARFBUZZ" != "qt" ]; then
echo
- echo "WARNING: AAT is not supported with -system-harfbuzz on Mac OS X."
+ echo "WARNING: On OS X, AAT is supported only with -qt-harfbuzz."
echo
fi
@@ -6542,7 +6547,7 @@ report_support " FontConfig ............." "$CFG_FONTCONFIG"
report_support " FreeType ..............." "$CFG_FREETYPE" system "system library" yes "bundled copy"
report_support " Glib ..................." "$CFG_GLIB"
report_support " GTK theme .............." "$CFG_QGTKSTYLE"
-report_support " HarfBuzz ..............." "$CFG_HARFBUZZ"
+report_support " HarfBuzz ..............." "$CFG_HARFBUZZ" system "system library" qt "bundled copy"
report_support " Iconv .................." "$CFG_ICONV"
report_support " ICU ...................." "$CFG_ICU"
report_support " Image formats:"
@@ -6630,6 +6635,13 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo "library names through OPENSSL_LIBS."
echo "For example:"
echo " OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' ./configure -openssl-linked"
+fi
+if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes"]; then
+ echo
+ echo "NOTE: journald or slog2 integration is enabled."
+ echo "If your users intend on developing applications against this build,"
+ echo "ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1"
+ echo "or the IDE is able to read the logged output from journald or slog2."
echo
fi
if [ "$CFG_XKBCOMMON" = "qt" ] && [ "$CFG_XKB_CONFIG_ROOT" = "not found" ]; then
diff --git a/doc/global/macros.qdocconf b/doc/global/macros.qdocconf
index 58d9a71c8c..71a9dc30d1 100644
--- a/doc/global/macros.qdocconf
+++ b/doc/global/macros.qdocconf
@@ -3,12 +3,11 @@ macro.Aring.HTML = "Å"
macro.aring.HTML = "å"
macro.Auml.HTML = "Ä"
macro.author = "\\b{Author:}"
-macro.br.HTML = "
"
macro.BR.HTML = "
"
macro.copyright.HTML = "©"
macro.eacute.HTML = "é"
macro.gui = "\\b"
-macro.hr.HTML = "
"
+macro.HR.HTML = "
"
macro.iacute.HTML = "í"
macro.key = "\\b"
macro.menu = "\\b"
diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css
index c993a07d47..7fc0d62fa6 100644
--- a/doc/global/template/style/offline.css
+++ b/doc/global/template/style/offline.css
@@ -305,6 +305,10 @@ headers
margin-left: 0px;
margin-right: 0px;
}
+ .subtitle, .small-subtitle {
+ display: block;
+ clear: left;
+ }
}
h1 {
diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp
index 152ce8601b..7645c75d8c 100644
--- a/examples/opengl/qopenglwidget/mainwindow.cpp
+++ b/examples/opengl/qopenglwidget/mainwindow.cpp
@@ -95,12 +95,9 @@ MainWindow::MainWindow()
groupBox->setLayout(m_layout);
- QMenu *fileMenu = new QMenu("&File");
- QMenu *helpMenu = new QMenu("&Help");
- QMenu *showMenu = new QMenu("&Show");
- menuBar()->addMenu(fileMenu);
- menuBar()->addMenu(showMenu);
- menuBar()->addMenu(helpMenu);
+ QMenu *fileMenu = menuBar()->addMenu("&File");
+ QMenu *showMenu = menuBar()->addMenu("&Show");
+ QMenu *helpMenu = menuBar()->addMenu("&Help");
QAction *exit = new QAction("E&xit", fileMenu);
QAction *aboutQt = new QAction("About Qt", helpMenu);
QAction *showLogo = new QAction("Show 3D Logo", showMenu);
diff --git a/examples/opengl/qopenglwindow/main.cpp b/examples/opengl/qopenglwindow/main.cpp
index a67bcbb2e3..bf95d09ecd 100644
--- a/examples/opengl/qopenglwindow/main.cpp
+++ b/examples/opengl/qopenglwindow/main.cpp
@@ -185,7 +185,7 @@ int main(int argc, char **argv)
fmt.setDepthBufferSize(24);
fmt.setStencilBufferSize(8);
window.setFormat(fmt);
- window.show();
+ window.showMaximized();
return app.exec();
}
diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp
index 2ff7a09969..b161c271aa 100644
--- a/examples/widgets/richtext/textedit/textedit.cpp
+++ b/examples/widgets/richtext/textedit/textedit.cpp
@@ -104,6 +104,9 @@ TextEdit::TextEdit(QWidget *parent)
textEdit->setFocus();
setCurrentFileName(QString());
+ QFont textFont("Helvetica");
+ textFont.setStyleHint(QFont::SansSerif);
+ textEdit->setFont(textFont);
fontChanged(textEdit->font());
colorChanged(textEdit->textColor());
alignmentChanged(textEdit->alignment());
diff --git a/header.LGPL21 b/header.LGPL21
new file mode 100644
index 0000000000..3148af4c87
--- /dev/null
+++ b/header.LGPL21
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index e16e7ac0c2..cedc6f2f22 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -56,6 +56,7 @@
# if defined(ANGLE_ENABLE_D3D11)
# include
+# include
# include
# include
# include
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index 17a13f97d6..651b065ca2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -305,6 +305,19 @@ EGLint Renderer11::initialize()
mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples);
}
+#if !defined(ANGLE_PLATFORM_WINRT)
+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
+ {
+ ID3D10Multithread *multithread;
+ result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
+ ASSERT(SUCCEEDED(result));
+ result = multithread->SetMultithreadProtected(true);
+ ASSERT(SUCCEEDED(result));
+ multithread->Release();
+ }
+#endif
+
initializeDevice();
return EGL_SUCCESS;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index 491c27a6ab..2c8a79f964 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -319,6 +319,10 @@ EGLint Renderer9::initialize()
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
+ behaviorFlags |= D3DCREATE_MULTITHREADED;
+
{
TRACE_EVENT0("gpu", "D3d9_CreateDevice");
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh
index e2ee78b290..40f2e3d152 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh
@@ -52,7 +52,13 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
#else
#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
#endif
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
+#else
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
+#endif
+
#define hb_mutex_impl_lock(M) EnterCriticalSection (M)
#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-private.hh
index 58d766c85c..3f70d74c26 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-private.hh
@@ -117,15 +117,16 @@
#endif
// Take from https://github.com/behdad/harfbuzz/commit/26a963b9cb4af3119177f277a2d48a5d537458fb
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE)
/* Some things not defined on Windows CE. */
#define MemoryBarrier()
#define getenv(Name) NULL
#define setlocale(Category, Locale) "C"
static int errno = 0; /* Use something better? */
+#elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define getenv(Name) NULL
#endif
-
/* Basics */
diff --git a/src/3rdparty/pcre/patches/pcre-r1495.patch b/src/3rdparty/pcre/patches/pcre-r1495.patch
new file mode 100644
index 0000000000..d8b4ce097a
--- /dev/null
+++ b/src/3rdparty/pcre/patches/pcre-r1495.patch
@@ -0,0 +1,23 @@
+Index: pcre_compile.c
+===================================================================
+--- pcre_compile.c (revision 1494)
++++ pcre_compile.c (revision 1495)
+@@ -8267,12 +8267,16 @@
+
+ /* If it was a capturing subpattern, check to see if it contained any
+ recursive back references. If so, we must wrap it in atomic brackets.
+- In any event, remove the block from the chain. */
++ Because we are moving code along, we must ensure that any pending recursive
++ references are updated. In any event, remove the block from the chain. */
+
+ if (capnumber > 0)
+ {
+ if (cd->open_caps->flag)
+ {
++ *code = OP_END;
++ adjust_recurse(start_bracket, 1 + LINK_SIZE,
++ (options & PCRE_UTF8) != 0, cd, cd->hwm);
+ memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
+ IN_UCHARS(code - start_bracket));
+ *start_bracket = OP_ONCE;
+
diff --git a/src/3rdparty/pcre/patches/pcre-r1498.patch b/src/3rdparty/pcre/patches/pcre-r1498.patch
new file mode 100644
index 0000000000..8ae48a4336
--- /dev/null
+++ b/src/3rdparty/pcre/patches/pcre-r1498.patch
@@ -0,0 +1,45 @@
+Index: pcre_compile.c
+===================================================================
+--- pcre_compile.c (revision 1497)
++++ pcre_compile.c (revision 1498)
+@@ -2374,6 +2374,7 @@
+ if (c == OP_RECURSE)
+ {
+ const pcre_uchar *scode = cd->start_code + GET(code, 1);
++ const pcre_uchar *endgroup = scode;
+ BOOL empty_branch;
+
+ /* Test for forward reference or uncompleted reference. This is disabled
+@@ -2388,24 +2389,20 @@
+ if (GET(scode, 1) == 0) return TRUE; /* Unclosed */
+ }
+
+- /* If we are scanning a completed pattern, there are no forward references
+- and all groups are complete. We need to detect whether this is a recursive
+- call, as otherwise there will be an infinite loop. If it is a recursion,
+- just skip over it. Simple recursions are easily detected. For mutual
+- recursions we keep a chain on the stack. */
++ /* If the reference is to a completed group, we need to detect whether this
++ is a recursive call, as otherwise there will be an infinite loop. If it is
++ a recursion, just skip over it. Simple recursions are easily detected. For
++ mutual recursions we keep a chain on the stack. */
+
++ do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
++ if (code >= scode && code <= endgroup) continue; /* Simple recursion */
+ else
+- {
++ {
+ recurse_check *r = recurses;
+- const pcre_uchar *endgroup = scode;
+-
+- do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
+- if (code >= scode && code <= endgroup) continue; /* Simple recursion */
+-
+ for (r = recurses; r != NULL; r = r->prev)
+ if (r->group == scode) break;
+ if (r != NULL) continue; /* Mutual recursion */
+- }
++ }
+
+ /* Completed reference; scan the referenced group, remembering it on the
+ stack chain to detect mutual recursions. */
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
index 5ce6b73c44..ce365e2915 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre/pcre_compile.c
@@ -2370,6 +2370,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
if (c == OP_RECURSE)
{
const pcre_uchar *scode = cd->start_code + GET(code, 1);
+ const pcre_uchar *endgroup = scode;
BOOL empty_branch;
/* Test for forward reference or uncompleted reference. This is disabled
@@ -2384,24 +2385,20 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
if (GET(scode, 1) == 0) return TRUE; /* Unclosed */
}
- /* If we are scanning a completed pattern, there are no forward references
- and all groups are complete. We need to detect whether this is a recursive
- call, as otherwise there will be an infinite loop. If it is a recursion,
- just skip over it. Simple recursions are easily detected. For mutual
- recursions we keep a chain on the stack. */
+ /* If the reference is to a completed group, we need to detect whether this
+ is a recursive call, as otherwise there will be an infinite loop. If it is
+ a recursion, just skip over it. Simple recursions are easily detected. For
+ mutual recursions we keep a chain on the stack. */
+ do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
+ if (code >= scode && code <= endgroup) continue; /* Simple recursion */
else
- {
+ {
recurse_check *r = recurses;
- const pcre_uchar *endgroup = scode;
-
- do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
- if (code >= scode && code <= endgroup) continue; /* Simple recursion */
-
for (r = recurses; r != NULL; r = r->prev)
if (r->group == scode) break;
if (r != NULL) continue; /* Mutual recursion */
- }
+ }
/* Completed reference; scan the referenced group, remembering it on the
stack chain to detect mutual recursions. */
@@ -8244,12 +8241,16 @@ for (;;)
/* If it was a capturing subpattern, check to see if it contained any
recursive back references. If so, we must wrap it in atomic brackets.
- In any event, remove the block from the chain. */
+ Because we are moving code along, we must ensure that any pending recursive
+ references are updated. In any event, remove the block from the chain. */
if (capnumber > 0)
{
if (cd->open_caps->flag)
{
+ *code = OP_END;
+ adjust_recurse(start_bracket, 1 + LINK_SIZE,
+ (options & PCRE_UTF8) != 0, cd, cd->hwm);
memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
IN_UCHARS(code - start_bracket));
*start_bracket = OP_ONCE;
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 31a99bf910..014023ecb1 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -108,15 +108,20 @@ public class QtNative
}
}
- public static void openURL(String url)
+ public static boolean openURL(String url)
{
+ boolean ok = true;
+
try {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
activity().startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
+ ok = false;
}
+
+ return ok;
}
// this method loads full path libs
diff --git a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
new file mode 100644
index 0000000000..1e60f0c54a
--- /dev/null
+++ b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
@@ -0,0 +1,72 @@
+From d52fac0c0b5d12cd117ae4b871f0ac6a202755ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michael=20Br=C3=BCning?=
+Date: Wed, 27 Aug 2014 12:42:00 +0200
+Subject: [PATCH] Let ANGLE use multithreaded devices if necessary.
+
+This is needed to prevent lock-ups in application that use ANGLE from
+multiple threads, as e.g. QtWebEngine based applications do.
+
+The environment variable QT_D3DCREATE_MULTITHREADED is used to
+communicate this from the QtWebEngine module.
+
+Change-Id: Ibd5a5c75eb68af567d420d9a35efb3490c93b27c
+---
+ src/3rdparty/angle/src/common/platform.h | 1 +
+ .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 13 +++++++++++++
+ .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 ++++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
+index e16e7ac..cedc6f2 100644
+--- a/src/3rdparty/angle/src/common/platform.h
++++ b/src/3rdparty/angle/src/common/platform.h
+@@ -56,6 +56,7 @@
+
+ # if defined(ANGLE_ENABLE_D3D11)
+ # include
++# include
+ # include
+ # include
+ # include
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+index 17a13f9..651b065 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+@@ -305,6 +305,19 @@ EGLint Renderer11::initialize()
+ mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples);
+ }
+
++#if !defined(ANGLE_PLATFORM_WINRT)
++ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
++ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
++ {
++ ID3D10Multithread *multithread;
++ result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
++ ASSERT(SUCCEEDED(result));
++ result = multithread->SetMultithreadProtected(true);
++ ASSERT(SUCCEEDED(result));
++ multithread->Release();
++ }
++#endif
++
+ initializeDevice();
+
+ return EGL_SUCCESS;
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+index 491c27a..2c8a79f 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+@@ -319,6 +319,10 @@ EGLint Renderer9::initialize()
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
+
++ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
++ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
++ behaviorFlags |= D3DCREATE_MULTITHREADED;
++
+ {
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+--
+1.8.3.2
+
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 95d7713cfe..28a09ee2e4 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -222,7 +222,8 @@ QUnifiedTimer::QUnifiedTimer() :
QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false),
startTimersPending(false), stopTimerPending(false),
- slowdownFactor(5.0f), profilerCallback(0)
+ slowdownFactor(5.0f), profilerCallback(0),
+ driverStartTime(0), temporalDrift(0)
{
time.invalidate();
driver = &defaultDriver;
@@ -253,18 +254,56 @@ QUnifiedTimer *QUnifiedTimer::instance()
void QUnifiedTimer::maybeUpdateAnimationsToCurrentTime()
{
- qint64 elapsed = driver->elapsed();
- if (elapsed - lastTick > 50)
- updateAnimationTimers(elapsed);
+ if (elapsed() - lastTick > 50)
+ updateAnimationTimers(-1);
}
-void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
+qint64 QUnifiedTimer::elapsed() const
+{
+ if (driver->isRunning())
+ return driverStartTime + driver->elapsed();
+ else if (time.isValid())
+ return time.elapsed() + temporalDrift;
+
+ // Reaching here would normally indicate that the function is called
+ // under the wrong circumstances as neither pauses nor actual animations
+ // are running and there should be no need to query for elapsed().
+ return 0;
+}
+
+void QUnifiedTimer::startAnimationDriver()
+{
+ if (driver->isRunning()) {
+ qWarning("QUnifiedTimer::startAnimationDriver: driver is already running...");
+ return;
+ }
+ // Set the start time to the currently elapsed() value before starting.
+ // This means we get the animation system time including the temporal drift
+ // which is what we want.
+ driverStartTime = elapsed();
+ driver->start();
+}
+
+void QUnifiedTimer::stopAnimationDriver()
+{
+ if (!driver->isRunning()) {
+ qWarning("QUnifiedTimer::stopAnimationDriver: driver is not running");
+ return;
+ }
+ // Update temporal drift. Since the driver is running, elapsed() will
+ // return the total animation time in driver-time. Subtract the current
+ // wall time to get the delta.
+ temporalDrift = elapsed() - time.elapsed();
+ driver->stop();
+}
+
+void QUnifiedTimer::updateAnimationTimers(qint64)
{
//setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations
if(insideTick)
return;
- qint64 totalElapsed = currentTick >= 0 ? currentTick : driver->elapsed();
+ qint64 totalElapsed = elapsed();
// ignore consistentTiming in case the pause timer is active
qint64 delta = (consistentTiming && !pauseTimer.isActive()) ?
@@ -323,8 +362,7 @@ void QUnifiedTimer::localRestart()
} else if (!driver->isRunning()) {
if (pauseTimer.isActive())
pauseTimer.stop();
- driver->setStartTime(time.isValid() ? time.elapsed() : 0);
- driver->start();
+ startAnimationDriver();
}
}
@@ -345,27 +383,26 @@ void QUnifiedTimer::setTimingInterval(int interval)
if (driver->isRunning() && !pauseTimer.isActive()) {
//we changed the timing interval
- driver->stop();
- driver->setStartTime(time.isValid() ? time.elapsed() : 0);
- driver->start();
+ stopAnimationDriver();
+ startAnimationDriver();
}
}
void QUnifiedTimer::startTimers()
{
startTimersPending = false;
- if (!animationTimers.isEmpty())
- updateAnimationTimers(-1);
//we transfer the waiting animations into the "really running" state
animationTimers += animationTimersToStart;
animationTimersToStart.clear();
if (!animationTimers.isEmpty()) {
- localRestart();
if (!time.isValid()) {
lastTick = 0;
time.start();
+ temporalDrift = 0;
+ driverStartTime = 0;
}
+ localRestart();
}
}
@@ -373,7 +410,7 @@ void QUnifiedTimer::stopTimer()
{
stopTimerPending = false;
if (animationTimers.isEmpty()) {
- driver->stop();
+ stopAnimationDriver();
pauseTimer.stop();
// invalidate the start reference time
time.invalidate();
@@ -483,14 +520,12 @@ void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d)
return;
}
- if (driver->isRunning()) {
- driver->stop();
- d->setStartTime(time.isValid() ? time.elapsed() : 0);
- d->start();
- }
-
+ bool running = driver->isRunning();
+ if (running)
+ stopAnimationDriver();
driver = d;
-
+ if (running)
+ startAnimationDriver();
}
void QUnifiedTimer::uninstallAnimationDriver(QAnimationDriver *d)
@@ -500,13 +535,12 @@ void QUnifiedTimer::uninstallAnimationDriver(QAnimationDriver *d)
return;
}
+ bool running = driver->isRunning();
+ if (running)
+ stopAnimationDriver();
driver = &defaultDriver;
-
- if (d->isRunning()) {
- d->stop();
- driver->setStartTime(time.isValid() ? time.elapsed() : 0);
- driver->start();
- }
+ if (running)
+ startAnimationDriver();
}
/*!
@@ -603,10 +637,12 @@ void QAnimationTimer::restartAnimationTimer()
void QAnimationTimer::startAnimations()
{
+ if (!startAnimationPending)
+ return;
startAnimationPending = false;
+
//force timer to update, which prevents large deltas for our newly added animations
- if (!animations.isEmpty())
- QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
+ QUnifiedTimer::instance()->maybeUpdateAnimationsToCurrentTime();
//we transfer the waiting animations into the "really running" state
animations += animationsToStart;
@@ -618,7 +654,8 @@ void QAnimationTimer::startAnimations()
void QAnimationTimer::stopTimer()
{
stopTimerPending = false;
- if (animations.isEmpty()) {
+ bool pendingStart = startAnimationPending && animationsToStart.size() > 0;
+ if (animations.isEmpty() && !pendingStart) {
QUnifiedTimer::resumeAnimationTimer(this);
QUnifiedTimer::stopAnimationTimer(this);
// invalidate the start reference time
@@ -749,20 +786,25 @@ QAnimationDriver::~QAnimationDriver()
This is to take into account that pauses can occur in running
animations which will stop the driver, but the time still
increases.
+
+ \obsolete
+
+ This logic is now handled internally in the animation system.
*/
-void QAnimationDriver::setStartTime(qint64 startTime)
+void QAnimationDriver::setStartTime(qint64)
{
- Q_D(QAnimationDriver);
- d->startTime = startTime;
}
/*!
Returns the start time of the animation.
+
+ \obsolete
+
+ This logic is now handled internally in the animation system.
*/
qint64 QAnimationDriver::startTime() const
{
- Q_D(const QAnimationDriver);
- return d->startTime;
+ return 0;
}
@@ -772,6 +814,10 @@ qint64 QAnimationDriver::startTime() const
If \a timeStep is positive, it will be used as the current time in the
calculations; otherwise, the current clock time will be used.
+
+ Since 5.4, the timeStep argument is ignored and elapsed() will be
+ used instead in combination with the internal time offsets of the
+ animation system.
*/
void QAnimationDriver::advanceAnimation(qint64 timeStep)
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
index f1aa6c0d78..2d0a88e45f 100644
--- a/src/corelib/animation/qabstractanimation.h
+++ b/src/corelib/animation/qabstractanimation.h
@@ -149,6 +149,7 @@ public:
virtual qint64 elapsed() const;
+ // ### Qt6: Remove these two functions
void setStartTime(qint64 startTime);
qint64 startTime() const;
@@ -157,6 +158,7 @@ Q_SIGNALS:
void stopped();
protected:
+ // ### Qt6: Remove timestep argument
void advanceAnimation(qint64 timeStep = -1);
virtual void start();
virtual void stop();
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index 39d9cf0fe6..6e71356c4c 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -132,9 +132,8 @@ private:
class Q_CORE_EXPORT QAnimationDriverPrivate : public QObjectPrivate
{
public:
- QAnimationDriverPrivate() : running(false), startTime(0) {}
+ QAnimationDriverPrivate() : running(false) {}
bool running;
- qint64 startTime;
};
class Q_CORE_EXPORT QAbstractAnimationTimer : public QObject
@@ -193,6 +192,10 @@ public:
int runningAnimationCount();
void registerProfilerCallback(void (*cb)(qint64));
+ void startAnimationDriver();
+ void stopAnimationDriver();
+ qint64 elapsed() const;
+
protected:
void timerEvent(QTimerEvent *);
@@ -233,6 +236,9 @@ private:
int closestPausedAnimationTimerTimeToFinish();
void (*profilerCallback)(qint64);
+
+ qint64 driverStartTime; // The time the animation driver was started
+ qint64 temporalDrift; // The delta between animation driver time and wall time.
};
class QAnimationTimer : public QAbstractAnimationTimer
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 7e3e629c47..9bce7bf614 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -1045,7 +1045,7 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
// determine charset
QTextCodec *c = QTextCodec::codecForUtfText(ba, 0);
if (!c) {
- QByteArray header = ba.left(512).toLower();
+ QByteArray header = ba.left(1024).toLower();
int pos = header.indexOf("meta ");
if (pos != -1) {
pos = header.indexOf("charset=", pos);
diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc
index 70f0b88e06..1a79a622b3 100644
--- a/src/corelib/doc/src/objectmodel/properties.qdoc
+++ b/src/corelib/doc/src/objectmodel/properties.qdoc
@@ -249,7 +249,7 @@
If the value is \e not compatible with the property's type, the
property is \e not changed, and false is returned. But if the
property with the given name doesn't exist in the QObject (i.e.,
- if it wasn't declared with Q_PROPERTY(), a new property with the
+ if it wasn't declared with Q_PROPERTY()), a new property with the
given name and value is automatically added to the QObject, but
false is still returned. This means that a return of false can't
be used to determine whether a particular property was actually
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index e894d547d0..d290d7dc37 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -392,7 +392,7 @@
compatible with the slot's arguments. Arguments can also be implicitly
converted by the compiler, if needed.
- You can also connect to functors or C++11 lamdas:
+ You can also connect to functors or C++11 lambdas:
\code
connect(sender, &QObject::destroyed, [=](){ this->m_objects.remove(sender); });
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 673369a012..9176d80f43 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -880,7 +880,12 @@ public:
int control;
};
-# ifdef Q_COMPILER_DECLTYPE
+// We need to use __typeof__ if we don't have decltype or if the compiler
+// hasn't been updated to the fix of Core Language Defect Report 382
+// (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#382).
+// GCC 4.3 and 4.4 have support for decltype, but are affected by DR 382.
+# if defined(Q_COMPILER_DECLTYPE) && \
+ (defined(Q_CC_CLANG) || defined(Q_CC_INTEL) || !defined(Q_CC_GNU) || (__GNUC__ * 100 + __GNUC_MINOR__) >= 405)
# define QT_FOREACH_DECLTYPE(x) typename QtPrivate::remove_reference::type
# else
# define QT_FOREACH_DECLTYPE(x) __typeof__((x))
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 485193b071..0da868602c 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -98,6 +98,7 @@ Qt {
#ifndef QT_NO_GESTURES
Q_ENUMS(GestureState)
Q_ENUMS(GestureType)
+ Q_ENUMS(NativeGestureType)
#endif
Q_ENUMS(CursorMoveStyle)
Q_ENUMS(TimerType)
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 81aed5f7b4..cebca1a56f 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -369,15 +369,15 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 maxlen)
if (fileHandle == INVALID_HANDLE_VALUE)
return -1;
- DWORD bytesToRead = DWORD(maxlen); // <- lossy
+ qint64 bytesToRead = maxlen;
// Reading on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
// the chunks are too large, so we limit the block size to 32MB.
- static const DWORD maxBlockSize = 32 * 1024 * 1024;
+ static const qint64 maxBlockSize = 32 * 1024 * 1024;
qint64 totalRead = 0;
do {
- DWORD blockSize = qMin(bytesToRead, maxBlockSize);
+ DWORD blockSize = DWORD(qMin(bytesToRead, maxBlockSize));
DWORD bytesRead;
if (!ReadFile(fileHandle, data + totalRead, blockSize, &bytesRead, NULL)) {
if (totalRead == 0) {
@@ -392,7 +392,7 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 maxlen)
totalRead += bytesRead;
bytesToRead -= bytesRead;
} while (totalRead < maxlen);
- return qint64(totalRead);
+ return totalRead;
}
/*
diff --git a/src/corelib/io/qsettings_winrt.cpp b/src/corelib/io/qsettings_winrt.cpp
index 82632bd16d..ad02f050e5 100644
--- a/src/corelib/io/qsettings_winrt.cpp
+++ b/src/corelib/io/qsettings_winrt.cpp
@@ -324,7 +324,7 @@ QWinRTSettingsPrivate::QWinRTSettingsPrivate(QSettings::Scope scope, const QStri
}
QWinRTSettingsPrivate::QWinRTSettingsPrivate(QString rPath)
- : QSettingsPrivate(QSettings::NativeFormat)
+ : QSettingsPrivate(QSettings::NativeFormat, QSettings::UserScope, rPath, QString())
, writeContainer(0)
{
init(QSettings::UserScope);
diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp
index 205ab3f62c..388b71b39c 100644
--- a/src/corelib/io/qstorageinfo.cpp
+++ b/src/corelib/io/qstorageinfo.cpp
@@ -48,24 +48,24 @@ QT_BEGIN_NAMESPACE
\class QStorageInfo
\inmodule QtCore
\since 5.4
- \brief Provides information about currently mounted storages and drives.
+ \brief Provides information about currently mounted storage and drives.
\ingroup io
\ingroup shared
Allows retrieving information about the volume's space, its mount point,
- label, filesystem name.
+ label, and filesystem name.
You can create an instance of QStorageInfo by passing the path to the
- volume's mount point as the constructor parameter, or you can set it using
- setPath() method. The static mountedVolumes() method can be used to get the
+ volume's mount point as a constructor parameter, or you can set it using
+ the setPath() method. The static mountedVolumes() method can be used to get the
list of all mounted filesystems.
- QStorageInfo always caches the retrieved information but you can call
+ QStorageInfo always caches the retrieved information, but you can call
refresh() to invalidate the cache.
The following example retrieves the most common information about the root
- volume of the system and prints information about it.
+ volume of the system, and prints information about it.
\snippet code/src_corelib_io_qstorageinfo.cpp 2
*/
@@ -73,7 +73,8 @@ QT_BEGIN_NAMESPACE
/*!
Constructs an empty QStorageInfo object.
- This object is not ready for use, invalid and all its parameters are empty.
+ Objects created with the default constructor will be invalid and therefore
+ not ready for use.
\sa setPath(), isReady(), isValid()
*/
@@ -83,15 +84,15 @@ QStorageInfo::QStorageInfo()
}
/*!
- Constructs a new QStorageInfo that gives information about the volume
+ Constructs a new QStorageInfo object that gives information about the volume
mounted at \a path.
If you pass a directory or file, the QStorageInfo object will refer to the
volume where this directory or file is located.
You can check if the created object is correct using the isValid() method.
- The following example shows how to get volume on which application is
- located. It is recommended to always check that volume is ready and valid.
+ The following example shows how to get the volume on which the application is
+ located. It is recommended to always check that the volume is ready and valid.
\snippet code/src_corelib_io_qstorageinfo.cpp 0
@@ -104,8 +105,8 @@ QStorageInfo::QStorageInfo(const QString &path)
}
/*!
- Constructs a new QStorageInfo that gives information about the volume
- that contains the \a dir folder.
+ Constructs a new QStorageInfo object that gives information about the volume
+ containing the \a dir folder.
*/
QStorageInfo::QStorageInfo(const QDir &dir)
: d(new QStorageInfoPrivate)
@@ -114,7 +115,7 @@ QStorageInfo::QStorageInfo(const QDir &dir)
}
/*!
- Constructs a new QStorageInfo that is a copy of the \a other QStorageInfo.
+ Constructs a new QStorageInfo object that is a copy of the \a other QStorageInfo object.
*/
QStorageInfo::QStorageInfo(const QStorageInfo &other)
: d(other.d)
@@ -122,14 +123,14 @@ QStorageInfo::QStorageInfo(const QStorageInfo &other)
}
/*!
- Destroys the QStorageInfo and frees its resources.
+ Destroys the QStorageInfo object and frees its resources.
*/
QStorageInfo::~QStorageInfo()
{
}
/*!
- Makes a copy of \a other QStorageInfo and assigns it to this QStorageInfo.
+ Makes a copy of the QStorageInfo object \a other and assigns it to this QStorageInfo object.
*/
QStorageInfo &QStorageInfo::operator=(const QStorageInfo &other)
{
@@ -140,20 +141,20 @@ QStorageInfo &QStorageInfo::operator=(const QStorageInfo &other)
/*!
\fn QStorageInfo &QStorageInfo::operator=(QStorageInfo &&other)
- Move-assigns \a other to this QStorageInfo instance.
+ Assigns \a other to this QStorageInfo instance.
*/
/*!
\fn void QStorageInfo::swap(QStorageInfo &other)
- Swaps this volume info with the \a other. This function is very fast and
+ Swaps this volume info with \a other. This function is very fast and
never fails.
*/
/*!
- Sets QStorageInfo to the filesystem mounted where \a path is located.
+ Sets this QStorageInfo object to the filesystem mounted where \a path is located.
- Path can either be a root path of the filesystem, or a directory or a file
+ \a path can either be a root path of the filesystem, a directory, or a file
within that filesystem.
\sa rootPath()
@@ -171,12 +172,12 @@ void QStorageInfo::setPath(const QString &path)
Returns the mount point of the filesystem this QStorageInfo object
represents.
- On Windows, returns the volume letter in case the volume is not mounted to
+ On Windows, it returns the volume letter in case the volume is not mounted to
a directory.
Note that the value returned by rootPath() is the real mount point of a
- volume and may not be equal to the value passed to constructor or setPath()
- method. For example, if you have only the root volume in the system and
+ volume, and may not be equal to the value passed to the constructor or setPath()
+ method. For example, if you have only the root volume in the system, and
pass '/directory' to setPath(), then this method will return '/'.
\sa setPath(), device()
@@ -187,10 +188,10 @@ QString QStorageInfo::rootPath() const
}
/*!
- Returns the size (in bytes) available for the current user. If the user is
- the root user or a system administrator returns all available size.
+ Returns the size (in bytes) available for the current user. It returns
+ the total size available if the user is the root user or a system administrator.
- This size can be less than or equal to the free size, returned by
+ This size can be less than or equal to the free size returned by
bytesFree() function.
\sa bytesTotal(), bytesFree()
@@ -201,9 +202,9 @@ qint64 QStorageInfo::bytesAvailable() const
}
/*!
- Returns the number of free bytes on a volume. Note, that if there are some
- kind of quotas on the filesystem, this value can be bigger than
- bytesAvailable().
+ Returns the number of free bytes in a volume. Note that if there are
+ quotas on the filesystem, this value can be larger than the value
+ returned by bytesAvailable().
\sa bytesTotal(), bytesAvailable()
*/
@@ -213,7 +214,7 @@ qint64 QStorageInfo::bytesFree() const
}
/*!
- Returns total volume size in bytes.
+ Returns the total volume size in bytes.
\sa bytesFree(), bytesAvailable()
*/
@@ -227,7 +228,7 @@ qint64 QStorageInfo::bytesTotal() const
This is a platform-dependent function, and filesystem names can vary
between different operating systems. For example, on Windows filesystems
- can be named as 'NTFS' and on Linux as 'ntfs-3g' or 'fuseblk'.
+ they can be named \c NTFS, and on Linux they can be named \c ntfs-3g or \c fuseblk.
\sa name()
*/
@@ -240,8 +241,8 @@ QByteArray QStorageInfo::fileSystemType() const
Returns the device for this volume.
For example, on Unix filesystems (including OS X), this returns the
- devpath like '/dev/sda0' for local storages. On Windows, returns the UNC
- path starting with \\\\?\\ for local storages (i.e. volume GUID).
+ devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
+ path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
\sa rootPath()
*/
@@ -251,13 +252,13 @@ QByteArray QStorageInfo::device() const
}
/*!
- Returns the human-readable name of a filesystem, usually called 'label'.
+ Returns the human-readable name of a filesystem, usually called \c label.
- Not all filesystems support this feature, in this case value returned by
+ Not all filesystems support this feature. In this case, the value returned by
this method could be empty. An empty string is returned if the file system
- does not support labels or no label is set.
+ does not support labels, or if no label is set.
- On Linux, retrieving the volume's label requires udev to be present in the
+ On Linux, retrieving the volume's label requires \c udev to be present in the
system.
\sa fileSystemType()
@@ -283,8 +284,8 @@ QString QStorageInfo::displayName() const
Returns true if this QStorageInfo represents the system root volume; false
otherwise.
- On Unix filesystems, the root volume is a volume mounted at "/", on Windows
- the root volume is the volume where OS is installed.
+ On Unix filesystems, the root volume is a volume mounted on \c /. On Windows,
+ the root volume is the volume where the OS is installed.
\sa root()
*/
@@ -299,8 +300,8 @@ bool QStorageInfo::isReadOnly() const
}
/*!
- Returns true if current filesystem is ready to work; false otherwise. For
- example, false is returned if CD volume is not inserted.
+ Returns true if the current filesystem is ready to work; false otherwise. For
+ example, false is returned if the CD volume is not inserted.
Note that fileSystemType(), name(), bytesTotal(), bytesFree(), and
bytesAvailable() will return invalid data until the volume is ready.
@@ -326,9 +327,9 @@ bool QStorageInfo::isValid() const
/*!
Resets QStorageInfo's internal cache.
- QStorageInfo caches information about storages to speed up performance -
- QStorageInfo retrieves information during object construction and/or call
- to setPath() method. You have to manually reset the cache by calling this
+ QStorageInfo caches information about storage to speed up performance.
+ QStorageInfo retrieves information during object construction and/or when calling
+ the setPath() method. You have to manually reset the cache by calling this
function to update storage information.
*/
void QStorageInfo::refresh()
@@ -338,17 +339,16 @@ void QStorageInfo::refresh()
}
/*!
- Returns list of QStorageInfos that corresponds to the list of currently
+ Returns the list of QStorageInfo objects that corresponds to the list of currently
mounted filesystems.
- On Windows, this returns drives presented in 'My Computer' folder. On Unix
- operating systems, returns list of all mounted filesystems (except for
+ On Windows, this returns the drives visible in the \gui{My Computer} folder. On Unix
+ operating systems, it returns the list of all mounted filesystems (except for
pseudo filesystems).
- By default, returns all currently mounted filesystems.
+ Returns all currently mounted filesystems by default.
- The example shows how to retrieve all storages present in the system and
- skip read-only storages.
+ The example shows how to retrieve all available filesystems, skipping read-only ones.
\snippet code/src_corelib_io_qstorageinfo.cpp 1
@@ -364,8 +364,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QStorageInfo, getRoot, (QStorageInfoPrivate::root()))
/*!
Returns a QStorageInfo object that represents the system root volume.
- On Unix systems this call returns '/' volume, on Windows the volume where
- operating system is installed is returned.
+ On Unix systems this call returns the root ('/') volume; in Windows the volume where
+ the operating system is installed.
\sa isRoot()
*/
@@ -379,8 +379,8 @@ QStorageInfo QStorageInfo::root()
\relates QStorageInfo
- Returns true if \a first QStorageInfo object refers to the same drive or volume
- as the \a second; otherwise returns false.
+ Returns true if the \a first QStorageInfo object refers to the same drive or volume
+ as the \a second; otherwise it returns false.
Note that the result of comparing two invalid QStorageInfo objects is always
positive.
@@ -391,8 +391,8 @@ QStorageInfo QStorageInfo::root()
\relates QStorageInfo
- Returns true if \a first QStorageInfo object refers to a different drive or
- volume than the one specified by \a second; otherwise returns false.
+ Returns true if the \a first QStorageInfo object refers to a different drive or
+ volume than the \a second; otherwise returns false.
*/
QT_END_NAMESPACE
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp
index c1e831192a..6f3a960f05 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/json/qjsonarray.cpp
@@ -746,6 +746,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
from which you got the reference.
*/
+/*! \fn QJsonValueRef *QJsonArray::iterator::operator->() const
+
+ Returns a pointer to a modifiable reference to the current item.
+*/
+
/*! \fn QJsonValueRef QJsonArray::iterator::operator[](int j) const
Returns a modifiable reference to the item at offset \a j from the
@@ -971,6 +976,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
Returns the current item.
*/
+/*! \fn QJsonValue *QJsonArray::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+*/
+
/*! \fn QJsonValue QJsonArray::const_iterator::operator[](int j) const
Returns the item at offset \a j from the item pointed to by this iterator (the item at
diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h
index 4cada7cec1..f3efa3d201 100644
--- a/src/corelib/json/qjsonarray.h
+++ b/src/corelib/json/qjsonarray.h
@@ -112,14 +112,17 @@ public:
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
typedef QJsonValue value_type;
- //typedef T *pointer;
typedef QJsonValueRef reference;
inline iterator() : a(0), i(0) { }
explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { }
inline QJsonValueRef operator*() const { return QJsonValueRef(a, i); }
- //inline T *operator->() const { return &concrete(i)->value; }
+#ifdef Q_QDOC
+ inline QJsonValueRef* operator->() const;
+#else
+ inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(a, i); }
+#endif
inline QJsonValueRef operator[](int j) const { return QJsonValueRef(a, i + j); }
inline bool operator==(const iterator &o) const { return i == o.i; }
@@ -153,7 +156,6 @@ public:
typedef std::random_access_iterator_tag iterator_category;
typedef qptrdiff difference_type;
typedef QJsonValue value_type;
- //typedef const T *pointer;
typedef QJsonValue reference;
inline const_iterator() : a(0), i(0) { }
@@ -162,7 +164,11 @@ public:
inline const_iterator(const iterator &o) : a(o.a), i(o.i) {}
inline QJsonValue operator*() const { return a->at(i); }
- //inline T *operator->() const { return &concrete(i)->value; }
+#ifdef Q_QDOC
+ inline QJsonValue* operator->() const;
+#else
+ inline QJsonValuePtr operator->() const { return QJsonValuePtr(a->at(i)); }
+#endif
inline QJsonValue operator[](int j) const { return a->at(i+j); }
inline bool operator==(const const_iterator &o) const { return i == o.i; }
inline bool operator!=(const const_iterator &o) const { return i != o.i; }
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index cfd797990f..b393701411 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -710,6 +710,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\sa key()
*/
+/*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const
+
+ Returns a pointer to a modifiable reference to the current item.
+*/
+
/*!
\fn bool QJsonObject::iterator::operator==(const iterator &other) const
\fn bool QJsonObject::iterator::operator==(const const_iterator &other) const
@@ -893,6 +898,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\sa key()
*/
+/*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const
+
+ Returns a pointer to the current item.
+*/
+
/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const
\fn bool QJsonObject::const_iterator::operator==(const iterator &other) const
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h
index 92dd19af5e..7973b8ab92 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/json/qjsonobject.h
@@ -107,7 +107,6 @@ public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef int difference_type;
typedef QJsonValue value_type;
-// typedef T *pointer;
typedef QJsonValueRef reference;
Q_DECL_CONSTEXPR inline iterator() : o(0), i(0) {}
@@ -116,7 +115,11 @@ public:
inline QString key() const { return o->keyAt(i); }
inline QJsonValueRef value() const { return QJsonValueRef(o, i); }
inline QJsonValueRef operator*() const { return QJsonValueRef(o, i); }
- //inline T *operator->() const { return &concrete(i)->value; }
+#ifdef Q_QDOC
+ inline QJsonValueRef* operator->() const;
+#else
+ inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(o, i); }
+#endif
inline bool operator==(const iterator &other) const { return i == other.i; }
inline bool operator!=(const iterator &other) const { return i != other.i; }
@@ -157,7 +160,11 @@ public:
inline QString key() const { return o->keyAt(i); }
inline QJsonValue value() const { return o->valueAt(i); }
inline QJsonValue operator*() const { return o->valueAt(i); }
- //inline const T *operator->() const { return &concrete(i)->value; }
+#ifdef Q_QDOC
+ inline QJsonValue* operator->() const;
+#else
+ inline QJsonValuePtr operator->() const { return QJsonValuePtr(o->valueAt(i)); }
+#endif
inline bool operator==(const const_iterator &other) const { return i == other.i; }
inline bool operator!=(const const_iterator &other) const { return i != other.i; }
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h
index a00bc0b72f..2d0453f130 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/json/qjsonvalue.h
@@ -192,6 +192,33 @@ private:
struct UnionHelper;
};
+#ifndef Q_QDOC
+// ### Qt 6: Get rid of these fake pointer classes
+class QJsonValuePtr
+{
+ QJsonValue value;
+public:
+ explicit QJsonValuePtr(const QJsonValue& val)
+ : value(val) {}
+
+ QJsonValue& operator*() { return value; }
+ QJsonValue* operator->() { return &value; }
+};
+
+class QJsonValueRefPtr
+{
+ QJsonValueRef valueRef;
+public:
+ QJsonValueRefPtr(QJsonArray *array, int idx)
+ : valueRef(array, idx) {}
+ QJsonValueRefPtr(QJsonObject *object, int idx)
+ : valueRef(object, idx) {}
+
+ QJsonValueRef& operator*() { return valueRef; }
+ QJsonValueRef* operator->() { return &valueRef; }
+};
+#endif
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 8d5a39115a..bc54a2ae74 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -184,6 +184,7 @@ QT_BEGIN_NAMESPACE
\value MouseMove Mouse move (QMouseEvent).
\value MouseTrackingChange The mouse tracking state has changed.
\value Move Widget's position changed (QMoveEvent).
+ \value NativeGesture The system has detected a gesture (QNativeGestureEvent).
\value OrientationChange The screens orientation has changes (QScreenOrientationChangeEvent)
\value Paint Screen update necessary (QPaintEvent).
\value PaletteChange Palette of the widget changed.
diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h
index 5f051c3ea6..b585d3c352 100644
--- a/src/corelib/kernel/qfunctions_winrt.h
+++ b/src/corelib/kernel/qfunctions_winrt.h
@@ -44,7 +44,7 @@
#include
-#ifdef Q_OS_WINRT
+#ifdef Q_OS_WIN
#include
#include
@@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
+#ifdef Q_OS_WINRT
+
// Environment ------------------------------------------------------
errno_t qt_winrt_getenv_s(size_t*, char*, size_t, const char*);
errno_t qt_winrt__putenv_s(const char*, const char*);
@@ -122,6 +124,8 @@ generate_inline_return_func2(_putenv_s, errno_t, const char *, const char *)
generate_inline_return_func0(tzset, void)
generate_inline_return_func0(_tzset, void)
+#endif // Q_OS_WINRT
+
// Convenience macros for handling HRESULT values
#define RETURN_IF_FAILED(msg, ret) \
if (FAILED(hr)) { \
@@ -211,5 +215,6 @@ static inline HRESULT await(const Microsoft::WRL::ComPtr &asyncOp, U *results
} // QWinRTFunctions
-#endif // Q_OS_WINRT
+#endif // Q_OS_WIN
+
#endif // QFUNCTIONS_WINRT_H
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp
index aa9b196e62..4581b70ca7 100644
--- a/src/corelib/kernel/qjni.cpp
+++ b/src/corelib/kernel/qjni.cpp
@@ -721,7 +721,7 @@ jboolean QJNIObjectPrivate::callStaticMethod(jclass clazz,
{
va_list args;
va_start(args, sig);
- jboolean res = callStaticMethod(clazz, methodName, sig);
+ jboolean res = callStaticMethod(clazz, methodName, sig, args);
va_end(args);
return res;
}
@@ -1026,7 +1026,7 @@ jlong QJNIObjectPrivate::callStaticMethod(jclass clazz,
{
va_list args;
va_start(args, sig);
- jlong res = callStaticMethod(clazz, methodName, sig);
+ jlong res = callStaticMethod(clazz, methodName, sig, args);
va_end(args);
return res;
}
@@ -1119,7 +1119,7 @@ jdouble QJNIObjectPrivate::callStaticMethod(const char *className,
{
va_list args;
va_start(args, sig);
- jdouble res = callStaticMethod(className, methodName, sig);
+ jdouble res = callStaticMethod(className, methodName, sig, args);
va_end(args);
return res;
}
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 9980e0d901..0647513221 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -65,6 +65,7 @@
# include "qjsonobject.h"
# include "qjsonarray.h"
# include "qjsondocument.h"
+# include "qbytearraylist.h"
#endif
#ifndef QT_NO_GEOM_VARIANT
@@ -270,6 +271,7 @@ struct DefinedTypesFilter {
\value QJsonDocument QJsonDocument
\value QModelIndex QModelIndex
\value QUuid QUuid
+ \value QByteArrayList QByteArrayList
\value User Base value for user types
\value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
@@ -1191,6 +1193,9 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::QVariant:
stream << *static_cast(data);
break;
+ case QMetaType::QByteArrayList:
+ stream << *static_cast(data);
+ break;
#endif
case QMetaType::QByteArray:
stream << *static_cast(data);
@@ -1414,6 +1419,9 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::QVariant:
stream >> *static_cast< NS(QVariant)*>(data);
break;
+ case QMetaType::QByteArrayList:
+ stream >> *static_cast< NS(QByteArrayList)*>(data);
+ break;
#endif
case QMetaType::QByteArray:
stream >> *static_cast< NS(QByteArray)*>(data);
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 1aa89a03b3..7570a6fb20 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -127,6 +127,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QVariantMap, 8, QVariantMap) \
F(QVariantList, 9, QVariantList) \
F(QVariantHash, 28, QVariantHash) \
+ F(QByteArrayList, 49, QByteArrayList) \
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
F(QFont, 64, QFont) \
@@ -180,6 +181,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QVariantList, -1, QVariantList, "QList") \
F(QVariantMap, -1, QVariantMap, "QMap") \
F(QVariantHash, -1, QVariantHash, "QHash") \
+ F(QByteArrayList, -1, QByteArrayList, "QList") \
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -393,7 +395,7 @@ public:
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = QJsonDocument,
+ LastCoreType = QByteArrayList,
FirstGuiType = QFont,
LastGuiType = QPolygonF,
FirstWidgetsType = QSizePolicy,
@@ -419,7 +421,7 @@ public:
QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
QRegularExpression = 44,
QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
- QObjectStar = 39, SChar = 40,
+ QByteArrayList = 49, QObjectStar = 39, SChar = 40,
Void = 43,
QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
@@ -1763,6 +1765,7 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
typedef QList QVariantList;
typedef QMap QVariantMap;
typedef QHash QVariantHash;
+typedef QList QByteArrayList;
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
QT_BEGIN_NAMESPACE \
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index 95b9e2e394..48cb6d6fcc 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -207,6 +207,7 @@ template<> struct TypeDefinition { static const bool IsAvailable =
template<> struct TypeDefinition { static const bool IsAvailable = false; };
template<> struct TypeDefinition { static const bool IsAvailable = false; };
template<> struct TypeDefinition { static const bool IsAvailable = false; };
+template<> struct TypeDefinition { static const bool IsAvailable = false; };
#endif
#ifdef QT_NO_GEOM_VARIANT
template<> struct TypeDefinition { static const bool IsAvailable = false; };
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index db2b086ff2..45bf4b62c5 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -4749,10 +4749,14 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
int signal_index = -1;
if (signal) {
void *args[] = { &signal_index, signal };
- senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
- if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
- qWarning("QObject::disconnect: signal not found in %s", senderMetaObject->className());
- return false;
+ for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
+ senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
+ if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
+ break;
+ }
+ if (!senderMetaObject) {
+ qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className());
+ return QMetaObject::Connection(0);
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
}
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 5e8f330a92..29734f902e 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -61,6 +61,7 @@
#include "qjsonobject.h"
#include "qjsonarray.h"
#include "qjsondocument.h"
+#include "qbytearraylist.h"
#endif
#include "private/qvariant_p.h"
#include "qmetatype_p.h"
@@ -2841,6 +2842,7 @@ bool QVariant::canConvert(int targetTypeId) const
if (targetTypeId == QMetaType::QVariantList
&& (d.type == QMetaType::QVariantList
|| d.type == QMetaType::QStringList
+ || d.type == QMetaType::QByteArrayList
|| QMetaType::hasRegisteredConverterFunction(d.type,
qMetaTypeId()))) {
return true;
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 5ff33cce5f..e141817993 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -51,6 +51,9 @@
#include
#include
#include
+#ifndef QT_BOOTSTRAPPED
+#include
+#endif
QT_BEGIN_NAMESPACE
@@ -713,6 +716,11 @@ namespace QtPrivate {
if (v.userType() == qMetaTypeId()) {
return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData())));
}
+#ifndef QT_BOOTSTRAPPED
+ if (v.userType() == qMetaTypeId()) {
+ return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData())));
+ }
+#endif
return QSequentialIterable(v.value());
}
};
@@ -735,7 +743,7 @@ namespace QtPrivate {
{
static QVariantList invoke(const QVariant &v)
{
- if (v.userType() == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) {
+ if (v.userType() == qMetaTypeId() || v.userType() == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) {
QSequentialIterable iter = QVariantValueHelperInterface::invoke(v);
QVariantList l;
l.reserve(iter.size());
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index a147b85eb7..0e6fad48df 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -526,10 +526,6 @@ QList QStateMachinePrivate::computeStatesToEnter(const QList lcac = QStatePrivate::get(lca)->childStates();
foreach (QAbstractState* child,lcac) {
@@ -727,6 +723,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
return;
}
}
+ addAncestorStatesToEnter(s, root, statesToEnter, statesForDefaultEntry);
}
}
@@ -1095,7 +1092,6 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta
if (currentErrorState != 0) {
QState *lca = findLCA(QList() << currentErrorState << currentContext);
addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
- addAncestorStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
} else {
qWarning("Unrecoverable error detected in running state machine: %s",
qPrintable(errorString));
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 6e0634ac3b..b927bf1ead 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -774,10 +774,10 @@ Q_OUTOFLINE_TEMPLATE QList::~QList()
template
Q_OUTOFLINE_TEMPLATE bool QList::operator==(const QList &l) const
{
- if (p.size() != l.p.size())
- return false;
if (d == l.d)
return true;
+ if (p.size() != l.p.size())
+ return false;
Node *i = reinterpret_cast(p.end());
Node *b = reinterpret_cast(p.begin());
Node *li = reinterpret_cast(l.p.end());
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 5454a8fe4d..e7bad15b5d 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -7929,6 +7929,11 @@ QString &QString::setRawData(const QChar *unicode, int size)
Returns the Latin-1 string stored in this object.
*/
+/*! \fn const char *QLatin1String::data() const
+
+ Returns the Latin-1 string stored in this object.
+*/
+
/*! \fn int QLatin1String::size() const
Returns the size of the Latin-1 string stored in this object.
@@ -7959,6 +7964,20 @@ QString &QString::setRawData(const QChar *unicode, int size)
go through QObject::tr(), for example.
*/
+/*!
+ \fn bool QLatin1String::operator==(const QByteArray &other) const
+ \since 5.0
+ \overload
+
+ The \a other byte array is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
/*! \fn bool QLatin1String::operator!=(const QString &other) const
Returns \c true if this string is not equal to string \a other;
@@ -7984,6 +8003,20 @@ QString &QString::setRawData(const QChar *unicode, int size)
go through QObject::tr(), for example.
*/
+/*!
+ \fn bool QLatin1String::operator!=(const QByteArray &other) const
+ \since 5.0
+ \overload operator!=()
+
+ The \a other byte array is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
/*!
\fn bool QLatin1String::operator>(const QString &other) const
@@ -8010,6 +8043,20 @@ QString &QString::setRawData(const QChar *unicode, int size)
for example.
*/
+/*!
+ \fn bool QLatin1String::operator>(const QByteArray &other) const
+ \since 5.0
+ \overload
+
+ The \a other const char pointer is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII
+ when you compile your applications. This can be useful if you want
+ to ensure that all user-visible strings go through QObject::tr(),
+ for example.
+*/
+
/*!
\fn bool QLatin1String::operator<(const QString &other) const
@@ -8036,6 +8083,20 @@ QString &QString::setRawData(const QChar *unicode, int size)
go through QObject::tr(), for example.
*/
+/*!
+ \fn bool QLatin1String::operator<(const QByteArray &other) const
+ \since 5.0
+ \overload
+
+ The \a other const char pointer is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
/*!
\fn bool QLatin1String::operator>=(const QString &other) const
@@ -8062,6 +8123,20 @@ QString &QString::setRawData(const QChar *unicode, int size)
go through QObject::tr(), for example.
*/
+/*!
+ \fn bool QLatin1String::operator>=(const QByteArray &other) const
+ \since 5.0
+ \overload
+
+ The \a other array is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
+
/*! \fn bool QLatin1String::operator<=(const QString &other) const
Returns \c true if this string is lexically less than or equal
@@ -8087,6 +8162,19 @@ QString &QString::setRawData(const QChar *unicode, int size)
go through QObject::tr(), for example.
*/
+/*!
+ \fn bool QLatin1String::operator<=(const QByteArray &other) const
+ \since 5.0
+ \overload
+
+ The \a other array is converted to a QString using
+ the QString::fromUtf8() function.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. This
+ can be useful if you want to ensure that all user-visible strings
+ go through QObject::tr(), for example.
+*/
/*! \fn bool operator==(QLatin1String s1, QLatin1String s2)
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index f09f1a3c41..cb4e193ffc 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -256,7 +256,7 @@ public:
static inline QVector fromStdVector(const std::vector &vector)
{ QVector tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
inline std::vector toStdVector() const
- { std::vector tmp; tmp.reserve(size()); std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+ { return std::vector(d->begin(), d->end()); }
private:
friend class QRegion; // Optimization for QRegion::rects()
@@ -711,10 +711,10 @@ typename QVector::iterator QVector::erase(iterator abegin, iterator aend)
template
bool QVector::operator==(const QVector &v) const
{
- if (d->size != v.d->size)
- return false;
if (d == v.d)
return true;
+ if (d->size != v.d->size)
+ return false;
T* b = d->begin();
T* i = b + d->size;
T* j = v.d->end();
@@ -810,7 +810,9 @@ bool QVector::contains(const T &t) const
template
int QVector::count(const T &t) const
{
- return int(std::count(cbegin(), cend(), t));
+ const T *b = d->begin();
+ const T *e = d->end();
+ return int(std::count(b, e, t));
}
template
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index ac95222c99..1e4a9ebe8c 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -989,10 +989,16 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
QImageWriter::supportedImageFormats() functions to retrieve a
complete list of the supported file formats.
- Note: When you add a non-empty filename to a QIcon, the icon becomes
+ If a high resolution version of the image exists (identified by
+ the suffix \c @2x on the base name), it is automatically loaded
+ and added with the \e{device pixel ratio} set to a value of 2.
+ This can be disabled by setting the environment variable
+ \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING (see QImageReader).
+
+ \note When you add a non-empty filename to a QIcon, the icon becomes
non-null, even if the file doesn't exist or points to a corrupt file.
- \sa addPixmap()
+ \sa addPixmap(), QPixmap::devicePixelRatio()
*/
void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state)
{
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 9e979023cd..12d9f9f14d 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -176,7 +176,6 @@ QIconTheme::QIconTheme(const QString &themeName)
{
QFile themeIndex;
- QList keyList;
QStringList iconDirs = QIcon::themeSearchPaths();
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
@@ -269,7 +268,7 @@ QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
}
QString contentDir = theme.contentDir() + QLatin1Char('/');
- QList subDirs = theme.keyList();
+ const QVector subDirs = theme.keyList();
const QString svgext(QLatin1String(".svg"));
const QString pngext(QLatin1String(".png"));
@@ -333,9 +332,7 @@ QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
QIconLoaderEngine::~QIconLoaderEngine()
{
- while (!m_entries.isEmpty())
- delete m_entries.takeLast();
- Q_ASSERT(m_entries.size() == 0);
+ qDeleteAll(m_entries);
}
QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
@@ -371,10 +368,8 @@ void QIconLoaderEngine::ensureLoaded()
{
if (!(QIconLoader::instance()->themeKey() == m_key)) {
- while (!m_entries.isEmpty())
- delete m_entries.takeLast();
+ qDeleteAll(m_entries);
- Q_ASSERT(m_entries.size() == 0);
m_entries = QIconLoader::instance()->loadIcon(m_iconName);
m_key = QIconLoader::instance()->themeKey();
}
@@ -448,8 +443,10 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
// Note that m_entries are sorted so that png-files
// come first
+ const int numEntries = m_entries.size();
+
// Search for exact matches first
- for (int i = 0; i < m_entries.count(); ++i) {
+ for (int i = 0; i < numEntries; ++i) {
QIconLoaderEngineEntry *entry = m_entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize)) {
return entry;
@@ -459,7 +456,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
// Find the minimum distance icon
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
- for (int i = 0; i < m_entries.count(); ++i) {
+ for (int i = 0; i < numEntries; ++i) {
QIconLoaderEngineEntry *entry = m_entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize);
if (distance < minimalSize) {
@@ -564,11 +561,12 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
{
QIconEngine::AvailableSizesArgument &arg
= *reinterpret_cast(data);
- const QList directoryKey = QIconLoader::instance()->theme().keyList();
arg.sizes.clear();
+ const int N = m_entries.size();
+ arg.sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
- for (int i = 0 ; i < m_entries.size() ; ++i) {
+ for (int i = 0; i < N; ++i) {
int size = m_entries.at(i)->dir.size;
arg.sizes.append(QSize(size, size));
}
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 419d93d576..2495ff4d50 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -62,6 +62,8 @@
#include
#include
#include
+#include
+#include
QT_BEGIN_NAMESPACE
@@ -84,6 +86,7 @@ struct QIconDirInfo
short threshold;
Type type : 4;
};
+Q_DECLARE_TYPEINFO(QIconDirInfo, Q_MOVABLE_TYPE);
class QIconLoaderEngineEntry
{
@@ -99,13 +102,13 @@ public:
struct ScalableEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
QIcon svgIcon;
};
struct PixmapEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
QPixmap basePixmap;
};
@@ -144,18 +147,18 @@ public:
QIconTheme(const QString &name);
QIconTheme() : m_valid(false) {}
QStringList parents() { return m_parents; }
- QList keyList() { return m_keyList; }
+ QVector keyList() { return m_keyList; }
QString contentDir() { return m_contentDir; }
bool isValid() { return m_valid; }
private:
QString m_contentDir;
- QList m_keyList;
+ QVector m_keyList;
QStringList m_parents;
bool m_valid;
};
-class Q_GUI_EXPORT QIconLoader : public QObject
+class Q_GUI_EXPORT QIconLoader
{
public:
QIconLoader();
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 16696f611d..c3b4b1444a 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1391,14 +1391,14 @@ QVector QImage::colorTable() const
/*!
Returns the device pixel ratio for the image. This is the
- ratio between image pixels and device-independent pixels.
+ ratio between \e{device pixels} and \e{device independent pixels}.
Use this function when calculating layout geometry based on
the image size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
- \sa setDevicePixelRatio()
+ \sa setDevicePixelRatio(), QImageReader
*/
qreal QImage::devicePixelRatio() const
{
@@ -1423,7 +1423,8 @@ qreal QImage::devicePixelRatio() const
image size will take the ratio into account:
QSize layoutSize = image.size() / image.devicePixelRatio()
The net effect of this is that the image is displayed as
- high-dpi image rather than a large image.
+ high-DPI image rather than a large image
+ (see \l{Drawing High Resolution Versions of Pixmaps and Images}).
\sa devicePixelRatio()
*/
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index a281349aa9..3bf002373c 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -74,17 +74,32 @@
that occurred, or errorString() to get a human readable
description of what went wrong.
+ \section1 Formats
+
Call supportedImageFormats() for a list of formats that
QImageReader can read. QImageReader supports all built-in image
formats, in addition to any image format plugins that support
- reading.
+ reading. Call supportedMimeTypes() to obtain a list of supported MIME
+ types, which for example can be passed to QFileDialog::setMimeTypeFilters().
QImageReader autodetects the image format by default, by looking at the
provided (optional) format string, the file name suffix, and the data
stream contents. You can enable or disable this feature, by calling
setAutoDetectImageFormat().
- \sa QImageWriter, QImageIOHandler, QImageIOPlugin
+ \section1 High Resolution Versions of Images
+
+ It is possible to provide high resolution versions of images should a scaling
+ between \e{device pixels} and \e{device independent pixels} be in effect.
+
+ The high resolution version is marked by the suffix \c @2x on the base name.
+ The image read will have its \e{device pixel ratio} set to a value of 2.
+
+ This can be disabled by setting the environment variable
+ \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING.
+
+ \sa QImageWriter, QImageIOHandler, QImageIOPlugin, QMimeDatabase
+ \sa QImage::devicePixelRatio(), QPixmap::devicePixelRatio(), QIcon, QPainter::drawPixmap(), QPainter::drawImage(), Qt::AA_UseHighDpiPixmaps
*/
/*!
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 2d41ca7e24..88ce48f0e8 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -648,14 +648,14 @@ void QPixmap::setMask(const QBitmap &mask)
/*!
Returns the device pixel ratio for the pixmap. This is the
- ratio between pixmap pixels and device-independent pixels.
+ ratio between \e{device pixels} and \e{device independent pixels}.
Use this function when calculating layout geometry based on
the pixmap size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
- \sa setDevicePixelRatio()
+ \sa setDevicePixelRatio(), QImageReader
*/
qreal QPixmap::devicePixelRatio() const
{
@@ -680,7 +680,8 @@ qreal QPixmap::devicePixelRatio() const
pixmap size will take the ratio into account:
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio()
The net effect of this is that the pixmap is displayed as
- high-dpi pixmap rather than a large pixmap.
+ high-DPI pixmap rather than a large pixmap
+ (see \l{Drawing High Resolution Versions of Pixmaps and Images}).
\sa devicePixelRatio()
*/
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 5edb866b62..ca87951dbb 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1094,7 +1094,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
return false;
QImage image;
- if (sourceImage.format() != QImage::Format_RGB32 || sourceImage.format() != QImage::Format_ARGB32 || sourceImage.format() != QImage::Format_ARGB32_Premultiplied)
+ if (sourceImage.format() != QImage::Format_RGB32 && sourceImage.format() != QImage::Format_ARGB32 && sourceImage.format() != QImage::Format_ARGB32_Premultiplied)
image = sourceImage.convertToFormat(QImage::Format_RGB32);
else
image = sourceImage;
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index c2422ec98b..1169985ea8 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -66,7 +66,6 @@ HEADERS += \
kernel/qplatformsharedgraphicscache.h \
kernel/qplatformdialoghelper.h \
kernel/qplatformservices.h \
- kernel/qplatformscreenpageflipper.h \
kernel/qplatformsystemtrayicon.h \
kernel/qplatformsessionmanager.h \
kernel/qpixelformat.h \
@@ -120,7 +119,6 @@ SOURCES += \
kernel/qplatformsharedgraphicscache.cpp \
kernel/qplatformdialoghelper.cpp \
kernel/qplatformservices.cpp \
- kernel/qplatformscreenpageflipper.cpp \
kernel/qplatformsystemtrayicon.cpp \
kernel/qplatformsessionmanager.cpp \
kernel/qplatformmenu.cpp \
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 1b853411f8..958df48f17 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3495,11 +3495,13 @@ static const char *eventClassName(QEvent::Type t)
return "QCloseEvent";
case QEvent::FileOpen:
return "QFileOpenEvent";
+#ifndef QT_NO_GESTURES
case QEvent::NativeGesture:
return "QNativeGestureEvent";
case QEvent::Gesture:
case QEvent::GestureOverride:
return "QGestureEvent";
+#endif
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
@@ -3595,6 +3597,14 @@ public:
static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("FocusReason");
return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(reason);
}
+
+# ifndef QT_NO_GESTURES
+ static const char *nativeGestureTypeToString(Qt::NativeGestureType type)
+ {
+ static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("NativeGestureType");
+ return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(type);
+ }
+# endif // !QT_NO_GESTURES
};
} // namespace
@@ -3775,7 +3785,8 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
# ifndef QT_NO_GESTURES
case QEvent::NativeGesture: {
const QNativeGestureEvent *ne = static_cast(e);
- dbg << "QNativeGestureEvent(localPos=" << ne->localPos() << ", value=" << ne->value() << ')';
+ dbg << "QNativeGestureEvent(" << DebugHelper::nativeGestureTypeToString(ne->gestureType())
+ << "localPos=" << ne->localPos() << ", value=" << ne->value() << ')';
}
break;
# endif // !QT_NO_GESTURES
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 71a1d1e074..6b2bb092b1 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -639,6 +639,7 @@ bool QOpenGLContext::create()
*/
void QOpenGLContext::destroy()
{
+ deleteQGLContext();
Q_D(QOpenGLContext);
if (d->platformGLContext)
emit aboutToBeDestroyed();
@@ -1086,6 +1087,9 @@ void *QOpenGLContext::qGLContextHandle() const
}
/*!
+ internal: If the delete function is specified QOpenGLContext "owns"
+ the passed context handle and will use the delete function to destroy it.
+
\internal
*/
void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 46e1572376..2d27b19ebe 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -198,6 +198,7 @@ class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate
public:
QOpenGLContextPrivate()
: qGLContextHandle(0)
+ , qGLContextDeleteFunction(0)
, platformGLContext(0)
, shareContext(0)
, shareGroup(0)
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 05d04ae4ee..0c47005807 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -274,15 +274,6 @@ QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window
Reimplement in subclass to return the image format which corresponds to the screen format
*/
-/*!
- Implemented in subclasses to return a page flipper object for the screen, or 0 if the
- hardware does not support page flipping. The default implementation returns 0.
- */
-QPlatformScreenPageFlipper *QPlatformScreen::pageFlipper() const
-{
- return 0;
-}
-
/*!
Reimplement this function in subclass to return the cursor of the screen.
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index 085a147e8d..151a6386d9 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -71,7 +71,6 @@ class QPlatformOpenGLContext;
class QPlatformScreenPrivate;
class QPlatformWindow;
class QPlatformCursor;
-class QPlatformScreenPageFlipper;
class QScreen;
class QSurfaceFormat;
@@ -115,7 +114,6 @@ public:
virtual QString name() const { return QString(); }
- virtual QPlatformScreenPageFlipper *pageFlipper() const;
virtual QPlatformCursor *cursor() const;
protected:
diff --git a/src/gui/kernel/qplatformscreenpageflipper.cpp b/src/gui/kernel/qplatformscreenpageflipper.cpp
deleted file mode 100644
index 8665adc463..0000000000
--- a/src/gui/kernel/qplatformscreenpageflipper.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformscreenpageflipper.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QPlatformScreenBuffer
- \since 5.0
- \internal
- \preliminary
- \ingroup qpa
-
- \brief The QPlatformScreenBuffer class provides an abstraction for screen buffers.
- */
-QPlatformScreenBuffer::QPlatformScreenBuffer()
- : m_destroyed(false)
- , m_ready(true)
-{
-
-}
-
-QPlatformScreenBuffer::~QPlatformScreenBuffer()
-{
-
-}
-
-bool QPlatformScreenBuffer::isDestroyed() const
-{
- return m_destroyed;
-}
-
-bool QPlatformScreenBuffer::isReady() const
-{
- return m_ready;
-}
-
-void QPlatformScreenBuffer::aboutToBeDisplayed()
-{
-}
-
-void QPlatformScreenBuffer::displayed()
-{
-}
-
-
-/*!
- \class QPlatformScreenPageFlipper
- \since 5.0
- \internal
- \preliminary
- \ingroup qpa
-
- \brief The QPlatformScreenPageFlipper class provides an abstract interface for display buffer swapping
-
- Implement the displayBuffer() function to initiate a buffer swap. The
- bufferDisplayed() signal should be emitted once the buffer is actually displayed on
- the screen. The bufferReleased() signal should be emitted when the buffer data is no
- longer owned by the display hardware.
-*/
-
-QPlatformScreenPageFlipper::QPlatformScreenPageFlipper(QObject *parent)
- :QObject(parent)
-{
-
-}
-
-/*!
- \fn bool QPlatformScreenPageFlipper::displayBuffer(QPlatformScreenBuffer *buffer)
-
- Implemented in subclasses to display \a buffer directly on the screen. Returns \c true
- if it is possible to display the buffer, and \c false if the buffer cannot be displayed.
-
- If this function returns \c true, the buffer must not be modified or destroyed before the
- bufferReleased() signal is emitted. The signal bufferDisplayed() is emitted when the buffer
- is displayed on the screen. The two signals may be emitted in either order.
-
- This function is allowed to block.
-*/
-
-QT_END_NAMESPACE
-
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index d3d3d3c222..d1b1106b28 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -508,7 +508,11 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
case MousePressAndHoldInterval:
return QVariant(800);
case MouseDoubleClickDistance:
- return QVariant(5);
+ {
+ bool ok = false;
+ int dist = qgetenv("QT_DBL_CLICK_DIST").toInt(&ok);
+ return QVariant(ok ? dist : 5);
+ }
}
return QVariant();
}
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 0c58745735..808181d48c 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -100,6 +100,7 @@ public:
, cursor(Qt::ArrowCursor)
, hasCursor(false)
#endif
+ , compositing(false)
{
isWindow = true;
}
@@ -175,6 +176,8 @@ public:
QCursor cursor;
bool hasCursor;
#endif
+
+ bool compositing;
};
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 43fff1c65a..23861bd778 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -47,6 +47,10 @@
#include
#include
+#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -360,8 +364,6 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::BGRATextureFormat;
if (extensionMatcher.match("GL_ARB_texture_rectangle"))
extensions |= QOpenGLExtensions::TextureRectangle;
- if (extensionMatcher.match("GL_SGIS_generate_mipmap"))
- extensions |= QOpenGLExtensions::GenerateMipmap;
if (extensionMatcher.match("GL_ARB_texture_compression"))
extensions |= QOpenGLExtensions::TextureCompression;
if (extensionMatcher.match("GL_EXT_texture_compression_s3tc"))
@@ -385,44 +387,51 @@ static int qt_gl_resolve_extensions()
if (format.majorVersion() >= 2)
extensions |= QOpenGLExtensions::GenerateMipmap;
- if (format.majorVersion() >= 3)
+ if (format.majorVersion() >= 3) {
extensions |= QOpenGLExtensions::PackedDepthStencil
| QOpenGLExtensions::Depth24
| QOpenGLExtensions::ElementIndexUint
- | QOpenGLExtensions::MapBufferRange;
+ | QOpenGLExtensions::MapBufferRange
+ | QOpenGLExtensions::FramebufferBlit
+ | QOpenGLExtensions::FramebufferMultisample;
+ } else {
+ // Recognize features by extension name.
+ if (extensionMatcher.match("GL_OES_packed_depth_stencil"))
+ extensions |= QOpenGLExtensions::PackedDepthStencil;
+ if (extensionMatcher.match("GL_OES_depth24"))
+ extensions |= QOpenGLExtensions::Depth24;
+ if (extensionMatcher.match("GL_ANGLE_framebuffer_blit"))
+ extensions |= QOpenGLExtensions::FramebufferBlit;
+ if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample"))
+ extensions |= QOpenGLExtensions::FramebufferMultisample;
+ if (extensionMatcher.match("GL_NV_framebuffer_blit"))
+ extensions |= QOpenGLExtensions::FramebufferBlit;
+ if (extensionMatcher.match("GL_NV_framebuffer_multisample"))
+ extensions |= QOpenGLExtensions::FramebufferMultisample;
+ }
if (extensionMatcher.match("GL_OES_mapbuffer"))
extensions |= QOpenGLExtensions::MapBuffer;
- if (extensionMatcher.match("GL_OES_packed_depth_stencil"))
- extensions |= QOpenGLExtensions::PackedDepthStencil;
if (extensionMatcher.match("GL_OES_element_index_uint"))
extensions |= QOpenGLExtensions::ElementIndexUint;
- if (extensionMatcher.match("GL_OES_depth24"))
- extensions |= QOpenGLExtensions::Depth24;
- // TODO: Consider matching GL_APPLE_texture_format_BGRA8888 as well, but it needs testing.
+ // We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics.
if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888"))
extensions |= QOpenGLExtensions::BGRATextureFormat;
- if (extensionMatcher.match("GL_ANGLE_framebuffer_blit"))
- extensions |= QOpenGLExtensions::FramebufferBlit;
- if (extensionMatcher.match("GL_ANGLE_framebuffer_multisample"))
- extensions |= QOpenGLExtensions::FramebufferMultisample;
- if (extensionMatcher.match("GL_NV_framebuffer_blit"))
- extensions |= QOpenGLExtensions::FramebufferBlit;
- if (extensionMatcher.match("GL_NV_framebuffer_multisample"))
- extensions |= QOpenGLExtensions::FramebufferMultisample;
- if (format.majorVersion() >= 3)
- extensions |= QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::FramebufferMultisample;
} else {
extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer;
- // Recognize features by extension name.
- if (format.majorVersion() >= 3
- || extensionMatcher.match("GL_ARB_framebuffer_object"))
- {
+ if (format.version() >= qMakePair(1, 2))
+ extensions |= QOpenGLExtensions::BGRATextureFormat;
+
+ if (format.version() >= qMakePair(1, 4) || extensionMatcher.match("GL_SGIS_generate_mipmap"))
+ extensions |= QOpenGLExtensions::GenerateMipmap;
+
+ if (format.majorVersion() >= 3 || extensionMatcher.match("GL_ARB_framebuffer_object")) {
extensions |= QOpenGLExtensions::FramebufferMultisample |
QOpenGLExtensions::FramebufferBlit |
QOpenGLExtensions::PackedDepthStencil;
} else {
+ // Recognize features by extension name.
if (extensionMatcher.match("GL_EXT_framebuffer_multisample"))
extensions |= QOpenGLExtensions::FramebufferMultisample;
if (extensionMatcher.match("GL_EXT_framebuffer_blit"))
@@ -430,21 +439,20 @@ static int qt_gl_resolve_extensions()
if (extensionMatcher.match("GL_EXT_packed_depth_stencil"))
extensions |= QOpenGLExtensions::PackedDepthStencil;
}
+
+ if (format.version() >= qMakePair(3, 2) || extensionMatcher.match("GL_ARB_geometry_shader4"))
+ extensions |= QOpenGLExtensions::GeometryShaders;
+
if (extensionMatcher.match("GL_ARB_map_buffer_range"))
extensions |= QOpenGLExtensions::MapBufferRange;
- }
- if (format.renderableType() == QSurfaceFormat::OpenGL && format.version() >= qMakePair(3, 2))
- extensions |= QOpenGLExtensions::GeometryShaders;
-
-#ifndef QT_OPENGL_ES
- if (extensionMatcher.match("GL_EXT_framebuffer_sRGB")) {
- GLboolean srgbCapableFramebuffers = false;
- ctx->functions()->glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers);
- if (srgbCapableFramebuffers)
- extensions |= QOpenGLExtensions::SRGBFrameBuffer;
+ if (extensionMatcher.match("GL_EXT_framebuffer_sRGB")) {
+ GLboolean srgbCapableFramebuffers = false;
+ ctx->functions()->glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers);
+ if (srgbCapableFramebuffers)
+ extensions |= QOpenGLExtensions::SRGBFrameBuffer;
+ }
}
-#endif
return extensions;
}
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index 6e85e5eb4b..8c0b3997fe 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -278,16 +278,27 @@ bool QOpenGLShaderPrivate::compile(QOpenGLShader *q)
"Fragment",
"Vertex",
"Geometry",
+ "Tessellation Control",
+ "Tessellation Evaluation",
+ "Compute",
""
};
- const char *type = types[3];
- if (shaderType == QOpenGLShader::Fragment)
- type = types[0];
- else if (shaderType == QOpenGLShader::Vertex)
- type = types[1];
- else if (shaderType == QOpenGLShader::Geometry)
- type = types[2];
+ const char *type = types[6];
+ switch (shaderType) {
+ case QOpenGLShader::Fragment:
+ type = types[0]; break;
+ case QOpenGLShader::Vertex:
+ type = types[1]; break;
+ case QOpenGLShader::Geometry:
+ type = types[2]; break;
+ case QOpenGLShader::TessellationControl:
+ type = types[3]; break;
+ case QOpenGLShader::TessellationEvaluation:
+ type = types[4]; break;
+ case QOpenGLShader::Compute:
+ type = types[5]; break;
+ }
// Get info and source code lengths
GLint infoLogLength = 0;
diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp
index ef548188c8..ebe0429290 100644
--- a/src/gui/opengl/qopengltextureblitter.cpp
+++ b/src/gui/opengl/qopengltextureblitter.cpp
@@ -248,9 +248,6 @@ bool QOpenGLTextureBlitter::create()
Q_D(QOpenGLTextureBlitter);
- d->vao->create();
- d->vao->bind();
-
if (d->program)
return true;
@@ -273,6 +270,9 @@ bool QOpenGLTextureBlitter::create()
d->program->bind();
+ // Create and bind the VAO, if supported.
+ QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data());
+
d->vertexBuffer.create();
d->vertexBuffer.bind();
d->vertexBuffer.allocate(vertex_buffer_data, sizeof(vertex_buffer_data));
@@ -292,8 +292,6 @@ bool QOpenGLTextureBlitter::create()
d->program->setUniformValue(d->swizzleUniformPos,false);
- d->vao->release();
-
return true;
}
@@ -316,7 +314,8 @@ void QOpenGLTextureBlitter::bind()
{
Q_D(QOpenGLTextureBlitter);
- d->vao->bind();
+ if (d->vao->isCreated())
+ d->vao->bind();
d->program->bind();
@@ -335,7 +334,8 @@ void QOpenGLTextureBlitter::release()
{
Q_D(QOpenGLTextureBlitter);
d->program->release();
- d->vao->release();
+ if (d->vao->isCreated())
+ d->vao->release();
}
void QOpenGLTextureBlitter::setSwizzleRB(bool swizzle)
diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp
index 27aece8eca..9cb5e8798e 100644
--- a/src/gui/opengl/qopengltexturehelper.cpp
+++ b/src/gui/opengl/qopengltexturehelper.cpp
@@ -164,6 +164,60 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
TexSubImage2D = reinterpret_cast(GetProcAddress(handle, QByteArrayLiteral("glTexSubImage2D")));
TexSubImage1D = reinterpret_cast(GetProcAddress(handle, QByteArrayLiteral("glTexSubImage1D")));
+#elif defined(QT_OPENGL_ES_2)
+ // Here we are targeting OpenGL ES 2.0+ only. This is likely using EGL, where,
+ // similarly to WGL, non-extension functions (i.e. any function that is part of the
+ // GLES spec) *may* not be queried via eglGetProcAddress.
+
+ // OpenGL 1.0
+ GetIntegerv = ::glGetIntegerv;
+ GetBooleanv = ::glGetBooleanv;
+ PixelStorei = ::glPixelStorei;
+ GetTexLevelParameteriv = 0;
+ GetTexLevelParameterfv = 0;
+ GetTexParameteriv = ::glGetTexParameteriv;
+ GetTexParameterfv = ::glGetTexParameterfv;
+ GetTexImage = 0;
+ TexImage2D = ::glTexImage2D;
+ TexImage1D = 0;
+ TexParameteriv = ::glTexParameteriv;
+ TexParameteri = ::glTexParameteri;
+ TexParameterfv = ::glTexParameterfv;
+ TexParameterf = ::glTexParameterf;
+
+ // OpenGL 1.1
+ GenTextures = ::glGenTextures;
+ DeleteTextures = ::glDeleteTextures;
+ BindTexture = ::glBindTexture;
+ TexSubImage2D = ::glTexSubImage2D;
+ TexSubImage1D = 0;
+
+ // OpenGL 1.3
+ GetCompressedTexImage = 0;
+ CompressedTexSubImage1D = 0;
+ CompressedTexSubImage2D = ::glCompressedTexSubImage2D;
+ CompressedTexImage1D = 0;
+ CompressedTexImage2D = ::glCompressedTexImage2D;
+ ActiveTexture = ::glActiveTexture;
+
+ // OpenGL 3.0
+ GenerateMipmap = ::glGenerateMipmap;
+
+ // OpenGL 3.2
+ TexImage3DMultisample = 0;
+ TexImage2DMultisample = 0;
+
+ // OpenGL 4.2
+ TexStorage3D = 0;
+ TexStorage2D = 0;
+ TexStorage1D = 0;
+
+ // OpenGL 4.3
+ TexStorage3DMultisample = 0;
+ TexStorage2DMultisample = 0;
+ TexBufferRange = 0;
+ TextureView = 0;
+
#else
// OpenGL 1.0
@@ -196,6 +250,13 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
CompressedTexImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3DOES")));
CompressedTexSubImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3DOES")));
} else {
+#ifdef QT_OPENGL_ES_3
+ // OpenGL ES 3.0+ has glTexImage3D.
+ TexImage3D = ::glTexImage3D;
+ TexSubImage3D = ::glTexSubImage3D;
+ CompressedTexImage3D = ::glCompressedTexImage3D;
+ CompressedTexSubImage3D = ::glCompressedTexSubImage3D;
+#else
// OpenGL 1.2
TexImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glTexImage3D")));
TexSubImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glTexSubImage3D")));
@@ -203,8 +264,10 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
// OpenGL 1.3
CompressedTexImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3D")));
CompressedTexSubImage3D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3D")));
+#endif
}
+#ifndef QT_OPENGL_ES_2
// OpenGL 1.3
GetCompressedTexImage = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGetCompressedTexImage")));
CompressedTexSubImage1D = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage1D")));
@@ -230,6 +293,7 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
TexStorage2DMultisample = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glTexStorage2DMultisample")));
TexBufferRange = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glTexBufferRange")));
TextureView = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glTextureView")));
+#endif
}
void QOpenGLTextureHelper::dsa_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param)
diff --git a/src/gui/opengl/qopenglversionfunctions.cpp b/src/gui/opengl/qopenglversionfunctions.cpp
index 3335a88cbb..f5ce8865a8 100644
--- a/src/gui/opengl/qopenglversionfunctions.cpp
+++ b/src/gui/opengl/qopenglversionfunctions.cpp
@@ -98,8 +98,10 @@ void QAbstractOpenGLFunctionsPrivate::removeFunctionsBackend(QOpenGLContext *con
Qt now provides a family of classes which all inherit from
QAbstractOpenGLFunctions which expose every core OpenGL function by way of a
corresponding member function. There is a class for every valid combination
- of OpenGL version and profile. Each class follows the naming convention
- QOpenGLFunctions__[_PROFILE].
+ of OpenGL version and profile. Each class follows the naming convention:
+ \badcode
+ QOpenGLFunctions__[_PROFILE]
+ \endcode
For OpenGL versions 1.0 through to 3.0 there are no profiles, leading to the
classes:
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 2e340219b9..914691375a 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -921,7 +921,7 @@ void QRasterPaintEngine::renderHintsChanged()
bool was_aa = s->flags.antialiased;
bool was_bilinear = s->flags.bilinear;
- s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing);
+ s->flags.antialiased = bool(s->renderHints & (QPainter::Antialiasing | QPainter::HighQualityAntialiasing));
s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform);
s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting);
@@ -2726,7 +2726,7 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
scanline += bpl;
}
} else { // 32-bit alpha...
- uint *sl = (uint *) src;
+ uint *sl = (uint *) scanline;
for (int y = y0; y < y1; ++y) {
for (int x = x0; x < x1; ) {
// Skip those with 0 coverage
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 0e03a0194a..5d046caaa4 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1106,6 +1106,11 @@ void QPainterPrivate::updateState(QPainterState *newState)
\li \inlineimage qpainter-pathstroking.png
\endtable
+ Text drawing is done using drawText(). When you need
+ fine-grained positioning, boundingRect() tells you where a given
+ drawText() command will draw.
+
+ \section1 Drawing Pixmaps and Images
There are functions to draw pixmaps/images, namely drawPixmap(),
drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
@@ -1113,15 +1118,25 @@ void QPainterPrivate::updateState(QPainterState *newState)
on-screen while drawImage() may be faster on a QPrinter or other
devices.
- Text drawing is done using drawText(). When you need
- fine-grained positioning, boundingRect() tells you where a given
- drawText() command will draw.
-
There is a drawPicture() function that draws the contents of an
entire QPicture. The drawPicture() function is the only function
that disregards all the painter's settings as QPicture has its own
settings.
+ \section2 Drawing High Resolution Versions of Pixmaps and Images
+
+ High resolution versions of pixmaps have a \e{device pixel ratio} value larger
+ than 1 (see QImageReader, QPixmap::devicePixelRatio()). Should it match the value
+ of the underlying QPaintDevice, it is drawn directly onto the device with no
+ additional transformation applied.
+
+ This is for example the case when drawing a QPixmap of 64x64 pixels size with
+ a device pixel ratio of 2 onto a high DPI screen which also has
+ a device pixel ratio of 2. Note that the pixmap is then effectively 32x32
+ pixels in \e{user space}. Code paths in Qt that calculate layout geometry
+ based on the pixmap size will use this size. The net effect of this is that
+ the pixmap is displayed as high DPI pixmap rather than a large pixmap.
+
\section1 Rendering Quality
To get the optimal rendering result using QPainter, you should use
@@ -5024,6 +5039,8 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor
into the given \a target in the paint device.
\note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
+ \note See \l{Drawing High Resolution Versions of Pixmaps and Images} on how this is affected
+ by QPixmap::devicePixelRatio().
\table 100%
\row
@@ -5038,7 +5055,7 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor
transparent. Drawing bitmaps with gradient or texture colors is
not supported.
- \sa drawImage()
+ \sa drawImage(), QPixmap::devicePixelRatio()
*/
void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
{
@@ -7694,6 +7711,8 @@ void QPainterState::init(QPainter *p) {
into the \a target rectangle in the paint device.
\note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
+ \note See \l{Drawing High Resolution Versions of Pixmaps and Images} on how this is affected
+ by QImage::devicePixelRatio().
If the image needs to be modified to fit in a lower-resolution
result (e.g. converting from 32-bit to 8-bit), use the \a flags to
@@ -7705,7 +7724,7 @@ void QPainterState::init(QPainter *p) {
\snippet code/src_gui_painting_qpainter.cpp 20
\endtable
- \sa drawPixmap()
+ \sa drawPixmap(), QImage::devicePixelRatio()
*/
/*!
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 66a56ac32f..407e032027 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -62,6 +62,7 @@ public:
QPlatformBackingStorePrivate(QWindow *w)
: window(w)
#ifndef QT_NO_OPENGL
+ , textureId(0)
, blitter(0)
#endif
{
@@ -276,7 +277,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(false);
}
- funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
@@ -287,6 +287,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
}
}
+ funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
funcs->glDisable(GL_BLEND);
d_ptr->blitter->release();
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 20c62fdd9d..eb197378ad 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -1072,28 +1072,12 @@ struct QRegionPrivate {
int innerArea;
inline QRegionPrivate() : numRects(0), innerArea(-1) {}
- inline QRegionPrivate(const QRect &r) {
- numRects = 1;
- extents = r;
- innerRect = r;
- innerArea = r.width() * r.height();
- }
-
- inline QRegionPrivate(const QRegionPrivate &r) {
- rects = r.rects;
- numRects = r.numRects;
- extents = r.extents;
- innerRect = r.innerRect;
- innerArea = r.innerArea;
- }
-
- inline QRegionPrivate &operator=(const QRegionPrivate &r) {
- rects = r.rects;
- numRects = r.numRects;
- extents = r.extents;
- innerRect = r.innerRect;
- innerArea = r.innerArea;
- return *this;
+ inline QRegionPrivate(const QRect &r)
+ : numRects(1),
+ extents(r),
+ innerRect(r),
+ innerArea(r.width() * r.height())
+ {
}
void intersect(const QRect &r);
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index eef316b039..cb3cb34d27 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -826,7 +826,7 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
}
if (set && set->outline_drawing)
- load_flags = FT_LOAD_NO_BITMAP;
+ load_flags |= FT_LOAD_NO_BITMAP;
if (default_hint_style == HintNone || (flags & DesignMetrics) || (set && set->outline_drawing))
load_flags |= FT_LOAD_NO_HINTING;
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index e9ffa68591..5dc81d241d 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -401,6 +401,16 @@ QString QPlatformFontDatabase::fontDir() const
return fontpath;
}
+/*!
+ Returns true if the font family is private. For any given family name,
+ the result is platform dependent.
+*/
+bool QPlatformFontDatabase::isPrivateFontFamily(const QString &family) const
+{
+ Q_UNUSED(family);
+ return false;
+}
+
/*!
Returns the default system font.
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index b200cf0e58..46ef5c0f46 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -110,6 +110,7 @@ public:
virtual QString fontDir() const;
virtual QFont defaultFont() const;
+ virtual bool isPrivateFontFamily(const QString &family) const;
virtual QString resolveFontFamilyAlias(const QString &family) const;
virtual bool fontsAlwaysScalable() const;
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index bead45ab83..e572745d51 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -2008,6 +2008,9 @@ static int qt_timeout_value(int msecs, int elapsed)
\note Multiple calls to this functions do not accumulate the time.
If the function times out, the connecting process will be aborted.
+ \note This function may fail randomly on Windows. Consider using the event
+ loop and the connected() signal if your software will run on Windows.
+
\sa connectToHost(), connected()
*/
bool QAbstractSocket::waitForConnected(int msecs)
@@ -2107,6 +2110,9 @@ bool QAbstractSocket::waitForConnected(int msecs)
there is new data available for reading; otherwise it returns \c false
(if an error occurred or the operation timed out).
+ \note This function may fail randomly on Windows. Consider using the event
+ loop and the readyRead() signal if your software will run on Windows.
+
\sa waitForBytesWritten()
*/
bool QAbstractSocket::waitForReadyRead(int msecs)
@@ -2166,6 +2172,20 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
}
/*! \reimp
+
+ This function blocks until at least one byte has been written on the socket
+ and the \l{QIODevice::}{bytesWritten()} signal has been emitted. The
+ function will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns \c true if the bytesWritten() signal is emitted;
+ otherwise it returns \c false (if an error occurred or the operation timed
+ out).
+
+ \note This function may fail randomly on Windows. Consider using the event
+ loop and the bytesWritten() signal if your software will run on Windows.
+
+ \sa waitForReadyRead()
*/
bool QAbstractSocket::waitForBytesWritten(int msecs)
{
@@ -2247,6 +2267,9 @@ bool QAbstractSocket::waitForBytesWritten(int msecs)
If msecs is -1, this function will not time out.
+ \note This function may fail randomly on Windows. Consider using the event
+ loop and the disconnected() signal if your software will run on Windows.
+
\sa disconnectFromHost(), close()
*/
bool QAbstractSocket::waitForDisconnected(int msecs)
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index ab6c2a6590..2ea6d6e015 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -51,8 +51,14 @@
#include
#include
#include
+#include
-#include
+#include
+#include
+
+#ifndef QT_NO_SSL
+#include
+#endif
#include
#include
@@ -124,6 +130,20 @@ struct SocketHandler
Q_GLOBAL_STATIC(SocketHandler, gSocketHandler)
+struct SocketGlobal
+{
+ SocketGlobal()
+ {
+ HRESULT hr;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
+ &bufferFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ComPtr bufferFactory;
+};
+Q_GLOBAL_STATIC(SocketGlobal, g)
+
static inline QString qt_QStringFromHString(const HString &string)
{
UINT32 length;
@@ -131,60 +151,7 @@ static inline QString qt_QStringFromHString(const HString &string)
return QString::fromWCharArray(rawString, length);
}
-#define READ_BUFFER_SIZE 8192
-
-class ByteArrayBuffer : public Microsoft::WRL::RuntimeClass,
- IBuffer, Windows::Storage::Streams::IBufferByteAccess>
-{
-public:
- ByteArrayBuffer(int size) : m_bytes(size, Qt::Uninitialized), m_length(0)
- {
- }
-
- ByteArrayBuffer(const char *data, int size) : m_bytes(data, size), m_length(size)
- {
- }
-
- HRESULT __stdcall Buffer(byte **value)
- {
- *value = reinterpret_cast(m_bytes.data());
- return S_OK;
- }
-
- HRESULT __stdcall get_Capacity(UINT32 *value)
- {
- *value = m_bytes.size();
- return S_OK;
- }
-
- HRESULT __stdcall get_Length(UINT32 *value)
- {
- *value = m_length;
- return S_OK;
- }
-
- HRESULT __stdcall put_Length(UINT32 value)
- {
- Q_ASSERT(value <= UINT32(m_bytes.size()));
- m_length = value;
- return S_OK;
- }
-
- ComPtr inputStream() const
- {
- return m_stream;
- }
-
- void setInputStream(ComPtr stream)
- {
- m_stream = stream;
- }
-
-private:
- QByteArray m_bytes;
- UINT32 m_length;
- ComPtr m_stream;
-};
+#define READ_BUFFER_SIZE 65536
template
static AsyncStatus opStatus(const ComPtr &op)
@@ -207,6 +174,14 @@ static AsyncStatus opStatus(const ComPtr &op)
QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
+#ifndef QT_NO_SSL
+ Q_D(QNativeSocketEngine);
+ Q_ASSERT(parent);
+ d->sslSocket = qobject_cast(parent->parent());
+#else
+ d->sslSocket = Q_NULLPTR;
+#endif
+
connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection);
connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection);
connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
@@ -239,16 +214,14 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
if (isValid())
close();
- d->socketDescriptor = socketDescriptor;
-
// Currently, only TCP sockets are initialized this way.
- SocketHandler *handler = gSocketHandler();
- d->tcp = handler->pendingTcpSockets.take(socketDescriptor);
+ d->socketDescriptor = qintptr(gSocketHandler->pendingTcpSockets.take(socketDescriptor));
d->socketType = QAbstractSocket::TcpSocket;
- if (!d->tcp || !d->fetchConnectionParameters()) {
+ if (!d->socketDescriptor || !d->fetchConnectionParameters()) {
d->setError(QAbstractSocket::UnsupportedSocketOperationError,
d->InvalidSocketErrorString);
+ d->socketDescriptor = -1;
return false;
}
@@ -287,68 +260,23 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
return false;
}
- ComPtr op;
const QString portString = QString::number(port);
HStringReference portReference(reinterpret_cast(portString.utf16()));
HRESULT hr = E_FAIL;
if (d->socketType == QAbstractSocket::TcpSocket)
- hr = d->tcp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op);
+ hr = d->tcpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->connectOp);
else if (d->socketType == QAbstractSocket::UdpSocket)
- hr = d->udp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op);
+ hr = d->udpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->connectOp);
if (FAILED(hr)) {
qWarning("QNativeSocketEnginePrivate::nativeConnect:: Could not obtain connect action");
return false;
}
-
- hr = op->put_Completed(Callback(
- d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Unable to set host connection callback.");
- return false;
- }
d->socketState = QAbstractSocket::ConnectingState;
- while (opStatus(op) == Started)
- d->eventLoop.processEvents();
+ hr = d->connectOp->put_Completed(Callback(
+ d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
+ Q_ASSERT_SUCCEEDED(hr);
- AsyncStatus status = opStatus(op);
- if (status == Error || status == Canceled)
- return false;
-
- if (hr == 0x8007274c) { // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
- d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString);
- d->socketState = QAbstractSocket::UnconnectedState;
- return false;
- }
- if (hr == 0x8007274d) { // No connection could be made because the target machine actively refused it.
- d->setError(QAbstractSocket::ConnectionRefusedError, d->ConnectionRefusedErrorString);
- d->socketState = QAbstractSocket::UnconnectedState;
- return false;
- }
- if (FAILED(hr)) {
- d->setError(QAbstractSocket::UnknownSocketError, d->UnknownSocketErrorString);
- d->socketState = QAbstractSocket::UnconnectedState;
- return false;
- }
-
- if (d->socketType == QAbstractSocket::TcpSocket) {
- IInputStream *stream;
- hr = d->tcp->get_InputStream(&stream);
- if (FAILED(hr))
- return false;
- ByteArrayBuffer *buffer = static_cast(d->readBuffer.Get());
- buffer->setInputStream(stream);
- ComPtr op;
- hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
- if (FAILED(hr))
- return false;
- hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to set socket read callback.");
- return false;
- }
- }
- d->socketState = QAbstractSocket::ConnectedState;
- return true;
+ return d->socketState == QAbstractSocket::ConnectedState;
}
bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
@@ -385,7 +313,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
return false;
}
} else if (d->socketType == QAbstractSocket::UdpSocket) {
- hr = d->udp->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
+ hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message
return false;
@@ -447,13 +375,16 @@ int QNativeSocketEngine::accept()
if (d->socketType == QAbstractSocket::TcpSocket) {
IStreamSocket *socket = d->pendingConnections.takeFirst();
- IInputStream *stream;
- socket->get_InputStream(&stream);
- // TODO: delete buffer and stream on socket close
- ByteArrayBuffer *buffer = static_cast(d->readBuffer.Get());
- buffer->setInputStream(stream);
+ HRESULT hr;
+ ComPtr buffer;
+ hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr stream;
+ hr = socket->get_InputStream(&stream);
+ Q_ASSERT_SUCCEEDED(hr);
ComPtr op;
- HRESULT hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Faild to read from the socket buffer.");
return -1;
@@ -476,12 +407,25 @@ int QNativeSocketEngine::accept()
void QNativeSocketEngine::close()
{
Q_D(QNativeSocketEngine);
+
+ if (d->connectOp) {
+ ComPtr info;
+ d->connectOp.As(&info);
+ if (info) {
+ info->Cancel();
+ info->Close();
+ }
+ }
+
if (d->socketDescriptor != -1) {
ComPtr socket;
- if (d->socketType == QAbstractSocket::TcpSocket && d->tcp)
- d->tcp.As(&socket);
- else if (d->socketType == QAbstractSocket::UdpSocket && d->udp)
- d->udp.As(&socket);
+ if (d->socketType == QAbstractSocket::TcpSocket) {
+ d->tcpSocket()->QueryInterface(IID_PPV_ARGS(&socket));
+ d->tcpSocket()->Release();
+ } else if (d->socketType == QAbstractSocket::UdpSocket) {
+ d->udpSocket()->QueryInterface(IID_PPV_ARGS(&socket));
+ d->udpSocket()->Release();
+ }
if (socket) {
d->closingDown = true;
@@ -549,42 +493,40 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
qint64 QNativeSocketEngine::write(const char *data, qint64 len)
{
Q_D(QNativeSocketEngine);
+ if (!isValid())
+ return -1;
+
HRESULT hr = E_FAIL;
ComPtr stream;
if (d->socketType == QAbstractSocket::TcpSocket)
- hr = d->tcp->get_OutputStream(&stream);
+ hr = d->tcpSocket()->get_OutputStream(&stream);
else if (d->socketType == QAbstractSocket::UdpSocket)
- hr = d->udp->get_OutputStream(&stream);
+ hr = d->udpSocket()->get_OutputStream(&stream);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get output stream to socket.");
return -1;
}
- ComPtr buffer = Make(data, len);
+ ComPtr buffer;
+ hr = g->bufferFactory->Create(len, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(len);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+ byte *bytes;
+ hr = byteArrayAccess->Buffer(&bytes);
+ Q_ASSERT_SUCCEEDED(hr);
+ memcpy(bytes, data, len);
ComPtr> op;
hr = stream->WriteAsync(buffer.Get(), &op);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to write to socket.");
- return -1;
- }
- hr = op->put_Completed(Callback>(
- d, &QNativeSocketEnginePrivate::handleWriteCompleted).Get());
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to set socket write callback.");
- return -1;
- }
-
- while (opStatus(op) == Started)
- d->eventLoop.processEvents();
-
- AsyncStatus status = opStatus(op);
- if (status == Error || status == Canceled)
- return -1;
+ RETURN_IF_FAILED("Failed to write to stream", return -1);
UINT32 bytesWritten;
- hr = op->GetResults(&bytesWritten);
+ hr = QWinRTFunctions::await(op, &bytesWritten);
if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get written socket length.");
+ d->setError(QAbstractSocket::SocketAccessError, QNativeSocketEnginePrivate::AccessErrorString);
return -1;
}
@@ -655,7 +597,7 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QH
ComPtr stream;
const QString portString = QString::number(port);
HStringReference portRef(reinterpret_cast(portString.utf16()));
- if (FAILED(d->udp->GetOutputStreamAsync(remoteHost.Get(), portRef.Get(), &streamOperation)))
+ if (FAILED(d->udpSocket()->GetOutputStreamAsync(remoteHost.Get(), portRef.Get(), &streamOperation)))
return -1;
HRESULT hr;
while (hr = streamOperation->GetResults(&stream) == E_ILLEGAL_METHOD_CALL)
@@ -825,29 +767,50 @@ void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
d->notifyOnException = enable;
}
+void QNativeSocketEngine::establishRead()
+{
+ Q_D(QNativeSocketEngine);
+
+ HRESULT hr;
+ ComPtr stream;
+ hr = d->tcpSocket()->get_InputStream(&stream);
+ RETURN_VOID_IF_FAILED("Failed to get socket input stream");
+
+ ComPtr buffer;
+ hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr op;
+ hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ RETURN_VOID_IF_FAILED("Failed to initiate socket read");
+ hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ Q_ASSERT_SUCCEEDED(hr);
+}
+
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{
Q_UNUSED(socketProtocol);
- SocketHandler *handler = gSocketHandler();
switch (socketType) {
case QAbstractSocket::TcpSocket: {
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &tcp);
+ ComPtr socket;
+ HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &socket);
if (FAILED(hr)) {
qWarning("Failed to create StreamSocket instance");
return false;
}
- socketDescriptor = ++handler->socketCount;
+ socketDescriptor = qintptr(socket.Detach());
return true;
}
case QAbstractSocket::UdpSocket: {
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &udp);
+ ComPtr socket;
+ HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket);
if (FAILED(hr)) {
qWarning("Failed to create stream socket");
return false;
}
EventRegistrationToken token;
- udp->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token);
- socketDescriptor = ++handler->socketCount;
+ udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token);
+ socketDescriptor = qintptr(socket.Detach());
return true;
}
default:
@@ -865,8 +828,6 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, closingDown(false)
, socketDescriptor(-1)
{
- ComPtr buffer = Make(READ_BUFFER_SIZE);
- readBuffer = buffer;
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
@@ -980,7 +941,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt)
{
ComPtr control;
if (socketType == QAbstractSocket::TcpSocket) {
- if (FAILED(tcp->get_Control(&control))) {
+ if (FAILED(tcpSocket()->get_Control(&control))) {
qWarning("QNativeSocketEnginePrivate::option: Could not obtain socket control");
return -1;
}
@@ -1036,7 +997,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o
{
ComPtr control;
if (socketType == QAbstractSocket::TcpSocket) {
- if (FAILED(tcp->get_Control(&control))) {
+ if (FAILED(tcpSocket()->get_Control(&control))) {
qWarning("QNativeSocketEnginePrivate::setOption: Could not obtain socket control");
return false;
}
@@ -1100,7 +1061,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
ComPtr hostName;
HString tmpHString;
ComPtr info;
- if (FAILED(tcp->get_Information(&info))) {
+ if (FAILED(tcpSocket()->get_Information(&info))) {
qWarning("QNativeSocketEnginePrivate::fetchConnectionParameters: Could not obtain socket info");
return false;
}
@@ -1129,7 +1090,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
ComPtr hostName;
HString tmpHString;
ComPtr info;
- if (FAILED(udp->get_Information(&info))) {
+ if (FAILED(udpSocket()->get_Information(&info))) {
qWarning("QNativeSocketEnginePrivate::fetchConnectionParameters: Could not obtain socket information");
return false;
}
@@ -1169,8 +1130,46 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus)
+HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus)
{
+ Q_Q(QNativeSocketEngine);
+
+ HRESULT hr = action->GetResults();
+ if (wasDeleted || !connectOp) // Protect against a late callback
+ return S_OK;
+
+ connectOp.Reset();
+ switch (hr) {
+ case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
+ setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
+ socketState = QAbstractSocket::UnconnectedState;
+ return S_OK;
+ case 0x80072751: // A socket operation was attempted to an unreachable host.
+ setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString);
+ socketState = QAbstractSocket::UnconnectedState;
+ return S_OK;
+ case 0x8007274d: // No connection could be made because the target machine actively refused it.
+ setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
+ socketState = QAbstractSocket::UnconnectedState;
+ return S_OK;
+ default:
+ if (FAILED(hr)) {
+ setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
+ socketState = QAbstractSocket::UnconnectedState;
+ return S_OK;
+ }
+ break;
+ }
+
+ socketState = QAbstractSocket::ConnectedState;
+ emit q->connectionReady();
+
+ // Delay the reader so that the SSL socket can upgrade
+ if (sslSocket)
+ q->connect(sslSocket, SIGNAL(encrypted()), SLOT(establishRead()));
+ else
+ q->establishRead();
+
return S_OK;
}
@@ -1183,22 +1182,25 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
if (status == Error || status == Canceled)
return S_OK;
- ByteArrayBuffer *buffer = 0;
- HRESULT hr = asyncInfo->GetResults((IBuffer **)&buffer);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get ready read results.");
- return S_OK;
- }
- UINT32 len;
- buffer->get_Length(&len);
- if (!len) {
+ ComPtr buffer;
+ HRESULT hr = asyncInfo->GetResults(&buffer);
+ RETURN_OK_IF_FAILED("Failed to get read results buffer");
+
+ UINT32 bufferLength;
+ hr = buffer->get_Length(&bufferLength);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (!bufferLength) {
if (q->isReadNotificationEnabled())
emit q->readReady();
return S_OK;
}
+ ComPtr byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
byte *data;
- buffer->Buffer(&data);
+ hr = byteArrayAccess->Buffer(&data);
+ Q_ASSERT_SUCCEEDED(hr);
readMutex.lock();
if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset
@@ -1208,15 +1210,25 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
qint64 readPos = readBytes.pos();
readBytes.seek(readBytes.size());
Q_ASSERT(readBytes.atEnd());
- readBytes.write(reinterpret_cast(data), qint64(len));
+ readBytes.write(reinterpret_cast(data), qint64(bufferLength));
readBytes.seek(readPos);
readMutex.unlock();
if (q->isReadNotificationEnabled())
emit q->readReady();
+ ComPtr stream;
+ hr = tcpSocket()->get_InputStream(&stream);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // Reuse the stream buffer
+ hr = buffer->get_Capacity(&bufferLength);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(0);
+ Q_ASSERT_SUCCEEDED(hr);
+
ComPtr op;
- hr = buffer->inputStream()->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ hr = stream->ReadAsync(buffer.Get(), bufferLength, InputStreamOptions_Partial, &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Could not read into socket stream buffer.");
return S_OK;
@@ -1229,28 +1241,6 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleWriteCompleted(IAsyncOperationWithProgress *op, AsyncStatus status)
-{
- if (status == Error) {
- ComPtr info;
- HRESULT hr = op->QueryInterface(IID_PPV_ARGS(&info));
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to cast operation.");
- return S_OK;
- }
- HRESULT errorCode;
- hr = info->get_ErrorCode(&errorCode);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get error code.");
- return S_OK;
- }
- qErrnoWarning(errorCode, "A socket error occurred.");
- return S_OK;
- }
-
- return S_OK;
-}
-
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index bf23faeb45..1d84c93f0a 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -134,6 +134,9 @@ signals:
void readReady();
void writeReady();
+private slots:
+ void establishRead();
+
private:
Q_DECLARE_PRIVATE(QNativeSocketEngine)
Q_DISABLE_COPY(QNativeSocketEngine)
@@ -192,17 +195,21 @@ public:
bool checkProxy(const QHostAddress &address);
bool fetchConnectionParameters();
+
private:
- Microsoft::WRL::ComPtr tcp;
- Microsoft::WRL::ComPtr udp;
+ inline ABI::Windows::Networking::Sockets::IStreamSocket *tcpSocket() const
+ { return reinterpret_cast(socketDescriptor); }
+ inline ABI::Windows::Networking::Sockets::IDatagramSocket *udpSocket() const
+ { return reinterpret_cast(socketDescriptor); }
Microsoft::WRL::ComPtr tcpListener;
- Microsoft::WRL::ComPtr readBuffer;
+ Microsoft::WRL::ComPtr connectOp;
QBuffer readBytes;
QMutex readMutex;
QList pendingDatagrams;
QList pendingConnections;
QList currentConnections;
QEventLoop eventLoop;
+ QAbstractSocket *sslSocket;
HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
@@ -211,7 +218,6 @@ private:
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
- HRESULT handleWriteCompleted(ABI::Windows::Foundation::IAsyncOperationWithProgress *, ABI::Windows::Foundation::AsyncStatus);
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qasn1element.cpp b/src/network/ssl/qasn1element.cpp
new file mode 100644
index 0000000000..d282a02827
--- /dev/null
+++ b/src/network/ssl/qasn1element.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jeremy Lainé
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qasn1element_p.h"
+
+#include
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap OidNameMap;
+static OidNameMap createOidMap()
+{
+ OidNameMap oids;
+ // used by unit tests
+ oids.insert(oids.end(), QByteArrayLiteral("0.9.2342.19200300.100.1.5"), QByteArrayLiteral("favouriteDrink"));
+ oids.insert(oids.end(), QByteArrayLiteral("1.2.840.113549.1.9.1"), QByteArrayLiteral("emailAddress"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.10"), QByteArrayLiteral("O"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.11"), QByteArrayLiteral("OU"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.12"), QByteArrayLiteral("title"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.13"), QByteArrayLiteral("description"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.17"), QByteArrayLiteral("postalCode"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.3"), QByteArrayLiteral("CN"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.4"), QByteArrayLiteral("SN"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.41"), QByteArrayLiteral("name"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.42"), QByteArrayLiteral("GN"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.43"), QByteArrayLiteral("initials"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.46"), QByteArrayLiteral("dnQualifier"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.5"), QByteArrayLiteral("serialNumber"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.6"), QByteArrayLiteral("C"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.7"), QByteArrayLiteral("L"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.8"), QByteArrayLiteral("ST"));
+ oids.insert(oids.end(), QByteArrayLiteral("2.5.4.9"), QByteArrayLiteral("street"));
+ return oids;
+}
+Q_GLOBAL_STATIC_WITH_ARGS(OidNameMap, oidNameMap, (createOidMap()))
+
+QAsn1Element::QAsn1Element(quint8 type, const QByteArray &value)
+ : mType(type)
+ , mValue(value)
+{
+}
+
+bool QAsn1Element::read(QDataStream &stream)
+{
+ // type
+ quint8 tmpType;
+ stream >> tmpType;
+ if (!tmpType)
+ return false;
+
+ // length
+ qint64 length = 0;
+ quint8 first;
+ stream >> first;
+ if (first & 0x80) {
+ // long form
+ const quint8 bytes = (first & 0x7f);
+ if (bytes > 7)
+ return false;
+
+ quint8 b;
+ for (int i = 0; i < bytes; i++) {
+ stream >> b;
+ length = (length << 8) | b;
+ }
+ } else {
+ // short form
+ length = (first & 0x7f);
+ }
+
+ // value
+ QByteArray tmpValue;
+ tmpValue.resize(length);
+ int count = stream.readRawData(tmpValue.data(), tmpValue.size());
+ if (count != length)
+ return false;
+
+ mType = tmpType;
+ mValue.swap(tmpValue);
+ return true;
+}
+
+bool QAsn1Element::read(const QByteArray &data)
+{
+ QDataStream stream(data);
+ return read(stream);
+}
+
+void QAsn1Element::write(QDataStream &stream) const
+{
+ // type
+ stream << mType;
+
+ // length
+ qint64 length = mValue.size();
+ if (length >= 128) {
+ // long form
+ quint8 encodedLength = 0x80;
+ QByteArray ba;
+ while (length) {
+ ba.prepend(quint8((length & 0xff)));
+ length >>= 8;
+ encodedLength += 1;
+ }
+ stream << encodedLength;
+ stream.writeRawData(ba.data(), ba.size());
+ } else {
+ // short form
+ stream << quint8(length);
+ }
+
+ // value
+ stream.writeRawData(mValue.data(), mValue.size());
+}
+
+QAsn1Element QAsn1Element::fromInteger(unsigned int val)
+{
+ QAsn1Element elem(QAsn1Element::IntegerType);
+ while (val > 127) {
+ elem.mValue.prepend(val & 0xff);
+ val >>= 8;
+ }
+ elem.mValue.prepend(val & 0x7f);
+ return elem;
+}
+
+QAsn1Element QAsn1Element::fromVector(const QVector &items)
+{
+ QAsn1Element seq;
+ seq.mType = SequenceType;
+ QDataStream stream(&seq.mValue, QIODevice::WriteOnly);
+ for (QVector::const_iterator it = items.cbegin(), end = items.cend(); it != end; ++it)
+ it->write(stream);
+ return seq;
+}
+
+QAsn1Element QAsn1Element::fromObjectId(const QByteArray &id)
+{
+ QAsn1Element elem;
+ elem.mType = ObjectIdentifierType;
+ QList bits = id.split('.');
+ Q_ASSERT(bits.size() > 2);
+ elem.mValue += quint8((bits[0].toUInt() * 40 + bits[1].toUInt()));
+ for (int i = 2; i < bits.size(); ++i) {
+ char buffer[std::numeric_limits::digits / 7 + 2];
+ char *pBuffer = buffer + sizeof(buffer);
+ *--pBuffer = '\0';
+ unsigned int node = bits[i].toUInt();
+ *--pBuffer = quint8((node & 0x7f));
+ node >>= 7;
+ while (node) {
+ *--pBuffer = quint8(((node & 0x7f) | 0x80));
+ node >>= 7;
+ }
+ elem.mValue += pBuffer;
+ }
+ return elem;
+}
+
+QDateTime QAsn1Element::toDateTime() const
+{
+ if (mValue.endsWith('Z')) {
+ if (mType == UtcTimeType && mValue.size() == 13)
+ return QDateTime(QDate(2000 + mValue.mid(0, 2).toInt(),
+ mValue.mid(2, 2).toInt(),
+ mValue.mid(4, 2).toInt()),
+ QTime(mValue.mid(6, 2).toInt(),
+ mValue.mid(8, 2).toInt(),
+ mValue.mid(10, 2).toInt()),
+ Qt::UTC);
+ else if (mType == GeneralizedTimeType && mValue.size() == 15)
+ return QDateTime(QDate(mValue.mid(0, 4).toInt(),
+ mValue.mid(4, 2).toInt(),
+ mValue.mid(6, 2).toInt()),
+ QTime(mValue.mid(8, 2).toInt(),
+ mValue.mid(10, 2).toInt(),
+ mValue.mid(12, 2).toInt()),
+ Qt::UTC);
+ }
+ return QDateTime();
+}
+
+QMultiMap QAsn1Element::toInfo() const
+{
+ QMultiMap info;
+ QAsn1Element elem;
+ QDataStream issuerStream(mValue);
+ while (elem.read(issuerStream) && elem.mType == QAsn1Element::SetType) {
+ QAsn1Element issuerElem;
+ QDataStream setStream(elem.mValue);
+ if (issuerElem.read(setStream) && issuerElem.mType == QAsn1Element::SequenceType) {
+ QVector elems = issuerElem.toVector();
+ if (elems.size() == 2) {
+ const QByteArray key = elems.front().toObjectName();
+ if (!key.isEmpty())
+ info.insert(key, elems.back().toString());
+ }
+ }
+ }
+ return info;
+}
+
+QVector QAsn1Element::toVector() const
+{
+ QVector items;
+ if (mType == SequenceType) {
+ QAsn1Element elem;
+ QDataStream stream(mValue);
+ while (elem.read(stream))
+ items << elem;
+ }
+ return items;
+}
+
+QByteArray QAsn1Element::toObjectId() const
+{
+ QByteArray key;
+ if (mType == ObjectIdentifierType && !mValue.isEmpty()) {
+ quint8 b = mValue[0];
+ key += QByteArray::number(b / 40) + '.' + QByteArray::number (b % 40);
+ unsigned int val = 0;
+ for (int i = 1; i < mValue.size(); ++i) {
+ b = mValue[i];
+ val = (val << 7) | (b & 0x7f);
+ if (!(b & 0x80)) {
+ key += '.' + QByteArray::number(val);
+ val = 0;
+ }
+ }
+ }
+ return key;
+}
+
+QByteArray QAsn1Element::toObjectName() const
+{
+ QByteArray key = toObjectId();
+ return oidNameMap->value(key, key);
+}
+
+QString QAsn1Element::toString() const
+{
+ if (mType == PrintableStringType || mType == TeletexStringType)
+ return QString::fromLatin1(mValue, mValue.size());
+ if (mType == Utf8StringType)
+ return QString::fromUtf8(mValue, mValue.size());
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreenpageflipper.h b/src/network/ssl/qasn1element_p.h
similarity index 51%
rename from src/gui/kernel/qplatformscreenpageflipper.h
rename to src/network/ssl/qasn1element_p.h
index 232e37d24a..6b3179ac35 100644
--- a/src/gui/kernel/qplatformscreenpageflipper.h
+++ b/src/network/ssl/qasn1element_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Jeremy Lainé
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -39,54 +39,78 @@
**
****************************************************************************/
-#ifndef QPLATFORMSCREENPAGEFLIPPER_H
-#define QPLATFORMSCREENPAGEFLIPPER_H
+
+#ifndef QASN1ELEMENT_P_H
+#define QASN1ELEMENT_P_H
//
// W A R N I N G
// -------------
//
-// This file is part of the QPA API and is not meant to be used
-// in applications. Usage of this API may make your code
-// source and binary incompatible with future versions of Qt.
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
//
-#include
+#include
+#include
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QPlatformScreenBuffer {
-public:
- QPlatformScreenBuffer();
- virtual ~QPlatformScreenBuffer();
-
- bool isDestroyed() const;
- bool isReady() const;
-
- virtual void aboutToBeDisplayed();
- virtual void displayed();
- virtual void release() = 0;
-
- virtual void *handle() const = 0;
-
-protected:
- bool m_destroyed;
- bool m_ready;
-};
-
-class Q_GUI_EXPORT QPlatformScreenPageFlipper : public QObject
+class Q_AUTOTEST_EXPORT QAsn1Element
{
- Q_OBJECT
public:
- explicit QPlatformScreenPageFlipper(QObject *parent = 0);
+ enum ElementType {
+ // universal
+ IntegerType = 0x02,
+ BitStringType = 0x03,
+ OctetStringType = 0x04,
+ NullType = 0x05,
+ ObjectIdentifierType = 0x06,
+ Utf8StringType = 0x0c,
+ PrintableStringType = 0x13,
+ TeletexStringType = 0x14,
+ UtcTimeType = 0x17,
+ GeneralizedTimeType = 0x18,
+ SequenceType = 0x30,
+ SetType = 0x31,
- virtual bool displayBuffer(QPlatformScreenBuffer *) = 0;
+ // application
+ Rfc822NameType = 0x81,
+ DnsNameType = 0x82,
-Q_SIGNALS:
- void bufferDisplayed(QPlatformScreenBuffer *);
- void bufferReleased(QPlatformScreenBuffer *);
+ // context specific
+ Context0Type = 0xA0,
+ Context3Type = 0xA3
+ };
+
+ explicit QAsn1Element(quint8 type = 0, const QByteArray &value = QByteArray());
+ bool read(QDataStream &data);
+ bool read(const QByteArray &data);
+ void write(QDataStream &data) const;
+
+ static QAsn1Element fromInteger(unsigned int val);
+ static QAsn1Element fromVector(const QVector &items);
+ static QAsn1Element fromObjectId(const QByteArray &id);
+
+ QDateTime toDateTime() const;
+ QMultiMap toInfo() const;
+ QVector toVector() const;
+ QByteArray toObjectId() const;
+ QByteArray toObjectName() const;
+ QString toString() const;
+
+ quint8 type() const { return mType; }
+ QByteArray value() const { return mValue; }
+
+private:
+ quint8 mType;
+ QByteArray mValue;
};
+Q_DECLARE_TYPEINFO(QAsn1Element, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-#endif // QPLATFORMSCREENPAGEFLIPPER_H
+#endif
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 47ea3343ea..bae78f4347 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -122,6 +122,7 @@
#include "qsslcertificate.h"
#include "qsslcertificate_p.h"
+#include "qasn1element_p.h"
#include "qsslkey_p.h"
#include
@@ -641,6 +642,155 @@ static const char *certificate_blacklist[] = {
0
};
+bool QSslCertificatePrivate::parse(const QByteArray &data)
+{
+#ifndef QT_NO_OPENSSL
+ Q_UNUSED(data);
+#else
+ QAsn1Element root;
+
+ QDataStream dataStream(data);
+ if (!root.read(dataStream) || root.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QDataStream rootStream(root.value());
+ QAsn1Element cert;
+ if (!cert.read(rootStream) || cert.type() != QAsn1Element::SequenceType)
+ return false;
+
+ // version or serial number
+ QAsn1Element elem;
+ QDataStream certStream(cert.value());
+ if (!elem.read(certStream))
+ return false;
+
+ if (elem.type() == QAsn1Element::Context0Type) {
+ QDataStream versionStream(elem.value());
+ if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType)
+ return false;
+
+ versionString = QByteArray::number(elem.value()[0] + 1);
+ if (!elem.read(certStream))
+ return false;
+ } else {
+ versionString = QByteArray::number(1);
+ }
+
+ // serial number
+ if (elem.type() != QAsn1Element::IntegerType)
+ return false;
+
+ QByteArray hexString;
+ hexString.reserve(elem.value().size() * 3);
+ for (int a = 0; a < elem.value().size(); ++a) {
+ const quint8 b = elem.value().at(a);
+ if (b || !hexString.isEmpty()) { // skip leading zeros
+ hexString += QByteArray::number(b, 16).rightJustified(2, '0');
+ hexString += ':';
+ }
+ }
+ hexString.chop(1);
+ serialNumberString = hexString;
+
+ // algorithm ID
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ //qDebug() << "algorithm ID" << elem.type() << elem.length << elem.value().toHex();
+
+ // issuer info
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length());
+ issuerInfo = elem.toInfo();
+
+ // validity period
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QDataStream validityStream(elem.value());
+ if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType))
+ return false;
+
+ notValidBefore = elem.toDateTime();
+ if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType))
+ return false;
+
+ notValidAfter = elem.toDateTime();
+
+ // subject name
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length());
+ subjectInfo = elem.toInfo();
+ subjectMatchesIssuer = issuerDer == subjectDer;
+
+ // public key
+ qint64 keyStart = certStream.device()->pos();
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ publicKeyDerData.resize(certStream.device()->pos() - keyStart);
+ QDataStream keyStream(elem.value());
+ if (!elem.read(keyStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+
+ // key algorithm
+ if (!elem.read(elem.value()) || elem.type() != QAsn1Element::ObjectIdentifierType)
+ return false;
+
+ const QByteArray oid = elem.toObjectId();
+ if (oid == "1.2.840.113549.1.1.1")
+ publicKeyAlgorithm = QSsl::Rsa;
+ else if (oid == "1.2.840.10040.4.1")
+ publicKeyAlgorithm = QSsl::Dsa;
+ else
+ publicKeyAlgorithm = QSsl::Opaque;
+
+ certStream.device()->seek(keyStart);
+ certStream.readRawData(publicKeyDerData.data(), publicKeyDerData.size());
+
+ // extensions
+ while (elem.read(certStream)) {
+ if (elem.type() == QAsn1Element::Context3Type) {
+ if (elem.read(elem.value()) && elem.type() == QAsn1Element::SequenceType) {
+ QDataStream extStream(elem.value());
+ while (elem.read(extStream) && elem.type() == QAsn1Element::SequenceType) {
+ QAsn1Element oidElem, valElem;
+ QDataStream seqStream(elem.value());
+ if (oidElem.read(seqStream) && oidElem.type() == QAsn1Element::ObjectIdentifierType &&
+ valElem.read(seqStream) && valElem.type() == QAsn1Element::OctetStringType) {
+ // alternative name
+ if (oidElem.toObjectId() == QByteArray("2.5.29.17")) {
+ QAsn1Element sanElem;
+ if (sanElem.read(valElem.value()) && sanElem.type() == QAsn1Element::SequenceType) {
+ QDataStream nameStream(sanElem.value());
+ QAsn1Element nameElem;
+ while (nameElem.read(nameStream)) {
+ if (nameElem.type() == QAsn1Element::Rfc822NameType) {
+ subjectAlternativeNames.insert(QSsl::EmailEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size()));
+ } else if (nameElem.type() == QAsn1Element::DnsNameType) {
+ subjectAlternativeNames.insert(QSsl::DnsEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ derData = data.left(dataStream.device()->pos());
+ null = false;
+
+#endif // QT_NO_OPENSSL
+ return true;
+}
+
bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
{
for (int a = 0; certificate_blacklist[a] != 0; a++) {
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index 4bee9edcb9..472553c30c 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -69,6 +69,11 @@ struct X509_EXTENSION;
struct ASN1_OBJECT;
#endif
+#ifdef Q_OS_WINRT
+#include
+#include
+#endif
+
QT_BEGIN_NAMESPACE
// forward declaration
@@ -99,9 +104,18 @@ public:
QDateTime notValidAfter;
QDateTime notValidBefore;
+#ifdef QT_NO_OPENSSL
+ bool subjectMatchesIssuer;
+ QSsl::KeyAlgorithm publicKeyAlgorithm;
+ QByteArray publicKeyDerData;
+ QMultiMap subjectAlternativeNames;
+
+ QByteArray derData;
+#endif
X509 *x509;
void init(const QByteArray &data, QSsl::EncodingFormat format);
+ bool parse(const QByteArray &data);
static QByteArray asn1ObjectId(ASN1_OBJECT *object);
static QByteArray asn1ObjectName(ASN1_OBJECT *object);
@@ -117,6 +131,12 @@ public:
friend class QSslSocketBackendPrivate;
QAtomicInt ref;
+
+#ifdef Q_OS_WINRT
+ Microsoft::WRL::ComPtr certificate;
+
+ static QSslCertificate QSslCertificate_from_Certificate(ABI::Windows::Security::Cryptography::Certificates::ICertificate *iCertificate);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp
new file mode 100644
index 0000000000..391ee6f7f9
--- /dev/null
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include "qsslcertificate.h"
+#include "qsslcertificate_p.h"
+#include "qsslkey.h"
+#include "qsslkey_p.h"
+#include "qsslcertificateextension.h"
+#include "qsslcertificateextension_p.h"
+
+QT_BEGIN_NAMESPACE
+
+bool QSslCertificate::operator==(const QSslCertificate &other) const
+{
+ if (d == other.d)
+ return true;
+ if (d->null && other.d->null)
+ return true;
+ return d->derData == other.d->derData;
+}
+
+bool QSslCertificate::isNull() const
+{
+ return d->null;
+}
+
+bool QSslCertificate::isSelfSigned() const
+{
+ if (d->null)
+ return false;
+
+ qWarning("QSslCertificate::isSelfSigned: This function does not check, whether the certificate \
+ is actually signed. It just checks whether issuer and subject are identical");
+ return d->subjectMatchesIssuer;
+}
+
+QByteArray QSslCertificate::version() const
+{
+ return d->versionString;
+}
+
+QByteArray QSslCertificate::serialNumber() const
+{
+ return d->serialNumberString;
+}
+
+QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
+{
+ return issuerInfo(QSslCertificatePrivate::subjectInfoToString(info));
+}
+
+QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
+{
+ return d->issuerInfo.values(attribute);
+}
+
+QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
+{
+ return subjectInfo(QSslCertificatePrivate::subjectInfoToString(info));
+}
+
+QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
+{
+ return d->subjectInfo.values(attribute);
+}
+
+QList QSslCertificate::subjectInfoAttributes() const
+{
+ return d->subjectInfo.uniqueKeys();
+}
+
+QList QSslCertificate::issuerInfoAttributes() const
+{
+ return d->issuerInfo.uniqueKeys();
+}
+
+QMultiMap QSslCertificate::subjectAlternativeNames() const
+{
+ return d->subjectAlternativeNames;
+}
+
+QDateTime QSslCertificate::effectiveDate() const
+{
+ return d->notValidBefore;
+}
+
+QDateTime QSslCertificate::expiryDate() const
+{
+ return d->notValidAfter;
+}
+
+#ifndef Q_OS_WINRT // implemented in qsslcertificate_winrt.cpp
+Qt::HANDLE QSslCertificate::handle() const
+{
+ Q_UNIMPLEMENTED();
+ return 0;
+}
+#endif
+
+QSslKey QSslCertificate::publicKey() const
+{
+ QSslKey key;
+ key.d->type = QSsl::PublicKey;
+ if (d->publicKeyAlgorithm != QSsl::Opaque) {
+ key.d->algorithm = d->publicKeyAlgorithm;
+ key.d->decodeDer(d->publicKeyDerData);
+ }
+ return key;
+}
+
+QList QSslCertificate::extensions() const
+{
+ Q_UNIMPLEMENTED();
+ return QList();
+}
+
+#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
+#define ENDCERTSTRING "-----END CERTIFICATE-----"
+
+QByteArray QSslCertificate::toPem() const
+{
+ QByteArray array = toDer();
+
+ // Convert to Base64 - wrap at 64 characters.
+ array = array.toBase64();
+ QByteArray tmp;
+ for (int i = 0; i <= array.size() - 64; i += 64) {
+ tmp += QByteArray::fromRawData(array.data() + i, 64);
+ tmp += '\n';
+ }
+ if (int remainder = array.size() % 64) {
+ tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder);
+ tmp += '\n';
+ }
+
+ return BEGINCERTSTRING "\n" + tmp + ENDCERTSTRING "\n";
+}
+
+QByteArray QSslCertificate::toDer() const
+{
+ return d->derData;
+}
+
+QString QSslCertificate::toText() const
+{
+ Q_UNIMPLEMENTED();
+ return QString();
+}
+
+void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
+{
+ if (!data.isEmpty()) {
+ QList certs = (format == QSsl::Pem)
+ ? certificatesFromPem(data, 1)
+ : certificatesFromDer(data, 1);
+ if (!certs.isEmpty()) {
+ *this = *certs.first().d;
+ }
+ }
+}
+
+static bool matchLineFeed(const QByteArray &pem, int *offset)
+{
+ char ch = 0;
+
+ // ignore extra whitespace at the end of the line
+ while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ')
+ ++*offset;
+
+ if (ch == '\n') {
+ *offset += 1;
+ return true;
+ }
+ if (ch == '\r' && pem.size() > (*offset + 1) && pem.at(*offset + 1) == '\n') {
+ *offset += 2;
+ return true;
+ }
+ return false;
+}
+
+QList QSslCertificatePrivate::certificatesFromPem(const QByteArray &pem, int count)
+{
+ QList certificates;
+ int offset = 0;
+ while (count == -1 || certificates.size() < count) {
+ int startPos = pem.indexOf(BEGINCERTSTRING, offset);
+ if (startPos == -1)
+ break;
+ startPos += sizeof(BEGINCERTSTRING) - 1;
+ if (!matchLineFeed(pem, &startPos))
+ break;
+
+ int endPos = pem.indexOf(ENDCERTSTRING, startPos);
+ if (endPos == -1)
+ break;
+
+ offset = endPos + sizeof(ENDCERTSTRING) - 1;
+ if (offset < pem.size() && !matchLineFeed(pem, &offset))
+ break;
+
+ QByteArray decoded = QByteArray::fromBase64(
+ QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
+ certificates << certificatesFromDer(decoded, 1);;
+ }
+
+ return certificates;
+}
+
+QList QSslCertificatePrivate::certificatesFromDer(const QByteArray &der, int count)
+{
+ QList certificates;
+
+ QByteArray data = der;
+ while (count == -1 || certificates.size() < count) {
+ QSslCertificate cert;
+ if (!cert.d->parse(data))
+ break;
+
+ certificates << cert;
+ data.remove(0, cert.d->derData.size());
+ }
+
+ return certificates;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcertificate_winrt.cpp b/src/network/ssl/qsslcertificate_winrt.cpp
index 9c857a6787..6f4bb80cf9 100644
--- a/src/network/ssl/qsslcertificate_winrt.cpp
+++ b/src/network/ssl/qsslcertificate_winrt.cpp
@@ -39,153 +39,76 @@
**
****************************************************************************/
-
-
-#include "qsslcertificate.h"
#include "qsslcertificate_p.h"
-QT_BEGIN_NAMESPACE
+#include
-bool QSslCertificate::operator==(const QSslCertificate &other) const
-{
- if (d == other.d)
- return true;
- return false;
-}
+#include
+#include
+#include
+#include
-bool QSslCertificate::isNull() const
-{
- Q_UNIMPLEMENTED();
- return true;
-}
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Security::Cryptography;
+using namespace ABI::Windows::Security::Cryptography::Certificates;
+using namespace ABI::Windows::Storage::Streams;
-bool QSslCertificate::isSelfSigned() const
-{
- Q_UNIMPLEMENTED();
- return true;
-}
+QT_USE_NAMESPACE
-QByteArray QSslCertificate::version() const
+struct SslCertificateGlobal
{
- Q_UNIMPLEMENTED();
- return QByteArray();
-}
+ SslCertificateGlobal() {
+ HRESULT hr;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Certificates_Certificate).Get(),
+ &certificateFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(),
+ &bufferFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
-QByteArray QSslCertificate::serialNumber() const
-{
- Q_UNIMPLEMENTED();
- return QByteArray();
-}
+ ComPtr certificateFactory;
+ ComPtr bufferFactory;
+};
+Q_GLOBAL_STATIC(SslCertificateGlobal, g)
-QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
+QSslCertificate QSslCertificatePrivate::QSslCertificate_from_Certificate(ICertificate *iCertificate)
{
- Q_UNIMPLEMENTED();
- return QStringList();
-}
+ Q_ASSERT(iCertificate);
+ ComPtr buffer;
+ HRESULT hr = iCertificate->GetCertificateBlob(&buffer);
+ RETURN_IF_FAILED("Could not obtain certification blob", return QSslCertificate());
+ ComPtr byteAccess;
+ hr = buffer.As(&byteAccess);
+ RETURN_IF_FAILED("Could not obtain byte access to buffer", return QSslCertificate());
+ char *data;
+ hr = byteAccess->Buffer(reinterpret_cast(&data));
+ RETURN_IF_FAILED("Could not obtain buffer data", return QSslCertificate());
+ UINT32 size;
+ hr = buffer->get_Length(&size);
+ RETURN_IF_FAILED("Could not obtain buffer length ", return QSslCertificate());
+ QByteArray der(data, size);
-QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
-{
- Q_UNIMPLEMENTED();
- return QStringList();
-}
+ QSslCertificate certificate;
+ certificate.d->null = false;
+ certificate.d->certificate = iCertificate;
-QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
-{
- Q_UNIMPLEMENTED();
- return QStringList();
-}
-
-QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
-{
- Q_UNIMPLEMENTED();
- return QStringList();
-}
-
-QList QSslCertificate::subjectInfoAttributes() const
-{
- Q_UNIMPLEMENTED();
- return QList();
-}
-
-QList QSslCertificate::issuerInfoAttributes() const
-{
- Q_UNIMPLEMENTED();
- return QList();
-}
-
-QMultiMap QSslCertificate::subjectAlternativeNames() const
-{
- Q_UNIMPLEMENTED();
- return QMultiMap();
-}
-
-QDateTime QSslCertificate::effectiveDate() const
-{
- Q_UNIMPLEMENTED();
- return QDateTime();
-}
-
-QDateTime QSslCertificate::expiryDate() const
-{
- Q_UNIMPLEMENTED();
- return QDateTime();
+ return certificatesFromDer(der, 1).at(0);
}
Qt::HANDLE QSslCertificate::handle() const
{
- Q_UNIMPLEMENTED();
- return 0;
-}
+ if (!d->certificate) {
+ HRESULT hr;
+ ComPtr buffer;
+ hr = g->bufferFactory->CreateFromByteArray(d->derData.length(), (BYTE *)d->derData.data(), &buffer);
+ RETURN_IF_FAILED("Failed to create the certificate data buffer", return 0);
-QSslKey QSslCertificate::publicKey() const
-{
- Q_UNIMPLEMENTED();
- return QSslKey();
-}
+ hr = g->certificateFactory->CreateCertificate(buffer.Get(), &d->certificate);
+ RETURN_IF_FAILED("Failed to create the certificate handle from the data buffer", return 0);
+ }
-QList QSslCertificate::extensions() const
-{
- Q_UNIMPLEMENTED();
- return QList();
+ return d->certificate.Get();
}
-
-QByteArray QSslCertificate::toPem() const
-{
- Q_UNIMPLEMENTED();
- return QByteArray();
-}
-
-QByteArray QSslCertificate::toDer() const
-{
- Q_UNIMPLEMENTED();
- return QByteArray();
-}
-
-QString QSslCertificate::toText() const
-{
- Q_UNIMPLEMENTED();
- return QString();
-}
-
-void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
-{
- Q_UNIMPLEMENTED();
-}
-
-QList