diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 02e55d847eb..02194aa0b75 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -76,8 +76,8 @@ sub normalizePath { # set output basedir to be where ever syncqt is run from our $out_basedir = getcwd(); normalizePath(\$out_basedir); +our $build_basedir = $out_basedir; our $basedir; -our $quoted_basedir; # Make sure we use Windows line endings for chomp and friends on Windows. $INPUT_RECORD_SEPARATOR = "\r\n" if ($^O eq "msys"); @@ -129,6 +129,7 @@ sub showUsage print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n"; print " -minimal Do not create CamelCase headers (default: " . ($minimal ? "yes" : "no") . ")\n"; print " -outdir Specify output directory for sync (default: $out_basedir)\n"; + print " -builddir Specify build directory for sync (default: $build_basedir)\n"; print " -version Specify the module's version (default: detect from qglobal.h)\n"; print " -quiet Only report problems, not activity (same as -verbose 0)\n"; print " -v, -verbose Sets the verbosity level (max. 4) (default: $verbose_level)\n"; @@ -648,17 +649,16 @@ sub listSubdirs { ###################################################################### # Syntax: loadSyncProfile() # -# Purpose: Locates the sync.profile. -# Returns: Hashmap of module name -> directory. +# Purpose: Loads the sync.profile. ###################################################################### sub loadSyncProfile { - my ($srcbase, $outbase) = @_; if ($verbose_level) { - print(" = $$srcbase \n"); - print(" = $$outbase \n"); + print(" = $basedir \n"); + print(" = $build_basedir \n"); + print(" = $out_basedir \n"); } - my $syncprofile = "$$srcbase/sync.profile"; + my $syncprofile = "$basedir/sync.profile"; my $result; unless ($result = do "$syncprofile") { die "syncqt couldn't parse $syncprofile: $@" if $@; @@ -670,13 +670,12 @@ sub loadSyncProfile { $reverse_classnames{$cn} = $fn; } } - - return $result; } sub basePrettify { my ($arg) = @_; $$arg =~ s,^\Q$basedir\E,,; + $$arg =~ s,^\Q$build_basedir\E,,; $$arg =~ s,^\Q$out_basedir\E,,; } @@ -686,6 +685,11 @@ sub cleanPath { return $arg; } +###################################################################### +# Syntax: locateSyncProfile() +# +# Purpose: Locates the sync.profile. +###################################################################### sub locateSyncProfile { my ($directory) = @_; @@ -724,11 +728,10 @@ sub globosort($$) { } # check if this is an in-source build, and if so use that as the basedir too -$basedir = locateSyncProfile($out_basedir); +$basedir = locateSyncProfile($build_basedir); if ($basedir) { $basedir = dirname($basedir) ; normalizePath(\$basedir); - $quoted_basedir = "\Q$basedir"; } # -------------------------------------------------------------------- @@ -750,6 +753,9 @@ while ( @ARGV ) { } elsif($arg eq "-o" || $arg eq "-outdir") { $var = "output"; $val = shift @ARGV; + } elsif($arg eq "-builddir") { + $var = "build"; + $val = shift @ARGV; } elsif($arg eq "-showonly" || $arg eq "-remove-stale" || $arg eq "-windows" || $arg eq "-relative" || $arg eq "-check-includes") { $var = substr($arg, 1); @@ -796,7 +802,6 @@ while ( @ARGV ) { die "Could not find a sync.profile for '$arg'\n" if (!$basedir); $basedir = dirname($basedir); normalizePath(\$basedir); - $quoted_basedir = "\Q$basedir"; $var = "ignore"; } @@ -877,6 +882,16 @@ while ( @ARGV ) { $out_basedir = $outdir; } normalizePath(\$out_basedir); + } elsif ($var eq "build") { + my $outdir = $val; + if (checkRelative($outdir)) { + $build_basedir = getcwd(); + chomp $build_basedir; + $build_basedir .= "/" . $outdir; + } else { + $build_basedir = $outdir; + } + normalizePath(\$build_basedir); } } @@ -892,7 +907,7 @@ our @ignore_for_qt_module_check = (); our %inject_headers = (); # load the module's sync.profile here, before we can -loadSyncProfile(\$basedir, \$out_basedir); +loadSyncProfile(); @modules_to_sync = keys(%modules) if($#modules_to_sync == -1); @@ -941,7 +956,7 @@ foreach my $lib (@modules_to_sync) { for my $p (keys %inject_headers) { next unless ($p =~ /^\Q$dir\E(\/|$)/); my $sp = $p; - $sp =~ s,^\Q$basedir\E/,$out_basedir/,; + $sp =~ s,^\Q$basedir\E/,$build_basedir/,; for my $n (@{$inject_headers{$p}}) { $injections{$sp."/".$n} = 1; } @@ -1039,7 +1054,7 @@ foreach my $lib (@modules_to_sync) { my $requires; my $iheader_src = $subdir . "/" . $header; my $iheader = $iheader_src; - $iheader =~ s/^\Q$basedir\E/$out_basedir/ if ($shadow); + $iheader =~ s/^\Q$basedir\E/$build_basedir/ if ($shadow); if ($check_includes) { # We need both $public_header and $private_header because QPA headers count as neither my $private_header = !$public_header && !$qpa_header diff --git a/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.cpp b/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.cpp deleted file mode 100644 index 2dde2914a23..00000000000 --- a/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -int main(int, char**) -{ - D3D11_QUERY_DATA_TIMESTAMP_DISJOINT qdtd; - (void)qdtd; - return 0; -} diff --git a/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.pro b/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.pro deleted file mode 100644 index f1e530ab6e6..00000000000 --- a/config.tests/win/angle_d3d11_qdtd/angle_d3d11_qdtd.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES = angle_d3d11_qdtd.cpp -CONFIG -= qt -CONFIG += console diff --git a/config_help.txt b/config_help.txt index 5c57e30d631..4be797cc6bd 100644 --- a/config_help.txt +++ b/config_help.txt @@ -126,6 +126,9 @@ Build options: -sanitize {address|thread|memory|undefined} Instrument with the specified compiler sanitizer. + Note that some sanitizers cannot be combined; + for example, -sanitize address cannot be combined with + -sanitize thread. -c++std .... Select C++ standard [c++1z/c++14/c++11] (Not supported with MSVC) diff --git a/dist/changes-5.9.4 b/dist/changes-5.9.4 index 0bb768424fa..f0cc6007c22 100644 --- a/dist/changes-5.9.4 +++ b/dist/changes-5.9.4 @@ -65,6 +65,12 @@ QtCore QtNetwork --------- + - Bearer Management: + * [QTBUG-40332] The nativewifi (Windows) bearer plugin was determined + to be causing network interference in the form of system-wide higher + latency and has been disabled. The CoreWlan (macOS) plugin has also + been disabled. + - QUdpSocket: * [QTBUG-64718] Fixed a regression from Qt 5.9.3 caused by an apparent Win32 API quirk we triggered when using readDatagram(), resulting in diff --git a/doc/global/macros.qdocconf b/doc/global/macros.qdocconf index 5544da425a9..dbf8c5cc6a6 100644 --- a/doc/global/macros.qdocconf +++ b/doc/global/macros.qdocconf @@ -18,6 +18,7 @@ macro.QA = "\\e{Qt Assistant}" macro.QD = "\\e{Qt Designer}" macro.QL = "\\e{Qt Linguist}" macro.QQV = "\\e{Qt QML Viewer}" +macro.QtVersion = "$QT_VERSION" macro.param = "\\e" macro.raisedaster.HTML = "*" macro.rarrow.HTML = "→" diff --git a/examples/corelib/ipc/ipc.pro b/examples/corelib/ipc/ipc.pro index 101552cea96..68c88d75aad 100644 --- a/examples/corelib/ipc/ipc.pro +++ b/examples/corelib/ipc/ipc.pro @@ -3,4 +3,8 @@ requires(qtHaveModule(widgets)) TEMPLATE = subdirs qtConfig(sharedmemory): SUBDIRS = sharedmemory -qtHaveModule(network): SUBDIRS += localfortuneserver localfortuneclient +qtHaveModule(network) { + QT_FOR_CONFIG += network + + qtConfig(localserver): SUBDIRS += localfortuneserver localfortuneclient +} diff --git a/examples/gui/rasterwindow/rasterwindow.cpp b/examples/gui/rasterwindow/rasterwindow.cpp index 68d1d7f524b..3eacd201455 100644 --- a/examples/gui/rasterwindow/rasterwindow.cpp +++ b/examples/gui/rasterwindow/rasterwindow.cpp @@ -111,6 +111,7 @@ void RasterWindow::renderNow() painter.fillRect(0, 0, width(), height(), Qt::white); render(&painter); + painter.end(); m_backingStore->endPaint(); m_backingStore->flush(rect); diff --git a/examples/opengl/hellogles3/main.cpp b/examples/opengl/hellogles3/main.cpp index a6c63986280..29b3b9617ab 100644 --- a/examples/opengl/hellogles3/main.cpp +++ b/examples/opengl/hellogles3/main.cpp @@ -64,6 +64,8 @@ int main(int argc, char *argv[]) { + QGuiApplication app(argc, argv); + QSurfaceFormat fmt; fmt.setDepthBufferSize(24); @@ -79,8 +81,6 @@ int main(int argc, char *argv[]) QSurfaceFormat::setDefaultFormat(fmt); - QGuiApplication app(argc, argv); - GLWindow glWindow; glWindow.showMaximized(); diff --git a/examples/widgets/doc/src/validators.qdoc b/examples/widgets/doc/src/validators.qdoc index bbb2e5f7b6b..9d82f3f5750 100644 --- a/examples/widgets/doc/src/validators.qdoc +++ b/examples/widgets/doc/src/validators.qdoc @@ -28,7 +28,6 @@ /*! \example widgets/validators \title Validators Example - \ingroup examples-widgets \brief The Validators example shows the signal emission behavior of input validators. diff --git a/examples/widgets/tutorials/notepad/notepad.cpp b/examples/widgets/tutorials/notepad/notepad.cpp index b4f6cf7f8f7..44d8597cb7d 100644 --- a/examples/widgets/tutorials/notepad/notepad.cpp +++ b/examples/widgets/tutorials/notepad/notepad.cpp @@ -52,8 +52,15 @@ #include #include #include +#if defined(QT_PRINTSUPPORT_LIB) +#include +#if QT_CONFIG(printer) +#if QT_CONFIG(printdialog) #include +#endif // QT_CONFIG(printdialog) #include +#endif // QT_CONFIG(printer) +#endif // QT_PRINTSUPPORT_LIB #include #include @@ -136,11 +143,15 @@ void Notepad::on_actionSave_as_triggered() void Notepad::on_actionPrint_triggered() { +#if QT_CONFIG(printer) QPrinter printDev; +#if QT_CONFIG(printdialog) QPrintDialog dialog(&printDev, this); if (dialog.exec() == QDialog::Rejected) return; +#endif // QT_CONFIG(printdialog) ui->textEdit->print(&printDev); +#endif // QT_CONFIG(printer) } void Notepad::on_actionExit_triggered() diff --git a/examples/widgets/tutorials/notepad/notepad.pro b/examples/widgets/tutorials/notepad/notepad.pro index a552dacf002..6451f22735e 100644 --- a/examples/widgets/tutorials/notepad/notepad.pro +++ b/examples/widgets/tutorials/notepad/notepad.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = notepad -QT += printsupport +qtHaveModule(printsupport): QT += printsupport requires(qtConfig(fontdialog)) SOURCES += \ diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf index 1a38f70205c..b7d2eecc820 100644 --- a/mkspecs/common/msvc-desktop.conf +++ b/mkspecs/common/msvc-desktop.conf @@ -15,7 +15,7 @@ MAKEFILE_GENERATOR = MSVC.NET QMAKE_PLATFORM = win32 QMAKE_COMPILER = msvc -CONFIG += incremental flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe +CONFIG += flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe DEFINES += UNICODE _UNICODE WIN32 QMAKE_COMPILER_DEFINES += _WIN32 contains(QMAKE_TARGET.arch, x86_64) { @@ -23,6 +23,7 @@ contains(QMAKE_TARGET.arch, x86_64) { QMAKE_COMPILER_DEFINES += _WIN64 } +QMAKE_CFLAGS_OPTIMIZE_DEBUG = -Od QMAKE_CFLAGS_OPTIMIZE = -O2 QMAKE_CFLAGS_OPTIMIZE_SIZE = -O1 @@ -94,7 +95,8 @@ QMAKE_EXTENSION_SHLIB = dll QMAKE_PREFIX_STATICLIB = QMAKE_EXTENSION_STATICLIB = lib -QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib ws2_32.lib ole32.lib user32.lib advapi32.lib +QMAKE_LIBS = +QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib ws2_32.lib ole32.lib uuid.lib user32.lib advapi32.lib QMAKE_LIBS_NETWORK = ws2_32.lib QMAKE_LIBS_OPENGL = glu32.lib opengl32.lib gdi32.lib user32.lib QMAKE_LIBS_OPENGL_ES2 = gdi32.lib user32.lib diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf index 9f5da91806b..ccd809abf3a 100644 --- a/mkspecs/common/msvc-version.conf +++ b/mkspecs/common/msvc-version.conf @@ -100,6 +100,11 @@ greaterThan(QMAKE_MSC_VER, 1909) { # API is used in direct2d, but also in multimedia, positioning and sensors. # We can try again with a later version of Visual Studio. # QMAKE_CXXFLAGS_STRICTCXX = -permissive- + # MSVC partially supports the following, but '__cplusplus' definition is set + # as for C++98 until MSVC fully conforms with C++14, see + # https://developercommunity.visualstudio.com/content/problem/139261/msvc-incorrectly-defines-cplusplus.html + # QMAKE_CXXFLAGS_CXX14 = -std:c++14 + # QMAKE_CXXFLAGS_CXX1Z = -std:c++latest } greaterThan(QMAKE_MSC_VER, 1910) { diff --git a/mkspecs/features/android/android_deployment_settings.prf b/mkspecs/features/android/android_deployment_settings.prf index 913ab71412b..e6b2431f9a2 100644 --- a/mkspecs/features/android/android_deployment_settings.prf +++ b/mkspecs/features/android/android_deployment_settings.prf @@ -1,4 +1,4 @@ -contains(TEMPLATE, ".*app"):!build_pass: { +contains(TEMPLATE, ".*app"):!build_pass:!android-embedded { defineReplace(emitString) { return("\"$$replace(1, \\\\, \\\\)\"") diff --git a/mkspecs/features/mac/default_pre.prf b/mkspecs/features/mac/default_pre.prf index e3534561a56..f1a4ca77b27 100644 --- a/mkspecs/features/mac/default_pre.prf +++ b/mkspecs/features/mac/default_pre.prf @@ -58,3 +58,10 @@ QMAKE_XCODE_LIBRARY_SUFFIX_SETTING = QT_LIBRARY_SUFFIX xcode_copy_phase_strip_setting.name = COPY_PHASE_STRIP xcode_copy_phase_strip_setting.value = NO QMAKE_MAC_XCODE_SETTINGS += xcode_copy_phase_strip_setting + +xcode_product_bundle_identifier_setting.name = PRODUCT_BUNDLE_IDENTIFIER +xcode_product_bundle_identifier_setting.value = $$QMAKE_TARGET_BUNDLE_PREFIX +isEmpty(xcode_product_bundle_identifier_setting.value): \ + xcode_product_bundle_identifier_setting.value = "com.yourcompany" +xcode_product_bundle_identifier_setting.value = "$${xcode_product_bundle_identifier_setting.value}.${PRODUCT_NAME:rfc1034identifier}" +QMAKE_MAC_XCODE_SETTINGS += xcode_product_bundle_identifier_setting diff --git a/mkspecs/features/qt_example_installs.prf b/mkspecs/features/qt_example_installs.prf index 668669e4cd7..c9ce926b1a9 100644 --- a/mkspecs/features/qt_example_installs.prf +++ b/mkspecs/features/qt_example_installs.prf @@ -44,19 +44,25 @@ contains(TEMPLATE, .*app): \ for(ex, EXAMPLE_FILES): \ sourcefiles += $$files($$absolute_path($$ex, $$_PRO_FILE_PWD_)) for(res, RESOURCES) { - rfile = $$cat($$absolute_path($$res, $$_PRO_FILE_PWD_), lines) - for(rline, rfile) { + !contains(res, \\.qrc$): \ + next() + rfile = $$absolute_path($$res, $$_PRO_FILE_PWD_) + rpath = $$dirname(rfile) + rcont = $$cat($$rfile, lines) + for (rline, rcont) { resrc = $$replace(rline, ^[ \\t]*]*>([^<]+)[ \\t]*$, \\1) !equals(resrc, $$rline): \ - sourcefiles += $$resrc + sourcefiles += $$absolute_path($$resrc, $$rpath) } } for(res, RC_FILE) { - rfile = $$cat($$absolute_path($$res, $$_PRO_FILE_PWD_), lines) - for(rline, rfile) { + rfile = $$absolute_path($$res, $$_PRO_FILE_PWD_) + rpath = $$dirname(rfile) + rcont = $$cat($$rfile, lines) + for (rline, rcont) { resrc = $$replace(rline, "^\\d+\\s+ICON\\s+[^\"]*\"([^\"]+)\"\$", \\1) !equals(resrc, $$rline): \ - sourcefiles += $$resrc + sourcefiles += $$absolute_path($$resrc, $$rpath) } } sourcefiles += \ diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index c0a8dcc251d..e6a0d97f1a6 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -274,7 +274,7 @@ load(qt_targets) else: \ QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS/raw] QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw] - QMAKE_PKGCONFIG_CFLAGS = -I${includedir}/$$MODULE_INCNAME + QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$QT_MAJOR_VERSION ") QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION) for(i, MODULE_DEPENDS): \ diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 931a26f5ae6..62b88c6fe2f 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -22,7 +22,8 @@ load(qt_build_paths) for(mod, MODULE_INCNAME): \ QMAKE_SYNCQT += -module $$mod QMAKE_SYNCQT += \ - -version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR + -version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) \ + -builddir $$system_quote($$shadowed($$MODULE_BASE_INDIR)) $$MODULE_SYNCQT_DIR !silent: message($$QMAKE_SYNCQT) system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT") diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index 3e1537dde0a..8d51c9d028c 100644 --- a/mkspecs/features/testcase.prf +++ b/mkspecs/features/testcase.prf @@ -44,7 +44,7 @@ unix { $${type}.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET) } else { # Windows - !isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = $${TEST_TARGET_DIR}$${QMAKE_DIR_SEP} + !isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = $$shell_path($$TEST_TARGET_DIR)$${QMAKE_DIR_SEP} $${type}.commands += $${TEST_TARGET_DIR}$(TARGET) } diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index d7280477655..9f366e08b86 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -10,14 +10,19 @@ load(device_config) include(../common/gcc-base.conf) include(../common/g++-base.conf) +include(../common/angle.conf) +include(../common/windows-vulkan.conf) # modifications to gcc-base.conf and g++-base.conf MAKEFILE_GENERATOR = MINGW QMAKE_PLATFORM = win32 mingw CONFIG += debug_and_release debug_and_release_target precompile_header -DEFINES += UNICODE _UNICODE -QMAKE_COMPILER_DEFINES += __GNUC__ WIN32 +DEFINES += UNICODE _UNICODE WIN32 +QMAKE_COMPILER_DEFINES += __GNUC__ _WIN32 +# can't add 'DEFINES += WIN64' and 'QMAKE_COMPILER_DEFINES += _WIN64' defines for +# x86_64 platform similar to 'msvc-desktop.conf' toolchain, because, unlike for MSVC, +# 'QMAKE_TARGET.arch' is inherently unavailable. QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_LEX = flex @@ -28,10 +33,10 @@ QMAKE_CFLAGS += -fno-keep-inline-dllexport QMAKE_CFLAGS_WARN_ON += -Wextra QMAKE_CFLAGS_SSE2 += -mstackrealign -QMAKE_CFLAGS_AESNI = -maes -QMAKE_CFLAGS_SHANI = -msha QMAKE_CXX = $${CROSS_COMPILE}g++ +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS +QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON QMAKE_CXXFLAGS_RTTI_ON = -frtti QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads @@ -81,8 +86,4 @@ QMAKE_STRIPFLAGS_LIB += --strip-unneeded QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_NM = $${CROSS_COMPILE}nm -P -include(../common/angle.conf) -include(../common/windows-vulkan.conf) -include(../common/gcc-base.conf) - load(qt_config) diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index a539bfba726..6acb07f8aa5 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -4,7 +4,7 @@ # Written for Intel C++ Compiler on Windows / icl 16.0 or higher # -# Use the Microsoft (R) C/C++ Optimizing Compiler configuration, +# Use the Microsoft C/C++ Optimizing Compiler configuration, # since ICC on Windows pretends to be MSVC include(../common/msvc-desktop.conf) @@ -13,11 +13,14 @@ include(../common/msvc-desktop.conf) QMAKE_COMPILER += intel_icl +QMAKE_CFLAGS_OPTIMIZE_FULL = -O3 + QMAKE_CC = icl -QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809,3373 -QMAKE_CFLAGS_WARN_ON = -W3 /Qwd673 -QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673 -QMAKE_CFLAGS_DEBUG = -Od -Zi -MDd +QMAKE_CFLAGS = -nologo -Zc:wchar_t -Qprec -Zm200 -Qdiag-disable:1744,1738,809,3373 +QMAKE_CFLAGS_WARN_ON = -W3 -Qdiag-disable:673 +QMAKE_CFLAGS_WARN_OFF = -W0 -Qdiag-disable:673 +QMAKE_CFLAGS_DEBUG = $$QMAKE_CFLAGS_OPTIMIZE_DEBUG -Zi -MDd +QMAKE_CFLAGS_UTF8_SOURCE = -Qoption,cpp,--unicode_source_kind,UTF-8 QMAKE_CFLAGS_LTCG = -Qipo QMAKE_CFLAGS_DISABLE_LTCG = -Qno-ipo @@ -46,7 +49,7 @@ QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF QMAKE_CXXFLAGS_CXX11 = -Qstd=c++11 # ICC supports the following but Qt won't compile #QMAKE_CXXFLAGS_CXX14 = -Qstd=c++14 -#QMAKE_CXXFLAGS_CXX1Z = -Qstd=c++1z +#QMAKE_CXXFLAGS_CXX1Z = -Qstd=c++17 QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG @@ -55,7 +58,4 @@ QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_LIB = xilib /NOLOGO -include(../common/angle.conf) -include(../common/windows-vulkan.conf) - load(qt_config) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 8b7d1b0853f..cc3b73418be 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2359,6 +2359,9 @@ Specifies the \l{All Modules}{Qt modules} that are used by your project. For the value to add for each module, see the module documentation. + At the C++ implementation level, using a Qt module makes its headers + available for inclusion and causes it to be linked to the binary. + By default, \c QT contains \c core and \c gui, ensuring that standard GUI applications can be built without further configuration. diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 684bcb9a371..afd41912fee 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -66,21 +66,22 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) bool IoUtils::isRelativePath(const QString &path) { - if (path.startsWith(QLatin1Char('/'))) - return false; #ifdef QMAKE_BUILTIN_PRFS if (path.startsWith(QLatin1String(":/"))) return false; #endif #ifdef Q_OS_WIN - if (path.startsWith(QLatin1Char('\\'))) - return false; - // Unlike QFileInfo, this won't accept a relative path with a drive letter. - // Such paths result in a royal mess anyway ... + // Unlike QFileInfo, this considers only paths with both a drive prefix and + // a subsequent (back-)slash absolute: if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter() - && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) + && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) { return false; -#endif + } + // (... unless, of course, they're UNC, which qmake fails on anyway) +#else + if (path.startsWith(QLatin1Char('/'))) + return false; +#endif // Q_OS_WIN return true; } @@ -100,6 +101,12 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) return QString(); if (isAbsolutePath(fileName)) return QDir::cleanPath(fileName); +#ifdef Q_OS_WIN // Add drive to otherwise-absolute path: + if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { + Q_ASSERT(isAbsolutePath(baseDir)); + return QDir::cleanPath(baseDir.left(2) + fileName); + } +#endif // Q_OS_WIN return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); } diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 759bff314e2..83c3d1d643a 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -1177,9 +1177,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (args.count() > 2) { evalError(fL1S("absolute_path(path[, base]) requires one or two arguments.")); } else { - QString rstr = QDir::cleanPath( - QDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory()) - .absoluteFilePath(args.at(0).toQString(m_tmp1))); + QString arg = args.at(0).toQString(m_tmp1); + QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : args.count() > 1 && rstr.isSharedWith(m_tmp2) @@ -1191,9 +1191,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (args.count() > 2) { evalError(fL1S("relative_path(path[, base]) requires one or two arguments.")); } else { - QDir baseDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory()); - QString rstr = baseDir.relativeFilePath(baseDir.absoluteFilePath( - args.at(0).toQString(m_tmp1))); + QString arg = args.at(0).toQString(m_tmp1); + QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); + QString rstr = QDir(baseDir).relativeFilePath(absArg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); } break; diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index b6dc8b20b66..d733d479cf0 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -68,6 +68,7 @@ #endif QT_BEGIN_NAMESPACE +using namespace QMakeInternal; // for IoUtils #define fL1S(s) QString::fromLatin1(s) @@ -96,9 +97,9 @@ QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &s { QString ret = QDir::cleanPath(spec); if (ret.contains(QLatin1Char('/'))) { - QString absRet = QDir(state.pwd).absoluteFilePath(ret); + QString absRet = IoUtils::resolvePath(state.pwd, ret); if (QFile::exists(absRet)) - ret = QDir::cleanPath(absRet); + ret = absRet; } return ret; } @@ -126,10 +127,10 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( user_template_prefix = arg; break; case ArgCache: - cachefile = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg)); + cachefile = args[*pos] = IoUtils::resolvePath(state.pwd, arg); break; case ArgQtConf: - qtconf = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg)); + qtconf = args[*pos] = IoUtils::resolvePath(state.pwd, arg); break; default: if (arg.startsWith(QLatin1Char('-'))) { @@ -259,11 +260,11 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const { QStringList ret; if (!val.isEmpty()) { - QDir bdir; + QString cwd(QDir::currentPath()); const QStringList vals = val.split(dirlist_sep); ret.reserve(vals.length()); for (const QString &it : vals) - ret << QDir::cleanPath(bdir.absoluteFilePath(it)); + ret << IoUtils::resolvePath(cwd, it); } return ret; } @@ -318,7 +319,7 @@ bool QMakeGlobals::initProperties() return false; data = proc.readAll(); #else - if (FILE *proc = QT_POPEN(QString(QMakeInternal::IoUtils::shellQuote(qmake_abslocation) + if (FILE *proc = QT_POPEN(QString(IoUtils::shellQuote(qmake_abslocation) + QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) { char buff[1024]; while (!feof(proc)) diff --git a/qmake/option.cpp b/qmake/option.cpp index 9737f1f6804..baad6442805 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -28,6 +28,7 @@ #include "option.h" #include "cachekeys.h" +#include #include #include #include @@ -38,6 +39,8 @@ QT_BEGIN_NAMESPACE +using namespace QMakeInternal; + EvalHandler Option::evalHandler; QMakeGlobals *Option::globals; ProFileCache *Option::proFileCache; @@ -325,7 +328,7 @@ Option::init(int argc, char **argv) #endif if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING) Option::qmake_mode = default_mode(argv0); - if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) { + if (!argv0.isEmpty() && IoUtils::isAbsolutePath(argv0)) { globals->qmake_abslocation = argv0; } else if (argv0.contains(QLatin1Char('/')) #ifdef Q_OS_WIN diff --git a/src/3rdparty/angle/src/libANGLE/Debug2.cpp b/src/3rdparty/angle/src/libANGLE/Debug2.cpp deleted file mode 100644 index 30321f41606..00000000000 --- a/src/3rdparty/angle/src/libANGLE/Debug2.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Debug.cpp: Defines debug state used for GL_KHR_debug - -#include "libANGLE/Debug.h" - -#include "common/debug.h" - -#include -#include - -namespace gl -{ - -Debug::Debug() - : mOutputEnabled(false), - mCallbackFunction(nullptr), - mCallbackUserParam(nullptr), - mMessages(), - mMaxLoggedMessages(0), - mOutputSynchronous(false), - mGroups() -{ - pushDefaultGroup(); -} - -void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages) -{ - mMaxLoggedMessages = maxLoggedMessages; -} - -void Debug::setOutputEnabled(bool enabled) -{ - mOutputEnabled = enabled; -} - -bool Debug::isOutputEnabled() const -{ - return mOutputEnabled; -} - -void Debug::setOutputSynchronous(bool synchronous) -{ - mOutputSynchronous = synchronous; -} - -bool Debug::isOutputSynchronous() const -{ - return mOutputSynchronous; -} - -void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam) -{ - mCallbackFunction = callback; - mCallbackUserParam = userParam; -} - -GLDEBUGPROCKHR Debug::getCallback() const -{ - return mCallbackFunction; -} - -const void *Debug::getUserParam() const -{ - return mCallbackUserParam; -} - -void Debug::insertMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - const std::string &message) -{ - std::string messageCopy(message); - insertMessage(source, type, id, severity, std::move(messageCopy)); -} - -void Debug::insertMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - std::string &&message) -{ - if (!isMessageEnabled(source, type, id, severity)) - { - return; - } - - if (mCallbackFunction != nullptr) - { - // TODO(geofflang) Check the synchronous flag and potentially flush messages from another - // thread. - mCallbackFunction(source, type, id, severity, static_cast(message.length()), - message.c_str(), mCallbackUserParam); - } - else - { - if (mMessages.size() >= mMaxLoggedMessages) - { - // Drop messages over the limit - return; - } - - Message m; - m.source = source; - m.type = type; - m.id = id; - m.severity = severity; - m.message = std::move(message); - - mMessages.push_back(std::move(m)); - } -} - -size_t Debug::getMessages(GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog) -{ - size_t messageCount = 0; - size_t messageStringIndex = 0; - while (messageCount <= count && !mMessages.empty()) - { - const Message &m = mMessages.front(); - - if (messageLog != nullptr) - { - // Check that this message can fit in the message buffer - if (messageStringIndex + m.message.length() + 1 > static_cast(bufSize)) - { - break; - } - - std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex); - messageStringIndex += m.message.length(); - - messageLog[messageStringIndex] = '\0'; - messageStringIndex += 1; - } - - if (sources != nullptr) - { - sources[messageCount] = m.source; - } - - if (types != nullptr) - { - types[messageCount] = m.type; - } - - if (ids != nullptr) - { - ids[messageCount] = m.id; - } - - if (severities != nullptr) - { - severities[messageCount] = m.severity; - } - - if (lengths != nullptr) - { - lengths[messageCount] = static_cast(m.message.length()); - } - - mMessages.pop_front(); - - messageCount++; - } - - return messageCount; -} - -size_t Debug::getNextMessageLength() const -{ - return mMessages.empty() ? 0 : mMessages.front().message.length(); -} - -size_t Debug::getMessageCount() const -{ - return mMessages.size(); -} - -void Debug::setMessageControl(GLenum source, - GLenum type, - GLenum severity, - std::vector &&ids, - bool enabled) -{ - Control c; - c.source = source; - c.type = type; - c.severity = severity; - c.ids = std::move(ids); - c.enabled = enabled; - - auto &controls = mGroups.back().controls; - controls.push_back(std::move(c)); -} - -void Debug::pushGroup(GLenum source, GLuint id, std::string &&message) -{ - insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION, - std::string(message)); - - Group g; - g.source = source; - g.id = id; - g.message = std::move(message); - mGroups.push_back(std::move(g)); -} - -void Debug::popGroup() -{ - // Make sure the default group is not about to be popped - ASSERT(mGroups.size() > 1); - - Group g = mGroups.back(); - mGroups.pop_back(); - - insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION, - g.message); -} - -size_t Debug::getGroupStackDepth() const -{ - return mGroups.size(); -} - -bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const -{ - if (!mOutputEnabled) - { - return false; - } - - for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++) - { - const auto &controls = groupIter->controls; - for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++) - { - const auto &control = *controlIter; - - if (control.source != GL_DONT_CARE && control.source != source) - { - continue; - } - - if (control.type != GL_DONT_CARE && control.type != type) - { - continue; - } - - if (control.severity != GL_DONT_CARE && control.severity != severity) - { - continue; - } - - if (!control.ids.empty() && - std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end()) - { - continue; - } - - return control.enabled; - } - } - - return true; -} - -void Debug::pushDefaultGroup() -{ - Group g; - g.source = GL_NONE; - g.id = 0; - g.message = ""; - - Control c0; - c0.source = GL_DONT_CARE; - c0.type = GL_DONT_CARE; - c0.severity = GL_DONT_CARE; - c0.enabled = true; - g.controls.push_back(std::move(c0)); - - Control c1; - c1.source = GL_DONT_CARE; - c1.type = GL_DONT_CARE; - c1.severity = GL_DEBUG_SEVERITY_LOW; - c1.enabled = false; - g.controls.push_back(std::move(c1)); - - mGroups.push_back(std::move(g)); -} -} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Debug2.h b/src/3rdparty/angle/src/libANGLE/Debug2.h deleted file mode 100644 index f545b815e4e..00000000000 --- a/src/3rdparty/angle/src/libANGLE/Debug2.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Debug.h: Defines debug state used for GL_KHR_debug - -#ifndef LIBANGLE_DEBUG_H_ -#define LIBANGLE_DEBUG_H_ - -#include "angle_gl.h" -#include "common/angleutils.h" - -#include -#include -#include - -namespace gl -{ - -class LabeledObject -{ - public: - virtual ~LabeledObject() {} - virtual void setLabel(const std::string &label) = 0; - virtual const std::string &getLabel() const = 0; -}; - -class Debug : angle::NonCopyable -{ - public: - Debug(); - - void setMaxLoggedMessages(GLuint maxLoggedMessages); - - void setOutputEnabled(bool enabled); - bool isOutputEnabled() const; - - void setOutputSynchronous(bool synchronous); - bool isOutputSynchronous() const; - - void setCallback(GLDEBUGPROCKHR callback, const void *userParam); - GLDEBUGPROCKHR getCallback() const; - const void *getUserParam() const; - - void insertMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - const std::string &message); - void insertMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - std::string &&message); - - void setMessageControl(GLenum source, - GLenum type, - GLenum severity, - std::vector &&ids, - bool enabled); - size_t getMessages(GLuint count, - GLsizei bufSize, - GLenum *sources, - GLenum *types, - GLuint *ids, - GLenum *severities, - GLsizei *lengths, - GLchar *messageLog); - size_t getNextMessageLength() const; - size_t getMessageCount() const; - - void pushGroup(GLenum source, GLuint id, std::string &&message); - void popGroup(); - size_t getGroupStackDepth() const; - - private: - bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const; - - void pushDefaultGroup(); - - struct Message - { - GLenum source; - GLenum type; - GLuint id; - GLenum severity; - std::string message; - }; - - struct Control - { - GLenum source; - GLenum type; - GLenum severity; - std::vector ids; - bool enabled; - }; - - struct Group - { - GLenum source; - GLuint id; - std::string message; - - std::vector controls; - }; - - bool mOutputEnabled; - GLDEBUGPROCKHR mCallbackFunction; - const void *mCallbackUserParam; - std::deque mMessages; - GLuint mMaxLoggedMessages; - bool mOutputSynchronous; - std::vector mGroups; -}; -} // namespace gl - -#endif // LIBANGLE_DEBUG_H_ diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json index a1966d43d62..9bfc14f29d8 100644 --- a/src/3rdparty/libjpeg/qt_attribution.json +++ b/src/3rdparty/libjpeg/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "The Independent JPEG Group's JPEG software", "Homepage": "http://libjpeg-turbo.virtualgl.org/", - "Version": "1.5.2", + "Version": "1.5.3", "License": "Independent JPEG Group License", "LicenseId": "IJG", "LicenseFile": "LICENSE", diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md index 2aaa50c1484..f5fe44bf851 100644 --- a/src/3rdparty/libjpeg/src/ChangeLog.md +++ b/src/3rdparty/libjpeg/src/ChangeLog.md @@ -1,3 +1,47 @@ +1.5.3 +===== + +### Significant changes relative to 1.5.2: + +1. Fixed a NullPointerException in the TurboJPEG Java wrapper that occurred +when using the YUVImage constructor that creates an instance backed by separate +image planes and allocates memory for the image planes. + +2. Fixed an issue whereby the Java version of TJUnitTest would fail when +testing BufferedImage encoding/decoding on big endian systems. + +3. Fixed a segfault in djpeg that would occur if an output format other than +PPM/PGM was selected along with the `-crop` option. The `-crop` option now +works with the GIF and Targa formats as well (unfortunately, it cannot be made +to work with the BMP and RLE formats due to the fact that those output engines +write scanlines in bottom-up order.) djpeg will now exit gracefully if an +output format other than PPM/PGM, GIF, or Targa is selected along with the +`-crop` option. + +4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color +quantization was enabled. + +5. TJBench (both C and Java versions) will now display usage information if any +command-line argument is unrecognized. This prevents the program from silently +ignoring typos. + +6. Fixed an access violation in tjbench.exe (Windows) that occurred when the +program was used to decompress an existing JPEG image. + +7. Fixed an ArrayIndexOutOfBoundsException in the TJExample Java program that +occurred when attempting to decompress a JPEG image that had been compressed +with 4:1:1 chrominance subsampling. + +8. Fixed an issue whereby, when using `jpeg_skip_scanlines()` to skip to the +end of a single-scan (non-progressive) image, subsequent calls to +`jpeg_consume_input()` would return `JPEG_SUSPENDED` rather than +`JPEG_REACHED_EOI`. + +9. `jpeg_crop_scanlines()` now works correctly when decompressing grayscale +JPEG images that were compressed with a sampling factor other than 1 (for +instance, with `cjpeg -grayscale -sample 2x2`). + + 1.5.2 ===== diff --git a/src/3rdparty/libjpeg/src/jcdctmgr.c b/src/3rdparty/libjpeg/src/jcdctmgr.c index aef8517f9c5..6e3b19bcb37 100644 --- a/src/3rdparty/libjpeg/src/jcdctmgr.c +++ b/src/3rdparty/libjpeg/src/jcdctmgr.c @@ -216,7 +216,7 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl) #endif dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */ - if(r <= 16) return 0; + if (r <= 16) return 0; else return 1; } diff --git a/src/3rdparty/libjpeg/src/jdapistd.c b/src/3rdparty/libjpeg/src/jdapistd.c index 37afc8448b9..105121df2be 100644 --- a/src/3rdparty/libjpeg/src/jdapistd.c +++ b/src/3rdparty/libjpeg/src/jdapistd.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2015-2016, D. R. Commander. + * Copyright (C) 2010, 2015-2017, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -190,7 +190,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, * single-pass decompression case, allowing us to use the same MCU column * width for all of the components. */ - align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor; + if (cinfo->comps_in_scan == 1 && cinfo->num_components == 1) + align = cinfo->_min_DCT_scaled_size; + else + align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor; /* Adjust xoffset to the nearest iMCU boundary <= the requested value */ input_xoffset = *xoffset; @@ -215,6 +218,9 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { + int hsf = (cinfo->comps_in_scan == 1 && cinfo->num_components == 1) ? + 1 : compptr->h_samp_factor; + /* Set downsampled_width to the new output width. */ orig_downsampled_width = compptr->downsampled_width; compptr->downsampled_width = @@ -228,11 +234,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, * values will be used in multi-scan decompressions. */ cinfo->master->first_MCU_col[ci] = - (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) / - (long) align; + (JDIMENSION) (long) (*xoffset * hsf) / (long) align; cinfo->master->last_MCU_col[ci] = (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) * - compptr->h_samp_factor), + hsf), (long) align) - 1; } @@ -293,6 +298,14 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, } +/* Dummy quantize function used by jpeg_skip_scanlines() */ +LOCAL(void) +noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +{ +} + + /* * In some cases, it is best to call jpeg_read_scanlines() and discard the * output, rather than skipping the scanlines, because this allows us to @@ -308,14 +321,22 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); + void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) = NULL; color_convert = cinfo->cconvert->color_convert; cinfo->cconvert->color_convert = noop_convert; + if (cinfo->cquantize && cinfo->cquantize->color_quantize) { + color_quantize = cinfo->cquantize->color_quantize; + cinfo->cquantize->color_quantize = noop_quantize; + } for (n = 0; n < num_lines; n++) jpeg_read_scanlines(cinfo, NULL, 1); cinfo->cconvert->color_convert = color_convert; + if (color_quantize) + cinfo->cquantize->color_quantize = color_quantize; } @@ -370,6 +391,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) /* Do not skip past the bottom of the image. */ if (cinfo->output_scanline + num_lines >= cinfo->output_height) { cinfo->output_scanline = cinfo->output_height; + (*cinfo->inputctl->finish_input_pass) (cinfo); + cinfo->inputctl->eoi_reached = TRUE; return cinfo->output_height - cinfo->output_scanline; } diff --git a/src/3rdparty/libjpeg/src/jdcolor.c b/src/3rdparty/libjpeg/src/jdcolor.c index ab8fa24925e..05cbf4df1fa 100644 --- a/src/3rdparty/libjpeg/src/jdcolor.c +++ b/src/3rdparty/libjpeg/src/jdcolor.c @@ -616,7 +616,7 @@ static const JLONG dither_matrix[4] = { static INLINE boolean is_big_endian(void) { int test_value = 1; - if(*(char *)&test_value != 1) + if (*(char *)&test_value != 1) return TRUE; return FALSE; } diff --git a/src/3rdparty/libjpeg/src/jdmerge.c b/src/3rdparty/libjpeg/src/jdmerge.c index 6276dd0950f..ca6f16c2525 100644 --- a/src/3rdparty/libjpeg/src/jdmerge.c +++ b/src/3rdparty/libjpeg/src/jdmerge.c @@ -503,7 +503,7 @@ static const JLONG dither_matrix[4] = { static INLINE boolean is_big_endian(void) { int test_value = 1; - if(*(char *)&test_value != 1) + if (*(char *)&test_value != 1) return TRUE; return FALSE; } diff --git a/src/3rdparty/pcre2/pcre2.pro b/src/3rdparty/pcre2/pcre2.pro index 3dde2f62f83..296e65cd59b 100644 --- a/src/3rdparty/pcre2/pcre2.pro +++ b/src/3rdparty/pcre2/pcre2.pro @@ -16,6 +16,8 @@ DEFINES += HAVE_CONFIG_H # platform/compiler specific definitions uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT +win32:contains(QT_ARCH, "arm"): DEFINES += PCRE2_DISABLE_JIT +win32:contains(QT_ARCH, "arm64"): DEFINES += PCRE2_DISABLE_JIT SOURCES += \ $$PWD/src/pcre2_auto_possess.c \ diff --git a/src/3rdparty/sqlite/qt_attribution.json b/src/3rdparty/sqlite/qt_attribution.json index 50c179bf6ef..38004772390 100644 --- a/src/3rdparty/sqlite/qt_attribution.json +++ b/src/3rdparty/sqlite/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.", "Homepage": "http://www.sqlite.org/", - "Version": "3.20.1", + "Version": "3.22.0", "License": "Public Domain", "Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed." } diff --git a/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java b/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java index e6814c202df..4f2c06644d4 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java +++ b/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java @@ -51,6 +51,7 @@ import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.widget.PopupWindow; import android.app.Activity; +import android.util.TypedValue; import android.view.ViewTreeObserver; /* This view represents one of the handle (selection or cursor handle) */ @@ -58,8 +59,9 @@ class CursorView extends ImageView { private CursorHandle mHandle; // The coordinare which where clicked - private int m_offsetX; - private int m_offsetY; + private float m_offsetX; + private float m_offsetY; + private boolean m_pressed = false; CursorView (Context context, CursorHandle handle) { super(context); @@ -76,21 +78,23 @@ class CursorView extends ImageView public boolean onTouchEvent(MotionEvent ev) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: { - m_offsetX = Math.round(ev.getRawX()); - m_offsetY = Math.round(ev.getRawY()); + m_offsetX = ev.getRawX(); + m_offsetY = ev.getRawY() + getHeight() / 2; + m_pressed = true; break; } case MotionEvent.ACTION_MOVE: { - mHandle.updatePosition(Math.round(ev.getRawX()) - m_offsetX, - Math.round(ev.getRawY()) - m_offsetY); + if (!m_pressed) + return false; + mHandle.updatePosition(Math.round(ev.getRawX() - m_offsetX), + Math.round(ev.getRawY() - m_offsetY)); break; } case MotionEvent.ACTION_UP: - break; - case MotionEvent.ACTION_CANCEL: + m_pressed = false; break; } return true; @@ -113,6 +117,7 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener private int m_lastY; int tolerance; private boolean m_rtl; + int m_yShift; public CursorHandle(Activity activity, View layout, int id, int attr, boolean rtl) { m_activity = activity; @@ -121,7 +126,8 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener m_layout = layout; DisplayMetrics metrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - tolerance = Math.round(2 * metrics.density); + m_yShift = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, metrics); + tolerance = Math.min(1, (int)(m_yShift / 2f)); m_lastX = m_lastY = -1 - tolerance; m_rtl = rtl; } @@ -158,7 +164,7 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener m_layout.getLocationOnScreen(location); int x2 = x + location[0]; - int y2 = y + location[1]; + int y2 = y + location[1] + m_yShift; if (m_id == QtNative.IdCursorHandle) { x2 -= m_cursorView.getWidth() / 2 ; @@ -187,6 +193,7 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener // The handle was dragged by a given relative position public void updatePosition(int x, int y) { + y -= m_yShift; if (Math.abs(m_lastX - x) > tolerance || Math.abs(m_lastY - y) > tolerance) { QtNative.handleLocationChanged(m_id, x + m_posX, y + m_posY); m_lastX = x; diff --git a/src/angle/src/common/gles_common.pri b/src/angle/src/common/gles_common.pri index 5d5682a1df5..82d38a62e6f 100644 --- a/src/angle/src/common/gles_common.pri +++ b/src/angle/src/common/gles_common.pri @@ -1,4 +1,4 @@ -CONFIG += simd no_batch +CONFIG += simd no_batch object_parallel_to_source include(common.pri) INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libANGLE @@ -48,6 +48,7 @@ HEADERS += \ $$ANGLE_DIR/src/libANGLE/Constants.h \ $$ANGLE_DIR/src/libANGLE/Context.h \ $$ANGLE_DIR/src/libANGLE/Data.h \ + $$ANGLE_DIR/src/libANGLE/Debug.h \ $$ANGLE_DIR/src/libANGLE/Device.h \ $$ANGLE_DIR/src/libANGLE/Display.h \ $$ANGLE_DIR/src/libANGLE/Error.h \ @@ -169,6 +170,7 @@ SOURCES += \ $$ANGLE_DIR/src/libANGLE/Config.cpp \ $$ANGLE_DIR/src/libANGLE/Context.cpp \ $$ANGLE_DIR/src/libANGLE/Data.cpp \ + $$ANGLE_DIR/src/libANGLE/Debug.cpp \ $$ANGLE_DIR/src/libANGLE/Device.cpp \ $$ANGLE_DIR/src/libANGLE/Display.cpp \ $$ANGLE_DIR/src/libANGLE/Error.cpp \ @@ -241,14 +243,6 @@ SOURCES += \ SSE2_SOURCES += $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimageSSE2.cpp -DEBUG_SOURCE = $$ANGLE_DIR/src/libANGLE/Debug.cpp -debug_copy.input = DEBUG_SOURCE -debug_copy.output = $$ANGLE_DIR/src/libANGLE/Debug2.cpp -debug_copy.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} -debug_copy.variable_out = GENERATED_SOURCES -debug_copy.CONFIG = target_predeps -QMAKE_EXTRA_COMPILERS += debug_copy - angle_d3d11 { HEADERS += \ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.h \ diff --git a/src/concurrent/concurrent.pro b/src/concurrent/concurrent.pro index 017153c74d5..18510e38a18 100644 --- a/src/concurrent/concurrent.pro +++ b/src/concurrent/concurrent.pro @@ -4,7 +4,7 @@ CONFIG += exceptions DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x66000000 QMAKE_DOCS = $$PWD/doc/qtconcurrent.qdocconf diff --git a/src/concurrent/doc/src/qtconcurrent-index.qdoc b/src/concurrent/doc/src/qtconcurrent-index.qdoc index 836cde131c1..3e4aa791f13 100644 --- a/src/concurrent/doc/src/qtconcurrent-index.qdoc +++ b/src/concurrent/doc/src/qtconcurrent-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -133,4 +133,13 @@ copy of the container when called. If you are using STL containers this copy operation might take some time, in this case we recommend specifying the begin and end iterators for the container instead. + + \section1 Licenses + + The Qt Concurrent module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. */ diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 2079d2117ff..3db2e2ceb86 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -12,7 +12,7 @@ CONFIG += qt_tracepoints CONFIG += $$MODULE_CONFIG DEFINES += $$MODULE_DEFINES DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x67000000 CONFIG += simd optimize_full diff --git a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp index a1372976ae8..ba31972aa12 100644 --- a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp @@ -55,7 +55,7 @@ class HelloWorldTask : public QRunnable { qDebug() << "Hello world from thread" << QThread::currentThread(); } -} +}; HelloWorldTask *hello = new HelloWorldTask(); // QThreadPool takes ownership and deletes 'hello' automatically diff --git a/src/corelib/doc/src/qtcore-index.qdoc b/src/corelib/doc/src/qtcore-index.qdoc index 9004c018ed0..04af0e9416b 100644 --- a/src/corelib/doc/src/qtcore-index.qdoc +++ b/src/corelib/doc/src/qtcore-index.qdoc @@ -104,17 +104,18 @@ \section1 Licenses and Attributions Qt Core is available under commercial licenses from \l{The Qt Company}. - In addition, it is available under the + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are \l{GNU Lesser General Public License, version 3}, or the \l{GNU General Public License, version 2}. See \l{Qt Licensing} for further details. Executables on Windows potentially link against \l{The qtmain Library}. This library is available - under commercial licenses, and in addition under the + under commercial licenses and also under the \l{BSD 3-clause "New" or "Revised" License}. - Furthermore Qt Core potentially contains third party + Furthermore, Qt Core in Qt \QtVersion may contain third party modules under following permissive licenses: \generatelist{groupsbymodule attributions-qtcore} diff --git a/src/corelib/global/qfloat16_f16c.c b/src/corelib/global/qfloat16_f16c.c index 31dff0b154f..a7eadc71b7b 100644 --- a/src/corelib/global/qfloat16_f16c.c +++ b/src/corelib/global/qfloat16_f16c.c @@ -57,6 +57,7 @@ QT_FUNCTION_TARGET(F16C) void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW { qsizetype i = 0; + int epilog_i; for (; i < len - 7; i += 8) _mm_storeu_si128((__m128i *)(out + i), _mm256_cvtps_ph(_mm256_loadu_ps(in + i), 0)); if (i < len - 3) { @@ -64,7 +65,7 @@ void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_N i += 4; } // Inlining "qfloat16::qfloat16(float f)": - SIMD_EPILOGUE(i, len, 3) + for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i) out[i] = _mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(in[i]), 0), 0); } @@ -72,6 +73,7 @@ QT_FUNCTION_TARGET(F16C) void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW { qsizetype i = 0; + int epilog_i; for (; i < len - 7; i += 8) _mm256_storeu_ps(out + i, _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(in + i)))); if (i < len - 3) { @@ -79,7 +81,7 @@ void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL i += 4; } // Inlining "qfloat16::operator float()": - SIMD_EPILOGUE(i, len, 3) + for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i) out[i] = _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(in[i]))); } diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 1fe1c8c0d10..2d8b860c5bb 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -84,7 +84,7 @@ # include #endif -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #include #endif @@ -2298,7 +2298,7 @@ static bool findUnixOsVersion(QUnixOSVersion &v) # endif // USE_ETC_OS_RELEASE #endif // Q_OS_UNIX -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) static const char *osVer_helper(QOperatingSystemVersion) { /* Data: @@ -2779,7 +2779,7 @@ QString QSysInfo::productVersion() */ QString QSysInfo::prettyProductName() { -#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) +#if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) const auto version = QOperatingSystemVersion::current(); const char *name = osVer_helper(version); if (name) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 39a5bbf6452..9f1fe7cabb6 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1597,7 +1597,7 @@ static bool syslog_default_message_handler(QtMsgType type, const QMessageLogCont } #endif -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) static bool android_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) @@ -1678,7 +1678,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con handledStderr |= systemd_default_message_handler(type, context, message); # elif QT_CONFIG(syslog) handledStderr |= syslog_default_message_handler(type, context, message); -# elif defined(Q_OS_ANDROID) +# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) handledStderr |= android_default_message_handler(type, context, message); # elif defined(QT_USE_APPLE_UNIFIED_LOGGING) if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 9b86a165168..5f8a124bcc2 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -168,7 +168,7 @@ namespace { // size_t. Implementations for 8- and 16-bit types will work but may not be as // efficient. Implementations for 64-bit may be missing on 32-bit platforms. -#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || defined(Q_CC_INTEL)) || QT_HAS_BUILTIN(__builtin_add_overflowx) +#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || (defined(Q_CC_INTEL) && !defined(Q_OS_WIN))) || QT_HAS_BUILTIN(__builtin_add_overflowx) // GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows template inline diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp index 682c9bab61e..4d267e328d2 100644 --- a/src/corelib/global/qoperatingsystemversion.cpp +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -45,7 +45,7 @@ #include #include -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #include #endif @@ -163,7 +163,7 @@ QOperatingSystemVersion QOperatingSystemVersion::current() { QOperatingSystemVersion version; version.m_os = currentType(); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #ifndef QT_BOOTSTRAPPED const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField( "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString()); diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 6c26d4682d8..9143e04d459 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -74,7 +74,7 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando } #endif -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) # include #endif diff --git a/src/corelib/io/QTEMPORARYFILE_LICENSE.txt b/src/corelib/io/QTEMPORARYFILE_LICENSE.txt deleted file mode 100644 index f5f1a2e05ea..00000000000 --- a/src/corelib/io/QTEMPORARYFILE_LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 1987, 1993 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index c6a5973306f..d138ab2f00b 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -159,7 +159,7 @@ win32 { } else { LIBS += -framework MobileCoreServices } - } else:android { + } else:android:!android-embedded { SOURCES += \ io/qstandardpaths_android.cpp \ io/qstorageinfo_unix.cpp diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 7dd4f6556d1..bc39ea73ee9 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -185,10 +185,11 @@ bool QFSFileEnginePrivate::nativeFlush() bool QFSFileEnginePrivate::nativeSyncToDisk() { Q_Q(QFSFileEngine); + int ret; #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 - const int ret = fdatasync(nativeHandle()); + EINTR_LOOP(ret, fdatasync(nativeHandle())); #else - const int ret = fsync(nativeHandle()); + EINTR_LOOP(ret, fsync(nativeHandle())); #endif if (ret != 0) q->setError(QFile::WriteError, qt_error_string(errno)); diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index b5f8e30b803..cd97268d716 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -44,6 +44,7 @@ #include #include #include +#include // We can't use the default macros because this would lead to recursion. // Instead let's define our own one that unconditionally logs... @@ -255,6 +256,15 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line) QLoggingRegistry::QLoggingRegistry() : categoryFilter(defaultCategoryFilter) { +#if defined(Q_OS_ANDROID) + // Unless QCoreApplication has been constructed we can't be sure that + // we are on Qt's main thread. If we did allow logging here, we would + // potentially set Qt's main thread to Android's thread 0, which would + // confuse Qt later when running main(). + if (!qApp) + return; +#endif + initializeRules(); // Init on first use } diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 6ab806d9fe2..3a62a67e3b7 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -101,7 +101,8 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe) unsigned int attempts = 1000; forever { _snwprintf(pipeName, sizeof(pipeName) / sizeof(pipeName[0]), - L"\\\\.\\pipe\\qt-%X", QRandomGenerator::global()->generate()); + L"\\\\.\\pipe\\qt-%lX-%X", long(QCoreApplication::applicationPid()), + QRandomGenerator::global()->generate()); DWORD dwOpenMode = FILE_FLAG_OVERLAPPED; DWORD dwOutputBufferSize = 0; diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 56934a9a0f7..0cbc8c2234f 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -264,7 +264,7 @@ bool QSaveFile::open(OpenMode mode) } #endif - d->fileEngine = new QTemporaryFileEngine(&d->finalFileName); + d->fileEngine = new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared); // if the target file exists, we'll copy its permissions below, // but until then, let's ensure the temporary file is not accessible // to a third party diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index bbc66120b52..4b1b9888d81 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -2366,6 +2366,11 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, limitations is to store the settings using the IniFormat instead of the NativeFormat. + \li On Windows, when the Windows system registry is used, QSettings + does not preserve the original type of the value. Therefore, + the type of the value might change when a new value is set. For + example, a value with type \c REG_EXPAND_SZ will change to \c REG_SZ. + \li On \macos and iOS, allKeys() will return some extra keys for global settings that apply to all applications. These keys can be read using value() but cannot be changed, only shadowed. diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp index 2a44daf8b52..0667d170c71 100644 --- a/src/corelib/io/qstandardpaths_android.cpp +++ b/src/corelib/io/qstandardpaths_android.cpp @@ -217,7 +217,16 @@ static QString getFilesDir() if (!path.isEmpty()) return path; - return (path = QDir::homePath()); + QJNIObjectPrivate appCtx = applicationContext(); + if (!appCtx.isValid()) + return QString(); + + QJNIObjectPrivate file = appCtx.callObjectMethod("getFilesDir", + "()Ljava/io/File;"); + if (!file.isValid()) + return QString(); + + return (path = getAbsolutePath(file)); } QString QStandardPaths::writableLocation(StandardLocation type) @@ -319,7 +328,9 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) if (!ba.isEmpty()) return QStringList((fontLocation = QDir::cleanPath(QString::fromLocal8Bit(ba)))); - return QStringList((fontLocation = QLatin1String("/system/fonts"))); + // Don't cache the fallback, as we might just have been called before + // QT_ANDROID_FONT_LOCATION has been set. + return QStringList(QLatin1String("/system/fonts")); } return QStringList(writableLocation(type)); diff --git a/src/corelib/io/qt_attribution.json b/src/corelib/io/qt_attribution.json index 0fa4502db43..e9eb9c85e4b 100644 --- a/src/corelib/io/qt_attribution.json +++ b/src/corelib/io/qt_attribution.json @@ -1,17 +1,3 @@ -[ -{ - "Id": "qtemporaryfile", - "Name": "Parts of QTemporaryFile", - "QDocModule": "qtcore", - "QtUsage": "Used in Qt Core. Disable the qtemporaryfile feature to avoid.", - "Path": "qtemporaryfile.cpp", - - "Description": "Generates a unique file path and returns a native handle to the open file.", - "License": "BSD 3-clause \"New\" or \"Revised\" License", - "LicenseId": "BSD-3-Clause", - "LicenseFile": "QTEMPORARYFILE_LICENSE.txt", - "Copyright": "Copyright (c) 1987, 1993 The Regents of the University of California." -}, { "Id": "psl", "Name": "The Public Suffix List", @@ -39,4 +25,3 @@ supported by Qt (by the QNetworkCookieJar class).", "Copyright": "The list was originally provided by Jo Hermans . It is now maintained on github (https://github.com/publicsuffix/list)." } -] diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 73249d7df8e..1983a22c651 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -207,7 +207,7 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext() changed and contain the generated path name. */ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &templ, - quint32 mode, QSystemError &error) + quint32 mode, int flags, QSystemError &error) { const int maxAttempts = 16; for (int attempt = 0; attempt < maxAttempts; ++attempt) { @@ -216,16 +216,18 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t #if defined(Q_OS_WIN) Q_UNUSED(mode); + const DWORD shareMode = (flags & QTemporaryFileEngine::Win32NonShared) + ? 0u : (FILE_SHARE_READ | FILE_SHARE_WRITE); # ifndef Q_OS_WINRT file = CreateFile((const wchar_t *)path.constData(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, + shareMode, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); # else // !Q_OS_WINRT file = CreateFile2((const wchar_t *)path.constData(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW, + shareMode, CREATE_NEW, NULL); # endif // Q_OS_WINRT @@ -247,6 +249,7 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t return false; } #else // POSIX + Q_UNUSED(flags) file = QT_OPEN(path.constData(), QT_OPEN_CREAT | QT_OPEN_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE, static_cast(mode)); @@ -366,7 +369,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) unnamedFile = true; d->fileEntry.clear(); } else if (st == CreateUnnamedFileStatus::NotSupported && - createFileFromTemplate(file, tfn, fileMode, error)) { + createFileFromTemplate(file, tfn, fileMode, flags, error)) { filePathIsTemplate = false; unnamedFile = false; d->fileEntry = QFileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath()); diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index fb8887af533..0fec88d3cd4 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -108,8 +108,10 @@ class QTemporaryFileEngine : public QFSFileEngine { Q_DECLARE_PRIVATE(QFSFileEngine) public: - QTemporaryFileEngine(const QString *templateName) - : templateName(*templateName) + enum Flags { Win32NonShared = 0x1 }; + + explicit QTemporaryFileEngine(const QString *_templateName, int _flags = 0) + : templateName(*_templateName), flags(_flags) {} void initialize(const QString &file, quint32 mode, bool nameIsTemplate = true) @@ -144,6 +146,7 @@ public: const QString &templateName; quint32 fileMode; + int flags = 0; bool filePathIsTemplate; bool filePathWasTemplate; bool unnamedFile = false; diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp index ce90ab49d3e..a9b23babc09 100644 --- a/src/corelib/io/qurlrecode.cpp +++ b/src/corelib/io/qurlrecode.cpp @@ -511,7 +511,7 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end) if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) { // badly-encoded data appendTo.resize(origSize + (end - begin)); - memcpy(appendTo.begin() + origSize, begin, (end - begin) * sizeof(ushort)); + memcpy(static_cast(appendTo.begin() + origSize), static_cast(begin), (end - begin) * sizeof(ushort)); return end - begin; } @@ -519,7 +519,7 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end) // detach appendTo.resize(origSize + (end - begin)); output = reinterpret_cast(appendTo.begin()) + origSize; - memcpy(output, begin, (input - begin) * sizeof(ushort)); + memcpy(static_cast(output), static_cast(begin), (input - begin) * sizeof(ushort)); output += input - begin; } diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp new file mode 100644 index 00000000000..255dc2ee4e8 --- /dev/null +++ b/src/corelib/json/qjsonarray.cpp @@ -0,0 +1,1238 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "qjsonwriter_p.h" +#include "qjson_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QJsonArray + \inmodule QtCore + \ingroup json + \ingroup shared + \reentrant + \since 5.0 + + \brief The QJsonArray class encapsulates a JSON array. + + A JSON array is a list of values. The list can be manipulated by inserting and + removing QJsonValue's from the array. + + A QJsonArray can be converted to and from a QVariantList. You can query the + number of entries with size(), insert(), and removeAt() entries from it + and iterate over its content using the standard C++ iterator pattern. + + QJsonArray is an implicitly shared class and shares the data with the document + it has been created from as long as it is not being modified. + + You can convert the array to and from text based JSON through QJsonDocument. + + \sa {JSON Support in Qt}, {JSON Save Game Example} +*/ + +/*! + \typedef QJsonArray::Iterator + + Qt-style synonym for QJsonArray::iterator. +*/ + +/*! + \typedef QJsonArray::ConstIterator + + Qt-style synonym for QJsonArray::const_iterator. +*/ + +/*! + \typedef QJsonArray::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::value_type + + Typedef for QJsonValue. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::difference_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::pointer + + Typedef for QJsonValue *. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::const_pointer + + Typedef for const QJsonValue *. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::reference + + Typedef for QJsonValue &. Provided for STL compatibility. +*/ + +/*! + \typedef QJsonArray::const_reference + + Typedef for const QJsonValue &. Provided for STL compatibility. +*/ + +/*! + Creates an empty array. + */ +QJsonArray::QJsonArray() + : d(0), a(0) +{ +} + +/*! + \fn QJsonArray::QJsonArray(std::initializer_list args) + \since 5.4 + Creates an array initialized from \a args initialization list. + + QJsonArray can be constructed in a way similar to JSON notation, + for example: + \code + QJsonArray array = { 1, 2.2, QString() }; + \endcode + */ + +/*! + \internal + */ +QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array) + : d(data), a(array) +{ + Q_ASSERT(data); + Q_ASSERT(array); + d->ref.ref(); +} + +/*! + This method replaces part of QJsonArray(std::initializer_list args) . + The constructor needs to be inline, but we do not want to leak implementation details + of this class. + \note this method is called for an uninitialized object + \internal + */ +void QJsonArray::initialize() +{ + d = 0; + a = 0; +} + +/*! + Deletes the array. + */ +QJsonArray::~QJsonArray() +{ + if (d && !d->ref.deref()) + delete d; +} + +/*! + Creates a copy of \a other. + + Since QJsonArray is implicitly shared, the copy is shallow + as long as the object doesn't get modified. + */ +QJsonArray::QJsonArray(const QJsonArray &other) +{ + d = other.d; + a = other.a; + if (d) + d->ref.ref(); +} + +/*! + Assigns \a other to this array. + */ +QJsonArray &QJsonArray::operator =(const QJsonArray &other) +{ + if (d != other.d) { + if (d && !d->ref.deref()) + delete d; + d = other.d; + if (d) + d->ref.ref(); + } + a = other.a; + + return *this; +} + +/*! \fn QJsonArray &QJsonArray::operator+=(const QJsonValue &value) + + Appends \a value to the array, and returns a reference to the array itself. + + \since 5.3 + \sa append(), operator<<() +*/ + +/*! \fn QJsonArray QJsonArray::operator+(const QJsonValue &value) const + + Returns an array that contains all the items in this array followed + by the provided \a value. + + \since 5.3 + \sa operator+=() +*/ + +/*! \fn QJsonArray &QJsonArray::operator<<(const QJsonValue &value) + + Appends \a value to the array, and returns a reference to the array itself. + + \since 5.3 + \sa operator+=(), append() +*/ + +/*! + Converts the string list \a list to a QJsonArray. + + The values in \a list will be converted to JSON values. + + \sa toVariantList(), QJsonValue::fromVariant() + */ +QJsonArray QJsonArray::fromStringList(const QStringList &list) +{ + QJsonArray array; + for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) + array.append(QJsonValue(*it)); + return array; +} + +/*! + Converts the variant list \a list to a QJsonArray. + + The QVariant values in \a list will be converted to JSON values. + + \sa toVariantList(), QJsonValue::fromVariant() + */ +QJsonArray QJsonArray::fromVariantList(const QVariantList &list) +{ + QJsonArray array; + if (list.isEmpty()) + return array; + + array.detach2(1024); + + QVector values; + values.resize(list.size()); + QJsonPrivate::Value *valueData = values.data(); + uint currentOffset = sizeof(QJsonPrivate::Base); + + for (int i = 0; i < list.size(); ++i) { + QJsonValue val = QJsonValue::fromVariant(list.at(i)); + + bool latinOrIntValue; + int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); + + if (!array.detach2(valueSize)) + return QJsonArray(); + + QJsonPrivate::Value *v = valueData + i; + v->type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); + v->latinOrIntValue = latinOrIntValue; + v->latinKey = false; + v->value = QJsonPrivate::Value::valueToStore(val, currentOffset); + if (valueSize) + QJsonPrivate::Value::copyData(val, (char *)array.a + currentOffset, latinOrIntValue); + + currentOffset += valueSize; + array.a->size = currentOffset; + } + + // write table + array.a->tableOffset = currentOffset; + if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size())) + return QJsonArray(); + memcpy(static_cast(array.a->table()), + static_cast(values.constData()), values.size()*sizeof(uint)); + array.a->length = values.size(); + array.a->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size(); + + return array; +} + +/*! + Converts this object to a QVariantList. + + Returns the created map. + */ +QVariantList QJsonArray::toVariantList() const +{ + QVariantList list; + + if (a) { + list.reserve(a->length); + for (int i = 0; i < (int)a->length; ++i) + list.append(QJsonValue(d, a, a->at(i)).toVariant()); + } + return list; +} + + +/*! + Returns the number of values stored in the array. + */ +int QJsonArray::size() const +{ + if (!d) + return 0; + + return (int)a->length; +} + +/*! + \fn QJsonArray::count() const + + Same as size(). + + \sa size() +*/ + +/*! + Returns \c true if the object is empty. This is the same as size() == 0. + + \sa size() + */ +bool QJsonArray::isEmpty() const +{ + if (!d) + return true; + + return !a->length; +} + +/*! + Returns a QJsonValue representing the value for index \a i. + + The returned QJsonValue is \c Undefined, if \a i is out of bounds. + + */ +QJsonValue QJsonArray::at(int i) const +{ + if (!a || i < 0 || i >= (int)a->length) + return QJsonValue(QJsonValue::Undefined); + + return QJsonValue(d, a, a->at(i)); +} + +/*! + Returns the first value stored in the array. + + Same as \c at(0). + + \sa at() + */ +QJsonValue QJsonArray::first() const +{ + return at(0); +} + +/*! + Returns the last value stored in the array. + + Same as \c{at(size() - 1)}. + + \sa at() + */ +QJsonValue QJsonArray::last() const +{ + return at(a ? (a->length - 1) : 0); +} + +/*! + Inserts \a value at the beginning of the array. + + This is the same as \c{insert(0, value)} and will prepend \a value to the array. + + \sa append(), insert() + */ +void QJsonArray::prepend(const QJsonValue &value) +{ + insert(0, value); +} + +/*! + Inserts \a value at the end of the array. + + \sa prepend(), insert() + */ +void QJsonArray::append(const QJsonValue &value) +{ + insert(a ? (int)a->length : 0, value); +} + +/*! + Removes the value at index position \a i. \a i must be a valid + index position in the array (i.e., \c{0 <= i < size()}). + + \sa insert(), replace() + */ +void QJsonArray::removeAt(int i) +{ + if (!a || i < 0 || i >= (int)a->length) + return; + + detach2(); + a->removeItems(i, 1); + ++d->compactionCounter; + if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) + compact(); +} + +/*! \fn void QJsonArray::removeFirst() + + Removes the first item in the array. Calling this function is + equivalent to calling \c{removeAt(0)}. The array must not be empty. If + the array can be empty, call isEmpty() before calling this + function. + + \sa removeAt(), removeLast() +*/ + +/*! \fn void QJsonArray::removeLast() + + Removes the last item in the array. Calling this function is + equivalent to calling \c{removeAt(size() - 1)}. The array must not be + empty. If the array can be empty, call isEmpty() before calling + this function. + + \sa removeAt(), removeFirst() +*/ + +/*! + Removes the item at index position \a i and returns it. \a i must + be a valid index position in the array (i.e., \c{0 <= i < size()}). + + If you don't use the return value, removeAt() is more efficient. + + \sa removeAt() + */ +QJsonValue QJsonArray::takeAt(int i) +{ + if (!a || i < 0 || i >= (int)a->length) + return QJsonValue(QJsonValue::Undefined); + + QJsonValue v(d, a, a->at(i)); + removeAt(i); // detaches + return v; +} + +/*! + Inserts \a value at index position \a i in the array. If \a i + is \c 0, the value is prepended to the array. If \a i is size(), the + value is appended to the array. + + \sa append(), prepend(), replace(), removeAt() + */ +void QJsonArray::insert(int i, const QJsonValue &value) +{ + Q_ASSERT (i >= 0 && i <= (a ? (int)a->length : 0)); + QJsonValue val = value; + + bool compressed; + int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); + + if (!detach2(valueSize + sizeof(QJsonPrivate::Value))) + return; + + if (!a->length) + a->tableOffset = sizeof(QJsonPrivate::Array); + + int valueOffset = a->reserveSpace(valueSize, i, 1, false); + if (!valueOffset) + return; + + QJsonPrivate::Value &v = (*a)[i]; + v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); + v.latinOrIntValue = compressed; + v.latinKey = false; + v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); + if (valueSize) + QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); +} + +/*! + \fn QJsonArray::iterator QJsonArray::insert(iterator before, const QJsonValue &value) + + Inserts \a value before the position pointed to by \a before, and returns an iterator + pointing to the newly inserted item. + + \sa erase(), insert() +*/ + +/*! + \fn QJsonArray::iterator QJsonArray::erase(iterator it) + + Removes the item pointed to by \a it, and returns an iterator pointing to the + next item. + + \sa removeAt() +*/ + +/*! + Replaces the item at index position \a i with \a value. \a i must + be a valid index position in the array (i.e., \c{0 <= i < size()}). + + \sa operator[](), removeAt() + */ +void QJsonArray::replace(int i, const QJsonValue &value) +{ + Q_ASSERT (a && i >= 0 && i < (int)(a->length)); + QJsonValue val = value; + + bool compressed; + int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); + + if (!detach2(valueSize)) + return; + + if (!a->length) + a->tableOffset = sizeof(QJsonPrivate::Array); + + int valueOffset = a->reserveSpace(valueSize, i, 1, true); + if (!valueOffset) + return; + + QJsonPrivate::Value &v = (*a)[i]; + v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); + v.latinOrIntValue = compressed; + v.latinKey = false; + v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); + if (valueSize) + QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); + + ++d->compactionCounter; + if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) + compact(); +} + +/*! + Returns \c true if the array contains an occurrence of \a value, otherwise \c false. + + \sa count() + */ +bool QJsonArray::contains(const QJsonValue &value) const +{ + for (int i = 0; i < size(); i++) { + if (at(i) == value) + return true; + } + return false; +} + +/*! + Returns the value at index position \a i as a modifiable reference. + \a i must be a valid index position in the array (i.e., \c{0 <= i < + size()}). + + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can + use it as if it were a reference to a QJsonValue. If you assign to it, + the assignment will apply to the character in the QJsonArray of QJsonObject + from which you got the reference. + + \sa at() + */ +QJsonValueRef QJsonArray::operator [](int i) +{ + Q_ASSERT(a && i >= 0 && i < (int)a->length); + return QJsonValueRef(this, i); +} + +/*! + \overload + + Same as at(). + */ +QJsonValue QJsonArray::operator[](int i) const +{ + return at(i); +} + +/*! + Returns \c true if this array is equal to \a other. + */ +bool QJsonArray::operator==(const QJsonArray &other) const +{ + if (a == other.a) + return true; + + if (!a) + return !other.a->length; + if (!other.a) + return !a->length; + if (a->length != other.a->length) + return false; + + for (int i = 0; i < (int)a->length; ++i) { + if (QJsonValue(d, a, a->at(i)) != QJsonValue(other.d, other.a, other.a->at(i))) + return false; + } + return true; +} + +/*! + Returns \c true if this array is not equal to \a other. + */ +bool QJsonArray::operator!=(const QJsonArray &other) const +{ + return !(*this == other); +} + +/*! \fn QJsonArray::iterator QJsonArray::begin() + + Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in + the array. + + \sa constBegin(), end() +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::begin() const + + \overload +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::constBegin() const + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item + in the array. + + \sa begin(), constEnd() +*/ + +/*! \fn QJsonArray::iterator QJsonArray::end() + + Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item + after the last item in the array. + + \sa begin(), constEnd() +*/ + +/*! \fn const_iterator QJsonArray::end() const + + \overload +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::constEnd() const + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last item in the array. + + \sa constBegin(), end() +*/ + +/*! \fn void QJsonArray::push_back(const QJsonValue &value) + + This function is provided for STL compatibility. It is equivalent + to \l{QJsonArray::append()}{append(value)} and will append \a value to the array. +*/ + +/*! \fn void QJsonArray::push_front(const QJsonValue &value) + + This function is provided for STL compatibility. It is equivalent + to \l{QJsonArray::prepend()}{prepend(value)} and will prepend \a value to the array. +*/ + +/*! \fn void QJsonArray::pop_front() + + This function is provided for STL compatibility. It is equivalent + to removeFirst(). The array must not be empty. If the array can be + empty, call isEmpty() before calling this function. +*/ + +/*! \fn void QJsonArray::pop_back() + + This function is provided for STL compatibility. It is equivalent + to removeLast(). The array must not be empty. If the array can be + empty, call isEmpty() before calling this function. +*/ + +/*! \fn bool QJsonArray::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty() and returns \c true if the array is empty. +*/ + +/*! \class QJsonArray::iterator + \inmodule QtCore + \brief The QJsonArray::iterator class provides an STL-style non-const iterator for QJsonArray. + + QJsonArray::iterator allows you to iterate over a QJsonArray + and to modify the array item associated with the + iterator. If you want to iterate over a const QJsonArray, use + QJsonArray::const_iterator instead. It is generally a good practice to + use QJsonArray::const_iterator on a non-const QJsonArray as well, unless + you need to change the QJsonArray through the iterator. Const + iterators are slightly faster and improves code readability. + + The default QJsonArray::iterator constructor creates an uninitialized + iterator. You must initialize it using a QJsonArray function like + QJsonArray::begin(), QJsonArray::end(), or QJsonArray::insert() before you can + start iterating. + + Most QJsonArray functions accept an integer index rather than an + iterator. For that reason, iterators are rarely useful in + connection with QJsonArray. One place where STL-style iterators do + make sense is as arguments to \l{generic algorithms}. + + Multiple iterators can be used on the same array. However, be + aware that any non-const function call performed on the QJsonArray + will render all existing iterators undefined. + + \sa QJsonArray::const_iterator +*/ + +/*! \typedef QJsonArray::iterator::iterator_category + + A synonym for \e {std::random_access_iterator_tag} indicating + this iterator is a random access iterator. +*/ + +/*! \typedef QJsonArray::iterator::difference_type + + \internal +*/ + +/*! \typedef QJsonArray::iterator::value_type + + \internal +*/ + +/*! \typedef QJsonArray::iterator::reference + + \internal +*/ + +/*! \typedef QJsonArray::iterator::pointer + + \internal +*/ + +/*! \fn QJsonArray::iterator::iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterator. Use operator=() to assign a value + to it before using it. + + \sa QJsonArray::begin(), QJsonArray::end() +*/ + +/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, int index) + \internal +*/ + +/*! \fn QJsonValueRef QJsonArray::iterator::operator*() const + + + Returns a modifiable reference to the current item. + + You can change the value of an item by using operator*() on the + left side of an assignment. + + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can + use it as if it were a reference to a QJsonValue. If you assign to it, + the assignment will apply to the character in the QJsonArray of QJsonObject + 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 + item pointed to by this iterator (the item at position \c{*this + j}). + + This function is provided to make QJsonArray iterators behave like C++ + pointers. + + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can + use it as if it were a reference to a QJsonValue. If you assign to it, + the assignment will apply to the character in the QJsonArray of QJsonObject + from which you got the reference. + + \sa operator+() +*/ + +/*! + \fn bool QJsonArray::iterator::operator==(const iterator &other) const + \fn bool QJsonArray::iterator::operator==(const const_iterator &other) const + + Returns \c true if \a other points to the same item as this + iterator; otherwise returns \c false. + + \sa operator!=() +*/ + +/*! + \fn bool QJsonArray::iterator::operator!=(const iterator &other) const + \fn bool QJsonArray::iterator::operator!=(const const_iterator &other) const + + Returns \c true if \a other points to a different item than this + iterator; otherwise returns \c false. + + \sa operator==() +*/ + +/*! + \fn bool QJsonArray::iterator::operator<(const iterator& other) const + \fn bool QJsonArray::iterator::operator<(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is less than + the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::iterator::operator<=(const iterator& other) const + \fn bool QJsonArray::iterator::operator<=(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is less than + or equal to the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::iterator::operator>(const iterator& other) const + \fn bool QJsonArray::iterator::operator>(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is greater + than the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::iterator::operator>=(const iterator& other) const + \fn bool QJsonArray::iterator::operator>=(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is greater + than or equal to the item pointed to by the \a other iterator. +*/ + +/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator++() + + The prefix ++ operator, \c{++it}, advances the iterator to the + next item in the array and returns an iterator to the new current + item. + + Calling this function on QJsonArray::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QJsonArray::iterator QJsonArray::iterator::operator++(int) + + \overload + + The postfix ++ operator, \c{it++}, advances the iterator to the + next item in the array and returns an iterator to the previously + current item. +*/ + +/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator--() + + The prefix -- operator, \c{--it}, makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QJsonArray::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! \fn QJsonArray::iterator QJsonArray::iterator::operator--(int) + + \overload + + The postfix -- operator, \c{it--}, makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(int j) + + Advances the iterator by \a j items. If \a j is negative, the + iterator goes backward. + + \sa operator-=(), operator+() +*/ + +/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(int j) + + Makes the iterator go back by \a j items. If \a j is negative, + the iterator goes forward. + + \sa operator+=(), operator-() +*/ + +/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. If \a j is negative, the iterator goes backward. + + \sa operator-(), operator+=() +*/ + +/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. If \a j is negative, the iterator goes forward. + + \sa operator+(), operator-=() +*/ + +/*! \fn int QJsonArray::iterator::operator-(iterator other) const + + Returns the number of items between the item pointed to by \a + other and the item pointed to by this iterator. +*/ + +/*! \class QJsonArray::const_iterator + \inmodule QtCore + \brief The QJsonArray::const_iterator class provides an STL-style const iterator for QJsonArray. + + QJsonArray::const_iterator allows you to iterate over a + QJsonArray. If you want to modify the QJsonArray as + you iterate over it, use QJsonArray::iterator instead. It is generally a + good practice to use QJsonArray::const_iterator on a non-const QJsonArray + as well, unless you need to change the QJsonArray through the + iterator. Const iterators are slightly faster and improves + code readability. + + The default QJsonArray::const_iterator constructor creates an + uninitialized iterator. You must initialize it using a QJsonArray + function like QJsonArray::constBegin(), QJsonArray::constEnd(), or + QJsonArray::insert() before you can start iterating. + + Most QJsonArray functions accept an integer index rather than an + iterator. For that reason, iterators are rarely useful in + connection with QJsonArray. One place where STL-style iterators do + make sense is as arguments to \l{generic algorithms}. + + Multiple iterators can be used on the same array. However, be + aware that any non-const function call performed on the QJsonArray + will render all existing iterators undefined. + + \sa QJsonArray::iterator +*/ + +/*! \fn QJsonArray::const_iterator::const_iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterator. Use operator=() to assign a value + to it before using it. + + \sa QJsonArray::constBegin(), QJsonArray::constEnd() +*/ + +/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, int index) + \internal +*/ + +/*! \typedef QJsonArray::const_iterator::iterator_category + + A synonym for \e {std::random_access_iterator_tag} indicating + this iterator is a random access iterator. +*/ + +/*! \typedef QJsonArray::const_iterator::difference_type + + \internal +*/ + +/*! \typedef QJsonArray::const_iterator::value_type + + \internal +*/ + +/*! \typedef QJsonArray::const_iterator::reference + + \internal +*/ + +/*! \typedef QJsonArray::const_iterator::pointer + + \internal +*/ + +/*! \fn QJsonArray::const_iterator::const_iterator(const const_iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn QJsonArray::const_iterator::const_iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn QJsonValue QJsonArray::const_iterator::operator*() 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 + position \c{*this + j}). + + This function is provided to make QJsonArray iterators behave like C++ + pointers. + + \sa operator+() +*/ + +/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &other) const + + Returns \c true if \a other points to the same item as this + iterator; otherwise returns \c false. + + \sa operator!=() +*/ + +/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &other) const + + Returns \c true if \a other points to a different item than this + iterator; otherwise returns \c false. + + \sa operator==() +*/ + +/*! + \fn bool QJsonArray::const_iterator::operator<(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is less than + the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::const_iterator::operator<=(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is less than + or equal to the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::const_iterator::operator>(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is greater + than the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QJsonArray::const_iterator::operator>=(const const_iterator& other) const + + Returns \c true if the item pointed to by this iterator is greater + than or equal to the item pointed to by the \a other iterator. +*/ + +/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator++() + + The prefix ++ operator, \c{++it}, advances the iterator to the + next item in the array and returns an iterator to the new current + item. + + Calling this function on QJsonArray::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator++(int) + + \overload + + The postfix ++ operator, \c{it++}, advances the iterator to the + next item in the array and returns an iterator to the previously + current item. +*/ + +/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator--() + + The prefix -- operator, \c{--it}, makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QJsonArray::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator--(int) + + \overload + + The postfix -- operator, \c{it--}, makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(int j) + + Advances the iterator by \a j items. If \a j is negative, the + iterator goes backward. + + \sa operator-=(), operator+() +*/ + +/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j items. If \a j is negative, + the iterator goes forward. + + \sa operator+=(), operator-() +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. If \a j is negative, the iterator goes backward. + + \sa operator-(), operator+=() +*/ + +/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. If \a j is negative, the iterator goes forward. + + \sa operator+(), operator-=() +*/ + +/*! \fn int QJsonArray::const_iterator::operator-(const_iterator other) const + + Returns the number of items between the item pointed to by \a + other and the item pointed to by this iterator. +*/ + + +/*! + \internal + */ +void QJsonArray::detach(uint reserve) +{ + Q_UNUSED(reserve) + Q_ASSERT(!reserve); + detach2(0); +} + +/*! + \internal + */ +bool QJsonArray::detach2(uint reserve) +{ + if (!d) { + if (reserve >= QJsonPrivate::Value::MaxSize) { + qWarning("QJson: Document too large to store in data structure"); + return false; + } + d = new QJsonPrivate::Data(reserve, QJsonValue::Array); + a = static_cast(d->header->root()); + d->ref.ref(); + return true; + } + if (reserve == 0 && d->ref.load() == 1) + return true; + + QJsonPrivate::Data *x = d->clone(a, reserve); + if (!x) + return false; + x->ref.ref(); + if (!d->ref.deref()) + delete d; + d = x; + a = static_cast(d->header->root()); + return true; +} + +/*! + \internal + */ +void QJsonArray::compact() +{ + if (!d || !d->compactionCounter) + return; + + detach2(); + d->compact(); + a = static_cast(d->header->root()); +} + + +#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) +QDebug operator<<(QDebug dbg, const QJsonArray &a) +{ + QDebugStateSaver saver(dbg); + if (!a.a) { + dbg << "QJsonArray()"; + return dbg; + } + QByteArray json; + QJsonPrivate::Writer::arrayToJson(a.a, json, 0, true); + dbg.nospace() << "QJsonArray(" + << json.constData() // print as utf-8 string without extra quotation marks + << ")"; + return dbg; +} +#endif + +QT_END_NAMESPACE + diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 2336278b17f..ca8bd306983 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -200,7 +200,7 @@ qnx:qtConfig(qqnx_pps) { kernel/qppsobjectprivate_p.h } -android { +android:!android-embedded { SOURCES += \ kernel/qjnionload.cpp \ kernel/qjnihelpers.cpp \ diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 4bab0b9f017..4e32f909643 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -95,7 +95,7 @@ #endif #endif // QT_NO_QOBJECT -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) # include # include #endif @@ -186,7 +186,7 @@ QString QCoreApplicationPrivate::appVersion() const #ifndef QT_BOOTSTRAPPED # ifdef Q_OS_DARWIN applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion")); -# elif defined(Q_OS_ANDROID) +# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QJNIObjectPrivate context(QtAndroidPrivate::context()); if (context.isValid()) { QJNIObjectPrivate pm = context.callObjectMethod( @@ -538,29 +538,10 @@ void QCoreApplicationPrivate::cleanupThreadData() void QCoreApplicationPrivate::createEventDispatcher() { Q_Q(QCoreApplication); -#if defined(Q_OS_UNIX) -# if defined(Q_OS_DARWIN) - bool ok = false; - int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); - if (ok && value > 0) - eventDispatcher = new QEventDispatcherCoreFoundation(q); - else - eventDispatcher = new QEventDispatcherUNIX(q); -# elif !defined(QT_NO_GLIB) - if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported()) - eventDispatcher = new QEventDispatcherGlib(q); - else - eventDispatcher = new QEventDispatcherUNIX(q); -# else - eventDispatcher = new QEventDispatcherUNIX(q); -# endif -#elif defined(Q_OS_WINRT) - eventDispatcher = new QEventDispatcherWinRT(q); -#elif defined(Q_OS_WIN) - eventDispatcher = new QEventDispatcherWin32(q); -#else -# error "QEventDispatcher not yet ported to this platform" -#endif + QThreadData *data = QThreadData::current(); + Q_ASSERT(!data->hasEventDispatcher()); + eventDispatcher = QThreadPrivate::createEventDispatcher(data); + eventDispatcher->setParent(q); } void QCoreApplicationPrivate::eventDispatcherReady() @@ -816,6 +797,14 @@ void QCoreApplicationPrivate::init() if (!coreappdata()->applicationVersionSet) coreappdata()->applicationVersion = appVersion(); +#if defined(Q_OS_ANDROID) + // We've deferred initializing the logging registry due to not being + // able to guarantee that logging happened on the same thread as the + // Qt main thread, but now that the Qt main thread is set up, we can + // enable categorized logging. + QLoggingRegistry::instance()->initializeRules(); +#endif + #if QT_CONFIG(library) // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0] // into account. If necessary, recompute right away and replay the manual changes on top of the @@ -848,8 +837,9 @@ void QCoreApplicationPrivate::init() #ifndef QT_NO_QOBJECT // use the event dispatcher created by the app programmer (if any) - if (!eventDispatcher) - eventDispatcher = threadData->eventDispatcher.load(); + Q_ASSERT(!eventDispatcher); + eventDispatcher = threadData->eventDispatcher.load(); + // otherwise we create one if (!eventDispatcher) createEventDispatcher(); @@ -2266,7 +2256,7 @@ QString QCoreApplication::applicationFilePath() } #endif #if defined( Q_OS_UNIX ) -# if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) +# if defined(Q_OS_LINUX) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED)) // Try looking for a /proc//exe symlink first which points to // the absolute path of the executable QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid())); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index bbd442d5704..330870f2198 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -905,6 +905,7 @@ bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) return true; d->winEventNotifierList.append(notifier); + d->winEventNotifierListModified = true; if (!d->winEventNotifierActivatedEvent) d->winEventNotifierActivatedEvent = CreateEvent(0, TRUE, FALSE, nullptr); @@ -928,6 +929,7 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) if (i == -1) return; d->winEventNotifierList.takeAt(i); + d->winEventNotifierListModified = true; QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); if (nd->waitHandle) nd->unregisterWaitObject(); @@ -938,16 +940,19 @@ void QEventDispatcherWin32::activateEventNotifiers() Q_D(QEventDispatcherWin32); ResetEvent(d->winEventNotifierActivatedEvent); - // Iterate backwards, because the notifier might remove itself on activate(). - for (int i = d->winEventNotifierList.count(); --i >= 0;) { - QWinEventNotifier *notifier = d->winEventNotifierList.at(i); - QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); - if (nd->signaledCount.load() != 0) { - --nd->signaledCount; - nd->unregisterWaitObject(); - d->activateEventNotifier(notifier); + // Activate signaled notifiers. Our winEventNotifierList can be modified in activation slots. + do { + d->winEventNotifierListModified = false; + for (int i = 0; i < d->winEventNotifierList.count(); ++i) { + QWinEventNotifier *notifier = d->winEventNotifierList.at(i); + QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); + if (nd->signaledCount.load() != 0) { + --nd->signaledCount; + nd->unregisterWaitObject(); + d->activateEventNotifier(notifier); + } } - } + } while (d->winEventNotifierListModified); // Re-register the remaining activated notifiers. for (int i = 0; i < d->winEventNotifierList.count(); ++i) { diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 683c7f8f36a..a7ed8dda8aa 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -195,6 +195,7 @@ public: HANDLE winEventNotifierActivatedEvent; QList winEventNotifierList; + bool winEventNotifierListModified = false; void activateEventNotifier(QWinEventNotifier * wen); QList queuedUserInputEvents; diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 8974ff77097..6034698349d 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -101,8 +101,10 @@ QEventLoop::QEventLoop(QObject *parent) Q_D(QEventLoop); if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) { qWarning("QEventLoop: Cannot be used without QApplication"); - } else if (!d->threadData->eventDispatcher.load()) { - QThreadPrivate::createEventDispatcher(d->threadData); + } else if (!d->threadData->hasEventDispatcher()) { + QAbstractEventDispatcher *eventDispatcher = QThreadPrivate::createEventDispatcher(d->threadData); + d->threadData->eventDispatcher.storeRelease(eventDispatcher); + eventDispatcher->startingUp(); } } @@ -129,7 +131,7 @@ QEventLoop::~QEventLoop() bool QEventLoop::processEvents(ProcessEventsFlags flags) { Q_D(QEventLoop); - if (!d->threadData->eventDispatcher.load()) + if (!d->threadData->hasEventDispatcher()) return false; return d->threadData->eventDispatcher.load()->processEvents(flags); } @@ -234,7 +236,7 @@ int QEventLoop::exec(ProcessEventsFlags flags) void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) { Q_D(QEventLoop); - if (!d->threadData->eventDispatcher.load()) + if (!d->threadData->hasEventDispatcher()) return; QElapsedTimer start; @@ -263,7 +265,7 @@ void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) void QEventLoop::exit(int returnCode) { Q_D(QEventLoop); - if (!d->threadData->eventDispatcher.load()) + if (!d->threadData->hasEventDispatcher()) return; d->returnCode.store(returnCode); @@ -292,7 +294,7 @@ bool QEventLoop::isRunning() const void QEventLoop::wakeUp() { Q_D(QEventLoop); - if (!d->threadData->eventDispatcher.load()) + if (!d->threadData->hasEventDispatcher()) return; d->threadData->eventDispatcher.load()->wakeUp(); } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 263c4019f7a..9e1c3a50cbb 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -238,7 +238,7 @@ QObjectPrivate::~QObjectPrivate() if (extraData && !extraData->runningTimers.isEmpty()) { if (Q_LIKELY(threadData->thread == QThread::currentThread())) { // unregister pending timers - if (threadData->eventDispatcher.load()) + if (threadData->hasEventDispatcher()) threadData->eventDispatcher.load()->unregisterTimers(q_ptr); // release the timer ids back to the pool @@ -1538,7 +1538,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData ++eventsMoved; } } - if (eventsMoved > 0 && targetData->eventDispatcher.load()) { + if (eventsMoved > 0 && targetData->hasEventDispatcher()) { targetData->canWait = false; targetData->eventDispatcher.load()->wakeUp(); } @@ -1621,7 +1621,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) qWarning("QObject::startTimer: Timers cannot have negative intervals"); return 0; } - if (Q_UNLIKELY(!d->threadData->eventDispatcher.load())) { + if (Q_UNLIKELY(!d->threadData->hasEventDispatcher())) { qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); return 0; } @@ -1703,7 +1703,7 @@ void QObject::killTimer(int id) return; } - if (d->threadData->eventDispatcher.load()) + if (d->threadData->hasEventDispatcher()) d->threadData->eventDispatcher.load()->unregisterTimer(id); d->extraData->runningTimers.remove(at); diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index 2268cb83bb0..6ff82689782 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -149,7 +149,7 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent) if (socket < 0) qWarning("QSocketNotifier: Invalid socket specified"); - else if (!d->threadData->eventDispatcher.load()) + else if (!d->threadData->hasEventDispatcher()) qWarning("QSocketNotifier: Can only be used with threads started with QThread"); else d->threadData->eventDispatcher.load()->registerSocketNotifier(this); @@ -234,7 +234,7 @@ void QSocketNotifier::setEnabled(bool enable) return; d->snenabled = enable; - if (!d->threadData->eventDispatcher.load()) // perhaps application/thread is shutting down + if (!d->threadData->hasEventDispatcher()) // perhaps application/thread is shutting down return; if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread"); diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index bca6918b4a0..a3b8be89115 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -239,21 +239,34 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib) if (lib) lib->errorString = file.errorString(); if (qt_debug_component()) { - qWarning("%s: %s", (const char*) QFile::encodeName(library), + qWarning("%s: %s", QFile::encodeName(library).constData(), qPrintable(QSystemError::stdString())); } return false; } QByteArray data; - const char *filedata = 0; ulong fdlen = file.size(); - filedata = (char *) file.map(0, fdlen); + const char *filedata = reinterpret_cast(file.map(0, fdlen)); + if (filedata == 0) { - // try reading the data into memory instead - data = file.readAll(); - filedata = data.constData(); - fdlen = data.size(); + if (uchar *mapdata = file.map(0, 1)) { + file.unmap(mapdata); + // Mapping is supported, but failed for the entire file, likely due to OOM. + // Return false, as readAll() would cause a bad_alloc and terminate the process. + if (lib) + lib->errorString = QLibrary::tr("Out of memory while loading plugin '%1'.").arg(library); + if (qt_debug_component()) { + qWarning("%s: %s", QFile::encodeName(library).constData(), + qPrintable(QSystemError::stdString(ENOMEM))); + } + return false; + } else { + // Try reading the data into memory instead. + data = file.readAll(); + filedata = data.constData(); + fdlen = data.size(); + } } /* @@ -751,7 +764,7 @@ void QLibraryPrivate::updatePluginState() if (qt_debug_component()) { qWarning("In %s:\n" " Plugin uses incompatible Qt library (%d.%d.%d) [%s]", - (const char*) QFile::encodeName(fileName), + QFile::encodeName(fileName).constData(), (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff, debug ? "debug" : "release"); } diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 3c4fbaf348e..23b9ad6434f 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -44,25 +44,17 @@ #include #include +#include + #ifdef Q_OS_MAC # include #endif QT_BEGIN_NAMESPACE -#if !defined(QT_HPUX_LD) -QT_BEGIN_INCLUDE_NAMESPACE -#include -QT_END_INCLUDE_NAMESPACE -#endif - static QString qdlerror() { -#if !defined(QT_HPUX_LD) const char *err = dlerror(); -#else - const char *err = strerror(errno); -#endif return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString(); } @@ -139,14 +131,6 @@ bool QLibraryPrivate::load_sys() suffixes = suffixes_sys(fullVersion); } int dlFlags = 0; -#if defined(QT_HPUX_LD) - dlFlags = DYNAMIC_PATH | BIND_NONFATAL; - if (loadHints & QLibrary::ResolveAllSymbolsHint) { - dlFlags |= BIND_IMMEDIATE; - } else { - dlFlags |= BIND_DEFERRED; - } -#else int loadHints = this->loadHints(); if (loadHints & QLibrary::ResolveAllSymbolsHint) { dlFlags |= RTLD_NOW; @@ -182,7 +166,6 @@ bool QLibraryPrivate::load_sys() dlFlags |= RTLD_MEMBER; } #endif -#endif // QT_HPUX_LD // If the filename is an absolute path then we want to try that first as it is most likely // what the callee wants. If we have been given a non-absolute path then lets try the @@ -211,11 +194,7 @@ bool QLibraryPrivate::load_sys() } else { attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); } -#if defined(QT_HPUX_LD) - pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0); -#else pHnd = dlopen(QFile::encodeName(attempt), dlFlags); -#endif if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { // We only want to continue if dlopen failed due to that the shared library did not exist. @@ -253,11 +232,7 @@ bool QLibraryPrivate::load_sys() bool QLibraryPrivate::unload_sys() { -#if defined(QT_HPUX_LD) - if (shl_unload((shl_t)pHnd)) { -#else if (dlclose(pHnd)) { -#endif #if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative" @@ -289,13 +264,7 @@ Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symb QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) { -#if defined(QT_HPUX_LD) - QFunctionPointer address = 0; - if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0) - address = 0; -#else QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol)); -#endif if (!address) { errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( QString::fromLatin1(symbol), fileName, qdlerror()); diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index baeefd87ffc..46294a5fc8a 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -195,7 +195,7 @@ public: #endif // Q_OS_WIN QThreadData *data; - static void createEventDispatcher(QThreadData *data); + static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data); void ref() { @@ -222,7 +222,7 @@ public: static void setCurrentThread(QThread*) {} static QThread *threadForId(int) { return QThread::currentThread(); } - static void createEventDispatcher(QThreadData *data); + static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data); void ref() {} void deref() {} diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 1bb8e613e04..6248842d78d 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -285,27 +285,27 @@ typedef void*(*QtThreadCallback)(void*); #endif // QT_NO_THREAD -void QThreadPrivate::createEventDispatcher(QThreadData *data) +QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data) { + Q_UNUSED(data); #if defined(Q_OS_DARWIN) bool ok = false; int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); if (ok && value > 0) - data->eventDispatcher.storeRelease(new QEventDispatcherCoreFoundation); + return new QEventDispatcherCoreFoundation; else - data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); + return new QEventDispatcherUNIX; #elif !defined(QT_NO_GLIB) + const bool isQtMainThread = data->thread == QCoreApplicationPrivate::mainThread(); if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") - && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB") + && (isQtMainThread || qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) && QEventDispatcherGlib::versionSupported()) - data->eventDispatcher.storeRelease(new QEventDispatcherGlib); + return new QEventDispatcherGlib; else - data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); + return new QEventDispatcherUNIX; #else - data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); + return new QEventDispatcherUNIX; #endif - - data->eventDispatcher.load()->startingUp(); } #ifndef QT_NO_THREAD @@ -352,10 +352,13 @@ void *QThreadPrivate::start(void *arg) data->quitNow = thr->d_func()->exited; } - if (data->eventDispatcher.load()) // custom event dispatcher set? - data->eventDispatcher.load()->startingUp(); - else - createEventDispatcher(data); + QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load(); + if (!eventDispatcher) { + eventDispatcher = createEventDispatcher(data); + data->eventDispatcher.storeRelease(eventDispatcher); + } + + eventDispatcher->startingUp(); #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) { diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 24d3ca2d7d0..4459ae87af7 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -331,15 +331,14 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) #endif // QT_NO_THREAD -void QThreadPrivate::createEventDispatcher(QThreadData *data) +QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data) { + Q_UNUSED(data); #ifndef Q_OS_WINRT - QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; + return new QEventDispatcherWin32; #else - QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT; + return new QEventDispatcherWinRT; #endif - data->eventDispatcher.storeRelease(theEventDispatcher); - theEventDispatcher->startingUp(); } #ifndef QT_NO_THREAD @@ -360,10 +359,13 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi data->quitNow = thr->d_func()->exited; } - if (data->eventDispatcher.load()) // custom event dispatcher set? - data->eventDispatcher.load()->startingUp(); - else - createEventDispatcher(data); + QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load(); + if (!eventDispatcher) { + eventDispatcher = createEventDispatcher(data); + data->eventDispatcher.storeRelease(eventDispatcher); + } + + eventDispatcher->startingUp(); #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT) // sets the name of the current thread. diff --git a/src/corelib/tools/CLDR_LICENSE.txt b/src/corelib/tools/UNICODE_LICENSE.txt similarity index 96% rename from src/corelib/tools/CLDR_LICENSE.txt rename to src/corelib/tools/UNICODE_LICENSE.txt index ad28161436d..1c73202b743 100644 --- a/src/corelib/tools/CLDR_LICENSE.txt +++ b/src/corelib/tools/UNICODE_LICENSE.txt @@ -1,4 +1,4 @@ -Copyright © 1991-2016 Unicode, Inc. All rights reserved. +Copyright © 1991-2018 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index b7c3bc1287c..d0f83d2b6a9 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -76,7 +76,8 @@ struct QPodArrayOps Q_ASSERT(b < e); Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size)); - ::memcpy(this->end(), b, (e - b) * sizeof(T)); + ::memcpy(static_cast(this->end()), static_cast(b), + (e - b) * sizeof(T)); this->size += e - b; } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 1e676365b06..b465bdc0f49 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3855,14 +3855,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after) while (i < pos) { int copyend = replacements[i].pos; int size = copyend - copystart; - memcpy(uc, d->data() + copystart, size * sizeof(QChar)); + memcpy(static_cast(uc), static_cast(d->data() + copystart), size * sizeof(QChar)); uc += size; - memcpy(uc, after.d->data(), al * sizeof(QChar)); + memcpy(static_cast(uc), static_cast(after.d->data()), al * sizeof(QChar)); uc += al; copystart = copyend + replacements[i].length; i++; } - memcpy(uc, d->data() + copystart, (d->size - copystart) * sizeof(QChar)); + memcpy(static_cast(uc), static_cast(d->data() + copystart), (d->size - copystart) * sizeof(QChar)); newstring.resize(newlen); *this = newstring; caretMode = QRegExp::CaretWontMatch; @@ -6353,7 +6353,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const while (padlen--) * uc++ = fill; if (len) - memcpy(uc, d->data(), sizeof(QChar)*len); + memcpy(static_cast(uc), static_cast(d->data()), sizeof(QChar)*len); } else { if (truncate) result = left(width); @@ -6931,6 +6931,8 @@ QString QString::vasprintf(const char *cformat, va_list ap) \snippet qstring/main.cpp 74 + This function ignores leading and trailing whitespace. + \sa number(), toULongLong(), toInt(), QLocale::toLongLong() */ @@ -6971,6 +6973,8 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b \snippet qstring/main.cpp 79 + This function ignores leading and trailing whitespace. + \sa number(), toLongLong(), QLocale::toULongLong() */ @@ -7013,6 +7017,8 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int \snippet qstring/main.cpp 73 + This function ignores leading and trailing whitespace. + \sa number(), toULong(), toInt(), QLocale::toInt() */ @@ -7042,6 +7048,8 @@ long QString::toLong(bool *ok, int base) const \snippet qstring/main.cpp 78 + This function ignores leading and trailing whitespace. + \sa number(), QLocale::toUInt() */ @@ -7070,6 +7078,8 @@ ulong QString::toULong(bool *ok, int base) const \snippet qstring/main.cpp 72 + This function ignores leading and trailing whitespace. + \sa number(), toUInt(), toDouble(), QLocale::toInt() */ @@ -7097,6 +7107,8 @@ int QString::toInt(bool *ok, int base) const \snippet qstring/main.cpp 77 + This function ignores leading and trailing whitespace. + \sa number(), toInt(), QLocale::toUInt() */ @@ -7124,6 +7136,8 @@ uint QString::toUInt(bool *ok, int base) const \snippet qstring/main.cpp 76 + This function ignores leading and trailing whitespace. + \sa number(), toUShort(), toInt(), QLocale::toShort() */ @@ -7151,6 +7165,8 @@ short QString::toShort(bool *ok, int base) const \snippet qstring/main.cpp 80 + This function ignores leading and trailing whitespace. + \sa number(), toShort(), QLocale::toUShort() */ @@ -7170,7 +7186,10 @@ ushort QString::toUShort(bool *ok, int base) const \snippet qstring/main.cpp 66 - \warning The QString content may only contain valid numerical characters which includes the plus/minus sign, the characters g and e used in scientific notation, and the decimal point. Including the unit or additional characters leads to a conversion error. + \warning The QString content may only contain valid numerical characters + which includes the plus/minus sign, the characters g and e used in scientific + notation, and the decimal point. Including the unit or additional characters + leads to a conversion error. \snippet qstring/main.cpp 67 @@ -7185,6 +7204,8 @@ ushort QString::toUShort(bool *ok, int base) const \snippet qstring/main.cpp 69 + This function ignores leading and trailing whitespace. + \sa number(), QLocale::setDefault(), QLocale::toDouble(), trimmed() */ @@ -7199,6 +7220,8 @@ double QString::toDouble(bool *ok) const If a conversion error occurs, *\a{ok} is set to \c false; otherwise *\a{ok} is set to \c true. Returns 0.0 if the conversion fails. + This function ignores leading and trailing whitespace. + The string conversion will always happen in the 'C' locale. For locale dependent conversion use QLocale::toFloat() @@ -7206,6 +7229,8 @@ double QString::toDouble(bool *ok) const \snippet qstring/main.cpp 71 + This function ignores leading and trailing whitespace. + \sa number(), toDouble(), toInt(), QLocale::toFloat() */ @@ -11878,7 +11903,7 @@ QString QString::toHtmlEscaped() const This cost can be avoided by using QStringLiteral instead: \code - if (node.hasAttribute(QStringLiteral("http-contents-length"))) //... + if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //... \endcode In this case, QString's internal data will be generated at compile time; no @@ -11898,6 +11923,10 @@ QString QString::toHtmlEscaped() const if (attribute.name() == QLatin1String("http-contents-length")) //... \endcode + \note Some compilers have bugs encoding strings containing characters outside + the US-ASCII character set. Make sure you prefix your string with \c{u} in + those cases. It is optional otherwise. + \sa QByteArrayLiteral */ diff --git a/src/corelib/tools/qt_attribution.json b/src/corelib/tools/qt_attribution.json index eec2cd67959..49a76cb8b48 100644 --- a/src/corelib/tools/qt_attribution.json +++ b/src/corelib/tools/qt_attribution.json @@ -1,13 +1,35 @@ +[ { - "Id": "cldr-data", - "Name": "Unicode CLDR (Unicode Common Locale Data Repository)", + "Id": "unicode-character-database", + "Name": "Unicode Character Database (UCD)", "QDocModule": "qtcore", - "QtUsage": "Used in Qt Core (QTimeZone). Disable the timezone feature to avoid.", - "Files": "qlocale_data_p.h", + "QtUsage": "Qt Core uses data obtained from UCD files for working with characters and strings.", + "Files": "qunicodetables_p.h qunicodetables.cpp", - "Description": "QTimeZone includes data obtained from the CLDR data files.", - "License": "Unicode Data Files and Software License", - "LicenseId": "Unicode-TOU", - "LicenseFile": "CLDR_LICENSE.txt", - "Copyright": "Copyright (C) 1991-2016 Unicode, Inc." + "Description": "The Unicode Character Database (UCD) is a set of files that + define the Unicode character properties and internal mappings.", + "Homepage": "https://www.unicode.org/ucd/", + "Version": "10.0.0", + "License": "Unicode License Agreement - Data Files and Software (2016)", + "LicenseId": "Unicode-DFS-2016", + "LicenseFile": "UNICODE_LICENSE.txt", + "Copyright": "Copyright (C) 1991-2018 Unicode, Inc." +}, +{ + "Id": "unicode-cldr", + "Name": "Unicode Common Locale Data Repository (CLDR)", + "QDocModule": "qtcore", + "QtUsage": "Used in Qt Core (QTimeZone, QLocale).", + "Files": "qlocale_data_p.h qtimezoneprivate_data_p.h", + + "Description": "The Unicode CLDR provides key building blocks for software to support the + world's languages, with the largest and most extensive standard repository of locale data + available.", + "Homepage": "http://cldr.unicode.org/", + "Version": "v31.0.1", + "License": "Unicode License Agreement - Data Files and Software (2016)", + "LicenseId": "Unicode-DFS-2016", + "LicenseFile": "UNICODE_LICENSE.txt", + "Copyright": "Copyright (C) 1991-2017 Unicode, Inc." } +] diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index a9a9b4f25e1..29299bfcd63 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -62,9 +62,9 @@ static QTimeZonePrivate *newBackendTimeZone() #else #if defined Q_OS_MAC return new QMacTimeZonePrivate(); -#elif defined Q_OS_ANDROID +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) return new QAndroidTimeZonePrivate(); -#elif defined Q_OS_UNIX +#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(); @@ -88,9 +88,9 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) #else #if defined Q_OS_MAC return new QMacTimeZonePrivate(ianaId); -#elif defined Q_OS_ANDROID +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) return new QAndroidTimeZonePrivate(ianaId); -#elif defined Q_OS_UNIX +#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(ianaId); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(ianaId); diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index ca36f9d297a..4d357111f28 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -68,7 +68,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone); #include #endif // Q_OS_WIN -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #include #endif @@ -266,7 +266,7 @@ private: }; #endif -#if defined Q_OS_UNIX && !defined Q_OS_MAC && !defined Q_OS_ANDROID +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED)) struct QTzTransitionTime { qint64 atMSecsSinceEpoch; @@ -442,7 +442,7 @@ private: }; #endif // Q_OS_WIN -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) class QAndroidTimeZonePrivate final : public QTimeZonePrivate { public: diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index b2f05452ae7..d0088471c7a 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -344,7 +344,7 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray::append(const T *abuf, in while (s < asize) new (ptr+(s++)) T(*abuf++); } else { - memcpy(&ptr[s], abuf, increment * sizeof(T)); + memcpy(static_cast(&ptr[s]), static_cast(abuf), increment * sizeof(T)); s = asize; } } @@ -392,7 +392,7 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray::realloc(int asize, int a QT_RETHROW; } } else { - memcpy(ptr, oldPtr, copySize * sizeof(T)); + memcpy(static_cast(ptr), static_cast(oldPtr), copySize * sizeof(T)); } } s = copySize; diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 24a19e68d4b..9a6e67cc0bf 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -747,7 +747,7 @@ typename QVector::iterator QVector::insert(iterator before, size_type n, c } else { T *b = d->begin() + offset; T *i = b + n; - memmove(i, b, (d->size - offset) * sizeof(T)); + memmove(static_cast(i), static_cast(b), (d->size - offset) * sizeof(T)); while (i != b) new (--i) T(copy); } diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 86afb46b8a8..88708851d76 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -161,7 +161,7 @@ qtConfig(timezone) { tools/qtimezoneprivate.cpp !nacl:darwin: { SOURCES += tools/qtimezoneprivate_mac.mm - } else: android: { + } else: android:!android-embedded: { SOURCES += tools/qtimezoneprivate_android.cpp } else: unix: { SOURCES += tools/qtimezoneprivate_tz.cpp diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h new file mode 100644 index 00000000000..e6c89e40cd5 --- /dev/null +++ b/src/corelib/xml/qxmlstream_p.h @@ -0,0 +1,1966 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +// This file was generated by qlalr - DO NOT EDIT! +#ifndef QXMLSTREAM_P_H +#define QXMLSTREAM_P_H + +#if defined(ERROR) +# undef ERROR +#endif + +class QXmlStreamReader_Table +{ +public: + enum VariousConstants { + EOF_SYMBOL = 0, + AMPERSAND = 5, + ANY = 41, + ATTLIST = 31, + BANG = 25, + CDATA = 47, + CDATA_START = 28, + COLON = 17, + COMMA = 19, + DASH = 20, + DBLQUOTE = 8, + DIGIT = 27, + DOCTYPE = 29, + DOT = 23, + ELEMENT = 30, + EMPTY = 40, + ENTITIES = 51, + ENTITY = 32, + ENTITY_DONE = 45, + EQ = 14, + ERROR = 43, + FIXED = 39, + HASH = 6, + ID = 48, + IDREF = 49, + IDREFS = 50, + IMPLIED = 38, + LANGLE = 3, + LBRACK = 9, + LETTER = 26, + LPAREN = 11, + NDATA = 36, + NMTOKEN = 52, + NMTOKENS = 53, + NOTATION = 33, + NOTOKEN = 1, + PARSE_ENTITY = 44, + PCDATA = 42, + PERCENT = 15, + PIPE = 13, + PLUS = 21, + PUBLIC = 35, + QUESTIONMARK = 24, + QUOTE = 7, + RANGLE = 4, + RBRACK = 10, + REQUIRED = 37, + RPAREN = 12, + SEMICOLON = 18, + SHIFT_THERE = 56, + SLASH = 16, + SPACE = 2, + STAR = 22, + SYSTEM = 34, + UNRESOLVED_ENTITY = 46, + VERSION = 55, + XML = 54, + + ACCEPT_STATE = 416, + RULE_COUNT = 270, + STATE_COUNT = 427, + TERMINAL_COUNT = 57, + NON_TERMINAL_COUNT = 84, + + GOTO_INDEX_OFFSET = 427, + GOTO_INFO_OFFSET = 1017, + GOTO_CHECK_OFFSET = 1017 + }; + + static const char *const spell []; + static const short lhs []; + static const short rhs []; + static const short goto_default []; + static const short action_default []; + static const short action_index []; + static const short action_info []; + static const short action_check []; + + static inline int nt_action (int state, int nt) + { + const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; + if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) + return goto_default [nt]; + + return action_info [GOTO_INFO_OFFSET + yyn]; + } + + static inline int t_action (int state, int token) + { + const int yyn = action_index [state] + token; + + if (yyn < 0 || action_check [yyn] != token) + return - action_default [state]; + + return action_info [yyn]; + } +}; + + +const char *const QXmlStreamReader_Table::spell [] = { + "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[", + "]", "(", ")", "|", "=", "%", "/", ":", ";", ",", + "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE", + "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED", + "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF", + "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", " class QXmlStreamSimpleStack { + T *data; + int tos, cap; +public: + inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){} + inline ~QXmlStreamSimpleStack(){ if (data) free(data); } + + inline void reserve(int extraCapacity) { + if (tos + extraCapacity + 1 > cap) { + cap = qMax(tos + extraCapacity + 1, cap << 1 ); + void *ptr = realloc(static_cast(data), cap * sizeof(T)); + data = reinterpret_cast(ptr); + Q_CHECK_PTR(data); + } + } + + inline T &push() { reserve(1); return data[++tos]; } + inline T &rawPush() { return data[++tos]; } + inline const T &top() const { return data[tos]; } + inline T &top() { return data[tos]; } + inline T &pop() { return data[tos--]; } + inline T &operator[](int index) { return data[index]; } + inline const T &at(int index) const { return data[index]; } + inline int size() const { return tos + 1; } + inline void resize(int s) { tos = s - 1; } + inline bool isEmpty() const { return tos < 0; } + inline void clear() { tos = -1; } +}; + + +class QXmlStream +{ + Q_DECLARE_TR_FUNCTIONS(QXmlStream) +}; + +class QXmlStreamPrivateTagStack { +public: + struct NamespaceDeclaration + { + QStringRef prefix; + QStringRef namespaceUri; + }; + + struct Tag + { + QStringRef name; + QStringRef qualifiedName; + NamespaceDeclaration namespaceDeclaration; + int tagStackStringStorageSize; + int namespaceDeclarationsSize; + }; + + + QXmlStreamPrivateTagStack(); + QXmlStreamSimpleStack namespaceDeclarations; + QString tagStackStringStorage; + int tagStackStringStorageSize; + int initialTagStackStringStorageSize; + bool tagsDone; + + inline QStringRef addToStringStorage(const QStringRef &s) { + int pos = tagStackStringStorageSize; + int sz = s.size(); + if (pos != tagStackStringStorage.size()) + tagStackStringStorage.resize(pos); + tagStackStringStorage.insert(pos, s.unicode(), sz); + tagStackStringStorageSize += sz; + return QStringRef(&tagStackStringStorage, pos, sz); + } + inline QStringRef addToStringStorage(const QString &s) { + int pos = tagStackStringStorageSize; + int sz = s.size(); + if (pos != tagStackStringStorage.size()) + tagStackStringStorage.resize(pos); + tagStackStringStorage.insert(pos, s.unicode(), sz); + tagStackStringStorageSize += sz; + return QStringRef(&tagStackStringStorage, pos, sz); + } + + QXmlStreamSimpleStack tagStack; + + + inline Tag &tagStack_pop() { + Tag& tag = tagStack.pop(); + tagStackStringStorageSize = tag.tagStackStringStorageSize; + namespaceDeclarations.resize(tag.namespaceDeclarationsSize); + tagsDone = tagStack.isEmpty(); + return tag; + } + inline Tag &tagStack_push() { + Tag &tag = tagStack.push(); + tag.tagStackStringStorageSize = tagStackStringStorageSize; + tag.namespaceDeclarationsSize = namespaceDeclarations.size(); + return tag; + } +}; + + +class QXmlStreamEntityResolver; +#ifndef QT_NO_XMLSTREAMREADER +class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{ + QXmlStreamReader *q_ptr; + Q_DECLARE_PUBLIC(QXmlStreamReader) +public: + QXmlStreamReaderPrivate(QXmlStreamReader *q); + ~QXmlStreamReaderPrivate(); + void init(); + + QByteArray rawReadBuffer; + QByteArray dataBuffer; + uchar firstByte; + qint64 nbytesread; + QString readBuffer; + int readBufferPos; + QXmlStreamSimpleStack putStack; + struct Entity { + Entity(const QString& str = QString()) + :value(str), external(false), unparsed(false), literal(false), + hasBeenParsed(false), isCurrentlyReferenced(false){} + static inline Entity createLiteral(const QString &entity) + { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; } + QString value; + uint external : 1; + uint unparsed : 1; + uint literal : 1; + uint hasBeenParsed : 1; + uint isCurrentlyReferenced : 1; + }; + QHash entityHash; + QHash parameterEntityHash; + QXmlStreamSimpleStackentityReferenceStack; + inline bool referenceEntity(Entity &entity) { + if (entity.isCurrentlyReferenced) { + raiseWellFormedError(QXmlStream::tr("Recursive entity detected.")); + return false; + } + entity.isCurrentlyReferenced = true; + entityReferenceStack.push() = &entity; + injectToken(ENTITY_DONE); + return true; + } + + + QIODevice *device; + bool deleteDevice; +#ifndef QT_NO_TEXTCODEC + QTextCodec *codec; + QTextDecoder *decoder; +#endif + bool atEnd; + + /*! + \sa setType() + */ + QXmlStreamReader::TokenType type; + QXmlStreamReader::Error error; + QString errorString; + QString unresolvedEntity; + + qint64 lineNumber, lastLineStart, characterOffset; + + + void write(const QString &); + void write(const char *); + + + QXmlStreamAttributes attributes; + QStringRef namespaceForPrefix(const QStringRef &prefix); + void resolveTag(); + void resolvePublicNamespaces(); + void resolveDtd(); + uint resolveCharRef(int symbolIndex); + bool checkStartDocument(); + void startDocument(); + void parseError(); + void checkPublicLiteral(const QStringRef &publicId); + + bool scanDtd; + QStringRef lastAttributeValue; + bool lastAttributeIsCData; + struct DtdAttribute { + QStringRef tagName; + QStringRef attributeQualifiedName; + QStringRef attributePrefix; + QStringRef attributeName; + QStringRef defaultValue; + bool isCDATA; + bool isNamespaceAttribute; + }; + QXmlStreamSimpleStack dtdAttributes; + struct NotationDeclaration { + QStringRef name; + QStringRef publicId; + QStringRef systemId; + }; + QXmlStreamSimpleStack notationDeclarations; + QXmlStreamNotationDeclarations publicNotationDeclarations; + QXmlStreamNamespaceDeclarations publicNamespaceDeclarations; + + struct EntityDeclaration { + QStringRef name; + QStringRef notationName; + QStringRef publicId; + QStringRef systemId; + QStringRef value; + bool parameter; + bool external; + inline void clear() { + name.clear(); + notationName.clear(); + publicId.clear(); + systemId.clear(); + value.clear(); + parameter = external = false; + } + }; + QXmlStreamSimpleStack entityDeclarations; + QXmlStreamEntityDeclarations publicEntityDeclarations; + + QStringRef text; + + QStringRef prefix, namespaceUri, qualifiedName, name; + QStringRef processingInstructionTarget, processingInstructionData; + QStringRef dtdName, dtdPublicId, dtdSystemId; + QStringRef documentVersion, documentEncoding; + uint isEmptyElement : 1; + uint isWhitespace : 1; + uint isCDATA : 1; + uint standalone : 1; + uint hasCheckedStartDocument : 1; + uint normalizeLiterals : 1; + uint hasSeenTag : 1; + uint inParseEntity : 1; + uint referenceToUnparsedEntityDetected : 1; + uint referenceToParameterEntityDetected : 1; + uint hasExternalDtdSubset : 1; + uint lockEncoding : 1; + uint namespaceProcessing : 1; + + int resumeReduction; + void resume(int rule); + + inline bool entitiesMustBeDeclared() const { + return (!inParseEntity + && (standalone + || (!referenceToUnparsedEntityDetected + && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25 + && !hasExternalDtdSubset))); + } + + // qlalr parser + int tos; + int stack_size; + struct Value { + int pos; + int len; + int prefix; + ushort c; + }; + + Value *sym_stack; + int *state_stack; + inline void reallocateStack(); + inline Value &sym(int index) const + { return sym_stack[tos + index - 1]; } + QString textBuffer; + inline void clearTextBuffer() { + if (!scanDtd) { + textBuffer.resize(0); + textBuffer.reserve(256); + } + } + struct Attribute { + Value key; + Value value; + }; + QXmlStreamSimpleStack attributeStack; + + inline QStringRef symString(int index) { + const Value &symbol = sym(index); + return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); + } + inline QStringRef symName(int index) { + const Value &symbol = sym(index); + return QStringRef(&textBuffer, symbol.pos, symbol.len); + } + inline QStringRef symString(int index, int offset) { + const Value &symbol = sym(index); + return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset); + } + inline QStringRef symPrefix(int index) { + const Value &symbol = sym(index); + if (symbol.prefix) + return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1); + return QStringRef(); + } + inline QStringRef symString(const Value &symbol) { + return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); + } + inline QStringRef symName(const Value &symbol) { + return QStringRef(&textBuffer, symbol.pos, symbol.len); + } + inline QStringRef symPrefix(const Value &symbol) { + if (symbol.prefix) + return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1); + return QStringRef(); + } + + inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; } + + + short token; + uint token_char; + + uint filterCarriageReturn(); + inline uint getChar(); + inline uint peekChar(); + inline void putChar(uint c) { putStack.push() = c; } + inline void putChar(QChar c) { putStack.push() = c.unicode(); } + void putString(const QString &s, int from = 0); + void putStringLiteral(const QString &s); + void putReplacement(const QString &s); + void putReplacementInAttributeValue(const QString &s); + uint getChar_helper(); + + bool scanUntil(const char *str, short tokenToInject = -1); + bool scanString(const char *str, short tokenToInject, bool requireSpace = true); + inline void injectToken(ushort tokenToInject) { + putChar(int(tokenToInject) << 16); + } + + QString resolveUndeclaredEntity(const QString &name); + void parseEntity(const QString &value); + QXmlStreamReaderPrivate *entityParser; + + bool scanAfterLangleBang(); + bool scanPublicOrSystem(); + bool scanNData(); + bool scanAfterDefaultDecl(); + bool scanAttType(); + + + // scan optimization functions. Not strictly necessary but LALR is + // not very well suited for scanning fast + int fastScanLiteralContent(); + int fastScanSpace(); + int fastScanContentCharList(); + int fastScanName(int *prefix = 0); + inline int fastScanNMTOKEN(); + + + bool parse(); + inline void consumeRule(int); + + void raiseError(QXmlStreamReader::Error error, const QString& message = QString()); + void raiseWellFormedError(const QString &message); + + QXmlStreamEntityResolver *entityResolver; + +private: + /*! \internal + Never assign to variable type directly. Instead use this function. + + This prevents errors from being ignored. + */ + inline void setType(const QXmlStreamReader::TokenType t) + { + if(type != QXmlStreamReader::Invalid) + type = t; + } +}; + +bool QXmlStreamReaderPrivate::parse() +{ + // cleanup currently reported token + + switch (type) { + case QXmlStreamReader::StartElement: + name.clear(); + prefix.clear(); + qualifiedName.clear(); + namespaceUri.clear(); + publicNamespaceDeclarations.clear(); + attributes.clear(); + if (isEmptyElement) { + setType(QXmlStreamReader::EndElement); + Tag &tag = tagStack_pop(); + namespaceUri = tag.namespaceDeclaration.namespaceUri; + name = tag.name; + qualifiedName = tag.qualifiedName; + isEmptyElement = false; + return true; + } + clearTextBuffer(); + break; + case QXmlStreamReader::EndElement: + name.clear(); + prefix.clear(); + qualifiedName.clear(); + namespaceUri.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::DTD: + publicNotationDeclarations.clear(); + publicEntityDeclarations.clear(); + dtdName.clear(); + dtdPublicId.clear(); + dtdSystemId.clear(); + Q_FALLTHROUGH(); + case QXmlStreamReader::Comment: + case QXmlStreamReader::Characters: + isCDATA = false; + isWhitespace = true; + text.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::EntityReference: + text.clear(); + name.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::ProcessingInstruction: + processingInstructionTarget.clear(); + processingInstructionData.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + break; + case QXmlStreamReader::StartDocument: + lockEncoding = true; + documentVersion.clear(); + documentEncoding.clear(); +#ifndef QT_NO_TEXTCODEC + if (decoder && decoder->hasFailure()) { + raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content.")); + readBuffer.clear(); + return false; + } +#endif + Q_FALLTHROUGH(); + default: + clearTextBuffer(); + ; + } + + setType(QXmlStreamReader::NoToken); + + + // the main parse loop + int act, r; + + if (resumeReduction) { + act = state_stack[tos-1]; + r = resumeReduction; + resumeReduction = 0; + goto ResumeReduction; + } + + act = state_stack[tos]; + + forever { + if (token == -1 && - TERMINAL_COUNT != action_index[act]) { + uint cu = getChar(); + token = NOTOKEN; + token_char = cu == ~0U ? cu : ushort(cu); + if ((cu != ~0U) && (cu & 0xff0000)) { + token = cu >> 16; + } else switch (token_char) { + case 0xfffe: + case 0xffff: + token = ERROR; + break; + case '\r': + token = SPACE; + if (cu == '\r') { + if ((token_char = filterCarriageReturn())) { + ++lineNumber; + lastLineStart = characterOffset + readBufferPos; + break; + } + } else { + break; + } + Q_FALLTHROUGH(); + case ~0U: { + token = EOF_SYMBOL; + if (!tagsDone && !inParseEntity) { + int a = t_action(act, token); + if (a < 0) { + raiseError(QXmlStreamReader::PrematureEndOfDocumentError); + return false; + } + } + + } break; + case '\n': + ++lineNumber; + lastLineStart = characterOffset + readBufferPos; + Q_FALLTHROUGH(); + case ' ': + case '\t': + token = SPACE; + break; + case '&': + token = AMPERSAND; + break; + case '#': + token = HASH; + break; + case '\'': + token = QUOTE; + break; + case '\"': + token = DBLQUOTE; + break; + case '<': + token = LANGLE; + break; + case '>': + token = RANGLE; + break; + case '[': + token = LBRACK; + break; + case ']': + token = RBRACK; + break; + case '(': + token = LPAREN; + break; + case ')': + token = RPAREN; + break; + case '|': + token = PIPE; + break; + case '=': + token = EQ; + break; + case '%': + token = PERCENT; + break; + case '/': + token = SLASH; + break; + case ':': + token = COLON; + break; + case ';': + token = SEMICOLON; + break; + case ',': + token = COMMA; + break; + case '-': + token = DASH; + break; + case '+': + token = PLUS; + break; + case '*': + token = STAR; + break; + case '.': + token = DOT; + break; + case '?': + token = QUESTIONMARK; + break; + case '!': + token = BANG; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token = DIGIT; + break; + default: + if (cu < 0x20) + token = NOTOKEN; + else + token = LETTER; + break; + } + } + + act = t_action (act, token); + if (act == ACCEPT_STATE) { + // reset the parser in case someone resumes (process instructions can follow a valid document) + tos = 0; + state_stack[tos++] = 0; + state_stack[tos] = 0; + return true; + } else if (act > 0) { + if (++tos == stack_size-1) + reallocateStack(); + + Value &val = sym_stack[tos]; + val.c = token_char; + val.pos = textBuffer.size(); + val.prefix = 0; + val.len = 1; + if (token_char) + textBuffer += QChar(token_char); + + state_stack[tos] = act; + token = -1; + + + } else if (act < 0) { + r = - act - 1; + +#if defined (QLALR_DEBUG) + int ridx = rule_index[r]; + printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]); + ++ridx; + for (int i = ridx; i < ridx + rhs[r]; ++i) { + int symbol = rule_info[i]; + if (const char *name = spell[symbol]) + printf (" %s", name); + else + printf (" #%d", symbol); + } + printf ("\n"); +#endif + + tos -= rhs[r]; + act = state_stack[tos++]; + ResumeReduction: + switch (r) { + + case 0: + setType(QXmlStreamReader::EndDocument); + break; + + case 1: + if (type != QXmlStreamReader::Invalid) { + if (hasSeenTag || inParseEntity) { + setType(QXmlStreamReader::EndDocument); + } else { + raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected.")); + // reset the parser + tos = 0; + state_stack[tos++] = 0; + state_stack[tos] = 0; + return false; + } + } + break; + + case 10: + entityReferenceStack.pop()->isCurrentlyReferenced = false; + clearSym(); + break; + + case 11: + if (!scanString(spell[VERSION], VERSION, false) && atEnd) { + resume(11); + return false; + } + break; + + case 12: + setType(QXmlStreamReader::StartDocument); + documentVersion = symString(6); + startDocument(); + break; + + case 13: + hasExternalDtdSubset = true; + dtdSystemId = symString(2); + break; + + case 14: + checkPublicLiteral(symString(2)); + dtdPublicId = symString(2); + dtdSystemId = symString(4); + hasExternalDtdSubset = true; + break; + + case 16: + if (!scanPublicOrSystem() && atEnd) { + resume(16); + return false; + } + dtdName = symString(3); + break; + + case 17: + case 18: + dtdName = symString(3); + Q_FALLTHROUGH(); + + case 19: + case 20: + setType(QXmlStreamReader::DTD); + text = &textBuffer; + break; + + case 21: + scanDtd = true; + break; + + case 22: + scanDtd = false; + break; + + case 37: + if (!scanString(spell[EMPTY], EMPTY, false) + && !scanString(spell[ANY], ANY, false) + && atEnd) { + resume(37); + return false; + } + break; + + case 43: + if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) { + resume(43); + return false; + } + break; + + case 68: { + lastAttributeIsCData = true; + } break; + + case 78: + if (!scanAfterDefaultDecl() && atEnd) { + resume(78); + return false; + } + break; + + case 83: + sym(1) = sym(2); + lastAttributeValue.clear(); + lastAttributeIsCData = false; + if (!scanAttType() && atEnd) { + resume(83); + return false; + } + break; + + case 84: { + DtdAttribute &dtdAttribute = dtdAttributes.push(); + dtdAttribute.tagName.clear(); + dtdAttribute.isCDATA = lastAttributeIsCData; + dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1)); + dtdAttribute.attributeName = addToStringStorage(symString(1)); + dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1)); + dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns") + || (dtdAttribute.attributePrefix.isEmpty() + && dtdAttribute.attributeName == QLatin1String("xmlns"))); + if (lastAttributeValue.isNull()) { + dtdAttribute.defaultValue.clear(); + } else { + if (dtdAttribute.isCDATA) + dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue); + else + dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified()); + + } + } break; + + case 88: { + if (referenceToUnparsedEntityDetected && !standalone) + break; + int n = dtdAttributes.size(); + QStringRef tagName = addToStringStorage(symName(3)); + while (n--) { + DtdAttribute &dtdAttribute = dtdAttributes[n]; + if (!dtdAttribute.tagName.isNull()) + break; + dtdAttribute.tagName = tagName; + for (int i = 0; i < n; ++i) { + if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName) + && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) { + dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it + break; + } + } + } + } break; + + case 89: { + if (!scanPublicOrSystem() && atEnd) { + resume(89); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.push(); + entityDeclaration.clear(); + entityDeclaration.name = symString(3); + } break; + + case 90: { + if (!scanPublicOrSystem() && atEnd) { + resume(90); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.push(); + entityDeclaration.clear(); + entityDeclaration.name = symString(5); + entityDeclaration.parameter = true; + } break; + + case 91: { + if (!scanNData() && atEnd) { + resume(91); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + entityDeclaration.systemId = symString(3); + entityDeclaration.external = true; + } break; + + case 92: { + if (!scanNData() && atEnd) { + resume(92); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + checkPublicLiteral((entityDeclaration.publicId = symString(3))); + entityDeclaration.systemId = symString(5); + entityDeclaration.external = true; + } break; + + case 93: { + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + entityDeclaration.notationName = symString(3); + if (entityDeclaration.parameter) + raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration.")); + } + Q_FALLTHROUGH(); + + case 94: + case 95: { + if (referenceToUnparsedEntityDetected && !standalone) { + entityDeclarations.pop(); + break; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + if (!entityDeclaration.external) + entityDeclaration.value = symString(2); + QString entityName = entityDeclaration.name.toString(); + QHash &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; + if (!hash.contains(entityName)) { + Entity entity(entityDeclaration.value.toString()); + entity.unparsed = (!entityDeclaration.notationName.isNull()); + entity.external = entityDeclaration.external; + hash.insert(entityName, entity); + } + } break; + + case 96: { + setType(QXmlStreamReader::ProcessingInstruction); + int pos = sym(4).pos + sym(4).len; + processingInstructionTarget = symString(3); + if (scanUntil("?>")) { + processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); + const QString piTarget(processingInstructionTarget.toString()); + if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { + raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document.")); + } + else if(!QXmlUtils::isNCName(piTarget)) + raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget)); + } else if (type != QXmlStreamReader::Invalid){ + resume(96); + return false; + } + } break; + + case 97: + setType(QXmlStreamReader::ProcessingInstruction); + processingInstructionTarget = symString(3); + if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive)) + raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name.")); + break; + + case 98: + if (!scanAfterLangleBang() && atEnd) { + resume(98); + return false; + } + break; + + case 99: + if (!scanUntil("--")) { + resume(99); + return false; + } + break; + + case 100: { + setType(QXmlStreamReader::Comment); + int pos = sym(1).pos + 4; + text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); + } break; + + case 101: { + setType(QXmlStreamReader::Characters); + isCDATA = true; + isWhitespace = false; + int pos = sym(2).pos; + if (scanUntil("]]>", -1)) { + text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); + } else { + resume(101); + return false; + } + } break; + + case 102: { + if (!scanPublicOrSystem() && atEnd) { + resume(102); + return false; + } + NotationDeclaration ¬ationDeclaration = notationDeclarations.push(); + notationDeclaration.name = symString(3); + } break; + + case 103: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + notationDeclaration.systemId = symString(3); + notationDeclaration.publicId.clear(); + } break; + + case 104: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + notationDeclaration.systemId.clear(); + checkPublicLiteral((notationDeclaration.publicId = symString(3))); + } break; + + case 105: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + checkPublicLiteral((notationDeclaration.publicId = symString(3))); + notationDeclaration.systemId = symString(5); + } break; + + case 129: + isWhitespace = false; + Q_FALLTHROUGH(); + + case 130: + sym(1).len += fastScanContentCharList(); + if (atEnd && !inParseEntity) { + resume(130); + return false; + } + break; + + case 139: + if (!textBuffer.isEmpty()) { + setType(QXmlStreamReader::Characters); + text = &textBuffer; + } + break; + + case 140: + case 141: + clearSym(); + break; + + case 142: + case 143: + sym(1) = sym(2); + break; + + case 144: + case 145: + case 146: + case 147: + sym(1).len += sym(2).len; + break; + + case 173: + if (normalizeLiterals) + textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' '); + break; + + case 174: + sym(1).len += fastScanLiteralContent(); + if (atEnd) { + resume(174); + return false; + } + break; + + case 175: { + if (!QXmlUtils::isPublicID(symString(1).toString())) { + raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString())); + resume(175); + return false; + } + } break; + + case 176: + case 177: + clearSym(); + break; + + case 178: + case 179: + sym(1) = sym(2); + break; + + case 180: + case 181: + case 182: + case 183: + sym(1).len += sym(2).len; + break; + + case 213: + case 214: + clearSym(); + break; + + case 215: + case 216: + sym(1) = sym(2); + lastAttributeValue = symString(1); + break; + + case 217: + case 218: + case 219: + case 220: + sym(1).len += sym(2).len; + break; + + case 229: { + QStringRef prefix = symPrefix(1); + if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) { + NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); + namespaceDeclaration.prefix.clear(); + + const QStringRef ns(symString(5)); + if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") || + ns == QLatin1String("http://www.w3.org/XML/1998/namespace")) + raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); + else + namespaceDeclaration.namespaceUri = addToStringStorage(ns); + } else { + Attribute &attribute = attributeStack.push(); + attribute.key = sym(1); + attribute.value = sym(5); + + QStringRef attributeQualifiedName = symName(1); + bool normalize = false; + for (int a = 0; a < dtdAttributes.size(); ++a) { + DtdAttribute &dtdAttribute = dtdAttributes[a]; + if (!dtdAttribute.isCDATA + && dtdAttribute.tagName == qualifiedName + && dtdAttribute.attributeQualifiedName == attributeQualifiedName + ) { + normalize = true; + break; + } + } + if (normalize) { + // normalize attribute value (simplify and trim) + int pos = textBuffer.size(); + int n = 0; + bool wasSpace = true; + for (int i = 0; i < attribute.value.len; ++i) { + QChar c = textBuffer.at(attribute.value.pos + i); + if (c.unicode() == ' ') { + if (wasSpace) + continue; + wasSpace = true; + } else { + wasSpace = false; + } + textBuffer += textBuffer.at(attribute.value.pos + i); + ++n; + } + if (wasSpace) + while (n && textBuffer.at(pos + n - 1).unicode() == ' ') + --n; + attribute.value.pos = pos; + attribute.value.len = n; + } + if (prefix == QLatin1String("xmlns") && namespaceProcessing) { + NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); + QStringRef namespacePrefix = symString(attribute.key); + QStringRef namespaceUri = symString(attribute.value); + attributeStack.pop(); + if (((namespacePrefix == QLatin1String("xml")) + ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))) + || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/") + || namespaceUri.isEmpty() + || namespacePrefix == QLatin1String("xmlns")) + raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); + + namespaceDeclaration.prefix = addToStringStorage(namespacePrefix); + namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri); + } + } + } break; + + case 235: { + normalizeLiterals = true; + Tag &tag = tagStack_push(); + prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2)); + name = tag.name = addToStringStorage(symString(2)); + qualifiedName = tag.qualifiedName = addToStringStorage(symName(2)); + if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name)) + raiseWellFormedError(QXmlStream::tr("Invalid XML name.")); + } break; + + case 236: + isEmptyElement = true; + Q_FALLTHROUGH(); + + case 237: + setType(QXmlStreamReader::StartElement); + resolveTag(); + if (tagStack.size() == 1 && hasSeenTag && !inParseEntity) + raiseWellFormedError(QXmlStream::tr("Extra content at end of document.")); + hasSeenTag = true; + break; + + case 238: { + setType(QXmlStreamReader::EndElement); + Tag &tag = tagStack_pop(); + + namespaceUri = tag.namespaceDeclaration.namespaceUri; + name = tag.name; + qualifiedName = tag.qualifiedName; + if (qualifiedName != symName(3)) + raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch.")); + } break; + + case 239: + if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity)); + break; + } + setType(QXmlStreamReader::EntityReference); + name = &unresolvedEntity; + break; + + case 240: { + sym(1).len += sym(2).len + 1; + QString reference = symString(2).toString(); + if (entityHash.contains(reference)) { + Entity &entity = entityHash[reference]; + if (entity.unparsed) { + raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference)); + } else { + if (!entity.hasBeenParsed) { + parseEntity(entity.value); + entity.hasBeenParsed = true; + } + if (entity.literal) + putStringLiteral(entity.value); + else if (referenceEntity(entity)) + putReplacement(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + } + break; + } + + if (entityResolver) { + QString replacementText = resolveUndeclaredEntity(reference); + if (!replacementText.isNull()) { + putReplacement(replacementText); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + } + + injectToken(UNRESOLVED_ENTITY); + unresolvedEntity = symString(2).toString(); + textBuffer.chop(2 + sym(2).len); + clearSym(); + + } break; + + case 241: { + sym(1).len += sym(2).len + 1; + QString reference = symString(2).toString(); + if (parameterEntityHash.contains(reference)) { + referenceToParameterEntityDetected = true; + Entity &entity = parameterEntityHash[reference]; + if (entity.unparsed || entity.external) { + referenceToUnparsedEntityDetected = true; + } else { + if (referenceEntity(entity)) + putString(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + } + } else if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString())); + } + } break; + + case 242: + sym(1).len += sym(2).len + 1; + break; + + case 243: { + sym(1).len += sym(2).len + 1; + QString reference = symString(2).toString(); + if (entityHash.contains(reference)) { + Entity &entity = entityHash[reference]; + if (entity.unparsed || entity.value.isNull()) { + raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference)); + break; + } + if (!entity.hasBeenParsed) { + parseEntity(entity.value); + entity.hasBeenParsed = true; + } + if (entity.literal) + putStringLiteral(entity.value); + else if (referenceEntity(entity)) + putReplacementInAttributeValue(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + + if (entityResolver) { + QString replacementText = resolveUndeclaredEntity(reference); + if (!replacementText.isNull()) { + putReplacement(replacementText); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + } + if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference)); + } + } break; + + case 244: { + if (uint s = resolveCharRef(3)) { + if (s >= 0xffff) + putStringLiteral(QString::fromUcs4(&s, 1)); + else + putChar((LETTER << 16) | s); + + textBuffer.chop(3 + sym(3).len); + clearSym(); + } else { + raiseWellFormedError(QXmlStream::tr("Invalid character reference.")); + } + } break; + + case 247: + case 248: + sym(1).len += sym(2).len; + break; + + case 259: + sym(1).len += fastScanSpace(); + if (atEnd) { + resume(259); + return false; + } + break; + + case 262: { + sym(1).len += fastScanName(&sym(1).prefix); + if (atEnd) { + resume(262); + return false; + } + } break; + + case 263: + sym(1).len += fastScanName(); + if (atEnd) { + resume(263); + return false; + } + break; + + case 264: + case 265: + case 266: + case 267: + case 268: + sym(1).len += fastScanNMTOKEN(); + if (atEnd) { + resume(268); + return false; + } + + break; + + default: + ; + } // switch + act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT); + if (type != QXmlStreamReader::NoToken) + return true; + } else { + parseError(); + break; + } + } + return false; +} +#endif //QT_NO_XMLSTREAMREADER.xml + + +#endif // QXMLSTREAM_P_H + diff --git a/src/dbus/doc/src/qtdbus-index.qdoc b/src/dbus/doc/src/qtdbus-index.qdoc index 080066cfa8d..eed5e42731c 100644 --- a/src/dbus/doc/src/qtdbus-index.qdoc +++ b/src/dbus/doc/src/qtdbus-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -200,6 +200,15 @@ Information about the messages will be written to the console the application was launched from. + \section1 Licenses + + The Qt D-Bus module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. + \section1 Further Reading The following documents contain information about Qt's D-Bus integration diff --git a/src/gui/configure.json b/src/gui/configure.json index ccaf38e4b71..27e913877f4 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -167,25 +167,20 @@ "label": "Fontconfig", "test": { "head": [ - "#include ", - "#include FT_FREETYPE_H", "#include ", "#ifndef FC_RGBA_UNKNOWN", "# error This version of fontconfig is tool old, it is missing the FC_RGBA_UNKNOWN define", - "#endif", - "#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20110)", - "# error This version of freetype is too old.", "#endif" ], "main": [ - "FT_Face face = 0;", "FcPattern *pattern = 0;" ] }, "sources": [ - { "type": "pkgConfig", "args": "fontconfig freetype2" }, - { "type": "freetype", "libs": "-lfontconfig -lfreetype" } - ] + { "type": "pkgConfig", "args": "fontconfig" }, + { "type": "freetype", "libs": "-lfontconfig" } + ], + "use": "freetype" }, "gbm": { "label": "GBM", @@ -637,7 +632,13 @@ "angle_d3d11_qdtd": { "label": "D3D11_QUERY_DATA_TIMESTAMP_DISJOINT", "type": "compile", - "test": "win/angle_d3d11_qdtd" + "test": { + "include": "d3d11.h", + "main": [ + "D3D11_QUERY_DATA_TIMESTAMP_DISJOINT qdtd;", + "(void) qdtd;" + ] + } }, "directwrite2": { "label": "DirectWrite 2", diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc index da3d4197357..010659df8cf 100644 --- a/src/gui/doc/src/qtgui.qdoc +++ b/src/gui/doc/src/qtgui.qdoc @@ -215,12 +215,13 @@ \section1 Licenses and Attributions Qt GUI is available under commercial licenses from \l{The Qt Company}. - In addition, it is available under the + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are \l{GNU Lesser General Public License, version 3}, or the \l{GNU General Public License, version 2}. See \l{Qt Licensing} for further details. - Furthermore Qt GUI potentially contains third party + Furthermore, Qt GUI in Qt \QtVersion may contain third-party modules under following permissive licenses: \generatelist{groupsbymodule attributions-qtgui} diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index d5e8b1b9743..010760de4cd 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -470,6 +470,10 @@ bool QMoviePrivate::next() currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) ); else currentPixmap = info.pixmap; + + if (!speed) + return true; + nextDelay = speedAdjustedDelay(info.delay); // Adjust delay according to the time it took to read the frame int processingTime = time.elapsed(); @@ -504,7 +508,7 @@ void QMoviePrivate::_q_loadNextFrame(bool starting) emit q->updated(frameRect); emit q->frameChanged(currentFrameNumber); - if (movieState == QMovie::Running) + if (speed && movieState == QMovie::Running) nextImageTimer.start(nextDelay); } else { // Could not read another frame @@ -926,6 +930,8 @@ void QMovie::setPaused(bool paused) void QMovie::setSpeed(int percentSpeed) { Q_D(QMovie); + if (!d->speed && d->movieState == Running) + d->nextImageTimer.start(nextFrameDelay()); d->speed = percentSpeed; } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 36c9b1a964d..f7da94d111c 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2122,7 +2122,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE QWindow *window = e->window.data(); modifier_buttons = e->modifiers; if (e->nullWindow() -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) || e->key == Qt::Key_Back || e->key == Qt::Key_Menu #endif ) { @@ -2158,7 +2158,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE if (window && !window->d_func()->blockedByModalWindow) QGuiApplication::sendSpontaneousEvent(window, &ev); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) else ev.setAccepted(false); diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 27ea3864b99..6f332c8ad69 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -1002,6 +1002,7 @@ bool QOpenGLContext::makeCurrent(QSurface *surface) if (rendererString) needsWorkaround = qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450 + || qstrcmp(rendererString, "Mali-T880") == 0 || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205 || qstrncmp(rendererString, "Adreno 2xx", 8) == 0 // Same as above but without the '(TM)' || qstrncmp(rendererString, "Adreno (TM) 30x", 14) == 0 // Adreno 302, 305 diff --git a/src/gui/kernel/qplatforminputcontext.cpp b/src/gui/kernel/qplatforminputcontext.cpp index 3f59116e9af..9771e6ba11f 100644 --- a/src/gui/kernel/qplatforminputcontext.cpp +++ b/src/gui/kernel/qplatforminputcontext.cpp @@ -287,6 +287,8 @@ void QPlatformInputContext::setSelectionOnFocusObject(const QPointF &anchorPos, if (success) { int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, cursorPos * mapToLocal).toInt(&success); if (success) { + if (anchor == cursor && anchorPos != cursorPos) + return; QList imAttributes; imAttributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, anchor, cursor - anchor, QVariant())); QInputMethodEvent event(QString(), imAttributes); diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 1b56c7d9f2c..c98b879a158 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -58,6 +58,7 @@ #include #include +#include #include #include @@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DRAGANDDROP +Q_LOGGING_CATEGORY(lcDnd, "qt.gui.dnd") + static QWindow* topLevelAt(const QPoint &pos) { QWindowList list = QGuiApplication::topLevelWindows(); @@ -94,9 +97,9 @@ static QWindow* topLevelAt(const QPoint &pos) */ QBasicDrag::QBasicDrag() : - m_restoreCursor(false), m_eventLoop(0), + m_current_window(nullptr), m_restoreCursor(false), m_eventLoop(nullptr), m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), - m_drag(0), m_drag_icon_window(0), m_useCompositing(true), + m_drag(nullptr), m_drag_icon_window(nullptr), m_useCompositing(true), m_screen(nullptr) { } @@ -161,6 +164,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) return true; // Eat all mouse move events } case QEvent::MouseButtonRelease: + { disableEventFilter(); if (canDrop()) { QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); @@ -169,8 +173,25 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) cancel(); } exitDndEventLoop(); - QCoreApplication::postEvent(o, new QMouseEvent(*static_cast(e))); + + // If a QShapedPixmapWindow (drag feedback) is being dragged along, the + // mouse event's localPos() will be relative to that, which is useless. + // We want a position relative to the window where the drag ends, if possible (?). + // If there is no such window (belonging to this Qt application), + // make the event relative to the window where the drag started. (QTBUG-66103) + const QMouseEvent *release = static_cast(e); + const QWindow *releaseWindow = topLevelAt(release->globalPos()); + qCDebug(lcDnd) << "mouse released over" << releaseWindow << "after drag from" << m_current_window << "globalPos" << release->globalPos(); + if (!releaseWindow) + releaseWindow = m_current_window; + QPoint releaseWindowPos = (releaseWindow ? releaseWindow->mapFromGlobal(release->globalPos()) : release->globalPos()); + QMouseEvent *newRelease = new QMouseEvent(release->type(), + releaseWindowPos, releaseWindowPos, release->screenPos(), + release->button(), release->buttons(), + release->modifiers(), release->source()); + QCoreApplication::postEvent(o, newRelease); return true; // defer mouse release events until drag event loop has returned + } case QEvent::MouseButtonDblClick: case QEvent::Wheel: return true; @@ -349,7 +370,7 @@ static inline QPoint fromNativeGlobalPixels(const QPoint &point) into account. */ -QSimpleDrag::QSimpleDrag() : m_current_window(0) +QSimpleDrag::QSimpleDrag() { } @@ -366,6 +387,7 @@ void QSimpleDrag::startDrag() updateCursor(Qt::IgnoreAction); } setExecutedDropAction(Qt::IgnoreAction); + qCDebug(lcDnd) << "drag began from" << m_current_window<< "cursor pos" << QCursor::pos() << "can drop?" << canDrop(); } void QSimpleDrag::cancel() diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index 4db8eb4505a..e56c7bf3060 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -105,6 +105,9 @@ protected: QDrag *drag() const { return m_drag; } +protected: + QWindow *m_current_window; + private: void enableEventFilter(); void disableEventFilter(); @@ -131,9 +134,6 @@ protected: virtual void cancel() override; virtual void move(const QPoint &globalPos) override; virtual void drop(const QPoint &globalPos) override; - -private: - QWindow *m_current_window; }; #endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 35a9ede2272..318a280a40e 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -283,9 +283,10 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::Application QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry) : WindowSystemEvent(GeometryChange) , window(window) - , requestedGeometry(window->handle() ? window->handle()->QPlatformWindow::geometry() : QRect()) , newGeometry(newGeometry) { + if (const QPlatformWindow *pw = window->handle()) + requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect) diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 3563f1b5d36..b825b56d45a 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -778,6 +778,8 @@ static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpen return QOpenGLTexture::Alpha; case QOpenGLTexture::RGBFormat: + return QOpenGLTexture::RGB; + case QOpenGLTexture::RGBAFormat: return QOpenGLTexture::RGBA; diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 1e14498f799..29bef14f0c7 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -127,7 +127,7 @@ AVX2_SOURCES += painting/qdrawhelper_avx2.cpp NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S -!uikit:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as +!uikit:!win32:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as !uikit:!win32:!contains(QT_ARCH, "arm64"): DEFINES += ENABLE_PIXMAN_DRAWHELPERS MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h index 74ecef767e5..d8a4fcfb1c8 100644 --- a/src/gui/painting/qmatrix.h +++ b/src/gui/painting/qmatrix.h @@ -65,10 +65,10 @@ public: #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove; the compiler-generated ones are fine! QMatrix &operator=(QMatrix &&other) Q_DECL_NOTHROW // = default - { memcpy(this, &other, sizeof(QMatrix)); return *this; } + { memcpy(static_cast(this), static_cast(&other), sizeof(QMatrix)); return *this; } QMatrix &operator=(const QMatrix &) Q_DECL_NOTHROW; // = default QMatrix(QMatrix &&other) Q_DECL_NOTHROW // = default - { memcpy(this, &other, sizeof(QMatrix)); } + { memcpy(static_cast(this), static_cast(&other), sizeof(QMatrix)); } QMatrix(const QMatrix &other) Q_DECL_NOTHROW; // = default #endif diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 79835b36e29..63c4a241c14 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -78,14 +78,14 @@ public: #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove; the compiler-generated ones are fine! QTransform &operator=(QTransform &&other) Q_DECL_NOTHROW // = default - { memcpy(this, &other, sizeof(QTransform)); return *this; } + { memcpy(static_cast(this), static_cast(&other), sizeof(QTransform)); return *this; } QTransform &operator=(const QTransform &) Q_DECL_NOTHROW; // = default QTransform(QTransform &&other) Q_DECL_NOTHROW // = default : affine(Qt::Uninitialized) - { memcpy(this, &other, sizeof(QTransform)); } + { memcpy(static_cast(this), static_cast(&other), sizeof(QTransform)); } QTransform(const QTransform &other) Q_DECL_NOTHROW // = default : affine(Qt::Uninitialized) - { memcpy(this, &other, sizeof(QTransform)); } + { memcpy(static_cast(this), static_cast(&other), sizeof(QTransform)); } #endif bool isAffine() const; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 8cdbeafd7d5..4b1564e69c7 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -237,13 +237,13 @@ struct QGlyphLayout last = numGlyphs; if (first == 0 && last == numGlyphs && reinterpret_cast(offsets + numGlyphs) == reinterpret_cast(glyphs)) { - memset(offsets, 0, (numGlyphs * SpaceNeeded)); + memset(static_cast(offsets), 0, (numGlyphs * SpaceNeeded)); } else { const int num = last - first; - memset(offsets + first, 0, num * sizeof(QFixedPoint)); + memset(static_cast(offsets + first), 0, num * sizeof(QFixedPoint)); memset(glyphs + first, 0, num * sizeof(glyph_t)); - memset(advances + first, 0, num * sizeof(QFixed)); - memset(justifications + first, 0, num * sizeof(QGlyphJustification)); + memset(static_cast(advances + first), 0, num * sizeof(QFixed)); + memset(static_cast(justifications + first), 0, num * sizeof(QGlyphJustification)); memset(attributes + first, 0, num * sizeof(QGlyphAttributes)); } } diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 7e4efa28f82..067f8473ea2 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -154,9 +154,9 @@ public: iterator(const iterator &o) Q_DECL_NOTHROW; // = default iterator &operator=(const iterator &o) Q_DECL_NOTHROW; // = default iterator(iterator &&other) Q_DECL_NOTHROW // = default - { memcpy(this, &other, sizeof(iterator)); } + { memcpy(static_cast(this), static_cast(&other), sizeof(iterator)); } iterator &operator=(iterator &&other) Q_DECL_NOTHROW // = default - { memcpy(this, &other, sizeof(iterator)); return *this; } + { memcpy(static_cast(this), static_cast(&other), sizeof(iterator)); return *this; } #endif QTextFrame *parentFrame() const { return f; } diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 517af326a89..0e2c257952b 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -354,7 +354,7 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) host += QByteArray::number(port); } - request.setHeaderField("Host", host); + request.prependHeaderField("Host", host); } reply->d_func()->requestIsPrepared = true; diff --git a/src/network/access/qhttpnetworkheader.cpp b/src/network/access/qhttpnetworkheader.cpp index 19a3dfcfe8c..3326f89d2fa 100644 --- a/src/network/access/qhttpnetworkheader.cpp +++ b/src/network/access/qhttpnetworkheader.cpp @@ -112,6 +112,11 @@ void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QBy fields.append(qMakePair(name, data)); } +void QHttpNetworkHeaderPrivate::prependHeaderField(const QByteArray &name, const QByteArray &data) +{ + fields.prepend(qMakePair(name, data)); +} + bool QHttpNetworkHeaderPrivate::operator==(const QHttpNetworkHeaderPrivate &other) const { return (url == other.url); diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h index f46c2599198..3adb0ed7f1c 100644 --- a/src/network/access/qhttpnetworkheader_p.h +++ b/src/network/access/qhttpnetworkheader_p.h @@ -92,6 +92,7 @@ public: QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; QList headerFieldValues(const QByteArray &name) const; void setHeaderField(const QByteArray &name, const QByteArray &data); + void prependHeaderField(const QByteArray &name, const QByteArray &data); bool operator==(const QHttpNetworkHeaderPrivate &other) const; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 3fcf9469455..cf4be3df95b 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -279,6 +279,11 @@ void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArra d->setHeaderField(name, data); } +void QHttpNetworkRequest::prependHeaderField(const QByteArray &name, const QByteArray &data) +{ + d->prependHeaderField(name, data); +} + QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other) { d = other.d; diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 2cbb8e255eb..bc797537ae2 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -102,6 +102,7 @@ public: QList > header() const override; QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const override; void setHeaderField(const QByteArray &name, const QByteArray &data) override; + void prependHeaderField(const QByteArray &name, const QByteArray &data); Operation operation() const; void setOperation(Operation operation); diff --git a/src/network/configure.json b/src/network/configure.json index 94a23bbc788..89bb1efffa2 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -141,10 +141,10 @@ "use": "network" }, "openssl11": { - "label": "OpenSSL v. 1.1 support", + "label": "OpenSSL 1.1 support", "type": "compile", "test": "unix/openssl11", - "use": "network" + "use": "openssl" } }, @@ -213,9 +213,9 @@ "output": [ "publicFeature", "feature" ] }, "opensslv11": { - "label": "OpenSSL v. 1.1", - "condition": "tests.openssl11", - "output": ["publicFeature", "feature"] + "label": "OpenSSL 1.1", + "condition": "features.openssl && tests.openssl11", + "output": [ "publicFeature" ] }, "sctp": { "label": "SCTP", @@ -341,6 +341,7 @@ For example: }, "openssl", "openssl-linked", + "opensslv11", "sctp", "system-proxies" ] diff --git a/src/network/network.pro b/src/network/network.pro index b8272d91d63..9082439f1cb 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -10,7 +10,7 @@ DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH #DEFINES += QTCPSOCKETENGINE_DEBUG QTCPSOCKET_DEBUG QTCPSERVER_DEBUG QSSLSOCKET_DEBUG #DEFINES += QUDPSOCKET_DEBUG QUDPSERVER_DEBUG #DEFINES += QSCTPSOCKET_DEBUG QSCTPSERVER_DEBUG -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x64000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x64000000 QMAKE_DOCS = $$PWD/doc/qtnetwork.qdocconf diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 2d771b56375..1fc7817fe82 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -541,12 +541,14 @@ QList QSslSocketPrivate::systemCaCertificates() directories << ministroPath; nameFilters << QLatin1String("*.der"); platformEncodingFormat = QSsl::Der; +# ifndef Q_OS_ANDROID_EMBEDDED if (ministroPath.isEmpty()) { QList certificateData = fetchSslCertificateData(); for (int i = 0; i < certificateData.size(); ++i) { systemCerts.append(QSslCertificate::fromData(certificateData.at(i), QSsl::Der)); } } else +# endif //Q_OS_ANDROID_EMBEDDED # endif //Q_OS_ANDROID { currentDir.setNameFilters(nameFilters); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index ced861805b3..6f34c6c888e 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -210,7 +210,7 @@ public: private: static bool ensureLibraryLoaded(); static void ensureCiphersAndCertsLoaded(); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) static QList fetchSslCertificateData(); #endif diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 949ebc3d2ad..2783effaf12 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -82,7 +82,7 @@ qtConfig(ssl) { darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp - android: SOURCES += ssl/qsslsocket_openssl_android.cpp + android:!android-embedded: SOURCES += ssl/qsslsocket_openssl_android.cpp # Add optional SSL libs # Static linking of OpenSSL with msvc: diff --git a/src/opengl/doc/src/qtopengl-index.qdoc b/src/opengl/doc/src/qtopengl-index.qdoc index 6ab888a14d9..30b657f6db2 100644 --- a/src/opengl/doc/src/qtopengl-index.qdoc +++ b/src/opengl/doc/src/qtopengl-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -41,9 +41,6 @@ platform, Microsoft Foundation Classes (MFC) under Windows, or Qt on both platforms. - \note OpenGL is a trademark of Silicon Graphics, Inc. in - the United States and other countries. - The Qt OpenGL module makes it easy to use OpenGL in Qt applications. It provides an OpenGL widget class that can be used just like any other Qt widget, except that it opens an OpenGL display buffer where @@ -68,4 +65,16 @@ The \l{Qt OpenGL C++ Classes} page gives an overview over the available classes in this module. + + \section1 Licenses and Trademarks + + The Qt OpenGL module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. + + OpenGL\reg is a trademark of Silicon Graphics, Inc. in + the United States and other countries. */ diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 077b190d3ee..8b2349ff2f8 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -3,7 +3,7 @@ QT = core-private gui-private widgets-private DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x63000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x63000000 solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_DOCS = $$PWD/doc/qtopengl.qdocconf diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 674ab290124..7a9a98573ed 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -45,7 +45,7 @@ #include #include -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #include #endif #ifndef Q_OS_WIN @@ -332,7 +332,7 @@ void QEGLPlatformContext::updateFormatFromGL() QByteArray version = QByteArray(reinterpret_cast(s)); int major, minor; if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) { -#ifdef Q_OS_ANDROID +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available. static int apiLevel = QtAndroidPrivate::androidSdkVersion(); if (apiLevel <= 17 && major >= 3) { diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index beec8e763ca..cc0246b64a3 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -993,9 +993,7 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info) { // false if exceeds QFontEngineFT::Glyph metrics - return (short)(info.linearAdvance) != info.linearAdvance - || (uchar)(info.width) != info.width - || (uchar)(info.height) != info.height; + return info.width > 0xFF || info.height > 0xFF; } static inline void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix) diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index f5585da7dee..d498b0ac8b2 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -133,7 +133,7 @@ public: /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ struct Glyph { ~Glyph(); - short linearAdvance; + int linearAdvance : 22; unsigned char width; unsigned char height; short x; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 2edee51989e..5eb5cd8a306 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -507,6 +507,23 @@ static QString familyNameFromPostScriptName(NSString *psName) } #endif +static void addExtraFallbacks(QStringList *fallbackList) +{ +#if defined(Q_OS_MACOS) + // Since we are only returning a list of default fonts for the current language, we do not + // cover all unicode completely. This was especially an issue for some of the common script + // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk + // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most + // of Unicode 2.1. + if (!fallbackList->contains(QStringLiteral("Arial Unicode MS"))) + fallbackList->append(QStringLiteral("Arial Unicode MS")); + // Since some symbols (specifically Braille) are not in Arial Unicode MS, we + // add Apple Symbols to cover those too. + if (!fallbackList->contains(QStringLiteral("Apple Symbols"))) + fallbackList->append(QStringLiteral("Apple Symbols")); +#endif +} + QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { Q_UNUSED(style); @@ -534,16 +551,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo fallbackList.append(QString::fromCFString(fallbackFamilyName)); } -#if defined(Q_OS_OSX) - // Since we are only returning a list of default fonts for the current language, we do not - // cover all unicode completely. This was especially an issue for some of the common script - // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk - // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most - // of Unicode 2.1. - if (!fallbackList.contains(QStringLiteral("Arial Unicode MS"))) - fallbackList.append(QStringLiteral("Arial Unicode MS")); -#endif - + addExtraFallbacks(&fallbackList); extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &); fallbackList = qt_sort_families_by_writing_system(script, fallbackList); @@ -584,14 +592,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo fallbackList.append(QLatin1String("Apple Color Emoji")); - // Since we are only returning a list of default fonts for the current language, we do not - // cover all unicode completely. This was especially an issue for some of the common script - // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk - // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most - // of Unicode 2.1. - if (!fallbackList.contains(QStringLiteral("Arial Unicode MS"))) - fallbackList.append(QStringLiteral("Arial Unicode MS")); - + addExtraFallbacks(&fallbackList); fallbackLists[styleLookupKey.arg(fallbackStyleHint)] = fallbackList; } #else diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 675f689aceb..25ff69d877d 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -182,6 +182,14 @@ public: : QCoreTextFontEngine(font, def) , m_fontData(fontData) {} + QFontEngine *cloneWithSize(qreal pixelSize) const + { + QFontDef newFontDef = fontDef; + newFontDef.pixelSize = pixelSize; + newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); + + return new QCoreTextRawFontEngine(cgFont, newFontDef, m_fontData); + } QByteArray m_fontData; }; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 1f7b3469092..b77aaa27c1c 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -125,7 +125,7 @@ public: static QFontEngine::GlyphFormat defaultGlyphFormat; static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); -private: +protected: void init(); QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); CTFontRef ctfont; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp index 67a6619b91a..b1133dca223 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp @@ -101,8 +101,10 @@ static inline HBITMAP createDIB(HDC hdc, int width, int height, uchar *bits = nullptr; HBITMAP bitmap = CreateDIBSection(hdc, reinterpret_cast(&bmi), DIB_RGB_COLORS, reinterpret_cast(&bits), 0, 0); - if (Q_UNLIKELY(!bitmap || !bits)) - qFatal("%s: CreateDIBSection failed.", __FUNCTION__); + if (Q_UNLIKELY(!bitmap || !bits)) { + qFatal("%s: CreateDIBSection failed (%dx%d, format: %d)", __FUNCTION__, + width, height, int(format)); + } *bitsIn = bits; return bitmap; diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index 824fd0388f9..afdc6131672 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -6,6 +6,6 @@ QT_FOR_CONFIG += network-private SUBDIRS += connman networkmanager } -android:SUBDIRS += android +android:!android-embedded: SUBDIRS += android isEmpty(SUBDIRS):SUBDIRS = generic diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index fe4c5be4cba..f548a1fa96f 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -438,6 +438,16 @@ QAndroidInputContext::QAndroidInputContext() QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QAndroidInputContext::updateSelectionHandles); + QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::anchorRectangleChanged, + this, &QAndroidInputContext::updateSelectionHandles); + QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::inputItemClipRectangleChanged, this, [this]{ + auto im = qGuiApp->inputMethod(); + if (!im->inputItemClipRectangle().contains(im->anchorRectangle()) || + !im->inputItemClipRectangle().contains(im->cursorRectangle())) { + m_cursorHandleShown = CursorHandleNotShown; + updateSelectionHandles(); + } + }); } QAndroidInputContext::~QAndroidInputContext() @@ -595,27 +605,63 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) double pixelDensity = window ? QHighDpiScaling::factor(window) : QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen()); - QPoint point(x / pixelDensity, y / pixelDensity); - y -= leftRect.width() / 2; + QPointF point(x / pixelDensity, y / pixelDensity); + point.setY(point.y() - leftRect.width() / 2); if (handleId == 1) { setSelectionOnFocusObject(point, point); return; } - QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition); + QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImCurrentSelection); QCoreApplication::sendEvent(m_focusObject, &query); int cpos = query.value(Qt::ImCursorPosition).toInt(); int anchor = query.value(Qt::ImAnchorPosition).toInt(); - + bool rtl = query.value(Qt::ImCurrentSelection).toString().isRightToLeft(); auto rightRect = im->anchorRectangle(); if (cpos > anchor) std::swap(leftRect, rightRect); + auto checkLeftHandle = [&rightRect](QPointF &handlePos) { + if (handlePos.y() > rightRect.center().y()) + handlePos.setY(rightRect.center().y()); // adjust Y handle pos + if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && handlePos.x() >= rightRect.x()) + return false; // same line and wrong X pos ? + return true; + }; + + auto checkRtlRightHandle = [&rightRect](QPointF &handlePos) { + if (handlePos.y() > rightRect.center().y()) + handlePos.setY(rightRect.center().y()); // adjust Y handle pos + if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && rightRect.x() >= handlePos.x()) + return false; // same line and wrong X pos ? + return true; + }; + + auto checkRightHandle = [&leftRect](QPointF &handlePos) { + if (handlePos.y() < leftRect.center().y()) + handlePos.setY(leftRect.center().y()); // adjust Y handle pos + if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && leftRect.x() >= handlePos.x()) + return false; // same line and wrong X pos ? + return true; + }; + + auto checkRtlLeftHandle = [&leftRect](QPointF &handlePos) { + if (handlePos.y() < leftRect.center().y()) + handlePos.setY(leftRect.center().y()); // adjust Y handle pos + if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && handlePos.x() >= leftRect.x()) + return false; // same line and wrong X pos ? + return true; + }; + if (handleId == 2) { - QPoint rightPoint(rightRect.center().toPoint()); + QPointF rightPoint(rightRect.center()); + if ((!rtl && !checkLeftHandle(point)) || (rtl && !checkRtlRightHandle(point))) + return; setSelectionOnFocusObject(point, rightPoint); } else if (handleId == 3) { - QPoint leftPoint(leftRect.center().toPoint()); + QPointF leftPoint(leftRect.center()); + if ((!rtl && !checkRightHandle(point)) || (rtl && !checkRtlLeftHandle(point))) + return; setSelectionOnFocusObject(leftPoint, point); } } diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 32be9ad4ee9..a94e0dc5176 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -311,6 +311,24 @@ QT_USE_NAMESPACE return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together. } +- (void)applicationWillHide:(NSNotification *)notification +{ + if (reflectionDelegate + && [reflectionDelegate respondsToSelector:@selector(applicationWillHide:)]) { + [reflectionDelegate applicationWillHide:notification]; + } + + // When the application is hidden Qt will hide the popup windows associated with + // it when it has lost the activation for the application. However, when it gets + // to this point it believes the popup windows to be hidden already due to the + // fact that the application itself is hidden, which will cause a problem when + // the application is made visible again. + const QWindowList topLevelWindows = QGuiApplication::topLevelWindows(); + for (QWindow *topLevelWindow : qAsConst(topLevelWindows)) { + if ((topLevelWindow->type() & Qt::Popup) == Qt::Popup && topLevelWindow->isVisible()) + topLevelWindow->hide(); + } +} - (void)applicationDidBecomeActive:(NSNotification *)notification { diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 00bfc8bef5f..94f2125bade 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -415,6 +415,13 @@ static QString strippedText(QString s) } else { QList result; QString filename = QString::fromNSString([[mSavePanel URL] path]).normalized(QString::NormalizationForm_C); + const QString defaultSuffix = mOptions->defaultSuffix(); + const QFileInfo fileInfo(filename); + // If neither the user or the NSSavePanel have provided a suffix, use + // the default suffix (if it exists). + if (fileInfo.suffix().isEmpty() && !defaultSuffix.isEmpty()) { + filename.append('.').append(defaultSuffix); + } result << QUrl::fromLocalFile(filename.remove(QLatin1String("___qt_very_unlikely_prefix_"))); return result; } @@ -442,10 +449,7 @@ static QString strippedText(QString s) [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead? if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) { - QStringList ext = [self acceptableExtensionsForSave]; - const QString defaultSuffix = mOptions->defaultSuffix(); - if (!ext.isEmpty() && !defaultSuffix.isEmpty()) - ext.prepend(defaultSuffix); + const QStringList ext = [self acceptableExtensionsForSave]; [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)]; } else { [mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 7a550b163b8..b3c2d5ae90e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -44,9 +44,11 @@ #include #include "qcocoaapplication.h" +#include "qcocoaintegration.h" #include "qcocoamenuloader.h" #include "qcocoamenubar.h" #include "qcocoawindow.h" +#include "qcocoascreen.h" QT_BEGIN_NAMESPACE @@ -364,8 +366,9 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, [popupCell setMenu:m_nativeMenu]; [popupCell selectItem:nsItem]; - int availableHeight = screen->availableSize().height(); - const QPoint &globalPos = parentWindow->mapToGlobal(pos); + QCocoaScreen *cocoaScreen = static_cast(screen->handle()); + int availableHeight = cocoaScreen->availableGeometry().height(); + const QPoint &globalPos = cocoaWindow->mapToGlobal(pos); int menuHeight = m_nativeMenu.size.height; if (globalPos.y() + menuHeight > availableHeight) { // Maybe we need to fix the vertical popup position but we don't know the diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm index 996a4ff194c..6be2569dbca 100644 --- a/src/plugins/platforms/cocoa/qcocoansmenu.mm +++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm @@ -40,6 +40,8 @@ #import "qcocoansmenu.h" #include "qcocoamenu.h" #include "qcocoamenuitem.h" +#include "qcocoamenubar.h" +#include "qcocoawindow.h" #import "qnsview.h" #include @@ -291,6 +293,19 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string) return nil; } +// Cocoa will query the menu item's target for the worksWhenModal selector. +// So we need to implement this to allow the items to be handled correctly +// when a modal dialog is visible. +- (BOOL)worksWhenModal +{ + if (!QGuiApplication::modalWindow()) + return YES; + const auto &qpaMenu = static_cast(self).qpaMenu; + if (auto *mb = qobject_cast(qpaMenu->menuParent())) + return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO; + return YES; +} + @end #undef CHECK_MENU_CLASS diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index e756f0aeb08..f4c968ab57d 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -72,8 +72,6 @@ ** ****************************************************************************/ -#define QT_MAC_SYSTEMTRAY_USE_GROWL - #include "qcocoasystemtrayicon.h" #ifndef QT_NO_SYSTEMTRAYICON diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index e4dd71f01b2..471a19adb04 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -498,9 +498,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) { const Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type); + const bool resizeable = type != Qt::Dialog; // Dialogs: remove zoom button by disabling resize - // Select base window type. - NSUInteger styleMask = frameless ? NSBorderlessWindowMask : NSResizableWindowMask; + // Select base window type. Note that the value of NSBorderlessWindowMask is 0. + NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask; if (frameless) { // No further customizations for frameless since there are no window decorations. @@ -1151,23 +1152,6 @@ void QCocoaWindow::handleExposeEvent(const QRegion ®ion) m_exposedRect = QRect(); } - QWindowPrivate *windowPrivate = qt_window_private(window()); - if (windowPrivate->updateRequestPending) { - // We can only deliver update request events when the window is exposed, - // and we also have to make sure we deliver any change to the exposed - // rect as a real expose event (including going from non-exposed to - // exposed). FIXME: Should this logic live in QGuiApplication? - if (isExposed() && m_exposedRect == previouslyExposedRect) { - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request"; - windowPrivate->deliverUpdateRequest(); - return; - } else { - // Since updateRequestPending is still set, we will issue a deferred setNeedsDisplay - // from drawRect and get back into this code on the next display cycle, delivering - // the pending update request. - } - } - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); QWindowSystemInterface::handleExposeEvent(window(), region); } @@ -1342,7 +1326,7 @@ void QCocoaWindow::recreateWindowIfNeeded() void QCocoaWindow::requestUpdate() { qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window(); - [m_view setNeedsDisplay:YES]; + [m_view requestUpdate]; } void QCocoaWindow::requestActivateWindow() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index f8903725a65..e2ea862cd5b 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -81,6 +81,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); NSEvent *m_currentlyInterpretedKeyEvent; bool m_isMenuView; QSet m_acceptedKeyDowns; + bool m_updateRequested; } @property (nonatomic, retain) NSCursor *cursor; @@ -105,6 +106,8 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)resetMouseButtons; +- (void)requestUpdate; + - (void)handleMouseEvent:(NSEvent *)theEvent; - (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber; - (bool)handleMouseDraggedEvent:(NSEvent *)theEvent withButton:(int)buttonNumber; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f9c28542a97..fd7f216e102 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -148,6 +148,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_isMenuView = false; self.focusRingType = NSFocusRingTypeNone; self.cursor = nil; + m_updateRequested = false; } return self; } @@ -300,6 +301,25 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") return m_platformWindow->isOpaque(); } +- (void)requestUpdate +{ + if (self.needsDisplay) { + // If the view already has needsDisplay set it means that there may be code waiting for + // a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an + // update request. We will re-trigger requestUpdate from drawRect. + return; + } + + [self setNeedsDisplay:YES]; + m_updateRequested = true; +} + +- (void)setNeedsDisplayInRect:(NSRect)rect +{ + [super setNeedsDisplayInRect:rect]; + m_updateRequested = false; +} + - (void)drawRect:(NSRect)dirtyRect { Q_UNUSED(dirtyRect); @@ -315,7 +335,11 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect(); qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion; + [self updateRegion:exposedRegion]; +} +- (void)updateRegion:(QRegion)dirtyRegion +{ #ifndef QT_NO_OPENGL if (m_glContext && m_shouldSetGLContextinDrawRect) { [m_glContext->nsOpenGLContext() setView:self]; @@ -323,18 +347,24 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") } #endif - m_platformWindow->handleExposeEvent(exposedRegion); + QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window()); - if (qt_window_private(m_platformWindow->window())->updateRequestPending) { - // A call to QWindow::requestUpdate was issued during the expose event, or we - // had to deliver a real expose event and still need to deliver the update. - // But AppKit will reset the needsDisplay state of the view after completing + if (m_updateRequested) { + Q_ASSERT(windowPrivate->updateRequestPending); + qCDebug(lcQpaCocoaWindow) << "Delivering update request to" << m_platformWindow->window(); + windowPrivate->deliverUpdateRequest(); + m_updateRequested = false; + } else { + m_platformWindow->handleExposeEvent(dirtyRegion); + } + + if (windowPrivate->updateRequestPending) { + // A call to QWindow::requestUpdate was issued during event delivery above, + // but AppKit will reset the needsDisplay state of the view after completing // the current display cycle, so we need to defer the request to redisplay. // FIXME: Perhaps this should be a trigger to enable CADisplayLink? qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request"; - dispatch_async(dispatch_get_main_queue (), ^{ - [self setNeedsDisplay:YES]; - }); + dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; }); } } @@ -351,7 +381,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") qCDebug(lcQpaCocoaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window(); // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect: - m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect()); + [self updateRegion:QRectF::fromCGRect(self.bounds).toRect()]; } - (void)viewDidChangeBackingProperties diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index f3efbea60b7..29cfd4ea79d 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -117,7 +117,7 @@ void QEglFSWindow::create() QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); if (screen->primarySurface() != EGL_NO_SURFACE) { if (Q_UNLIKELY(!isRaster() || !compositor->targetWindow())) { -#if !defined(Q_OS_ANDROID) +#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED) // We can have either a single OpenGL window or multiple raster windows. // Other combinations cannot work. qFatal("EGLFS: OpenGL windows cannot be mixed with others."); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp index 88b401c920b..475d9d55dd1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp @@ -141,10 +141,15 @@ void QEglFSKmsVsp2Screen::initDumbFrameBuffers() void QEglFSKmsVsp2Screen::initVsp2() { qCDebug(qLcEglfsKmsDebug, "Initializing Vsp2 hardware"); - const QSize screenSize = rawGeometry().size(); - m_blendDevice.reset(new QVsp2BlendingDevice(screenSize)); + m_blendDevice.reset(new QVsp2BlendingDevice(rawGeometry().size())); // Enable input for main buffer drawn by the compositor (always on) + initQtLayer(); +} + +void QEglFSKmsVsp2Screen::initQtLayer() +{ + const QSize screenSize = rawGeometry().size(); const uint bytesPerLine = uint(screenSize.width()) * 4; //TODO: is this ok? bool formatSet = m_blendDevice->enableInput(m_qtLayer, QRect(QPoint(), screenSize), m_output.drm_format, bytesPerLine); if (!formatSet) { @@ -298,8 +303,13 @@ void QEglFSKmsVsp2Screen::blendAndFlipDrm() vBlank.request.signal = 0; drmWaitVBlank(driFd, &vBlank); - if (!m_blendDevice->blend(backBuffer.dmabufFd)) - qWarning() << "Vsp2: blending failed"; + if (!m_blendDevice->blend(backBuffer.dmabufFd)) { + qWarning() << "Vsp2: Blending failed"; + + // For some reason, a failed blend may often mess up the qt layer, so reinitialize it here + m_blendDevice->disableInput(m_qtLayer); + initQtLayer(); + } for (auto cb : m_blendFinishedCallbacks) cb(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h index fa03e367853..76185103338 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h @@ -60,6 +60,7 @@ public: void initDumbFrameBuffers(); void initVsp2(); + void initQtLayer(); //TODO: use a fixed index API instead of auto increment? int addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp index 879d312341f..132806a2e3b 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp @@ -219,11 +219,12 @@ bool QVsp2BlendingDevice::blend(int outputDmabufFd) if (!m_dirty) qWarning("Blending without being dirty, should not be necessary"); - if (!m_inputs[0].enabled) { - qWarning("Vsp2: Can't blend with layer 0 disabled"); + if (!hasContinuousLayers()) { + qWarning("Vsp2: Can't blend when layers are not enabled in order from 0 without gaps."); return false; } + bool queueingFailed = false; // Queue dma input buffers for (int i=0; i < m_inputs.size(); ++i) { auto &input = m_inputs[i]; @@ -233,12 +234,22 @@ bool QVsp2BlendingDevice::blend(int outputDmabufFd) << "with dmabuf" << input.dmabuf.fd << "and size" << input.geometry.size(); - if (!disableInput(i)) - qWarning() << "Vsp2: Failed to disable input" << i; + queueingFailed = true; } } } + if (queueingFailed) { + qWarning() << "Vsp2: Trying to clean up queued buffers"; + for (auto &input : qAsConst(m_inputs)) { + if (input.enabled) { + if (!input.rpfInput->clearBuffers()) + qWarning() << "Vsp2: Failed to remove buffers after an aborted blend"; + } + } + return false; + } + if (!m_wpfOutput->queueBuffer(outputDmabufFd, m_screenSize)) { qWarning() << "Vsp2: Failed to queue blending output buffer" << outputDmabufFd << m_screenSize; return false; @@ -270,6 +281,17 @@ int QVsp2BlendingDevice::numInputs() const return m_inputs.size(); } +bool QVsp2BlendingDevice::hasContinuousLayers() const +{ + bool seenDisabled = false; + for (auto &input : qAsConst(m_inputs)) { + if (seenDisabled && input.enabled) + return false; + seenDisabled |= !input.enabled; + } + return m_inputs[0].enabled; +} + bool QVsp2BlendingDevice::streamOn() { for (auto &input : m_inputs) { diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h index be48954f47b..ee34ae654ae 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h @@ -63,6 +63,7 @@ public: bool blend(int outputDmabufFd); int numInputs() const; bool isDirty() const { return m_dirty; } + bool hasContinuousLayers() const; private: bool streamOn(); bool streamOff(); diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index d5af31044d1..2028fc2a422 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -110,6 +110,10 @@ private: friend class QIOSScreen; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QIOSWindow *window); +#endif + QT_END_NAMESPACE #endif // QIOSWINDOW_H diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 38136c05dbf..6ee258e363d 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -381,6 +381,19 @@ CAEAGLLayer *QIOSWindow::eaglLayer() const return static_cast(m_view.layer); } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QIOSWindow *window) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QIOSWindow(" << (const void *)window; + if (window) + debug << ", window=" << window->window(); + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + #include "moc_qioswindow.cpp" QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 6960698bf1a..584dfe9b41a 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -149,6 +149,21 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") [super dealloc]; } +- (NSString *)description +{ + NSMutableString *description = [NSMutableString stringWithString:[super description]]; + +#ifndef QT_NO_DEBUG_STREAM + QString platformWindowDescription; + QDebug debug(&platformWindowDescription); + debug.nospace() << "; " << m_qioswindow << ">"; + NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1]; + [description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()]; +#endif + + return description; +} + - (void)willMoveToWindow:(UIWindow *)newWindow { // UIKIt will normally set the scale factor of a view to match the corresponding @@ -193,13 +208,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") // when the size is also changed. if (!CGAffineTransformIsIdentity(self.transform)) - qWarning() << m_qioswindow->window() - << "is backed by a UIView that has a transform set. This is not supported."; + qWarning() << self << "has a transform set. This is not supported."; QWindow *window = m_qioswindow->window(); QRect lastReportedGeometry = qt_window_private(window)->geometry; QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect(); - qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << currentGeometry; + qCDebug(lcQpaWindow) << m_qioswindow << "new geometry is" << currentGeometry; QWindowSystemInterface::handleGeometryChange(window, currentGeometry); if (currentGeometry.size() != lastReportedGeometry.size()) { @@ -232,7 +246,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") region = QRect(QPoint(), bounds); } - qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed(); + qCDebug(lcQpaWindow) << m_qioswindow << region << "isExposed" << m_qioswindow->isExposed(); QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); } @@ -256,16 +270,14 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") // blocked by this guard. FirstResponderCandidate firstResponderCandidate(self); - qImDebug() << "win:" << m_qioswindow->window() << "self:" << self - << "first:" << [UIResponder currentFirstResponder]; + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; if (![super becomeFirstResponder]) { - qImDebug() << m_qioswindow->window() - << "was not allowed to become first responder"; + qImDebug() << self << "was not allowed to become first responder"; return NO; } - qImDebug() << m_qioswindow->window() << "became first responder"; + qImDebug() << self << "became first responder"; } if (qGuiApp->focusWindow() != m_qioswindow->window()) @@ -297,13 +309,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") - (BOOL)resignFirstResponder { - qImDebug() << "win:" << m_qioswindow->window() << "self:" << self - << "first:" << [UIResponder currentFirstResponder]; + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; if (![super resignFirstResponder]) return NO; - qImDebug() << m_qioswindow->window() << "resigned first responder"; + qImDebug() << self << "resigned first responder"; UIResponder *newResponder = FirstResponderCandidate::currentCandidate(); if ([self responderShouldTriggerWindowDeactivation:newResponder]) diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 6f79cd96d30..f835dbf6d41 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -59,13 +59,13 @@ #include #endif -#if QT_CONFIG(evdev) && !defined(Q_OS_ANDROID) +#if QT_CONFIG(evdev) #include #include #include #endif -#if QT_CONFIG(tslib) && !defined(Q_OS_ANDROID) +#if QT_CONFIG(tslib) #include #endif @@ -162,7 +162,7 @@ void QLinuxFbIntegration::createInputHandlers() new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); #endif -#if QT_CONFIG(evdev) && !defined(Q_OS_ANDROID) +#if QT_CONFIG(evdev) new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); #if QT_CONFIG(tslib) diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 9ccc2b54b9c..e61887618fc 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs QT_FOR_CONFIG += gui-private -android: SUBDIRS += android +android:!android-embedded: SUBDIRS += android !android: SUBDIRS += minimal @@ -36,7 +36,7 @@ qtConfig(directfb) { qtConfig(linuxfb): SUBDIRS += linuxfb -qtConfig(vnc): SUBDIRS += vnc +qtHaveModule(network):qtConfig(vnc): SUBDIRS += vnc freebsd { SUBDIRS += bsdfb diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 15d33200e5f..96bfa1dd192 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -71,14 +71,14 @@ HEADERS = main.h \ LIBS += -lscreen -qtConfig(opengles2) { +qtConfig(egl) { SOURCES += qqnxglcontext.cpp \ qqnxeglwindow.cpp HEADERS += qqnxglcontext.h \ qqnxeglwindow.h - QMAKE_USE += opengl_es2 egl + QMAKE_USE += egl } qtConfig(qqnx_pps) { diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp index 33ce0f924c2..48766fc4358 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp @@ -56,18 +56,12 @@ QT_BEGIN_NAMESPACE QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow) : QQnxWindow(window, context, needRootWindow), - m_platformOpenGLContext(0), m_newSurfaceRequested(true), + m_eglDisplay(EGL_NO_DISPLAY), m_eglSurface(EGL_NO_SURFACE) { initWindow(); - // Set window usage - const int val = SCREEN_USAGE_OPENGL_ES2; - const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val); - if (Q_UNLIKELY(result != 0)) - qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno); - m_requestedBufferSize = shouldMakeFullScreen() ? screen()->geometry().size() : window->geometry().size(); } @@ -77,14 +71,58 @@ QQnxEglWindow::~QQnxEglWindow() destroyEGLSurface(); } -void QQnxEglWindow::createEGLSurface() +bool QQnxEglWindow::isInitialized() const { + return m_eglSurface != EGL_NO_SURFACE; +} + +void QQnxEglWindow::ensureInitialized(QQnxGLContext* context) +{ + if (m_newSurfaceRequested.testAndSetOrdered(true, false)) { + const QMutexLocker locker(&m_mutex); // Set geomety must not reset the requestedBufferSize till + // the surface is created + + if (m_requestedBufferSize != bufferSize() || m_eglSurface == EGL_NO_SURFACE) { + if (m_eglSurface != EGL_NO_SURFACE) { + context->doneCurrent(); + destroyEGLSurface(); + } + createEGLSurface(context); + } else { + // Must've been a sequence of unprocessed changes returning us to the original size. + resetBuffers(); + } + } +} + +void QQnxEglWindow::createEGLSurface(QQnxGLContext *context) +{ + if (context->format().renderableType() != QSurfaceFormat::OpenGLES) { + qFatal("QQnxEglWindow: renderable type is not OpenGLES"); + return; + } + + // Set window usage + int usage = SCREEN_USAGE_OPENGL_ES2; +#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(1, 0, 0) + if (context->format().majorVersion() == 3) + usage |= SCREEN_USAGE_OPENGL_ES3; +#endif + + const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &usage); + if (Q_UNLIKELY(result != 0)) + qFatal("QQnxEglWindow: failed to set window usage, errno=%d", errno); + if (!m_requestedBufferSize.isValid()) { qWarning("QQNX: Trying to create 0 size EGL surface. " "Please set a valid window size before calling QOpenGLContext::makeCurrent()"); return; } + m_eglDisplay = context->eglDisplay(); + m_eglConfig = context->eglConfig(); + m_format = context->format(); + // update the window's buffers before we create the EGL surface setBufferSize(m_requestedBufferSize); @@ -94,24 +132,27 @@ void QQnxEglWindow::createEGLSurface() EGL_NONE }; - qEglWindowDebug() << "Creating EGL surface" << platformOpenGLContext()->getEglDisplay() - << platformOpenGLContext()->getEglConfig(); + qEglWindowDebug() << "Creating EGL surface from" << this << context + << window()->surfaceType() << window()->type(); // Create EGL surface - m_eglSurface = eglCreateWindowSurface(platformOpenGLContext()->getEglDisplay(), - platformOpenGLContext()->getEglConfig(), - (EGLNativeWindowType) nativeHandle(), eglSurfaceAttrs); - if (m_eglSurface == EGL_NO_SURFACE) { - const EGLenum error = QQnxGLContext::checkEGLError("eglCreateWindowSurface"); - qWarning("QQNX: failed to create EGL surface, err=%d", error); - } + EGLSurface eglSurface = eglCreateWindowSurface( + m_eglDisplay, + m_eglConfig, + (EGLNativeWindowType) nativeHandle(), + eglSurfaceAttrs); + + if (eglSurface == EGL_NO_SURFACE) + qWarning("QQNX: failed to create EGL surface, err=%d", eglGetError()); + + m_eglSurface = eglSurface; } void QQnxEglWindow::destroyEGLSurface() { // Destroy EGL surface if it exists if (m_eglSurface != EGL_NO_SURFACE) { - EGLBoolean eglResult = eglDestroySurface(platformOpenGLContext()->getEglDisplay(), m_eglSurface); + EGLBoolean eglResult = eglDestroySurface(m_eglDisplay, m_eglSurface); if (Q_UNLIKELY(eglResult != EGL_TRUE)) qFatal("QQNX: failed to destroy EGL surface, err=%d", eglGetError()); } @@ -119,40 +160,8 @@ void QQnxEglWindow::destroyEGLSurface() m_eglSurface = EGL_NO_SURFACE; } -void QQnxEglWindow::swapEGLBuffers() +EGLSurface QQnxEglWindow::surface() const { - qEglWindowDebug(); - // Set current rendering API - EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to set EGL API, err=%d", eglGetError()); - - // Post EGL surface to window - eglResult = eglSwapBuffers(m_platformOpenGLContext->getEglDisplay(), m_eglSurface); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError()); - - windowPosted(); -} - -EGLSurface QQnxEglWindow::getSurface() -{ - if (m_newSurfaceRequested.testAndSetOrdered(true, false)) { - const QMutexLocker locker(&m_mutex); //Set geomety must not reset the requestedBufferSize till - //the surface is created - - if ((m_requestedBufferSize != bufferSize()) || (m_eglSurface == EGL_NO_SURFACE)) { - if (m_eglSurface != EGL_NO_SURFACE) { - platformOpenGLContext()->doneCurrent(); - destroyEGLSurface(); - } - createEGLSurface(); - } else { - // Must've been a sequence of unprocessed changes returning us to the original size. - resetBuffers(); - } - } - return m_eglSurface; } @@ -169,35 +178,24 @@ void QQnxEglWindow::setGeometry(const QRect &rect) // that test. const QMutexLocker locker(&m_mutex); m_requestedBufferSize = newGeometry.size(); - if (m_platformOpenGLContext != 0 && bufferSize() != newGeometry.size()) + if (isInitialized() && bufferSize() != newGeometry.size()) m_newSurfaceRequested.testAndSetRelease(false, true); } QQnxWindow::setGeometry(newGeometry); } -void QQnxEglWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext) -{ - // This function does not take ownership of the platform gl context. - // It is owned by the frontend QOpenGLContext - m_platformOpenGLContext = platformOpenGLContext; -} - int QQnxEglWindow::pixelFormat() const { - if (!m_platformOpenGLContext) //The platform GL context was not set yet - return -1; - - const QSurfaceFormat format = m_platformOpenGLContext->format(); // Extract size of color channels from window format - const int redSize = format.redBufferSize(); + const int redSize = m_format.redBufferSize(); if (Q_UNLIKELY(redSize == -1)) qFatal("QQnxWindow: red size not defined"); - const int greenSize = format.greenBufferSize(); + const int greenSize = m_format.greenBufferSize(); if (Q_UNLIKELY(greenSize == -1)) qFatal("QQnxWindow: green size not defined"); - const int blueSize = format.blueBufferSize(); + const int blueSize = m_format.blueBufferSize(); if (Q_UNLIKELY(blueSize == -1)) qFatal("QQnxWindow: blue size not defined"); diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.h b/src/plugins/platforms/qnx/qqnxeglwindow.h index 183be11ddcf..3a3840f13c2 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.h +++ b/src/plugins/platforms/qnx/qqnxeglwindow.h @@ -53,13 +53,10 @@ public: QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow); ~QQnxEglWindow(); - void createEGLSurface(); - void destroyEGLSurface(); - void swapEGLBuffers(); - EGLSurface getSurface(); + EGLSurface surface() const; - void setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext); - QQnxGLContext *platformOpenGLContext() const { return m_platformOpenGLContext; } + bool isInitialized() const; + void ensureInitialized(QQnxGLContext *context); void setGeometry(const QRect &rect) override; @@ -68,6 +65,9 @@ protected: void resetBuffers() override; private: + void createEGLSurface(QQnxGLContext *context); + void destroyEGLSurface(); + QSize m_requestedBufferSize; // This mutex is used to protect access to the m_requestedBufferSize @@ -78,9 +78,11 @@ private: // QQnxGLContext::makeCurrent() mutable QMutex m_mutex; - QQnxGLContext *m_platformOpenGLContext; QAtomicInt m_newSurfaceRequested; + EGLDisplay m_eglDisplay; + EGLConfig m_eglConfig; EGLSurface m_eglSurface; + QSurfaceFormat m_format; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index d35a4f0bba4..d4493943e23 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -59,117 +59,13 @@ QT_BEGIN_NAMESPACE EGLDisplay QQnxGLContext::ms_eglDisplay = EGL_NO_DISPLAY; -QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext) - : QPlatformOpenGLContext(), - m_glContext(glContext), - m_currentEglSurface(EGL_NO_SURFACE) +QQnxGLContext::QQnxGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share) + : QEGLPlatformContext(format, share, ms_eglDisplay) { - qGLContextDebug(); - QSurfaceFormat format = m_glContext->format(); - - // Set current rendering API - EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to set EGL API, err=%d", eglGetError()); - - // Get colour channel sizes from window format - int alphaSize = format.alphaBufferSize(); - int redSize = format.redBufferSize(); - int greenSize = format.greenBufferSize(); - int blueSize = format.blueBufferSize(); - - // Check if all channels are don't care - if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) { - // Set colour channels based on depth of window's screen - QQnxScreen *screen = static_cast(glContext->screen()->handle()); - int depth = screen->depth(); - if (depth == 32) { - // SCREEN_FORMAT_RGBA8888 - alphaSize = 8; - redSize = 8; - greenSize = 8; - blueSize = 8; - } else { - // SCREEN_FORMAT_RGB565 - alphaSize = 0; - redSize = 5; - greenSize = 6; - blueSize = 5; - } - } else { - // Choose best match based on supported pixel formats - if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) { - // SCREEN_FORMAT_RGB565 - alphaSize = 0; - redSize = 5; - greenSize = 6; - blueSize = 5; - } else { - // SCREEN_FORMAT_RGBA8888 - alphaSize = 8; - redSize = 8; - greenSize = 8; - blueSize = 8; - } - } - - // Update colour channel sizes in window format - format.setAlphaBufferSize(alphaSize); - format.setRedBufferSize(redSize); - format.setGreenBufferSize(greenSize); - format.setBlueBufferSize(blueSize); - - // Select EGL config based on requested window format - m_eglConfig = q_configFromGLFormat(ms_eglDisplay, format); - if (Q_UNLIKELY(m_eglConfig == 0)) - qFatal("QQnxGLContext: failed to find EGL config"); - - QQnxGLContext *glShareContext = static_cast(m_glContext->shareHandle()); - m_eglShareContext = glShareContext ? glShareContext->m_eglContext : EGL_NO_CONTEXT; - - m_eglContext = eglCreateContext(ms_eglDisplay, m_eglConfig, m_eglShareContext, - contextAttrs(format)); - if (Q_UNLIKELY(m_eglContext == EGL_NO_CONTEXT)) { - checkEGLError("eglCreateContext"); - qFatal("QQnxGLContext: failed to create EGL context, err=%d", eglGetError()); - } - - // Query/cache window format of selected EGL config - m_windowFormat = q_glFormatFromConfig(ms_eglDisplay, m_eglConfig); } QQnxGLContext::~QQnxGLContext() { - qGLContextDebug(); - - // Cleanup EGL context if it exists - if (m_eglContext != EGL_NO_CONTEXT) - eglDestroyContext(ms_eglDisplay, m_eglContext); -} - -EGLenum QQnxGLContext::checkEGLError(const char *msg) -{ - static const char *errmsg[] = - { - "EGL function succeeded", - "EGL is not initialized, or could not be initialized, for the specified display", - "EGL cannot access a requested resource", - "EGL failed to allocate resources for the requested operation", - "EGL fail to access an unrecognized attribute or attribute value was passed in an attribute list", - "EGLConfig argument does not name a valid EGLConfig", - "EGLContext argument does not name a valid EGLContext", - "EGL current surface of the calling thread is no longer valid", - "EGLDisplay argument does not name a valid EGLDisplay", - "EGL arguments are inconsistent", - "EGLNativePixmapType argument does not refer to a valid native pixmap", - "EGLNativeWindowType argument does not refer to a valid native window", - "EGL one or more argument values are invalid", - "EGLSurface argument does not name a valid surface configured for rendering", - "EGL power management event has occurred", - }; - EGLenum error = eglGetError(); - fprintf(stderr, "%s: %s\n", msg, errmsg[error - EGL_SUCCESS]); - return error; } void QQnxGLContext::initializeContext() @@ -178,16 +74,12 @@ void QQnxGLContext::initializeContext() // Initialize connection to EGL ms_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (Q_UNLIKELY(ms_eglDisplay == EGL_NO_DISPLAY)) { - checkEGLError("eglGetDisplay"); - qFatal("QQnxGLContext: failed to obtain EGL display"); - } + if (Q_UNLIKELY(ms_eglDisplay == EGL_NO_DISPLAY)) + qFatal("QQnxGLContext: failed to obtain EGL display: %x", eglGetError()); EGLBoolean eglResult = eglInitialize(ms_eglDisplay, 0, 0); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) { - checkEGLError("eglInitialize"); + if (Q_UNLIKELY(eglResult != EGL_TRUE)) qFatal("QQnxGLContext: failed to initialize EGL display, err=%d", eglGetError()); - } } void QQnxGLContext::shutdownContext() @@ -198,98 +90,32 @@ void QQnxGLContext::shutdownContext() eglTerminate(ms_eglDisplay); } +EGLSurface QQnxGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +{ + QQnxEglWindow *window = static_cast(surface); + window->ensureInitialized(this); + return window->surface(); +} + bool QQnxGLContext::makeCurrent(QPlatformSurface *surface) { qGLContextDebug(); - - Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); - - // Set current rendering API - EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQnxGLContext: failed to set EGL API, err=%d", eglGetError()); - - QQnxEglWindow *platformWindow = dynamic_cast(surface); - if (!platformWindow) - return false; - - platformWindow->setPlatformOpenGLContext(this); - - if (m_currentEglSurface == EGL_NO_SURFACE || m_currentEglSurface != platformWindow->getSurface()) { - m_currentEglSurface = platformWindow->getSurface(); - doneCurrent(); - } - - eglResult = eglMakeCurrent(ms_eglDisplay, m_currentEglSurface, m_currentEglSurface, m_eglContext); - if (eglResult != EGL_TRUE) { - checkEGLError("eglMakeCurrent"); - qWarning("QQNX: failed to set current EGL context, err=%d", eglGetError()); - return false; - } - return (eglResult == EGL_TRUE); -} - -void QQnxGLContext::doneCurrent() -{ - qGLContextDebug(); - - // set current rendering API - EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to set EGL API, err=%d", eglGetError()); - - // clear curent EGL context and unbind EGL surface - eglResult = eglMakeCurrent(ms_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to clear current EGL context, err=%d", eglGetError()); + return QEGLPlatformContext::makeCurrent(surface); } void QQnxGLContext::swapBuffers(QPlatformSurface *surface) { qGLContextDebug(); - QQnxEglWindow *platformWindow = dynamic_cast(surface); - if (!platformWindow) - return; - platformWindow->swapEGLBuffers(); + QEGLPlatformContext::swapBuffers(surface); + + QQnxEglWindow *platformWindow = static_cast(surface); + platformWindow->windowPosted(); } -QFunctionPointer QQnxGLContext::getProcAddress(const char *procName) +void QQnxGLContext::doneCurrent() { - qGLContextDebug(); - - // Set current rendering API - EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); - if (Q_UNLIKELY(eglResult != EGL_TRUE)) - qFatal("QQNX: failed to set EGL API, err=%d", eglGetError()); - - // Lookup EGL extension function pointer - QFunctionPointer result = static_cast(eglGetProcAddress(procName)); - if (!result) - result = reinterpret_cast(dlsym(RTLD_DEFAULT, procName)); - return result; -} - -bool QQnxGLContext::isSharing() const -{ - return m_eglShareContext != EGL_NO_CONTEXT; -} - -EGLDisplay QQnxGLContext::getEglDisplay() { - return ms_eglDisplay; -} - -EGLint *QQnxGLContext::contextAttrs(const QSurfaceFormat &format) -{ - qGLContextDebug(); - - // Choose EGL settings based on OpenGL version -#if defined(QT_OPENGL_ES_2) - static EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, format.version().first, EGL_NONE }; - return attrs; -#else - return 0; -#endif + QEGLPlatformContext::doneCurrent(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index 6e5408e8bf0..19179a80e25 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -46,49 +46,31 @@ #include #include +#include QT_BEGIN_NAMESPACE class QQnxWindow; -class QQnxGLContext : public QPlatformOpenGLContext +class QQnxGLContext : public QEGLPlatformContext { public: - QQnxGLContext(QOpenGLContext *glContext); + QQnxGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share); virtual ~QQnxGLContext(); - static EGLenum checkEGLError(const char *msg); - static void initializeContext(); static void shutdownContext(); - void requestSurfaceChange(); - bool makeCurrent(QPlatformSurface *surface) override; - void doneCurrent() override; void swapBuffers(QPlatformSurface *surface) override; - QFunctionPointer getProcAddress(const char *procName) override; + void doneCurrent() override; - virtual QSurfaceFormat format() const override { return m_windowFormat; } - bool isSharing() const override; - - static EGLDisplay getEglDisplay(); - EGLConfig getEglConfig() const { return m_eglConfig;} - EGLContext getEglContext() const { return m_eglContext; } +protected: + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; private: //Can be static because different displays returne the same handle static EGLDisplay ms_eglDisplay; - - QSurfaceFormat m_windowFormat; - QOpenGLContext *m_glContext; - - EGLConfig m_eglConfig; - EGLContext m_eglContext; - EGLContext m_eglShareContext; - EGLSurface m_currentEglSurface; - - static EGLint *contextAttrs(const QSurfaceFormat &format); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 072510e0528..bffe7ee34bd 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -313,7 +313,58 @@ QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *wind QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { qIntegrationDebug(); - return new QQnxGLContext(context); + + // Get color channel sizes from window format + QSurfaceFormat format = context->format(); + int alphaSize = format.alphaBufferSize(); + int redSize = format.redBufferSize(); + int greenSize = format.greenBufferSize(); + int blueSize = format.blueBufferSize(); + + // Check if all channels are don't care + if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) { + // Set color channels based on depth of window's screen + QQnxScreen *screen = static_cast(context->screen()->handle()); + int depth = screen->depth(); + if (depth == 32) { + // SCREEN_FORMAT_RGBA8888 + alphaSize = 8; + redSize = 8; + greenSize = 8; + blueSize = 8; + } else { + // SCREEN_FORMAT_RGB565 + alphaSize = 0; + redSize = 5; + greenSize = 6; + blueSize = 5; + } + } else { + // Choose best match based on supported pixel formats + if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) { + // SCREEN_FORMAT_RGB565 + alphaSize = 0; + redSize = 5; + greenSize = 6; + blueSize = 5; + } else { + // SCREEN_FORMAT_RGBA8888 + alphaSize = 8; + redSize = 8; + greenSize = 8; + blueSize = 8; + } + } + + // Update color channel sizes in window format + format.setAlphaBufferSize(alphaSize); + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + context->setFormat(format); + + QQnxGLContext *ctx = new QQnxGLContext(context->format(), context->shareHandle()); + return ctx; } #endif diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 468fe9cd91b..3eebb9c7424 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -98,7 +98,7 @@ void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resour void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { if (resource == "eglcontext" && context) - return static_cast(context->handle())->getEglContext(); + return static_cast(context->handle())->eglContext(); return 0; } diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h index 8a498434aaa..a6d5623d049 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.h +++ b/src/plugins/platforms/qnx/qqnxscreen.h @@ -49,10 +49,14 @@ #include -// For pre-7.0 SDPs, map some screen property names to the old +#if !defined(_SCREEN_VERSION) +#define _SCREEN_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch)) +#define _SCREEN_VERSION _SCREEN_MAKE_VERSION(0, 0, 0) +#endif + +// For pre-1.0.0 screen, map some screen property names to the old // names. -#include -#if _NTO_VERSION < 700 +#if _SCREEN_VERSION < _SCREEN_MAKE_VERSION(1, 0, 0) const int SCREEN_PROPERTY_FLAGS = SCREEN_PROPERTY_KEY_FLAGS; const int SCREEN_PROPERTY_FOCUS = SCREEN_PROPERTY_KEYBOARD_FOCUS; const int SCREEN_PROPERTY_MODIFIERS = SCREEN_PROPERTY_KEY_MODIFIERS; diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index dfcca78f80e..2895a547b17 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -112,12 +112,13 @@ public: bool shouldMakeFullScreen() const; + void windowPosted(); + protected: virtual int pixelFormat() const = 0; virtual void resetBuffers() = 0; void initWindow(); - void windowPosted(); screen_context_t m_screenContext; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index c146f8ec252..3d0dbd7b1a3 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -980,8 +980,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::QuerySizeHints: d->m_creationContext->applyToMinMaxInfo(reinterpret_cast(lParam)); return true; - case QtWindows::ResizeEvent: - d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + case QtWindows::ResizeEvent: { + const QSize size(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) - d->m_creationContext->menuHeight); + d->m_creationContext->obtainedGeometry.setSize(size); + } return true; case QtWindows::MoveEvent: d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 70ee708b618..80ee7b22870 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -68,7 +68,6 @@ #include #include #include -#include #include #include @@ -1135,12 +1134,32 @@ void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel } } +static bool isHexRange(const QString& s, int start, int end) +{ + for (;start < end; ++start) { + QChar ch = s.at(start); + if (!(ch.isDigit() + || (ch >= QLatin1Char('a') && ch <= QLatin1Char('f')) + || (ch >= QLatin1Char('A') && ch <= QLatin1Char('F')))) + return false; + } + return true; +} + static inline bool isClsid(const QString &s) { // detect "374DE290-123F-4565-9164-39C4925E467B". - static const QRegularExpression pattern(QLatin1String("\\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\\z")); - Q_ASSERT(pattern.isValid()); - return pattern.match(s).hasMatch(); + const QChar dash(QLatin1Char('-')); + return s.size() == 36 + && isHexRange(s, 0, 8) + && s.at(8) == dash + && isHexRange(s, 9, 13) + && s.at(13) == dash + && isHexRange(s, 14, 18) + && s.at(18) == dash + && isHexRange(s, 19, 23) + && s.at(23) == dash + && isHexRange(s, 24, 36); } void QWindowsNativeFileDialogBase::selectFile(const QString &fileName) const diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index ada124b5af0..159e1250d0b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1034,8 +1034,10 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QMargins effectiveMargins = margins + customMargins; frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right(); frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom(); - if (QWindowsMenuBar::menuBarOf(w) != nullptr) - frameHeight += GetSystemMetrics(SM_CYMENU); + if (QWindowsMenuBar::menuBarOf(w) != nullptr) { + menuHeight = GetSystemMetrics(SM_CYMENU); + frameHeight += menuHeight; + } const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel(); if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) { frameX -= effectiveMargins.left(); @@ -2558,7 +2560,7 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) newFrame.moveTo(topLeft); qCDebug(lcQpaWindows) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins << currentFrameGeometry << "->" << newFrame; - SetWindowPos(m_data.hwnd, 0, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED); + SetWindowPos(m_data.hwnd, 0, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 37322557387..8d29b871bf7 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -101,6 +101,7 @@ struct QWindowCreationContext int frameY = CW_USEDEFAULT; int frameWidth = CW_USEDEFAULT; int frameHeight = CW_USEDEFAULT; + int menuHeight = 0; }; struct QWindowsWindowData diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 56a737e8824..21024385b08 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -134,7 +134,11 @@ static void updateFormatFromContext(QSurfaceFormat &format) } format.setProfile(QSurfaceFormat::NoProfile); + const bool isStereo = format.testOption(QSurfaceFormat::StereoBuffers); format.setOptions(QSurfaceFormat::FormatOptions()); + // Restore flags that come from the VisualInfo/FBConfig. + if (isStereo) + format.setOption(QSurfaceFormat::StereoBuffers); if (format.renderableType() == QSurfaceFormat::OpenGL) { if (format.version() < qMakePair(3, 0)) { diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 1cf45c96d13..eae0ee76131 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -48,9 +48,11 @@ #include #include +#include #include #include +#include #include #include @@ -61,6 +63,11 @@ #include #include + +#if (XCB_SHM_MAJOR_VERSION == 1 && XCB_SHM_MINOR_VERSION >= 2) || XCB_SHM_MAJOR_VERSION > 1 +#define XCB_USE_SHM_FD +#endif + QT_BEGIN_NAMESPACE class QXcbShmImage : public QXcbObject @@ -85,6 +92,9 @@ public: void preparePaint(const QRegion ®ion); private: + void createShmSegment(size_t segmentSize); + void destroyShmSegment(size_t segmentSize); + void destroy(); void ensureGC(xcb_drawable_t dst); @@ -154,6 +164,11 @@ private: QImage *m_image; }; +static inline size_t imageDataSize(const xcb_image_t *image) +{ + return static_cast(image->stride) * image->height; +} + QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format) : QXcbObject(screen->connection()) , m_graphics_buffer(nullptr) @@ -173,39 +188,13 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI XCB_IMAGE_ORDER_MSB_FIRST, 0, ~0, 0); - const int segmentSize = m_xcb_image->stride * m_xcb_image->height; + const size_t segmentSize = imageDataSize(m_xcb_image); if (!segmentSize) return; - int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); - if (id == -1) { - qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %d (%dx%d)", - errno, strerror(errno), segmentSize, size.width(), size.height()); - } else { - m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat(id, 0, 0); - } - m_shm_info.shmid = id; - m_shm_info.shmseg = xcb_generate_id(xcb_connection()); + createShmSegment(segmentSize); - const xcb_query_extension_reply_t *shm_reply = xcb_get_extension_data(xcb_connection(), &xcb_shm_id); - bool shm_present = shm_reply != NULL && shm_reply->present; - xcb_generic_error_t *error = NULL; - if (shm_present) - error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); - if (!shm_present || error || id == -1) { - free(error); - - if (id != -1) { - shmdt(m_shm_info.shmaddr); - shmctl(m_shm_info.shmid, IPC_RMID, 0); - } - m_shm_info.shmaddr = 0; - - m_xcb_image->data = (uint8_t *)malloc(segmentSize); - } else { - if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1) - qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); - } + m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize); m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; if (!m_hasAlpha) @@ -270,6 +259,111 @@ void QXcbShmImage::flushScrolledRegion(bool clientSideScroll) } } +void QXcbShmImage::createShmSegment(size_t segmentSize) +{ + m_shm_info.shmaddr = nullptr; + + if (!connection()->hasShm()) + return; + +#ifdef XCB_USE_SHM_FD + if (connection()->hasShmFd()) { + if (Q_UNLIKELY(segmentSize > std::numeric_limits::max())) { + qWarning("QXcbShmImage: xcb_shm_create_segment() can't be called for size %zu, maximum allowed size is %u", + segmentSize, std::numeric_limits::max()); + return; + } + const auto seg = xcb_generate_id(xcb_connection()); + auto reply = Q_XCB_REPLY(xcb_shm_create_segment, + xcb_connection(), seg, segmentSize, false); + if (!reply) { + qWarning("QXcbShmImage: xcb_shm_create_segment() failed for size %zu", segmentSize); + return; + } + + int *fds = xcb_shm_create_segment_reply_fds(xcb_connection(), reply.get()); + if (reply->nfd != 1) { + for (int i = 0; i < reply->nfd; i++) + close(fds[i]); + + qWarning("QXcbShmImage: failed to get file descriptor for shm segment of size %zu", segmentSize); + return; + } + + void *addr = mmap(nullptr, segmentSize, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0); + if (addr == MAP_FAILED) { + qWarning("QXcbShmImage: failed to mmap segment from X server (%d: %s) for size %zu", + errno, strerror(errno), segmentSize); + close(fds[0]); + xcb_shm_detach(xcb_connection(), seg); + return; + } + + close(fds[0]); + m_shm_info.shmseg = seg; + m_shm_info.shmaddr = static_cast(addr); + } else +#endif + { + const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); + if (id == -1) { + qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu", + errno, strerror(errno), segmentSize); + return; + } + + void *addr = shmat(id, 0, 0); + if (addr == (void *)-1) { + qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d", + errno, strerror(errno), id); + return; + } + + if (shmctl(id, IPC_RMID, 0) == -1) + qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); + + const auto seg = xcb_generate_id(xcb_connection()); + auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false); + auto *error = xcb_request_check(xcb_connection(), cookie); + if (error) { + connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error); + free(error); + if (shmdt(addr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), addr); + } + return; + } + + m_shm_info.shmseg = seg; + m_shm_info.shmid = id; // unused + m_shm_info.shmaddr = static_cast(addr); + } +} + +void QXcbShmImage::destroyShmSegment(size_t segmentSize) +{ + auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg); + xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); + if (error) + connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error); + +#ifdef XCB_USE_SHM_FD + if (connection()->hasShmFd()) { + if (munmap(m_shm_info.shmaddr, segmentSize) == -1) { + qWarning("QXcbShmImage: munmap() failed (%d: %s) for %p with size %zu", + errno, strerror(errno), m_shm_info.shmaddr, segmentSize); + } + } else +#endif + { + if (shmdt(m_shm_info.shmaddr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), m_shm_info.shmaddr); + } + } +} + extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) @@ -318,17 +412,11 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) void QXcbShmImage::destroy() { - const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0; - if (segmentSize && m_shm_info.shmaddr) - xcb_shm_detach(xcb_connection(), m_shm_info.shmseg); - - if (segmentSize) { - if (m_shm_info.shmaddr) { - shmdt(m_shm_info.shmaddr); - shmctl(m_shm_info.shmid, IPC_RMID, 0); - } else { + if (m_xcb_image->data) { + if (m_shm_info.shmaddr) + destroyShmSegment(imageDataSize(m_xcb_image)); + else free(m_xcb_image->data); - } } xcb_image_destroy(m_xcb_image); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index d6013541fcb..ee25d6a12f5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -582,6 +582,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeAllAtoms(); + initializeShm(); if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR")) initializeXRandr(); if (!has_randr_extension) @@ -961,14 +962,20 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result)) return; + printXcbError("QXcbConnection: XCB error", error); +} + +void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *error) +{ uint clamped_error_code = qMin(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); uint clamped_major_code = qMin(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", - int(error->error_code), xcb_errors[clamped_error_code], - int(error->sequence), int(error->resource_id), - int(error->major_code), xcb_protocol_request_codes[clamped_major_code], - int(error->minor_code)); + qWarning("%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", + message, + int(error->error_code), xcb_errors[clamped_error_code], + int(error->sequence), int(error->resource_id), + int(error->major_code), xcb_protocol_request_codes[clamped_major_code], + int(error->minor_code)); } static Qt::MouseButtons translateMouseButtons(int s) @@ -2084,6 +2091,26 @@ void QXcbConnection::sync() free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); } +void QXcbConnection::initializeShm() +{ + const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id); + if (!reply || !reply->present) { + qWarning("QXcbConnection: MIT-SHM extension is not present on the X server."); + return; + } + + has_shm = true; + + auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection); + if (!shm_query) { + qWarning("QXcbConnection: Failed to request MIT-SHM version"); + return; + } + + has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) || + shm_query->major_version > 1; +} + void QXcbConnection::initializeXFixes() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 2e06292f78f..0a7f878ed86 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -438,6 +438,7 @@ public: void sync(); void handleXcbError(xcb_generic_error_t *error); + void printXcbError(const char *message, xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); void printXcbEvent(const QLoggingCategory &log, const char *message, xcb_generic_event_t *event) const; @@ -475,6 +476,8 @@ public: bool hasXKB() const { return has_xkb; } bool hasXRender() const { return has_render_extension; } bool hasXInput2() const { return m_xi2Enabled; } + bool hasShm() const { return has_shm; } + bool hasShmFd() const { return has_shm_fd; } bool threadedEventHandling() const { return m_reader->isRunning(); } @@ -542,6 +545,7 @@ private slots: private: void initializeAllAtoms(); void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); + void initializeShm(); void initializeXFixes(); void initializeXRender(); void initializeXRandr(); @@ -696,6 +700,8 @@ private: bool has_input_shape; bool has_xkb = false; bool has_render_extension = false; + bool has_shm = false; + bool has_shm_fd = false; Qt::MouseButtons m_buttonState = 0; Qt::MouseButton m_button = Qt::NoButton; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5b05a230e4a..e9a6e536a75 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2071,7 +2071,7 @@ bool QXcbWindow::isEmbedded() const QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const { if (!m_embedded) - return pos; + return QPlatformWindow::mapToGlobal(pos); QPoint ret; auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), @@ -2088,7 +2088,7 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const { if (!m_embedded) - return pos; + return QPlatformWindow::mapFromGlobal(pos); QPoint ret; auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), @@ -2857,7 +2857,7 @@ QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window) utf8Atom, 0, 1024); if (reply && reply->format == 8 && reply->type == utf8Atom) { const char *name = reinterpret_cast(xcb_get_property_value(reply.get())); - return QString::fromUtf8(name); + return QString::fromUtf8(name, xcb_get_property_value_length(reply.get())); } return QString(); } diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp index 0b677390950..ec4ff68e8da 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp @@ -41,6 +41,7 @@ #include #include +#include #undef signals #include @@ -426,9 +427,11 @@ void QGtk3Menu::showPopup(const QWindow *parentWindow, const QRect &targetRect, if (index != -1) gtk_menu_set_active(GTK_MENU(m_menu), index); - m_targetPos = targetRect.bottomLeft(); - if (parentWindow) - m_targetPos = parentWindow->mapToGlobal(m_targetPos); + m_targetPos = QPoint(targetRect.x(), targetRect.y() + targetRect.height()); + + QPlatformWindow *pw = parentWindow ? parentWindow->handle() : nullptr; + if (pw) + m_targetPos = pw->mapToGlobal(m_targetPos); gtk_menu_popup(GTK_MENU(m_menu), NULL, NULL, qt_gtk_menu_position_func, this, 0, gtk_get_current_event_time()); } diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp index 6447776f253..077955eb4e2 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp @@ -153,7 +153,7 @@ bool QGtk3Theme::usePlatformNativeDialog(DialogType type) const case ColorDialog: return true; case FileDialog: - return true; + return useNativeFileDialog(); case FontDialog: return true; default: @@ -167,6 +167,8 @@ QPlatformDialogHelper *QGtk3Theme::createPlatformDialogHelper(DialogType type) c case ColorDialog: return new QGtk3ColorDialogHelper; case FileDialog: + if (!useNativeFileDialog()) + return nullptr; return new QGtk3FileDialogHelper; case FontDialog: return new QGtk3FontDialogHelper; @@ -185,4 +187,17 @@ QPlatformMenuItem* QGtk3Theme::createPlatformMenuItem() const return new QGtk3MenuItem; } +bool QGtk3Theme::useNativeFileDialog() +{ + /* Require GTK3 >= 3.15.5 to avoid running into this bug: + * https://bugzilla.gnome.org/show_bug.cgi?id=725164 + * + * While this bug only occurs when using widget-based file dialogs + * (native GTK3 dialogs are fine) we have to disable platform file + * dialogs entirely since we can't avoid creation of a platform + * dialog helper. + */ + return gtk_check_version(3, 15, 5) == 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.h b/src/plugins/platformthemes/gtk3/qgtk3theme.h index 8f03b84bb6b..54296d2ff11 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3theme.h +++ b/src/plugins/platformthemes/gtk3/qgtk3theme.h @@ -59,6 +59,8 @@ public: QPlatformMenuItem* createPlatformMenuItem() const override; static const char *name; +private: + static bool useNativeFileDialog(); }; QT_END_NAMESPACE diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index df2b637630c..9e8af78a8e4 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3348,13 +3348,12 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai } break; case PE_IndicatorMenuCheckMark: { - if (!(opt->state & State_On)) - break; QColor pc; - if (opt->state & State_Selected) + if (opt->state & State_On) pc = opt->palette.highlightedText().color(); else pc = opt->palette.text().color(); + QCFType checkmarkColor = CGColorCreateGenericRGB(static_cast(pc.redF()), static_cast(pc.greenF()), static_cast(pc.blueF()), @@ -4273,8 +4272,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const int xp = mi->rect.x() + macItemFrame; checkmarkOpt.rect = QRect(xp, mi->rect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh); - checkmarkOpt.state |= State_On; // Always on. Never rendered when off. - checkmarkOpt.state.setFlag(State_Selected, active); + checkmarkOpt.state.setFlag(State_On, active); checkmarkOpt.state.setFlag(State_Enabled, enabled); if (widgetSize == QStyleHelper::SizeMini) checkmarkOpt.state |= State_Mini; diff --git a/src/printsupport/doc/src/qtprintsupport-index.qdoc b/src/printsupport/doc/src/qtprintsupport-index.qdoc index 7ac448f66fb..a8a0f0cb20e 100644 --- a/src/printsupport/doc/src/qtprintsupport-index.qdoc +++ b/src/printsupport/doc/src/qtprintsupport-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -165,6 +165,19 @@ QTextEdit requires a QPrinter rather than a QPainter because it uses information about the configured page dimensions in order to insert page breaks at the most appropriate places in printed documents. + + \section1 Licenses and Trademarks + + The Qt Print Support module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. + + Please note that Adobe\reg places restrictions on the use of its trademarks + (including logos) in conjunction with PDF; e.g. "Adobe PDF". Please refer + to \l{http://www.adobe.com}{www.adobe.com} for guidelines. */ /*! diff --git a/src/sql/doc/src/qtsql.qdoc b/src/sql/doc/src/qtsql.qdoc index 56d714becf6..f0d74739b01 100644 --- a/src/sql/doc/src/qtsql.qdoc +++ b/src/sql/doc/src/qtsql.qdoc @@ -54,12 +54,13 @@ \section1 Licenses and Attributions Qt SQL is available under commercial licenses from \l{The Qt Company}. - In addition, it is available under the + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are \l{GNU Lesser General Public License, version 3}, or the \l{GNU General Public License, version 2}. See \l{Qt Licensing} for further details. - Furthermore Qt SQL potentially contains third party + Furthermore, Qt SQL in Qt \QtVersion may contain third party modules under following permissive licenses: \generatelist{groupsbymodule attributions-qtsql} diff --git a/src/sql/sql.pro b/src/sql/sql.pro index 133bf831c86..821ae1c9b97 100644 --- a/src/sql/sql.pro +++ b/src/sql/sql.pro @@ -2,7 +2,7 @@ TARGET = QtSql QT = core-private DEFINES += QT_NO_USING_NAMESPACE -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x62000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x62000000 QMAKE_DOCS = $$PWD/doc/qtsql.qdocconf diff --git a/src/src.pro b/src/src.pro index 3b93b1a9d8b..1f7c5d99c1c 100644 --- a/src/src.pro +++ b/src/src.pro @@ -210,9 +210,11 @@ qtConfig(gui) { src_plugins.depends += src_gui src_platformsupport src_platformheaders src_testlib.depends += src_gui # if QtGui is enabled, QtTest requires QtGui's headers qtConfig(widgets) { - SUBDIRS += src_tools_uic src_widgets src_printsupport + SUBDIRS += src_tools_uic src_widgets + !android-embedded: SUBDIRS += src_printsupport TOOLS += src_tools_uic - src_plugins.depends += src_widgets src_printsupport + src_plugins.depends += src_widgets + !android-embedded: src_plugins.depends += src_printsupport src_testlib.depends += src_widgets # if QtWidgets is enabled, QtTest requires QtWidgets's headers qtConfig(opengl) { SUBDIRS += src_opengl @@ -224,7 +226,7 @@ SUBDIRS += src_plugins nacl: SUBDIRS -= src_network src_testlib -android: SUBDIRS += src_android src_3rdparty_gradle +android:!android-embedded: SUBDIRS += src_android src_3rdparty_gradle TR_EXCLUDE = \ src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_tools_qlalr \ diff --git a/src/testlib/doc/src/qttest-index.qdoc b/src/testlib/doc/src/qttest-index.qdoc index 7b3e96f72e8..b3c2be7375e 100644 --- a/src/testlib/doc/src/qttest-index.qdoc +++ b/src/testlib/doc/src/qttest-index.qdoc @@ -55,12 +55,13 @@ \section1 Licenses and Attributions Qt Test is available under commercial licenses from \l{The Qt Company}. - In addition, it is available under the + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are \l{GNU Lesser General Public License, version 3}, or the \l{GNU General Public License, version 2}. See \l{Qt Licensing} for further details. - Furthermore Qt Test potentially contains third party + Furthermore, Qt Test in Qt \QtVersion may contain third party modules under following permissive licenses: \generatelist{groupsbymodule attributions-qttestlib} diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 4cda5f34ad4..3d91bdef347 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2830,7 +2830,10 @@ void QFileDialogPrivate::init(const QUrl &directory, const QString &nameFilter, if (!nameFilter.isEmpty()) q->setNameFilter(nameFilter); q->setDirectoryUrl(workingDirectory(directory)); - q->selectFile(initialSelection(directory)); + if (directory.isLocalFile()) + q->selectFile(initialSelection(directory)); + else + q->selectUrl(directory); #ifndef QT_NO_SETTINGS // Try to restore from the FileDialog settings group; if it fails, fall back diff --git a/src/widgets/doc/src/qtwidgets-index.qdoc b/src/widgets/doc/src/qtwidgets-index.qdoc index 7cd1c8d735d..1a23d172ddd 100644 --- a/src/widgets/doc/src/qtwidgets-index.qdoc +++ b/src/widgets/doc/src/qtwidgets-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -128,6 +128,15 @@ interfaces \image graphicsview-items.png + \section1 Licenses + + The Qt Widgets module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. + \section1 Related Information \section2 Tutorials diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 1cc8543fddc..0c847b899e3 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -313,13 +313,15 @@ void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEv QList touchPoints = touchEvent->touchPoints(); for (int i = 0; i < touchPoints.count(); ++i) { QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; + const QSizeF ellipseDiameters = touchPoint.ellipseDiameters(); // the scene will set the item local pos, startPos, lastPos, and rect before delivering to // an item, but for now those functions are returning the view's local coordinates - touchPoint.setSceneRect(d->mapToScene(touchPoint.rect())); + touchPoint.setScenePos(d->mapToScene(touchPoint.pos())); touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos())); touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos())); + touchPoint.setEllipseDiameters(ellipseDiameters); - // screenPos, startScreenPos, lastScreenPos, and screenRect are already set + // screenPos, startScreenPos, and lastScreenPos are already set } touchEvent->setTouchPoints(touchPoints); diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp index 3268fda2fca..117de8edf97 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.cpp +++ b/src/widgets/itemviews/qabstractitemdelegate.cpp @@ -526,7 +526,15 @@ bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *ev if (tryFixup(editor)) emit q->commitData(editor); + // If the application loses focus while editing, then the focus needs to go back + // to the itemview when the editor closes. This ensures that when the application + // is active again it will have the focus on the itemview as expected. + const bool manuallyFixFocus = (event->type() == QEvent::FocusOut) && !editor->hasFocus() && + editor->parentWidget() && + (static_cast(event)->reason() == Qt::ActiveWindowFocusReason); emit q->closeEditor(editor, QAbstractItemDelegate::NoHint); + if (manuallyFixFocus) + editor->parentWidget()->setFocus(); } #ifndef QT_NO_SHORTCUT } else if (event->type() == QEvent::ShortcutOverride) { diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 585cfddff5d..c90a61d4ff1 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -351,7 +351,7 @@ void QHeaderView::setModel(QAbstractItemModel *model) if (model == this->model()) return; Q_D(QHeaderView); - d->persistentHiddenSections.clear(); + d->layoutChangePersistentSections.clear(); if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) { if (d->orientation == Qt::Horizontal) { QObject::disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), @@ -2160,14 +2160,28 @@ void QHeaderViewPrivate::_q_sectionsAboutToBeChanged() || model->columnCount(root) == 0) return; - if (hiddenSectionSize.count() == 0) - return; + layoutChangePersistentSections.clear(); + layoutChangePersistentSections.reserve(std::min(10, sectionItems.count())); + // after layoutChanged another section can be last stretched section + if (stretchLastSection) { + const int visual = visualIndex(lastSectionLogicalIdx); + sectionItems[visual].size = lastSectionSize; + } + for (int i = 0; i < sectionItems.size(); ++i) { + const auto &s = sectionItems.at(i); + // only add if the section is not default and not visually moved + if (s.size == defaultSectionSize && !s.isHidden && s.resizeMode == globalResizeMode) + continue; - for (int i = 0; i < sectionItems.count(); ++i) - if (isVisualIndexHidden(i)) // ### note that we are using column or row 0 - persistentHiddenSections.append(orientation == Qt::Horizontal - ? model->index(0, logicalIndex(i), root) - : model->index(logicalIndex(i), 0, root)); + // ### note that we are using column or row 0 + layoutChangePersistentSections.append({orientation == Qt::Horizontal + ? model->index(0, logicalIndex(i), root) + : model->index(logicalIndex(i), 0, root), + s}); + + if (layoutChangePersistentSections.size() > 1000) + break; + } } void QHeaderViewPrivate::_q_sectionsChanged() @@ -2175,25 +2189,57 @@ void QHeaderViewPrivate::_q_sectionsChanged() Q_Q(QHeaderView); viewport->update(); - const auto hiddenSections = persistentHiddenSections; - persistentHiddenSections.clear(); + const auto oldPersistentSections = layoutChangePersistentSections; + layoutChangePersistentSections.clear(); - clear(); - q->initializeSections(); - invalidateCachedSizeHint(); - - if (modelIsEmpty()) { + const int newCount = modelSectionCount(); + const int oldCount = sectionItems.size(); + if (newCount == 0) { + clear(); + if (oldCount != 0) + emit q->sectionCountChanged(oldCount, 0); return; } - for (const auto &index : hiddenSections) { - if (index.isValid()) { - const int logical = (orientation == Qt::Horizontal - ? index.column() - : index.row()); - q->setSectionHidden(logical, true); + // adjust section size + if (newCount != oldCount) { + const int min = qBound(0, oldCount, newCount - 1); + q->initializeSections(min, newCount - 1); + } + // reset sections + sectionItems.fill(SectionItem(defaultSectionSize, globalResizeMode), newCount); + + // all hidden sections are in oldPersistentSections + hiddenSectionSize.clear(); + + for (const auto &item : oldPersistentSections) { + const auto &index = item.index; + if (!index.isValid()) + continue; + + const int newLogicalIndex = (orientation == Qt::Horizontal + ? index.column() + : index.row()); + // the new visualIndices are already adjusted / reset by initializeSections() + const int newVisualIndex = visualIndex(newLogicalIndex); + auto &newSection = sectionItems[newVisualIndex]; + newSection = item.section; + + if (newSection.isHidden) { + // otherwise setSectionHidden will return without doing anything + newSection.isHidden = false; + q->setSectionHidden(newLogicalIndex, true); } } + + recalcSectionStartPos(); + length = headerLength(); + + if (stretchLastSection) { + // force rebuild of stretched section later on + lastSectionLogicalIdx = -1; + maybeRestorePrevLastSectionAndStretchLast(); + } } /*! diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h index d8442746184..24dc3bf0758 100644 --- a/src/widgets/itemviews/qheaderview_p.h +++ b/src/widgets/itemviews/qheaderview_p.h @@ -231,10 +231,6 @@ public: : model->rowCount(root)); } - inline bool modelIsEmpty() const { - return (model->rowCount(root) == 0 || model->columnCount(root) == 0); - } - inline void doDelayedResizeSections() { if (!delayedResize.isActive()) delayedResize.start(0, q_func()); @@ -300,7 +296,6 @@ public: QLabel *sectionIndicator; #endif QHeaderView::ResizeMode globalResizeMode; - QList persistentHiddenSections; mutable bool sectionStartposRecalc; int resizeContentsPrecision; // header sections @@ -331,6 +326,11 @@ public: }; QVector sectionItems; + struct LayoutChangeItem { + QPersistentModelIndex index; + SectionItem section; + }; + QVector layoutChangePersistentSections; void createSectionItems(int start, int end, int size, QHeaderView::ResizeMode mode); void removeSectionsFromSectionItems(int start, int end); @@ -384,6 +384,7 @@ public: }; Q_DECLARE_TYPEINFO(QHeaderViewPrivate::SectionItem, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(QHeaderViewPrivate::LayoutChangeItem, Q_MOVABLE_TYPE); QT_END_NAMESPACE diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 9b7797993cc..ebeefad682e 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -987,7 +987,7 @@ void QTreeView::setTreePosition(int index) { Q_D(QTreeView); d->treePosition = index; - update(); + d->viewport->update(); } /*! diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 967b0b8ddea..8c8217bb75f 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -1332,9 +1332,8 @@ bool QAction::isShortcutVisibleInContextMenu() const { Q_D(const QAction); if (d->shortcutVisibleInContextMenu == -1) { - if (QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus)) - return false; - return qApp->styleHints()->showShortcutsInContextMenus(); + return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) + && QGuiApplication::styleHints()->showShortcutsInContextMenus(); } return d->shortcutVisibleInContextMenu; } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 9e4910ebd05..b855e32f2da 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2847,7 +2847,7 @@ void QApplication::setStartDragDistance(int l) and the current position (e.g. in the mouse move event) is \c currentPos, you can find out if a drag should be started with code like this: - \snippet code/src_gui_kernel_qapplication.cpp 6 + \snippet code/src_gui_kernel_qapplication.cpp 7 Qt uses this value internally, e.g. in QFileDialog. diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index bc5062e942e..74f2dc0c419 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1482,7 +1482,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) { win->create(); // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing. - win->handle()->setFrameStrutEventsEnabled(true); + if (QPlatformWindow *platformWindow = win->handle()) + platformWindow->setFrameStrutEventsEnabled(true); } data.window_flags = win->flags(); diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 26f651906ae..6873ca876e6 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -763,7 +763,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect); QColor checkMarkColor = option->palette.text().color().darker(120); - const int checkMarkPadding = 1 + rect.width() * 0.2; // at least one pixel padding + const qreal checkMarkPadding = 1 + rect.width() * 0.13; // at least one pixel padding if (checkbox->state & State_NoChange) { gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()); @@ -776,21 +776,22 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->setBrush(gradient); painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); - } else if (checkbox->state & (State_On)) { - qreal penWidth = QStyleHelper::dpiScaled(1.8); - penWidth = qMax(penWidth , 0.18 * rect.height()); - penWidth = qMin(penWidth , 0.30 * rect.height()); + } else if (checkbox->state & State_On) { + qreal penWidth = QStyleHelper::dpiScaled(1.5); + penWidth = qMax(penWidth , 0.13 * rect.height()); + penWidth = qMin(penWidth , 0.20 * rect.height()); QPen checkPen = QPen(checkMarkColor, penWidth); checkMarkColor.setAlpha(210); - painter->translate(-0.8, 0.5); + painter->translate(dpiScaled(-0.8), dpiScaled(0.5)); painter->setPen(checkPen); painter->setBrush(Qt::NoBrush); // Draw checkmark QPainterPath path; - path.moveTo(1.33 * checkMarkPadding, rect.height() / 2.0); - path.lineTo(rect.width() / 2.0, rect.height() - checkMarkPadding); - path.lineTo(rect.width() - checkMarkPadding * 0.92, checkMarkPadding); + const qreal rectHeight = rect.height(); // assuming height equals width + path.moveTo(checkMarkPadding + rectHeight * 0.11, rectHeight * 0.47); + path.lineTo(rectHeight * 0.5, rectHeight - checkMarkPadding); + path.lineTo(rectHeight - checkMarkPadding, checkMarkPadding); painter->drawPath(path.translated(rect.topLeft())); } } @@ -1561,8 +1562,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio bool ignoreCheckMark = false; const int checkColHOffset = windowsItemHMargin + windowsItemFrame - 1; - int checkcol = qMax(menuItem->rect.height() * 0.7, - qMax(menuItem->maxIconWidth * 1.0, dpiScaled(17))); // icon checkbox's highlihgt column width + int checkcol = qMax(menuItem->rect.height() * 0.79, + qMax(menuItem->maxIconWidth * 1.0, dpiScaled(21))); // icon checkbox's highlihgt column width if ( #if QT_CONFIG(combobox) qobject_cast(widget) || @@ -1571,10 +1572,12 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate if (!ignoreCheckMark) { - // Check - const int boxMargin = dpiScaled(4); - const int boxWidth = checkcol - 2 * boxMargin; - QRect checkRect(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth); + // Check, using qreal and QRectF to avoid error accumulation + const qreal boxMargin = dpiScaled(3.5); + const qreal boxWidth = checkcol - 2 * boxMargin; + QRectF checkRectF(option->rect.left() + boxMargin + checkColHOffset, option->rect.center().y() - boxWidth/2 + 1, boxWidth, boxWidth); + QRect checkRect = checkRectF.toRect(); + checkRect.setWidth(checkRect.height()); // avoid .toRect() round error results in non-perfect square checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); if (checkable) { if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 373699a7aa1..8679d96eda9 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -411,14 +411,6 @@ QWindow *styleObjectWindow(QObject *so) return 0; } -void setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) -{ - QWidget *wadget = const_cast(widget); - wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge); - wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall); - wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini); -} - WidgetSizePolicy widgetSizePolicy(const QWidget *widget, const QStyleOption *opt) { while (widget) { diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h index bd263cea7b0..260860bf4d6 100644 --- a/src/widgets/styles/qstylehelper_p.h +++ b/src/widgets/styles/qstylehelper_p.h @@ -94,7 +94,6 @@ namespace QStyleHelper enum WidgetSizePolicy { SizeLarge = 0, SizeSmall = 1, SizeMini = 2, SizeDefault = -1 }; - void setWidgetSizePolicy(const QWidget *w, WidgetSizePolicy policy); Q_WIDGETS_EXPORT WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0); } diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 9ce1a04d86d..e12aeb900bc 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3968,10 +3968,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q x += reverse ? -chunkWidth : chunkWidth; --chunkCount; }; - } else { + } else if (chunkWidth > 0) { + const int chunkCount = ceil(qreal(fillWidth)/chunkWidth); int x = reverse ? r.left() + r.width() - chunkWidth : r.x(); - for (int i = 0; i < ceil(qreal(fillWidth)/chunkWidth); ++i) { + for (int i = 0; i < chunkCount; ++i) { r.setRect(x, rect.y(), chunkWidth, rect.height()); r = m.mapRect(QRectF(r)).toRect(); subRule.drawRule(p, r); diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 447c7b2aeb7..86c824afdbd 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -111,9 +111,7 @@ static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon) \li All X11 desktop environments that implement the D-Bus \l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem} specification, including recent versions of KDE and Unity. - \li All supported versions of \macos. Note that the Growl - notification system must be installed for - QSystemTrayIcon::showMessage() to display messages on \macos prior to 10.8 (Mountain Lion). + \li All supported versions of \macos. \endlist To check whether a system tray is present on the user's desktop, @@ -420,9 +418,6 @@ bool QSystemTrayIcon::supportsMessages() On Windows, the \a millisecondsTimeoutHint is usually ignored by the system when the application has focus. - On \macos, the Growl notification system must be installed for this function to - display messages. - Has been turned into a slot in Qt 5.2. \sa show(), supportsMessages() diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro index 27d7fe98746..e028a691c81 100644 --- a/src/widgets/widgets.pro +++ b/src/widgets/widgets.pro @@ -4,7 +4,7 @@ MODULE_CONFIG = uic CONFIG += $$MODULE_CONFIG DEFINES += QT_NO_USING_NAMESPACE -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x65000000 QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 7d4498af5b8..e70d096e049 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -2582,7 +2583,8 @@ bool QComboBoxPrivate::showNativePopup() else if (q->testAttribute(Qt::WA_MacMiniSize)) offset = QPoint(-2, 6); - m_platformMenu->showPopup(tlw, QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize()), currentItem); + const QRect targetRect = QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize()); + m_platformMenu->showPopup(tlw, QHighDpi::toNativePixels(targetRect, tlw), currentItem); #ifdef Q_OS_OSX // The Cocoa popup will swallow any mouse release event. diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index e3b348f0efc..bdeef7cdf77 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -80,9 +80,8 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include "qkeysequence.h" -#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ - ? false \ - : qApp->styleHints()->showShortcutsInContextMenus()) \ +#define ACCEL_KEY(k) ((!QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus) \ + && QGuiApplication::styleHints()->showShortcutsInContextMenus()) \ && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) #else diff --git a/src/widgets/widgets/qtoolbarextension.cpp b/src/widgets/widgets/qtoolbarextension.cpp index 47cf16e0cc7..bbe7eddaa49 100644 --- a/src/widgets/widgets/qtoolbarextension.cpp +++ b/src/widgets/widgets/qtoolbarextension.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qtoolbarextension_p.h" -#include +#include #include #include #include @@ -47,10 +47,11 @@ QT_BEGIN_NAMESPACE QToolBarExtension::QToolBarExtension(QWidget *parent) : QToolButton(parent) + , m_orientation(Qt::Horizontal) { setObjectName(QLatin1String("qt_toolbar_ext_button")); setAutoRaise(true); - setOrientation(Qt::Horizontal); + setOrientation(m_orientation); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setCheckable(true); } @@ -63,7 +64,8 @@ void QToolBarExtension::setOrientation(Qt::Orientation o) setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton, &opt)); } else { setIcon(style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton, &opt)); - } + } + m_orientation = o; } void QToolBarExtension::paintEvent(QPaintEvent *) @@ -83,6 +85,18 @@ QSize QToolBarExtension::sizeHint() const return QSize(ext, ext); } +bool QToolBarExtension::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::LayoutDirectionChange: + setOrientation(m_orientation); + break; + default: + break; + } + return QToolButton::event(event); +} + QT_END_NAMESPACE #include "moc_qtoolbarextension_p.cpp" diff --git a/src/widgets/widgets/qtoolbarextension_p.h b/src/widgets/widgets/qtoolbarextension_p.h index a388f1e40f0..146e0e58c14 100644 --- a/src/widgets/widgets/qtoolbarextension_p.h +++ b/src/widgets/widgets/qtoolbarextension_p.h @@ -69,6 +69,12 @@ public: public Q_SLOTS: void setOrientation(Qt::Orientation o); + +protected: + bool event(QEvent *e) override; + +private: + Qt::Orientation m_orientation; }; QT_END_NAMESPACE diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 93158dcdbac..d3203e180bb 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -93,9 +93,8 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include -#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ - ? false \ - : qApp->styleHints()->showShortcutsInContextMenus()) \ +#define ACCEL_KEY(k) ((!QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) \ + && QGuiApplication::styleHints()->showShortcutsInContextMenus()) \ && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) diff --git a/src/xml/doc/src/qtxml-index.qdoc b/src/xml/doc/src/qtxml-index.qdoc index eb35903756c..91f2515d606 100644 --- a/src/xml/doc/src/qtxml-index.qdoc +++ b/src/xml/doc/src/qtxml-index.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -45,4 +45,13 @@ The \l{Qt XML C++ Classes} page gives an overview over the available classes in this module. + + \section1 Licenses + + The Qt XML module is available under commercial licenses from \l{The Qt Company}. + In addition, it is available under free software licenses. Since Qt 5.4, + these free software licenses are + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. */ diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index b781176e139..168e8c3cb44 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -1270,18 +1270,8 @@ void QXmlInputSource::fetchData() } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) { rawData.resize(BufferSize); qint64 size = device->read(rawData.data(), BufferSize); - - if (size != -1) { - // We don't want to give fromRawData() less than four bytes if we can avoid it. - while (size < 4) { - if (!device->waitForReadyRead(-1)) - break; - int ret = device->read(rawData.data() + size, BufferSize - size); - if (ret <= 0) - break; - size += ret; - } - } + if (size == 0 && device->waitForReadyRead(-1)) + size = device->read(rawData.data(), BufferSize); rawData.resize(qMax(qint64(0), size)); } diff --git a/src/xml/xml.pro b/src/xml/xml.pro index cf9feda9bc9..31d742d6ea5 100644 --- a/src/xml/xml.pro +++ b/src/xml/xml.pro @@ -3,7 +3,7 @@ QT = core-private DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH -win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x61000000 +msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x61000000 QMAKE_DOCS = $$PWD/doc/qtxml.qdocconf diff --git a/tests/auto/concurrent/qtconcurrentmap/BLACKLIST b/tests/auto/concurrent/qtconcurrentmap/BLACKLIST deleted file mode 100644 index 7cd8961f6f1..00000000000 --- a/tests/auto/concurrent/qtconcurrentmap/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[qFutureAssignmentLeak] -ci opensuse diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp index 2ff1b9410c6..b864b065e6b 100644 --- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp +++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp @@ -2402,9 +2402,12 @@ void tst_QtConcurrentMap::qFutureAssignmentLeak() future.waitForFinished(); } - QCOMPARE(currentInstanceCount.load(), 1000); + // Use QTRY_COMPARE because QtConcurrent::ThreadEngine::asynchronousFinish() + // deletes its internals after signaling finished, so it might still be holding + // on to copies of InstanceCounter for a short while. + QTRY_COMPARE(currentInstanceCount.load(), 1000); future = QFuture(); - QCOMPARE(currentInstanceCount.load(), 0); + QTRY_COMPARE(currentInstanceCount.load(), 0); } inline void increment(int &num) diff --git a/tests/auto/corelib/io/qdir/qdir.pro b/tests/auto/corelib/io/qdir/qdir.pro index 48709223122..2252e71cd8a 100644 --- a/tests/auto/corelib/io/qdir/qdir.pro +++ b/tests/auto/corelib/io/qdir/qdir.pro @@ -8,6 +8,6 @@ TESTDATA += testdir testData searchdir resources entrylist types tst_qdir.cpp contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA -android { +android:!android-embedded { RESOURCES += android_testdata.qrc } diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 8dbac281831..9d47bb28845 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -228,13 +228,13 @@ private: Q_DECLARE_METATYPE(tst_QDir::UncHandling) tst_QDir::tst_QDir() -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) : m_dataPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) #elif !defined(BUILTIN_TESTDATA) : m_dataPath(QFileInfo(QFINDTESTDATA("testData")).absolutePath()) #endif { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString resourceSourcePath = QStringLiteral(":/android_testdata/"); QDirIterator it(resourceSourcePath, QDirIterator::Subdirectories); while (it.hasNext()) { @@ -2186,7 +2186,7 @@ void tst_QDir::equalityOperator_data() QString pathinroot(QDir::rootPath() + QLatin1String("assets/..")); #elif defined (Q_OS_WIN) QString pathinroot("c:/windows/.."); -#elif defined(Q_OS_ANDROID) +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString pathinroot("/system/.."); #elif defined(Q_OS_HAIKU) QString pathinroot("/boot/.."); diff --git a/tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp b/tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp index 6450e9af7b3..a55989aacd3 100644 --- a/tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp +++ b/tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp @@ -118,7 +118,7 @@ private: void tst_QDirIterator::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString testdata_dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); QString resourceSourcePath = QStringLiteral(":/"); QDirIterator it(resourceSourcePath, QDirIterator::Subdirectories); diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index bfb14da8b81..cd13e2bd19f 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -1684,6 +1684,15 @@ static bool fOpen(const QByteArray &fileName, const char *mode, FILE **file) void tst_QFile::largeUncFileSupport() { + // Currently there is a single network test server that is used by all VMs running tests in + // the CI. This test accesses a file shared with Samba on that server. Unfortunately many + // clients accessing the file at the same time is a sharing violation. This test already + // attempted to deal with the problem with retries, but that has led to the test timing out, + // not eventually succeeding. Due to the timeouts blacklisting the test wouldn't help. + // See https://bugreports.qt.io/browse/QTQAINFRA-1727 which will be resolved by the new + // test server architecture where the server is no longer shared. + QSKIP("Multiple instances of running this test at the same time fail due to QTQAINFRA-1727"); + qint64 size = Q_INT64_C(8589934592); qint64 dataOffset = Q_INT64_C(8589914592); QByteArray knownData("LargeFile content at offset 8589914592"); diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 02b70c317e0..87d5675e7af 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -1186,7 +1186,7 @@ void tst_QFileInfo::fileTimes() QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed QVERIFY(readTime.isValid()); -#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID) +#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) noAccessTime = true; #elif defined(Q_OS_WIN) //In Vista the last-access timestamp is not updated when the file is accessed/touched (by default). @@ -1623,7 +1623,7 @@ void tst_QFileInfo::isWritable() void tst_QFileInfo::isExecutable() { QString appPath = QCoreApplication::applicationDirPath(); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) appPath += "/libtst_qfileinfo.so"; #else appPath += "/tst_qfileinfo"; diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index 154c7ec5bfa..b05a876a52f 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -89,7 +89,7 @@ tst_QFileSystemWatcher::tst_QFileSystemWatcher() m_tempDirPattern += QStringLiteral("tst_qfilesystemwatcherXXXXXX"); #endif // QT_NO_FILESYSTEMWATCHER -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QDir::setCurrent(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); #endif } diff --git a/tests/auto/corelib/io/qiodevice/qiodevice.pro b/tests/auto/corelib/io/qiodevice/qiodevice.pro index 945022a289c..1c978953d67 100644 --- a/tests/auto/corelib/io/qiodevice/qiodevice.pro +++ b/tests/auto/corelib/io/qiodevice/qiodevice.pro @@ -6,7 +6,7 @@ SOURCES = tst_qiodevice.cpp TESTDATA += tst_qiodevice.cpp MOC_DIR=tmp -android { +android:!android-embedded { RESOURCES += \ android_testdata.qrc } diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp index a485788ec2c..4923baa0cae 100644 --- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp +++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp @@ -70,7 +70,7 @@ private: void tst_QIODevice::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QVERIFY(QFileInfo(QStringLiteral("./tst_qiodevice.cpp")).exists() || QFile::copy(QStringLiteral(":/tst_qiodevice.cpp"), QStringLiteral("./tst_qiodevice.cpp"))); #endif diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp index fc7ab70d419..eeeb3bc6e26 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -78,7 +78,7 @@ public: void tst_QLockFile::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("This test requires deploying and running external console applications"); #elif !QT_CONFIG(process) QSKIP("This test requires QProcess support"); diff --git a/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro b/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro index 287ab309936..ac976e9b9cc 100644 --- a/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro +++ b/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro @@ -7,7 +7,7 @@ QT = core core-private testlib SOURCES += tst_qloggingregistry.cpp TESTDATA += qtlogging.ini -android { +android:!android-embedded { RESOURCES += \ android_testdata.qrc } diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro index 658201e03a7..f937d23fe2c 100644 --- a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro +++ b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro @@ -18,6 +18,6 @@ TESTDATA += \ testqrc/* GENERATED_TESTDATA = $${runtime_resource.target} -android { +android:!android-embedded { RESOURCES += android_testdata.qrc } diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp index 7fdd00876f1..ab1866fb2da 100644 --- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp +++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp @@ -36,7 +36,7 @@ class tst_QResourceEngine: public QObject public: tst_QResourceEngine() -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) : m_runtimeResourceRcc(QFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/runtime_resource.rcc")).absoluteFilePath()) #else : m_runtimeResourceRcc(QFINDTESTDATA("runtime_resource.rcc")) @@ -64,7 +64,7 @@ private: void tst_QResourceEngine::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString sourcePath(QStringLiteral(":/android_testdata/")); QString dataPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); @@ -121,7 +121,7 @@ void tst_QResourceEngine::checkStructure_data() << QLatin1String("test") << QLatin1String("withoutslashes"); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) rootContents.insert(1, QLatin1String("android_testdata")); #endif diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro index 7da73a549a1..5b4cc8a6916 100644 --- a/tests/auto/corelib/io/qsettings/qsettings.pro +++ b/tests/auto/corelib/io/qsettings/qsettings.pro @@ -5,5 +5,5 @@ SOURCES = tst_qsettings.cpp RESOURCES += qsettings.qrc INCLUDEPATH += $$PWD/../../kernel/qmetatype -win32-msvc*:LIBS += advapi32.lib +msvc: LIBS += advapi32.lib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp index 76462be376d..6dbb8ddd0d4 100644 --- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp +++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp @@ -290,7 +290,7 @@ void tst_QTemporaryDir::nonWritableCurrentDir() { #ifdef Q_OS_UNIX -# if defined(Q_OS_ANDROID) +# if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) const char nonWritableDir[] = "/data"; # else const char nonWritableDir[] = "/home"; diff --git a/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.pro b/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.pro index e17cb05cd8b..11a5d58dc8f 100644 --- a/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.pro +++ b/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.pro @@ -5,6 +5,6 @@ SOURCES = tst_qtemporaryfile.cpp TESTDATA += tst_qtemporaryfile.cpp RESOURCES += qtemporaryfile.qrc -android { +android:!android-embedded { RESOURCES += android_testdata.qrc } diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 2d87c2193b8..dbc3d68e932 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -102,7 +102,7 @@ void tst_QTemporaryFile::initTestCase() QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); QCoreApplication::setApplicationName("tst_qtemporaryfile"); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString sourceDir(":/android_testdata/"); QDirIterator it(sourceDir, QDirIterator::Subdirectories); while (it.hasNext()) { @@ -351,7 +351,7 @@ void tst_QTemporaryFile::nonWritableCurrentDir() ChdirOnReturn cor(QDir::currentPath()); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QDir::setCurrent("/data"); #else QDir::setCurrent("/home"); @@ -571,7 +571,7 @@ void tst_QTemporaryFile::renameFdLeak() { #ifdef Q_OS_UNIX -# if defined(Q_OS_ANDROID) +# if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) ChdirOnReturn cor(QDir::currentPath()); QDir::setCurrent(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); # endif @@ -780,7 +780,7 @@ void tst_QTemporaryFile::createNativeFile_data() QTest::addColumn("valid"); QTest::addColumn("content"); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) const QString nativeFilePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/resources/test.txt"); #else const QString nativeFilePath = QFINDTESTDATA("resources/test.txt"); diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro index b5f1d0fe00e..ad148ccc7f2 100644 --- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro +++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro @@ -6,7 +6,7 @@ SOURCES = tst_qmetatype.cpp TESTDATA=./typeFlags.bin DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -win32-msvc*|winrt { +msvc|winrt { # Prevents "fatal error C1128: number of sections exceeded object file format limit". QMAKE_CXXFLAGS += /bigobj # Reduce compile time diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro index e6732789208..d8924c2d5f2 100644 --- a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro +++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro @@ -4,6 +4,6 @@ QT = core testlib SOURCES = tst_qtranslator.cpp RESOURCES += qtranslator.qrc -android: RESOURCES += android_testdata.qrc +android:!android-embedded: RESOURCES += android_testdata.qrc else: TESTDATA += dependencies_la.qm hellotr_la.qm msgfmt_from_po.qm diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp index 5bfe133966e..451f96339ed 100644 --- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp +++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp @@ -65,7 +65,7 @@ tst_QTranslator::tst_QTranslator() void tst_QTranslator::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString sourceDir(":/android_testdata/"); QDirIterator it(sourceDir, QDirIterator::Subdirectories); while (it.hasNext()) { diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp index 15a39b62c0f..76efa008f7c 100644 --- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp +++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp @@ -29,8 +29,11 @@ #include #include #include +#include +#include #include +#include #include class tst_QWinEventNotifier : public QObject @@ -44,6 +47,8 @@ private slots: void simple_data(); void simple(); void manyNotifiers(); + void disableNotifiersInActivatedSlot_data(); + void disableNotifiersInActivatedSlot(); private: HANDLE simpleHEvent; @@ -109,9 +114,6 @@ public: this, &EventWithNotifier::onNotifierActivated); notifier.setHandle(CreateEvent(0, TRUE, FALSE, 0)); notifier.setEnabled(true); - - static int nextIndex = 0; - idx = nextIndex++; } ~EventWithNotifier() @@ -122,6 +124,7 @@ public: HANDLE eventHandle() const { return notifier.handle(); } int numberOfTimesActivated() const { return activatedCount; } + void setEnabled(bool b) { notifier.setEnabled(b); } signals: void activated(); @@ -137,7 +140,6 @@ public slots: private: QWinEventNotifier notifier; int activatedCount = 0; - int idx = 0; }; void tst_QWinEventNotifier::manyNotifiers() @@ -184,6 +186,60 @@ void tst_QWinEventNotifier::manyNotifiers() })); } +using Indices = QVector; + +void tst_QWinEventNotifier::disableNotifiersInActivatedSlot_data() +{ + QTest::addColumn("count"); + QTest::addColumn("notifiersToSignal"); + QTest::addColumn("notifiersToDisable"); + QTest::addColumn("deleteNotifiers"); + QTest::newRow("disable_signaled") << 3 << Indices{1} << Indices{1} << false; + QTest::newRow("disable_signaled2") << 3 << Indices{1, 2} << Indices{1} << false; + QTest::newRow("disable_before_signaled") << 3 << Indices{1} << Indices{0, 1} << false; + QTest::newRow("disable_after_signaled") << 3 << Indices{1} << Indices{1, 2} << false; + QTest::newRow("delete_signaled") << 3 << Indices{1} << Indices{1} << true; + QTest::newRow("delete_before_signaled1") << 3 << Indices{1} << Indices{0} << true; + QTest::newRow("delete_before_signaled2") << 3 << Indices{1} << Indices{0, 1} << true; + QTest::newRow("delete_before_signaled3") << 4 << Indices{3, 1} << Indices{0, 1} << true; + QTest::newRow("delete_after_signaled1") << 3 << Indices{1} << Indices{1, 2} << true; + QTest::newRow("delete_after_signaled2") << 4 << Indices{1, 3} << Indices{1, 2} << true; + QTest::newRow("delete_after_signaled3") << 5 << Indices{1} << Indices{1, 4} << true; +} + +void tst_QWinEventNotifier::disableNotifiersInActivatedSlot() +{ + QFETCH(int, count); + QFETCH(Indices, notifiersToSignal); + QFETCH(Indices, notifiersToDisable); + QFETCH(bool, deleteNotifiers); + + QVarLengthArray, 10> events(count); + for (int i = 0; i < count; ++i) + events[i].reset(new EventWithNotifier); + + auto isActivatedOrNull = [&events](int i) { + return !events.at(i) || events.at(i)->numberOfTimesActivated() > 0; + }; + + for (auto &e : events) { + connect(e.get(), &EventWithNotifier::activated, [&]() { + for (int i : notifiersToDisable) { + if (deleteNotifiers) + events[i].reset(); + else + events.at(i)->setEnabled(false); + } + if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), isActivatedOrNull)) + QTimer::singleShot(0, &QTestEventLoop::instance(), SLOT(exitLoop())); + }); + } + for (int i : notifiersToSignal) + SetEvent(events.at(i)->eventHandle()); + QTestEventLoop::instance().enterLoop(30); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + QTEST_MAIN(tst_QWinEventNotifier) #include "tst_qwineventnotifier.moc" diff --git a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro index 291b3eb6110..25f8b889a0a 100644 --- a/tests/auto/corelib/serialization/qdatastream/qdatastream.pro +++ b/tests/auto/corelib/serialization/qdatastream/qdatastream.pro @@ -5,7 +5,7 @@ SOURCES = tst_qdatastream.cpp TESTDATA += datastream.q42 -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index b80c6ae8111..17763f31f95 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -6684,10 +6684,13 @@ void tst_QStateMachine::dontProcessSlotsWhenMachineIsNotRunning() machine.addState(&initialState); machine.addState(&finalState); machine.setInitialState(&initialState); - machine.start(); connect(&machine, &QStateMachine::finished, &emitter.thread, &QThread::quit); - QSignalSpy signalSpy(&machine, &QStateMachine::finished); - QTRY_COMPARE_WITH_TIMEOUT(signalSpy.count(), 1, 100); + machine.start(); + QSignalSpy emittedSpy(&emitter, &SignalEmitter::signalWithNoArg); + QSignalSpy finishedSpy(&machine, &QStateMachine::finished); + QTRY_COMPARE_WITH_TIMEOUT(emittedSpy.count(), 2, 100); + QTRY_COMPARE(finishedSpy.count(), 1); + QTRY_VERIFY(emitter.thread.isFinished()); } QTEST_MAIN(tst_QStateMachine) diff --git a/tests/auto/corelib/tools/qbytearray/qbytearray.pro b/tests/auto/corelib/tools/qbytearray/qbytearray.pro index f59cdf3524c..c2101b06119 100644 --- a/tests/auto/corelib/tools/qbytearray/qbytearray.pro +++ b/tests/auto/corelib/tools/qbytearray/qbytearray.pro @@ -10,7 +10,7 @@ mac { LIBS += -framework Foundation } -android { +android:!android-embedded { RESOURCES += \ android_testdata.qrc } diff --git a/tests/auto/corelib/tools/qchar/qchar.pro b/tests/auto/corelib/tools/qchar/qchar.pro index 012e591298c..70c12229887 100644 --- a/tests/auto/corelib/tools/qchar/qchar.pro +++ b/tests/auto/corelib/tools/qchar/qchar.pro @@ -5,7 +5,7 @@ SOURCES = tst_qchar.cpp TESTDATA += data/NormalizationTest.txt -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 35a9af05f60..480e723f441 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -187,7 +187,7 @@ void tst_QCollator::compare() QCollator collator(locale); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) if (collator.locale() != QLocale()) QSKIP("Posix implementation of collation only supports default locale"); #endif diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index 10398f1a99e..527e07593c0 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -512,7 +512,7 @@ void tst_QCommandLineParser::testVersionOption() #if !QT_CONFIG(process) QSKIP("This test requires QProcess support"); #else -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Deploying executable applications to file system on Android not supported."); #endif @@ -578,7 +578,7 @@ void tst_QCommandLineParser::testHelpOption() #if !QT_CONFIG(process) QSKIP("This test requires QProcess support"); #else -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Deploying executable applications to file system on Android not supported."); #endif @@ -625,7 +625,7 @@ void tst_QCommandLineParser::testQuoteEscaping() { #if !QT_CONFIG(process) QSKIP("This test requires QProcess support"); -#elif defined(Q_OS_ANDROID) +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Deploying executable applications to file system on Android not supported."); #else QCoreApplication app(empty_argc, empty_argv); diff --git a/tests/auto/corelib/tools/qcryptographichash/qcryptographichash.pro b/tests/auto/corelib/tools/qcryptographichash/qcryptographichash.pro index 7fead5938be..8d3957a5249 100644 --- a/tests/auto/corelib/tools/qcryptographichash/qcryptographichash.pro +++ b/tests/auto/corelib/tools/qcryptographichash/qcryptographichash.pro @@ -5,7 +5,7 @@ SOURCES = tst_qcryptographichash.cpp TESTDATA += data/* -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 393e1b68aaa..919f9cb718a 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2267,6 +2267,7 @@ void tst_QDateTime::fromStringDateFormat_data() QTest::newRow("ISO short") << QString::fromLatin1("2017-07-01T") << Qt::ISODate << invalidDateTime(); QTest::newRow("ISO zoned date") << QString::fromLatin1("2017-07-01Z") << Qt::ISODate << invalidDateTime(); QTest::newRow("ISO zoned empty time") << QString::fromLatin1("2017-07-01TZ") << Qt::ISODate << invalidDateTime(); + QTest::newRow("ISO mis-punctuated") << QString::fromLatin1("2018/01/30 ") << Qt::ISODate << invalidDateTime(); // Test Qt::RFC2822Date format (RFC 2822). QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp index 62dd33131bc..3e1668522ea 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #ifndef DEFAULT_MAKESPEC # error DEFAULT_MAKESPEC not defined @@ -69,6 +70,16 @@ static QString makespec() QT_BEGIN_NAMESPACE namespace QTest { #if QT_CONFIG(process) + static void ensureStopped(QProcess &process) + { + if (process.state() == QProcess::Running) { + process.terminate(); + QThread::msleep(20); + if (process.state() == QProcess::Running) + process.kill(); + } + } + class QExternalProcess: public QProcess { protected: @@ -594,7 +605,7 @@ namespace QTest { ok = qmake.waitForFinished(); exitCode = qmake.exitCode(); if (!ok) - qmake.terminate(); + QTest::ensureStopped(qmake); std_out += qmake.readAllStandardOutput(); std_err += qmake.readAllStandardError(); @@ -661,7 +672,7 @@ namespace QTest { make.closeWriteChannel(); bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : 60000); if (!ok) - make.terminate(); + QTest::ensureStopped(make); exitCode = make.exitCode(); std_out += make.readAllStandardOutput(); std_err += make.readAllStandardError(); diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro b/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro index 8e0216b1759..3c9f03842d1 100644 --- a/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro +++ b/tests/auto/corelib/tools/qtextboundaryfinder/qtextboundaryfinder.pro @@ -5,7 +5,7 @@ SOURCES = tst_qtextboundaryfinder.cpp TESTDATA += data -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp index 20cd8caad34..80f22ad8674 100644 --- a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp +++ b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -1083,6 +1083,7 @@ void tst_QDBusAbstractAdaptor::methodCallsPeer_data() void tst_QDBusAbstractAdaptor::methodCallsPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); if (QSysInfo::productType().compare("opensuse", Qt::CaseInsensitive) == 0 && QSysInfo::productVersion() == QLatin1String("42.1") && qgetenv("QTEST_ENVIRONMENT").split(' ').contains("ci")) { @@ -1150,6 +1151,7 @@ void tst_QDBusAbstractAdaptor::methodCallsPeer() void tst_QDBusAbstractAdaptor::methodCallScriptablePeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1169,6 +1171,7 @@ void tst_QDBusAbstractAdaptor::signalEmissionsPeer_data() void tst_QDBusAbstractAdaptor::signalEmissionsPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QFETCH(QString, interface); QFETCH(QString, name); QFETCH(QVariant, parameter); @@ -1233,6 +1236,7 @@ void tst_QDBusAbstractAdaptor::signalEmissionsPeer() void tst_QDBusAbstractAdaptor::sameSignalDifferentPathsPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1261,6 +1265,7 @@ void tst_QDBusAbstractAdaptor::sameSignalDifferentPathsPeer() void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1283,6 +1288,7 @@ void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer() void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer");; QVERIFY(con.isConnected()); @@ -1356,6 +1362,7 @@ void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer_data() void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1407,6 +1414,7 @@ void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer() void tst_QDBusAbstractAdaptor::readPropertiesPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1431,6 +1439,7 @@ void tst_QDBusAbstractAdaptor::readPropertiesPeer() void tst_QDBusAbstractAdaptor::readPropertiesInvalidInterfacePeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1451,6 +1460,7 @@ void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer_data() void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1481,6 +1491,7 @@ void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer() void tst_QDBusAbstractAdaptor::readAllPropertiesPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1507,6 +1518,7 @@ void tst_QDBusAbstractAdaptor::readAllPropertiesPeer() void tst_QDBusAbstractAdaptor::readAllPropertiesInvalidInterfacePeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1572,6 +1584,7 @@ void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer() void tst_QDBusAbstractAdaptor::writePropertiesPeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); @@ -1883,6 +1896,7 @@ void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValue() void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValuePeer() { + QSKIP("Test is currently too flaky (QTBUG-66223)"); QDBusConnection con("peer"); QVERIFY(con.isConnected()); diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro index 39ce4e26cb0..56618e0bfad 100644 --- a/tests/auto/gui/image/qimage/qimage.pro +++ b/tests/auto/gui/image/qimage/qimage.pro @@ -5,6 +5,6 @@ SOURCES += tst_qimage.cpp QT += core-private gui-private testlib qtConfig(c++11): CONFIG += c++11 -android: RESOURCES+=qimage.qrc +android:!android-embedded: RESOURCES += qimage.qrc TESTDATA += images/* diff --git a/tests/auto/gui/image/qimagereader/qimagereader.pro b/tests/auto/gui/image/qimagereader/qimagereader.pro index 3d35bf59da7..b06f56dddf8 100644 --- a/tests/auto/gui/image/qimagereader/qimagereader.pro +++ b/tests/auto/gui/image/qimagereader/qimagereader.pro @@ -5,7 +5,7 @@ MOC_DIR=tmp QT += core-private gui-private network testlib RESOURCES += qimagereader.qrc -android { +android:!android-embedded { RESOURCES += android_testdata.qrc } diff --git a/tests/auto/gui/image/qimagewriter/qimagewriter.pro b/tests/auto/gui/image/qimagewriter/qimagewriter.pro index 34adedd1874..e63e57886ce 100644 --- a/tests/auto/gui/image/qimagewriter/qimagewriter.pro +++ b/tests/auto/gui/image/qimagewriter/qimagewriter.pro @@ -3,5 +3,5 @@ TARGET = tst_qimagewriter QT += testlib SOURCES += tst_qimagewriter.cpp MOC_DIR=tmp -android: RESOURCES+= qimagewriter.qrc +android:!android-embedded: RESOURCES += qimagewriter.qrc TESTDATA += images/* diff --git a/tests/auto/gui/image/qmovie/tst_qmovie.cpp b/tests/auto/gui/image/qmovie/tst_qmovie.cpp index bcaa759faa1..4e9e9b8115b 100644 --- a/tests/auto/gui/image/qmovie/tst_qmovie.cpp +++ b/tests/auto/gui/image/qmovie/tst_qmovie.cpp @@ -170,6 +170,16 @@ void tst_QMovie::playMovie() QCOMPARE(movie.state(), QMovie::NotRunning); QCOMPARE(movie.frameCount(), frameCount); #endif + + movie.stop(); + QSignalSpy finishedSpy(&movie, &QMovie::finished); + movie.setSpeed(0); + movie.start(); + QCOMPARE(movie.state(), QMovie::Running); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(movie.state(), QMovie::Running); + QCOMPARE(movie.currentFrameNumber(), 0); } void tst_QMovie::jumpToFrame_data() diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 4469b989530..05cf1b5a30e 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -1,5 +1,5 @@ [positioning:default] -ubuntu-16.04 +linux osx-10.12 ci [positioning:fake] osx-10.12 ci diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro index 0d3899ee92e..9ccf8f20bad 100644 --- a/tests/auto/gui/painting/qpainter/qpainter.pro +++ b/tests/auto/gui/painting/qpainter/qpainter.pro @@ -9,7 +9,7 @@ SOURCES += tst_qpainter.cpp TESTDATA += drawEllipse/* drawLine_rop_bitmap/* drawPixmap_rop/* drawPixmap_rop_bitmap/* \ task217400.png -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp index 37f94d02783..373ad7fef96 100644 --- a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp +++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp @@ -93,6 +93,9 @@ private slots: void fallbackFontsOrder(); + void qtbug65923_partal_clone_data(); + void qtbug65923_partal_clone(); + private: QString testFont; QString testFontBoldItalic; @@ -1044,6 +1047,42 @@ void tst_QRawFont::fallbackFontsOrder() fontDatabase.removeApplicationFont(id); } +void tst_QRawFont::qtbug65923_partal_clone_data() +{ + QTest::addColumn("shouldClone"); + + QTest::newRow("Without cloning font engine") << false; + QTest::newRow("Cloning font engine") << true; +} + +void tst_QRawFont::qtbug65923_partal_clone() +{ + QFile file(testFont); + file.open(QIODevice::ReadOnly); + QByteArray fontData = file.readAll(); + + QRawFont outerFont; + + { + QRawFont innerFont(fontData, 16, QFont::PreferDefaultHinting); + + QFETCH(bool, shouldClone); + if (shouldClone) { + // This will trigger QFontEngine::cloneWithSize + innerFont.setPixelSize(innerFont.pixelSize() + 1); + } + + outerFont = innerFont; + } + + // This will detach if data is shared with the raw font. If the raw font has + // a naked reference to the data, without informing Qt of it via the ref count + // of the byte array, this will result in clearing 'live' data. + fontData.fill('\0'); + + QVERIFY(!outerFont.boundingRect(42).isEmpty()); +} + #endif // QT_NO_RAWFONT QTEST_MAIN(tst_QRawFont) diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp index d42702e1ded..1620c2ade6d 100644 --- a/tests/auto/network/access/qftp/tst_qftp.cpp +++ b/tests/auto/network/access/qftp/tst_qftp.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "../../../network-settings.h" diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index 4410549f092..7ffc2797cc2 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -18,6 +18,9 @@ windows windows [ioPostToHttpFromSocket] windows +# QTBUG-66247 +[ioHttpRedirect] +windows [ioHttpRedirectMultipartPost] linux [ioHttpRedirectPolicy] diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp index 31f82539aa8..161d94d642c 100644 --- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp @@ -420,13 +420,20 @@ void tst_QTcpServer::maxPendingConnections() QTcpSocket socket2; QTcpSocket socket3; + QSignalSpy spy(&server, SIGNAL(newConnection())); QVERIFY(server.listen()); socket1.connectToHost(QHostAddress::LocalHost, server.serverPort()); socket2.connectToHost(QHostAddress::LocalHost, server.serverPort()); socket3.connectToHost(QHostAddress::LocalHost, server.serverPort()); - QVERIFY(server.waitForNewConnection(5000)); + // We must have two and only two connections. First compare waits until + // two connections have been made. The second compare makes sure no + // more are accepted. Creating connections happens multithreaded so + // qWait must be used for that. + QTRY_COMPARE(spy.count(), 2); + QTest::qWait(100); + QCOMPARE(spy.count(), 2); QVERIFY(server.hasPendingConnections()); QVERIFY(server.nextPendingConnection()); diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST index 96e59e5678d..d724897b74b 100644 --- a/tests/auto/network/socket/qtcpsocket/BLACKLIST +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -8,4 +8,6 @@ windows windows [timeoutConnect:ip] windows -] +# QTBUG-66247 +[taskQtBug5799ConnectionErrorEventLoop] +windows diff --git a/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp index 5842d58fab2..b8d19c0c0d0 100644 --- a/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp +++ b/tests/auto/other/qprocess_and_guieventloop/tst_qprocess_and_guieventloop.cpp @@ -40,7 +40,7 @@ private slots: void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Not supported on Android"); #else diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 387a2fb84e6..786b9e72f12 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -34,6 +34,12 @@ #include #include +#ifdef Q_OS_WIN +# define EVAL_DRIVE "R:" +#else +# define EVAL_DRIVE +#endif + void tst_qmakelib::addAssignments() { QTest::newRow("assignment") @@ -1599,20 +1605,28 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << true; QTest::newRow("$$absolute_path(): file & path") - << "VAR = $$absolute_path(dir/file.ext, /root/sub)" - << "VAR = /root/sub/dir/file.ext" + << "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" << "" << true; +#ifdef Q_OS_WIN + QTest::newRow("$$absolute_path(): driveless file & absolute path") + << "VAR = $$absolute_path(/root/sub/dir/file.ext, " EVAL_DRIVE "/other)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" + << "" + << true; +#endif + QTest::newRow("$$absolute_path(): absolute file & path") - << "VAR = $$absolute_path(/root/sub/dir/file.ext, /other)" - << "VAR = /root/sub/dir/file.ext" + << "VAR = $$absolute_path(" EVAL_DRIVE "/root/sub/dir/file.ext, " EVAL_DRIVE "/other)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" << "" << true; QTest::newRow("$$absolute_path(): empty file & path") - << "VAR = $$absolute_path('', /root/sub)" - << "VAR = /root/sub" + << "VAR = $$absolute_path('', " EVAL_DRIVE "/root/sub)" + << "VAR = " EVAL_DRIVE "/root/sub" << "" << true; @@ -1634,14 +1648,22 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << "" << true; +#ifdef Q_OS_WIN + QTest::newRow("$$relative_path(): driveless file & absolute path") + << "VAR = $$relative_path(/root/sub/dir/file.ext, " EVAL_DRIVE "/root/sub)" + << "VAR = dir/file.ext" + << "" + << true; +#endif + QTest::newRow("$$relative_path(): absolute file & path") - << "VAR = $$relative_path(/root/sub/dir/file.ext, /root/sub)" + << "VAR = $$relative_path(" EVAL_DRIVE "/root/sub/dir/file.ext, " EVAL_DRIVE "/root/sub)" << "VAR = dir/file.ext" << "" << true; QTest::newRow("$$relative_path(): empty file & path") - << "VAR = $$relative_path('', /root/sub)" + << "VAR = $$relative_path('', " EVAL_DRIVE "/root/sub)" << "VAR = ." << "" << true; @@ -2593,20 +2615,20 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) << true; QTest::newRow("touch(): missing target") - << "touch(/does/not/exist, files/other.txt): OK = 1" + << "touch(" EVAL_DRIVE "/does/not/exist, files/other.txt): OK = 1" << "OK = UNDEF" #ifdef Q_OS_WIN - << "##:1: Cannot open /does/not/exist: The system cannot find the path specified." + << "##:1: Cannot open " EVAL_DRIVE "/does/not/exist: The system cannot find the path specified." #else << "##:1: Cannot touch /does/not/exist: No such file or directory." #endif << true; QTest::newRow("touch(): missing reference") - << "touch(" + wpath + ", /does/not/exist): OK = 1" + << "touch(" + wpath + ", " EVAL_DRIVE "/does/not/exist): OK = 1" << "OK = UNDEF" #ifdef Q_OS_WIN - << "##:1: Cannot open reference file /does/not/exist: The system cannot find the path specified." + << "##:1: Cannot open reference file " EVAL_DRIVE "/does/not/exist: The system cannot find the path specified." #else << "##:1: Cannot stat() reference file /does/not/exist: No such file or directory." #endif diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp index b1250f4f1ad..4a4b20fe50d 100644 --- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp +++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp @@ -42,6 +42,7 @@ void tst_qmakelib::initTestCase() #endif m_prop.insert(ProKey("P1"), ProString("prop val")); m_prop.insert(ProKey("QT_HOST_DATA/get"), ProString(m_indir)); + m_prop.insert(ProKey("QT_HOST_DATA/src"), ProString(m_indir)); QVERIFY(!m_indir.isEmpty()); QVERIFY(QDir(m_outdir).removeRecursively()); @@ -224,21 +225,99 @@ void tst_qmakelib::pathUtils() QVERIFY(IoUtils::isRelativePath(fn0)); QString fn1 = "/a/unix/file/path"; - QVERIFY(IoUtils::isAbsolutePath(fn1)); QCOMPARE(IoUtils::pathName(fn1).toString(), QStringLiteral("/a/unix/file/")); QCOMPARE(IoUtils::fileName(fn1).toString(), QStringLiteral("path")); +} -#ifdef Q_OS_WIN - QString fn0a = "c:file/path"; - QVERIFY(IoUtils::isRelativePath(fn0a)); +void tst_qmakelib::ioUtilRelativity_data() +{ + QTest::addColumn("path"); + QTest::addColumn("relative"); - QString fn1a = "c:\\file\\path"; - QVERIFY(IoUtils::isAbsolutePath(fn1a)); + static const struct { + const char *name; + const char *path; + bool relative; + } rows[] = { + { "resource", ":/resource", +#ifdef QMAKE_BUILTIN_PRFS + false +#else + true #endif + }, +#ifdef Q_OS_WIN // all the complications: + // (except UNC: unsupported) + { "drive-abs", "c:/path/to/file", false }, + { "drive-abs-bs", "c:\\path\\to\\file", false }, + { "drive-path", "c:path/to/file.txt", true }, + { "drive-path-bs", "c:path\\to\\file.txt", true }, + { "rooted", "/Users/qt/bin/true", true }, + { "rooted-bs", "\\Users\\qt\\bin\\true", true }, + { "drive-rel", "c:file.txt", true }, + { "subdir-bs", "path\\to\\file", true }, +#else + { "rooted", "/usr/bin/false", false }, +#endif // Q_OS_WIN + { "subdir", "path/to/file", true }, + { "simple", "file.name", true }, + { "empty", "", true } + }; - QString fnbase = "/another/dir"; - QCOMPARE(IoUtils::resolvePath(fnbase, fn0), QStringLiteral("/another/dir/file/path")); - QCOMPARE(IoUtils::resolvePath(fnbase, fn1), QStringLiteral("/a/unix/file/path")); + for (unsigned int i = sizeof(rows) / sizeof(rows[0]); i-- > 0; ) + QTest::newRow(rows[i].name) << QString::fromLatin1(rows[i].path) + << rows[i].relative; +} + +void tst_qmakelib::ioUtilRelativity() +{ + QFETCH(QString, path); + QFETCH(bool, relative); + + QCOMPARE(IoUtils::isRelativePath(path), relative); +} + +void tst_qmakelib::ioUtilResolve_data() +{ + QTest::addColumn("base"); + QTest::addColumn("path"); + QTest::addColumn("expect"); + + static const struct { + const char *name; + const char *base; + const char *path; + const char *expect; + } data[] = { +#ifdef Q_OS_WIN // all the complications: + { "drive-drive", "a:/ms/dir", "z:/root/file", "z:/root/file" }, + { "drive-drive-bs", "a:\\ms\\dir", "z:\\root\\file", "z:/root/file" }, + { "drive-root", "a:/ms/dir", "/root/file", "a:/root/file" }, + { "drive-root-bs", "a:\\ms\\dir", "\\root\\file", "a:/root/file" }, + { "drive-sub", "a:/ms/dir", "sub/file", "a:/ms/dir/sub/file" }, + { "drive-sub-bs", "a:\\ms\\dir", "sub\\file", "a:/ms/dir/sub/file" }, + { "drive-rel", "a:/ms/dir", "file.txt", "a:/ms/dir/file.txt" }, + { "drive-rel-bs", "a:\\ms\\dir", "file.txt", "a:/ms/dir/file.txt" }, +#else + { "abs-abs", "/a/unix/dir", "/root/file", "/root/file" }, + { "abs-sub", "/a/unix/dir", "sub/file", "/a/unix/dir/sub/file" }, + { "abs-rel", "/a/unix/dir", "file.txt", "/a/unix/dir/file.txt" }, +#endif // Q_OS_WIN + }; + + for (unsigned i = sizeof(data) / sizeof(data[0]); i-- > 0; ) + QTest::newRow(data[i].name) << QString::fromLatin1(data[i].base) + << QString::fromLatin1(data[i].path) + << QString::fromLatin1(data[i].expect); +} + +void tst_qmakelib::ioUtilResolve() +{ + QFETCH(QString, base); + QFETCH(QString, path); + QFETCH(QString, expect); + + QCOMPARE(IoUtils::resolvePath(base, path), expect); } void QMakeTestHandler::print(const QString &fileName, int lineNo, int type, const QString &msg) diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.h b/tests/auto/tools/qmakelib/tst_qmakelib.h index e75dedb7ec8..acfeb43ecdb 100644 --- a/tests/auto/tools/qmakelib/tst_qmakelib.h +++ b/tests/auto/tools/qmakelib/tst_qmakelib.h @@ -48,7 +48,12 @@ private slots: void quoteArgUnix(); void quoteArgWin_data(); void quoteArgWin(); + void pathUtils(); + void ioUtilRelativity_data(); + void ioUtilRelativity(); + void ioUtilResolve_data(); + void ioUtilResolve(); void proString(); void proStringList(); diff --git a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST index 36e47830d0d..da52809aad5 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST +++ b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST @@ -1,2 +1,2 @@ [defaultButton] -osx ci +* diff --git a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp index 78d0372ac02..3c189f92ccd 100644 --- a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp +++ b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp @@ -84,7 +84,7 @@ void tst_QSidebar::addUrls() QAbstractItemModel *model = qsidebar.model(); QDir testDir = QDir::home(); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) // temp and home is the same directory on Android testDir.mkdir(QStringLiteral("test")); QVERIFY(testDir.cd(QStringLiteral("test"))); diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index 539580f6289..fe8571abf13 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -254,6 +254,7 @@ private slots: void zeroScale(); void focusItemChangedSignal(); void minimumRenderSize(); + void checkTouchPointsEllipseDiameters(); // task specific tests below me void task139710_bspTreeCrash(); @@ -2657,7 +2658,7 @@ void tst_QGraphicsScene::render() void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Test only works on platforms with resizable windows"); #endif @@ -2736,7 +2737,7 @@ protected: void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Test fails on some Android devices (QTBUG-44430)"); #endif @@ -4009,7 +4010,7 @@ void tst_QGraphicsScene::polishItems2() void tst_QGraphicsScene::isActive() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Fails on Android (QTBUG-44430)"); #endif @@ -4764,6 +4765,81 @@ void tst_QGraphicsScene::minimumRenderSize() QVERIFY(smallChild->repaints > smallerGrandChild->repaints); } +class TouchItem : public QGraphicsRectItem +{ +public: + TouchItem() : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), + seenTouch(false) + { + setAcceptTouchEvents(true); + setFlag(QGraphicsItem::ItemIgnoresTransformations); + } + bool seenTouch; + QList touchPoints; +protected: + bool sceneEvent(QEvent *event) override + { + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + seenTouch = true; + touchPoints = static_cast(event)->touchPoints(); + event->accept(); + return true; + default: + break; + } + return QGraphicsRectItem::sceneEvent(event); + } +}; + +void tst_QGraphicsScene::checkTouchPointsEllipseDiameters() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.setSceneRect(1, 1, 198, 198); + view.scale(1.5, 1.5); + view.setFocus(); + TouchItem *rect = new TouchItem; + scene.addItem(rect); + view.show(); + QApplication::setActiveWindow(&view); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + const QSizeF ellipseDiameters(10.0, 10.0); + QTouchEvent::TouchPoint touchPoint(0); + touchPoint.setState(Qt::TouchPointPressed); + touchPoint.setPos(view.mapFromScene(rect->mapToScene(rect->boundingRect().center()))); + touchPoint.setScreenPos(view.mapToGlobal(touchPoint.pos().toPoint())); + touchPoint.setEllipseDiameters(ellipseDiameters); + + QList touchPoints = { touchPoint }; + + QTouchDevice *testDevice = QTest::createTouchDevice(QTouchDevice::TouchPad); + QTouchEvent touchEvent(QEvent::TouchBegin, + testDevice, + Qt::NoModifier, + Qt::TouchPointPressed, + touchPoints); + QApplication::sendEvent(view.viewport(), &touchEvent); + QVERIFY(rect->seenTouch); + QVERIFY(rect->touchPoints.size() == 1); + QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters()); + + rect->seenTouch = false; + rect->touchPoints.clear(); + QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, + testDevice, + Qt::NoModifier, + Qt::TouchPointMoved, + touchPoints); + QApplication::sendEvent(view.viewport(), &touchEvent); + QVERIFY(rect->seenTouch); + QVERIFY(rect->touchPoints.size() == 1); + QCOMPARE(ellipseDiameters, rect->touchPoints.first().ellipseDiameters()); +} + void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache() { QGraphicsScene scene; diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST index 40d106e3bae..bc83dad714f 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST @@ -14,3 +14,5 @@ xcb xcb [resizeAnchor] xcb +[update2] +opensuse-42.3 diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index e99ed8f2f42..47232212930 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -149,6 +149,8 @@ private slots: void inputMethodEnabled(); void currentFollowsIndexWidget_data(); void currentFollowsIndexWidget(); + void checkFocusAfterActivationChanges_data(); + void checkFocusAfterActivationChanges(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -2443,5 +2445,82 @@ void tst_QAbstractItemView::currentFollowsIndexWidget() QCOMPARE(view->currentIndex(), item1->index()); } +class EditorItemDelegate : public QItemDelegate +{ +public: + EditorItemDelegate() : QItemDelegate(), openedEditor(nullptr) { } + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &) const override + { + openedEditor = new QLineEdit(parent); + return openedEditor; + } + mutable QPointer openedEditor; +}; + +// Testing the case reported in QTBUG-62253. +// When an itemview with an editor that has focus loses focus +// due to a change in the active window then we need to check +// that the itemview gets focus once the activation is back +// on the original window. +void tst_QAbstractItemView::checkFocusAfterActivationChanges_data() +{ + QTest::addColumn("viewType"); + + QTest::newRow("QListView") << "QListView"; + QTest::newRow("QTableView") << "QTableView"; + QTest::newRow("QTreeView") << "QTreeView"; +} + +void tst_QAbstractItemView::checkFocusAfterActivationChanges() +{ + QFETCH(QString, viewType); + + const QRect availableGeo = qApp->primaryScreen()->availableGeometry(); + const int halfWidth = availableGeo.width() / 2; + QWidget otherTopLevel; + otherTopLevel.setGeometry(availableGeo.x(), availableGeo.y(), + halfWidth, availableGeo.height()); + otherTopLevel.show(); + + QWidget w; + w.setGeometry(availableGeo.x() + halfWidth, availableGeo.y(), + halfWidth, availableGeo.height()); + QLineEdit *le = new QLineEdit(&w); + QAbstractItemView *view = 0; + if (viewType == "QListView") + view = new QListView(&w); + else if (viewType == "QTableView") + view = new QTableView(&w); + else if (viewType == "QTreeView") + view = new QTreeView(&w); + + QStandardItemModel model(5, 5); + view->setModel(&model); + view->move(0, 50); + EditorItemDelegate delegate; + view->setItemDelegate(&delegate); + w.show(); + + QTest::qWaitForWindowActive(&w); + QVERIFY(le->hasFocus()); + + view->setFocus(); + QVERIFY(view->hasFocus()); + + view->edit(model.index(0,0)); + QVERIFY(QTest::qWaitForWindowExposed(delegate.openedEditor)); + QVERIFY(delegate.openedEditor->hasFocus()); + + QApplication::setActiveWindow(&otherTopLevel); + QTest::qWaitForWindowActive(&otherTopLevel); + otherTopLevel.setFocus(); + QVERIFY(!delegate.openedEditor); + + QApplication::setActiveWindow(&w); + QTest::qWaitForWindowActive(&w); + QVERIFY(view->hasFocus()); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro b/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro index 3527b424c1c..0429315d951 100644 --- a/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro +++ b/tests/auto/widgets/itemviews/qdirmodel/qdirmodel.pro @@ -12,7 +12,7 @@ android { DEFINES += SRCDIR=\\\"$$PWD/\\\" } -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp index 2044704e76f..48d39bbb11f 100644 --- a/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp +++ b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp @@ -112,7 +112,7 @@ void tst_QDirModel::getSetCheck() void tst_QDirModel::initTestCase() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QString dataPath = SRCDIR; QString resourceSourcePath = QStringLiteral(":/android_testdata"); QDirIterator it(resourceSourcePath, QDirIterator::Subdirectories); @@ -614,7 +614,7 @@ void tst_QDirModel::task196768_sorting() view.setSortingEnabled(true); index2 = model.index(path); -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QEXPECT_FAIL("", "QTBUG-43818", Continue); #else if (EmulationDetector::isRunningArmOnX86()) diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index a5d131a4368..3594e7fa018 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -2262,10 +2262,6 @@ void tst_QHeaderView::QTBUG6058_reset() void tst_QHeaderView::QTBUG7833_sectionClicked() { - - - - QTableView tv; QStandardItemModel *sim = new QStandardItemModel(&tv); QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&tv); @@ -2289,11 +2285,20 @@ void tst_QHeaderView::QTBUG7833_sectionClicked() tv.horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); tv.setModel(proxyModel); + const int section4Size = tv.horizontalHeader()->sectionSize(4) + 1; + tv.horizontalHeader()->resizeSection(4, section4Size); tv.setColumnHidden(5, true); tv.setColumnHidden(6, true); tv.horizontalHeader()->swapSections(8, 10); tv.sortByColumn(1, Qt::AscendingOrder); + QCOMPARE(tv.isColumnHidden(5), true); + QCOMPARE(tv.isColumnHidden(6), true); + QCOMPARE(tv.horizontalHeader()->sectionsMoved(), true); + QCOMPARE(tv.horizontalHeader()->logicalIndex(8), 10); + QCOMPARE(tv.horizontalHeader()->logicalIndex(10), 8); + QCOMPARE(tv.horizontalHeader()->sectionSize(4), section4Size); + QSignalSpy clickedSpy(tv.horizontalHeader(), SIGNAL(sectionClicked(int))); QSignalSpy pressedSpy(tv.horizontalHeader(), SIGNAL(sectionPressed(int))); diff --git a/tests/auto/widgets/kernel/qlayout/qlayout.pro b/tests/auto/widgets/kernel/qlayout/qlayout.pro index 8e0ea1bfdba..e768e19a268 100644 --- a/tests/auto/widgets/kernel/qlayout/qlayout.pro +++ b/tests/auto/widgets/kernel/qlayout/qlayout.pro @@ -6,7 +6,7 @@ QT += widgets widgets-private testlib testlib-private SOURCES += tst_qlayout.cpp TESTDATA += baseline/* -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp index a55693bb6ce..300a8878bac 100644 --- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp +++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp @@ -337,7 +337,7 @@ void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated() void tst_QLayout::testRetainSizeWhenHidden() { -#if defined(Q_OS_ANDROID) +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) QSKIP("Test does not work on platforms which default to showMaximized()"); #endif diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index c822539966a..2ca30f98c3b 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -59,6 +59,8 @@ osx osx [setToolTip] osx +[moveInResizeEvent] +ubuntu-16.04 [moveChild:right] osx [activateWindow] diff --git a/tests/auto/widgets/styles/qstyle/qstyle.pro b/tests/auto/widgets/styles/qstyle/qstyle.pro index 0fb74999463..9ad09402451 100644 --- a/tests/auto/widgets/styles/qstyle/qstyle.pro +++ b/tests/auto/widgets/styles/qstyle/qstyle.pro @@ -3,7 +3,7 @@ TARGET = tst_qstyle QT += widgets testlib testlib-private SOURCES += tst_qstyle.cpp -android { +android:!android-embedded { RESOURCES += \ testdata.qrc } diff --git a/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST new file mode 100644 index 00000000000..26d1776b0d4 --- /dev/null +++ b/tests/auto/widgets/widgets/qmdisubwindow/BLACKLIST @@ -0,0 +1,2 @@ +[setOpaqueResizeAndMove] +osx-10.12 diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST index b3bf606a087..9b8e07312d4 100644 --- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST @@ -1,2 +1,5 @@ [check_menuPosition] ubuntu-16.04 +#QTBUG-66255 +[activatedCount] +* diff --git a/tests/auto/widgets/widgets/qscrollbar/BLACKLIST b/tests/auto/widgets/widgets/qscrollbar/BLACKLIST new file mode 100644 index 00000000000..277ae4d2605 --- /dev/null +++ b/tests/auto/widgets/widgets/qscrollbar/BLACKLIST @@ -0,0 +1,3 @@ +#QTBUG-66321 +[QTBUG_42871] +macos diff --git a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp index c5e9a443989..752e39c23f6 100644 --- a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp +++ b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp @@ -48,6 +48,7 @@ private slots: void reset() const; void resetSimplified() const; void waitForReadyIODevice() const; + void inputFromSlowDevice() const; }; /*! @@ -207,5 +208,88 @@ void tst_QXmlInputSource::waitForReadyIODevice() const QVERIFY(sv.success); } +// This class is used to emulate a case where less than 4 bytes are sent in +// a single packet to ensure it is still parsed correctly +class SlowIODevice : public QIODevice +{ +public: + SlowIODevice(const QString &expectedData, QObject *parent = 0) + : QIODevice(parent), currentPos(0), readyToSend(true) + { + stringData = expectedData.toUtf8(); + dataTimer = new QTimer(this); + connect(dataTimer, &QTimer::timeout, [=]() { + readyToSend = true; + emit readyRead(); + dataTimer->stop(); + }); + dataTimer->start(1000); + } + bool open(SlowIODevice::OpenMode) override + { + setOpenMode(ReadOnly); + return true; + } + bool isSequential() const override + { + return true; + } + qint64 bytesAvailable() const override + { + if (readyToSend && stringData.size() != currentPos) + return qMax(3, stringData.size() - currentPos); + return 0; + } + qint64 readData(char *data, qint64 maxSize) override + { + if (!readyToSend) + return 0; + const qint64 readSize = qMin(qMin((qint64)3, maxSize), (qint64)(stringData.size() - currentPos)); + if (readSize > 0) + memcpy(data, &stringData.constData()[currentPos], readSize); + currentPos += readSize; + readyToSend = false; + if (currentPos != stringData.size()) + dataTimer->start(1000); + return readSize; + } + qint64 writeData(const char *, qint64) override { return 0; } + bool waitForReadyRead(int msecs) override + { + // Delibrately wait a maximum of 10 seconds for the sake + // of the test, so it doesn't unduly hang + const int waitTime = qMax(10000, msecs); + QTime t; + t.start(); + while (t.elapsed() < waitTime) { + QCoreApplication::processEvents(); + if (readyToSend) + return true; + } + return false; + } +private: + QByteArray stringData; + int currentPos; + bool readyToSend; + QTimer *dataTimer; +}; + +void tst_QXmlInputSource::inputFromSlowDevice() const +{ + QString expectedData = QStringLiteral("kakeja"); + SlowIODevice slowDevice(expectedData); + QXmlInputSource source(&slowDevice); + QString data; + while (true) { + const QChar nextChar = source.next(); + if (nextChar == QXmlInputSource::EndOfDocument) + break; + else if (nextChar != QXmlInputSource::EndOfData) + data += nextChar; + } + QCOMPARE(data, expectedData); +} + QTEST_MAIN(tst_QXmlInputSource) #include "tst_qxmlinputsource.moc" diff --git a/tests/manual/touchGraphicsItem/main.cpp b/tests/manual/touchGraphicsItem/main.cpp new file mode 100644 index 00000000000..7afadc7edd7 --- /dev/null +++ b/tests/manual/touchGraphicsItem/main.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +class TouchableItem : public QGraphicsRectItem +{ +public: + TouchableItem() : QGraphicsRectItem(50, 50, 400, 400) + { + setBrush(Qt::yellow); + setAcceptTouchEvents(true); + } +protected: + bool sceneEvent(QEvent *e) + { + const bool ret = QGraphicsRectItem::sceneEvent(e); + switch (e->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QTouchEvent *te = static_cast(e); + for (const QTouchEvent::TouchPoint &tp : te->touchPoints()) { + QGraphicsEllipseItem *diameterItem = nullptr; + QSizeF ellipse = tp.ellipseDiameters(); + if (ellipse.isNull()) { + ellipse = QSizeF(5, 5); + } else { + diameterItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2, tp.pos().y() - ellipse.height() / 2, + ellipse.width(), ellipse.height()), this); + diameterItem->setPen(QPen(Qt::red)); + diameterItem->setBrush(QBrush(Qt::red)); + if (ellipse.width() > qreal(2) && ellipse.height() > qreal(2)) + ellipse.scale(ellipse.width() - 2, ellipse.height() - 2, Qt::IgnoreAspectRatio); + } + QGraphicsItem *parent = diameterItem ? static_cast(diameterItem) : static_cast(this); + QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(QRectF(tp.pos().x() - ellipse.width() / 2, + tp.pos().y() - ellipse.height() / 2, + ellipse.width(), ellipse.height()), parent); + ellipseItem->setPen(QPen(Qt::blue)); + ellipseItem->setBrush(QBrush(Qt::blue)); + } + te->accept(); + return true; + } + default: + break; + } + return ret; + } +}; + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + QMainWindow mw; + QWidget *w = new QWidget; + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(new QLabel("The blue ellipses should indicate touch point contact patches")); + qDebug() << "Touch devices:"; + for (const QTouchDevice *device : QTouchDevice::devices()) { + QString result; + QTextStream str(&result); + str << (device->type() == QTouchDevice::TouchScreen ? "TouchScreen" : "TouchPad") + << " \"" << device->name() << "\", max " << device->maximumTouchPoints() + << " touch points, capabilities:"; + const QTouchDevice::Capabilities capabilities = device->capabilities(); + if (capabilities & QTouchDevice::Position) + str << " Position"; + if (capabilities & QTouchDevice::Area) + str << " Area"; + if (capabilities & QTouchDevice::Pressure) + str << " Pressure"; + if (capabilities & QTouchDevice::Velocity) + str << " Velocity"; + if (capabilities & QTouchDevice::RawPositions) + str << " RawPositions"; + if (capabilities & QTouchDevice::NormalizedPosition) + str << " NormalizedPosition"; + if (capabilities & QTouchDevice::MouseEmulation) + str << " MouseEmulation"; + vbox->addWidget(new QLabel(result)); + qDebug() << " " << result; + } + QGraphicsView *view = new QGraphicsView; + view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents); + QGraphicsScene *scene = new QGraphicsScene(0, 0, 500, 500); + TouchableItem *touchableItem = new TouchableItem; + scene->addItem(touchableItem); + view->setScene(scene); + vbox->addWidget(view); + w->setLayout(vbox); + mw.setCentralWidget(w); + QMenu *menu = mw.menuBar()->addMenu("Menu"); + QAction *clear = new QAction("Clear"); + QObject::connect(clear, &QAction::triggered, [=]() { + qDeleteAll(touchableItem->childItems()); + }); + menu->addAction(clear); + QAction *ignoreTransform = new QAction("Ignore transformations"); + QObject::connect(ignoreTransform, &QAction::triggered, [=]() { + view->scale(1.5, 1.5); + touchableItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); + }); + menu->addAction(ignoreTransform); + QAction *quit = new QAction("Quit"); + quit->setShortcut(QKeySequence::Quit); + QObject::connect(quit, &QAction::triggered, &QApplication::quit); + menu->addAction(quit); + mw.show(); + + return a.exec(); +} + + diff --git a/tests/manual/touchGraphicsItem/touchGraphicsItem.pro b/tests/manual/touchGraphicsItem/touchGraphicsItem.pro new file mode 100644 index 00000000000..67799ce9c4e --- /dev/null +++ b/tests/manual/touchGraphicsItem/touchGraphicsItem.pro @@ -0,0 +1,5 @@ +QT+=widgets +TEMPLATE = app +TARGET = touchGraphicsItem +INCLUDEPATH += . +SOURCES += main.cpp