summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE.GPLv3686
-rw-r--r--LICENSE.LGPLv21514
-rw-r--r--LICENSE.LGPLv32
-rwxr-xr-xbin/syncqt.pl84
-rw-r--r--config_help.txt2
-rwxr-xr-xconfigure2
-rw-r--r--configure.json4
-rw-r--r--configure.pri10
-rw-r--r--dist/changes-5.11.0399
-rw-r--r--doc/global/config.qdocconf2
-rw-r--r--doc/global/html-footer-online.qdocconf2
-rw-r--r--doc/global/html-footer.qdocconf2
-rw-r--r--doc/global/qt-module-defaults-online.qdocconf2
-rw-r--r--doc/src/images/dirview-example.pngbin22348 -> 25348 bytes
-rw-r--r--doc/src/images/dynamiclayouts-example.pngbin0 -> 22858 bytes
-rw-r--r--doc/src/images/findfiles-example.pngbin11219 -> 11174 bytes
-rw-r--r--doc/src/images/transitions.pngbin0 -> 4314 bytes
-rw-r--r--examples/widgets/animation/sub-attaq/mainwindow.cpp9
-rw-r--r--examples/widgets/doc/src/addressbook-tutorial.qdoc10
-rw-r--r--examples/widgets/doc/src/dirview.qdoc36
-rw-r--r--examples/widgets/doc/src/dynamiclayouts.qdoc75
-rw-r--r--examples/widgets/doc/src/eventtransitions.qdoc27
-rw-r--r--examples/widgets/doc/src/findfiles.qdoc105
-rw-r--r--examples/widgets/doc/src/graphicsview-flowlayout.qdoc14
-rw-r--r--examples/widgets/graphicsview/flowlayout/main.cpp3
-rw-r--r--examples/widgets/itemviews/frozencolumn/main.cpp9
-rw-r--r--examples/widgets/layouts/dynamiclayouts/dialog.cpp54
-rw-r--r--examples/widgets/layouts/dynamiclayouts/dialog.h8
-rw-r--r--examples/widgets/layouts/flowlayout/main.cpp3
-rw-r--r--examples/widgets/painting/pathstroke/pathstroke.cpp4
-rw-r--r--examples/widgets/painting/pathstroke/pathstroke.h1
-rw-r--r--examples/widgets/tools/i18n/languagechooser.cpp9
-rw-r--r--examples/widgets/tools/i18n/mainwindow.cpp2
-rw-r--r--examples/widgets/tools/regularexpression/regularexpressiondialog.cpp57
-rw-r--r--examples/widgets/tools/regularexpression/regularexpressiondialog.h2
-rw-r--r--header.BSD2
-rw-r--r--header.COMM4
-rw-r--r--header.FDL2
-rw-r--r--header.GPL2
-rw-r--r--header.GPL-EXCEPT2
-rw-r--r--header.LGPL2
-rw-r--r--header.LGPL-NOGPL22
-rw-r--r--header.LGPL-ONLY4
-rw-r--r--header.LGPL34
-rw-r--r--header.LGPL3-COMM4
-rw-r--r--mkspecs/android-clang/qmake.conf3
-rw-r--r--mkspecs/android-g++/qmake.conf3
-rw-r--r--mkspecs/common/android-base-tail.conf10
-rw-r--r--mkspecs/features/configure_base.prf20
-rw-r--r--mkspecs/features/create_cmake.prf4
-rw-r--r--mkspecs/features/ctest_testcase_common.prf2
-rw-r--r--mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in21
-rw-r--r--mkspecs/features/exclusive_builds.prf4
-rw-r--r--mkspecs/features/mac/sdk.prf12
-rw-r--r--mkspecs/features/qmltestcase.prf1
-rw-r--r--mkspecs/features/qt_build_config.prf1
-rw-r--r--mkspecs/features/qt_configure.prf24
-rw-r--r--mkspecs/features/qt_installs.prf6
-rw-r--r--mkspecs/features/qt_module.prf7
-rw-r--r--mkspecs/features/qt_module_headers.prf20
-rw-r--r--mkspecs/features/resources.prf4
-rw-r--r--mkspecs/macx-clang/qmake.conf7
-rw-r--r--qmake/doc/src/qmake-manual.qdoc15
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp3
-rw-r--r--qmake/generators/unix/unixmake2.cpp4
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp24
-rw-r--r--qmake/library/ioutils.cpp9
-rw-r--r--qmake/library/ioutils.h8
-rw-r--r--qmake/library/qmakebuiltins.cpp33
-rw-r--r--qmake/library/qmakeevaluator.cpp57
-rw-r--r--qmake/library/qmakeevaluator.h3
-rw-r--r--qmake/library/qmakeglobals.cpp64
-rw-r--r--qmake/library/qmakeglobals.h2
-rw-r--r--qmake/library/qmakeparser.cpp82
-rw-r--r--qmake/library/qmakeparser.h29
-rw-r--r--qmake/library/qmakevfs.cpp146
-rw-r--r--qmake/library/qmakevfs.h85
-rw-r--r--qmake/project.cpp2
-rw-r--r--src/3rdparty/sqlite/qt_attribution.json2
-rw-r--r--src/3rdparty/sqlite/sqlite3.c6499
-rw-r--r--src/3rdparty/sqlite/sqlite3.h534
-rw-r--r--src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp5
-rw-r--r--src/corelib/Qt5Config.cmake.in4
-rw-r--r--src/corelib/Qt5CoreConfigExtras.cmake.in23
-rw-r--r--src/corelib/Qt5CoreMacros.cmake57
-rw-r--r--src/corelib/arch/arch.pri7
-rw-r--r--src/corelib/arch/qatomic_msvc.h485
-rw-r--r--src/corelib/corelib.pro1
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp6
-rw-r--r--src/corelib/doc/src/objectmodel/properties.qdoc2
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h1
-rw-r--r--src/corelib/global/qglobal.cpp8
-rw-r--r--src/corelib/global/qglobal.h10
-rw-r--r--src/corelib/global/qlogging.cpp4
-rw-r--r--src/corelib/global/qrandom.cpp4
-rw-r--r--src/corelib/io/qdir.cpp36
-rw-r--r--src/corelib/io/qfile.cpp5
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp23
-rw-r--r--src/corelib/io/qipaddress.cpp5
-rw-r--r--src/corelib/io/qresource.cpp20
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp2
-rw-r--r--src/corelib/io/qwindowspipereader.cpp6
-rw-r--r--src/corelib/itemmodels/itemmodels.pri48
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h2
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel_p.h2
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.cpp5
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h7
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel_p.h4
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.cpp5
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h2
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel_p.h2
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp5
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h7
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp4
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.h7
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm12
-rw-r--r--src/corelib/kernel/qcoreevent.cpp2
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp2
-rw-r--r--src/corelib/kernel/qmetatype.cpp26
-rw-r--r--src/corelib/kernel/qmetatype.h37
-rw-r--r--src/corelib/kernel/qmetatype_p.h4
-rw-r--r--src/corelib/kernel/qobject.cpp8
-rw-r--r--src/corelib/kernel/qobject.h6
-rw-r--r--src/corelib/kernel/qvariant.cpp161
-rw-r--r--src/corelib/kernel/qvariant.h32
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp2
-rw-r--r--src/corelib/thread/qatomic_bootstrap.h (renamed from src/corelib/arch/qatomic_bootstrap.h)0
-rw-r--r--src/corelib/thread/qatomic_cxx11.h (renamed from src/corelib/arch/qatomic_cxx11.h)0
-rw-r--r--src/corelib/thread/qbasicatomic.h16
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp2
-rw-r--r--src/corelib/thread/qgenericatomic.h3
-rw-r--r--src/corelib/thread/qsemaphore.cpp155
-rw-r--r--src/corelib/thread/thread.pri4
-rw-r--r--src/corelib/tools/qalgorithms.h10
-rw-r--r--src/corelib/tools/qbytearray.cpp1
-rw-r--r--src/corelib/tools/qeasingcurve.cpp75
-rw-r--r--src/corelib/tools/qlocale_p.h14
-rw-r--r--src/corelib/tools/qregularexpression.cpp4
-rw-r--r--src/corelib/tools/qregularexpression.h6
-rw-r--r--src/corelib/tools/qshareddata.h12
-rw-r--r--src/corelib/tools/qsharedpointer.cpp2
-rw-r--r--src/corelib/tools/qstring.cpp30
-rw-r--r--src/corelib/tools/qstring.h14
-rw-r--r--src/corelib/tools/qstringlist.cpp22
-rw-r--r--src/corelib/tools/qstringlist.h24
-rw-r--r--src/corelib/tools/qvarlengtharray.h4
-rw-r--r--src/corelib/tools/qvector.h4
-rw-r--r--src/dbus/LIBDBUS-1-LICENSE.txt157
-rw-r--r--src/dbus/Qt5DBusMacros.cmake6
-rw-r--r--src/dbus/doc/src/qtdbus-index.qdoc7
-rw-r--r--src/dbus/qt_attribution.json15
-rw-r--r--src/gui/configure.json2
-rw-r--r--src/gui/doc/src/qtgui.qdoc13
-rw-r--r--src/gui/image/qimage_conversions.cpp12
-rw-r--r--src/gui/image/qimage_p.h30
-rw-r--r--src/gui/image/qpixmap.cpp8
-rw-r--r--src/gui/image/qpixmap_raster.cpp9
-rw-r--r--src/gui/image/qpixmap_raster_p.h2
-rw-r--r--src/gui/itemmodels/itemmodels.pri2
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp4
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.h7
-rw-r--r--src/gui/itemmodels/qstandarditemmodel_p.h6
-rw-r--r--src/gui/kernel/qguiapplication.cpp21
-rw-r--r--src/gui/kernel/qopenglwindow.cpp3
-rw-r--r--src/gui/kernel/qstylehints.cpp2
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp2
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp1
-rw-r--r--src/gui/opengl/qopengltexture.cpp12
-rw-r--r--src/gui/painting/qblendfunctions_p.h20
-rw-r--r--src/gui/painting/qdrawhelper.cpp98
-rw-r--r--src/gui/painting/qdrawhelper_p.h9
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp10
-rw-r--r--src/gui/painting/qpagelayout.cpp9
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp22
-rw-r--r--src/gui/painting/qpainterpath.cpp7
-rw-r--r--src/gui/painting/qpdf.cpp15
-rw-r--r--src/gui/text/qfontdatabase.cpp2
-rw-r--r--src/gui/text/qtextdocument.cpp6
-rw-r--r--src/gui/text/qtextdocument.h2
-rw-r--r--src/gui/util/qdesktopservices.cpp7
-rw-r--r--src/gui/util/qshadergenerator.cpp4
-rw-r--r--src/gui/util/qshaderlanguage_p.h1
-rw-r--r--src/gui/util/qvalidator.cpp4
-rw-r--r--src/gui/util/qvalidator.h8
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp21
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp1
-rw-r--r--src/network/kernel/qnetworkinterface.cpp2
-rw-r--r--src/network/kernel/qnetworkinterface.h2
-rw-r--r--src/network/kernel/qnetworkinterface_linux.cpp13
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp356
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h27
-rw-r--r--src/network/socket/socket.pri2
-rw-r--r--src/network/ssl/qssl.cpp12
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp2
-rw-r--r--src/network/ssl/qsslconfiguration.cpp20
-rw-r--r--src/network/ssl/qsslconfiguration.h6
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp4
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp62
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_mac_shared.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl11_symbols_p.h6
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h3
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp8
-rw-r--r--src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp6
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp5
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp2
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm5
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.h4
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm16
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm47
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h2
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm3
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm14
-rw-r--r--src/plugins/platforms/ios/quiview.mm2
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp41
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp131
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h15
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp41
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp84
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp184
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp57
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h16
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h3
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp3
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpaktheme.cpp88
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.cpp6
-rw-r--r--src/plugins/platformthemes/platformthemes.pro2
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp4
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci.cpp6
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp6
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp49
-rw-r--r--src/plugins/styles/mac/mac.pro2
-rw-r--r--src/plugins/styles/mac/qmacstyle.qdoc207
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm2111
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h75
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp3
-rw-r--r--src/sql/kernel/qsqldatabase.cpp6
-rw-r--r--src/sql/kernel/qsqlresult.cpp6
-rw-r--r--src/sql/kernel/qsqlresult_p.h2
-rw-r--r--src/testlib/configure.json22
-rw-r--r--src/testlib/qabstractitemmodeltester.h4
-rw-r--r--src/testlib/qbenchmark.h2
-rw-r--r--src/testlib/qbenchmark_p.h2
-rw-r--r--src/testlib/qbenchmarkmetric.h2
-rw-r--r--src/testlib/qbenchmarkmetric_p.h2
-rw-r--r--src/testlib/qtest.h2
-rw-r--r--src/testlib/qtestaccessible.h2
-rw-r--r--src/testlib/qtestblacklist_p.h2
-rw-r--r--src/testlib/qtestcase.cpp28
-rw-r--r--src/testlib/qtestcase.h4
-rw-r--r--src/testlib/qtestdata.h2
-rw-r--r--src/testlib/qtestevent.h19
-rw-r--r--src/testlib/qtesteventloop.h2
-rw-r--r--src/testlib/qtestkeyboard.h2
-rw-r--r--src/testlib/qtestlog.cpp10
-rw-r--r--src/testlib/qtestlog_p.h2
-rw-r--r--src/testlib/qtestmouse.cpp2
-rw-r--r--src/testlib/qtestmouse.h2
-rw-r--r--src/testlib/qtestresult_p.h2
-rw-r--r--src/testlib/qtesttable_p.h2
-rw-r--r--src/testlib/qtesttouch.h2
-rw-r--r--src/testlib/qttestglobal.h (renamed from src/testlib/qtest_global.h)6
-rw-r--r--src/testlib/testlib.pro14
-rw-r--r--src/tools/rcc/rcc.cpp61
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp2
-rw-r--r--src/widgets/doc/images/graphicsflowlayout.pngbin0 -> 6064 bytes
-rw-r--r--src/widgets/itemviews/qheaderview.cpp18
-rw-r--r--src/widgets/itemviews/qheaderview.h3
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp2
-rw-r--r--src/widgets/kernel/qaction.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp4
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp2
-rw-r--r--src/widgets/kernel/qshortcut.cpp9
-rw-r--r--src/widgets/kernel/qtooltip.cpp12
-rw-r--r--src/widgets/kernel/qwidget.cpp6
-rw-r--r--src/widgets/styles/qfusionstyle.cpp8
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp9
-rw-r--r--src/widgets/widgets/qdockwidget.cpp10
-rw-r--r--src/widgets/widgets/qlabel.cpp21
-rw-r--r--src/widgets/widgets/qlabel.h3
-rw-r--r--src/widgets/widgets/qlabel_p.h1
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp23
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h4
-rw-r--r--src/widgets/widgets/qmenu.cpp7
-rw-r--r--src/widgets/widgets/qsplitter.cpp13
-rw-r--r--src/widgets/widgets/qtabbar.cpp6
-rw-r--r--src/xml/dom/qdom.cpp2
-rw-r--r--sync.profile3
-rw-r--r--tests/auto/cmake/CMakeLists.txt23
-rw-r--r--tests/auto/cmake/test_use_modules_function/CMakeLists.txt18
-rw-r--r--tests/auto/cmake/test_use_modules_function/three.cpp45
-rw-r--r--tests/auto/cmake/test_use_modules_function/two.cpp43
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp21
-rw-r--r--tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp8
-rw-r--r--tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp1
-rw-r--r--tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp1
-rw-r--r--tests/auto/corelib/io/qprocess/BLACKLIST3
-rw-r--r--tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp1
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp19
-rw-r--r--tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp10
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp2
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp7
-rw-r--r--tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp46
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp69
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp8
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp4
-rw-r--r--tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp70
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp71
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp68
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp37
-rw-r--r--tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp12
-rw-r--r--tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp29
-rw-r--r--tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp6
-rw-r--r--tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp19
-rw-r--r--tests/auto/gui/kernel/qcursor/tst_qcursor.cpp3
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp13
-rw-r--r--tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp8
-rw-r--r--tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp34
-rw-r--r--tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp6
-rw-r--r--tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp29
-rw-r--r--tests/auto/gui/kernel/qwindow/BLACKLIST6
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp30
-rw-r--r--tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp4
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp28
-rw-r--r--tests/auto/network/access/http2/http2srv.h5
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp47
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp9
-rw-r--r--tests/auto/network/kernel/qdnslookup/BLACKLIST2
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp6
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp15
-rw-r--r--tests/auto/network/ssl/qsslkey/BLACKLIST3
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp18
-rw-r--r--tests/auto/opengl/qgl/tst_qgl.cpp3
-rw-r--r--tests/auto/other/compiler/tst_compiler.cpp2
-rw-r--r--tests/auto/other/gestures/BLACKLIST4
-rw-r--r--tests/auto/other/lancelot/paintcommands.cpp380
-rw-r--r--tests/auto/other/lancelot/paintcommands.h194
-rw-r--r--tests/auto/other/qfocusevent/tst_qfocusevent.cpp5
-rw-r--r--tests/auto/other/qobjectrace/tst_qobjectrace.cpp12
-rw-r--r--tests/auto/other/toolsupport/tst_toolsupport.cpp25
-rw-r--r--tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp6
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp11
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp217
-rw-r--r--tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp3
-rwxr-xr-xtests/auto/testlib/selftests/generate_expected_output.py2
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp3
-rw-r--r--tests/auto/tools/moc/moc.pro10
-rw-r--r--tests/auto/tools/moc/no-keywords.h15
-rw-r--r--tests/auto/tools/qmakelib/evaltest.cpp24
-rw-r--r--tests/auto/tools/qmakelib/parsertest.cpp2
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro2
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp3
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp21
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp31
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp26
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp6
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST3
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp7
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp104
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp2
-rw-r--r--tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp6
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp5
-rw-r--r--tests/auto/widgets/util/qscroller/tst_qscroller.cpp21
-rw-r--r--tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp12
-rw-r--r--tests/benchmarks/gui/painting/lancebench/lancebench.pro13
-rw-r--r--tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp328
-rw-r--r--tests/benchmarks/gui/painting/painting.pro3
-rw-r--r--tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp10
-rw-r--r--tests/manual/qtabletevent/regular_widgets/main.cpp60
-rw-r--r--tests/manual/shortcuts/main.cpp304
-rw-r--r--tests/shared/emulationdetector.h4
396 files changed, 10951 insertions, 8119 deletions
diff --git a/LICENSE.GPLv3 b/LICENSE.GPLv3
deleted file mode 100644
index 71c4ad49c3..0000000000
--- a/LICENSE.GPLv3
+++ /dev/null
@@ -1,686 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
-
- The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
- Contact: http://www.qt.io/licensing/
-
- You may use, distribute and copy the Qt Toolkit under the terms of
- GNU Lesser General Public License version 3. That license references
- the General Public License version 3, that is displayed below. Other
- portions of the Qt Toolkit may be licensed directly under this license.
-
--------------------------------------------------------------------------
-
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LICENSE.LGPLv21 b/LICENSE.LGPLv21
deleted file mode 100644
index 15a208b486..0000000000
--- a/LICENSE.LGPLv21
+++ /dev/null
@@ -1,514 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
-
- The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd.
- Contact: http://www.qt.io/licensing/
-
- You may use, distribute and copy the Qt Toolkit under the terms of
- GNU Lesser General Public License version 2.1, which is displayed below.
-
--------------------------------------------------------------------------
-
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/LICENSE.LGPLv3 b/LICENSE.LGPLv3
index 849103ad91..1fe5d9d9d2 100644
--- a/LICENSE.LGPLv3
+++ b/LICENSE.LGPLv3
@@ -6,7 +6,7 @@
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 3, which is displayed below.
This license makes reference to the version 3 of the GNU General
- Public License, which you can find in the LICENSE.GPLv3 file.
+ Public License, which you can find in the LICENSE.GPL3 file.
-------------------------------------------------------------------------
diff --git a/bin/syncqt.pl b/bin/syncqt.pl
index ff4cafa7b9..f202599fe0 100755
--- a/bin/syncqt.pl
+++ b/bin/syncqt.pl
@@ -98,14 +98,11 @@ my $showonly = 0;
my $verbose_level = 1;
my $remove_stale = 1;
my $force_win = 0;
-my $force_relative = 0;
my $check_includes = 0;
my $copy_headers = 0;
-my $create_private_headers = 1;
my $minimal = 0;
my $module_version = 0;
my @modules_to_sync ;
-$force_relative = 1 if ( -d "/System/Library/Frameworks" );
# functions ----------------------------------------------------------
@@ -124,7 +121,6 @@ sub showUsage
print " -copy Copy headers instead of include-fwd(default: " . ($copy_headers ? "yes" : "no") . ")\n";
print " -remove-stale Removes stale headers (default: " . ($remove_stale ? "yes" : "no") . ")\n";
- print " -relative Force relative symlinks (default: " . ($force_relative ? "yes" : "no") . ")\n";
print " -windows Force platform to Windows (default: " . ($force_win ? "yes" : "no") . ")\n";
print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n";
print " -minimal Do not create CamelCase headers (default: " . ($minimal ? "yes" : "no") . ")\n";
@@ -137,7 +133,6 @@ sub showUsage
print " -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR>\n";
print " Create headers for <NAME> with original headers in\n";
print " <HEADERDIR> relative to <PROFILEDIR> \n";
- print " -private Force copy private headers (default: " . ($create_private_headers ? "yes" : "no") . ")\n";
print " -help This help\n";
exit 0;
}
@@ -782,9 +777,6 @@ while ( @ARGV ) {
} elsif($arg eq "-minimal") {
$var = "minimal";
$val = "yes";
- } elsif($arg eq "-private") {
- $var = "create_private_headers";
- $val = "yes";
} elsif($arg eq "-version") {
$var = "version";
$val = shift @ARGV;
@@ -841,12 +833,6 @@ while ( @ARGV ) {
} elsif($force_win) {
$force_win--;
}
- } elsif ($var eq "relative") {
- if($val eq "yes") {
- $force_relative++;
- } elsif($force_relative) {
- $force_relative--;
- }
} elsif ($var eq "minimal") {
if($val eq "yes") {
$minimal++;
@@ -934,11 +920,9 @@ foreach my $lib (@modules_to_sync) {
$allheadersprivate = 1 if $allmoduleheadersprivate{$lib};
#information used after the syncing
- my $pri_install_classes = "";
+ my $pri_install_gfiles = "";
my $pri_install_files = "";
- my $pri_install_ifiles = "";
my $pri_install_pfiles = "";
- my $pri_install_ipfiles = "";
my $pri_install_qpafiles = "";
my $pri_injections = "";
my $pri_clean_files = "";
@@ -1084,9 +1068,9 @@ foreach my $lib (@modules_to_sync) {
$header_copies++ if (!$shadow && syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts));
}
- } elsif ($create_private_headers && !$qpa_header) {
+ } elsif (!$qpa_header) {
$oheader = "$out_basedir/include/$lib/$module_version/$lib/private/$header";
- } elsif ($create_private_headers) {
+ } else {
$oheader = "$out_basedir/include/$lib/$module_version/$lib/qpa/$header";
}
$header_copies++ if (!$shadow && syncHeader($lib, $oheader, $iheader, $copy_headers, $ts));
@@ -1100,15 +1084,13 @@ foreach my $lib (@modules_to_sync) {
# if ($class =~ m/::/) {
# $class =~ s,::,/,g;
# }
- my $class_header = fixPaths("$out_basedir/include/$lib/$class", $dir) . " ";
- $pri_install_classes .= $class_header
- unless($pri_install_classes =~ $class_header);
+ my $class_header = "$class ";
+ $pri_install_gfiles .= $class_header
+ unless ($shadow || $pri_install_gfiles =~ $class_header);
$injection .= ":$class";
}
- if ($shadow) {
- $pri_install_ifiles .= "$pri_install_iheader ";
- } else {
+ if (!$shadow) {
# put it into the master file
$master_contents{$public_header} = $requires if (shouldMasterInclude($iheader));
@@ -1120,10 +1102,7 @@ foreach my $lib (@modules_to_sync) {
elsif ($qpa_header) {
$pri_install_qpafiles.= "$pri_install_iheader ";;
}
- elsif ($shadow) {
- $pri_install_ipfiles .= "$pri_install_iheader ";
- }
- else {
+ elsif (!$shadow) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
$pri_injections .= fixPaths($iheader, "$out_basedir/include/$lib")
@@ -1175,16 +1154,10 @@ foreach my $lib (@modules_to_sync) {
# create deprecated headers
my $first = 1;
while (my ($header, $include) = each %{$deprecatedheaders{$lib}}) {
- my $public_header = 0;
- $public_header = 1 unless ($allheadersprivate || ($header =~ /_p\.h$/));
- next unless ($public_header || $create_private_headers);
-
- my $header_path = "$out_basedir/include/$lib/";
- unless ($public_header) {
- $header_path .= "$module_version/$lib/private/";
- }
- $header_path .= "$header";
+ die "Attempting unsupported aliasing of private header $header.\n"
+ if ($allheadersprivate || ($header =~ /_p\.h$/));
+ my $header_path = "$out_basedir/include/$lib/$header";
unless (-e $header_path) {
my $guard = "DEPRECATED_HEADER_" . $lib . "_" . $header;
$guard =~ s/([^a-zA-Z0-9_])/_/g;
@@ -1192,26 +1165,19 @@ foreach my $lib (@modules_to_sync) {
my $header_dir = dirname($header_path);
make_path($header_dir, $lib, $verbose_level);
+ my $warning = "Header <$lib/$header> is deprecated. Please include <$include> instead.";
my $hdrcont =
"#ifndef $guard\n" .
- "#define $guard\n";
- my $warning = "Header <$lib/";
- $warning .= "private/" unless ($public_header);
- $warning .= "$header> is deprecated. Please include <$include> instead.";
- $hdrcont .=
+ "#define $guard\n" .
"#if defined(__GNUC__)\n" .
"# warning $warning\n" .
"#elif defined(_MSC_VER)\n" .
"# pragma message (\"$warning\")\n" .
"#endif\n" .
- "#include <$include>\n";
- if ($public_header) {
- $hdrcont .=
- "#if 0\n" .
- "#pragma qt_no_master_include\n" .
- "#endif\n";
- }
- $hdrcont .=
+ "#include <$include>\n" .
+ "#if 0\n" .
+ "#pragma qt_no_master_include\n" .
+ "#endif\n" .
"#endif\n";
if (writeFile($header_path, $hdrcont)) {
if ($verbose_level < 3) {
@@ -1225,12 +1191,7 @@ foreach my $lib (@modules_to_sync) {
}
}
- my $addendum = fixPaths($header_path, $dir) . " ";
- if ($public_header) {
- $pri_install_files .= $addendum;
- } else {
- $pri_install_pfiles .= $addendum;
- }
+ $pri_install_gfiles .= "$header ";
}
if ($verbose_level < 3) {
print " }\n" unless ($first);
@@ -1240,8 +1201,7 @@ foreach my $lib (@modules_to_sync) {
my $vheader = "$out_basedir/include/$lib/".lc($lib)."version.h";
my $VHeader = "$out_basedir/include/$lib/${lib}Version";
syncHeader($lib, $VHeader, $vheader, 0);
- $pri_install_files .= fixPaths($vheader, $dir) . " ";
- $pri_install_classes .= fixPaths($VHeader, $dir) . " ";
+ $pri_install_gfiles .= lc($lib)."version.h ${lib}Version ";
my @versions = split(/\./, $module_version);
my $modulehexstring = sprintf("0x%02X%02X%02X", $versions[0], $versions[1], $versions[2]);
my $vhdrcont =
@@ -1257,7 +1217,7 @@ foreach my $lib (@modules_to_sync) {
writeFile($vheader, $vhdrcont, $lib, "version header");
my $master_include = "$out_basedir/include/$lib/$lib";
- $pri_install_files .= fixPaths($master_include, $dir) . " ";
+ $pri_install_gfiles .= "$lib ";
writeFile($master_include, $master_contents, $lib, "master header");
}
@@ -1265,10 +1225,8 @@ foreach my $lib (@modules_to_sync) {
#handle the headers.pri for each module
my $headers_pri_contents = "";
$headers_pri_contents .= "SYNCQT.HEADER_FILES = $pri_install_files\n";
- $headers_pri_contents .= "SYNCQT.INJECTED_HEADER_FILES = $pri_install_ifiles\n";
- $headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n";
+ $headers_pri_contents .= "SYNCQT.GENERATED_HEADER_FILES = $pri_install_gfiles\n";
$headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n";
- $headers_pri_contents .= "SYNCQT.INJECTED_PRIVATE_HEADER_FILES = $pri_install_ipfiles\n";
$headers_pri_contents .= "SYNCQT.QPA_HEADER_FILES = $pri_install_qpafiles\n";
$headers_pri_contents .= "SYNCQT.CLEAN_HEADER_FILES = $pri_clean_files\n";
$headers_pri_contents .= "SYNCQT.INJECTIONS = $pri_injections\n";
diff --git a/config_help.txt b/config_help.txt
index 3e2c0c61b0..d15e113b9a 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -95,6 +95,8 @@ Build options:
-optimized-tools ..... Build optimized host tools even in debug build [no]
-force-debug-info .... Create symbol files for release builds [no]
-separate-debug-info . Split off debug information to separate files [no]
+ -gdb-index ........... Index the debug info to speed up GDB
+ [no; auto if -developer-build with debug info]
-strip ............... Strip release binaries of unneeded symbols [yes]
-force-asserts ....... Enable Q_ASSERT even in release builds [no]
-developer-build ..... Compile and link Qt for developing Qt itself
diff --git a/configure b/configure
index 9757254097..2830a1b189 100755
--- a/configure
+++ b/configure
@@ -305,7 +305,7 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
BUILD_ON_MAC=no
-if [ -d /System/Library/Frameworks/Carbon.framework ]; then
+if [ -d /System/Library/Frameworks/Cocoa.framework ]; then
BUILD_ON_MAC=yes
fi
if [ "$OSTYPE" = "msys" ]; then
diff --git a/configure.json b/configure.json
index 2e606ad1ad..4dcff122bd 100644
--- a/configure.json
+++ b/configure.json
@@ -14,7 +14,8 @@
"src/xml",
"src/widgets",
"src/printsupport",
- "src/plugins/sqldrivers"
+ "src/plugins/sqldrivers",
+ "src/testlib"
],
"commandline": {
@@ -78,6 +79,7 @@
"force-debug-info": { "type": "boolean", "name": "force_debug_info" },
"force-pkg-config": { "type": "void", "name": "pkg-config" },
"framework": "boolean",
+ "gdb-index": { "type": "boolean", "name": "gdb_index" },
"gcc-sysroot": "boolean",
"gcov": "boolean",
"gnumake": { "type": "boolean", "name": "GNUmake" },
diff --git a/configure.pri b/configure.pri
index 494507830b..87f9e38152 100644
--- a/configure.pri
+++ b/configure.pri
@@ -696,10 +696,14 @@ defineReplace(printHostPaths) {
defineTest(qtConfOutput_preparePaths) {
isEmpty(config.input.prefix) {
- $$qtConfEvaluate("features.developer-build"): \
+ $$qtConfEvaluate("features.developer-build") {
config.input.prefix = $$QT_BUILD_TREE # In Development, we use sandboxed builds by default
- else: \
- config.input.prefix = /usr/local/Qt-$$[QT_VERSION]
+ } else {
+ win32: \
+ config.input.prefix = C:/Qt/Qt-$$[QT_VERSION]
+ else: \
+ config.input.prefix = /usr/local/Qt-$$[QT_VERSION]
+ }
have_prefix = false
} else {
config.input.prefix = $$absolute_path($$config.input.prefix, $$OUT_PWD)
diff --git a/dist/changes-5.11.0 b/dist/changes-5.11.0
new file mode 100644
index 0000000000..7f3bdf4b9b
--- /dev/null
+++ b/dist/changes-5.11.0
@@ -0,0 +1,399 @@
+Qt 5.11 introduces many new features and improvements as well as bugfixes
+over the 5.10.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.11 series is binary compatible with the 5.10.x series.
+Applications compiled for 5.10 will continue to run with 5.11.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+ - [QTBUG-63150] Characters invalid in XML, such as 0x0 or 0xfffe, as well
+ as strings containing unmatched UTF-16 surrogates are now suppressed
+ from the output of QXmlStreamWriter and cause the error flag to be set.
+
+ - Logging (including qDebug and qWarning):
+ * The QT_LOGGING_TO_CONSOLE environment variable has been deprecated.
+ Use the more specific QT_ASSUME_STDERR_HAS_CONSOLE or
+ QT_FORCE_STDERR_LOGGING, depending on your usecase.
+
+****************************************************************************
+* General Notes *
+****************************************************************************
+
+Deprecation Notices
+-------------------
+
+ - Microsoft Visual Studio 2013 (compiler version 12.0) is no longer
+ supported with this Qt version.
+ - macOS 10.10 is no longer supported with this Qt version.
+
+Third-Party Code
+----------------
+
+ - Removed attribution for QTemporaryFile: The original code got rewritten.
+ - Documented use of "Unicode Character Database (UCD)" in Qt Core.
+ - Clarified use of "Unicode Common Local Data Repository (CLDR)" in the
+ documentation. Also updated SPDX license name / ID.
+ - Sqlite was updated to version 3.23.1
+ - Libdbus-1 code in Qt D-Bus is now properly documented. The code is
+ licensed under AFL-2.1 OR GPL-2.0-or-later.
+ - Bundled HarfBuzz-NG copy updated to 1.7.4.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtCore
+------
+
+ - [QTBUG-38156] Apple Unified Logging is now supported on Apple platforms.
+
+ - QAbstractItemModel:
+ * Added QAbstractItemModel::checkIndex(), a debugging function for
+ QAbstractItemModel subclasses.
+
+ - QBitArray:
+ * Added fromBits(), which creates a QBitArray from a dense bit array,
+ and bits(), which returns that.
+
+ - QDateTime:
+ * [QTBUG-64401] Years up to 9999 can now be parsed without error
+ (previously 8000 and beyond were treated as invalid) in all formats
+ (not only in ISO format). Widgets handling dates now support dates to
+ 9999, likewise.
+ * [QTBUG-63072] When parsing dates and times from strings, fixed-width
+ date-time fields, such as a "dd" for day, QDateTime now rejects all
+ values that should be padded, rather than only doing so when the value
+ is a prefix of some value that would fill the field-width. Use a
+ single letter for the field, e.g. "d" for day, if you want to accept
+ short values. (QDateTimeEdit is not affected.)
+
+ - QJsonValue:
+ * fromVariant() conversion now converts from QUrl and QUuid using
+ special encoding forms to ensure best JSON compatibility.
+
+ - QLockFile:
+ * [QTBUG-63425] QLockFile can now properly conclude that a lock file
+ from a previous boot of the same device is stale and can be removed.
+ This is implemented only for Linux and Apple operating systems.
+
+ - QMetaObject:
+ * [QTBUG-66744] It is now possible to use template class instances
+ inheriting from a Q_GADGET in Qml.
+
+ - QSaveFile:
+ * [QTBUG-66268] Fixed an issue that would cause QSaveFile::commit() to
+ fail if Unix signals were delivered at the same time.
+
+ - QScopedPointer:
+ * Added get(), for compatibility with std::shared_ptr.
+
+ - QSharedPointer:
+ * Added get(), for compatibility with std::shared_ptr.
+
+ - QString:
+ * Added remove() overload taking QLatin1String.
+
+ - QStringBuilder:
+ * Added support for char16_t characters and strings.
+ * Added support for QStringView.
+
+ - QSysInfo:
+ * [QTBUG-63425] Added machineUniqueId() and bootUniqueId().
+
+ - QThread:
+ * [QTBUG-53357] Changed how Qt thread priorities are mapped to QNX
+ system thread priorities.
+
+ - QUrl:
+ * Fixed a bug in parsing IPv6 addresses with more than 4 hex digits in a
+ component.
+
+ - QUuid:
+ * Added a parameter to both toString() and toByteArray() to allow
+ controlling the use or not of the braces and dashes in the string
+ form.
+
+ - QVarLengthArray:
+ * Added rvalue overloads of prepend and insert.
+ * QVarLengthArray can now contain movable but non-copyable types, such as
+ std::unique_ptr.
+ * Added missing rvalue overload of operator+=() and operator<<().
+
+ - QVariant:
+ * Conversions of QDateTime to strings now contain the millisecond
+ components.
+
+ - QVector:
+ * Added rvalue overloads of prepend and insert.
+ * Added missing rvalue overload of operator+=() and operator<<()
+
+QtGui
+-----
+
+ - [QTBUG-59762] The QT_QPA_PLATFORM environment variable and the -platform
+ argument now support a list of platform plugins in prioritized
+ order. Platforms are separated by semicolons.
+
+ - QGuiApplication:
+ * Added fontChanged() signal.
+
+ - QIcon:
+ * [QTBUG-33123] Added fallbackSearchPaths() that will be used to find
+ icons missing in the current icon theme.
+
+ - QStaticText:
+ * [QTBUG-65836] Fixed explicitly set width not being respected.
+
+ - Text:
+ * [QTBUG-45957] Fixed a bug where QStaticText would not use the
+ QPainter's pen color for text when other text colors were also in use.
+ Internally this reserves QColor(0, 0, 0, 0) for use with QStaticText.
+ * Added QFontMetrics::horizontalAdvance() and
+ QFontMetricsF::horizontalAdvance() to replace the confusingly named
+ width() function. The latter has now been deprecated.
+ * [QTBUG-65345] Fixed an issue where changing the letter spacing type of
+ a QTextCharFormat would not cause its font to update.
+
+QtNetwork
+---------
+
+ - QHostAddress:
+ * Added isGlobal(), isLinkLocal(), isSiteLocal(),
+ isUniqueLocalUnicast(), and isBroadcast() classification functions to
+ complement isLoopback() and isMulticast().
+ * Fixed a bug in parsing IPv6 addresses with more than 4 hex digits in a
+ component.
+
+- QNetworkAccessManager:
+ * [QTBUG-61397] Added Http2DirectAttribute to enable 'direct' HTTP/2
+ protocol without ALPN/NPN and without protocol upgrade negotiations.
+ * [QTBUG-66913] Fixed a crash in HTTP/2 protocol handler (when server
+ responds with redirect or some error status code early, not wating
+ for a stream to be closed on client side).
+
+ - QNetworkInterface:
+ * Added type().
+ * Added maximumTransmissionUnit().
+ * Added preferredLifetime() and validityLifetime() to
+ QNetworkAddressEntry that report the remaining lifetime of the address
+ in the network interface.
+ * Added dnsEligibility() to QNetworkAddressEntry to indicate whether the
+ address is eligible or not for publication in DNS or similar
+ mechanisms.
+ * [QTBUG-67226] Fixed a regression in reporting the local address of a
+ point-to-point tunnel network interface.
+
+ - QSslSocket:
+ * [QTBUG-67584] When using OpenSSL 1.1, it now correctly sets protocol
+ version for QSsl::TlsV1_0, QSsl::TlsV1_1 and QSsl::TlsV1_2.
+ * [QTBUG-67112] On WinRT QSsl::SecureProtocols (default) now enables
+ TLSv1.1 and TLSv1.2.
+ * On WinRT QSsl::TlsV1SslV3 now enables SSLv3 and not just TLSv1.
+
+QtPrintSupport
+--------------
+
+ - Larger improvements to the CUPS print dialog.
+ * Added an advanced options tab in the printer properties, containing
+ all the printer options exposed through the CUPS API.
+ * Implemented support for installable options (add-ons to the printer).
+ * Added support for storing the selected settings between application runs.
+ * Added support for localized options in the advanced tab.
+ * The CUPS print dialog now supports printing of arbitrary ranges.
+
+ - QPrintDialog
+ * [QTBUG-58733] Fixed handling of custom page sizes.
+
+QtSql
+-----
+
+ - OCI support:
+ * [QTBUG-23] Added support for the TIMESTAMP data type.
+
+ - PostgreSQL support:
+ * [QTBUG-63714] Added support for forward-only queries (requires libpq
+ version 9.2 or later).
+ * Added support for multiple result sets.
+
+ - QSqlDatabase:
+ * [QTBUG-216] QSqlDatabase::database() will return an invalid
+ QSqlDatabase if the calling thread does not own the requested
+ QSqlDatabase.
+
+QtTest
+------
+
+ - The qtest_global.h header is now deprecated. Include qttestglobal.h
+ instead.
+ - Added QAbstractItemModelTester, a class to help testing item models.
+
+QtWidgets
+---------
+
+ - [QTBUG-62094] QDesktopWidget has been deprecated. Use the corresponding
+ QScreen functions instead.
+ - [QTBUG-49374][QTBUG-65237][QTBUG-49374] Fixed several issues related
+ to HiDPI support in QStyle.
+
+ - Item views:
+ * [QTBUG-48725] QTreeView now calls canFetchMore() and fetchMore() when
+ the bottom of the QTreeView is scrolled to.
+ * [QTBUG-65082] Add ability to show QJsonValue::Bool/Double to
+ QTreeView, QTableView and QListView.
+
+ - QAbstractItemModel:
+ * Implemented improved support for the optional "role" parameter in the
+ "dataChanged" signal.
+
+ - QColorDialog:
+ * [QTBUG-64500] Fixed persistence of custom colors when relaunching an
+ application.
+
+ - QHeaderView:
+ * Flat treeviews can now allow the user to move the first column (like
+ in Qt 4.x) using the new method QHeaderView::setFirstSectionMovable().
+ * MinimumSectionSize/MaximumSectionSize is now respected when calling
+ resizeSection().
+
+ - QLineEdit:
+ * Implemented quick text selection by mouse in QLineEdit.
+ * Placeholder text is now used as accessible description if the latter
+ has not been set.
+
+ - QListView:
+ * QListView now honors css :first/:middle/:last Pseudo-States.
+
+ - QMenu:
+ * [QTBUG-25669] Fixed a bug in QMenu that caused QMenuBar::triggered() to
+ be fired multiple times.
+
+ - QMenuBar:
+ * Added overloads of addAction() using Qt 5 signals and slots.
+
+ - QStandardItemModel:
+ * [QTBUG-45114][QTBUG-10872] Fixed setItemData() incorrectly deleting
+ unmodified data. That behavior is not following QAbstractItemModel's
+ documented behavior which is no modification of data not provided in
+ parameter.
+
+ - QStyle:
+ * [QTBUG-53094] Added SH_ComboBox_AllowWheelScrolling as a style hint to
+ enable/disable the use of the mouse wheel in a QComboBox. This
+ defaults to true in all styles except the macOS one so there is no
+ change in existing behavior.
+
+ - QTextEdit/QPlainTextEdit
+ * [QTBUG-63868] context menus will now open on right mouse click even if
+ the focus policy is Qt::NoFcous (allowing text copy).
+
+ - QTreeWidgetItem:
+ * QTreeWidgetItem::insertChildren now ignores insertions happening at
+ invalid indices, for consistency with QTreeWidgetItem::insertChild.
+
+****************************************************************************
+* Platform-specific Changes *
+****************************************************************************
+
+Android
+-------
+
+ - The application and dependent Qt libraries are now loaded on the same
+ thread as main() is run on, ensuring that global static initializers,
+ constructor functions, and main() are all run on the same thread. The
+ same applies during application shutdown, for destructors of global
+ objects, and destructor functions.
+
+Linux/EGLFS
+-----------
+
+ - [QTBUG-63088] The DRM+GBM backend now exposes the DRM/GBM device handle
+ under the key "dri_fd", queriable via nativeResourceForIntegration().
+
+Linux/XCB
+---------
+
+ - [QTBUG-56452] Added missing dead key symbols, enabling their use with
+ the "compose" input module.
+ - Added support for flatpak portals. Flatpak is a software utility for
+ software deployment and package management. It provides a sandbox
+ environment in which users can run applications in isolation from the
+ rest of the system. To communicate with the system flatpak uses portals,
+ which are designed to be a bridge between sandboxed applications and
+ desktop/system running on user's computer. Flatpak runs automatically
+ this as service, called xdg-desktop-portal, which exports portals on DBus
+ and which are by default visible to all applications running under
+ Flatpak.
+ - [QTBUG-44938] Qt now falls back to X11 core keycode information if an XKB
+ keymap could not be determined through the connection.
+
+ - ibus:
+ * Support ForwardKeyEvent signal
+
+Windows
+-------
+
+ - [QTPM-487][QTBUG-53024][QTBUG-43190][QTBUG-61926][QTBUG-38499]
+ [QTBUG-38337][QTBUG-38501][QTBUG-38502][QTBUG-38504][QTBUG-38505]
+ [QTBUG-38507] The Windows Accessibility back end, formerly based on
+ Microsoft Active Accessibility, was replaced with a new implementation
+ based on Microsoft UI Automation.
+
+ - [QTBUG-44594] Added support for End-User Defined Characters in Qt.
+
+iOS
+---
+
+ - [QTBUG-59042] The Apple Pencil now generates QTabletEvents, with the
+ complete feature set (tilt, rotation, pressure).
+
+macOS
+-----
+
+ - QMacStyle does no longer depend on HITheme — or Carbon for that matter.
+ Its implementation now relies exclusively on AppKit and custom code for
+ rendering and pixel metrics.
+
+****************************************************************************
+* Tools *
+****************************************************************************
+
+configure & build system
+------------------------
+
+ - [QTBUG-61260] Fixed build with -sanitize address.
+ - [QTBUG-61373][Windows] Restored default -prefix to C:\Qt\Qt-<version>\.
+ - [QTBUG-66355] pkg-config is now tried first to find system pcre2-16.
+ - [QTBUG-66675] Fixed -debug-and-release builds with qtquickcompiler.
+ - [Windows] OpenSSL 1.1 detection is now automatic.
+ - [X11] The -xkb-config-root command line switch has been removed as it
+ is no longer needed when configuring with -qt-xkbcommon-x11.
+ - Added the -gdb-index option to speed up debugging with GDB.
+ - More Qt features were made optional as part of the Qt Lite project.
+ - Removed compatibility of the modules with CMake < 3.1.
+
+qmake
+-----
+
+ - [QTBUG-35131][Xcode] Fixed build breakage when an extra compiler's
+ output directory (OBJECTS_DIR, MOC_DIR, etc.) contains "/../".
+ - [QTBUG-45211][iOS] Fixed building of QML based test cases.
+ - [QTBUG-66265][VS2017] Fixed building projects with Windows 8.1 SDK.
+ - [QTBUG-66770][Android][x86] The clang makespec now adds -mstackrealign.
+ - [QTBUG-67011] Fixed immediate RESOURCES when using an absolute RCC_DIR.
+ - [QTBUG-67286][Darwin] Fixed error messages when SDK cannot be resolved.
+ - [Darwin] Fixed the selected SDK's compilers not being used for plain C
+ sources.
+ - [Darwin] Fixed QMAKE_BUNDLE_DATA with extra compiler generated files.
diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf
index a18396876d..dbbccd0445 100644
--- a/doc/global/config.qdocconf
+++ b/doc/global/config.qdocconf
@@ -3,7 +3,7 @@
dita.metadata.default.author = Qt Project
dita.metadata.default.permissions = all
dita.metadata.default.publisher = Qt Project
-dita.metadata.default.copyryear = 2017
+dita.metadata.default.copyryear = 2018
dita.metadata.default.copyrholder = The Qt Company Ltd
dita.metadata.default.audience = programmer
diff --git a/doc/global/html-footer-online.qdocconf b/doc/global/html-footer-online.qdocconf
index d6cf5d2122..f2631555c1 100644
--- a/doc/global/html-footer-online.qdocconf
+++ b/doc/global/html-footer-online.qdocconf
@@ -78,7 +78,7 @@ HTML.footer += \
" <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \
" <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \
" <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \
- " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2017 The Qt Company</a></li>\n" \
+ " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2018 The Qt Company</a></li>\n" \
" </ul>\n" \
"</div>\n" \
"</div>\n" \
diff --git a/doc/global/html-footer.qdocconf b/doc/global/html-footer.qdocconf
index 5a0fbd85e1..9957e71f20 100644
--- a/doc/global/html-footer.qdocconf
+++ b/doc/global/html-footer.qdocconf
@@ -8,7 +8,7 @@ HTML.footer = \
"</div>\n" \
"<div class=\"footer\">\n" \
" <p>\n" \
- " <acronym title=\"Copyright\">&copy;</acronym> 2017 The Qt Company Ltd.\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \
" their respective owners.<br>" \
" The documentation provided herein is licensed under the terms of the" \
diff --git a/doc/global/qt-module-defaults-online.qdocconf b/doc/global/qt-module-defaults-online.qdocconf
index 15c193d698..1bed0c7934 100644
--- a/doc/global/qt-module-defaults-online.qdocconf
+++ b/doc/global/qt-module-defaults-online.qdocconf
@@ -5,7 +5,7 @@
HTML.footer = \
" </div>\n" \
" <p class=\"copy-notice\">\n" \
- " <acronym title=\"Copyright\">&copy;</acronym> 2017 The Qt Company Ltd.\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \
" their respective owners. " \
" The documentation provided herein is licensed under the terms of the" \
diff --git a/doc/src/images/dirview-example.png b/doc/src/images/dirview-example.png
index 6412ead5b2..deb06267f6 100644
--- a/doc/src/images/dirview-example.png
+++ b/doc/src/images/dirview-example.png
Binary files differ
diff --git a/doc/src/images/dynamiclayouts-example.png b/doc/src/images/dynamiclayouts-example.png
new file mode 100644
index 0000000000..b26d3725cc
--- /dev/null
+++ b/doc/src/images/dynamiclayouts-example.png
Binary files differ
diff --git a/doc/src/images/findfiles-example.png b/doc/src/images/findfiles-example.png
index acb5ea1abf..cf3885c015 100644
--- a/doc/src/images/findfiles-example.png
+++ b/doc/src/images/findfiles-example.png
Binary files differ
diff --git a/doc/src/images/transitions.png b/doc/src/images/transitions.png
new file mode 100644
index 0000000000..b29466f5ab
--- /dev/null
+++ b/doc/src/images/transitions.png
Binary files differ
diff --git a/examples/widgets/animation/sub-attaq/mainwindow.cpp b/examples/widgets/animation/sub-attaq/mainwindow.cpp
index 106404682d..b08a7d9f98 100644
--- a/examples/widgets/animation/sub-attaq/mainwindow.cpp
+++ b/examples/widgets/animation/sub-attaq/mainwindow.cpp
@@ -84,8 +84,13 @@ MainWindow::MainWindow() : QMainWindow(0)
view->setAlignment(Qt::AlignLeft | Qt::AlignTop);
scene->setupScene(newAction, quitAction);
#ifndef QT_NO_OPENGL
- view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+ QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
+ if (glWidget->context()->isValid()) {
+ view->setViewport(glWidget);
+ } else {
+ qWarning("Unable to create an Open GL context with sample buffers, not using Open GL.");
+ delete glWidget;
+ }
#endif
-
setCentralWidget(view);
}
diff --git a/examples/widgets/doc/src/addressbook-tutorial.qdoc b/examples/widgets/doc/src/addressbook-tutorial.qdoc
index 31d1d64dac..1f6966e8ae 100644
--- a/examples/widgets/doc/src/addressbook-tutorial.qdoc
+++ b/examples/widgets/doc/src/addressbook-tutorial.qdoc
@@ -80,7 +80,7 @@
/*!
\example tutorials/addressbook/part1
\title Part 1 - Designing the User Interface
-
+ \brief Describes how to code the user interface of the Address Book Example.
This first part covers the design of the basic graphical user
interface (GUI) for our address book application.
@@ -232,6 +232,7 @@
/*!
\example tutorials/addressbook/part2
\title Part 2 - Adding Addresses
+ \brief Describes the code for inserting records in the Address Book Example.
The next step in creating the address book is to implement some
user interactions.
@@ -381,9 +382,10 @@
/*!
\example tutorials/addressbook/part3
\title Part 3 - Navigating between Entries
+ \brief Explains the code that enables navigating the contacts.
The address book is now about half complete. We should add the
- capability to navigate among the contacts, but first we must
+ capability to navigate the contacts, but first we must
decide what sort of a data structure we need for containing these
contacts.
@@ -496,6 +498,7 @@
/*!
\example tutorials/addressbook/part4
\title Part 4 - Editing and Removing Addresses
+ \brief Explains how to add edit and remove functionality.
Now we look at ways to modify the contents of contacts stored in
the address book.
@@ -628,6 +631,7 @@
/*!
\example tutorials/addressbook/part5
\title Part 5 - Adding a Find Function
+ \brief Describes how to add a find function.
Here we look at ways to locate contacts and addresses in the
address book.
@@ -770,6 +774,7 @@
/*!
\example tutorials/addressbook/part6
\title Part 6 - Loading and Saving
+ \brief Describes how to add save and load functionality.
This part covers the Qt file handling features we use to write
loading and saving routines for the address book.
@@ -890,6 +895,7 @@
/*!
\example tutorials/addressbook/part7
\title Part 7 - Additional Features
+ \brief Describes how to export data in VCard format.
This part covers some additional features that make the address
book more convenient for the frequent user.
diff --git a/examples/widgets/doc/src/dirview.qdoc b/examples/widgets/doc/src/dirview.qdoc
index 3d58553b8d..d9a16fa58d 100644
--- a/examples/widgets/doc/src/dirview.qdoc
+++ b/examples/widgets/doc/src/dirview.qdoc
@@ -31,8 +31,38 @@
\ingroup examples-itemviews
\brief This example demonstrates the usage of a tree view.
- \brief The Dir View example shows a tree view onto the local filing system. It uses the
- QFileSystemModel class to provide file and directory information.
+ The Dir View example shows a tree view of the local file
+ system. It uses the QFileSystemModel class to provide file
+ and directory information.
- \image dirview-example.png
+ \borderedimage dirview-example.png
+
+ The example supports a number of command line options.
+ These options include:
+ \list
+ \li Application description
+ \li -help option
+ \li -version option
+ \li if the optionc {-c} is specified, the application will not
+ use custom directory options
+ \endlist
+
+ \quotefromfile itemviews/dirview/main.cpp
+ \skipto QCommandLineParser parser
+ \printuntil parser.positionalArguments
+
+ Declares a QFileSystemModel as data model for viewing
+ the local file system. QFileSystem works with a cache, that is,
+ it is updated continually with QFileSystemWatcher on that folder.
+
+ \skipto QFileSystemModel
+ \printuntil tree.setModel
+
+ Creates a model/view implementation called \c tree
+ for viewing the filesystem.
+
+ \skipto tree.setAnimated(false)
+ \printuntil tree.setWindowTitle
+
+ Sets some formatting options for \c tree.
*/
diff --git a/examples/widgets/doc/src/dynamiclayouts.qdoc b/examples/widgets/doc/src/dynamiclayouts.qdoc
index be59aa6ab9..0b9d43c98e 100644
--- a/examples/widgets/doc/src/dynamiclayouts.qdoc
+++ b/examples/widgets/doc/src/dynamiclayouts.qdoc
@@ -34,7 +34,82 @@
applications. The widget placement depends on whether \c Horizontal or \c
Vertical is chosen.
+ \borderedimage dynamiclayouts-example.png
For more information, visit the \l{Layout Management} page.
+ \section1 Dialog Constructor
+
+ To begin with, the application creates the UI components by calling the
+ following methods:
+
+ \list
+ \li createRotatableGroupBox()
+ \li createOptionsGroupBox()
+ \li createButtonBox()
+ \endlist
+
+ It then adds the UI components to a GridLayout (\c mainLayout).
+
+ Finally, \c Dialog::rotateWidgets() is called.
+
+ \quotefromfile layouts/dynamiclayouts/dialog.cpp
+ \skipuntil createRotatableGroupBox
+ \printuntil setWindowTitle
+
+ \section1 Creating the Main Widgets
+
+ The \c createRotatableGroupBox() method creates a rotatable group box,
+ then adds a series of widgets:
+
+ \list
+ \li QSpinBox
+ \li QSlider
+ \li QDial
+ \li QProgressBar
+ \endlist
+
+ It goes on to add signals and slots to each widget, and assigns
+ a QGridLayout called \a rotatableLayout.
+
+ \skipto Dialog::createRotatableGroupBox
+ \printuntil /^\}/
+
+ \section1 Adding Options
+
+ \c createOptionsGroupBox() creates the following widgets:
+ \list
+ \li \c optionsGroupBox
+ \li \c buttonsOrientationLabel
+ \li \c buttonsOrientationComboBox. The orientation of the ComboBox is either
+ \c horizontal (default value) or \c vertical. These two values
+ are added during the startup of the application. It is not possible
+ to leave the option empty.
+ \endlist
+
+ \skipto Dialog::createOptionsGroupBox()
+ \printuntil /^\}/
+
+ \section1 Adding Buttons
+
+ createButtonBox() constructs a QDialogButtonBox called \c buttonBox
+ to which are added a \c closeButton, a \c helpButton and a
+ \c rotateWidgetsButton.
+ It then assigns a signal and a slot to each button in \c buttonBox.
+
+ \skipto Dialog::createButtonBox()
+ \printuntil /^\}/
+
+
+ \section1 Rotating the Widgets
+
+ Removes the current widgets and activates the next widget.
+
+ \quotefromfile layouts/dynamiclayouts/dialog.cpp
+ \skipto Dialog::rotateWidgets()
+ \printuntil rotatableLayout->addWidget(rotatableWidgets[i]
+ \printuntil }
+ \printuntil }
+
\include examples-run.qdocinc
*/
+
diff --git a/examples/widgets/doc/src/eventtransitions.qdoc b/examples/widgets/doc/src/eventtransitions.qdoc
index 2c59d0863d..e74831b14b 100644
--- a/examples/widgets/doc/src/eventtransitions.qdoc
+++ b/examples/widgets/doc/src/eventtransitions.qdoc
@@ -29,17 +29,29 @@
\example statemachine/eventtransitions
\title Event Transitions Example
- \brief The Event Transitions example shows how to use event transitions, a
- feature of \l{The State Machine Framework}.
+ \brief The Event Transitions example shows how to use event transitions,
+ a feature of \l{The State Machine Framework}.
+
+ The Event Transitions Example illustrates how states change when a
+ user enters or leaves the area of a button. The states are handled by
+ a QStateMachine object. The screen consists of a QVBoxLayout with a
+ central button.
+
+ When the mouse is outside the button, the text in the button displays
+ "Outside". When the mouse enters the button, it displays "Inside".
+
+ \borderedimage transitions.png
\snippet statemachine/eventtransitions/main.cpp 0
The \c Window class's constructors begins by creating a button.
+ This button is added to \c layout, which is a QVBoxLayout object.
+ Then two states are created: \c s1 is the state
+ "Outside", and \c s2 is the state "Inside".
\snippet statemachine/eventtransitions/main.cpp 1
- Two states, \c s1 and \c s2, are created; upon entry they will assign
- "Outside" and "Inside" to the button's text, respectively.
+ State \c s1 is the state "Outside" and state \c s2 is state "Inside".
\snippet statemachine/eventtransitions/main.cpp 2
@@ -54,11 +66,11 @@
\snippet statemachine/eventtransitions/main.cpp 4
- Next, the state \c s3 is created. \c s3 will be entered when the button
+ Next, state \c s3 is created. \c s3 will be entered when the button
receives an event of type QEvent::MouseButtonPress and the state machine
is in state \c s2. When the button receives an event of type
QEvent::MouseButtonRelease and the state machine is in state \c s3, the
- machine will transition back to state \c s2.
+ machine will revert to state \c s2.
\snippet statemachine/eventtransitions/main.cpp 5
@@ -67,6 +79,7 @@
\snippet statemachine/eventtransitions/main.cpp 6
- The main() function constructs a Window object and shows it.
+ The main() function constructs a Window object that displays the QVBoxLayout
+ object \c layout with its \c button.
*/
diff --git a/examples/widgets/doc/src/findfiles.qdoc b/examples/widgets/doc/src/findfiles.qdoc
index a2eb326519..ad39b003ae 100644
--- a/examples/widgets/doc/src/findfiles.qdoc
+++ b/examples/widgets/doc/src/findfiles.qdoc
@@ -30,43 +30,74 @@
\title Find Files Example
\ingroup examples-dialogs
- \brief The Find Files example shows how to use QProgressDialog to provide
- feedback on the progress of a slow operation. The example also
- shows how to use QFileDialog to facilitate browsing, how to use
- QTextStream's streaming operators to read a file, and how to use
- QTableWidget to provide standard table display facilities for
- applications. In addition, files can be opened using the
- QDesktopServices class.
+ \brief A dialog for finding files in a specified folder
+
+ The Find Files application allows the user to search for files in a
+ specified directory, matching a given file name or wildcard,
+ and containing a specified string (if filled in). The search
+ result is displayed in a table containing the names of the files
+ and their sizes. The application also shows the number of files found.
+
+ The Find Files example illustrates the use of several classes:
+
+ \table
+ \row
+ \li QProgressDialog
+ \li Provide feedback on the progress of a search operation
+ \row
+ \li QFileDialog
+ \li Browse through a file list
+ \row
+ \li QTextStream
+ \li Use stream operators to read a file
+ \row
+ \li QTableWidget
+ \li Browse through the search results in a table
+ \row
+ \li QDesktopServices
+ \li Open files in the result list in a suitable application
+ \endtable
\image findfiles-example.png Screenshot of the Find Files example
- With the Find Files application the user can search for files in a
- specified directory, matching a specified file name (using wild
- cards if appropriate) and containing a specified text.
-
- The user is provided with a \uicontrol Browse option, and the result of
- the search is displayed in a table with the names of the files
- found and their sizes. In addition the application provides a
- total count of the files found.
\section1 Window Class Definition
The \c Window class inherits QWidget, and is the main application
- widget. It shows the search options, and displays the search
+ widget. It shows the search options and displays the search
results.
\snippet dialogs/findfiles/window.h 0
- We need two private slots: The \c browse() slot is called whenever
- the user wants to browse for a directory to search in, and the \c
- find() slot is called whenever the user requests a search to be
- performed by pressing the \uicontrol Find button.
-
- In addition we declare several private functions: We use the \c
- findFiles() function to search for files matching the user's
- specifications, we call the \c showFiles() function to display the
- results, and we use \c createButton(), \c createComboBox() and \c
- createFilesTable() when we are constructing the widget.
+ The application has two private slots:
+ \table
+ \row
+ \li The \c browse() slot
+ \li Called whenever the user wants to browse for a directory to search in
+ \row
+ \li The \c find() slot
+ \li Called whenever the user launches a search with the \uicontrol Find button
+ \endtable
+
+ In addition we declare several private functions:
+
+ \table
+ \row
+ \li findFiles()
+ \li Search for files matching the search parameters
+ \row
+ \li showFiles()
+ \li Display the search result
+ \row
+ \li ceateButton()
+ \li Construct the widget
+ \row
+ \li createComboBox()
+ \li Construct the widget
+ \row
+ \li createFilesTable()
+ \li Construct the widget
+ \endtable
\section1 Window Class Implementation
@@ -103,11 +134,11 @@
Here we use the static QFileDialog::getExistingDirectory()
function which returns an existing directory selected by the
user. Then we display the directory in the directory combobox
- using the QComboBox::addItem() function, and updates the current
+ using the QComboBox::addItem() function and update the current
index.
QComboBox::addItem() adds an item to the combobox with the given
- text (if it is not already present in the list), and containing
+ text (if not already present in the list), and containing
the specified userData. The item is appended to the list of
existing items.
@@ -118,13 +149,13 @@
First we eliminate any previous search results by setting the
table widgets row count to zero. Then we retrieve the
- specified file name, text and directory path from the respective
+ specified file name, text, and directory path from the respective
comboboxes.
\snippet dialogs/findfiles/window.cpp 4
We use the directory's path to create a QDir; the QDir class
- provides access to directory structures and their contents.
+ provides access to the directory structure and its contents.
We use QDirIterator to iterate over the files that match the
specified file name and build a QStringList of paths.
@@ -144,15 +175,11 @@
In the private \c findFiles() function we search through a list of
files, looking for the ones that contain a specified text. This
can be a very slow operation depending on the number of files as
- well as their sizes. In case there are a large number of files, or
- there exists some large files on the list, we provide a
- QProgressDialog.
-
- The QProgressDialog class provides feedback on the progress of a
- slow operation. It is used to give the user an indication of how
- long an operation is going to take, and to demonstrate that the
- application has not frozen. It can also give the user an
- opportunity to abort the operation.
+ well as their sizes. QProgressDialog displays a progress dialog
+ if the application has to search through a large number of files,
+ or if some of the files have a large size. QProgressDialog can
+ also allow the user to abort the operation if it takes too much
+ time.
\snippet dialogs/findfiles/window.cpp 6
diff --git a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc b/examples/widgets/doc/src/graphicsview-flowlayout.qdoc
index e5080c672d..13819f5499 100644
--- a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc
+++ b/examples/widgets/doc/src/graphicsview-flowlayout.qdoc
@@ -36,5 +36,17 @@
\image graphicsflowlayout-example.png
- See the \l{Flow Layout Example} for a corresponding widget-based example.
+ This example uses a Graphics View to display the widget, which is a more
+ customizable approach than displaying the flow layout in the application
+ window (See \l {Flow Layout Example}).
+
+ Graphics View Flow Layout snippet:
+
+ \snippet graphicsview/flowlayout/main.cpp 1
+
+ Flow Layout Example snippet:
+
+ \snippet layouts/flowlayout/main.cpp 1
+
+
*/
diff --git a/examples/widgets/graphicsview/flowlayout/main.cpp b/examples/widgets/graphicsview/flowlayout/main.cpp
index 850302e175..74c03b9bce 100644
--- a/examples/widgets/graphicsview/flowlayout/main.cpp
+++ b/examples/widgets/graphicsview/flowlayout/main.cpp
@@ -47,7 +47,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
+//! [1]
#include "window.h"
#include <QApplication>
@@ -68,3 +68,4 @@ int main(int argc, char *argv[])
return app.exec();
}
+//! [1]
diff --git a/examples/widgets/itemviews/frozencolumn/main.cpp b/examples/widgets/itemviews/frozencolumn/main.cpp
index 5a4d3e0f42..6f2b4a8d71 100644
--- a/examples/widgets/itemviews/frozencolumn/main.cpp
+++ b/examples/widgets/itemviews/frozencolumn/main.cpp
@@ -51,6 +51,7 @@
#include <QApplication>
#include <QStandardItemModel>
#include <QFile>
+#include <QTextStream>
#include "freezetablewidget.h"
@@ -63,14 +64,16 @@ int main(int argc, char* argv[])
QFile file(":/grades.txt");
if (file.open(QFile::ReadOnly)) {
- QString line = file.readLine(200);
+ QTextStream stream(&file);
+
+ QString line = stream.readLine();
QStringList list = line.simplified().split(',');
model->setHorizontalHeaderLabels(list);
int row = 0;
QStandardItem *newItem = 0;
- while (file.canReadLine()) {
- line = file.readLine(200);
+ while (!stream.atEnd()) {
+ line = stream.readLine();
if (!line.startsWith('#') && line.contains(',')) {
list = line.simplified().split(',');
for (int col = 0; col < list.length(); ++col){
diff --git a/examples/widgets/layouts/dynamiclayouts/dialog.cpp b/examples/widgets/layouts/dynamiclayouts/dialog.cpp
index 080d69204b..f46053372a 100644
--- a/examples/widgets/layouts/dynamiclayouts/dialog.cpp
+++ b/examples/widgets/layouts/dynamiclayouts/dialog.cpp
@@ -55,12 +55,12 @@
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
- createRotableGroupBox();
+ createRotatableGroupBox();
createOptionsGroupBox();
createButtonBox();
mainLayout = new QGridLayout;
- mainLayout->addWidget(rotableGroupBox, 0, 0);
+ mainLayout->addWidget(rotatableGroupBox, 0, 0);
mainLayout->addWidget(optionsGroupBox, 1, 0);
mainLayout->addWidget(buttonBox, 2, 0);
setLayout(mainLayout);
@@ -102,17 +102,17 @@ void Dialog::buttonsOrientationChanged(int index)
void Dialog::rotateWidgets()
{
- Q_ASSERT(rotableWidgets.count() % 2 == 0);
+ Q_ASSERT(rotatableWidgets.count() % 2 == 0);
- foreach (QWidget *widget, rotableWidgets)
- rotableLayout->removeWidget(widget);
+ foreach (QWidget *widget, rotatableWidgets)
+ rotatableLayout->removeWidget(widget);
- rotableWidgets.enqueue(rotableWidgets.dequeue());
+ rotatableWidgets.enqueue(rotatableWidgets.dequeue());
- const int n = rotableWidgets.count();
+ const int n = rotatableWidgets.count();
for (int i = 0; i < n / 2; ++i) {
- rotableLayout->addWidget(rotableWidgets[n - i - 1], 0, i);
- rotableLayout->addWidget(rotableWidgets[i], 1, i);
+ rotatableLayout->addWidget(rotatableWidgets[n - i - 1], 0, i);
+ rotatableLayout->addWidget(rotatableWidgets[i], 1, i);
}
}
@@ -123,23 +123,23 @@ void Dialog::help()
"dynamically."));
}
-void Dialog::createRotableGroupBox()
+void Dialog::createRotatableGroupBox()
{
- rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));
+ rotatableGroupBox = new QGroupBox(tr("Rotatable Widgets"));
- rotableWidgets.enqueue(new QSpinBox);
- rotableWidgets.enqueue(new QSlider);
- rotableWidgets.enqueue(new QDial);
- rotableWidgets.enqueue(new QProgressBar);
+ rotatableWidgets.enqueue(new QSpinBox);
+ rotatableWidgets.enqueue(new QSlider);
+ rotatableWidgets.enqueue(new QDial);
+ rotatableWidgets.enqueue(new QProgressBar);
- int n = rotableWidgets.count();
+ int n = rotatableWidgets.count();
for (int i = 0; i < n; ++i) {
- connect(rotableWidgets[i], SIGNAL(valueChanged(int)),
- rotableWidgets[(i + 1) % n], SLOT(setValue(int)));
+ connect(rotatableWidgets[i], SIGNAL(valueChanged(int)),
+ rotatableWidgets[(i + 1) % n], SLOT(setValue(int)));
}
- rotableLayout = new QGridLayout;
- rotableGroupBox->setLayout(rotableLayout);
+ rotatableLayout = new QGridLayout;
+ rotatableGroupBox->setLayout(rotatableLayout);
rotateWidgets();
}
@@ -154,8 +154,10 @@ void Dialog::createOptionsGroupBox()
buttonsOrientationComboBox->addItem(tr("Horizontal"), Qt::Horizontal);
buttonsOrientationComboBox->addItem(tr("Vertical"), Qt::Vertical);
- connect(buttonsOrientationComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(buttonsOrientationChanged(int)));
+ connect(buttonsOrientationComboBox,
+ QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this,
+ &Dialog::buttonsOrientationChanged);
optionsLayout = new QGridLayout;
optionsLayout->addWidget(buttonsOrientationLabel, 0, 0);
@@ -173,7 +175,9 @@ void Dialog::createButtonBox()
rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widgets"),
QDialogButtonBox::ActionRole);
- connect(rotateWidgetsButton, SIGNAL(clicked()), this, SLOT(rotateWidgets()));
- connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(helpButton, SIGNAL(clicked()), this, SLOT(help()));
+ connect(rotateWidgetsButton, &QPushButton::clicked, this, &Dialog::rotateWidgets);
+ connect(closeButton, &QPushButton::clicked, this, &Dialog::close);
+ connect(helpButton, &QPushButton::clicked, this, &Dialog::help);
}
+
+
diff --git a/examples/widgets/layouts/dynamiclayouts/dialog.h b/examples/widgets/layouts/dynamiclayouts/dialog.h
index 0ff0c12b38..923a6fe01b 100644
--- a/examples/widgets/layouts/dynamiclayouts/dialog.h
+++ b/examples/widgets/layouts/dynamiclayouts/dialog.h
@@ -76,12 +76,12 @@ private slots:
void help();
private:
- void createRotableGroupBox();
+ void createRotatableGroupBox();
void createOptionsGroupBox();
void createButtonBox();
- QGroupBox *rotableGroupBox;
- QQueue<QWidget *> rotableWidgets;
+ QGroupBox *rotatableGroupBox;
+ QQueue<QWidget *> rotatableWidgets;
QGroupBox *optionsGroupBox;
QLabel *buttonsOrientationLabel;
@@ -93,7 +93,7 @@ private:
QPushButton *rotateWidgetsButton;
QGridLayout *mainLayout;
- QGridLayout *rotableLayout;
+ QGridLayout *rotatableLayout;
QGridLayout *optionsLayout;
};
diff --git a/examples/widgets/layouts/flowlayout/main.cpp b/examples/widgets/layouts/flowlayout/main.cpp
index 99725195e5..bbc78ccda3 100644
--- a/examples/widgets/layouts/flowlayout/main.cpp
+++ b/examples/widgets/layouts/flowlayout/main.cpp
@@ -47,7 +47,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
+//! [1]
#include <QApplication>
#include "window.h"
@@ -59,3 +59,4 @@ int main(int argc, char *argv[])
window.show();
return app.exec();
}
+//! [1]
diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp
index 1e2f75b2a5..5a7b8fd9fe 100644
--- a/examples/widgets/painting/pathstroke/pathstroke.cpp
+++ b/examples/widgets/painting/pathstroke/pathstroke.cpp
@@ -87,10 +87,12 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
QRadioButton *bevelJoin = new QRadioButton(m_joinGroup);
QRadioButton *miterJoin = new QRadioButton(m_joinGroup);
+ QRadioButton *svgMiterJoin = new QRadioButton(m_joinGroup);
QRadioButton *roundJoin = new QRadioButton(m_joinGroup);
m_joinGroup->setTitle(tr("Join Style"));
bevelJoin->setText(tr("Bevel"));
miterJoin->setText(tr("Miter"));
+ svgMiterJoin->setText(tr("SvgMiter"));
roundJoin->setText(tr("Round"));
m_styleGroup = new QGroupBox(parent);
@@ -145,6 +147,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup);
joinGroupLayout->addWidget(bevelJoin);
joinGroupLayout->addWidget(miterJoin);
+ joinGroupLayout->addWidget(svgMiterJoin);
joinGroupLayout->addWidget(roundJoin);
QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup);
@@ -167,6 +170,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
+ connect(svgMiterJoin, SIGNAL(clicked()), m_renderer, SLOT(setSvgMiterJoin()));
connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
diff --git a/examples/widgets/painting/pathstroke/pathstroke.h b/examples/widgets/painting/pathstroke/pathstroke.h
index 71352c8cc2..7bc7e09003 100644
--- a/examples/widgets/painting/pathstroke/pathstroke.h
+++ b/examples/widgets/painting/pathstroke/pathstroke.h
@@ -92,6 +92,7 @@ public slots:
void setBevelJoin() { m_joinStyle = Qt::BevelJoin; update(); }
void setMiterJoin() { m_joinStyle = Qt::MiterJoin; update(); }
+ void setSvgMiterJoin() { m_joinStyle = Qt::SvgMiterJoin; update(); }
void setRoundJoin() { m_joinStyle = Qt::RoundJoin; update(); }
void setCurveMode() { m_pathMode = CurveMode; update(); }
diff --git a/examples/widgets/tools/i18n/languagechooser.cpp b/examples/widgets/tools/i18n/languagechooser.cpp
index 83aafe6b8a..58cf9d4047 100644
--- a/examples/widgets/tools/i18n/languagechooser.cpp
+++ b/examples/widgets/tools/i18n/languagechooser.cpp
@@ -70,7 +70,10 @@ LanguageChooser::LanguageChooser(const QString& defaultLang, QWidget *parent)
for (int i = 0; i < qmFiles.size(); ++i) {
QCheckBox *checkBox = new QCheckBox(languageName(qmFiles[i]));
qmFileForCheckBoxMap.insert(checkBox, qmFiles[i]);
- connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled()));
+ connect(checkBox,
+ QOverload<bool>::of(&QCheckBox::toggled),
+ this,
+ &LanguageChooser::checkBoxToggled);
if (languageMatch(defaultLang, qmFiles[i]))
checkBox->setCheckState(Qt::Checked);
groupBoxLayout->addWidget(checkBox, i / 2, i % 2);
@@ -84,8 +87,8 @@ LanguageChooser::LanguageChooser(const QString& defaultLang, QWidget *parent)
hideAllButton = buttonBox->addButton("Hide All",
QDialogButtonBox::ActionRole);
- connect(showAllButton, SIGNAL(clicked()), this, SLOT(showAll()));
- connect(hideAllButton, SIGNAL(clicked()), this, SLOT(hideAll()));
+ connect(showAllButton, &QAbstractButton::clicked, this, &LanguageChooser::showAll);
+ connect(hideAllButton, &QAbstractButton::clicked, this, &LanguageChooser::hideAll);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(groupBox);
diff --git a/examples/widgets/tools/i18n/mainwindow.cpp b/examples/widgets/tools/i18n/mainwindow.cpp
index d5de81cab7..6ebfddfa98 100644
--- a/examples/widgets/tools/i18n/mainwindow.cpp
+++ b/examples/widgets/tools/i18n/mainwindow.cpp
@@ -76,7 +76,7 @@ MainWindow::MainWindow()
centralWidget->setLayout(mainLayout);
exitAction = new QAction(tr("E&xit"), this);
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ connect(exitAction, &QAction::triggered, qApp, QApplication::quit);
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->setPalette(QPalette(Qt::red));
diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
index 67d0db4bed..8fbf143cbd 100644
--- a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
+++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
@@ -77,6 +77,13 @@
Q_DECLARE_METATYPE(QRegularExpression::MatchType)
+static QString rawStringLiteral(QString pattern)
+{
+ pattern.prepend(QLatin1String("R\"RX("));
+ pattern.append(QLatin1String(")RX\""));
+ return pattern;
+}
+
static QString patternToCode(QString pattern)
{
pattern.replace(QLatin1String("\\"), QLatin1String("\\\\"));
@@ -173,6 +180,29 @@ void PatternLineEdit::contextMenuEvent(QContextMenuEvent *event)
menu->popup(event->globalPos());
}
+class DisplayLineEdit : public QLineEdit
+{
+public:
+ explicit DisplayLineEdit(QWidget *parent = nullptr);
+};
+
+DisplayLineEdit::DisplayLineEdit(QWidget *parent) : QLineEdit(parent)
+{
+ setReadOnly(true);
+ QPalette disabledPalette = palette();
+ disabledPalette.setBrush(QPalette::Base, disabledPalette.brush(QPalette::Disabled, QPalette::Base));
+ setPalette(disabledPalette);
+
+#if QT_CONFIG(clipboard)
+ QAction *copyAction = new QAction(this);
+ copyAction->setText(RegularExpressionDialog::tr("Copy to clipboard"));
+ copyAction->setIcon(QIcon(QStringLiteral(":/images/copy.png")));
+ connect(copyAction, &QAction::triggered, this,
+ [this] () { QGuiApplication::clipboard()->setText(text()); });
+ addAction(copyAction, QLineEdit::TrailingPosition);
+#endif
+}
+
RegularExpressionDialog::RegularExpressionDialog(QWidget *parent)
: QDialog(parent)
{
@@ -230,6 +260,7 @@ void RegularExpressionDialog::refresh()
offsetSpinBox->setMaximum(qMax(0, text.length() - 1));
escapedPatternLineEdit->setText(patternToCode(pattern));
+ rawStringLiteralLineEdit->setText(rawStringLiteral(pattern));
setTextColor(patternLineEdit, subjectTextEdit->palette().color(QPalette::Text));
matchDetailsTreeWidget->clear();
@@ -322,15 +353,6 @@ void RegularExpressionDialog::refresh()
setUpdatesEnabled(true);
}
-void RegularExpressionDialog::copyEscapedPatternToClipboard()
-{
-#if QT_CONFIG(clipboard)
- QClipboard *clipboard = QGuiApplication::clipboard();
- if (clipboard)
- clipboard->setText(escapedPatternLineEdit->text());
-#endif
-}
-
void RegularExpressionDialog::setupUi()
{
QWidget *leftHalfContainer = setupLeftUi();
@@ -363,20 +385,9 @@ QWidget *RegularExpressionDialog::setupLeftUi()
patternLineEdit->setClearButtonEnabled(true);
layout->addRow(tr("&Pattern:"), patternLineEdit);
- escapedPatternLineEdit = new QLineEdit;
- escapedPatternLineEdit->setReadOnly(true);
- QPalette palette = escapedPatternLineEdit->palette();
- palette.setBrush(QPalette::Base, palette.brush(QPalette::Disabled, QPalette::Base));
- escapedPatternLineEdit->setPalette(palette);
-
-#if QT_CONFIG(clipboard)
- QAction *copyEscapedPatternAction = new QAction(this);
- copyEscapedPatternAction->setText(tr("Copy to clipboard"));
- copyEscapedPatternAction->setIcon(QIcon(QStringLiteral(":/images/copy.png")));
- connect(copyEscapedPatternAction, &QAction::triggered, this, &RegularExpressionDialog::copyEscapedPatternToClipboard);
- escapedPatternLineEdit->addAction(copyEscapedPatternAction, QLineEdit::TrailingPosition);
-#endif
-
+ rawStringLiteralLineEdit = new DisplayLineEdit;
+ layout->addRow(tr("&Raw string literal:"), rawStringLiteralLineEdit);
+ escapedPatternLineEdit = new DisplayLineEdit;
layout->addRow(tr("&Escaped pattern:"), escapedPatternLineEdit);
subjectTextEdit = new QPlainTextEdit;
diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.h b/examples/widgets/tools/regularexpression/regularexpressiondialog.h
index f7d64085fc..ba5b38b5e3 100644
--- a/examples/widgets/tools/regularexpression/regularexpressiondialog.h
+++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.h
@@ -74,13 +74,13 @@ public:
private:
void refresh();
- void copyEscapedPatternToClipboard();
void setupUi();
QWidget *setupLeftUi();
QWidget *setupRightUi();
void setResultUiEnabled(bool enabled);
QLineEdit *patternLineEdit;
+ QLineEdit *rawStringLiteralLineEdit;
QLineEdit *escapedPatternLineEdit;
QPlainTextEdit *subjectTextEdit;
diff --git a/header.BSD b/header.BSD
index aa400a469d..ca6777aca0 100644
--- a/header.BSD
+++ b/header.BSD
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
diff --git a/header.COMM b/header.COMM
index 1c8cb00e73..73512a57eb 100644
--- a/header.COMM
+++ b/header.COMM
@@ -1,7 +1,7 @@
/******************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) YYYY The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the <Fill> module.
**
diff --git a/header.FDL b/header.FDL
index 90195db138..ea0a503f9b 100644
--- a/header.FDL
+++ b/header.FDL
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
diff --git a/header.GPL b/header.GPL
index af4a1636b7..62651cb181 100644
--- a/header.GPL
+++ b/header.GPL
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
diff --git a/header.GPL-EXCEPT b/header.GPL-EXCEPT
index 26ed5a245a..4a6bb4cc00 100644
--- a/header.GPL-EXCEPT
+++ b/header.GPL-EXCEPT
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
diff --git a/header.LGPL b/header.LGPL
index 3c0d12810e..3ca3e49a1d 100644
--- a/header.LGPL
+++ b/header.LGPL
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
diff --git a/header.LGPL-NOGPL2 b/header.LGPL-NOGPL2
index 80b4449cbc..d7d0b9f68d 100644
--- a/header.LGPL-NOGPL2
+++ b/header.LGPL-NOGPL2
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) YYYY The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
diff --git a/header.LGPL-ONLY b/header.LGPL-ONLY
index 9a676032e0..70cf167575 100644
--- a/header.LGPL-ONLY
+++ b/header.LGPL-ONLY
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) YYYY The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
**
diff --git a/header.LGPL3 b/header.LGPL3
index d9a65c2e44..0940ad9e17 100644
--- a/header.LGPL3
+++ b/header.LGPL3
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) YYYY The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
**
diff --git a/header.LGPL3-COMM b/header.LGPL3-COMM
index b5dc15d384..409a09b67f 100644
--- a/header.LGPL3-COMM
+++ b/header.LGPL3-COMM
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) YYYY The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the FOO module of the Qt Toolkit.
**
diff --git a/mkspecs/android-clang/qmake.conf b/mkspecs/android-clang/qmake.conf
index fae2c8ebd9..b665000d00 100644
--- a/mkspecs/android-clang/qmake.conf
+++ b/mkspecs/android-clang/qmake.conf
@@ -42,7 +42,6 @@ ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$A
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so
ANDROID_CXX_STL_LIBS = -lc++
-QMAKE_ARM_CFLAGS_RELEASE = -Oz
-QMAKE_ARM_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -Oz
+QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
include(../common/android-base-tail.conf)
diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf
index c8145ae66b..e72c802405 100644
--- a/mkspecs/android-g++/qmake.conf
+++ b/mkspecs/android-g++/qmake.conf
@@ -31,7 +31,4 @@ else: \
LIBGCC_PATH_FULL = $$system("$$QMAKE_CXX -print-libgcc-file-name")
ANDROID_SOURCES_CXX_STL_LIBDIR += $$dirname(LIBGCC_PATH_FULL)
-QMAKE_ARM_CFLAGS_RELEASE = -Os
-QMAKE_ARM_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -Os
-
include(../common/android-base-tail.conf)
diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf
index 160caf011f..7c3ae9566a 100644
--- a/mkspecs/common/android-base-tail.conf
+++ b/mkspecs/common/android-base-tail.conf
@@ -14,8 +14,7 @@ else: equals(ANDROID_TARGET_ARCH, armeabi): \
QMAKE_CFLAGS_WARN_ON = -Wall -W
QMAKE_CFLAGS_WARN_OFF =
equals(ANDROID_TARGET_ARCH, armeabi-v7a) | equals(ANDROID_TARGET_ARCH, armeabi) {
- QMAKE_CFLAGS_RELEASE = $$QMAKE_ARM_CFLAGS_RELEASE
- QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_ARM_CFLAGS_RELEASE_WITH_DEBUGINFO
+ CONFIG += optimize_size
QMAKE_CFLAGS_DEBUG = -g -marm -O0
equals(ANDROID_TARGET_ARCH, armeabi):if(equals(NDK_TOOLCHAIN_VERSION, 4.8)|equals(NDK_TOOLCHAIN_VERSION, 4.9)) {
DEFINES += QT_OS_ANDROID_GCC_48_WORKAROUND
@@ -23,13 +22,6 @@ equals(ANDROID_TARGET_ARCH, armeabi-v7a) | equals(ANDROID_TARGET_ARCH, armeabi)
QMAKE_CFLAGS_RELEASE += -mthumb
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -mthumb
}
-
- # Don't override our options with -O3
- QMAKE_CFLAGS_OPTIMIZE_FULL =
-} else {
- QMAKE_CFLAGS_RELEASE = -O2
- QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -O2
- QMAKE_CFLAGS_DEBUG = -g
}
QMAKE_CFLAGS_SHLIB = -fPIC
diff --git a/mkspecs/features/configure_base.prf b/mkspecs/features/configure_base.prf
index e870e2ee10..73e0273f18 100644
--- a/mkspecs/features/configure_base.prf
+++ b/mkspecs/features/configure_base.prf
@@ -23,9 +23,29 @@ QMAKE_MAKE_NAME = $$basename(QMAKE_MAKE)
# Make sure we don't inherit MAKEFLAGS - -i in particular is fatal.
QMAKE_MAKE = "$${SETENV_PFX}MAKEFLAGS=$$SETENV_SFX $$QMAKE_MAKE"
+QMAKE_PERSIST_LOG = false
+QMAKE_PERSISTED_LOG =
+
defineTest(qtLog) {
write_file($$QMAKE_CONFIG_LOG, 1, append)
$$QMAKE_CONFIG_VERBOSE: for (l, 1): log("$$l$$escape_expand(\\n)")
+ $$QMAKE_PERSIST_LOG {
+ QMAKE_PERSISTED_LOG += $$1
+ export(QMAKE_PERSISTED_LOG)
+ }
+}
+
+defineTest(qtPersistLog) {
+ QMAKE_PERSIST_LOG = true
+ QMAKE_PERSISTED_LOG =
+ export(QMAKE_PERSIST_LOG)
+ export(QMAKE_PERSISTED_LOG)
+}
+
+defineReplace(qtPersistedLog) {
+ QMAKE_PERSIST_LOG = false
+ export(QMAKE_PERSIST_LOG)
+ return($$QMAKE_PERSISTED_LOG)
}
defineTest(qtRunLoggedCommand) {
diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf
index bb5083c925..66acedef55 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -53,7 +53,9 @@ contains(CMAKE_INCLUDE_DIR, "^\\.\\./.*") {
CMAKE_INCLUDE_DIR_IS_ABSOLUTE = True
}
-!exists($$first(QT.$${MODULE}_private.includes)): CMAKE_NO_PRIVATE_INCLUDES = true
+isEmpty(QT.$${MODULE}_private.includes)| \
+ !exists($$first(QT.$${MODULE}_private.includes)): \
+ CMAKE_NO_PRIVATE_INCLUDES = true
CMAKE_LIB_DIR = $$cmakeRelativePath($$[QT_INSTALL_LIBS], $$[QT_INSTALL_PREFIX])
contains(CMAKE_LIB_DIR,"^\\.\\./.*") {
diff --git a/mkspecs/features/ctest_testcase_common.prf b/mkspecs/features/ctest_testcase_common.prf
index 1e3f9d2c1c..0d5ff5f89c 100644
--- a/mkspecs/features/ctest_testcase_common.prf
+++ b/mkspecs/features/ctest_testcase_common.prf
@@ -20,7 +20,7 @@ isEmpty(CTEST_VERSION) {
return()
}
-!versionAtLeast(CMAKE_VERSION, 2.8.3) {
+!versionAtLeast(CMAKE_VERSION, 3.1.0) {
message("cmake $$CMAKE_VERSION is too old for this test.")
return()
}
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index 55c74aad66..27f4c277d6 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -1,13 +1,7 @@
-!!IF !equals(TEMPLATE, aux)
-if (CMAKE_VERSION VERSION_LESS 2.8.3)
- message(FATAL_ERROR \"Qt 5 requires at least CMake version 2.8.3\")
-endif()
-!!ELSE
-if (CMAKE_VERSION VERSION_LESS 3.0.0)
- message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.0.0\")
+if (CMAKE_VERSION VERSION_LESS 3.1.0)
+ message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.1.0\")
endif()
-!!ENDIF
!!IF !isEmpty(CMAKE_USR_MOVE_WORKAROUND)
!!IF !isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
@@ -161,9 +155,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(_Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_MODULE_DEPS)
- if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
- list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\")
- endif()
+ list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\")
!!ENDIF
set(Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS ${Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS})
@@ -219,9 +211,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_QT5_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_QT5_MODULE_DEPS)
- if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
- list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\")
- endif()
+ list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\")
!!ENDIF
!!IF !isEmpty(CMAKE_STATIC_TYPE)
@@ -252,8 +242,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
endif()
endforeach()
- if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST
- AND NOT CMAKE_VERSION VERSION_LESS 3.0.0 )
+ if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST)
add_library(Qt5::$${CMAKE_MODULE_NAME}Private INTERFACE IMPORTED)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME}Private PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS}
diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf
index b477cff162..2d7f0e1ab6 100644
--- a/mkspecs/features/exclusive_builds.prf
+++ b/mkspecs/features/exclusive_builds.prf
@@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) {
}
# Default directories to process
-QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR
-QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR
+QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR
+QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR
diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf
index bbcad8125c..8360dd8b38 100644
--- a/mkspecs/features/mac/sdk.prf
+++ b/mkspecs/features/mac/sdk.prf
@@ -8,21 +8,21 @@ contains(QMAKE_MAC_SDK, .*/.*): \
defineReplace(xcodeSDKInfo) {
info = $$1
equals(info, "Path"): \
- info = --show-sdk-path
+ infoarg = --show-sdk-path
equals(info, "PlatformPath"): \
- info = --show-sdk-platform-path
+ infoarg = --show-sdk-platform-path
equals(info, "SDKVersion"): \
- info = --show-sdk-version
+ infoarg = --show-sdk-version
sdk = $$2
isEmpty(sdk): \
sdk = $$QMAKE_MAC_SDK
isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}) {
- QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$info 2>/dev/null")
+ QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$infoarg 2>/dev/null")
# --show-sdk-platform-path won't work for Command Line Tools; this is fine
# only used by the XCTest backend to testlib
- isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(info, "--show-sdk-platform-path")): \
- error("Could not resolve SDK $$info for \'$$sdk\'")
+ isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(infoarg, "--show-sdk-platform-path")): \
+ error("Could not resolve SDK $$info for \'$$sdk\' using $$infoarg")
cache(QMAKE_MAC_SDK.$${sdk}.$${info}, set stash, QMAKE_MAC_SDK.$${sdk}.$${info})
}
diff --git a/mkspecs/features/qmltestcase.prf b/mkspecs/features/qmltestcase.prf
index 4dfec50be8..216f37d61a 100644
--- a/mkspecs/features/qmltestcase.prf
+++ b/mkspecs/features/qmltestcase.prf
@@ -1,7 +1,6 @@
!isEmpty(SOURCES) {
QT += qml qmltest
load(testcase)
- CONFIG -= app_bundle
DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\"
} else {
# Allow a project to run tests without a CPP stub
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index a2fa1be481..021036e4f9 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -26,6 +26,7 @@ MOC_DIR = .moc
RCC_DIR = .rcc
UI_DIR = .uic
TRACEGEN_DIR = .tracegen
+QMLCACHE_DIR = .qmlcache
intel_icl {
# ICL 14.0 has a bug that makes it not find #includes in dirs starting with .
MOC_DIR = tmp/moc
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
index d80bfde567..10c7025434 100644
--- a/mkspecs/features/qt_configure.prf
+++ b/mkspecs/features/qt_configure.prf
@@ -710,13 +710,14 @@ defineTest(qtConfHandleLibrary) {
}
use_args = $$eval($${lpfx}.literal_args)
- qtConfLoadResult($${lpfx}, $$1) {
+ qtConfLoadResult($${lpfx}, $$1, "library") {
$$eval($${lpfx}.result): \
qtConfExportLibrary($$1)
return()
}
qtLogTestIntro($${lpfx}, "looking for library $${1}")
+ qtPersistLog()
result = false
for (s, $${lpfx}.sources._KEYS_) {
@@ -768,6 +769,9 @@ defineTest(qtConfHandleLibrary) {
break()
}
+ $${lpfx}.msgs = $$qtPersistedLog()
+ export($${lpfx}.msgs)
+
qtLogTestResult($${lpfx}, $$result)
$${lpfx}.result = $$result
@@ -1024,7 +1028,7 @@ defineTest(qtLogTestIntro) {
label = $$eval($${1}.label)
isEmpty(label): return()
- log("Checking for $${label}... ")
+ isEmpty(3): log("Checking for $${label}... ")
$$QMAKE_CONFIG_VERBOSE: log("$$escape_expand(\\n)")
write_file($$QMAKE_CONFIG_LOG, 2, append)
}
@@ -1044,14 +1048,14 @@ defineTest(qtLogTestResult) {
msg = "test $$1 FAILED"
}
$$QMAKE_CONFIG_VERBOSE: log_msg = $$msg
- logn("$$log_msg")
+ isEmpty(3): logn("$$log_msg")
write_file($$QMAKE_CONFIG_LOG, msg, append)
}
defineTest(qtConfSaveResult) {
equals($${1}.cache, -): \
return()
- keys = result $$eval($${1}.cache)
+ keys = result msgs $$eval($${1}.cache)
cont = "cache.$${2}._KEYS_ = $$keys"
cache.$${2}._KEYS_ = $$keys
export(cache.$${2}._KEYS_)
@@ -1074,6 +1078,12 @@ defineTest(qtConfLoadResult) {
$${1}.$${k} = $$eval(cache.$${2}.$${k})
export($${1}.$${k})
}
+ # we could print the cached result, but that's basically just noise -
+ # the explicitly generated summary is supposed to contain all relevant
+ # information.
+ qtLogTestIntro($$1, "loaded result for $$3 $$1", false)
+ qtLog($$eval($${1}.msgs))
+ qtLogTestResult($$1, $$eval($${1}.result), false)
return(true)
}
@@ -1154,14 +1164,18 @@ defineTest(qtRunSingleTest) {
# note: we do this only after resolving the dependencies and the
# preparation (which may resolve libraries), so that caching does
# not alter the execution order (and thus the output).
- qtConfLoadResult($${tpfx}, $$1): \
+ qtConfLoadResult($${tpfx}, $$1, "config test"): \
return()
qtLogTestIntro($${tpfx}, "executing config test $${1}")
+ qtPersistLog()
result = false
$${call}($${tpfx}): result = true
+ $${tpfx}.msgs = $$qtPersistedLog()
+ export($${tpfx}.msgs)
+
qtLogTestResult($${tpfx}, $$result)
$${tpfx}.result = $$result
diff --git a/mkspecs/features/qt_installs.prf b/mkspecs/features/qt_installs.prf
index 90d84cc535..8f98987b99 100644
--- a/mkspecs/features/qt_installs.prf
+++ b/mkspecs/features/qt_installs.prf
@@ -28,9 +28,9 @@
#headers
qt_install_headers {
- class_headers.files = $$SYNCQT.HEADER_CLASSES
- class_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME
- INSTALLS += class_headers
+ gen_headers.files = $$SYNCQT.GENERATED_HEADER_FILES
+ gen_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME
+ INSTALLS += gen_headers
targ_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.INJECTED_HEADER_FILES
targ_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index e6a0d97f1a..f8729de947 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -136,7 +136,7 @@ lib_bundle {
if(if(!debug_and_release|CONFIG(release, debug|release))) {
FRAMEWORK_HEADERS.version = Versions
FRAMEWORK_HEADERS.files = \
- $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES $$SYNCQT.INJECTED_HEADER_FILES
+ $$SYNCQT.HEADER_FILES $$SYNCQT.GENERATED_HEADER_FILES $$SYNCQT.INJECTED_HEADER_FILES
FRAMEWORK_HEADERS.path = Headers
FRAMEWORK_PRIVATE_HEADERS.version = Versions
FRAMEWORK_PRIVATE_HEADERS.files = \
@@ -224,7 +224,7 @@ android: CONFIG += qt_android_deps no_linker_version_script
private_api_headers = $$SYNCQT.PRIVATE_HEADER_FILES $$SYNCQT.QPA_HEADER_FILES
for(header, private_api_headers): \
- verscript_content += " @FILE:$${_PRO_FILE_PWD_}/$$header@"
+ verscript_content += " @FILE:$$header@"
verscript_content += "};"
current = Qt_$$QT_MAJOR_VERSION
@@ -244,8 +244,7 @@ android: CONFIG += qt_android_deps no_linker_version_script
verscriptprocess.name = linker version script ${QMAKE_FILE_BASE}
verscriptprocess.input = verscript_in
verscriptprocess.CONFIG += no_link target_predeps
- for(header, private_api_headers): \
- verscriptprocess.depends += $${_PRO_FILE_PWD_}/$$header
+ verscriptprocess.depends = $$private_api_headers
verscriptprocess.output = $$verscript
verscriptprocess.commands = perl $${PWD}/data/unix/findclasslist.pl < ${QMAKE_FILE_IN} > $@
silent:verscriptprocess.commands = @echo creating linker version script ${QMAKE_FILE_BASE} && $$verscriptprocess.commands
diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf
index 62b88c6fe2..e45ac94966 100644
--- a/mkspecs/features/qt_module_headers.prf
+++ b/mkspecs/features/qt_module_headers.prf
@@ -96,12 +96,24 @@ MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES
minimal_syncqt: return()
+defineTest(syncQtResolve) {
+ out =
+ for (f, SYNCQT.$$1): \
+ out += $$absolute_path($$f, $$2)
+ SYNCQT.$$1 = $$out
+ export(SYNCQT.$$1)
+}
+
#load up the headers info
git_build: \
INC_PATH = $$MODULE_BASE_OUTDIR
else: \
INC_PATH = $$MODULE_BASE_INDIR
include($$INC_PATH/include/$$MODULE_INCNAME/headers.pri, "", true)
+syncQtResolve(HEADER_FILES, $$_PRO_FILE_PWD_)
+syncQtResolve(PRIVATE_HEADER_FILES, $$_PRO_FILE_PWD_)
+syncQtResolve(QPA_HEADER_FILES, $$_PRO_FILE_PWD_)
+syncQtResolve(GENERATED_HEADER_FILES, $$INC_PATH/include/$$MODULE_INCNAME)
!lib_bundle: \ # Headers are embedded into the bundle, so don't install them separately.
CONFIG += qt_install_headers
@@ -114,9 +126,6 @@ exists($$OUT_PWD/qt$${MODULE}-config.h) {
SYNCQT.INJECTIONS += \
$$fwd_rel/qt$${MODULE}-config.h:qt$${MODULE}-config.h \
$$fwd_rel/qt$${MODULE}-config_p.h:$$MODULE_VERSION/$$MODULE_INCNAME/private/qt$${MODULE}-config_p.h
- inst_rel = $$relative_path($$OUT_PWD, $$_PRO_FILE_PWD_)
- SYNCQT.HEADER_FILES += $$inst_rel/qt$${MODULE}-config.h
- SYNCQT.INJECTED_PRIVATE_HEADER_FILES += $$inst_rel/qt$${MODULE}-config_p.h
}
for (injection, SYNCQT.INJECTIONS) {
@@ -129,6 +138,10 @@ for (injection, SYNCQT.INJECTIONS) {
write_file($$MAIN_FWD, MAIN_FWD_CONT)|error()
equals(fwd_hdr, ofwd_hdr): touch($$MAIN_FWD, $$dst_hdr)
!git_build: QMAKE_DISTCLEAN += $$MAIN_FWD
+ !contains(ofwd_hdr, .*/private/.*): \
+ SYNCQT.INJECTED_HEADER_FILES += $$dst_hdr
+ else: \
+ SYNCQT.INJECTED_PRIVATE_HEADER_FILES += $$dst_hdr
injects = $$member(injects, 2, -1)
for (inject, injects) {
CLASS_FWD = $$MODULE_INC_OUTDIR/$$inject
@@ -136,6 +149,7 @@ for (injection, SYNCQT.INJECTIONS) {
write_file($$CLASS_FWD, CLASS_FWD_CONT)|error()
touch($$CLASS_FWD, $$MAIN_FWD)
!git_build: QMAKE_DISTCLEAN += $$CLASS_FWD
+ SYNCQT.INJECTED_HEADER_FILES += $$CLASS_FWD
}
}
diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf
index 3f5979202c..ff45446219 100644
--- a/mkspecs/features/resources.prf
+++ b/mkspecs/features/resources.prf
@@ -33,7 +33,7 @@ for(resource, RESOURCES) {
next()
}
- resource_file = $$RCC_DIR/qmake_$${resource}.qrc
+ resource_file = $$absolute_path($$RCC_DIR/qmake_$${resource}.qrc, $$OUT_PWD)
isEmpty(BUILDS)|build_pass {
# Collection of files, generate qrc file
@@ -64,7 +64,7 @@ for(resource, RESOURCES) {
"</qresource>" \
"</RCC>"
- !write_file($$absolute_path($$resource_file, $$OUT_PWD), resource_file_content): \
+ !write_file($$resource_file, resource_file_content): \
error()
}
diff --git a/mkspecs/macx-clang/qmake.conf b/mkspecs/macx-clang/qmake.conf
index 170464d08f..14c885fd78 100644
--- a/mkspecs/macx-clang/qmake.conf
+++ b/mkspecs/macx-clang/qmake.conf
@@ -11,13 +11,16 @@ QMAKE_APPLE_DEVICE_ARCHS = x86_64
# configure \
# -pkg-config \
# -fontconfig -system-freetype \
-# -system-xcb -xkb -no-opengl \
-# -qt-xkbcommon -qt-xkbcommon-x11
+# -system-xcb -no-opengl
#
# Ensure that pkg-config is properly configured, or that
# PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig:/opt/X11/share/pkgconfig
# is set in your build environment.
#
+# If you don't want to use pkg-config, you can add:
+# -L/opt/X11/lib -I/opt/X11/include
+# to the configure options.
+#
# Due to irreconcilable differences between Cocoa
# and X11, OpenGL is currently not supported.
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index cc3b73418b..35f24e1793 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2913,7 +2913,8 @@
Returns the absolute path of \c path.
If \c base is not specified, uses the current directory as the base
- directory.
+ directory. If it is a relative path, it is resolved relative to the current
+ directory before use.
For example, the following call returns the string
\c {"/home/johndoe/myproject/readme.txt"}:
@@ -3152,9 +3153,15 @@
\section2 relative_path(filePath[, base])
- Returns the path to \c filePath relative to \c base. If \c base is not
- specified, it is the current project directory. This function is a wrapper
- around QDir::relativeFilePath.
+ Returns the path to \c filePath relative to \c base.
+
+ If \c base is not specified, it is the current project
+ directory. If it is relative, it is resolved relative to the
+ current project directory before use.
+
+ If \c filePath is relative, it is first resolved against the base
+ directory; in that case, this function effectively acts as
+ $$clean_path().
See also \l{absolute_path(path[, base])}{absolute_path()},
\l{clean_path(path)}{clean_path()}.
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index db7a1b2714..3b1f904253 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -779,8 +779,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
mkt << "\\\n\t";
++added;
const QString file_name = fileFixify(fn, FileFixifyFromOutdir);
+ const QString tmpOut = fileFixify(tmp_out.first().toQString(), FileFixifyFromOutdir);
mkt << ' ' << escapeDependencyPath(Option::fixPathToTargetOS(
- replaceExtraCompilerVariables(tmp_out.first().toQString(), file_name, QString(), NoShell)));
+ replaceExtraCompilerVariables(tmpOut, file_name, QString(), NoShell)));
}
}
}
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 8ecfa0bf31..5468285c2e 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -943,7 +943,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QString fn = files.at(file).toQString();
QString src = fileFixify(fn, FileFixifyAbsolute);
if (!QFile::exists(src))
- src = fn;
+ src = fileFixify(fn, FileFixifyFromOutdir);
+ else
+ src = fileFixify(fn);
QString dst = path + Option::dir_sep + fileInfo(fn).fileName();
bundledFiles << dst;
alldeps << dst;
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 38bf3a0cbd..9f82ce4f8e 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -34,6 +34,7 @@
#include <qscopedpointer.h>
#include <qstringlist.h>
#include <qfileinfo.h>
+#include <qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -618,17 +619,30 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< tagValue("RootNamespace", tool.Name)
<< tagValue("Keyword", tool.Keyword);
+ QString windowsTargetPlatformVersion;
if (isWinRT) {
xml << tagValue("MinimumVisualStudioVersion", tool.Version)
<< tagValue("DefaultLanguage", "en")
<< tagValue("AppContainerApplication", "true")
<< tagValue("ApplicationType", "Windows Store")
<< tagValue("ApplicationTypeRevision", tool.SdkVersion);
- if (tool.SdkVersion == "10.0") {
- const QString ucrtVersion = qgetenv("UCRTVERSION");
- xml << tagValue("WindowsTargetPlatformVersion", ucrtVersion)
- << tagValue("WindowsTargetPlatformMinVersion", ucrtVersion);
- }
+ if (tool.SdkVersion == "10.0")
+ windowsTargetPlatformVersion = qgetenv("UCRTVERSION");
+ } else {
+ QByteArray winSDKVersionStr = qgetenv("WindowsSDKVersion").trimmed();
+
+ // This environment variable might end with a backslash due to a VS bug.
+ if (winSDKVersionStr.endsWith('\\'))
+ winSDKVersionStr.chop(1);
+
+ QVersionNumber winSDKVersion = QVersionNumber::fromString(
+ QString::fromLocal8Bit(winSDKVersionStr));
+ if (!winSDKVersion.isNull())
+ windowsTargetPlatformVersion = winSDKVersionStr;
+ }
+ if (!windowsTargetPlatformVersion.isEmpty()) {
+ xml << tagValue("WindowsTargetPlatformVersion", windowsTargetPlatformVersion)
+ << tagValue("WindowsTargetPlatformMinVersion", windowsTargetPlatformVersion);
}
xml << closetag();
diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp
index afd41912fe..fd84dff59d 100644
--- a/qmake/library/ioutils.cpp
+++ b/qmake/library/ioutils.cpp
@@ -60,7 +60,7 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName)
struct ::stat st;
if (::stat(fileName.toLocal8Bit().constData(), &st))
return FileNotFound;
- return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular;
+ return S_ISDIR(st.st_mode) ? FileIsDir : S_ISREG(st.st_mode) ? FileIsRegular : FileNotFound;
#endif
}
@@ -103,7 +103,7 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &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));
+ Q_ASSERT_X(isAbsolutePath(baseDir), "IoUtils::resolvePath", qUtf8Printable(baseDir));
return QDir::cleanPath(baseDir.left(2) + fileName);
}
#endif // Q_OS_WIN
@@ -258,9 +258,8 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF
# endif
return true;
}
-#endif
-#ifdef Q_OS_UNIX
+#if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX)
bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target)
{
const QByteArray localSymlinkPath = QFile::encodeName(symlinkPath);
@@ -295,4 +294,6 @@ bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target)
}
#endif
+#endif // PROEVALUATOR_FULL
+
QT_END_NAMESPACE
diff --git a/qmake/library/ioutils.h b/qmake/library/ioutils.h
index ad379404f3..32bf675f62 100644
--- a/qmake/library/ioutils.h
+++ b/qmake/library/ioutils.h
@@ -29,6 +29,8 @@
#ifndef IOUTILS_H
#define IOUTILS_H
+#include "qmake_global.h"
+
#include <qstring.h>
QT_BEGIN_NAMESPACE
@@ -39,7 +41,7 @@ namespace QMakeInternal {
This class provides replacement functionality for QFileInfo, QFile & QDir,
as these are abysmally slow.
*/
-class IoUtils {
+class QMAKE_EXPORT IoUtils {
public:
enum FileType {
FileNotFound = 0,
@@ -64,9 +66,9 @@ public:
#endif
#if defined(PROEVALUATOR_FULL)
static bool touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString);
-#endif
-#ifdef Q_OS_UNIX
+# if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX)
static bool readLinkTarget(const QString &symlinkPath, QString *target);
+# endif
#endif
};
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 83c3d1d643..c1d446263e 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -443,15 +443,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json
QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- bool exe, const QString &contents)
+ QMakeVfs::VfsFlags flags, const QString &contents)
{
+ int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
+ int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate);
QString errStr;
- if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) {
+ if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse;
}
- m_parser->discardFileFromCache(fn);
+ if (oldId)
+ m_parser->discardFileFromCache(oldId);
return ReturnTrue;
}
@@ -1178,7 +1181,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
- QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
+ QString baseDir = args.count() > 1
+ ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
+ : currentDirectory();
QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
ret << (rstr.isSharedWith(m_tmp1)
? args.at(0)
@@ -1192,7 +1197,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
} else {
QString arg = args.at(0).toQString(m_tmp1);
- QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
+ QString baseDir = args.count() > 1
+ ? IoUtils::resolvePath(currentDirectory(), 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)));
@@ -1339,7 +1346,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
- int pro = m_parser->idForFileName(fn);
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
if (!pro)
return ReturnFalse;
ProValueMap &vmap = m_valuemapStack.first();
@@ -1412,7 +1420,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
VisitReturn ret = ReturnFalse;
QString contents = args.join(statics.field_sep);
ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
- m_current.pro->fileName(), m_current.line);
+ 0, m_current.pro->fileName(), m_current.line);
if (m_cumulative || pro->isOk()) {
m_locationStack.push(m_current);
visitProBlock(pro, pro->tokPtr());
@@ -1780,7 +1788,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
QIODevice::OpenMode mode = QIODevice::Truncate;
- bool exe = false;
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString contents;
if (args.count() >= 2) {
const ProStringList &vals = values(args.at(1).toKey());
@@ -1792,7 +1800,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (opt == QLatin1String("append")) {
mode = QIODevice::Append;
} else if (opt == QLatin1String("exe")) {
- exe = true;
+ flags |= QMakeVfs::VfsExecutable;
} else {
evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQString(m_tmp3)));
return ReturnFalse;
@@ -1802,7 +1810,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
QString path = resolvePath(args.at(0).toQString(m_tmp1));
path.detach(); // make sure to not leak m_tmp1 into the map of written files.
- return writeFile(QString(), path, mode, exe, contents);
+ return writeFile(QString(), path, mode, flags, contents);
}
case T_TOUCH: {
if (args.count() != 2) {
@@ -1956,6 +1964,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
varstr += QLatin1Char('\n');
}
QString fn;
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (target == TargetSuper) {
if (m_superfile.isEmpty()) {
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
@@ -1979,12 +1988,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
fn = m_stashfile;
if (fn.isEmpty())
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
- if (!m_vfs->exists(fn)) {
+ if (!m_vfs->exists(fn, flags)) {
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
}
}
- return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr);
+ return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
}
case T_RELOAD_PROPERTIES:
#ifdef QT_BUILD_QMAKE
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 6e6c72de59..7112b57c11 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -1104,6 +1104,7 @@ void QMakeEvaluator::loadDefaults()
bool QMakeEvaluator::prepareProject(const QString &inDir)
{
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString superdir;
if (m_option->do_cache) {
QString conffile;
@@ -1114,7 +1115,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
superdir = m_outputDir;
forever {
QString superfile = superdir + QLatin1String("/.qmake.super");
- if (m_vfs->exists(superfile)) {
+ if (m_vfs->exists(superfile, flags)) {
m_superfile = QDir::cleanPath(superfile);
break;
}
@@ -1129,10 +1130,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir;
forever {
conffile = sdir + QLatin1String("/.qmake.conf");
- if (!m_vfs->exists(conffile))
+ if (!m_vfs->exists(conffile, flags))
conffile.clear();
cachefile = dir + QLatin1String("/.qmake.cache");
- if (!m_vfs->exists(cachefile))
+ if (!m_vfs->exists(cachefile, flags))
cachefile.clear();
if (!conffile.isEmpty() || !cachefile.isEmpty()) {
if (dir != sdir)
@@ -1160,7 +1161,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir;
forever {
QString stashfile = dir + QLatin1String("/.qmake.stash");
- if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) {
+ if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile, flags)) {
m_stashfile = QDir::cleanPath(stashfile);
break;
}
@@ -1259,7 +1260,7 @@ bool QMakeEvaluator::loadSpec()
goto cool;
}
}
- evalError(fL1S("Could not find qmake configuration file %1.").arg(qmakespec));
+ evalError(fL1S("Could not find qmake spec '%1'.").arg(qmakespec));
return false;
}
cool:
@@ -1285,7 +1286,8 @@ bool QMakeEvaluator::loadSpec()
m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
return false;
}
- if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) {
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) {
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile);
if (evaluateFile(
m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
@@ -1308,7 +1310,7 @@ void QMakeEvaluator::setupProject()
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
{
if (!cmds.isEmpty()) {
- ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1);
+ ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), 0, where, -1);
if (pro->isOk()) {
m_locationStack.push(m_current);
visitProBlock(pro, pro->tokPtr());
@@ -1812,7 +1814,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional(
const QStringRef &cond, const QString &where, int line)
{
VisitReturn ret = ReturnFalse;
- ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar);
+ ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar);
if (pro->isOk()) {
m_locationStack.push(m_current);
ret = visitProBlock(pro, pro->tokPtr());
@@ -1980,23 +1982,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile(
// needs to be determined. Failed lookups are represented via non-null empty strings.
QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)];
if (fnp->isNull()) {
- int start_root = 0;
- const QStringList &paths = m_featureRoots->paths;
- if (!currFn.isEmpty()) {
- QStringRef currPath = IoUtils::pathName(currFn);
- for (int root = 0; root < paths.size(); ++root)
- if (currPath == paths.at(root)) {
- start_root = root + 1;
- break;
- }
- }
- for (int root = start_root; root < paths.size(); ++root) {
- QString fname = paths.at(root) + fn;
- if (IoUtils::exists(fname)) {
- fn = fname;
+#ifdef QMAKE_OVERRIDE_PRFS
+ {
+ QString ovrfn(QLatin1String(":/qmake/override_features/") + fn);
+ if (QFileInfo::exists(ovrfn)) {
+ fn = ovrfn;
goto cool;
}
}
+#endif
+ {
+ int start_root = 0;
+ const QStringList &paths = m_featureRoots->paths;
+ if (!currFn.isEmpty()) {
+ QStringRef currPath = IoUtils::pathName(currFn);
+ for (int root = 0; root < paths.size(); ++root)
+ if (currPath == paths.at(root)) {
+ start_root = root + 1;
+ break;
+ }
+ }
+ for (int root = start_root; root < paths.size(); ++root) {
+ QString fname = paths.at(root) + fn;
+ if (IoUtils::exists(fname)) {
+ fn = fname;
+ goto cool;
+ }
+ }
+ }
#ifdef QMAKE_BUILTIN_PRFS
fn.prepend(QLatin1String(":/qmake/features/"));
if (QFileInfo::exists(fn))
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index 7318664d46..1f0255e55a 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -34,6 +34,7 @@
#endif
#include "qmakeparser.h"
+#include "qmakevfs.h"
#include "ioutils.h"
#include <qlist.h>
@@ -237,7 +238,7 @@ public:
VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value);
VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- bool exe, const QString &contents);
+ QMakeVfs::VfsFlags flags, const QString &contents);
#if QT_CONFIG(process)
void runProcess(QProcess *proc, const QString &command) const;
#endif
diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp
index d733d479cf..452b44c045 100644
--- a/qmake/library/qmakeglobals.cpp
+++ b/qmake/library/qmakeglobals.cpp
@@ -327,6 +327,13 @@ bool QMakeGlobals::initProperties()
QT_PCLOSE(proc);
}
#endif
+ parseProperties(data, properties);
+ return true;
+}
+#endif
+
+void QMakeGlobals::parseProperties(const QByteArray &data, QHash<ProKey, ProString> &properties)
+{
const auto lines = data.split('\n');
for (QByteArray line : lines) {
int off = line.indexOf(':');
@@ -337,47 +344,50 @@ bool QMakeGlobals::initProperties()
QString name = QString::fromLatin1(line.left(off));
ProString value = ProString(QDir::fromNativeSeparators(
QString::fromLocal8Bit(line.mid(off + 1))));
+ if (value.isNull())
+ value = ProString(""); // Make sure it is not null, to discern from missing keys
properties.insert(ProKey(name), value);
if (name.startsWith(QLatin1String("QT_"))) {
- bool plain = !name.contains(QLatin1Char('/'));
- if (!plain) {
- if (!name.endsWith(QLatin1String("/get")))
+ enum { PropPut, PropRaw, PropGet } variant;
+ if (name.contains(QLatin1Char('/'))) {
+ if (name.endsWith(QLatin1String("/raw")))
+ variant = PropRaw;
+ else if (name.endsWith(QLatin1String("/get")))
+ variant = PropGet;
+ else // Nothing falls back on /src or /dev.
continue;
name.chop(4);
+ } else {
+ variant = PropPut;
}
if (name.startsWith(QLatin1String("QT_INSTALL_"))) {
- if (plain) {
- properties.insert(ProKey(name + QLatin1String("/raw")), value);
- properties.insert(ProKey(name + QLatin1String("/get")), value);
- }
- properties.insert(ProKey(name + QLatin1String("/src")), value);
- if (name == QLatin1String("QT_INSTALL_PREFIX")
- || name == QLatin1String("QT_INSTALL_DATA")
- || name == QLatin1String("QT_INSTALL_BINS")) {
- name.replace(3, 7, QLatin1String("HOST"));
- if (plain) {
- properties.insert(ProKey(name), value);
- properties.insert(ProKey(name + QLatin1String("/get")), value);
+ if (variant < PropRaw) {
+ if (name == QLatin1String("QT_INSTALL_PREFIX")
+ || name == QLatin1String("QT_INSTALL_DATA")
+ || name == QLatin1String("QT_INSTALL_LIBS")
+ || name == QLatin1String("QT_INSTALL_BINS")) {
+ // Qt4 fallback
+ QString hname = name;
+ hname.replace(3, 7, QLatin1String("HOST"));
+ properties.insert(ProKey(hname), value);
+ properties.insert(ProKey(hname + QLatin1String("/get")), value);
+ properties.insert(ProKey(hname + QLatin1String("/src")), value);
}
- properties.insert(ProKey(name + QLatin1String("/src")), value);
+ properties.insert(ProKey(name + QLatin1String("/raw")), value);
}
- } else if (name.startsWith(QLatin1String("QT_HOST_"))) {
- if (plain)
+ if (variant <= PropRaw)
+ properties.insert(ProKey(name + QLatin1String("/dev")), value);
+ } else if (!name.startsWith(QLatin1String("QT_HOST_"))) {
+ continue;
+ }
+ if (variant != PropRaw) {
+ if (variant < PropGet)
properties.insert(ProKey(name + QLatin1String("/get")), value);
properties.insert(ProKey(name + QLatin1String("/src")), value);
}
}
}
- return true;
}
-#else
-void QMakeGlobals::setProperties(const QHash<QString, QString> &props)
-{
- QHash<QString, QString>::ConstIterator it = props.constBegin(), eit = props.constEnd();
- for (; it != eit; ++it)
- properties.insert(ProKey(it.key()), ProString(it.value()));
-}
-#endif
#endif // QT_BUILD_QMAKE
QT_END_NAMESPACE
diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h
index 000f685b73..6c00b1f3af 100644
--- a/qmake/library/qmakeglobals.h
+++ b/qmake/library/qmakeglobals.h
@@ -131,10 +131,10 @@ public:
void reloadProperties() { property->reload(); }
ProString propertyValue(const ProKey &name) const { return property->value(name); }
#else
+ static void parseProperties(const QByteArray &data, QHash<ProKey, ProString> &props);
# ifdef PROEVALUATOR_INIT_PROPS
bool initProperties();
# else
- void setProperties(const QHash<QString, QString> &props);
void setProperties(const QHash<ProKey, ProString> &props) { properties = props; }
# endif
ProString propertyValue(const ProKey &name) const { return properties.value(name); }
diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp
index b5d89c1ba6..37608c7a15 100644
--- a/qmake/library/qmakeparser.cpp
+++ b/qmake/library/qmakeparser.cpp
@@ -52,12 +52,22 @@ ProFileCache::~ProFileCache()
ent.pro->deref();
}
-void ProFileCache::discardFile(const QString &fileName)
+void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)
+{
+ int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly);
+ if (eid)
+ discardFile(eid);
+ int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly);
+ if (cid && cid != eid)
+ discardFile(cid);
+}
+
+void ProFileCache::discardFile(int id)
{
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker lck(&mutex);
#endif
- QHash<QString, Entry>::Iterator it = parsed_files.find(fileName);
+ auto it = parsed_files.find(id);
if (it != parsed_files.end()) {
#ifdef PROPARSER_THREAD_SAFE
if (it->locker) {
@@ -77,16 +87,16 @@ void ProFileCache::discardFile(const QString &fileName)
}
}
-void ProFileCache::discardFiles(const QString &prefix)
+void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs)
{
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker lck(&mutex);
#endif
- QHash<QString, Entry>::Iterator
- it = parsed_files.begin(),
- end = parsed_files.end();
- while (it != end)
- if (it.key().startsWith(prefix)) {
+ auto it = parsed_files.begin(), end = parsed_files.end();
+ while (it != end) {
+ // Note: this is empty for virtual files from other VFSes.
+ QString fn = vfs->fileNameForId(it.key());
+ if (fn.startsWith(prefix)) {
#ifdef PROPARSER_THREAD_SAFE
if (it->locker) {
if (!it->locker->done) {
@@ -105,6 +115,7 @@ void ProFileCache::discardFiles(const QString &prefix)
} else {
++it;
}
+ }
}
////////// Parser ///////////
@@ -167,12 +178,15 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
{
ProFile *pro;
+ QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative
+ : QMakeVfs::VfsExact);
+ int id = m_vfs->idForFileName(fileName, vfsFlags);
if ((flags & ParseUseCache) && m_cache) {
ProFileCache::Entry *ent;
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_cache->mutex);
#endif
- QHash<QString, ProFileCache::Entry>::Iterator it = m_cache->parsed_files.find(fileName);
+ auto it = m_cache->parsed_files.find(id);
if (it != m_cache->parsed_files.end()) {
ent = &*it;
#ifdef PROPARSER_THREAD_SAFE
@@ -190,18 +204,18 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
if ((pro = ent->pro))
pro->ref();
} else {
- ent = &m_cache->parsed_files[fileName];
+ ent = &m_cache->parsed_files[id];
#ifdef PROPARSER_THREAD_SAFE
ent->locker = new ProFileCache::Entry::Locker;
locker.unlock();
#endif
- pro = new ProFile(idForFileName(fileName), fileName);
- if (!read(pro, flags)) {
- delete pro;
- pro = 0;
- } else {
+ QString contents;
+ if (readFile(id, flags, &contents)) {
+ pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
pro->itemsRef()->squeeze();
pro->ref();
+ } else {
+ pro = 0;
}
ent->pro = pro;
#ifdef PROPARSER_THREAD_SAFE
@@ -216,51 +230,39 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
#endif
}
} else {
- pro = new ProFile(idForFileName(fileName), fileName);
- if (!read(pro, flags)) {
- delete pro;
+ QString contents;
+ if (readFile(id, flags, &contents))
+ pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
+ else
pro = 0;
- }
}
return pro;
}
ProFile *QMakeParser::parsedProBlock(
- const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
+ const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar)
{
- ProFile *pro = new ProFile(0, name);
+ ProFile *pro = new ProFile(id, name);
read(pro, contents, line, grammar);
return pro;
}
-int QMakeParser::idForFileName(const QString &fileName)
-{
-#ifdef PROPARSER_THREAD_SAFE
- QMutexLocker lck(&fileIdMutex);
-#endif
- int &place = fileIdMap[fileName];
- if (!place)
- place = ++fileIdCounter;
- return place;
-}
-
-void QMakeParser::discardFileFromCache(const QString &fileName)
+void QMakeParser::discardFileFromCache(int id)
{
if (m_cache)
- m_cache->discardFile(fileName);
+ m_cache->discardFile(id);
}
-bool QMakeParser::read(ProFile *pro, ParseFlags flags)
+bool QMakeParser::readFile(int id, ParseFlags flags, QString *contents)
{
- QString content;
QString errStr;
- if (!m_vfs->readFile(pro->fileName(), &content, &errStr)) {
- if (m_handler && ((flags & ParseReportMissing) || m_vfs->exists(pro->fileName())))
+ QMakeVfs::ReadResult result = m_vfs->readFile(id, contents, &errStr);
+ if (result != QMakeVfs::ReadOk) {
+ if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
m_handler->message(QMakeParserHandler::ParserIoError,
- fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr));
+ fL1S("Cannot read %1: %2").arg(m_vfs->fileNameForId(id), errStr));
return false;
}
- read(pro, QStringRef(&content), 1, FullGrammar);
return true;
}
diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h
index a29e9c227d..3ae30dcf74 100644
--- a/qmake/library/qmakeparser.h
+++ b/qmake/library/qmakeparser.h
@@ -30,6 +30,7 @@
#define QMAKEPARSER_H
#include "qmake_global.h"
+#include "qmakevfs.h"
#include "proitems.h"
#include <qhash.h>
@@ -78,7 +79,12 @@ public:
enum ParseFlag {
ParseDefault = 0,
ParseUseCache = 1,
- ParseReportMissing = 4
+ ParseReportMissing = 4,
+#ifdef PROEVALUATOR_DUAL_VFS
+ ParseCumulative = 8
+#else
+ ParseCumulative = 0
+#endif
};
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
@@ -87,12 +93,10 @@ public:
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
// fileName is expected to be absolute and cleanPath()ed.
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
- ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
+ ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line = 0,
SubGrammar grammar = FullGrammar);
- int idForFileName(const QString &fileName);
-
- void discardFileFromCache(const QString &fileName);
+ void discardFileFromCache(int id);
#ifdef PROPARSER_DEBUG
static QString formatProBlock(const QString &block);
@@ -131,7 +135,7 @@ private:
ushort terminator; // '}' if replace function call is braced, ':' if test function
};
- bool read(ProFile *pro, ParseFlags flags);
+ bool readFile(int id, QMakeParser::ParseFlags flags, QString *contents);
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
@@ -182,12 +186,6 @@ private:
QString m_tmp; // Temporary for efficient toQString
- QHash<QString, int> fileIdMap;
-#ifdef PROEVALUATOR_THREAD_SAFE
- QMutex fileIdMutex;
-#endif
- int fileIdCounter = 0;
-
ProFileCache *m_cache;
QMakeParserHandler *m_handler;
QMakeVfs *m_vfs;
@@ -206,8 +204,9 @@ public:
ProFileCache() {}
~ProFileCache();
- void discardFile(const QString &fileName);
- void discardFiles(const QString &prefix);
+ void discardFile(int id);
+ void discardFile(const QString &fileName, QMakeVfs *vfs);
+ void discardFiles(const QString &prefix, QMakeVfs *vfs);
private:
struct Entry {
@@ -223,7 +222,7 @@ private:
#endif
};
- QHash<QString, Entry> parsed_files;
+ QHash<int, Entry> parsed_files;
#ifdef PROPARSER_THREAD_SAFE
QMutex mutex;
#endif
diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp
index 5aa9ec9299..2239a2beec 100644
--- a/qmake/library/qmakevfs.cpp
+++ b/qmake/library/qmakevfs.cpp
@@ -35,6 +35,10 @@ using namespace QMakeInternal;
#include <qfile.h>
#include <qfileinfo.h>
+#ifndef QT_NO_TEXTCODEC
+#include <qtextcodec.h>
+#endif
+
#define fL1S(s) QString::fromLatin1(s)
QT_BEGIN_NAMESPACE
@@ -45,34 +49,107 @@ QMakeVfs::QMakeVfs()
, m_magicExisting(fL1S("existing"))
#endif
{
+#ifndef QT_NO_TEXTCODEC
+ m_textCodec = 0;
+#endif
+}
+
+#ifdef PROPARSER_THREAD_SAFE
+QMutex QMakeVfs::s_mutex;
+#endif
+QAtomicInt QMakeVfs::s_fileIdCounter;
+QHash<QString, int> QMakeVfs::s_fileIdMap;
+QHash<int, QString> QMakeVfs::s_idFileMap;
+
+int QMakeVfs::idForFileName(const QString &fn, VfsFlags flags)
+{
+#ifdef PROEVALUATOR_DUAL_VFS
+ {
+# ifdef PROPARSER_THREAD_SAFE
+ QMutexLocker locker(&m_vmutex);
+# endif
+ int idx = (flags & VfsCumulative) ? 1 : 0;
+ if (flags & VfsCreate) {
+ int &id = m_virtualFileIdMap[idx][fn];
+ if (!id) {
+ id = ++s_fileIdCounter;
+ m_virtualIdFileMap[id] = fn;
+ }
+ return id;
+ }
+ int id = m_virtualFileIdMap[idx].value(fn);
+ if (id || (flags & VfsCreatedOnly))
+ return id;
+ }
+#endif
+ if (!(flags & VfsAccessedOnly)) {
+#ifdef PROPARSER_THREAD_SAFE
+ QMutexLocker locker(&s_mutex);
+#endif
+ int &id = s_fileIdMap[fn];
+ if (!id) {
+ id = ++s_fileIdCounter;
+ s_idFileMap[id] = fn;
+ }
+ return id;
+ }
+ return s_fileIdMap.value(fn);
+}
+
+QString QMakeVfs::fileNameForId(int id)
+{
+#ifdef PROEVALUATOR_DUAL_VFS
+ {
+# ifdef PROPARSER_THREAD_SAFE
+ QMutexLocker locker(&m_vmutex);
+# endif
+ const QString &fn = m_virtualIdFileMap.value(id);
+ if (!fn.isEmpty())
+ return fn;
+ }
+#endif
+#ifdef PROPARSER_THREAD_SAFE
+ QMutexLocker locker(&s_mutex);
+#endif
+ return s_idFileMap.value(id);
+}
+
+void QMakeVfs::clearIds()
+{
+#ifdef PROEVALUATOR_THREAD_SAFE
+ QMutexLocker locker(&s_mutex);
+#endif
+ s_fileIdCounter = 0;
+ s_fileIdMap.clear();
+ s_idFileMap.clear();
}
-bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
+bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QString *cont = &m_files[fn];
+ QString *cont = &m_files[id];
+ Q_UNUSED(flags)
if (mode & QIODevice::Append)
*cont += contents;
else
*cont = contents;
Q_UNUSED(errStr)
- Q_UNUSED(exe)
return true;
#else
- QFileInfo qfi(fn);
+ QFileInfo qfi(fileNameForId(id));
if (!QDir::current().mkpath(qfi.path())) {
*errStr = fL1S("Cannot create parent directory");
return false;
}
QByteArray bytes = contents.toLocal8Bit();
- QFile cfile(fn);
+ QFile cfile(qfi.filePath());
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (cfile.readAll() == bytes) {
- if (exe) {
+ if (flags & VfsExecutable) {
cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
} else {
@@ -93,70 +170,78 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
*errStr = cfile.errorString();
return false;
}
- if (exe)
+ if (flags & VfsExecutable)
cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
return true;
#endif
}
-bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr)
+QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errStr)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QHash<QString, QString>::ConstIterator it = m_files.constFind(fn);
+ auto it = m_files.constFind(id);
if (it != m_files.constEnd()) {
if (it->constData() == m_magicMissing.constData()) {
*errStr = fL1S("No such file or directory");
- return false;
+ return ReadNotFound;
}
if (it->constData() != m_magicExisting.constData()) {
*contents = *it;
- return true;
+ return ReadOk;
}
}
#endif
- QFile file(fn);
+ QFile file(fileNameForId(id));
if (!file.open(QIODevice::ReadOnly)) {
+ if (!file.exists()) {
#ifndef PROEVALUATOR_FULL
- if (!IoUtils::exists(fn)) {
- m_files[fn] = m_magicMissing;
- *errStr = fL1S("No such file or directory");
- } else
+ m_files[id] = m_magicMissing;
#endif
- *errStr = file.errorString();
- return false;
+ *errStr = fL1S("No such file or directory");
+ return ReadNotFound;
+ }
+ *errStr = file.errorString();
+ return ReadOtherError;
}
#ifndef PROEVALUATOR_FULL
- m_files[fn] = m_magicExisting;
+ m_files[id] = m_magicExisting;
#endif
QByteArray bcont = file.readAll();
if (bcont.startsWith("\xef\xbb\xbf")) {
// UTF-8 BOM will cause subtle errors
*errStr = fL1S("Unexpected UTF-8 BOM");
- return false;
+ return ReadOtherError;
}
- *contents = QString::fromLocal8Bit(bcont);
- return true;
+ *contents =
+#ifndef QT_NO_TEXTCODEC
+ m_textCodec ? m_textCodec->toUnicode(bcont) :
+#endif
+ QString::fromLocal8Bit(bcont);
+ return ReadOk;
}
-bool QMakeVfs::exists(const QString &fn)
+bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QHash<QString, QString>::ConstIterator it = m_files.constFind(fn);
+ int id = idForFileName(fn, flags);
+ auto it = m_files.constFind(id);
if (it != m_files.constEnd())
return it->constData() != m_magicMissing.constData();
+#else
+ Q_UNUSED(flags)
#endif
- bool ex = IoUtils::exists(fn);
+ bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
#ifndef PROEVALUATOR_FULL
- m_files[fn] = ex ? m_magicExisting : m_magicMissing;
+ m_files[id] = ex ? m_magicExisting : m_magicMissing;
#endif
return ex;
}
@@ -168,7 +253,7 @@ void QMakeVfs::invalidateCache()
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QHash<QString, QString>::Iterator it = m_files.begin(), eit = m_files.end();
+ auto it = m_files.begin(), eit = m_files.end();
while (it != eit) {
if (it->constData() == m_magicMissing.constData()
||it->constData() == m_magicExisting.constData())
@@ -188,4 +273,11 @@ void QMakeVfs::invalidateContents()
}
#endif
+#ifndef QT_NO_TEXTCODEC
+void QMakeVfs::setTextCodec(const QTextCodec *textCodec)
+{
+ m_textCodec = textCodec;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h
index 8677ba08c1..1217225471 100644
--- a/qmake/library/qmakevfs.h
+++ b/qmake/library/qmakevfs.h
@@ -31,12 +31,20 @@
#include "qmake_global.h"
-# include <qiodevice.h>
-#ifndef PROEVALUATOR_FULL
-# include <qhash.h>
-# include <qstring.h>
-# ifdef PROEVALUATOR_THREAD_SAFE
-# include <qmutex.h>
+#include <qiodevice.h>
+#include <qhash.h>
+#include <qstring.h>
+#ifdef PROEVALUATOR_THREAD_SAFE
+# include <qmutex.h>
+#endif
+
+#ifndef QT_NO_TEXTCODEC
+QT_FORWARD_DECLARE_CLASS(QTextCodec)
+#endif
+
+#ifdef PROEVALUATOR_DUAL_VFS
+# ifndef PROEVALUATOR_CUMULATIVE
+# error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE
# endif
#endif
@@ -45,28 +53,85 @@ QT_BEGIN_NAMESPACE
class QMAKE_EXPORT QMakeVfs
{
public:
+ enum ReadResult {
+ ReadOk,
+ ReadNotFound,
+ ReadOtherError
+ };
+
+ enum VfsFlag {
+ VfsExecutable = 1,
+ VfsExact = 0,
+#ifdef PROEVALUATOR_DUAL_VFS
+ VfsCumulative = 2,
+ VfsCreate = 4,
+ VfsCreatedOnly = 8,
+#else
+ VfsCumulative = 0,
+ VfsCreate = 0,
+ VfsCreatedOnly = 0,
+#endif
+ VfsAccessedOnly = 16
+ };
+ Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
+
QMakeVfs();
- bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr);
- bool readFile(const QString &fn, QString *contents, QString *errStr);
- bool exists(const QString &fn);
+ int idForFileName(const QString &fn, VfsFlags flags);
+ QString fileNameForId(int id);
+ static void clearIds();
+ bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
+ ReadResult readFile(int id, QString *contents, QString *errStr);
+ bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
#ifndef PROEVALUATOR_FULL
void invalidateCache();
void invalidateContents();
#endif
+#ifndef QT_NO_TEXTCODEC
+ void setTextCodec(const QTextCodec *textCodec);
+#endif
+
private:
+#ifdef PROEVALUATOR_THREAD_SAFE
+ static QMutex s_mutex;
+#endif
+ static QAtomicInt s_fileIdCounter;
+ // Qt Creator's ProFile cache is a singleton to maximize its cross-project
+ // effectiveness (shared prf files from QtVersions).
+ // For this to actually work, real files need a global mapping.
+ // This is fine, because the namespace of real files is indeed global.
+ static QHash<QString, int> s_fileIdMap;
+ static QHash<int, QString> s_idFileMap;
+#ifdef PROEVALUATOR_DUAL_VFS
+# ifdef PROEVALUATOR_THREAD_SAFE
+ // The simple way to avoid recursing m_mutex.
+ QMutex m_vmutex;
+# endif
+ // Virtual files are bound to the project context they were created in,
+ // so their ids need to be local as well.
+ // We violate that rule in lupdate (which has a non-dual VFS), but that
+ // does not matter, because it has only one project context anyway.
+ QHash<QString, int> m_virtualFileIdMap[2]; // Exact and cumulative
+ QHash<int, QString> m_virtualIdFileMap; // Only one map, as ids are unique across realms.
+#endif
+
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutex m_mutex;
# endif
- QHash<QString, QString> m_files;
+ QHash<int, QString> m_files;
QString m_magicMissing;
QString m_magicExisting;
#endif
+#ifndef QT_NO_TEXTCODEC
+ const QTextCodec *m_textCodec;
+#endif
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags)
+
QT_END_NAMESPACE
#endif // QMAKEVFS_H
diff --git a/qmake/project.cpp b/qmake/project.cpp
index e8509ad096..e6bdb04bfb 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -123,7 +123,7 @@ QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList>
ProString QMakeProject::expand(const QString &expr, const QString &where, int line)
{
ProString ret;
- ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), where, line,
+ ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), 0, where, line,
QMakeParser::ValueGrammar);
if (pro->isOk()) {
m_current.pro = pro;
diff --git a/src/3rdparty/sqlite/qt_attribution.json b/src/3rdparty/sqlite/qt_attribution.json
index 3800477239..b470e7e38c 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.22.0",
+ "Version": "3.23.1",
"License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
}
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 73c69efbd5..c49f89c923 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.22.0. By combining all the individual C code files into this
+** version 3.23.1. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -213,7 +213,7 @@ static const char * const sqlite3azCompileOpt[] = {
"ENABLE_BATCH_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_CEROD
- "ENABLE_CEROD",
+ "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
@@ -1147,9 +1147,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.22.0"
-#define SQLITE_VERSION_NUMBER 3022000
-#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"
+#define SQLITE_VERSION "3.23.1"
+#define SQLITE_VERSION_NUMBER 3023001
+#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -2088,6 +2088,12 @@ struct sqlite3_io_methods {
** so that all subsequent write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
+** a file lock using the xLock or xShmLock methods of the VFS to wait
+** for up to M milliseconds before failing, where M is the single
+** unsigned integer parameter.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -2122,6 +2128,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
+#define SQLITE_FCNTL_LOCK_TIMEOUT 34
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -3078,11 +3085,13 @@ struct sqlite3_mem_methods {
** connections at all to the database. If so, it performs a checkpoint
** operation before closing the connection. This option may be used to
** override this behaviour. The first parameter passed to this operation
-** is an integer - non-zero to disable checkpoints-on-close, or zero (the
-** default) to enable them. The second parameter is a pointer to an integer
+** is an integer - positive to disable checkpoints-on-close, or zero (the
+** default) to enable them, and negative to leave the setting unchanged.
+** The second parameter is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
+**
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
@@ -3092,13 +3101,20 @@ struct sqlite3_mem_methods {
** slower. But the QPSG has the advantage of more predictable behavior. With
** the QPSG active, SQLite will always use the same query plan in the field as
** was used during testing in the lab.
+** The first argument to this setting is an integer which is 0 to disable
+** the QPSG, positive to enable QPSG, or negative to leave the setting
+** unchanged. The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether the QPSG is disabled or enabled
+** following this call.
** </dd>
+**
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
** behavior. The first parameter passed to this operation is an integer -
-** non-zero to enable output for trigger programs, or zero to disable it.
+** positive to enable output for trigger programs, or zero to disable it,
+** or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which is written
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
** it is not disabled, 1 if it is.
@@ -3520,16 +3536,16 @@ SQLITE_API void sqlite3_free_table(char **result);
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
-** These routines understand most of the common K&R formatting options,
-** plus some additional non-standard formats, detailed below.
-** Note that some of the more obscure formatting options from recent
-** C-library standards are omitted from this implementation.
+** These routines understand most of the common formatting options from
+** the standard library printf()
+** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
+** See the [built-in printf()] documentation for details.
**
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
-** results into memory obtained from [sqlite3_malloc()].
+** results into memory obtained from [sqlite3_malloc64()].
** The strings returned by these two routines should be
** released by [sqlite3_free()]. ^Both routines return a
-** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
+** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
** memory to hold the resulting string.
**
** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
@@ -3553,71 +3569,7 @@ SQLITE_API void sqlite3_free_table(char **result);
**
** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
**
-** These routines all implement some additional formatting
-** options that are useful for constructing SQL statements.
-** All of the usual printf() formatting options apply. In addition, there
-** is are "%q", "%Q", "%w" and "%z" options.
-**
-** ^(The %q option works like %s in that it substitutes a nul-terminated
-** string from the argument list. But %q also doubles every '\'' character.
-** %q is designed for use inside a string literal.)^ By doubling each '\''
-** character it escapes that character and allows it to be inserted into
-** the string.
-**
-** For example, assume the string variable zText contains text as follows:
-**
-** <blockquote><pre>
-** char *zText = "It's a happy day!";
-** </pre></blockquote>
-**
-** One can use this text in an SQL statement as follows:
-**
-** <blockquote><pre>
-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-** sqlite3_exec(db, zSQL, 0, 0, 0);
-** sqlite3_free(zSQL);
-** </pre></blockquote>
-**
-** Because the %q format string is used, the '\'' character in zText
-** is escaped and the SQL generated is as follows:
-**
-** <blockquote><pre>
-** INSERT INTO table1 VALUES('It''s a happy day!')
-** </pre></blockquote>
-**
-** This is correct. Had we used %s instead of %q, the generated SQL
-** would have looked like this:
-**
-** <blockquote><pre>
-** INSERT INTO table1 VALUES('It's a happy day!');
-** </pre></blockquote>
-**
-** This second example is an SQL syntax error. As a general rule you should
-** always use %q instead of %s when inserting text into a string literal.
-**
-** ^(The %Q option works like %q except it also adds single quotes around
-** the outside of the total string. Additionally, if the parameter in the
-** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
-** single quotes).)^ So, for example, one could say:
-**
-** <blockquote><pre>
-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-** sqlite3_exec(db, zSQL, 0, 0, 0);
-** sqlite3_free(zSQL);
-** </pre></blockquote>
-**
-** The code above will render a correct SQL statement in the zSQL
-** variable even if the zText variable is a NULL pointer.
-**
-** ^(The "%w" formatting option is like "%q" except that it expects to
-** be contained within double-quotes instead of single quotes, and it
-** escapes the double-quote character instead of the single-quote
-** character.)^ The "%w" formatting option is intended for safely inserting
-** table and column names into a constructed SQL statement.
-**
-** ^(The "%z" formatting option works like "%s" but with the
-** addition that after the string has been read and copied into
-** the result, [sqlite3_free()] is called on the input string.)^
+** See also: [built-in printf()], [printf() SQL function]
*/
SQLITE_API char *sqlite3_mprintf(const char*,...);
SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
@@ -4683,13 +4635,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** </li>
+** </ol>
**
** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
** the extra prepFlags parameter, which is a bit array consisting of zero or
** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
** sqlite3_prepare_v2() interface works exactly the same as
** sqlite3_prepare_v3() with a zero prepFlags parameter.
-** </ol>
*/
SQLITE_API int sqlite3_prepare(
sqlite3 *db, /* Database handle */
@@ -8318,6 +8270,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
**
+** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
+** <dd>This parameter returns the number of dirty cache entries that have
+** been written to disk in the middle of a transaction due to the page
+** cache overflowing. Transactions are more efficient if they are written
+** to disk all at once. When pages spill mid-transaction, that introduces
+** additional overhead. This parameter can be used help identify
+** inefficiencies that can be resolve by increasing the cache size.
+** </dd>
+**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
** <dd>This parameter returns zero for the current value if and only if
** all foreign key constraints (deferred or immediate) have been
@@ -8337,7 +8298,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_WRITE 9
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
-#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_CACHE_SPILL 12
+#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
/*
@@ -9818,6 +9780,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
/*
+** CAPI3REF: Serialize a database
+**
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
+** that is a serialization of the S database on [database connection] D.
+** If P is not a NULL pointer, then the size of the database in bytes
+** is written into *P.
+**
+** For an ordinary on-disk database file, the serialization is just a
+** copy of the disk file. For an in-memory database or a "TEMP" database,
+** the serialization is the same sequence of bytes which would be written
+** to disk if that database where backed up to disk.
+**
+** The usual case is that sqlite3_serialize() copies the serialization of
+** the database into memory obtained from [sqlite3_malloc64()] and returns
+** a pointer to that memory. The caller is responsible for freeing the
+** returned value to avoid a memory leak. However, if the F argument
+** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
+** are made, and the sqlite3_serialize() function will return a pointer
+** to the contiguous memory representation of the database that SQLite
+** is currently using for that database, or NULL if the no such contiguous
+** memory representation of the database exists. A contiguous memory
+** representation of the database will usually only exist if there has
+** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
+** values of D and S.
+** The size of the database is written into *P even if the
+** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
+** of the database exists.
+**
+** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
+** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
+** allocation error occurs.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_DESERIALIZE] option.
+*/
+SQLITE_API unsigned char *sqlite3_serialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */
+ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
+ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3_serialize
+**
+** Zero or more of the following constants can be OR-ed together for
+** the F argument to [sqlite3_serialize(D,S,P,F)].
+**
+** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return
+** a pointer to contiguous in-memory database that it is currently using,
+** without making a copy of the database. If SQLite is not currently using
+** a contiguous in-memory database, then this option causes
+** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be
+** using a contiguous in-memory database if it has been initialized by a
+** prior call to [sqlite3_deserialize()].
+*/
+#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */
+
+/*
+** CAPI3REF: Deserialize a database
+**
+** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
+** [database connection] D to disconnect from database S and then
+** reopen S as an in-memory database based on the serialization contained
+** in P. The serialized database P is N bytes in size. M is the size of
+** the buffer P, which might be larger than N. If M is larger than N, and
+** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
+** permitted to add content to the in-memory database as long as the total
+** size does not exceed M bytes.
+**
+** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
+** invoke sqlite3_free() on the serialization buffer when the database
+** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
+** SQLite will try to increase the buffer size using sqlite3_realloc64()
+** if writes on the database cause it to grow larger than M bytes.
+**
+** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
+** database is currently in a read transaction or is involved in a backup
+** operation.
+**
+** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
+** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
+** [sqlite3_free()] is invoked on argument P prior to returning.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_DESERIALIZE] option.
+*/
+SQLITE_API int sqlite3_deserialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which DB to reopen with the deserialization */
+ unsigned char *pData, /* The serialized database content */
+ sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szBuf, /* Total size of buffer pData[] */
+ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3_deserialize()
+**
+** The following are allowed values for 6th argument (the F argument) to
+** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
+**
+** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
+** in the P argument is held in memory obtained from [sqlite3_malloc64()]
+** and that SQLite should take ownership of this memory and automatically
+** free it when it has finished using it. Without this flag, the caller
+** is resposible for freeing any dynamically allocated memory.
+**
+** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
+** grow the size of the database using calls to [sqlite3_realloc64()]. This
+** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used.
+** Without this flag, the deserialized database cannot increase in size beyond
+** the number of bytes specified by the M parameter.
+**
+** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database
+** should be treated as read-only.
+*/
+#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */
+#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
+#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
+
+/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
@@ -9964,16 +10048,23 @@ extern "C" {
/*
** CAPI3REF: Session Object Handle
+**
+** An instance of this object is a [session] that can be used to
+** record changes to a database.
*/
typedef struct sqlite3_session sqlite3_session;
/*
** CAPI3REF: Changeset Iterator Handle
+**
+** An instance of this object acts as a cursor for iterating
+** over the elements of a [changeset] or [patchset].
*/
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
/*
** CAPI3REF: Create A New Session Object
+** CONSTRUCTOR: sqlite3_session
**
** Create a new session object attached to database handle db. If successful,
** a pointer to the new object is written to *ppSession and SQLITE_OK is
@@ -10010,6 +10101,7 @@ SQLITE_API int sqlite3session_create(
/*
** CAPI3REF: Delete A Session Object
+** DESTRUCTOR: sqlite3_session
**
** Delete a session object previously allocated using
** [sqlite3session_create()]. Once a session object has been deleted, the
@@ -10025,6 +10117,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPI3REF: Enable Or Disable A Session Object
+** METHOD: sqlite3_session
**
** Enable or disable the recording of changes by a session object. When
** enabled, a session object records changes made to the database. When
@@ -10044,6 +10137,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
/*
** CAPI3REF: Set Or Clear the Indirect Change Flag
+** METHOD: sqlite3_session
**
** Each change recorded by a session object is marked as either direct or
** indirect. A change is marked as indirect if either:
@@ -10073,6 +10167,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
/*
** CAPI3REF: Attach A Table To A Session Object
+** METHOD: sqlite3_session
**
** If argument zTab is not NULL, then it is the name of a table to attach
** to the session object passed as the first argument. All subsequent changes
@@ -10135,6 +10230,7 @@ SQLITE_API int sqlite3session_attach(
/*
** CAPI3REF: Set a table filter on a Session Object.
+** METHOD: sqlite3_session
**
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session object, the filter is called
@@ -10153,6 +10249,7 @@ SQLITE_API void sqlite3session_table_filter(
/*
** CAPI3REF: Generate A Changeset From A Session Object
+** METHOD: sqlite3_session
**
** Obtain a changeset containing changes to the tables attached to the
** session object passed as the first argument. If successful,
@@ -10262,7 +10359,8 @@ SQLITE_API int sqlite3session_changeset(
);
/*
-** CAPI3REF: Load The Difference Between Tables Into A Session
+** CAPI3REF: Load The Difference Between Tables Into A Session
+** METHOD: sqlite3_session
**
** If it is not already attached to the session object passed as the first
** argument, this function attaches table zTbl in the same manner as the
@@ -10327,6 +10425,7 @@ SQLITE_API int sqlite3session_diff(
/*
** CAPI3REF: Generate A Patchset From A Session Object
+** METHOD: sqlite3_session
**
** The differences between a patchset and a changeset are that:
**
@@ -10378,6 +10477,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
+** CONSTRUCTOR: sqlite3_changeset_iter
**
** Create an iterator used to iterate through the contents of a changeset.
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
@@ -10418,6 +10518,7 @@ SQLITE_API int sqlite3changeset_start(
/*
** CAPI3REF: Advance A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function may only be used with iterators created by function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
@@ -10442,6 +10543,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -10476,6 +10578,7 @@ SQLITE_API int sqlite3changeset_op(
/*
** CAPI3REF: Obtain The Primary Key Definition Of A Table
+** METHOD: sqlite3_changeset_iter
**
** For each modified table, a changeset includes the following:
**
@@ -10507,6 +10610,7 @@ SQLITE_API int sqlite3changeset_pk(
/*
** CAPI3REF: Obtain old.* Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -10537,6 +10641,7 @@ SQLITE_API int sqlite3changeset_old(
/*
** CAPI3REF: Obtain new.* Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -10570,6 +10675,7 @@ SQLITE_API int sqlite3changeset_new(
/*
** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function should only be used with iterator objects passed to a
** conflict-handler callback by [sqlite3changeset_apply()] with either
@@ -10597,6 +10703,7 @@ SQLITE_API int sqlite3changeset_conflict(
/*
** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
+** METHOD: sqlite3_changeset_iter
**
** This function may only be called with an iterator passed to an
** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
@@ -10613,6 +10720,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
/*
** CAPI3REF: Finalize A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function is used to finalize an iterator allocated with
** [sqlite3changeset_start()].
@@ -10629,6 +10737,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** to that error is returned by this function. Otherwise, SQLITE_OK is
** returned. This is to allow the following pattern (pseudo-code):
**
+** <pre>
** sqlite3changeset_start();
** while( SQLITE_ROW==sqlite3changeset_next() ){
** // Do something with change.
@@ -10637,6 +10746,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** if( rc!=SQLITE_OK ){
** // An error has occurred
** }
+** </pre>
*/
SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
@@ -10684,6 +10794,7 @@ SQLITE_API int sqlite3changeset_invert(
** sqlite3_changegroup object. Calling it produces similar results as the
** following code fragment:
**
+** <pre>
** sqlite3_changegroup *pGrp;
** rc = sqlite3_changegroup_new(&pGrp);
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
@@ -10694,6 +10805,7 @@ SQLITE_API int sqlite3changeset_invert(
** *ppOut = 0;
** *pnOut = 0;
** }
+** </pre>
**
** Refer to the sqlite3_changegroup documentation below for details.
*/
@@ -10709,11 +10821,15 @@ SQLITE_API int sqlite3changeset_concat(
/*
** CAPI3REF: Changegroup Handle
+**
+** A changegroup is an object used to combine two or more
+** [changesets] or [patchsets]
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
** CAPI3REF: Create A New Changegroup Object
+** CONSTRUCTOR: sqlite3_changegroup
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
@@ -10751,6 +10867,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** CAPI3REF: Add A Changeset To A Changegroup
+** METHOD: sqlite3_changegroup
**
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
@@ -10828,6 +10945,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
+** METHOD: sqlite3_changegroup
**
** Obtain a buffer containing a changeset (or patchset) representing the
** current contents of the changegroup. If the inputs to the changegroup
@@ -10858,25 +10976,25 @@ SQLITE_API int sqlite3changegroup_output(
/*
** CAPI3REF: Delete A Changegroup Object
+** DESTRUCTOR: sqlite3_changegroup
*/
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
**
-** Apply a changeset to a database. This function attempts to update the
-** "main" database attached to handle db with the changes found in the
-** changeset passed via the second and third arguments.
+** Apply a changeset or patchset to a database. These functions attempt to
+** update the "main" database attached to handle db with the changes found in
+** the changeset passed via the second and third arguments.
**
-** The fourth argument (xFilter) passed to this function is the "filter
+** The fourth argument (xFilter) passed to these functions is the "filter
** callback". If it is not NULL, then for each table affected by at least one
** change in the changeset, the filter callback is invoked with
** the table name as the second argument, and a copy of the context pointer
-** passed as the sixth argument to this function as the first. If the "filter
-** callback" returns zero, then no attempt is made to apply any changes to
-** the table. Otherwise, if the return value is non-zero or the xFilter
-** argument to this function is NULL, all changes related to the table are
-** attempted.
+** passed as the sixth argument as the first. If the "filter callback"
+** returns zero, then no attempt is made to apply any changes to the table.
+** Otherwise, if the return value is non-zero or the xFilter argument to
+** is NULL, all changes related to the table are attempted.
**
** For each table that is not excluded by the filter callback, this function
** tests that the target database contains a compatible table. A table is
@@ -10921,7 +11039,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** <dl>
** <dt>DELETE Changes<dd>
-** For each DELETE change, this function checks if the target database
+** For each DELETE change, the function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all non-primary key columns also match the values stored in
@@ -10966,7 +11084,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** [SQLITE_CHANGESET_REPLACE].
**
** <dt>UPDATE Changes<dd>
-** For each UPDATE change, this function checks if the target database
+** For each UPDATE change, the function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all modified non-primary key columns also match the values
@@ -10997,11 +11115,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** This can be used to further customize the applications conflict
** resolution strategy.
**
-** All changes made by this function are enclosed in a savepoint transaction.
+** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
+**
+** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
+** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
+** may set (*ppRebase) to point to a "rebase" that may be used with the
+** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
+** is set to the size of the buffer in bytes. It is the responsibility of the
+** caller to eventually free any such buffer using sqlite3_free(). The buffer
+** is only allocated and populated if one or more conflicts were encountered
+** while applying the patchset. See comments surrounding the sqlite3_rebaser
+** APIs for further details.
+**
+** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter.
+**
+** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b>
+** and therefore subject to change.
*/
SQLITE_API int sqlite3changeset_apply(
sqlite3 *db, /* Apply change to "main" db of this handle */
@@ -11018,6 +11153,41 @@ SQLITE_API int sqlite3changeset_apply(
),
void *pCtx /* First argument passed to xConflict */
);
+SQLITE_API int sqlite3changeset_apply_v2(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int nChangeset, /* Size of changeset in bytes */
+ void *pChangeset, /* Changeset blob */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
+ int flags /* Combination of SESSION_APPLY_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_apply_v2
+**
+** The following flags may passed via the 9th parameter to
+** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]:
+**
+** <dl>
+** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd>
+** Usually, the sessions module encloses all operations performed by
+** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The
+** SAVEPOINT is committed if the changeset or patchset is successfully
+** applied, or rolled back if an error occurs. Specifying this flag
+** causes the sessions module to omit this savepoint. In this case, if the
+** caller has an open transaction or savepoint when apply_v2() is called,
+** it may revert the partially applied changeset by rolling it back.
+*/
+#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -11115,6 +11285,161 @@ SQLITE_API int sqlite3changeset_apply(
#define SQLITE_CHANGESET_REPLACE 1
#define SQLITE_CHANGESET_ABORT 2
+/*
+** CAPI3REF: Rebasing changesets
+** EXPERIMENTAL
+**
+** Suppose there is a site hosting a database in state S0. And that
+** modifications are made that move that database to state S1 and a
+** changeset recorded (the "local" changeset). Then, a changeset based
+** on S0 is received from another site (the "remote" changeset) and
+** applied to the database. The database is then in state
+** (S1+"remote"), where the exact state depends on any conflict
+** resolution decisions (OMIT or REPLACE) made while applying "remote".
+** Rebasing a changeset is to update it to take those conflict
+** resolution decisions into account, so that the same conflicts
+** do not have to be resolved elsewhere in the network.
+**
+** For example, if both the local and remote changesets contain an
+** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)":
+**
+** local: INSERT INTO t1 VALUES(1, 'v1');
+** remote: INSERT INTO t1 VALUES(1, 'v2');
+**
+** and the conflict resolution is REPLACE, then the INSERT change is
+** removed from the local changeset (it was overridden). Or, if the
+** conflict resolution was "OMIT", then the local changeset is modified
+** to instead contain:
+**
+** UPDATE t1 SET b = 'v2' WHERE a=1;
+**
+** Changes within the local changeset are rebased as follows:
+**
+** <dl>
+** <dt>Local INSERT<dd>
+** This may only conflict with a remote INSERT. If the conflict
+** resolution was OMIT, then add an UPDATE change to the rebased
+** changeset. Or, if the conflict resolution was REPLACE, add
+** nothing to the rebased changeset.
+**
+** <dt>Local DELETE<dd>
+** This may conflict with a remote UPDATE or DELETE. In both cases the
+** only possible resolution is OMIT. If the remote operation was a
+** DELETE, then add no change to the rebased changeset. If the remote
+** operation was an UPDATE, then the old.* fields of change are updated
+** to reflect the new.* values in the UPDATE.
+**
+** <dt>Local UPDATE<dd>
+** This may conflict with a remote UPDATE or DELETE. If it conflicts
+** with a DELETE, and the conflict resolution was OMIT, then the update
+** is changed into an INSERT. Any undefined values in the new.* record
+** from the update change are filled in using the old.* values from
+** the conflicting DELETE. Or, if the conflict resolution was REPLACE,
+** the UPDATE change is simply omitted from the rebased changeset.
+**
+** If conflict is with a remote UPDATE and the resolution is OMIT, then
+** the old.* values are rebased using the new.* values in the remote
+** change. Or, if the resolution is REPLACE, then the change is copied
+** into the rebased changeset with updates to columns also updated by
+** the conflicting remote UPDATE removed. If this means no columns would
+** be updated, the change is omitted.
+** </dl>
+**
+** A local change may be rebased against multiple remote changes
+** simultaneously. If a single key is modified by multiple remote
+** changesets, they are combined as follows before the local changeset
+** is rebased:
+**
+** <ul>
+** <li> If there has been one or more REPLACE resolutions on a
+** key, it is rebased according to a REPLACE.
+**
+** <li> If there have been no REPLACE resolutions on a key, then
+** the local changeset is rebased according to the most recent
+** of the OMIT resolutions.
+** </ul>
+**
+** Note that conflict resolutions from multiple remote changesets are
+** combined on a per-field basis, not per-row. This means that in the
+** case of multiple remote UPDATE operations, some fields of a single
+** local change may be rebased for REPLACE while others are rebased for
+** OMIT.
+**
+** In order to rebase a local changeset, the remote changeset must first
+** be applied to the local database using sqlite3changeset_apply_v2() and
+** the buffer of rebase information captured. Then:
+**
+** <ol>
+** <li> An sqlite3_rebaser object is created by calling
+** sqlite3rebaser_create().
+** <li> The new object is configured with the rebase buffer obtained from
+** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure().
+** If the local changeset is to be rebased against multiple remote
+** changesets, then sqlite3rebaser_configure() should be called
+** multiple times, in the same order that the multiple
+** sqlite3changeset_apply_v2() calls were made.
+** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase().
+** <li> The sqlite3_rebaser object is deleted by calling
+** sqlite3rebaser_delete().
+** </ol>
+*/
+typedef struct sqlite3_rebaser sqlite3_rebaser;
+
+/*
+** CAPI3REF: Create a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Allocate a new changeset rebaser object. If successful, set (*ppNew) to
+** point to the new object and return SQLITE_OK. Otherwise, if an error
+** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
+** to NULL.
+*/
+SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
+
+/*
+** CAPI3REF: Configure a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Configure the changeset rebaser object to rebase changesets according
+** to the conflict resolutions described by buffer pRebase (size nRebase
+** bytes), which must have been obtained from a previous call to
+** sqlite3changeset_apply_v2().
+*/
+SQLITE_API int sqlite3rebaser_configure(
+ sqlite3_rebaser*,
+ int nRebase, const void *pRebase
+);
+
+/*
+** CAPI3REF: Rebase a changeset
+** EXPERIMENTAL
+**
+** Argument pIn must point to a buffer containing a changeset nIn bytes
+** in size. This function allocates and populates a buffer with a copy
+** of the changeset rebased rebased according to the configuration of the
+** rebaser object passed as the first argument. If successful, (*ppOut)
+** is set to point to the new buffer containing the rebased changset and
+** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
+** responsibility of the caller to eventually free the new buffer using
+** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
+** are set to zero and an SQLite error code returned.
+*/
+SQLITE_API int sqlite3rebaser_rebase(
+ sqlite3_rebaser*,
+ int nIn, const void *pIn,
+ int *pnOut, void **ppOut
+);
+
+/*
+** CAPI3REF: Delete a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Delete the changeset rebaser object and all associated resources. There
+** should be one call to this function for each successful invocation
+** of sqlite3rebaser_create().
+*/
+SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
+
/*
** CAPI3REF: Streaming Versions of API functions.
**
@@ -11124,6 +11449,7 @@ SQLITE_API int sqlite3changeset_apply(
** <table border=1 style="margin-left:8ex;margin-right:8ex">
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply]
+** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2]
** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat]
** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert]
** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start]
@@ -11219,6 +11545,23 @@ SQLITE_API int sqlite3changeset_apply_strm(
),
void *pCtx /* First argument passed to xConflict */
);
+SQLITE_API int sqlite3changeset_apply_v2_strm(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
+ void *pIn, /* First arg for xInput */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
+);
SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
@@ -11256,6 +11599,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
+SQLITE_API int sqlite3rebaser_rebase_strm(
+ sqlite3_rebaser *pRebaser,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int (*xOutput)(void *pOut, const void *pData, int nData),
+ void *pOut
+);
/*
@@ -12673,23 +13023,25 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_INDEX 140
#define TK_ALTER 141
#define TK_ADD 142
-#define TK_ISNOT 143
-#define TK_FUNCTION 144
-#define TK_COLUMN 145
-#define TK_AGG_FUNCTION 146
-#define TK_AGG_COLUMN 147
-#define TK_UMINUS 148
-#define TK_UPLUS 149
-#define TK_REGISTER 150
-#define TK_VECTOR 151
-#define TK_SELECT_COLUMN 152
-#define TK_IF_NULL_ROW 153
-#define TK_ASTERISK 154
-#define TK_SPAN 155
-#define TK_END_OF_FILE 156
-#define TK_UNCLOSED_STRING 157
-#define TK_SPACE 158
-#define TK_ILLEGAL 159
+#define TK_TRUEFALSE 143
+#define TK_ISNOT 144
+#define TK_FUNCTION 145
+#define TK_COLUMN 146
+#define TK_AGG_FUNCTION 147
+#define TK_AGG_COLUMN 148
+#define TK_UMINUS 149
+#define TK_UPLUS 150
+#define TK_TRUTH 151
+#define TK_REGISTER 152
+#define TK_VECTOR 153
+#define TK_SELECT_COLUMN 154
+#define TK_IF_NULL_ROW 155
+#define TK_ASTERISK 156
+#define TK_SPAN 157
+#define TK_END_OF_FILE 158
+#define TK_UNCLOSED_STRING 159
+#define TK_SPACE 160
+#define TK_ILLEGAL 161
/* The token codes above must all fit in 8 bits */
#define TKFLG_MASK 0xff
@@ -13133,9 +13485,10 @@ typedef INT16_TYPE LogEst;
*/
typedef struct BusyHandler BusyHandler;
struct BusyHandler {
- int (*xFunc)(void *,int); /* The busy callback */
- void *pArg; /* First arg to busy callback */
- int nBusy; /* Incremented with each busy call */
+ int (*xBusyHandler)(void *,int); /* The busy callback */
+ void *pBusyArg; /* First arg to busy callback */
+ int nBusy; /* Incremented with each busy call */
+ u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
};
/*
@@ -13935,80 +14288,81 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */
#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_Offset 96 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_IsTrue 96 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_Column 98 /* synopsis: r[P3]=PX */
-#define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 101 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 102
-#define OP_SetCookie 103
-#define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenDup 107
-#define OP_OpenAutoindex 108 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 109 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 110
-#define OP_SequenceTest 111 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 112 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 113
-#define OP_ColumnsUsed 114
-#define OP_Sequence 115 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 116 /* synopsis: r[P2]=rowid */
-#define OP_Insert 117 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_InsertInt 118 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 119
-#define OP_ResetCount 120
-#define OP_SorterCompare 121 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 122 /* synopsis: r[P2]=data */
-#define OP_RowData 123 /* synopsis: r[P2]=data */
-#define OP_Rowid 124 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 125
-#define OP_SeekEnd 126
-#define OP_SorterInsert 127 /* synopsis: key=r[P2] */
-#define OP_IdxInsert 128 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 129 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 130 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 131 /* synopsis: r[P2]=rowid */
+#define OP_Offset 98 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 99 /* synopsis: r[P3]=PX */
+#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 102 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 103
+#define OP_SetCookie 104
+#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 108
+#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 111
+#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 114
+#define OP_ColumnsUsed 115
+#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */
+#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 120
+#define OP_ResetCount 121
+#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 123 /* synopsis: r[P2]=data */
+#define OP_RowData 124 /* synopsis: r[P2]=data */
+#define OP_Rowid 125 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 126
+#define OP_SeekEnd 127
+#define OP_SorterInsert 128 /* synopsis: key=r[P2] */
+#define OP_IdxInsert 129 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 130 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 131 /* synopsis: Move P3 to P1.rowid if needed */
#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_Destroy 133
-#define OP_Clear 134
-#define OP_ResetSorter 135
-#define OP_CreateBtree 136 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 137
-#define OP_ParseSchema 138
-#define OP_LoadAnalysis 139
-#define OP_DropTable 140
-#define OP_DropIndex 141
-#define OP_DropTrigger 142
-#define OP_IntegrityCk 143
-#define OP_RowSetAdd 144 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 145
-#define OP_FkCounter 146 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 147 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 148 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggStep0 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggFinal 151 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 152
-#define OP_TableLock 153 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 154
-#define OP_VCreate 155
-#define OP_VDestroy 156
-#define OP_VOpen 157
-#define OP_VColumn 158 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 159
-#define OP_Pagecount 160
-#define OP_MaxPgcnt 161
-#define OP_PureFunc0 162
-#define OP_Function0 163 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_PureFunc 164
-#define OP_Function 165 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Trace 166
-#define OP_CursorHint 167
-#define OP_Noop 168
-#define OP_Explain 169
+#define OP_IdxRowid 133 /* synopsis: r[P2]=rowid */
+#define OP_Destroy 134
+#define OP_Clear 135
+#define OP_ResetSorter 136
+#define OP_CreateBtree 137 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 138
+#define OP_ParseSchema 139
+#define OP_LoadAnalysis 140
+#define OP_DropTable 141
+#define OP_DropIndex 142
+#define OP_DropTrigger 143
+#define OP_IntegrityCk 144
+#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 146
+#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 153
+#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 155
+#define OP_VCreate 156
+#define OP_VDestroy 157
+#define OP_VOpen 158
+#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 160
+#define OP_Pagecount 161
+#define OP_MaxPgcnt 162
+#define OP_PureFunc0 163
+#define OP_Function0 164 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_PureFunc 165
+#define OP_Function 166 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Trace 167
+#define OP_CursorHint 168
+#define OP_Noop 169
+#define OP_Explain 170
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -14033,16 +14387,16 @@ typedef struct VdbeOpList VdbeOpList;
/* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\
/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
-/* 96 */ 0x20, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
+/* 96 */ 0x12, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10,\
/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04,\
-/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\
-/* 136 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 144 */ 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00,\
+/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\
+/* 128 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\
+/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\
/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x00,}
+/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00, 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -14343,7 +14697,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*);
@@ -14429,6 +14783,11 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
+#else
+# define sqlite3PagerResetLockTimeout(X)
+#endif
/* Functions used to truncate the database file. */
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
@@ -15248,8 +15607,9 @@ struct sqlite3 {
int newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
- u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
- u8 imposterTable; /* Building an imposter table */
+ unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
+ unsigned imposterTable : 1; /* Building an imposter table */
+ unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -15414,6 +15774,8 @@ struct sqlite3 {
#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
/* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
+#define SQLITE_PushDown 0x1000 /* The push-down optimization */
+#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -15637,6 +15999,7 @@ struct Column {
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
+#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
/*
** A "Collating Sequence" is defined by an instance of the following
@@ -16874,7 +17237,6 @@ struct Parse {
int nMaxArg; /* Max args passed to user function by sub-program */
#if SELECTTRACE_ENABLED
int nSelect; /* Number of SELECT statements seen */
- int nSelectIndent; /* How far to indent SELECTTRACE() output */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
@@ -17238,9 +17600,9 @@ struct Walker {
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
- struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
+ struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
ExprList *pGroupBy; /* GROUP BY clause */
- struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */
+ Select *pSelect; /* HAVING to WHERE clause ctx */
} u;
};
@@ -17704,6 +18066,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
@@ -17721,6 +18084,8 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
+SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
+SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
@@ -17903,6 +18268,10 @@ SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
SQLITE_PRIVATE const char *sqlite3ErrName(int);
#endif
+#ifdef SQLITE_ENABLE_DESERIALIZE
+SQLITE_PRIVATE int sqlite3MemdbInit(void);
+#endif
+
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
@@ -17951,6 +18320,9 @@ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
SQLITE_PRIVATE int sqlite3PendingByte;
#endif
#endif
+#ifdef VDBE_PROFILE
+SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt;
+#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
@@ -17973,7 +18345,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -18574,6 +18946,13 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
{ "1", 1 }
};
+#ifdef VDBE_PROFILE
+/*
+** The following performance counter can be used in place of
+** sqlite3Hwtime() for profiling. This is a no-op on standard builds.
+*/
+SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0;
+#endif
/*
** The value of the "pending" byte must be 0x40000000 (1 byte past the
@@ -18857,8 +19236,6 @@ struct sqlite3_value {
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlite3_bind_pointer() or
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
-** If both MEM_Null and MEM_Zero are set, that means that the value is
-** an unchanging column value from VColumn.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
@@ -18952,7 +19329,6 @@ struct sqlite3_context {
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
- u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
@@ -19122,6 +19498,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
@@ -19515,6 +19892,9 @@ SQLITE_API int sqlite3_db_status(
** pagers the database handle is connected to. *pHighwater is always set
** to zero.
*/
+ case SQLITE_DBSTATUS_CACHE_SPILL:
+ op = SQLITE_DBSTATUS_CACHE_WRITE+1;
+ /* Fall through into the next case */
case SQLITE_DBSTATUS_CACHE_HIT:
case SQLITE_DBSTATUS_CACHE_MISS:
case SQLITE_DBSTATUS_CACHE_WRITE:{
@@ -20935,8 +21315,11 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
** routine has no return value since the return value would be meaningless.
*/
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
+ if( id->pMethods==0 ) return SQLITE_NOTFOUND;
#ifdef SQLITE_TEST
- if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
+ if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
+ && op!=SQLITE_FCNTL_LOCK_TIMEOUT
+ ){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
** transaction has been committed. Injecting a fault at this point
@@ -20953,7 +21336,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
return id->pMethods->xFileControl(id, op, pArg);
}
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
- (void)id->pMethods->xFileControl(id, op, pArg);
+ if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
}
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
@@ -24108,11 +24491,12 @@ struct sqlite3_mutex {
#endif
};
#if SQLITE_MUTEX_NREF
-#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
+# define SQLITE3_MUTEX_INITIALIZER(id) \
+ {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0}
#elif defined(SQLITE_ENABLE_API_ARMOR)
-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 }
+# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id }
#else
-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER }
#endif
/*
@@ -24209,18 +24593,18 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
*/
static sqlite3_mutex *pthreadMutexAlloc(int iType){
static sqlite3_mutex staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER
+ SQLITE3_MUTEX_INITIALIZER(2),
+ SQLITE3_MUTEX_INITIALIZER(3),
+ SQLITE3_MUTEX_INITIALIZER(4),
+ SQLITE3_MUTEX_INITIALIZER(5),
+ SQLITE3_MUTEX_INITIALIZER(6),
+ SQLITE3_MUTEX_INITIALIZER(7),
+ SQLITE3_MUTEX_INITIALIZER(8),
+ SQLITE3_MUTEX_INITIALIZER(9),
+ SQLITE3_MUTEX_INITIALIZER(10),
+ SQLITE3_MUTEX_INITIALIZER(11),
+ SQLITE3_MUTEX_INITIALIZER(12),
+ SQLITE3_MUTEX_INITIALIZER(13)
};
sqlite3_mutex *p;
switch( iType ){
@@ -24239,6 +24623,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
pthread_mutex_init(&p->mutex, &recursiveAttr);
pthread_mutexattr_destroy(&recursiveAttr);
#endif
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
+ p->id = SQLITE_MUTEX_RECURSIVE;
+#endif
}
break;
}
@@ -24246,6 +24633,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
pthread_mutex_init(&p->mutex, 0);
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
+ p->id = SQLITE_MUTEX_FAST;
+#endif
}
break;
}
@@ -24261,7 +24651,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
}
}
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
- if( p ) p->id = iType;
+ assert( p==0 || p->id==iType );
#endif
return p;
}
@@ -24778,7 +25168,7 @@ struct sqlite3_mutex {
#ifdef SQLITE_DEBUG
volatile int nRef; /* Number of enterances */
volatile DWORD owner; /* Thread holding this mutex */
- volatile int trace; /* True to trace changes */
+ volatile LONG trace; /* True to trace changes */
#endif
};
@@ -24790,10 +25180,10 @@ struct sqlite3_mutex {
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
#ifdef SQLITE_DEBUG
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
+#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
0L, (DWORD)0, 0 }
#else
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
+#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
#endif
#ifdef SQLITE_DEBUG
@@ -24836,18 +25226,18 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
** Initialize and deinitialize the mutex subsystem.
*/
static sqlite3_mutex winMutex_staticMutexes[] = {
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER,
- SQLITE3_MUTEX_INITIALIZER
+ SQLITE3_MUTEX_INITIALIZER(2),
+ SQLITE3_MUTEX_INITIALIZER(3),
+ SQLITE3_MUTEX_INITIALIZER(4),
+ SQLITE3_MUTEX_INITIALIZER(5),
+ SQLITE3_MUTEX_INITIALIZER(6),
+ SQLITE3_MUTEX_INITIALIZER(7),
+ SQLITE3_MUTEX_INITIALIZER(8),
+ SQLITE3_MUTEX_INITIALIZER(9),
+ SQLITE3_MUTEX_INITIALIZER(10),
+ SQLITE3_MUTEX_INITIALIZER(11),
+ SQLITE3_MUTEX_INITIALIZER(12),
+ SQLITE3_MUTEX_INITIALIZER(13)
};
static int winMutex_isInit = 0;
@@ -24977,15 +25367,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){
}
#endif
p = &winMutex_staticMutexes[iType-2];
- p->id = iType;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
- p->trace = 1;
+ InterlockedCompareExchange(&p->trace, 1, 0);
#endif
#endif
break;
}
}
+ assert( p==0 || p->id==iType );
return p;
}
@@ -26064,6 +26454,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
+ /* pAccum never starts out with an empty buffer that was obtained from
+ ** malloc(). This precondition is required by the mprintf("%z...")
+ ** optimization. */
+ assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
+
bufpt = 0;
if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
pArgList = va_arg(ap, PrintfArguments*);
@@ -26482,9 +26877,38 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
case etCHARX:
if( bArgList ){
bufpt = getTextArg(pArgList);
- c = bufpt ? bufpt[0] : 0;
+ length = 1;
+ if( bufpt ){
+ buf[0] = c = *(bufpt++);
+ if( (c&0xc0)==0xc0 ){
+ while( length<4 && (bufpt[0]&0xc0)==0x80 ){
+ buf[length++] = *(bufpt++);
+ }
+ }
+ }else{
+ buf[0] = 0;
+ }
}else{
- c = va_arg(ap,int);
+ unsigned int ch = va_arg(ap,unsigned int);
+ if( ch<0x00080 ){
+ buf[0] = ch & 0xff;
+ length = 1;
+ }else if( ch<0x00800 ){
+ buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
+ buf[1] = 0x80 + (u8)(ch & 0x3f);
+ length = 2;
+ }else if( ch<0x10000 ){
+ buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
+ buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
+ buf[2] = 0x80 + (u8)(ch & 0x3f);
+ length = 3;
+ }else{
+ buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
+ buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
+ buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
+ buf[3] = 0x80 + (u8)(ch & 0x3f);
+ length = 4;
+ }
}
if( precision>1 ){
width -= precision-1;
@@ -26492,12 +26916,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
sqlite3AppendChar(pAccum, width-1, ' ');
width = 0;
}
- sqlite3AppendChar(pAccum, precision-1, c);
+ while( precision-- > 1 ){
+ sqlite3StrAccumAppend(pAccum, buf, length);
+ }
}
- length = 1;
- buf[0] = c;
bufpt = buf;
- break;
+ flag_altform2 = 1;
+ goto adjust_width_for_utf8;
case etSTRING:
case etDYNSTRING:
if( bArgList ){
@@ -26509,17 +26934,45 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( bufpt==0 ){
bufpt = "";
}else if( xtype==etDYNSTRING ){
+ if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){
+ /* Special optimization for sqlite3_mprintf("%z..."):
+ ** Extend an existing memory allocation rather than creating
+ ** a new one. */
+ assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
+ pAccum->zText = bufpt;
+ pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);
+ pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);
+ pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;
+ length = 0;
+ break;
+ }
zExtra = bufpt;
}
if( precision>=0 ){
- for(length=0; length<precision && bufpt[length]; length++){}
+ if( flag_altform2 ){
+ /* Set length to the number of bytes needed in order to display
+ ** precision characters */
+ unsigned char *z = (unsigned char*)bufpt;
+ while( precision-- > 0 && z[0] ){
+ SQLITE_SKIP_UTF8(z);
+ }
+ length = (int)(z - (unsigned char*)bufpt);
+ }else{
+ for(length=0; length<precision && bufpt[length]; length++){}
+ }
}else{
length = 0x7fffffff & (int)strlen(bufpt);
}
+ adjust_width_for_utf8:
+ if( flag_altform2 && width>0 ){
+ /* Adjust width to account for extra bytes in UTF-8 characters */
+ int ii = length - 1;
+ while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
+ }
break;
- case etSQLESCAPE: /* Escape ' characters */
- case etSQLESCAPE2: /* Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* Escape " characters */
+ case etSQLESCAPE: /* %q: Escape ' characters */
+ case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
+ case etSQLESCAPE3: { /* %w: Escape " characters */
int i, j, k, n, isnull;
int needQuote;
char ch;
@@ -26533,9 +26986,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+ /* For %q, %Q, and %w, the precision is the number of byte (or
+ ** characters if the ! flags is present) to use from the input.
+ ** Because of the extra quoting characters inserted, the number
+ ** of output characters may be larger than the precision.
+ */
k = precision;
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
if( ch==q ) n++;
+ if( flag_altform2 && (ch&0xc0)==0xc0 ){
+ while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
+ }
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 3;
@@ -26558,10 +27019,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( needQuote ) bufpt[j++] = q;
bufpt[j] = 0;
length = j;
- /* The precision in %q and %Q means how many input characters to
- ** consume, not the length of the output...
- ** if( precision>=0 && precision<length ) length = precision; */
- break;
+ goto adjust_width_for_utf8;
}
case etTOKEN: {
Token *pToken;
@@ -26600,7 +27058,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long. The field width is "width". Do
- ** the output.
+ ** the output. Both length and width are in bytes, not characters,
+ ** at this point. If the "!" flag was present on string conversions
+ ** indicating that width and precision should be expressed in characters,
+ ** then the values have been translated prior to reaching this point.
*/
width -= length;
if( width>0 ){
@@ -27115,11 +27576,21 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPush(pView, 1);
}
do{
+#if SELECTTRACE_ENABLED
+ sqlite3TreeViewLine(pView,
+ "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d",
+ ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
+ ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
+ p->zSelName, p, p->selFlags,
+ (int)p->nSelectRow
+ );
+#else
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags,
(int)p->nSelectRow
);
+#endif
if( cnt++ ) sqlite3TreeViewPop(pView);
if( p->pPrior ){
n = 1000;
@@ -27270,6 +27741,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewLine(pView,"NULL");
break;
}
+ case TK_TRUEFALSE: {
+ sqlite3TreeViewLine(pView,
+ sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
+ break;
+ }
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
@@ -27326,6 +27802,19 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
+ case TK_TRUTH: {
+ int x;
+ const char *azOp[] = {
+ "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
+ };
+ assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
+ assert( pExpr->pRight );
+ assert( pExpr->pRight->op==TK_TRUEFALSE );
+ x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
+ zUniOp = azOp[x];
+ break;
+ }
+
case TK_SPAN: {
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
@@ -29063,7 +29552,7 @@ static int compare2pow63(const char *zNum, int incr){
** Returns:
**
** 0 Successful transformation. Fits in a 64-bit signed integer.
-** 1 Excess text after the integer value
+** 1 Excess non-space text after the integer value
** 2 Integer too large for a 64-bit signed integer or is malformed
** 3 Special case of 9223372036854775808
**
@@ -29106,47 +29595,57 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
u = u*10 + c - '0';
}
+ testcase( i==18*incr );
+ testcase( i==19*incr );
+ testcase( i==20*incr );
if( u>LARGEST_INT64 ){
+ /* This test and assignment is needed only to suppress UB warnings
+ ** from clang and -fsanitize=undefined. This test and assignment make
+ ** the code a little larger and slower, and no harm comes from omitting
+ ** them, but we must appaise the undefined-behavior pharisees. */
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
}else if( neg ){
*pNum = -(i64)u;
}else{
*pNum = (i64)u;
}
- testcase( i==18 );
- testcase( i==19 );
- testcase( i==20 );
- if( &zNum[i]<zEnd /* Extra bytes at the end */
- || (i==0 && zStart==zNum) /* No digits */
+ rc = 0;
+ if( (i==0 && zStart==zNum) /* No digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
rc = 1;
- }else{
- rc = 0;
+ }else if( &zNum[i]<zEnd ){ /* Extra bytes at the end */
+ int jj = i;
+ do{
+ if( !sqlite3Isspace(zNum[jj]) ){
+ rc = 1; /* Extra non-space text after the integer */
+ break;
+ }
+ jj += incr;
+ }while( &zNum[jj]<zEnd );
}
- if( i>19*incr ){ /* Too many digits */
- /* zNum is empty or contains non-numeric text or is longer
- ** than 19 digits (thus guaranteeing that it is too large) */
- return 2;
- }else if( i<19*incr ){
+ if( i<19*incr ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
return rc;
}else{
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
- c = compare2pow63(zNum, incr);
+ c = i>19*incr ? 1 : compare2pow63(zNum, incr);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return rc;
- }else if( c>0 ){
- /* zNum is greater than 9223372036854775808 so it overflows */
- return 2;
}else{
- /* zNum is exactly 9223372036854775808. Fits if negative. The
- ** special case 2 overflow if positive */
- assert( u-1==LARGEST_INT64 );
- return neg ? rc : 3;
+ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
+ if( c>0 ){
+ /* zNum is greater than 9223372036854775808 so it overflows */
+ return 2;
+ }else{
+ /* zNum is exactly 9223372036854775808. Fits if negative. The
+ ** special case 2 overflow if positive */
+ assert( u-1==LARGEST_INT64 );
+ return neg ? rc : 3;
+ }
}
}
}
@@ -30463,80 +30962,81 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
/* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
- /* 96 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 96 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
/* 97 */ "String8" OpHelp("r[P2]='P4'"),
- /* 98 */ "Column" OpHelp("r[P3]=PX"),
- /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 101 */ "Count" OpHelp("r[P2]=count()"),
- /* 102 */ "ReadCookie" OpHelp(""),
- /* 103 */ "SetCookie" OpHelp(""),
- /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 107 */ "OpenDup" OpHelp(""),
- /* 108 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 109 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 110 */ "SorterOpen" OpHelp(""),
- /* 111 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 112 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 113 */ "Close" OpHelp(""),
- /* 114 */ "ColumnsUsed" OpHelp(""),
- /* 115 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 116 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 117 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 118 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 119 */ "Delete" OpHelp(""),
- /* 120 */ "ResetCount" OpHelp(""),
- /* 121 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 122 */ "SorterData" OpHelp("r[P2]=data"),
- /* 123 */ "RowData" OpHelp("r[P2]=data"),
- /* 124 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 125 */ "NullRow" OpHelp(""),
- /* 126 */ "SeekEnd" OpHelp(""),
- /* 127 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 128 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 129 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 130 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 131 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 98 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 99 */ "Column" OpHelp("r[P3]=PX"),
+ /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 102 */ "Count" OpHelp("r[P2]=count()"),
+ /* 103 */ "ReadCookie" OpHelp(""),
+ /* 104 */ "SetCookie" OpHelp(""),
+ /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 108 */ "OpenDup" OpHelp(""),
+ /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 111 */ "SorterOpen" OpHelp(""),
+ /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 114 */ "Close" OpHelp(""),
+ /* 115 */ "ColumnsUsed" OpHelp(""),
+ /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 120 */ "Delete" OpHelp(""),
+ /* 121 */ "ResetCount" OpHelp(""),
+ /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 123 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 124 */ "RowData" OpHelp("r[P2]=data"),
+ /* 125 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 126 */ "NullRow" OpHelp(""),
+ /* 127 */ "SeekEnd" OpHelp(""),
+ /* 128 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 129 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 130 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 131 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 132 */ "Real" OpHelp("r[P2]=P4"),
- /* 133 */ "Destroy" OpHelp(""),
- /* 134 */ "Clear" OpHelp(""),
- /* 135 */ "ResetSorter" OpHelp(""),
- /* 136 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 137 */ "SqlExec" OpHelp(""),
- /* 138 */ "ParseSchema" OpHelp(""),
- /* 139 */ "LoadAnalysis" OpHelp(""),
- /* 140 */ "DropTable" OpHelp(""),
- /* 141 */ "DropIndex" OpHelp(""),
- /* 142 */ "DropTrigger" OpHelp(""),
- /* 143 */ "IntegrityCk" OpHelp(""),
- /* 144 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 145 */ "Param" OpHelp(""),
- /* 146 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 147 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 148 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 149 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 150 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 151 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 152 */ "Expire" OpHelp(""),
- /* 153 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 154 */ "VBegin" OpHelp(""),
- /* 155 */ "VCreate" OpHelp(""),
- /* 156 */ "VDestroy" OpHelp(""),
- /* 157 */ "VOpen" OpHelp(""),
- /* 158 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 159 */ "VRename" OpHelp(""),
- /* 160 */ "Pagecount" OpHelp(""),
- /* 161 */ "MaxPgcnt" OpHelp(""),
- /* 162 */ "PureFunc0" OpHelp(""),
- /* 163 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 164 */ "PureFunc" OpHelp(""),
- /* 165 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 166 */ "Trace" OpHelp(""),
- /* 167 */ "CursorHint" OpHelp(""),
- /* 168 */ "Noop" OpHelp(""),
- /* 169 */ "Explain" OpHelp(""),
+ /* 133 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 134 */ "Destroy" OpHelp(""),
+ /* 135 */ "Clear" OpHelp(""),
+ /* 136 */ "ResetSorter" OpHelp(""),
+ /* 137 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 138 */ "SqlExec" OpHelp(""),
+ /* 139 */ "ParseSchema" OpHelp(""),
+ /* 140 */ "LoadAnalysis" OpHelp(""),
+ /* 141 */ "DropTable" OpHelp(""),
+ /* 142 */ "DropIndex" OpHelp(""),
+ /* 143 */ "DropTrigger" OpHelp(""),
+ /* 144 */ "IntegrityCk" OpHelp(""),
+ /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 146 */ "Param" OpHelp(""),
+ /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 153 */ "Expire" OpHelp(""),
+ /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 155 */ "VBegin" OpHelp(""),
+ /* 156 */ "VCreate" OpHelp(""),
+ /* 157 */ "VDestroy" OpHelp(""),
+ /* 158 */ "VOpen" OpHelp(""),
+ /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 160 */ "VRename" OpHelp(""),
+ /* 161 */ "Pagecount" OpHelp(""),
+ /* 162 */ "MaxPgcnt" OpHelp(""),
+ /* 163 */ "PureFunc0" OpHelp(""),
+ /* 164 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 165 */ "PureFunc" OpHelp(""),
+ /* 166 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 167 */ "Trace" OpHelp(""),
+ /* 168 */ "CursorHint" OpHelp(""),
+ /* 169 */ "Noop" OpHelp(""),
+ /* 170 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -30775,6 +31275,9 @@ struct unixFile {
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
unsigned fsFlags; /* cached details from statfs() */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ unsigned iBusyTimeout; /* Wait this many millisec on locks */
+#endif
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID */
#endif
@@ -31212,7 +31715,11 @@ static struct unix_syscall {
#endif
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
+#if defined(HAVE_FCHOWN)
{ "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
+#else
+ { "geteuid", (sqlite3_syscall_ptr)0, 0 },
+#endif
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
@@ -31440,15 +31947,16 @@ static int robust_open(const char *z, int f, mode_t m){
** assert( unixMutexHeld() );
** unixEnterLeave()
*/
+static sqlite3_mutex *unixBigLock = 0;
static void unixEnterMutex(void){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ sqlite3_mutex_enter(unixBigLock);
}
static void unixLeaveMutex(void){
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ sqlite3_mutex_leave(unixBigLock);
}
#ifdef SQLITE_DEBUG
static int unixMutexHeld(void) {
- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ return sqlite3_mutex_held(unixBigLock);
}
#endif
@@ -32205,6 +32713,43 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
}
/*
+** Set a posix-advisory-lock.
+**
+** There are two versions of this routine. If compiled with
+** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
+** which is a pointer to a unixFile. If the unixFile->iBusyTimeout
+** value is set, then it is the number of milliseconds to wait before
+** failing the lock. The iBusyTimeout value is always reset back to
+** zero on each call.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
+** attempt to set the lock.
+*/
+#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
+# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
+#else
+static int osSetPosixAdvisoryLock(
+ int h, /* The file descriptor on which to take the lock */
+ struct flock *pLock, /* The description of the lock */
+ unixFile *pFile /* Structure holding timeout value */
+){
+ int rc = osFcntl(h,F_SETLK,pLock);
+ while( rc<0 && pFile->iBusyTimeout>0 ){
+ /* On systems that support some kind of blocking file lock with a timeout,
+ ** make appropriate changes here to invoke that blocking file lock. On
+ ** generic posix, however, there is no such API. So we simply try the
+ ** lock once every millisecond until either the timeout expires, or until
+ ** the lock is obtained. */
+ usleep(1000);
+ rc = osFcntl(h,F_SETLK,pLock);
+ pFile->iBusyTimeout--;
+ }
+ return rc;
+}
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
+
+/*
** Attempt to set a system-lock on the file pFile. The lock is
** described by pLock.
**
@@ -32236,7 +32781,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
lock.l_type = F_WRLCK;
- rc = osFcntl(pFile->h, F_SETLK, &lock);
+ rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
if( rc<0 ) return rc;
pInode->bProcessLock = 1;
pInode->nLock++;
@@ -32244,7 +32789,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
rc = 0;
}
}else{
- rc = osFcntl(pFile->h, F_SETLK, pLock);
+ rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
}
return rc;
}
@@ -34604,6 +35149,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = fileHasMoved(pFile);
return SQLITE_OK;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ pFile->iBusyTimeout = *(int*)pArg;
+ return SQLITE_OK;
+ }
+#endif
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -34919,13 +35470,11 @@ static int unixShmSystemLock(
if( pShmNode->h>=0 ){
/* Initialize the locking parameters */
- memset(&f, 0, sizeof(f));
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
-
- rc = osFcntl(pShmNode->h, F_SETLK, &f);
+ rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
}
@@ -36590,7 +37139,6 @@ static int unixOpen(
randomnessPid = osGetpid(0);
sqlite3_randomness(0,0);
}
-
memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){
@@ -38465,6 +39013,7 @@ SQLITE_API int sqlite3_os_init(void){
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
+ unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
return SQLITE_OK;
}
@@ -38476,6 +39025,7 @@ SQLITE_API int sqlite3_os_init(void){
** This routine is a no-op for unix.
*/
SQLITE_API int sqlite3_os_end(void){
+ unixBigLock = 0;
return SQLITE_OK;
}
@@ -42314,15 +42864,16 @@ static SYSTEM_INFO winSysInfo;
** assert( winShmMutexHeld() );
** winShmLeaveMutex()
*/
+static sqlite3_mutex *winBigLock = 0;
static void winShmEnterMutex(void){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ sqlite3_mutex_enter(winBigLock);
}
static void winShmLeaveMutex(void){
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ sqlite3_mutex_leave(winBigLock);
}
#ifndef NDEBUG
static int winShmMutexHeld(void) {
- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1));
+ return sqlite3_mutex_held(winBigLock);
}
#endif
@@ -44745,6 +45296,10 @@ SQLITE_API int sqlite3_os_init(void){
sqlite3_vfs_register(&winLongPathNolockVfs, 0);
#endif
+#ifndef SQLITE_OMIT_WAL
+ winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+
return SQLITE_OK;
}
@@ -44755,12 +45310,609 @@ SQLITE_API int sqlite3_os_end(void){
sleepObj = NULL;
}
#endif
+
+#ifndef SQLITE_OMIT_WAL
+ winBigLock = 0;
+#endif
+
return SQLITE_OK;
}
#endif /* SQLITE_OS_WIN */
/************** End of os_win.c **********************************************/
+/************** Begin file memdb.c *******************************************/
+/*
+** 2016-09-07
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file implements an in-memory VFS. A database is held as a contiguous
+** block of memory.
+**
+** This file also implements interface sqlite3_serialize() and
+** sqlite3_deserialize().
+*/
+#ifdef SQLITE_ENABLE_DESERIALIZE
+/* #include "sqliteInt.h" */
+
+/*
+** Forward declaration of objects used by this utility
+*/
+typedef struct sqlite3_vfs MemVfs;
+typedef struct MemFile MemFile;
+
+/* Access to a lower-level VFS that (might) implement dynamic loading,
+** access to randomness, etc.
+*/
+#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
+
+/* An open file */
+struct MemFile {
+ sqlite3_file base; /* IO methods */
+ sqlite3_int64 sz; /* Size of the file */
+ sqlite3_int64 szMax; /* Space allocated to aData */
+ unsigned char *aData; /* content of the file */
+ int nMmap; /* Number of memory mapped pages */
+ unsigned mFlags; /* Flags */
+ int eLock; /* Most recent lock against this file */
+};
+
+/*
+** Methods for MemFile
+*/
+static int memdbClose(sqlite3_file*);
+static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
+static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
+static int memdbSync(sqlite3_file*, int flags);
+static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
+static int memdbLock(sqlite3_file*, int);
+/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
+static int memdbFileControl(sqlite3_file*, int op, void *pArg);
+/* static int memdbSectorSize(sqlite3_file*); // not used */
+static int memdbDeviceCharacteristics(sqlite3_file*);
+static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+
+/*
+** Methods for MemVfs
+*/
+static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
+static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
+static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
+static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
+static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
+static void memdbDlClose(sqlite3_vfs*, void*);
+static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
+static int memdbSleep(sqlite3_vfs*, int microseconds);
+/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
+static int memdbGetLastError(sqlite3_vfs*, int, char *);
+static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+
+static sqlite3_vfs memdb_vfs = {
+ 2, /* iVersion */
+ 0, /* szOsFile (set when registered) */
+ 1024, /* mxPathname */
+ 0, /* pNext */
+ "memdb", /* zName */
+ 0, /* pAppData (set when registered) */
+ memdbOpen, /* xOpen */
+ 0, /* memdbDelete, */ /* xDelete */
+ memdbAccess, /* xAccess */
+ memdbFullPathname, /* xFullPathname */
+ memdbDlOpen, /* xDlOpen */
+ memdbDlError, /* xDlError */
+ memdbDlSym, /* xDlSym */
+ memdbDlClose, /* xDlClose */
+ memdbRandomness, /* xRandomness */
+ memdbSleep, /* xSleep */
+ 0, /* memdbCurrentTime, */ /* xCurrentTime */
+ memdbGetLastError, /* xGetLastError */
+ memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+};
+
+static const sqlite3_io_methods memdb_io_methods = {
+ 3, /* iVersion */
+ memdbClose, /* xClose */
+ memdbRead, /* xRead */
+ memdbWrite, /* xWrite */
+ memdbTruncate, /* xTruncate */
+ memdbSync, /* xSync */
+ memdbFileSize, /* xFileSize */
+ memdbLock, /* xLock */
+ memdbLock, /* xUnlock - same as xLock in this case */
+ 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
+ memdbFileControl, /* xFileControl */
+ 0, /* memdbSectorSize,*/ /* xSectorSize */
+ memdbDeviceCharacteristics, /* xDeviceCharacteristics */
+ 0, /* xShmMap */
+ 0, /* xShmLock */
+ 0, /* xShmBarrier */
+ 0, /* xShmUnmap */
+ memdbFetch, /* xFetch */
+ memdbUnfetch /* xUnfetch */
+};
+
+
+
+/*
+** Close an memdb-file.
+**
+** The pData pointer is owned by the application, so there is nothing
+** to free.
+*/
+static int memdbClose(sqlite3_file *pFile){
+ MemFile *p = (MemFile *)pFile;
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
+ return SQLITE_OK;
+}
+
+/*
+** Read data from an memdb-file.
+*/
+static int memdbRead(
+ sqlite3_file *pFile,
+ void *zBuf,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ MemFile *p = (MemFile *)pFile;
+ if( iOfst+iAmt>p->sz ){
+ memset(zBuf, 0, iAmt);
+ if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ return SQLITE_IOERR_SHORT_READ;
+ }
+ memcpy(zBuf, p->aData+iOfst, iAmt);
+ return SQLITE_OK;
+}
+
+/*
+** Try to enlarge the memory allocation to hold at least sz bytes
+*/
+static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
+ unsigned char *pNew;
+ if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
+ return SQLITE_FULL;
+ }
+ pNew = sqlite3_realloc64(p->aData, newSz);
+ if( pNew==0 ) return SQLITE_NOMEM;
+ p->aData = pNew;
+ p->szMax = newSz;
+ return SQLITE_OK;
+}
+
+/*
+** Write data to an memdb-file.
+*/
+static int memdbWrite(
+ sqlite3_file *pFile,
+ const void *z,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ MemFile *p = (MemFile *)pFile;
+ if( iOfst+iAmt>p->sz ){
+ int rc;
+ if( iOfst+iAmt>p->szMax
+ && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
+ ){
+ return rc;
+ }
+ if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
+ p->sz = iOfst+iAmt;
+ }
+ memcpy(p->aData+iOfst, z, iAmt);
+ return SQLITE_OK;
+}
+
+/*
+** Truncate an memdb-file.
+**
+** In rollback mode (which is always the case for memdb, as it does not
+** support WAL mode) the truncate() method is only used to reduce
+** the size of a file, never to increase the size.
+*/
+static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
+ MemFile *p = (MemFile *)pFile;
+ if( NEVER(size>p->sz) ) return SQLITE_FULL;
+ p->sz = size;
+ return SQLITE_OK;
+}
+
+/*
+** Sync an memdb-file.
+*/
+static int memdbSync(sqlite3_file *pFile, int flags){
+ return SQLITE_OK;
+}
+
+/*
+** Return the current file-size of an memdb-file.
+*/
+static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
+ MemFile *p = (MemFile *)pFile;
+ *pSize = p->sz;
+ return SQLITE_OK;
+}
+
+/*
+** Lock an memdb-file.
+*/
+static int memdbLock(sqlite3_file *pFile, int eLock){
+ MemFile *p = (MemFile *)pFile;
+ p->eLock = eLock;
+ return SQLITE_OK;
+}
+
+#if 0 /* Never used because memdbAccess() always returns false */
+/*
+** Check if another file-handle holds a RESERVED lock on an memdb-file.
+*/
+static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
+ *pResOut = 0;
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** File control method. For custom operations on an memdb-file.
+*/
+static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
+ MemFile *p = (MemFile *)pFile;
+ int rc = SQLITE_NOTFOUND;
+ if( op==SQLITE_FCNTL_VFSNAME ){
+ *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
+/*
+** Return the sector-size in bytes for an memdb-file.
+*/
+static int memdbSectorSize(sqlite3_file *pFile){
+ return 1024;
+}
+#endif
+
+/*
+** Return the device characteristic flags supported by an memdb-file.
+*/
+static int memdbDeviceCharacteristics(sqlite3_file *pFile){
+ return SQLITE_IOCAP_ATOMIC |
+ SQLITE_IOCAP_POWERSAFE_OVERWRITE |
+ SQLITE_IOCAP_SAFE_APPEND |
+ SQLITE_IOCAP_SEQUENTIAL;
+}
+
+/* Fetch a page of a memory-mapped file */
+static int memdbFetch(
+ sqlite3_file *pFile,
+ sqlite3_int64 iOfst,
+ int iAmt,
+ void **pp
+){
+ MemFile *p = (MemFile *)pFile;
+ p->nMmap++;
+ *pp = (void*)(p->aData + iOfst);
+ return SQLITE_OK;
+}
+
+/* Release a memory-mapped page */
+static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
+ MemFile *p = (MemFile *)pFile;
+ p->nMmap--;
+ return SQLITE_OK;
+}
+
+/*
+** Open an mem file handle.
+*/
+static int memdbOpen(
+ sqlite3_vfs *pVfs,
+ const char *zName,
+ sqlite3_file *pFile,
+ int flags,
+ int *pOutFlags
+){
+ MemFile *p = (MemFile*)pFile;
+ if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
+ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
+ *pOutFlags = flags | SQLITE_OPEN_MEMORY;
+ p->base.pMethods = &memdb_io_methods;
+ return SQLITE_OK;
+}
+
+#if 0 /* Only used to delete rollback journals, master journals, and WAL
+ ** files, none of which exist in memdb. So this routine is never used */
+/*
+** Delete the file located at zPath. If the dirSync argument is true,
+** ensure the file-system modifications are synced to disk before
+** returning.
+*/
+static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+ return SQLITE_IOERR_DELETE;
+}
+#endif
+
+/*
+** Test for access permissions. Return true if the requested permission
+** is available, or false otherwise.
+**
+** With memdb, no files ever exist on disk. So always return false.
+*/
+static int memdbAccess(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int flags,
+ int *pResOut
+){
+ *pResOut = 0;
+ return SQLITE_OK;
+}
+
+/*
+** Populate buffer zOut with the full canonical pathname corresponding
+** to the pathname in zPath. zOut is guaranteed to point to a buffer
+** of at least (INST_MAX_PATHNAME+1) bytes.
+*/
+static int memdbFullPathname(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nOut,
+ char *zOut
+){
+ sqlite3_snprintf(nOut, zOut, "%s", zPath);
+ return SQLITE_OK;
+}
+
+/*
+** Open the dynamic library located at zPath and return a handle.
+*/
+static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+ return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
+}
+
+/*
+** Populate the buffer zErrMsg (size nByte bytes) with a human readable
+** utf-8 string describing the most recent error encountered associated
+** with dynamic libraries.
+*/
+static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
+ ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
+}
+
+/*
+** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
+*/
+static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
+ return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
+}
+
+/*
+** Close the dynamic library handle pHandle.
+*/
+static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
+ ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
+}
+
+/*
+** Populate the buffer pointed to by zBufOut with nByte bytes of
+** random data.
+*/
+static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+ return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
+}
+
+/*
+** Sleep for nMicro microseconds. Return the number of microseconds
+** actually slept.
+*/
+static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
+ return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
+}
+
+#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
+/*
+** Return the current time as a Julian Day number in *pTimeOut.
+*/
+static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+ return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
+}
+#endif
+
+static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
+ return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
+}
+static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
+ return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
+}
+
+/*
+** Translate a database connection pointer and schema name into a
+** MemFile pointer.
+*/
+static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
+ MemFile *p = 0;
+ int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
+ if( rc ) return 0;
+ if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ return p;
+}
+
+/*
+** Return the serialization of a database
+*/
+SQLITE_API unsigned char *sqlite3_serialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which database within the connection */
+ sqlite3_int64 *piSize, /* Write size here, if not NULL */
+ unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
+){
+ MemFile *p;
+ int iDb;
+ Btree *pBt;
+ sqlite3_int64 sz;
+ int szPage = 0;
+ sqlite3_stmt *pStmt = 0;
+ unsigned char *pOut;
+ char *zSql;
+ int rc;
+
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
+
+ if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
+ p = memdbFromDbSchema(db, zSchema);
+ iDb = sqlite3FindDbName(db, zSchema);
+ if( piSize ) *piSize = -1;
+ if( iDb<0 ) return 0;
+ if( p ){
+ if( piSize ) *piSize = p->sz;
+ if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
+ pOut = p->aData;
+ }else{
+ pOut = sqlite3_malloc64( p->sz );
+ if( pOut ) memcpy(pOut, p->aData, p->sz);
+ }
+ return pOut;
+ }
+ pBt = db->aDb[iDb].pBt;
+ if( pBt==0 ) return 0;
+ szPage = sqlite3BtreeGetPageSize(pBt);
+ zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
+ rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
+ sqlite3_free(zSql);
+ if( rc ) return 0;
+ rc = sqlite3_step(pStmt);
+ if( rc!=SQLITE_ROW ){
+ pOut = 0;
+ }else{
+ sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ if( piSize ) *piSize = sz;
+ if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
+ pOut = 0;
+ }else{
+ pOut = sqlite3_malloc64( sz );
+ if( pOut ){
+ int nPage = sqlite3_column_int(pStmt, 0);
+ Pager *pPager = sqlite3BtreePager(pBt);
+ int pgno;
+ for(pgno=1; pgno<=nPage; pgno++){
+ DbPage *pPage = 0;
+ unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
+ rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
+ if( rc==SQLITE_OK ){
+ memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
+ }else{
+ memset(pTo, 0, szPage);
+ }
+ sqlite3PagerUnref(pPage);
+ }
+ }
+ }
+ }
+ sqlite3_finalize(pStmt);
+ return pOut;
+}
+
+/* Convert zSchema to a MemDB and initialize its content.
+*/
+SQLITE_API int sqlite3_deserialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which DB to reopen with the deserialization */
+ unsigned char *pData, /* The serialized database content */
+ sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szBuf, /* Total size of buffer pData[] */
+ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
+){
+ MemFile *p;
+ char *zSql;
+ sqlite3_stmt *pStmt = 0;
+ int rc;
+ int iDb;
+
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ if( szDb<0 ) return SQLITE_MISUSE_BKPT;
+ if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
+#endif
+
+ sqlite3_mutex_enter(db->mutex);
+ if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
+ iDb = sqlite3FindDbName(db, zSchema);
+ if( iDb<0 ){
+ rc = SQLITE_ERROR;
+ goto end_deserialize;
+ }
+ zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ if( rc ) goto end_deserialize;
+ db->init.iDb = (u8)iDb;
+ db->init.reopenMemdb = 1;
+ rc = sqlite3_step(pStmt);
+ db->init.reopenMemdb = 0;
+ if( rc!=SQLITE_DONE ){
+ rc = SQLITE_ERROR;
+ goto end_deserialize;
+ }
+ p = memdbFromDbSchema(db, zSchema);
+ if( p==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ p->aData = pData;
+ p->sz = szDb;
+ p->szMax = szBuf;
+ p->mFlags = mFlags;
+ rc = SQLITE_OK;
+ }
+
+end_deserialize:
+ sqlite3_finalize(pStmt);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** This routine is called when the extension is loaded.
+** Register the new VFS.
+*/
+SQLITE_PRIVATE int sqlite3MemdbInit(void){
+ sqlite3_vfs *pLower = sqlite3_vfs_find(0);
+ int sz = pLower->szOsFile;
+ memdb_vfs.pAppData = pLower;
+ /* In all known configurations of SQLite, the size of a default
+ ** sqlite3_file is greater than the size of a memdb sqlite3_file.
+ ** Should that ever change, remove the following NEVER() */
+ if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
+ memdb_vfs.szOsFile = sz;
+ return sqlite3_vfs_register(&memdb_vfs, 0);
+}
+#endif /* SQLITE_ENABLE_DESERIALIZE */
+
+/************** End of memdb.c ***********************************************/
/************** Begin file bitvec.c ******************************************/
/*
** 2008 February 16
@@ -45609,7 +46761,7 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress(
sqlite3_log(SQLITE_FULL,
"spill page %d making room for %d - cache used: %d/%d",
pPg->pgno, pgno,
- sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
+ sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache),
numberOfCachePages(pCache));
#endif
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
@@ -48665,7 +49817,7 @@ struct Pager {
char *zJournal; /* Name of the journal file */
int (*xBusyHandler)(void*); /* Function to call when busy */
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
- int aStat[3]; /* Total cache hits, misses and writes */
+ int aStat[4]; /* Total cache hits, misses, writes, spills */
#ifdef SQLITE_TEST
int nRead; /* Database pages read */
#endif
@@ -48693,6 +49845,7 @@ struct Pager {
#define PAGER_STAT_HIT 0
#define PAGER_STAT_MISS 1
#define PAGER_STAT_WRITE 2
+#define PAGER_STAT_SPILL 3
/*
** The following global variables hold counters used for
@@ -49179,7 +50332,7 @@ static int jrnlBufferSize(Pager *pPager){
#endif
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){
+ if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){
return -1;
}
#endif
@@ -50095,7 +51248,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
rc = pager_truncate(pPager, pPager->dbSize);
}
- if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
+ if( rc==SQLITE_OK && bCommit ){
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
}
@@ -50914,9 +52067,7 @@ end_playback:
** assertion that the transaction counter was modified.
*/
#ifdef SQLITE_DEBUG
- if( pPager->fd->pMethods ){
- sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
- }
+ sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
#endif
/* If this playback is happening automatically as a result of an IO or
@@ -51669,20 +52820,18 @@ static int pagerOpentemp(
** retried. If it returns zero, then the SQLITE_BUSY error is
** returned to the caller of the pager API function.
*/
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
Pager *pPager, /* Pager object */
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
){
+ void **ap;
pPager->xBusyHandler = xBusyHandler;
pPager->pBusyHandlerArg = pBusyHandlerArg;
-
- if( isOpen(pPager->fd) ){
- void **ap = (void **)&pPager->xBusyHandler;
- assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
- assert( ap[1]==pBusyHandlerArg );
- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
- }
+ ap = (void **)&pPager->xBusyHandler;
+ assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+ assert( ap[1]==pBusyHandlerArg );
+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
}
/*
@@ -52068,6 +53217,30 @@ static void pagerFreeMapHdrs(Pager *pPager){
}
}
+/* Verify that the database file has not be deleted or renamed out from
+** under the pager. Return SQLITE_OK if the database is still where it ought
+** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
+** code from sqlite3OsAccess()) if the database has gone missing.
+*/
+static int databaseIsUnmoved(Pager *pPager){
+ int bHasMoved = 0;
+ int rc;
+
+ if( pPager->tempFile ) return SQLITE_OK;
+ if( pPager->dbSize==0 ) return SQLITE_OK;
+ assert( pPager->zFilename && pPager->zFilename[0] );
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
+ if( rc==SQLITE_NOTFOUND ){
+ /* If the HAS_MOVED file-control is unimplemented, assume that the file
+ ** has not been moved. That is the historical behavior of SQLite: prior to
+ ** version 3.8.3, it never checked */
+ rc = SQLITE_OK;
+ }else if( rc==SQLITE_OK && bHasMoved ){
+ rc = SQLITE_READONLY_DBMOVED;
+ }
+ return rc;
+}
+
/*
** Shutdown the page cache. Free all memory and close all files.
@@ -52084,8 +53257,7 @@ static void pagerFreeMapHdrs(Pager *pPager){
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
- u8 *pTmp = (u8 *)pPager->pTmpSpace;
-
+ u8 *pTmp = (u8*)pPager->pTmpSpace;
assert( db || pagerUseWal(pPager)==0 );
assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
@@ -52094,11 +53266,17 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
/* pPager->errCode = 0; */
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
- assert( db || pPager->pWal==0 );
- sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
- (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
- );
- pPager->pWal = 0;
+ {
+ u8 *a = 0;
+ assert( db || pPager->pWal==0 );
+ if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
+ && SQLITE_OK==databaseIsUnmoved(pPager)
+ ){
+ a = pTmp;
+ }
+ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
+ pPager->pWal = 0;
+ }
#endif
pager_reset(pPager);
if( MEMDB ){
@@ -52555,6 +53733,7 @@ static int pagerStress(void *p, PgHdr *pPg){
return SQLITE_OK;
}
+ pPager->aStat[PAGER_STAT_SPILL]++;
pPg->pDirty = 0;
if( pagerUseWal(pPager) ){
/* Write a single frame for this page to the log. */
@@ -52660,6 +53839,11 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ int memJM = 0; /* Memory journal mode */
+#else
+# define memJM 0
+#endif
int readOnly = 0; /* True if this is a read-only file */
int journalFileSize; /* Bytes to allocate for each journal fd */
char *zPathname = 0; /* Full path to database file */
@@ -52787,7 +53971,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
- readOnly = (fout&SQLITE_OPEN_READONLY);
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
+#endif
+ readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
/* If the file was successfully opened for read/write access,
** choose a default page size in case we have to create the
@@ -52918,7 +54105,7 @@ act_like_temp_file:
setSectorSize(pPager);
if( !useJournal ){
pPager->journalMode = PAGER_JOURNALMODE_OFF;
- }else if( memDb ){
+ }else if( memDb || memJM ){
pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
}
/* pPager->xBusyHandler = 0; */
@@ -52933,30 +54120,6 @@ act_like_temp_file:
}
-/* Verify that the database file has not be deleted or renamed out from
-** under the pager. Return SQLITE_OK if the database is still were it ought
-** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
-** code from sqlite3OsAccess()) if the database has gone missing.
-*/
-static int databaseIsUnmoved(Pager *pPager){
- int bHasMoved = 0;
- int rc;
-
- if( pPager->tempFile ) return SQLITE_OK;
- if( pPager->dbSize==0 ) return SQLITE_OK;
- assert( pPager->zFilename && pPager->zFilename[0] );
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
- if( rc==SQLITE_NOTFOUND ){
- /* If the HAS_MOVED file-control is unimplemented, assume that the file
- ** has not been moved. That is the historical behavior of SQLite: prior to
- ** version 3.8.3, it never checked */
- rc = SQLITE_OK;
- }else if( rc==SQLITE_OK && bHasMoved ){
- rc = SQLITE_READONLY_DBMOVED;
- }
- return rc;
-}
-
/*
** This function is called after transitioning from PAGER_UNLOCK to
@@ -53644,6 +54807,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){
assert( pPg->pgno==1 );
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
pPager = pPg->pPager;
+ sqlite3PagerResetLockTimeout(pPager);
sqlite3PcacheRelease(pPg);
pagerUnlockIfUnused(pPager);
}
@@ -54239,12 +55403,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
*/
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
int rc = SQLITE_OK;
-
- if( isOpen(pPager->fd) ){
- void *pArg = (void*)zMaster;
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
- }
+ void *pArg = (void*)zMaster;
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
+ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
if( rc==SQLITE_OK && !pPager->noSync ){
assert( !MEMDB );
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
@@ -54465,8 +55626,9 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
if( bBatch ){
if( rc==SQLITE_OK ){
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
- }else{
- sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
}
}
@@ -54690,8 +55852,12 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
#endif
/*
-** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
-** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
+** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE,
+** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation
+** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because
+** it was added later.
+**
+** Before returning, *pnVal is incremented by the
** current cache hit or miss count, according to the value of eStat. If the
** reset parameter is non-zero, the cache hit or miss count is zeroed before
** returning.
@@ -54701,15 +55867,18 @@ SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, i
assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
|| eStat==SQLITE_DBSTATUS_CACHE_MISS
|| eStat==SQLITE_DBSTATUS_CACHE_WRITE
+ || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1
);
assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
- assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
+ assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1
+ && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 );
- *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
+ eStat -= SQLITE_DBSTATUS_CACHE_HIT;
+ *pnVal += pPager->aStat[eStat];
if( reset ){
- pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
+ pPager->aStat[eStat] = 0;
}
}
@@ -54913,6 +56082,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
return pPager->fd;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+/*
+** Reset the lock timeout for pager.
+*/
+SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
+ int x = 0;
+ sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
+}
+#endif
+
/*
** Return the file handle for the journal file (if it exists).
** This will be either the rollback journal or the WAL file.
@@ -55373,6 +56552,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint(
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
+ sqlite3PagerResetLockTimeout(pPager);
}
return rc;
}
@@ -56155,7 +57335,11 @@ struct WalIterator {
** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
** then an SQLite error code is returned and *ppPage is set to 0.
*/
-static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
+static SQLITE_NOINLINE int walIndexPageRealloc(
+ Wal *pWal, /* The WAL context */
+ int iPage, /* The page we seek */
+ volatile u32 **ppPage /* Write the page pointer here */
+){
int rc = SQLITE_OK;
/* Enlarge the pWal->apWiData[] array if required */
@@ -56174,21 +57358,20 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
}
/* Request a pointer to the required page from the VFS */
- if( pWal->apWiData[iPage]==0 ){
- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
- pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
- if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
- }else{
- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
- pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
- );
- assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
- testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
- if( (rc&0xff)==SQLITE_READONLY ){
- pWal->readOnly |= WAL_SHM_RDONLY;
- if( rc==SQLITE_READONLY ){
- rc = SQLITE_OK;
- }
+ assert( pWal->apWiData[iPage]==0 );
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
+ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
+ }else{
+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
+ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
+ );
+ assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
+ testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
+ if( (rc&0xff)==SQLITE_READONLY ){
+ pWal->readOnly |= WAL_SHM_RDONLY;
+ if( rc==SQLITE_READONLY ){
+ rc = SQLITE_OK;
}
}
}
@@ -56197,6 +57380,16 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
return rc;
}
+static int walIndexPage(
+ Wal *pWal, /* The WAL context */
+ int iPage, /* The page we seek */
+ volatile u32 **ppPage /* Write the page pointer here */
+){
+ if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){
+ return walIndexPageRealloc(pWal, iPage, ppPage);
+ }
+ return SQLITE_OK;
+}
/*
** Return a pointer to the WalCkptInfo structure in the wal-index.
@@ -57173,8 +58366,9 @@ static void walIteratorFree(WalIterator *p){
/*
** Construct a WalInterator object that can be used to loop over all
-** pages in the WAL in ascending order. The caller must hold the checkpoint
-** lock.
+** pages in the WAL following frame nBackfill in ascending order. Frames
+** nBackfill or earlier may be included - excluding them is an optimization
+** only. The caller must hold the checkpoint lock.
**
** On success, make *pp point to the newly allocated WalInterator object
** return SQLITE_OK. Otherwise, return an error code. If this routine
@@ -57183,7 +58377,7 @@ static void walIteratorFree(WalIterator *p){
** The calling routine should invoke walIteratorFree() to destroy the
** WalIterator object when it has finished with it.
*/
-static int walIteratorInit(Wal *pWal, WalIterator **pp){
+static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
WalIterator *p; /* Return value */
int nSegment; /* Number of segments to merge */
u32 iLast; /* Last frame in log */
@@ -57220,7 +58414,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
rc = SQLITE_NOMEM_BKPT;
}
- for(i=0; rc==SQLITE_OK && i<nSegment; i++){
+ for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
volatile ht_slot *aHash;
u32 iZero;
volatile u32 *aPgno;
@@ -57254,6 +58448,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
if( rc!=SQLITE_OK ){
walIteratorFree(p);
+ p = 0;
}
*pp = p;
return rc;
@@ -57376,13 +58571,6 @@ static int walCheckpoint(
pInfo = walCkptInfo(pWal);
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
- /* Allocate the iterator */
- rc = walIteratorInit(pWal, &pIter);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pIter );
-
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
@@ -57419,7 +58607,13 @@ static int walCheckpoint(
}
}
- if( pInfo->nBackfill<mxSafeFrame
+ /* Allocate the iterator */
+ if( pInfo->nBackfill<mxSafeFrame ){
+ rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
+ assert( rc==SQLITE_OK || pIter==0 );
+ }
+
+ if( pIter
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
){
i64 nSize; /* Current size of database file */
@@ -58469,7 +59663,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
** table after the current read-transaction had started.
*/
iMinHash = walFramePage(pWal->minFrame);
- for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){
+ for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
volatile ht_slot *aHash; /* Pointer to hash table */
volatile u32 *aPgno; /* Pointer to array of page numbers */
u32 iZero; /* Frame number corresponding to aPgno[0] */
@@ -58492,6 +59686,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
return SQLITE_CORRUPT_BKPT;
}
}
+ if( iRead ) break;
}
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -59906,20 +61101,20 @@ struct BtCursor {
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
u8 hints; /* As configured by CursorSetHints() */
- int nOvflAlloc; /* Allocated size of aOverflow[] array */
+ int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
+ ** Error code if eState==CURSOR_FAULT */
Btree *pBtree; /* The Btree to which this cursor belongs */
- BtShared *pBt; /* The BtShared this cursor points to */
- BtCursor *pNext; /* Forms a linked list of all cursors */
Pgno *aOverflow; /* Cache of overflow page locations */
- CellInfo info; /* A parse of the cell we are pointing at */
- i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor last known position */
- Pgno pgnoRoot; /* The root page of this tree */
- int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
- ** Error code if eState==CURSOR_FAULT */
/* All fields above are zeroed when the cursor is allocated. See
** sqlite3BtreeCursorZero(). Fields that follow must be manually
** initialized. */
+#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
+ BtShared *pBt; /* The BtShared this cursor points to */
+ BtCursor *pNext; /* Forms a linked list of all cursors */
+ CellInfo info; /* A parse of the cell we are pointing at */
+ i64 nKey; /* Size of pKey, or last integer key */
+ Pgno pgnoRoot; /* The root page of this tree */
i8 iPage; /* Index of current page in apPage */
u8 curIntKey; /* Value of apPage[0]->intKey */
u16 ix; /* Current index for apPage[iPage] */
@@ -59969,8 +61164,8 @@ struct BtCursor {
** Do nothing else with this cursor. Any attempt to use the cursor
** should return the error code stored in BtCursor.skipNext
*/
-#define CURSOR_INVALID 0
-#define CURSOR_VALID 1
+#define CURSOR_VALID 0
+#define CURSOR_INVALID 1
#define CURSOR_SKIPNEXT 2
#define CURSOR_REQUIRESEEK 3
#define CURSOR_FAULT 4
@@ -62634,7 +63829,8 @@ static int btreeInvokeBusyHandler(void *pArg){
BtShared *pBt = (BtShared*)pArg;
assert( pBt->db );
assert( sqlite3_mutex_held(pBt->db->mutex) );
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
+ sqlite3PagerFile(pBt->pPager));
}
/*
@@ -62812,7 +64008,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
}
pBt->openFlags = (u8)flags;
pBt->db = db;
- sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
+ sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
pBt->pCursor = 0;
@@ -63775,6 +64971,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
+ sqlite3PagerResetLockTimeout(pBt->pPager);
if( rc==SQLITE_OK ){
if( p->inTrans==TRANS_NONE ){
@@ -64748,7 +65945,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
** of run-time by skipping the initialization of those elements.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
- memset(p, 0, offsetof(BtCursor, iPage));
+ memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT));
}
/*
@@ -64791,11 +65988,19 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
** Using this cache reduces the number of calls to btreeParseCell().
*/
#ifndef NDEBUG
+ static int cellInfoEqual(CellInfo *a, CellInfo *b){
+ if( a->nKey!=b->nKey ) return 0;
+ if( a->pPayload!=b->pPayload ) return 0;
+ if( a->nPayload!=b->nPayload ) return 0;
+ if( a->nLocal!=b->nLocal ) return 0;
+ if( a->nSize!=b->nSize ) return 0;
+ return 1;
+ }
static void assertCellInfo(BtCursor *pCur){
CellInfo info;
memset(&info, 0, sizeof(info));
btreeParseCell(pCur->pPage, pCur->ix, &info);
- assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
+ assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) );
}
#else
#define assertCellInfo(x)
@@ -65071,14 +66276,15 @@ static int accessPayload(
*/
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
- if( nOvfl>pCur->nOvflAlloc ){
+ if( pCur->aOverflow==0
+ || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
+ ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
return SQLITE_NOMEM_BKPT;
}else{
- pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
@@ -66592,9 +67798,8 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Write the
-** local Cell size (the number of bytes on the original page, omitting
-** overflow) into *pnSize.
+** Free any overflow pages associated with the given Cell. Store
+** size information about the cell in pInfo.
*/
static int clearCell(
MemPage *pPage, /* The page that contains the Cell */
@@ -67798,7 +69003,7 @@ static int balance_nonroot(
}
/* Load b.apCell[] with pointers to all cells in pOld. If pOld
- ** constains overflow cells, include them in the b.apCell[] array
+ ** contains overflow cells, include them in the b.apCell[] array
** in the correct spot.
**
** Note that when there are multiple overflow cells, it is always the
@@ -71283,6 +72488,51 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Check that string value of pMem agrees with its integer or real value.
+**
+** A single int or real value always converts to the same strings. But
+** many different strings can be converted into the same int or real.
+** If a table contains a numeric value and an index is based on the
+** corresponding string value, then it is important that the string be
+** derived from the numeric value, not the other way around, to ensure
+** that the index and table are consistent. See ticket
+** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
+** an example.
+**
+** This routine looks at pMem to verify that if it has both a numeric
+** representation and a string representation then the string rep has
+** been derived from the numeric and not the other way around. It returns
+** true if everything is ok and false if there is a problem.
+**
+** This routine is for use inside of assert() statements only.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemConsistentDualRep(Mem *p){
+ char zBuf[100];
+ char *z;
+ int i, j, incr;
+ if( (p->flags & MEM_Str)==0 ) return 1;
+ if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1;
+ if( p->flags & MEM_Int ){
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i);
+ }else{
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r);
+ }
+ z = p->z;
+ i = j = 0;
+ incr = 1;
+ if( p->enc!=SQLITE_UTF8 ){
+ incr = 2;
+ if( p->enc==SQLITE_UTF16BE ) z++;
+ }
+ while( zBuf[j] ){
+ if( zBuf[j++]!=z[i] ) return 0;
+ i += incr;
+ }
+ return 1;
+}
+#endif /* SQLITE_DEBUG */
/*
** If pMem is an object with a valid string representation, this routine
@@ -71718,6 +72968,16 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
}
/*
+** Return 1 if pMem represents true, and return 0 if pMem represents false.
+** Return the value ifNull if pMem is NULL.
+*/
+SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
+ if( pMem->flags & MEM_Int ) return pMem->u.i!=0;
+ if( pMem->flags & MEM_Null ) return ifNull;
+ return sqlite3VdbeRealValue(pMem)!=0.0;
+}
+
+/*
** The MEM structure is already a MEM_Real. Try to also make it a
** MEM_Int if we can.
*/
@@ -71772,6 +73032,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
return SQLITE_OK;
}
+/* Compare a floating point value to an integer. Return true if the two
+** values are the same within the precision of the floating point value.
+**
+** For some versions of GCC on 32-bit machines, if you do the more obvious
+** comparison of "r1==(double)i" you sometimes get an answer of false even
+** though the r1 and (double)i values are bit-for-bit the same.
+*/
+static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
+ double r2 = (double)i;
+ return memcmp(&r1, &r2, sizeof(r1))==0;
+}
+
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
@@ -71791,7 +73063,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
}else{
i64 i = pMem->u.i;
sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
- if( rc==1 && pMem->u.r==(double)i ){
+ if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){
pMem->u.i = i;
MemSetTypeFlag(pMem, MEM_Int);
}else{
@@ -72274,6 +73546,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|| pVal->db->mallocFailed );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
+ assert( sqlite3VdbeMemConsistentDualRep(pVal) );
return pVal->z;
}else{
return 0;
@@ -72296,6 +73569,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
assert( (pVal->flags & MEM_RowSet)==0 );
if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
+ assert( sqlite3VdbeMemConsistentDualRep(pVal) );
return pVal->z;
}
if( pVal->flags&MEM_Null ){
@@ -78077,14 +79351,12 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
- pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
- pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
@@ -78190,8 +79462,7 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
return SQLITE_OK;
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
- pCtx->isError = errCode;
- pCtx->fErrorOrAux = 1;
+ pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
@@ -78205,7 +79476,6 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
- pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
@@ -78215,7 +79485,6 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
pCtx->isError = SQLITE_NOMEM_BKPT;
- pCtx->fErrorOrAux = 1;
sqlite3OomFault(pCtx->pOut->db);
}
@@ -78622,10 +79891,7 @@ SQLITE_API void sqlite3_set_auxdata(
pAuxData->iAuxArg = iArg;
pAuxData->pNextAux = pVdbe->pAuxData;
pVdbe->pAuxData = pAuxData;
- if( pCtx->fErrorOrAux==0 ){
- pCtx->isError = 0;
- pCtx->fErrorOrAux = 1;
- }
+ if( pCtx->isError==0 ) pCtx->isError = -1;
}else if( pAuxData->xDeleteAux ){
pAuxData->xDeleteAux(pAuxData->pAux);
}
@@ -79381,7 +80647,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
u32 v;
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !pStmt ){
+ if( !pStmt
+ || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
+ ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
@@ -80155,6 +81423,11 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
pRec->flags |= MEM_Real;
if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
}
+ /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the
+ ** string representation after computing a numeric equivalent, because the
+ ** string representation might not be the canonical representation for the
+ ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */
+ pRec->flags &= ~MEM_Str;
}
/*
@@ -80623,7 +81896,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pOp>=aOp && pOp<&aOp[p->nOp]);
#ifdef VDBE_PROFILE
- start = sqlite3Hwtime();
+ start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
#endif
nVmStep++;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -82147,18 +83420,8 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- pIn1 = &aMem[pOp->p1];
- if( pIn1->flags & MEM_Null ){
- v1 = 2;
- }else{
- v1 = sqlite3VdbeIntValue(pIn1)!=0;
- }
- pIn2 = &aMem[pOp->p2];
- if( pIn2->flags & MEM_Null ){
- v2 = 2;
- }else{
- v2 = sqlite3VdbeIntValue(pIn2)!=0;
- }
+ v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2);
+ v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2);
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
v1 = and_logic[v1*3+v2];
@@ -82176,6 +83439,35 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
break;
}
+/* Opcode: IsTrue P1 P2 P3 P4 *
+** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4
+**
+** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and
+** IS NOT FALSE operators.
+**
+** Interpret the value in register P1 as a boolean value. Store that
+** boolean (a 0 or 1) in register P2. Or if the value in register P1 is
+** NULL, then the P3 is stored in register P2. Invert the answer if P4
+** is 1.
+**
+** The logic is summarized like this:
+**
+** <ul>
+** <li> If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE
+** <li> If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE
+** <li> If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE
+** <li> If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE
+** </ul>
+*/
+case OP_IsTrue: { /* in1, out2 */
+ assert( pOp->p4type==P4_INT32 );
+ assert( pOp->p4.i==0 || pOp->p4.i==1 );
+ assert( pOp->p3==0 || pOp->p3==1 );
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p2],
+ sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i);
+ break;
+}
+
/* Opcode: Not P1 P2 * * *
** Synopsis: r[P2]= !r[P1]
**
@@ -82186,10 +83478,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
case OP_Not: { /* same as TK_NOT, in1, out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
- sqlite3VdbeMemSetNull(pOut);
if( (pIn1->flags & MEM_Null)==0 ){
- pOut->flags = MEM_Int;
- pOut->u.i = !sqlite3VdbeIntValue(pIn1);
+ sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0));
+ }else{
+ sqlite3VdbeMemSetNull(pOut);
}
break;
}
@@ -82256,30 +83548,25 @@ case OP_Once: { /* jump */
** is considered true if it is numeric and non-zero. If the value
** in P1 is NULL then take the jump if and only if P3 is non-zero.
*/
+case OP_If: { /* jump, in1 */
+ int c;
+ c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3);
+ VdbeBranchTaken(c!=0, 2);
+ if( c ) goto jump_to_p2;
+ break;
+}
+
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False. The value
** is considered false if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if and only if P3 is non-zero.
*/
-case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
- pIn1 = &aMem[pOp->p1];
- if( pIn1->flags & MEM_Null ){
- c = pOp->p3;
- }else{
-#ifdef SQLITE_OMIT_FLOATING_POINT
- c = sqlite3VdbeIntValue(pIn1)!=0;
-#else
- c = sqlite3VdbeRealValue(pIn1)!=0.0;
-#endif
- if( pOp->opcode==OP_IfNot ) c = !c;
- }
+ c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3);
VdbeBranchTaken(c!=0, 2);
- if( c ){
- goto jump_to_p2;
- }
+ if( c ) goto jump_to_p2;
break;
}
@@ -82340,7 +83627,7 @@ case OP_IfNullRow: { /* jump */
** P2 is the column number for the argument to the sqlite_offset() function.
** This opcode does not use P2 itself, but the P2 value is used by the
** code generator. The P1, P2, and P3 operands to this opcode are the
-** as as for OP_Column.
+** same as for OP_Column.
**
** This opcode is only available if SQLite is compiled with the
** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
@@ -84248,6 +85535,10 @@ case OP_NewRowid: { /* out2 */
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
+ if( !pC->isTable ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
@@ -86184,12 +87475,17 @@ case OP_AggStep0: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
+ pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
+ (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
if( pCtx==0 ) goto no_mem;
pCtx->pMem = 0;
+ pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+ sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
+ pCtx->skipFlag = 0;
+ pCtx->isError = 0;
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
@@ -86200,7 +87496,6 @@ case OP_AggStep: {
int i;
sqlite3_context *pCtx;
Mem *pMem;
- Mem t;
assert( pOp->p4type==P4_FUNCCTX );
pCtx = pOp->p4.pCtx;
@@ -86223,26 +87518,28 @@ case OP_AggStep: {
#endif
pMem->n++;
- sqlite3VdbeMemInit(&t, db, MEM_Null);
- pCtx->pOut = &t;
- pCtx->fErrorOrAux = 0;
- pCtx->skipFlag = 0;
+ assert( pCtx->pOut->flags==MEM_Null );
+ assert( pCtx->isError==0 );
+ assert( pCtx->skipFlag==0 );
(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
- if( pCtx->fErrorOrAux ){
- if( pCtx->isError ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
+ if( pCtx->isError ){
+ if( pCtx->isError>0 ){
+ sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
rc = pCtx->isError;
}
- sqlite3VdbeMemRelease(&t);
+ if( pCtx->skipFlag ){
+ assert( pOp[-1].opcode==OP_CollSeq );
+ i = pOp[-1].p1;
+ if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
+ pCtx->skipFlag = 0;
+ }
+ sqlite3VdbeMemRelease(pCtx->pOut);
+ pCtx->pOut->flags = MEM_Null;
+ pCtx->isError = 0;
if( rc ) goto abort_due_to_error;
- }else{
- assert( t.flags==MEM_Null );
- }
- if( pCtx->skipFlag ){
- assert( pOp[-1].opcode==OP_CollSeq );
- i = pOp[-1].p1;
- if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
}
+ assert( pCtx->pOut->flags==MEM_Null );
+ assert( pCtx->skipFlag==0 );
break;
}
@@ -86729,7 +88026,8 @@ case OP_VColumn: {
}
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
sqlite3VtabImportErrmsg(p, pVtab);
- if( sContext.isError ){
+ if( sContext.isError>0 ){
+ sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
rc = sContext.isError;
}
sqlite3VdbeChangeEncoding(pDest, encoding);
@@ -86994,6 +88292,7 @@ case OP_Function0: {
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
+ pCtx->isError = 0;
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
@@ -87028,16 +88327,17 @@ case OP_Function: {
}
#endif
MemSetTypeFlag(pOut, MEM_Null);
- pCtx->fErrorOrAux = 0;
+ assert( pCtx->isError==0 );
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
/* If the function returned an error, throw an exception */
- if( pCtx->fErrorOrAux ){
- if( pCtx->isError ){
+ if( pCtx->isError ){
+ if( pCtx->isError>0 ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
+ pCtx->isError = 0;
if( rc ) goto abort_due_to_error;
}
@@ -87079,8 +88379,10 @@ case OP_Function: {
*/
case OP_Trace:
case OP_Init: { /* jump */
- char *zTrace;
int i;
+#ifndef SQLITE_OMIT_TRACE
+ char *zTrace;
+#endif
/* If the P4 argument is not NULL, then it must be an SQL comment string.
** The "--" string is broken up to prevent false-positives with srcck1.c.
@@ -87197,7 +88499,7 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef VDBE_PROFILE
{
- u64 endTime = sqlite3Hwtime();
+ u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
if( endTime>start ) pOrigOp->cycles += endTime - start;
pOrigOp->cnt++;
}
@@ -91584,10 +92886,16 @@ static int lookupName(
** Because no reference was made to outer contexts, the pNC->nRef
** fields are not changed in any context.
*/
- if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
- pExpr->op = TK_STRING;
- pExpr->pTab = 0;
- return WRC_Prune;
+ if( cnt==0 && zTab==0 ){
+ assert( pExpr->op==TK_ID );
+ if( ExprHasProperty(pExpr,EP_DblQuoted) ){
+ pExpr->op = TK_STRING;
+ pExpr->pTab = 0;
+ return WRC_Prune;
+ }
+ if( sqlite3ExprIdToTrueFalse(pExpr) ){
+ return WRC_Prune;
+ }
}
/*
@@ -91936,15 +93244,30 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
break;
}
+ case TK_IS:
+ case TK_ISNOT: {
+ Expr *pRight;
+ assert( !ExprHasProperty(pExpr, EP_Reduced) );
+ /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
+ ** and "x IS NOT FALSE". */
+ if( (pRight = pExpr->pRight)->op==TK_ID ){
+ int rc = resolveExprStep(pWalker, pRight);
+ if( rc==WRC_Abort ) return WRC_Abort;
+ if( pRight->op==TK_TRUEFALSE ){
+ pExpr->op2 = pExpr->op;
+ pExpr->op = TK_TRUTH;
+ return WRC_Continue;
+ }
+ }
+ /* Fall thru */
+ }
case TK_BETWEEN:
case TK_EQ:
case TK_NE:
case TK_LT:
case TK_LE:
case TK_GT:
- case TK_GE:
- case TK_IS:
- case TK_ISNOT: {
+ case TK_GE: {
int nLeft, nRight;
if( pParse->db->mallocFailed ) break;
assert( pExpr->pLeft!=0 );
@@ -94420,6 +95743,34 @@ SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
}
/*
+** If the input expression is an ID with the name "true" or "false"
+** then convert it into an TK_TRUEFALSE term. Return non-zero if
+** the conversion happened, and zero if the expression is unaltered.
+*/
+SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
+ assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
+ if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
+ || sqlite3StrICmp(pExpr->u.zToken, "false")==0
+ ){
+ pExpr->op = TK_TRUEFALSE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE
+** and 0 if it is FALSE.
+*/
+SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){
+ assert( pExpr->op==TK_TRUEFALSE );
+ assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
+ || sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
+ return pExpr->u.zToken[4]==0;
+}
+
+
+/*
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant. The
** Walker.eCode value determines the type of "constant" we are looking
@@ -94466,6 +95817,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
return WRC_Abort;
}
case TK_ID:
+ /* Convert "true" or "false" in a DEFAULT clause into the
+ ** appropriate TK_TRUEFALSE operator */
+ if( sqlite3ExprIdToTrueFalse(pExpr) ){
+ return WRC_Prune;
+ }
+ /* Fall thru */
case TK_COLUMN:
case TK_AGG_FUNCTION:
case TK_AGG_COLUMN:
@@ -96230,6 +97587,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
codeInteger(pParse, pExpr, 0, target);
return target;
}
+ case TK_TRUEFALSE: {
+ sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target);
+ return target;
+ }
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
@@ -96385,6 +97746,18 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
sqlite3VdbeAddOp2(v, op, r1, inReg);
break;
}
+ case TK_TRUTH: {
+ int isTrue; /* IS TRUE or IS NOT TRUE */
+ int bNormal; /* IS TRUE or IS FALSE */
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ testcase( regFree1==0 );
+ isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+ bNormal = pExpr->op2==TK_IS;
+ testcase( isTrue && bNormal);
+ testcase( !isTrue && bNormal);
+ sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal);
+ break;
+ }
case TK_ISNULL:
case TK_NOTNULL: {
int addr;
@@ -97160,6 +98533,23 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
break;
}
+ case TK_TRUTH: {
+ int isNot; /* IS NOT TRUE or IS NOT FALSE */
+ int isTrue; /* IS TRUE or IS NOT TRUE */
+ testcase( jumpIfNull==0 );
+ isNot = pExpr->op2==TK_ISNOT;
+ isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+ testcase( isTrue && isNot );
+ testcase( !isTrue && isNot );
+ if( isTrue ^ isNot ){
+ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
+ isNot ? SQLITE_JUMPIFNULL : 0);
+ }else{
+ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
+ isNot ? SQLITE_JUMPIFNULL : 0);
+ }
+ break;
+ }
case TK_IS:
case TK_ISNOT:
testcase( op==TK_IS );
@@ -97314,6 +98704,26 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
break;
}
+ case TK_TRUTH: {
+ int isNot; /* IS NOT TRUE or IS NOT FALSE */
+ int isTrue; /* IS TRUE or IS NOT TRUE */
+ testcase( jumpIfNull==0 );
+ isNot = pExpr->op2==TK_ISNOT;
+ isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+ testcase( isTrue && isNot );
+ testcase( !isTrue && isNot );
+ if( isTrue ^ isNot ){
+ /* IS TRUE and IS NOT FALSE */
+ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest,
+ isNot ? 0 : SQLITE_JUMPIFNULL);
+
+ }else{
+ /* IS FALSE and IS NOT TRUE */
+ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest,
+ isNot ? 0 : SQLITE_JUMPIFNULL);
+ }
+ break;
+ }
case TK_IS:
case TK_ISNOT:
testcase( pExpr->op==TK_IS );
@@ -97602,6 +99012,105 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i
}
/*
+** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
+** If the expression node requires that the table at pWalker->iCur
+** have a non-NULL column, then set pWalker->eCode to 1 and abort.
+*/
+static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
+ /* This routine is only called for WHERE clause expressions and so it
+ ** cannot have any TK_AGG_COLUMN entries because those are only found
+ ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
+ ** but that is an illegal construct and the query will be rejected at
+ ** a later stage of processing, so the TK_AGG_FUNCTION case does not
+ ** need to be considered here. */
+ assert( pExpr->op!=TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_AGG_FUNCTION );
+
+ if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
+ switch( pExpr->op ){
+ case TK_ISNOT:
+ case TK_NOT:
+ case TK_ISNULL:
+ case TK_IS:
+ case TK_OR:
+ case TK_CASE:
+ case TK_IN:
+ case TK_FUNCTION:
+ testcase( pExpr->op==TK_ISNOT );
+ testcase( pExpr->op==TK_NOT );
+ testcase( pExpr->op==TK_ISNULL );
+ testcase( pExpr->op==TK_IS );
+ testcase( pExpr->op==TK_OR );
+ testcase( pExpr->op==TK_CASE );
+ testcase( pExpr->op==TK_IN );
+ testcase( pExpr->op==TK_FUNCTION );
+ return WRC_Prune;
+ case TK_COLUMN:
+ if( pWalker->u.iCur==pExpr->iTable ){
+ pWalker->eCode = 1;
+ return WRC_Abort;
+ }
+ return WRC_Prune;
+
+ /* Virtual tables are allowed to use constraints like x=NULL. So
+ ** a term of the form x=y does not prove that y is not null if x
+ ** is the column of a virtual table */
+ case TK_EQ:
+ case TK_NE:
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ testcase( pExpr->op==TK_EQ );
+ testcase( pExpr->op==TK_NE );
+ testcase( pExpr->op==TK_LT );
+ testcase( pExpr->op==TK_LE );
+ testcase( pExpr->op==TK_GT );
+ testcase( pExpr->op==TK_GE );
+ if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
+ || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+ ){
+ return WRC_Prune;
+ }
+ default:
+ return WRC_Continue;
+ }
+}
+
+/*
+** Return true (non-zero) if expression p can only be true if at least
+** one column of table iTab is non-null. In other words, return true
+** if expression p will always be NULL or false if every column of iTab
+** is NULL.
+**
+** False negatives are acceptable. In other words, it is ok to return
+** zero even if expression p will never be true of every column of iTab
+** is NULL. A false negative is merely a missed optimization opportunity.
+**
+** False positives are not allowed, however. A false positive may result
+** in an incorrect answer.
+**
+** Terms of p that are marked with EP_FromJoin (and hence that come from
+** the ON or USING clauses of LEFT JOINS) are excluded from the analysis.
+**
+** This routine is used to check if a LEFT JOIN can be converted into
+** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE
+** clause requires that some column of the right table of the LEFT JOIN
+** be non-NULL, then the LEFT JOIN can be safely converted into an
+** ordinary join.
+*/
+SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
+ Walker w;
+ w.xExprCallback = impliesNotNullRow;
+ w.xSelectCallback = 0;
+ w.xSelectCallback2 = 0;
+ w.eCode = 0;
+ w.u.iCur = iTab;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
+}
+
+/*
** An instance of the following structure is used by the tree walker
** to determine if an expression can be evaluated by reference to the
** index only, without having to do a search for the corresponding
@@ -99845,7 +101354,7 @@ static void analyzeOneTable(
/* Do not gather statistics on views or virtual tables */
return;
}
- if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){
+ if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){
/* Do not gather statistics on system tables */
return;
}
@@ -100824,6 +102333,10 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
**
** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
** third argument.
+**
+** If the db->init.reopenMemdb flags is set, then instead of attaching a
+** new database, close the database on db->init.iDb and reopen it as an
+** empty MemDB.
*/
static void attachFunc(
sqlite3_context *context,
@@ -100844,65 +102357,85 @@ static void attachFunc(
sqlite3_vfs *pVfs;
UNUSED_PARAMETER(NotUsed);
-
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
- /* Check for the following errors:
- **
- ** * Too many attached databases,
- ** * Transaction currently open
- ** * Specified database name already being used.
- */
- if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
- zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
- db->aLimit[SQLITE_LIMIT_ATTACHED]
- );
- goto attach_error;
- }
- for(i=0; i<db->nDb; i++){
- char *z = db->aDb[i].zDbSName;
- assert( z && zName );
- if( sqlite3StrICmp(z, zName)==0 ){
- zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
+#ifdef SQLITE_ENABLE_DESERIALIZE
+# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
+#else
+# define REOPEN_AS_MEMDB(db) (0)
+#endif
+
+ if( REOPEN_AS_MEMDB(db) ){
+ /* This is not a real ATTACH. Instead, this routine is being called
+ ** from sqlite3_deserialize() to close database db->init.iDb and
+ ** reopen it as a MemDB */
+ pVfs = sqlite3_vfs_find("memdb");
+ if( pVfs==0 ) return;
+ pNew = &db->aDb[db->init.iDb];
+ if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
+ pNew->pBt = 0;
+ pNew->pSchema = 0;
+ rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
+ }else{
+ /* This is a real ATTACH
+ **
+ ** Check for the following errors:
+ **
+ ** * Too many attached databases,
+ ** * Transaction currently open
+ ** * Specified database name already being used.
+ */
+ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
+ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
+ db->aLimit[SQLITE_LIMIT_ATTACHED]
+ );
goto attach_error;
}
+ for(i=0; i<db->nDb; i++){
+ char *z = db->aDb[i].zDbSName;
+ assert( z && zName );
+ if( sqlite3StrICmp(z, zName)==0 ){
+ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
+ goto attach_error;
+ }
+ }
+
+ /* Allocate the new entry in the db->aDb[] array and initialize the schema
+ ** hash tables.
+ */
+ if( db->aDb==db->aDbStatic ){
+ aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
+ if( aNew==0 ) return;
+ memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
+ }else{
+ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
+ if( aNew==0 ) return;
+ }
+ db->aDb = aNew;
+ pNew = &db->aDb[db->nDb];
+ memset(pNew, 0, sizeof(*pNew));
+
+ /* Open the database file. If the btree is successfully opened, use
+ ** it to obtain the database schema. At this point the schema may
+ ** or may not be initialized.
+ */
+ flags = db->openFlags;
+ rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
+ sqlite3_result_error(context, zErr, -1);
+ sqlite3_free(zErr);
+ return;
+ }
+ assert( pVfs );
+ flags |= SQLITE_OPEN_MAIN_DB;
+ rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
+ sqlite3_free( zPath );
+ db->nDb++;
}
-
- /* Allocate the new entry in the db->aDb[] array and initialize the schema
- ** hash tables.
- */
- if( db->aDb==db->aDbStatic ){
- aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
- if( aNew==0 ) return;
- memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
- }else{
- aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
- if( aNew==0 ) return;
- }
- db->aDb = aNew;
- pNew = &db->aDb[db->nDb];
- memset(pNew, 0, sizeof(*pNew));
-
- /* Open the database file. If the btree is successfully opened, use
- ** it to obtain the database schema. At this point the schema may
- ** or may not be initialized.
- */
- flags = db->openFlags;
- rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
- return;
- }
- assert( pVfs );
- flags |= SQLITE_OPEN_MAIN_DB;
- rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
- sqlite3_free( zPath );
- db->nDb++;
db->skipBtreeMutex = 0;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
@@ -100929,7 +102462,7 @@ static void attachFunc(
sqlite3BtreeLeave(pNew->pBt);
}
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- pNew->zDbSName = sqlite3DbStrDup(db, zName);
+ if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -100969,13 +102502,15 @@ static void attachFunc(
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
- ** remove the entry from the db->aDb[] array. i.e. put everything back the way
- ** we found it.
+ ** remove the entry from the db->aDb[] array. i.e. put everything back the
+ ** way we found it.
*/
if( rc==SQLITE_OK ){
sqlite3BtreeEnterAll(db);
+ db->init.iDb = 0;
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
+ assert( zErrDyn==0 || rc!=SQLITE_OK );
}
#ifdef SQLITE_USER_AUTHENTICATION
if( rc==SQLITE_OK ){
@@ -100987,21 +102522,23 @@ static void attachFunc(
}
#endif
if( rc ){
- int iDb = db->nDb - 1;
- assert( iDb>=2 );
- if( db->aDb[iDb].pBt ){
- sqlite3BtreeClose(db->aDb[iDb].pBt);
- db->aDb[iDb].pBt = 0;
- db->aDb[iDb].pSchema = 0;
- }
- sqlite3ResetAllSchemasOfConnection(db);
- db->nDb = iDb;
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
- sqlite3DbFree(db, zErrDyn);
- zErrDyn = sqlite3MPrintf(db, "out of memory");
- }else if( zErrDyn==0 ){
- zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
+ if( !REOPEN_AS_MEMDB(db) ){
+ int iDb = db->nDb - 1;
+ assert( iDb>=2 );
+ if( db->aDb[iDb].pBt ){
+ sqlite3BtreeClose(db->aDb[iDb].pBt);
+ db->aDb[iDb].pBt = 0;
+ db->aDb[iDb].pSchema = 0;
+ }
+ sqlite3ResetAllSchemasOfConnection(db);
+ db->nDb = iDb;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomFault(db);
+ sqlite3DbFree(db, zErrDyn);
+ zErrDyn = sqlite3MPrintf(db, "out of memory");
+ }else if( zErrDyn==0 ){
+ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
+ }
}
goto attach_error;
}
@@ -101273,6 +102810,14 @@ SQLITE_PRIVATE int sqlite3FixSelect(
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
return 1;
}
+ if( pSelect->pWith ){
+ int i;
+ for(i=0; i<pSelect->pWith->nCte; i++){
+ if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
+ return 1;
+ }
+ }
+ }
pSelect = pSelect->pPrior;
}
return 0;
@@ -102736,10 +104281,24 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
*/
SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
Table *p;
+ Column *pCol;
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
- p->aCol[p->nCol-1].notNull = (u8)onError;
+ pCol = &p->aCol[p->nCol-1];
+ pCol->notNull = (u8)onError;
p->tabFlags |= TF_HasNotNull;
+
+ /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created
+ ** on this column. */
+ if( pCol->colFlags & COLFLAG_UNIQUE ){
+ Index *pIdx;
+ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None );
+ if( pIdx->aiColumn[0]==p->nCol-1 ){
+ pIdx->uniqNotNull = 1;
+ }
+ }
+ }
}
/*
@@ -102856,7 +104415,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
pCol->zName);
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
- ** tokens that point to volatile memory.
+ ** tokens that point to volatile memory.
*/
Expr x;
sqlite3ExprDelete(db, pCol->pDflt);
@@ -103100,7 +104659,7 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){
Vdbe *v = pParse->pVdbe;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION,
- db->aDb[iDb].pSchema->schema_cookie+1);
+ (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie));
}
/*
@@ -103474,8 +105033,6 @@ SQLITE_PRIVATE void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
- assert( !db->init.busy || !pSelect );
-
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" or "sqlite_temp_master" table on the disk.
** So do not write to the disk again. Extract the root page number
@@ -103486,6 +105043,10 @@ SQLITE_PRIVATE void sqlite3EndTable(
** table itself. So mark it read-only.
*/
if( db->init.busy ){
+ if( pSelect ){
+ sqlite3ErrorMsg(pParse, "");
+ return;
+ }
p->tnum = db->init.newTnum;
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
@@ -103776,7 +105337,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
+#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -104703,7 +106264,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
*/
if( pList==0 ){
Token prevCol;
- sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName);
+ Column *pCol = &pTab->aCol[pTab->nCol-1];
+ pCol->colFlags |= COLFLAG_UNIQUE;
+ sqlite3TokenInit(&prevCol, pCol->zName);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index;
@@ -107548,6 +109111,8 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
** iteration of the aggregate loop.
*/
static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
+ assert( context->isError<=0 );
+ context->isError = -1;
context->skipFlag = 1;
}
@@ -107614,8 +109179,6 @@ static void lengthFunc(
int argc,
sqlite3_value **argv
){
- int len;
-
assert( argc==1 );
UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
@@ -107627,13 +109190,17 @@ static void lengthFunc(
}
case SQLITE_TEXT: {
const unsigned char *z = sqlite3_value_text(argv[0]);
+ const unsigned char *z0;
+ unsigned char c;
if( z==0 ) return;
- len = 0;
- while( *z ){
- len++;
- SQLITE_SKIP_UTF8(z);
+ z0 = z;
+ while( (c = *z)!=0 ){
+ z++;
+ if( c>=0xc0 ){
+ while( (*z & 0xc0)==0x80 ){ z++; z0++; }
+ }
}
- sqlite3_result_int(context, len);
+ sqlite3_result_int(context, (int)(z-z0));
break;
}
default: {
@@ -108708,6 +110275,8 @@ static void replaceFunc(
i64 nOut; /* Maximum size of zOut */
int loopLimit; /* Last zStr[] that might match zPattern[] */
int i, j; /* Loop counters */
+ unsigned cntExpand; /* Number zOut expansions */
+ sqlite3 *db = sqlite3_context_db_handle(context);
assert( argc==3 );
UNUSED_PARAMETER(argc);
@@ -108739,33 +110308,40 @@ static void replaceFunc(
return;
}
loopLimit = nStr - nPattern;
+ cntExpand = 0;
for(i=j=0; i<=loopLimit; i++){
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
}else{
- u8 *zOld;
- sqlite3 *db = sqlite3_context_db_handle(context);
- nOut += nRep - nPattern;
- testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
- testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
- if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlite3_result_error_toobig(context);
- sqlite3_free(zOut);
- return;
- }
- zOld = zOut;
- zOut = sqlite3_realloc64(zOut, (int)nOut);
- if( zOut==0 ){
- sqlite3_result_error_nomem(context);
- sqlite3_free(zOld);
- return;
+ if( nRep>nPattern ){
+ nOut += nRep - nPattern;
+ testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ sqlite3_free(zOut);
+ return;
+ }
+ cntExpand++;
+ if( (cntExpand&(cntExpand-1))==0 ){
+ /* Grow the size of the output buffer only on substitutions
+ ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
+ u8 *zOld;
+ zOld = zOut;
+ zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(context);
+ sqlite3_free(zOld);
+ return;
+ }
+ }
}
memcpy(&zOut[j], zRep, nRep);
j += nRep;
i += nPattern-1;
}
}
- assert( j+nStr-i+1==nOut );
+ assert( j+nStr-i+1<=nOut );
memcpy(&zOut[j], &zStr[i], nStr-i);
j += nStr - i;
assert( j<=nOut );
@@ -111047,11 +112623,12 @@ static int readsTable(Parse *p, int iDb, Table *pTab){
** first use of table pTab. On 2nd and subsequent uses, the original
** AutoincInfo structure is used.
**
-** Three memory locations are allocated:
+** Four consecutive registers are allocated:
**
-** (1) Register to hold the name of the pTab table.
-** (2) Register to hold the maximum ROWID of pTab.
-** (3) Register to hold the rowid in sqlite_sequence of pTab
+** (1) The name of the pTab table.
+** (2) The maximum ROWID of pTab.
+** (3) The rowid in sqlite_sequence of pTab
+** (4) The original value of the max ROWID in pTab, or NULL if none
**
** The 2nd register is the one that is returned. That is all the
** insert routine needs to know about.
@@ -111079,7 +112656,7 @@ static int autoIncBegin(
pInfo->iDb = iDb;
pToplevel->nMem++; /* Register to hold name of table */
pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */
- pToplevel->nMem++; /* Rowid in sqlite_sequence */
+ pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */
}
memId = pInfo->regCtr;
}
@@ -111107,15 +112684,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList autoInc[] = {
/* 0 */ {OP_Null, 0, 0, 0},
- /* 1 */ {OP_Rewind, 0, 9, 0},
+ /* 1 */ {OP_Rewind, 0, 10, 0},
/* 2 */ {OP_Column, 0, 0, 0},
- /* 3 */ {OP_Ne, 0, 7, 0},
+ /* 3 */ {OP_Ne, 0, 9, 0},
/* 4 */ {OP_Rowid, 0, 0, 0},
/* 5 */ {OP_Column, 0, 1, 0},
- /* 6 */ {OP_Goto, 0, 9, 0},
- /* 7 */ {OP_Next, 0, 2, 0},
- /* 8 */ {OP_Integer, 0, 0, 0},
- /* 9 */ {OP_Close, 0, 0, 0}
+ /* 6 */ {OP_AddImm, 0, 0, 0},
+ /* 7 */ {OP_Copy, 0, 0, 0},
+ /* 8 */ {OP_Goto, 0, 11, 0},
+ /* 9 */ {OP_Next, 0, 2, 0},
+ /* 10 */ {OP_Integer, 0, 0, 0},
+ /* 11 */ {OP_Close, 0, 0, 0}
};
VdbeOp *aOp;
pDb = &db->aDb[p->iDb];
@@ -111126,14 +112705,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn);
if( aOp==0 ) break;
aOp[0].p2 = memId;
- aOp[0].p3 = memId+1;
+ aOp[0].p3 = memId+2;
aOp[2].p3 = memId;
aOp[3].p1 = memId-1;
aOp[3].p3 = memId;
aOp[3].p5 = SQLITE_JUMPIFNULL;
aOp[4].p2 = memId+1;
aOp[5].p3 = memId;
- aOp[8].p2 = memId;
+ aOp[6].p1 = memId;
+ aOp[7].p2 = memId+2;
+ aOp[7].p1 = memId;
+ aOp[10].p2 = memId;
}
}
@@ -111180,6 +112762,8 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
iRec = sqlite3GetTempReg(pParse);
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
+ sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId);
+ VdbeCoverage(v);
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn);
if( aOp==0 ) break;
@@ -113828,8 +115412,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_pointer sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
-#define sqlite3_value_nochange sqltie3_api->value_nochange
-#define sqlite3_vtab_collation sqltie3_api->vtab_collation
+#define sqlite3_value_nochange sqlite3_api->value_nochange
+#define sqlite3_vtab_collation sqlite3_api->vtab_collation
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -117813,7 +119397,7 @@ static void corruptSchema(
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
- if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
+ if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
sqlite3DbFree(db, *pData->pzErrMsg);
*pData->pzErrMsg = z;
}
@@ -118707,8 +120291,7 @@ SQLITE_API int sqlite3_prepare16_v3(
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
- sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\
- (S)->zSelName,(S)),\
+ sqlite3DebugPrintf("%s/%p: ",(S)->zSelName,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
@@ -119069,6 +120652,29 @@ static void setJoinExpr(Expr *p, int iTable){
}
}
+/* Undo the work of setJoinExpr(). In the expression tree p, convert every
+** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
+** an ordinary term that omits the EP_FromJoin mark.
+**
+** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
+*/
+static void unsetJoinExpr(Expr *p, int iTable){
+ while( p ){
+ if( ExprHasProperty(p, EP_FromJoin)
+ && (iTable<0 || p->iRightJoinTable==iTable) ){
+ ExprClearProperty(p, EP_FromJoin);
+ }
+ if( p->op==TK_FUNCTION && p->x.pList ){
+ int i;
+ for(i=0; i<p->x.pList->nExpr; i++){
+ unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
+ }
+ }
+ unsetJoinExpr(p->pLeft, iTable);
+ p = p->pRight;
+ }
+}
+
/*
** This routine processes the join information for a SELECT statement.
** ON and USING clauses are converted into extra terms of the WHERE clause.
@@ -119952,12 +121558,15 @@ static void generateSortTail(
iSortTab = iTab;
bSeq = 1;
}
- for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
+ for(i=0, iCol=nKey+bSeq-1; i<nSortData; i++){
+ if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
+ }
+ for(i=nSortData-1; i>=0; i--){
int iRead;
if( aOutEx[i].u.x.iOrderByCol ){
iRead = aOutEx[i].u.x.iOrderByCol-1;
}else{
- iRead = iCol++;
+ iRead = iCol--;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
@@ -122434,7 +124043,6 @@ static int flattenSubquery(
pOrderBy->a[i].u.x.iOrderByCol = 0;
}
assert( pParent->pOrderBy==0 );
- assert( pSub->pPrior==0 );
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
@@ -122518,12 +124126,22 @@ static int flattenSubquery(
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
** close would change the meaning of the LIMIT).
**
-** (4) The inner query is the right operand of a LEFT JOIN. (The caller
-** enforces this restriction since this routine does not have enough
-** information to know.)
+** (4) The inner query is the right operand of a LEFT JOIN and the
+** expression to be pushed down does not come from the ON clause
+** on that LEFT JOIN.
**
** (5) The WHERE clause expression originates in the ON or USING clause
-** of a LEFT JOIN.
+** of a LEFT JOIN where iCursor is not the right-hand table of that
+** left join. An example:
+**
+** SELECT *
+** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa
+** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2)
+** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2);
+**
+** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9).
+** But if the (b2=2) term were to be pushed down into the bb subquery,
+** then the (1,1,NULL) row would be suppressed.
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -122532,7 +124150,8 @@ static int pushDownWhereTerms(
Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
- int iCursor /* Cursor number of the subquery */
+ int iCursor, /* Cursor number of the subquery */
+ int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */
){
Expr *pNew;
int nChng = 0;
@@ -122556,15 +124175,25 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
- nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
+ iCursor, isLeftJoin);
pWhere = pWhere->pLeft;
}
- if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */
+ if( isLeftJoin
+ && (ExprHasProperty(pWhere,EP_FromJoin)==0
+ || pWhere->iRightJoinTable!=iCursor)
+ ){
+ return 0; /* restriction (4) */
+ }
+ if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
+ return 0; /* restriction (5) */
+ }
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
+ unsetJoinExpr(pNew, -1);
x.pParse = pParse;
x.iTable = iCursor;
x.iNewTable = iCursor;
@@ -123019,9 +124648,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
- if( OK_IF_ALWAYS_TRUE(p->pWith) ){
- sqlite3WithPush(pParse, p->pWith, 0);
- }
+ sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
@@ -123597,14 +125224,6 @@ static void explainSimpleCount(
#endif
/*
-** Context object for havingToWhereExprCb().
-*/
-struct HavingToWhereCtx {
- Expr **ppWhere;
- ExprList *pGroupBy;
-};
-
-/*
** sqlite3WalkExpr() callback used by havingToWhere().
**
** If the node passed to the callback is a TK_AND node, return
@@ -123617,15 +125236,16 @@ struct HavingToWhereCtx {
*/
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op!=TK_AND ){
- struct HavingToWhereCtx *p = pWalker->u.pHavingCtx;
- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){
+ Select *pS = pWalker->u.pSelect;
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
sqlite3 *db = pWalker->pParse->db;
Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
if( pNew ){
- Expr *pWhere = *(p->ppWhere);
+ Expr *pWhere = pS->pWhere;
SWAP(Expr, *pNew, *pExpr);
pNew = sqlite3ExprAnd(db, pWhere, pNew);
- *(p->ppWhere) = pNew;
+ pS->pWhere = pNew;
+ pWalker->eCode = 1;
}
}
return WRC_Prune;
@@ -123648,23 +125268,19 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
** entirely of constants and expressions that are also GROUP BY terms that
** use the "BINARY" collation sequence.
*/
-static void havingToWhere(
- Parse *pParse,
- ExprList *pGroupBy,
- Expr *pHaving,
- Expr **ppWhere
-){
- struct HavingToWhereCtx sCtx;
+static void havingToWhere(Parse *pParse, Select *p){
Walker sWalker;
-
- sCtx.ppWhere = ppWhere;
- sCtx.pGroupBy = pGroupBy;
-
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.xExprCallback = havingToWhereExprCb;
- sWalker.u.pHavingCtx = &sCtx;
- sqlite3WalkExpr(&sWalker, pHaving);
+ sWalker.u.pSelect = p;
+ sqlite3WalkExpr(&sWalker, p->pHaving);
+#if SELECTTRACE_ENABLED
+ if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
+ SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
}
/*
@@ -123825,7 +125441,6 @@ SQLITE_PRIVATE int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
- pParse->nSelectIndent++;
SELECTTRACE(1,pParse,p, ("begin processing:\n"));
if( sqlite3SelectTrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
@@ -123871,13 +125486,29 @@ SQLITE_PRIVATE int sqlite3Select(
generateColumnNames(pParse, p);
}
- /* Try to flatten subqueries in the FROM clause up into the main query
+ /* Try to various optimizations (flattening subqueries, and strength
+ ** reduction of join operators) in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
+
+ /* Convert LEFT JOIN into JOIN if there are terms of the right table
+ ** of the LEFT JOIN used in the WHERE clause.
+ */
+ if( (pItem->fg.jointype & JT_LEFT)!=0
+ && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor)
+ && OptimizationEnabled(db, SQLITE_SimplifyJoin)
+ ){
+ SELECTTRACE(0x100,pParse,p,
+ ("LEFT-JOIN simplifies to JOIN on term %d\n",i));
+ pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
+ unsetJoinExpr(p->pWhere, pItem->iCursor);
+ }
+
+ /* No futher action if this term of the FROM clause is no a subquery */
if( pSub==0 ) continue;
/* Catch mismatch in the declared columns of a view and the number of
@@ -123946,7 +125577,6 @@ SQLITE_PRIVATE int sqlite3Select(
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
- pParse->nSelectIndent--;
#endif
return rc;
}
@@ -124019,8 +125649,9 @@ SQLITE_PRIVATE int sqlite3Select(
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
- if( (pItem->fg.jointype & JT_OUTER)==0
- && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor)
+ if( OptimizationEnabled(db, SQLITE_PushDown)
+ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
+ (pItem->fg.jointype & JT_OUTER)!=0)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
@@ -124028,6 +125659,8 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ }else{
+ SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
zSavedAuthContext = pParse->zAuthContext;
@@ -124230,6 +125863,7 @@ SQLITE_PRIVATE int sqlite3Select(
wctrlFlags |= p->selFlags & SF_FixedLimit;
/* Begin the database scan. */
+ SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
p->pEList, wctrlFlags, p->nSelectRow);
if( pWInfo==0 ) goto select_end;
@@ -124331,7 +125965,9 @@ SQLITE_PRIVATE int sqlite3Select(
if( pHaving ){
if( pGroupBy ){
assert( pWhere==p->pWhere );
- havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere);
+ assert( pHaving==p->pHaving );
+ assert( pGroupBy==p->pGroupBy );
+ havingToWhere(pParse, p);
pWhere = p->pWhere;
}
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
@@ -124418,6 +126054,7 @@ SQLITE_PRIVATE int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
+ SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
);
@@ -124673,6 +126310,7 @@ SQLITE_PRIVATE int sqlite3Select(
assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
+ SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
0, minMaxFlag, 0);
if( pWInfo==0 ){
@@ -124728,7 +126366,6 @@ select_end:
sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end processing\n"));
- pParse->nSelectIndent--;
#endif
return rc;
}
@@ -126474,7 +128111,7 @@ SQLITE_PRIVATE void sqlite3Update(
regKey = ++pParse->nMem;
iEph = pParse->nTab++;
- sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
@@ -127024,8 +128661,8 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
- if( zSubSql ){
- assert( zSubSql[0]!='S' );
+ assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB );
+ if( zSubSql && zSubSql[0]!='S' ){
rc = execSql(db, pzErrMsg, zSubSql);
if( rc!=SQLITE_OK ) break;
}
@@ -128646,7 +130283,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlite3WhereTrace;
+/***/ extern int sqlite3WhereTrace;
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
@@ -130563,7 +132200,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( sqlite3ExprIsVector(pX->pRight) ){
r1 = rTemp = sqlite3GetTempReg(pParse);
codeExprOrVector(pParse, pX->pRight, r1, 1);
- op = aMoveOp[(pX->op - TK_GT) | 0x0001];
+ testcase( pX->op==TK_GT );
+ testcase( pX->op==TK_GE );
+ testcase( pX->op==TK_LT );
+ testcase( pX->op==TK_LE );
+ op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1];
+ assert( pX->op!=TK_GT || op==OP_SeekGE );
+ assert( pX->op!=TK_GE || op==OP_SeekGE );
+ assert( pX->op!=TK_LT || op==OP_SeekLE );
+ assert( pX->op!=TK_LE || op==OP_SeekLE );
}else{
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
disableTerm(pLevel, pStart);
@@ -131287,7 +132932,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
continue;
}
- if( pTerm->wtFlags & TERM_LIKECOND ){
+ if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){
/* If the TERM_LIKECOND flag is set, that means that the range search
** is sufficient to guarantee that the LIKE operator is true, so we
** can skip the call to the like(A,B) function. But this only works
@@ -131297,8 +132942,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
continue;
#else
u32 x = pLevel->iLikeRepCntr;
- assert( x>0 );
- skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1));
+ if( x>0 ){
+ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1));
+ }
VdbeCoverage(v);
#endif
}
@@ -131338,6 +132984,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
+ if( (pAlt->eOperator & WO_IN)
+ && (pAlt->pExpr->flags & EP_xIsSelect)
+ && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
+ ){
+ continue;
+ }
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IS );
testcase( pAlt->eOperator & WO_IN );
@@ -132252,6 +133904,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
for(i=0; i<pSrc->nSrc; i++){
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn);
+ if( pSrc->a[i].fg.isTabFunc ){
+ mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
+ }
}
}
pS = pS->pPrior;
@@ -132664,7 +134319,7 @@ static void exprAnalyze(
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
+ pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
pTerm->eOperator = 0;
}
@@ -135281,8 +136936,8 @@ static int whereLoopAddBtreeIndex(
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n",
- pProbe->zName, pNew->u.btree.nEq));
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n",
+ pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq));
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
@@ -135389,10 +137044,12 @@ static int whereLoopAddBtreeIndex(
if( iCol==XN_ROWID
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
){
- if( iCol>=0 && pProbe->uniqNotNull==0 ){
- pNew->wsFlags |= WHERE_UNQ_WANTED;
- }else{
+ if( iCol==XN_ROWID || pProbe->uniqNotNull
+ || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
+ ){
pNew->wsFlags |= WHERE_ONEROW;
+ }else{
+ pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
}else if( eOp & WO_ISNULL ){
@@ -135566,8 +137223,8 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags = saved_wsFlags;
}
- WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n",
- pProbe->zName, saved_nEq, rc));
+ WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n",
+ pProbe->pTable->zName, pProbe->zName, saved_nEq, rc));
return rc;
}
@@ -136005,9 +137662,9 @@ static int whereLoopAddVirtualOne(
|| pNew->aLTerm[iTerm]!=0
|| pIdxCons->usable==0
){
- rc = SQLITE_ERROR;
sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- return rc;
+ testcase( pIdxInfo->needToFreeIdxStr );
+ return SQLITE_ERROR;
}
testcase( iTerm==nConstraint-1 );
testcase( j==0 );
@@ -136035,6 +137692,15 @@ static int whereLoopAddVirtualOne(
pNew->u.vtab.omitMask &= ~mNoOmit;
pNew->nLTerm = mxTerm+1;
+ for(i=0; i<=mxTerm; i++){
+ if( pNew->aLTerm[i]==0 ){
+ /* The non-zero argvIdx values must be contiguous. Raise an
+ ** error if they are not */
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
+ testcase( pIdxInfo->needToFreeIdxStr );
+ return SQLITE_ERROR;
+ }
+ }
assert( pNew->nLTerm<=pNew->nLSlot );
pNew->u.vtab.idxNum = pIdxInfo->idxNum;
pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
@@ -136150,6 +137816,7 @@ static int whereLoopAddVirtual(
}
/* First call xBestIndex() with all constraints usable. */
+ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
WHERETRACE(0x40, (" VirtualOne: all usable\n"));
rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
@@ -136225,6 +137892,7 @@ static int whereLoopAddVirtual(
if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
sqlite3DbFreeNN(pParse->db, p);
+ WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -137539,6 +139207,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
*/
for(ii=0; ii<sWLB.pWC->nTerm; ii++){
WhereTerm *pT = &sWLB.pWC->a[ii];
+ if( pT->wtFlags & TERM_VIRTUAL ) continue;
if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
pT->wtFlags |= TERM_CODED;
@@ -138364,17 +140033,17 @@ typedef union {
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
#define YYFALLBACK 1
-#define YYNSTATE 466
-#define YYNRULE 330
+#define YYNSTATE 472
+#define YYNRULE 333
#define YYNTOKEN 143
-#define YY_MAX_SHIFT 465
-#define YY_MIN_SHIFTREDUCE 675
-#define YY_MAX_SHIFTREDUCE 1004
-#define YY_ERROR_ACTION 1005
-#define YY_ACCEPT_ACTION 1006
-#define YY_NO_ACTION 1007
-#define YY_MIN_REDUCE 1008
-#define YY_MAX_REDUCE 1337
+#define YY_MAX_SHIFT 471
+#define YY_MIN_SHIFTREDUCE 681
+#define YY_MAX_SHIFTREDUCE 1013
+#define YY_ERROR_ACTION 1014
+#define YY_ACCEPT_ACTION 1015
+#define YY_NO_ACTION 1016
+#define YY_MIN_REDUCE 1017
+#define YY_MAX_REDUCE 1349
/************* End control #defines *******************************************/
/* Define the yytestcase() macro to be a no-op if is not already defined
@@ -138440,322 +140109,324 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1541)
+#define YY_ACTTAB_COUNT (1566)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 1006, 156, 156, 2, 1302, 90, 87, 179, 90, 87,
- /* 10 */ 179, 460, 1048, 460, 465, 1010, 460, 333, 1130, 335,
- /* 20 */ 246, 330, 112, 303, 439, 1258, 304, 419, 1129, 1087,
- /* 30 */ 72, 798, 50, 50, 50, 50, 331, 30, 30, 799,
- /* 40 */ 951, 364, 371, 97, 98, 88, 983, 983, 859, 862,
- /* 50 */ 851, 851, 95, 95, 96, 96, 96, 96, 120, 371,
- /* 60 */ 370, 120, 348, 22, 90, 87, 179, 438, 423, 438,
- /* 70 */ 440, 335, 420, 385, 90, 87, 179, 116, 73, 163,
- /* 80 */ 848, 848, 860, 863, 94, 94, 94, 94, 93, 93,
- /* 90 */ 92, 92, 92, 91, 361, 97, 98, 88, 983, 983,
- /* 100 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96,
- /* 110 */ 718, 365, 339, 93, 93, 92, 92, 92, 91, 361,
- /* 120 */ 99, 371, 453, 335, 94, 94, 94, 94, 93, 93,
- /* 130 */ 92, 92, 92, 91, 361, 852, 94, 94, 94, 94,
- /* 140 */ 93, 93, 92, 92, 92, 91, 361, 97, 98, 88,
- /* 150 */ 983, 983, 859, 862, 851, 851, 95, 95, 96, 96,
- /* 160 */ 96, 96, 92, 92, 92, 91, 361, 838, 132, 195,
- /* 170 */ 58, 244, 412, 409, 408, 335, 457, 457, 457, 304,
- /* 180 */ 59, 332, 831, 407, 394, 962, 830, 391, 94, 94,
- /* 190 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 97,
- /* 200 */ 98, 88, 983, 983, 859, 862, 851, 851, 95, 95,
- /* 210 */ 96, 96, 96, 96, 426, 357, 460, 830, 830, 832,
- /* 220 */ 91, 361, 962, 963, 964, 195, 459, 335, 412, 409,
- /* 230 */ 408, 280, 361, 820, 132, 11, 11, 50, 50, 407,
- /* 240 */ 94, 94, 94, 94, 93, 93, 92, 92, 92, 91,
- /* 250 */ 361, 97, 98, 88, 983, 983, 859, 862, 851, 851,
- /* 260 */ 95, 95, 96, 96, 96, 96, 460, 221, 460, 264,
- /* 270 */ 375, 254, 438, 428, 1276, 1276, 383, 1074, 1053, 335,
- /* 280 */ 245, 422, 299, 713, 271, 271, 1074, 50, 50, 50,
- /* 290 */ 50, 962, 94, 94, 94, 94, 93, 93, 92, 92,
- /* 300 */ 92, 91, 361, 97, 98, 88, 983, 983, 859, 862,
- /* 310 */ 851, 851, 95, 95, 96, 96, 96, 96, 90, 87,
- /* 320 */ 179, 1306, 438, 437, 438, 418, 368, 253, 962, 963,
- /* 330 */ 964, 335, 360, 360, 360, 706, 359, 358, 324, 962,
- /* 340 */ 1281, 951, 364, 230, 94, 94, 94, 94, 93, 93,
- /* 350 */ 92, 92, 92, 91, 361, 97, 98, 88, 983, 983,
- /* 360 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96,
- /* 370 */ 769, 460, 120, 226, 226, 366, 962, 963, 964, 1089,
- /* 380 */ 990, 900, 990, 335, 1057, 425, 421, 839, 759, 759,
- /* 390 */ 425, 427, 50, 50, 432, 381, 94, 94, 94, 94,
- /* 400 */ 93, 93, 92, 92, 92, 91, 361, 97, 98, 88,
- /* 410 */ 983, 983, 859, 862, 851, 851, 95, 95, 96, 96,
- /* 420 */ 96, 96, 460, 259, 460, 120, 117, 354, 942, 1332,
- /* 430 */ 942, 1333, 1332, 278, 1333, 335, 680, 681, 682, 825,
- /* 440 */ 201, 176, 303, 50, 50, 49, 49, 404, 94, 94,
- /* 450 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 97,
- /* 460 */ 98, 88, 983, 983, 859, 862, 851, 851, 95, 95,
- /* 470 */ 96, 96, 96, 96, 199, 460, 380, 265, 433, 380,
- /* 480 */ 265, 383, 256, 158, 258, 319, 1003, 335, 155, 940,
- /* 490 */ 177, 940, 273, 379, 276, 322, 34, 34, 302, 962,
- /* 500 */ 94, 94, 94, 94, 93, 93, 92, 92, 92, 91,
- /* 510 */ 361, 97, 98, 88, 983, 983, 859, 862, 851, 851,
- /* 520 */ 95, 95, 96, 96, 96, 96, 905, 905, 397, 460,
- /* 530 */ 301, 158, 101, 319, 941, 340, 962, 963, 964, 313,
- /* 540 */ 283, 449, 335, 327, 146, 1266, 1004, 257, 234, 248,
- /* 550 */ 35, 35, 94, 94, 94, 94, 93, 93, 92, 92,
- /* 560 */ 92, 91, 361, 709, 785, 1227, 97, 98, 88, 983,
- /* 570 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96,
- /* 580 */ 96, 962, 1227, 1229, 245, 422, 838, 198, 197, 196,
- /* 590 */ 1079, 1079, 1077, 1077, 1004, 1334, 320, 335, 172, 171,
- /* 600 */ 709, 831, 159, 271, 271, 830, 76, 94, 94, 94,
- /* 610 */ 94, 93, 93, 92, 92, 92, 91, 361, 962, 963,
- /* 620 */ 964, 97, 98, 88, 983, 983, 859, 862, 851, 851,
- /* 630 */ 95, 95, 96, 96, 96, 96, 830, 830, 832, 1157,
- /* 640 */ 1157, 199, 1157, 173, 1227, 231, 232, 1282, 2, 335,
- /* 650 */ 271, 764, 271, 820, 271, 271, 763, 389, 389, 389,
- /* 660 */ 132, 79, 94, 94, 94, 94, 93, 93, 92, 92,
- /* 670 */ 92, 91, 361, 97, 98, 88, 983, 983, 859, 862,
- /* 680 */ 851, 851, 95, 95, 96, 96, 96, 96, 460, 264,
- /* 690 */ 223, 460, 1257, 783, 1223, 1157, 1086, 1082, 80, 271,
- /* 700 */ 78, 335, 340, 1031, 341, 344, 345, 902, 346, 10,
- /* 710 */ 10, 902, 25, 25, 94, 94, 94, 94, 93, 93,
- /* 720 */ 92, 92, 92, 91, 361, 97, 86, 88, 983, 983,
- /* 730 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96,
- /* 740 */ 1157, 270, 395, 117, 233, 263, 235, 70, 456, 341,
- /* 750 */ 225, 176, 335, 1305, 342, 133, 736, 966, 980, 249,
- /* 760 */ 1150, 396, 325, 1085, 1028, 178, 94, 94, 94, 94,
- /* 770 */ 93, 93, 92, 92, 92, 91, 361, 98, 88, 983,
- /* 780 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96,
- /* 790 */ 96, 783, 783, 132, 120, 966, 120, 120, 120, 798,
- /* 800 */ 252, 937, 335, 353, 321, 429, 355, 799, 822, 692,
- /* 810 */ 390, 203, 446, 450, 372, 716, 454, 94, 94, 94,
- /* 820 */ 94, 93, 93, 92, 92, 92, 91, 361, 88, 983,
- /* 830 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96,
- /* 840 */ 96, 84, 455, 1225, 3, 1209, 120, 120, 382, 387,
- /* 850 */ 120, 203, 1271, 716, 384, 168, 266, 203, 458, 72,
- /* 860 */ 260, 1246, 84, 455, 178, 3, 378, 94, 94, 94,
- /* 870 */ 94, 93, 93, 92, 92, 92, 91, 361, 350, 458,
- /* 880 */ 1245, 362, 430, 213, 228, 290, 415, 285, 414, 200,
- /* 890 */ 783, 882, 444, 726, 725, 405, 283, 921, 209, 921,
- /* 900 */ 281, 132, 362, 72, 838, 289, 147, 733, 734, 392,
- /* 910 */ 81, 82, 922, 444, 922, 267, 288, 83, 362, 462,
- /* 920 */ 461, 272, 132, 830, 23, 838, 388, 923, 1216, 923,
- /* 930 */ 1056, 81, 82, 84, 455, 899, 3, 899, 83, 362,
- /* 940 */ 462, 461, 761, 962, 830, 75, 1, 443, 275, 747,
- /* 950 */ 458, 5, 962, 204, 830, 830, 832, 833, 18, 748,
- /* 960 */ 229, 962, 277, 19, 153, 317, 317, 316, 216, 314,
- /* 970 */ 279, 460, 689, 362, 1055, 830, 830, 832, 833, 18,
- /* 980 */ 962, 963, 964, 962, 444, 181, 460, 251, 981, 962,
- /* 990 */ 963, 964, 8, 8, 20, 250, 838, 1070, 962, 963,
- /* 1000 */ 964, 417, 81, 82, 768, 204, 347, 36, 36, 83,
- /* 1010 */ 362, 462, 461, 1054, 284, 830, 84, 455, 1123, 3,
- /* 1020 */ 962, 963, 964, 460, 183, 962, 981, 764, 889, 1107,
- /* 1030 */ 460, 184, 763, 458, 132, 182, 74, 455, 460, 3,
- /* 1040 */ 981, 898, 834, 898, 8, 8, 830, 830, 832, 833,
- /* 1050 */ 18, 8, 8, 458, 219, 1156, 362, 1103, 349, 8,
- /* 1060 */ 8, 240, 962, 963, 964, 236, 889, 444, 792, 336,
- /* 1070 */ 158, 203, 885, 435, 700, 209, 362, 114, 981, 838,
- /* 1080 */ 834, 227, 334, 1114, 441, 81, 82, 444, 442, 305,
- /* 1090 */ 784, 306, 83, 362, 462, 461, 369, 1162, 830, 838,
- /* 1100 */ 460, 1037, 237, 1030, 237, 81, 82, 7, 96, 96,
- /* 1110 */ 96, 96, 83, 362, 462, 461, 1019, 1018, 830, 1020,
- /* 1120 */ 1289, 37, 37, 400, 96, 96, 96, 96, 89, 830,
- /* 1130 */ 830, 832, 833, 18, 1100, 318, 962, 292, 94, 94,
- /* 1140 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 830,
- /* 1150 */ 830, 832, 833, 18, 94, 94, 94, 94, 93, 93,
- /* 1160 */ 92, 92, 92, 91, 361, 359, 358, 226, 226, 727,
- /* 1170 */ 294, 296, 460, 962, 963, 964, 460, 989, 160, 425,
- /* 1180 */ 170, 1295, 262, 460, 987, 374, 988, 386, 1145, 255,
- /* 1190 */ 326, 460, 373, 38, 38, 410, 174, 39, 39, 413,
- /* 1200 */ 460, 287, 460, 1053, 40, 40, 298, 728, 1220, 990,
- /* 1210 */ 445, 990, 26, 26, 1219, 460, 311, 460, 169, 1292,
- /* 1220 */ 460, 27, 27, 29, 29, 998, 460, 206, 135, 995,
- /* 1230 */ 1265, 1263, 460, 57, 60, 460, 41, 41, 42, 42,
- /* 1240 */ 460, 43, 43, 460, 343, 351, 460, 9, 9, 460,
- /* 1250 */ 144, 460, 130, 44, 44, 460, 103, 103, 460, 137,
- /* 1260 */ 70, 45, 45, 460, 46, 46, 460, 31, 31, 1142,
- /* 1270 */ 47, 47, 48, 48, 460, 376, 32, 32, 460, 122,
- /* 1280 */ 122, 460, 157, 460, 123, 123, 139, 124, 124, 460,
- /* 1290 */ 186, 460, 377, 460, 115, 54, 54, 460, 403, 33,
- /* 1300 */ 33, 460, 104, 104, 51, 51, 460, 161, 460, 140,
- /* 1310 */ 105, 105, 106, 106, 102, 102, 460, 141, 121, 121,
- /* 1320 */ 460, 142, 119, 119, 190, 460, 1152, 110, 110, 109,
- /* 1330 */ 109, 702, 460, 148, 393, 65, 460, 107, 107, 460,
- /* 1340 */ 323, 108, 108, 399, 460, 1234, 53, 53, 1214, 269,
- /* 1350 */ 154, 416, 1115, 55, 55, 220, 401, 52, 52, 191,
- /* 1360 */ 24, 24, 274, 192, 193, 28, 28, 1021, 328, 702,
- /* 1370 */ 1073, 352, 1072, 718, 1071, 431, 1111, 1064, 329, 1045,
- /* 1380 */ 69, 205, 6, 291, 1044, 286, 1112, 1043, 1304, 1110,
- /* 1390 */ 293, 300, 295, 297, 1063, 1200, 1109, 77, 241, 448,
- /* 1400 */ 356, 452, 436, 100, 214, 71, 434, 1027, 1093, 21,
- /* 1410 */ 463, 242, 243, 957, 215, 217, 218, 464, 309, 307,
- /* 1420 */ 308, 310, 1016, 125, 1250, 1251, 1011, 1249, 126, 127,
- /* 1430 */ 1248, 113, 676, 337, 238, 338, 134, 363, 167, 1041,
- /* 1440 */ 1040, 56, 247, 367, 180, 897, 111, 895, 136, 1038,
- /* 1450 */ 818, 128, 138, 750, 261, 911, 185, 143, 145, 61,
- /* 1460 */ 62, 63, 64, 129, 914, 187, 188, 910, 118, 12,
- /* 1470 */ 189, 903, 268, 992, 203, 162, 398, 150, 149, 691,
- /* 1480 */ 402, 288, 194, 406, 151, 411, 66, 13, 729, 239,
- /* 1490 */ 282, 14, 67, 131, 837, 836, 865, 758, 15, 4,
- /* 1500 */ 68, 762, 175, 222, 224, 424, 152, 869, 791, 202,
- /* 1510 */ 786, 75, 72, 880, 866, 864, 16, 17, 920, 207,
- /* 1520 */ 919, 208, 447, 946, 164, 211, 947, 210, 165, 451,
- /* 1530 */ 868, 166, 315, 835, 701, 85, 212, 1297, 312, 952,
- /* 1540 */ 1296,
+ /* 0 */ 1169, 1015, 167, 167, 1, 168, 466, 1313, 466, 1083,
+ /* 10 */ 1062, 466, 97, 94, 183, 1057, 466, 329, 1083, 342,
+ /* 20 */ 97, 94, 183, 459, 459, 459, 436, 57, 57, 57,
+ /* 30 */ 57, 807, 57, 57, 367, 367, 367, 57, 57, 808,
+ /* 40 */ 1270, 1088, 1088, 104, 105, 95, 991, 991, 868, 871,
+ /* 50 */ 860, 860, 102, 102, 103, 103, 103, 103, 233, 233,
+ /* 60 */ 326, 1011, 449, 437, 449, 446, 351, 449, 461, 1142,
+ /* 70 */ 463, 342, 449, 426, 1316, 209, 180, 742, 80, 299,
+ /* 80 */ 857, 857, 869, 872, 101, 101, 101, 101, 100, 100,
+ /* 90 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991,
+ /* 100 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103,
+ /* 110 */ 99, 99, 99, 98, 368, 355, 97, 94, 183, 228,
+ /* 120 */ 106, 1012, 407, 342, 101, 101, 101, 101, 100, 100,
+ /* 130 */ 99, 99, 99, 98, 368, 861, 101, 101, 101, 101,
+ /* 140 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95,
+ /* 150 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103,
+ /* 160 */ 103, 103, 201, 368, 375, 420, 417, 416, 387, 273,
+ /* 170 */ 65, 97, 94, 183, 168, 342, 415, 951, 1343, 396,
+ /* 180 */ 66, 1343, 320, 959, 371, 970, 334, 340, 101, 101,
+ /* 190 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104,
+ /* 200 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102,
+ /* 210 */ 103, 103, 103, 103, 373, 100, 100, 99, 99, 99,
+ /* 220 */ 98, 368, 970, 971, 972, 201, 1100, 342, 420, 417,
+ /* 230 */ 416, 287, 366, 365, 337, 970, 1162, 463, 949, 415,
+ /* 240 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98,
+ /* 250 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860,
+ /* 260 */ 102, 102, 103, 103, 103, 103, 777, 241, 233, 233,
+ /* 270 */ 9, 847, 970, 971, 972, 390, 998, 1141, 998, 342,
+ /* 280 */ 463, 252, 829, 719, 98, 368, 840, 298, 338, 142,
+ /* 290 */ 839, 339, 101, 101, 101, 101, 100, 100, 99, 99,
+ /* 300 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871,
+ /* 310 */ 860, 860, 102, 102, 103, 103, 103, 103, 272, 466,
+ /* 320 */ 392, 839, 839, 841, 97, 94, 183, 390, 1317, 253,
+ /* 330 */ 456, 342, 125, 166, 807, 712, 208, 407, 386, 970,
+ /* 340 */ 57, 57, 808, 238, 101, 101, 101, 101, 100, 100,
+ /* 350 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991,
+ /* 360 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103,
+ /* 370 */ 466, 108, 466, 267, 465, 442, 970, 971, 972, 261,
+ /* 380 */ 951, 1344, 909, 342, 1344, 142, 829, 848, 1292, 959,
+ /* 390 */ 371, 55, 55, 57, 57, 242, 101, 101, 101, 101,
+ /* 400 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95,
+ /* 410 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103,
+ /* 420 */ 103, 103, 272, 382, 262, 253, 456, 310, 364, 253,
+ /* 430 */ 456, 86, 264, 84, 266, 342, 441, 176, 175, 834,
+ /* 440 */ 464, 949, 767, 767, 332, 313, 1094, 396, 101, 101,
+ /* 450 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104,
+ /* 460 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102,
+ /* 470 */ 103, 103, 103, 103, 227, 227, 233, 233, 233, 233,
+ /* 480 */ 387, 273, 234, 234, 326, 950, 463, 342, 463, 298,
+ /* 490 */ 463, 914, 914, 404, 463, 1037, 123, 265, 27, 970,
+ /* 500 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98,
+ /* 510 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860,
+ /* 520 */ 102, 102, 103, 103, 103, 103, 435, 233, 233, 466,
+ /* 530 */ 285, 686, 687, 688, 127, 271, 970, 971, 972, 463,
+ /* 540 */ 1345, 327, 342, 407, 157, 1012, 988, 13, 13, 181,
+ /* 550 */ 41, 41, 101, 101, 101, 101, 100, 100, 99, 99,
+ /* 560 */ 99, 98, 368, 715, 794, 378, 104, 105, 95, 991,
+ /* 570 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103,
+ /* 580 */ 103, 970, 378, 377, 346, 239, 847, 1086, 1086, 280,
+ /* 590 */ 1169, 283, 204, 203, 202, 177, 298, 342, 407, 298,
+ /* 600 */ 715, 840, 169, 299, 407, 839, 82, 101, 101, 101,
+ /* 610 */ 101, 100, 100, 99, 99, 99, 98, 368, 970, 971,
+ /* 620 */ 972, 104, 105, 95, 991, 991, 868, 871, 860, 860,
+ /* 630 */ 102, 102, 103, 103, 103, 103, 839, 839, 841, 362,
+ /* 640 */ 240, 124, 1169, 172, 126, 378, 1269, 1169, 1066, 342,
+ /* 650 */ 253, 456, 407, 407, 407, 396, 352, 401, 407, 429,
+ /* 660 */ 398, 85, 101, 101, 101, 101, 100, 100, 99, 99,
+ /* 670 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871,
+ /* 680 */ 860, 860, 102, 102, 103, 103, 103, 103, 1169, 466,
+ /* 690 */ 230, 233, 233, 792, 1235, 1095, 1091, 1293, 1, 77,
+ /* 700 */ 278, 342, 205, 463, 974, 911, 1040, 348, 353, 911,
+ /* 710 */ 42, 42, 79, 403, 101, 101, 101, 101, 100, 100,
+ /* 720 */ 99, 99, 99, 98, 368, 104, 93, 95, 991, 991,
+ /* 730 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103,
+ /* 740 */ 402, 9, 974, 243, 772, 458, 348, 232, 180, 771,
+ /* 750 */ 946, 312, 342, 328, 363, 349, 143, 831, 389, 1278,
+ /* 760 */ 211, 211, 21, 347, 432, 182, 101, 101, 101, 101,
+ /* 770 */ 100, 100, 99, 99, 99, 98, 368, 105, 95, 991,
+ /* 780 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103,
+ /* 790 */ 103, 792, 724, 22, 732, 731, 233, 233, 1239, 256,
+ /* 800 */ 391, 274, 342, 211, 79, 360, 257, 413, 463, 397,
+ /* 810 */ 207, 288, 260, 450, 79, 1239, 1241, 101, 101, 101,
+ /* 820 */ 101, 100, 100, 99, 99, 99, 98, 368, 95, 991,
+ /* 830 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103,
+ /* 840 */ 103, 91, 457, 296, 3, 233, 233, 5, 438, 212,
+ /* 850 */ 331, 394, 739, 740, 295, 898, 894, 463, 460, 207,
+ /* 860 */ 801, 1237, 722, 211, 698, 843, 1283, 101, 101, 101,
+ /* 870 */ 101, 100, 100, 99, 99, 99, 98, 368, 1239, 380,
+ /* 880 */ 357, 369, 233, 233, 989, 219, 236, 297, 423, 292,
+ /* 890 */ 422, 206, 454, 898, 463, 970, 91, 457, 290, 3,
+ /* 900 */ 722, 142, 268, 843, 847, 466, 1258, 149, 388, 425,
+ /* 910 */ 88, 89, 769, 460, 930, 87, 447, 90, 369, 468,
+ /* 920 */ 467, 385, 989, 839, 1257, 439, 57, 57, 395, 931,
+ /* 930 */ 1065, 158, 970, 971, 972, 772, 369, 471, 1019, 399,
+ /* 940 */ 771, 253, 456, 254, 932, 119, 891, 454, 233, 233,
+ /* 950 */ 4, 970, 1096, 275, 839, 839, 841, 842, 19, 847,
+ /* 960 */ 463, 449, 448, 163, 453, 88, 89, 776, 970, 1127,
+ /* 970 */ 279, 930, 90, 369, 468, 467, 91, 457, 839, 3,
+ /* 980 */ 235, 1064, 466, 1228, 233, 233, 931, 970, 970, 971,
+ /* 990 */ 972, 970, 908, 460, 908, 2, 463, 81, 457, 212,
+ /* 1000 */ 3, 932, 282, 10, 10, 970, 971, 972, 189, 839,
+ /* 1010 */ 839, 841, 842, 19, 460, 284, 369, 354, 907, 286,
+ /* 1020 */ 907, 753, 466, 1079, 970, 971, 972, 454, 970, 971,
+ /* 1030 */ 972, 754, 970, 1063, 989, 372, 792, 369, 1118, 847,
+ /* 1040 */ 291, 452, 466, 10, 10, 88, 89, 142, 454, 168,
+ /* 1050 */ 300, 412, 90, 369, 468, 467, 793, 356, 839, 706,
+ /* 1060 */ 847, 341, 121, 10, 10, 301, 88, 89, 379, 970,
+ /* 1070 */ 971, 972, 989, 90, 369, 468, 467, 244, 205, 839,
+ /* 1080 */ 1306, 245, 1135, 245, 250, 1168, 1114, 253, 456, 839,
+ /* 1090 */ 839, 841, 842, 19, 1125, 237, 122, 451, 1174, 733,
+ /* 1100 */ 324, 324, 323, 222, 321, 466, 1046, 695, 182, 225,
+ /* 1110 */ 839, 839, 841, 842, 19, 103, 103, 103, 103, 96,
+ /* 1120 */ 185, 466, 259, 1039, 1028, 170, 10, 10, 1027, 421,
+ /* 1130 */ 258, 1029, 1300, 708, 792, 466, 408, 734, 8, 347,
+ /* 1140 */ 444, 174, 12, 12, 290, 101, 101, 101, 101, 100,
+ /* 1150 */ 100, 99, 99, 99, 98, 368, 32, 32, 466, 187,
+ /* 1160 */ 466, 1111, 103, 103, 103, 103, 188, 466, 325, 138,
+ /* 1170 */ 186, 708, 303, 305, 307, 358, 970, 270, 393, 43,
+ /* 1180 */ 43, 44, 44, 1157, 333, 178, 418, 294, 45, 45,
+ /* 1190 */ 1232, 318, 101, 101, 101, 101, 100, 100, 99, 99,
+ /* 1200 */ 99, 98, 368, 381, 343, 366, 365, 466, 263, 253,
+ /* 1210 */ 456, 466, 1062, 970, 971, 972, 1231, 997, 309, 466,
+ /* 1220 */ 455, 466, 427, 466, 995, 173, 996, 1303, 46, 46,
+ /* 1230 */ 145, 376, 37, 37, 1006, 1277, 466, 214, 1275, 64,
+ /* 1240 */ 47, 47, 33, 33, 34, 34, 1003, 67, 466, 998,
+ /* 1250 */ 350, 998, 466, 155, 233, 233, 466, 36, 36, 24,
+ /* 1260 */ 140, 77, 1154, 466, 383, 466, 463, 428, 466, 48,
+ /* 1270 */ 48, 466, 147, 49, 49, 466, 150, 50, 50, 466,
+ /* 1280 */ 151, 152, 466, 384, 11, 11, 51, 51, 466, 110,
+ /* 1290 */ 110, 153, 52, 52, 411, 466, 38, 38, 466, 191,
+ /* 1300 */ 53, 53, 466, 54, 54, 466, 400, 466, 330, 39,
+ /* 1310 */ 39, 466, 1164, 466, 25, 466, 56, 56, 466, 131,
+ /* 1320 */ 131, 72, 466, 132, 132, 159, 133, 133, 61, 61,
+ /* 1330 */ 1226, 195, 40, 40, 111, 111, 58, 58, 406, 112,
+ /* 1340 */ 112, 466, 277, 113, 113, 466, 226, 466, 1246, 466,
+ /* 1350 */ 197, 466, 164, 466, 409, 466, 198, 466, 199, 466,
+ /* 1360 */ 335, 281, 109, 109, 466, 1030, 130, 130, 129, 129,
+ /* 1370 */ 117, 117, 116, 116, 114, 114, 115, 115, 60, 60,
+ /* 1380 */ 62, 62, 466, 359, 466, 59, 59, 424, 1082, 1081,
+ /* 1390 */ 1080, 724, 1073, 1054, 336, 293, 1053, 1052, 1315, 431,
+ /* 1400 */ 361, 76, 248, 31, 31, 35, 35, 1072, 249, 440,
+ /* 1410 */ 302, 434, 213, 1122, 6, 311, 1212, 107, 83, 251,
+ /* 1420 */ 78, 1123, 445, 220, 443, 1036, 304, 23, 1121, 469,
+ /* 1430 */ 965, 221, 223, 1104, 314, 224, 344, 317, 315, 316,
+ /* 1440 */ 470, 306, 1025, 1120, 308, 1262, 1020, 134, 120, 246,
+ /* 1450 */ 682, 370, 171, 255, 1263, 135, 184, 1261, 1260, 374,
+ /* 1460 */ 118, 906, 904, 827, 1050, 146, 136, 137, 148, 1049,
+ /* 1470 */ 63, 1047, 756, 190, 269, 920, 154, 156, 68, 69,
+ /* 1480 */ 70, 71, 139, 923, 192, 193, 144, 919, 345, 128,
+ /* 1490 */ 14, 194, 276, 211, 1000, 405, 196, 161, 912, 160,
+ /* 1500 */ 26, 697, 410, 295, 200, 289, 414, 162, 419, 73,
+ /* 1510 */ 15, 16, 141, 74, 28, 247, 846, 845, 735, 874,
+ /* 1520 */ 954, 75, 430, 955, 29, 433, 179, 229, 231, 800,
+ /* 1530 */ 165, 795, 87, 210, 889, 79, 875, 17, 873, 877,
+ /* 1540 */ 929, 18, 928, 216, 215, 878, 20, 30, 462, 844,
+ /* 1550 */ 707, 92, 766, 770, 7, 322, 217, 218, 319, 1308,
+ /* 1560 */ 960, 1016, 1016, 1016, 1016, 1307,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 144, 145, 146, 147, 172, 222, 223, 224, 222, 223,
- /* 10 */ 224, 152, 180, 152, 148, 149, 152, 173, 176, 19,
- /* 20 */ 154, 173, 156, 152, 163, 242, 152, 163, 176, 163,
- /* 30 */ 26, 31, 173, 174, 173, 174, 173, 173, 174, 39,
- /* 40 */ 1, 2, 152, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 197, 169,
- /* 60 */ 170, 197, 188, 197, 222, 223, 224, 208, 209, 208,
- /* 70 */ 209, 19, 208, 152, 222, 223, 224, 22, 26, 24,
+ /* 0 */ 152, 144, 145, 146, 147, 152, 152, 172, 152, 180,
+ /* 10 */ 181, 152, 223, 224, 225, 180, 152, 164, 189, 19,
+ /* 20 */ 223, 224, 225, 168, 169, 170, 163, 173, 174, 173,
+ /* 30 */ 174, 31, 173, 174, 168, 169, 170, 173, 174, 39,
+ /* 40 */ 243, 191, 192, 43, 44, 45, 46, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 195, 196,
+ /* 60 */ 22, 23, 208, 209, 208, 209, 218, 208, 209, 176,
+ /* 70 */ 207, 19, 208, 209, 23, 212, 213, 26, 26, 152,
/* 80 */ 46, 47, 48, 49, 84, 85, 86, 87, 88, 89,
/* 90 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47,
/* 100 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 110 */ 106, 245, 157, 88, 89, 90, 91, 92, 93, 94,
- /* 120 */ 68, 231, 251, 19, 84, 85, 86, 87, 88, 89,
+ /* 110 */ 90, 91, 92, 93, 94, 188, 223, 224, 225, 171,
+ /* 120 */ 68, 83, 152, 19, 84, 85, 86, 87, 88, 89,
/* 130 */ 90, 91, 92, 93, 94, 101, 84, 85, 86, 87,
/* 140 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45,
/* 150 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 160 */ 56, 57, 90, 91, 92, 93, 94, 82, 79, 99,
- /* 170 */ 66, 200, 102, 103, 104, 19, 168, 169, 170, 152,
- /* 180 */ 24, 210, 97, 113, 229, 59, 101, 232, 84, 85,
+ /* 160 */ 56, 57, 99, 94, 194, 102, 103, 104, 109, 110,
+ /* 170 */ 66, 223, 224, 225, 152, 19, 113, 22, 23, 152,
+ /* 180 */ 24, 26, 160, 1, 2, 59, 164, 173, 84, 85,
/* 190 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43,
/* 200 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 210 */ 54, 55, 56, 57, 152, 188, 152, 132, 133, 134,
- /* 220 */ 93, 94, 96, 97, 98, 99, 152, 19, 102, 103,
- /* 230 */ 104, 23, 94, 72, 79, 173, 174, 173, 174, 113,
+ /* 210 */ 54, 55, 56, 57, 244, 88, 89, 90, 91, 92,
+ /* 220 */ 93, 94, 96, 97, 98, 99, 196, 19, 102, 103,
+ /* 230 */ 104, 23, 88, 89, 173, 59, 163, 207, 83, 113,
/* 240 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
/* 250 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 260 */ 52, 53, 54, 55, 56, 57, 152, 171, 152, 108,
- /* 270 */ 109, 110, 208, 209, 119, 120, 152, 180, 181, 19,
- /* 280 */ 119, 120, 152, 23, 152, 152, 189, 173, 174, 173,
- /* 290 */ 174, 59, 84, 85, 86, 87, 88, 89, 90, 91,
+ /* 260 */ 52, 53, 54, 55, 56, 57, 90, 240, 195, 196,
+ /* 270 */ 171, 82, 96, 97, 98, 152, 132, 176, 134, 19,
+ /* 280 */ 207, 200, 72, 23, 93, 94, 97, 152, 173, 79,
+ /* 290 */ 101, 210, 84, 85, 86, 87, 88, 89, 90, 91,
/* 300 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49,
- /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 222, 223,
- /* 320 */ 224, 186, 208, 209, 208, 209, 194, 194, 96, 97,
- /* 330 */ 98, 19, 168, 169, 170, 23, 88, 89, 163, 59,
- /* 340 */ 0, 1, 2, 219, 84, 85, 86, 87, 88, 89,
+ /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 108, 152,
+ /* 320 */ 152, 132, 133, 134, 223, 224, 225, 152, 186, 119,
+ /* 330 */ 120, 19, 197, 234, 31, 23, 26, 152, 239, 59,
+ /* 340 */ 173, 174, 39, 220, 84, 85, 86, 87, 88, 89,
/* 350 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47,
/* 360 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 370 */ 90, 152, 197, 195, 196, 243, 96, 97, 98, 196,
- /* 380 */ 132, 11, 134, 19, 182, 207, 115, 23, 117, 118,
- /* 390 */ 207, 163, 173, 174, 152, 220, 84, 85, 86, 87,
+ /* 370 */ 152, 22, 152, 16, 152, 208, 96, 97, 98, 194,
+ /* 380 */ 22, 23, 11, 19, 26, 79, 72, 23, 0, 1,
+ /* 390 */ 2, 173, 174, 173, 174, 220, 84, 85, 86, 87,
/* 400 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45,
/* 410 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 420 */ 56, 57, 152, 16, 152, 197, 171, 208, 22, 23,
- /* 430 */ 22, 23, 26, 16, 26, 19, 7, 8, 9, 23,
- /* 440 */ 212, 213, 152, 173, 174, 173, 174, 19, 84, 85,
+ /* 420 */ 56, 57, 108, 109, 110, 119, 120, 152, 208, 119,
+ /* 430 */ 120, 137, 75, 139, 77, 19, 152, 88, 89, 23,
+ /* 440 */ 115, 83, 117, 118, 163, 227, 163, 152, 84, 85,
/* 450 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43,
/* 460 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 470 */ 54, 55, 56, 57, 46, 152, 109, 110, 208, 109,
- /* 480 */ 110, 152, 75, 152, 77, 22, 23, 19, 233, 83,
- /* 490 */ 152, 83, 75, 238, 77, 164, 173, 174, 226, 59,
+ /* 470 */ 54, 55, 56, 57, 195, 196, 195, 196, 195, 196,
+ /* 480 */ 109, 110, 195, 196, 22, 23, 207, 19, 207, 152,
+ /* 490 */ 207, 108, 109, 110, 207, 163, 22, 140, 24, 59,
/* 500 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
/* 510 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 520 */ 52, 53, 54, 55, 56, 57, 108, 109, 110, 152,
- /* 530 */ 152, 152, 22, 22, 23, 107, 96, 97, 98, 160,
- /* 540 */ 112, 251, 19, 164, 22, 152, 83, 140, 219, 152,
+ /* 520 */ 52, 53, 54, 55, 56, 57, 152, 195, 196, 152,
+ /* 530 */ 16, 7, 8, 9, 197, 240, 96, 97, 98, 207,
+ /* 540 */ 249, 250, 19, 152, 22, 83, 26, 173, 174, 152,
/* 550 */ 173, 174, 84, 85, 86, 87, 88, 89, 90, 91,
/* 560 */ 92, 93, 94, 59, 124, 152, 43, 44, 45, 46,
/* 570 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 580 */ 57, 59, 169, 170, 119, 120, 82, 108, 109, 110,
- /* 590 */ 191, 192, 191, 192, 83, 248, 249, 19, 88, 89,
+ /* 580 */ 57, 59, 169, 170, 157, 194, 82, 191, 192, 75,
+ /* 590 */ 152, 77, 108, 109, 110, 26, 152, 19, 152, 152,
/* 600 */ 96, 97, 24, 152, 152, 101, 138, 84, 85, 86,
/* 610 */ 87, 88, 89, 90, 91, 92, 93, 94, 96, 97,
/* 620 */ 98, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 630 */ 52, 53, 54, 55, 56, 57, 132, 133, 134, 152,
- /* 640 */ 152, 46, 152, 26, 231, 194, 194, 146, 147, 19,
- /* 650 */ 152, 116, 152, 72, 152, 152, 121, 152, 152, 152,
- /* 660 */ 79, 138, 84, 85, 86, 87, 88, 89, 90, 91,
+ /* 630 */ 52, 53, 54, 55, 56, 57, 132, 133, 134, 188,
+ /* 640 */ 194, 197, 152, 123, 197, 232, 194, 152, 182, 19,
+ /* 650 */ 119, 120, 152, 152, 152, 152, 218, 230, 152, 163,
+ /* 660 */ 233, 138, 84, 85, 86, 87, 88, 89, 90, 91,
/* 670 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49,
- /* 680 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 108,
- /* 690 */ 23, 152, 194, 26, 194, 152, 194, 194, 137, 152,
- /* 700 */ 139, 19, 107, 166, 167, 218, 218, 29, 218, 173,
- /* 710 */ 174, 33, 173, 174, 84, 85, 86, 87, 88, 89,
+ /* 680 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 152,
+ /* 690 */ 23, 195, 196, 26, 194, 194, 194, 146, 147, 130,
+ /* 700 */ 194, 19, 46, 207, 59, 29, 166, 167, 218, 33,
+ /* 710 */ 173, 174, 26, 218, 84, 85, 86, 87, 88, 89,
/* 720 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47,
/* 730 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 740 */ 152, 194, 64, 171, 239, 239, 239, 130, 166, 167,
- /* 750 */ 212, 213, 19, 23, 246, 247, 26, 59, 26, 152,
- /* 760 */ 163, 218, 163, 163, 163, 98, 84, 85, 86, 87,
+ /* 740 */ 64, 171, 97, 240, 116, 166, 167, 212, 213, 121,
+ /* 750 */ 23, 152, 19, 26, 218, 247, 248, 23, 23, 152,
+ /* 760 */ 26, 26, 22, 107, 163, 98, 84, 85, 86, 87,
/* 770 */ 88, 89, 90, 91, 92, 93, 94, 44, 45, 46,
/* 780 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 790 */ 57, 124, 26, 79, 197, 97, 197, 197, 197, 31,
- /* 800 */ 152, 23, 19, 19, 26, 19, 218, 39, 23, 21,
- /* 810 */ 238, 26, 163, 163, 100, 59, 163, 84, 85, 86,
+ /* 790 */ 57, 124, 106, 53, 100, 101, 195, 196, 152, 152,
+ /* 800 */ 23, 23, 19, 26, 26, 19, 152, 23, 207, 239,
+ /* 810 */ 26, 23, 152, 163, 26, 169, 170, 84, 85, 86,
/* 820 */ 87, 88, 89, 90, 91, 92, 93, 94, 45, 46,
/* 830 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 840 */ 57, 19, 20, 152, 22, 23, 197, 197, 23, 19,
- /* 850 */ 197, 26, 152, 97, 23, 123, 23, 26, 36, 26,
- /* 860 */ 152, 152, 19, 20, 98, 22, 78, 84, 85, 86,
- /* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 94, 36,
- /* 880 */ 152, 59, 96, 99, 100, 101, 102, 103, 104, 105,
- /* 890 */ 124, 103, 70, 100, 101, 23, 112, 12, 26, 12,
- /* 900 */ 23, 79, 59, 26, 82, 101, 22, 7, 8, 152,
- /* 910 */ 88, 89, 27, 70, 27, 152, 112, 95, 96, 97,
- /* 920 */ 98, 152, 79, 101, 22, 82, 96, 42, 140, 42,
- /* 930 */ 182, 88, 89, 19, 20, 132, 22, 134, 95, 96,
- /* 940 */ 97, 98, 23, 59, 101, 26, 22, 62, 152, 62,
- /* 950 */ 36, 22, 59, 24, 132, 133, 134, 135, 136, 72,
- /* 960 */ 5, 59, 152, 22, 71, 10, 11, 12, 13, 14,
- /* 970 */ 152, 152, 17, 59, 182, 132, 133, 134, 135, 136,
- /* 980 */ 96, 97, 98, 59, 70, 30, 152, 32, 59, 96,
- /* 990 */ 97, 98, 173, 174, 53, 40, 82, 152, 96, 97,
- /* 1000 */ 98, 90, 88, 89, 90, 24, 187, 173, 174, 95,
- /* 1010 */ 96, 97, 98, 152, 152, 101, 19, 20, 152, 22,
- /* 1020 */ 96, 97, 98, 152, 69, 59, 97, 116, 59, 214,
- /* 1030 */ 152, 76, 121, 36, 79, 80, 19, 20, 152, 22,
- /* 1040 */ 59, 132, 59, 134, 173, 174, 132, 133, 134, 135,
- /* 1050 */ 136, 173, 174, 36, 234, 152, 59, 152, 187, 173,
- /* 1060 */ 174, 211, 96, 97, 98, 187, 97, 70, 23, 114,
- /* 1070 */ 152, 26, 23, 187, 23, 26, 59, 26, 97, 82,
- /* 1080 */ 97, 22, 164, 152, 152, 88, 89, 70, 192, 152,
- /* 1090 */ 124, 152, 95, 96, 97, 98, 141, 152, 101, 82,
- /* 1100 */ 152, 152, 184, 152, 186, 88, 89, 199, 54, 55,
- /* 1110 */ 56, 57, 95, 96, 97, 98, 152, 152, 101, 152,
- /* 1120 */ 152, 173, 174, 235, 54, 55, 56, 57, 58, 132,
- /* 1130 */ 133, 134, 135, 136, 211, 150, 59, 211, 84, 85,
- /* 1140 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 132,
- /* 1150 */ 133, 134, 135, 136, 84, 85, 86, 87, 88, 89,
- /* 1160 */ 90, 91, 92, 93, 94, 88, 89, 195, 196, 35,
- /* 1170 */ 211, 211, 152, 96, 97, 98, 152, 100, 198, 207,
- /* 1180 */ 171, 122, 240, 152, 107, 215, 109, 240, 202, 215,
- /* 1190 */ 202, 152, 220, 173, 174, 177, 185, 173, 174, 65,
- /* 1200 */ 152, 176, 152, 181, 173, 174, 215, 73, 176, 132,
- /* 1210 */ 228, 134, 173, 174, 176, 152, 201, 152, 199, 155,
- /* 1220 */ 152, 173, 174, 173, 174, 60, 152, 122, 244, 38,
- /* 1230 */ 159, 159, 152, 241, 241, 152, 173, 174, 173, 174,
- /* 1240 */ 152, 173, 174, 152, 159, 111, 152, 173, 174, 152,
- /* 1250 */ 22, 152, 43, 173, 174, 152, 173, 174, 152, 190,
- /* 1260 */ 130, 173, 174, 152, 173, 174, 152, 173, 174, 202,
- /* 1270 */ 173, 174, 173, 174, 152, 18, 173, 174, 152, 173,
- /* 1280 */ 174, 152, 221, 152, 173, 174, 193, 173, 174, 152,
- /* 1290 */ 158, 152, 159, 152, 22, 173, 174, 152, 18, 173,
- /* 1300 */ 174, 152, 173, 174, 173, 174, 152, 221, 152, 193,
- /* 1310 */ 173, 174, 173, 174, 173, 174, 152, 193, 173, 174,
- /* 1320 */ 152, 193, 173, 174, 158, 152, 190, 173, 174, 173,
- /* 1330 */ 174, 59, 152, 190, 159, 137, 152, 173, 174, 152,
- /* 1340 */ 202, 173, 174, 61, 152, 237, 173, 174, 202, 236,
- /* 1350 */ 22, 107, 159, 173, 174, 159, 178, 173, 174, 158,
- /* 1360 */ 173, 174, 159, 158, 158, 173, 174, 159, 178, 97,
- /* 1370 */ 175, 63, 175, 106, 175, 125, 217, 183, 178, 175,
- /* 1380 */ 107, 159, 22, 216, 177, 175, 217, 175, 175, 217,
- /* 1390 */ 216, 159, 216, 216, 183, 225, 217, 137, 227, 178,
- /* 1400 */ 94, 178, 126, 129, 25, 128, 127, 162, 206, 26,
- /* 1410 */ 161, 230, 230, 13, 153, 153, 6, 151, 203, 205,
- /* 1420 */ 204, 202, 151, 165, 171, 171, 151, 171, 165, 165,
- /* 1430 */ 171, 179, 4, 250, 179, 250, 247, 3, 22, 171,
- /* 1440 */ 171, 171, 142, 81, 15, 23, 16, 23, 131, 171,
- /* 1450 */ 120, 111, 123, 20, 16, 1, 125, 123, 131, 53,
- /* 1460 */ 53, 53, 53, 111, 96, 34, 122, 1, 5, 22,
- /* 1470 */ 107, 67, 140, 74, 26, 24, 41, 107, 67, 20,
- /* 1480 */ 19, 112, 105, 66, 22, 66, 22, 22, 28, 66,
- /* 1490 */ 23, 22, 22, 37, 23, 23, 23, 116, 22, 22,
- /* 1500 */ 26, 23, 122, 23, 23, 26, 22, 11, 96, 34,
- /* 1510 */ 124, 26, 26, 23, 23, 23, 34, 34, 23, 26,
- /* 1520 */ 23, 22, 24, 23, 22, 122, 23, 26, 22, 24,
- /* 1530 */ 23, 22, 15, 23, 23, 22, 122, 122, 23, 1,
- /* 1540 */ 122, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- /* 1550 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- /* 1560 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ /* 840 */ 57, 19, 20, 101, 22, 195, 196, 22, 19, 24,
+ /* 850 */ 163, 19, 7, 8, 112, 59, 23, 207, 36, 26,
+ /* 860 */ 23, 152, 59, 26, 21, 59, 152, 84, 85, 86,
+ /* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 232, 221,
+ /* 880 */ 94, 59, 195, 196, 59, 99, 100, 101, 102, 103,
+ /* 890 */ 104, 105, 70, 97, 207, 59, 19, 20, 112, 22,
+ /* 900 */ 97, 79, 152, 97, 82, 152, 152, 71, 221, 90,
+ /* 910 */ 88, 89, 23, 36, 12, 26, 163, 95, 96, 97,
+ /* 920 */ 98, 78, 97, 101, 152, 96, 173, 174, 96, 27,
+ /* 930 */ 182, 22, 96, 97, 98, 116, 59, 148, 149, 152,
+ /* 940 */ 121, 119, 120, 154, 42, 156, 103, 70, 195, 196,
+ /* 950 */ 22, 59, 163, 152, 132, 133, 134, 135, 136, 82,
+ /* 960 */ 207, 208, 209, 71, 62, 88, 89, 90, 59, 152,
+ /* 970 */ 152, 12, 95, 96, 97, 98, 19, 20, 101, 22,
+ /* 980 */ 22, 182, 152, 140, 195, 196, 27, 59, 96, 97,
+ /* 990 */ 98, 59, 132, 36, 134, 22, 207, 19, 20, 24,
+ /* 1000 */ 22, 42, 152, 173, 174, 96, 97, 98, 219, 132,
+ /* 1010 */ 133, 134, 135, 136, 36, 152, 59, 187, 132, 152,
+ /* 1020 */ 134, 62, 152, 152, 96, 97, 98, 70, 96, 97,
+ /* 1030 */ 98, 72, 59, 152, 59, 246, 26, 59, 214, 82,
+ /* 1040 */ 152, 192, 152, 173, 174, 88, 89, 79, 70, 152,
+ /* 1050 */ 152, 19, 95, 96, 97, 98, 124, 187, 101, 23,
+ /* 1060 */ 82, 164, 26, 173, 174, 152, 88, 89, 100, 96,
+ /* 1070 */ 97, 98, 97, 95, 96, 97, 98, 187, 46, 101,
+ /* 1080 */ 122, 184, 152, 186, 211, 152, 152, 119, 120, 132,
+ /* 1090 */ 133, 134, 135, 136, 152, 5, 22, 152, 152, 35,
+ /* 1100 */ 10, 11, 12, 13, 14, 152, 152, 17, 98, 235,
+ /* 1110 */ 132, 133, 134, 135, 136, 54, 55, 56, 57, 58,
+ /* 1120 */ 30, 152, 32, 152, 152, 198, 173, 174, 152, 65,
+ /* 1130 */ 40, 152, 152, 59, 124, 152, 236, 73, 199, 107,
+ /* 1140 */ 187, 171, 173, 174, 112, 84, 85, 86, 87, 88,
+ /* 1150 */ 89, 90, 91, 92, 93, 94, 173, 174, 152, 69,
+ /* 1160 */ 152, 211, 54, 55, 56, 57, 76, 152, 150, 79,
+ /* 1170 */ 80, 97, 211, 211, 211, 111, 59, 241, 241, 173,
+ /* 1180 */ 174, 173, 174, 202, 202, 185, 177, 176, 173, 174,
+ /* 1190 */ 176, 201, 84, 85, 86, 87, 88, 89, 90, 91,
+ /* 1200 */ 92, 93, 94, 215, 114, 88, 89, 152, 215, 119,
+ /* 1210 */ 120, 152, 181, 96, 97, 98, 176, 100, 215, 152,
+ /* 1220 */ 229, 152, 163, 152, 107, 199, 109, 155, 173, 174,
+ /* 1230 */ 245, 141, 173, 174, 60, 159, 152, 122, 159, 242,
+ /* 1240 */ 173, 174, 173, 174, 173, 174, 38, 242, 152, 132,
+ /* 1250 */ 159, 134, 152, 22, 195, 196, 152, 173, 174, 222,
+ /* 1260 */ 43, 130, 202, 152, 18, 152, 207, 208, 152, 173,
+ /* 1270 */ 174, 152, 190, 173, 174, 152, 193, 173, 174, 152,
+ /* 1280 */ 193, 193, 152, 159, 173, 174, 173, 174, 152, 173,
+ /* 1290 */ 174, 193, 173, 174, 18, 152, 173, 174, 152, 158,
+ /* 1300 */ 173, 174, 152, 173, 174, 152, 159, 152, 202, 173,
+ /* 1310 */ 174, 152, 190, 152, 222, 152, 173, 174, 152, 173,
+ /* 1320 */ 174, 137, 152, 173, 174, 190, 173, 174, 173, 174,
+ /* 1330 */ 202, 158, 173, 174, 173, 174, 173, 174, 61, 173,
+ /* 1340 */ 174, 152, 237, 173, 174, 152, 159, 152, 238, 152,
+ /* 1350 */ 158, 152, 22, 152, 178, 152, 158, 152, 158, 152,
+ /* 1360 */ 178, 159, 173, 174, 152, 159, 173, 174, 173, 174,
+ /* 1370 */ 173, 174, 173, 174, 173, 174, 173, 174, 173, 174,
+ /* 1380 */ 173, 174, 152, 63, 152, 173, 174, 107, 175, 175,
+ /* 1390 */ 175, 106, 183, 175, 178, 175, 177, 175, 175, 178,
+ /* 1400 */ 94, 107, 231, 173, 174, 173, 174, 183, 231, 125,
+ /* 1410 */ 216, 178, 159, 217, 22, 159, 226, 129, 137, 228,
+ /* 1420 */ 128, 217, 126, 25, 127, 162, 216, 26, 217, 161,
+ /* 1430 */ 13, 153, 153, 206, 205, 6, 251, 202, 204, 203,
+ /* 1440 */ 151, 216, 151, 217, 216, 171, 151, 165, 179, 179,
+ /* 1450 */ 4, 3, 22, 142, 171, 165, 15, 171, 171, 81,
+ /* 1460 */ 16, 23, 23, 120, 171, 131, 165, 111, 123, 171,
+ /* 1470 */ 171, 171, 20, 125, 16, 1, 123, 131, 53, 53,
+ /* 1480 */ 53, 53, 111, 96, 34, 122, 248, 1, 251, 5,
+ /* 1490 */ 22, 107, 140, 26, 74, 41, 122, 107, 67, 67,
+ /* 1500 */ 24, 20, 19, 112, 105, 23, 66, 22, 66, 22,
+ /* 1510 */ 22, 22, 37, 22, 22, 66, 23, 23, 28, 23,
+ /* 1520 */ 23, 26, 24, 23, 22, 24, 122, 23, 23, 96,
+ /* 1530 */ 22, 124, 26, 34, 23, 26, 23, 34, 23, 23,
+ /* 1540 */ 23, 34, 23, 22, 26, 11, 22, 22, 26, 23,
+ /* 1550 */ 23, 22, 116, 23, 22, 15, 122, 122, 23, 122,
+ /* 1560 */ 1, 252, 252, 252, 252, 122, 252, 252, 252, 252,
/* 1570 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
/* 1580 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
/* 1590 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
@@ -138767,147 +140438,152 @@ static const YYCODETYPE yy_lookahead[] = {
/* 1650 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
/* 1660 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
/* 1670 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- /* 1680 */ 252, 252, 252, 252,
+ /* 1680 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ /* 1690 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ /* 1700 */ 252, 252, 252, 252, 252, 252, 252, 252, 252,
};
-#define YY_SHIFT_COUNT (465)
+#define YY_SHIFT_COUNT (471)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1538)
+#define YY_SHIFT_MAX (1559)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 39, 822, 955, 843, 997, 997, 997, 997, 0, 0,
- /* 10 */ 104, 630, 997, 997, 997, 997, 997, 997, 997, 1077,
- /* 20 */ 1077, 126, 161, 155, 52, 156, 208, 260, 312, 364,
- /* 30 */ 416, 468, 523, 578, 630, 630, 630, 630, 630, 630,
- /* 40 */ 630, 630, 630, 630, 630, 630, 630, 630, 630, 630,
- /* 50 */ 630, 682, 630, 733, 783, 783, 914, 997, 997, 997,
- /* 60 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997,
- /* 70 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997,
- /* 80 */ 997, 997, 997, 997, 997, 997, 997, 997, 1017, 997,
- /* 90 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997,
- /* 100 */ 997, 997, 1070, 1054, 1054, 1054, 1054, 1054, 40, 25,
- /* 110 */ 72, 232, 788, 428, 248, 248, 232, 581, 367, 127,
- /* 120 */ 465, 138, 1541, 1541, 1541, 784, 784, 784, 522, 522,
- /* 130 */ 887, 887, 893, 406, 408, 232, 232, 232, 232, 232,
- /* 140 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
- /* 150 */ 232, 232, 232, 232, 232, 370, 340, 714, 698, 698,
- /* 160 */ 465, 89, 89, 89, 89, 89, 89, 1541, 1541, 1541,
- /* 170 */ 504, 85, 85, 884, 70, 280, 902, 440, 966, 924,
- /* 180 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
- /* 190 */ 232, 232, 232, 232, 232, 232, 1134, 1134, 1134, 232,
- /* 200 */ 232, 667, 232, 232, 232, 929, 232, 232, 885, 232,
- /* 210 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 418,
- /* 220 */ 678, 981, 981, 981, 981, 766, 271, 911, 510, 429,
- /* 230 */ 617, 786, 786, 830, 617, 830, 4, 730, 595, 768,
- /* 240 */ 786, 561, 768, 768, 732, 535, 55, 1165, 1105, 1105,
- /* 250 */ 1191, 1191, 1105, 1228, 1209, 1130, 1257, 1257, 1257, 1257,
- /* 260 */ 1105, 1280, 1130, 1228, 1209, 1209, 1130, 1105, 1280, 1198,
- /* 270 */ 1282, 1105, 1105, 1280, 1328, 1105, 1280, 1105, 1280, 1328,
- /* 280 */ 1244, 1244, 1244, 1308, 1328, 1244, 1267, 1244, 1308, 1244,
- /* 290 */ 1244, 1250, 1273, 1250, 1273, 1250, 1273, 1250, 1273, 1105,
- /* 300 */ 1360, 1105, 1260, 1328, 1306, 1306, 1328, 1274, 1276, 1277,
- /* 310 */ 1279, 1130, 1379, 1383, 1400, 1400, 1410, 1410, 1410, 1541,
- /* 320 */ 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541,
- /* 330 */ 1541, 1541, 1541, 1541, 1541, 34, 407, 463, 511, 417,
- /* 340 */ 479, 1272, 778, 941, 785, 825, 831, 833, 872, 877,
- /* 350 */ 756, 793, 900, 804, 919, 1045, 969, 1049, 803, 909,
- /* 360 */ 1051, 983, 1059, 1428, 1434, 1416, 1300, 1429, 1362, 1430,
- /* 370 */ 1422, 1424, 1330, 1317, 1340, 1329, 1433, 1331, 1438, 1454,
- /* 380 */ 1334, 1327, 1406, 1407, 1408, 1409, 1352, 1368, 1431, 1344,
- /* 390 */ 1466, 1463, 1447, 1363, 1332, 1404, 1448, 1411, 1399, 1435,
- /* 400 */ 1370, 1451, 1459, 1461, 1369, 1377, 1462, 1417, 1464, 1465,
- /* 410 */ 1467, 1469, 1419, 1460, 1470, 1423, 1456, 1471, 1472, 1473,
- /* 420 */ 1474, 1381, 1476, 1478, 1477, 1479, 1380, 1480, 1481, 1412,
- /* 430 */ 1475, 1484, 1386, 1485, 1482, 1486, 1483, 1490, 1485, 1491,
- /* 440 */ 1492, 1495, 1493, 1497, 1499, 1496, 1500, 1502, 1498, 1501,
- /* 450 */ 1503, 1506, 1505, 1501, 1507, 1509, 1510, 1511, 1513, 1403,
- /* 460 */ 1414, 1415, 1418, 1515, 1517, 1538,
+ /* 0 */ 182, 1090, 822, 822, 306, 957, 957, 957, 957, 210,
+ /* 10 */ 0, 0, 104, 630, 957, 957, 957, 957, 957, 957,
+ /* 20 */ 957, 1117, 1117, 126, 968, 306, 306, 306, 306, 306,
+ /* 30 */ 306, 52, 156, 208, 260, 312, 364, 416, 468, 523,
+ /* 40 */ 578, 630, 630, 630, 630, 630, 630, 630, 630, 630,
+ /* 50 */ 630, 630, 630, 630, 630, 630, 630, 630, 682, 630,
+ /* 60 */ 733, 783, 783, 877, 957, 957, 957, 957, 957, 957,
+ /* 70 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957,
+ /* 80 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957,
+ /* 90 */ 957, 957, 957, 957, 957, 978, 957, 957, 957, 957,
+ /* 100 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 1061,
+ /* 110 */ 1108, 1108, 1108, 1108, 1108, 40, 127, 20, 280, 843,
+ /* 120 */ 1032, 144, 144, 280, 310, 310, 310, 310, 59, 191,
+ /* 130 */ 69, 1566, 1566, 1566, 786, 786, 786, 522, 836, 522,
+ /* 140 */ 959, 959, 892, 155, 358, 280, 280, 280, 280, 280,
+ /* 150 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ /* 160 */ 280, 280, 280, 280, 280, 280, 371, 388, 645, 645,
+ /* 170 */ 531, 1566, 1566, 1566, 504, 189, 189, 909, 63, 176,
+ /* 180 */ 928, 440, 932, 973, 280, 280, 280, 280, 280, 314,
+ /* 190 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ /* 200 */ 280, 280, 1064, 1064, 1064, 280, 280, 280, 280, 667,
+ /* 210 */ 280, 280, 280, 825, 280, 280, 902, 280, 280, 280,
+ /* 220 */ 280, 280, 280, 280, 280, 383, 676, 325, 975, 975,
+ /* 230 */ 975, 975, 1010, 325, 325, 819, 349, 524, 569, 829,
+ /* 240 */ 829, 832, 569, 832, 686, 51, 656, 303, 303, 303,
+ /* 250 */ 829, 294, 520, 628, 474, 1174, 1115, 1115, 1208, 1208,
+ /* 260 */ 1115, 1231, 1217, 1131, 1246, 1246, 1246, 1246, 1115, 1276,
+ /* 270 */ 1131, 1231, 1217, 1217, 1131, 1115, 1276, 1184, 1277, 1115,
+ /* 280 */ 1276, 1330, 1115, 1276, 1115, 1276, 1330, 1280, 1280, 1280,
+ /* 290 */ 1320, 1330, 1280, 1285, 1280, 1320, 1280, 1280, 1330, 1306,
+ /* 300 */ 1306, 1330, 1284, 1294, 1284, 1294, 1284, 1294, 1284, 1294,
+ /* 310 */ 1115, 1392, 1115, 1281, 1288, 1296, 1292, 1297, 1131, 1398,
+ /* 320 */ 1401, 1417, 1417, 1429, 1429, 1429, 1566, 1566, 1566, 1566,
+ /* 330 */ 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566,
+ /* 340 */ 1566, 1566, 34, 357, 38, 462, 514, 484, 1074, 727,
+ /* 350 */ 740, 734, 735, 777, 778, 784, 788, 803, 694, 845,
+ /* 360 */ 742, 796, 833, 837, 889, 860, 886, 1036, 806, 958,
+ /* 370 */ 1446, 1448, 1430, 1311, 1441, 1378, 1444, 1438, 1439, 1343,
+ /* 380 */ 1334, 1356, 1345, 1452, 1348, 1458, 1474, 1353, 1346, 1425,
+ /* 390 */ 1426, 1427, 1428, 1371, 1387, 1450, 1363, 1486, 1484, 1468,
+ /* 400 */ 1384, 1352, 1431, 1467, 1432, 1420, 1454, 1374, 1390, 1476,
+ /* 410 */ 1481, 1483, 1391, 1399, 1485, 1440, 1487, 1488, 1482, 1489,
+ /* 420 */ 1442, 1490, 1491, 1449, 1475, 1493, 1494, 1496, 1495, 1497,
+ /* 430 */ 1492, 1498, 1500, 1502, 1501, 1404, 1504, 1505, 1433, 1499,
+ /* 440 */ 1508, 1407, 1506, 1503, 1509, 1507, 1511, 1513, 1515, 1506,
+ /* 450 */ 1516, 1517, 1518, 1519, 1521, 1534, 1524, 1525, 1526, 1527,
+ /* 460 */ 1529, 1530, 1532, 1522, 1436, 1434, 1435, 1437, 1443, 1535,
+ /* 470 */ 1540, 1559,
};
-#define YY_REDUCE_COUNT (334)
-#define YY_REDUCE_MIN (-217)
-#define YY_REDUCE_MAX (1278)
+#define YY_REDUCE_COUNT (341)
+#define YY_REDUCE_MIN (-211)
+#define YY_REDUCE_MAX (1301)
static const short yy_reduce_ofst[] = {
- /* 0 */ -144, -139, -134, -136, -141, 64, 114, 116, -158, -148,
- /* 10 */ -217, 96, 819, 871, 878, 219, 270, 886, 272, -110,
- /* 20 */ 413, 918, 972, 228, -214, -214, -214, -214, -214, -214,
- /* 30 */ -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
- /* 40 */ -214, -214, -214, -214, -214, -214, -214, -214, -214, -214,
- /* 50 */ -214, -214, -214, -214, -214, -214, 62, 323, 377, 536,
- /* 60 */ 539, 834, 948, 1020, 1024, 1031, 1039, 1048, 1050, 1063,
- /* 70 */ 1065, 1068, 1074, 1080, 1083, 1088, 1091, 1094, 1097, 1099,
- /* 80 */ 1103, 1106, 1111, 1114, 1122, 1126, 1129, 1131, 1137, 1139,
- /* 90 */ 1141, 1145, 1149, 1154, 1156, 1164, 1168, 1173, 1180, 1184,
- /* 100 */ 1187, 1192, -214, -214, -214, -214, -214, -214, -214, -214,
- /* 110 */ -214, 132, -45, 97, 8, 164, 379, 175, 255, -214,
- /* 120 */ 178, -214, -214, -214, -214, -168, -168, -168, 124, 329,
- /* 130 */ 399, 401, -129, 347, 347, 331, 133, 451, 452, 498,
- /* 140 */ 500, 502, 503, 505, 487, 506, 488, 490, 507, 543,
- /* 150 */ 547, -126, 588, 290, 27, 572, 501, 597, 537, 582,
- /* 160 */ 183, 599, 600, 601, 649, 650, 653, 508, 538, -29,
- /* 170 */ -156, -152, -137, -79, 135, 74, 130, 242, 338, 378,
- /* 180 */ 393, 397, 607, 648, 691, 700, 708, 709, 728, 757,
- /* 190 */ 763, 769, 796, 810, 818, 845, 202, 748, 792, 861,
- /* 200 */ 862, 815, 866, 903, 905, 850, 931, 932, 896, 937,
- /* 210 */ 939, 945, 74, 949, 951, 964, 965, 967, 968, 888,
- /* 220 */ 820, 923, 926, 959, 960, 815, 980, 908, 1009, 985,
- /* 230 */ 986, 970, 974, 942, 988, 947, 1018, 1011, 1022, 1025,
- /* 240 */ 991, 982, 1032, 1038, 1015, 1019, 1064, 984, 1071, 1072,
- /* 250 */ 992, 993, 1085, 1061, 1069, 1067, 1093, 1116, 1124, 1128,
- /* 260 */ 1133, 1132, 1138, 1086, 1136, 1143, 1146, 1175, 1166, 1108,
- /* 270 */ 1113, 1193, 1196, 1201, 1178, 1203, 1205, 1208, 1206, 1190,
- /* 280 */ 1195, 1197, 1199, 1194, 1200, 1204, 1207, 1210, 1211, 1212,
- /* 290 */ 1213, 1159, 1167, 1169, 1174, 1172, 1176, 1179, 1177, 1222,
- /* 300 */ 1170, 1232, 1171, 1221, 1181, 1182, 1223, 1202, 1214, 1216,
- /* 310 */ 1215, 1219, 1245, 1249, 1261, 1262, 1266, 1271, 1275, 1183,
- /* 320 */ 1185, 1189, 1258, 1253, 1254, 1256, 1259, 1263, 1252, 1255,
- /* 330 */ 1268, 1269, 1270, 1278, 1264,
+ /* 0 */ -143, 789, 753, 1059, -137, -146, -144, -141, -136, 687,
+ /* 10 */ -107, 101, -203, -52, 830, 870, 890, 167, 953, 218,
+ /* 20 */ 220, 413, 646, 897, 73, 281, 283, 332, 496, 601,
+ /* 30 */ 650, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+ /* 40 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+ /* 50 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211,
+ /* 60 */ -211, -211, -211, 374, 377, 537, 969, 983, 1006, 1008,
+ /* 70 */ 1015, 1055, 1067, 1069, 1071, 1084, 1096, 1100, 1104, 1111,
+ /* 80 */ 1113, 1116, 1119, 1123, 1127, 1130, 1136, 1143, 1146, 1150,
+ /* 90 */ 1153, 1155, 1159, 1161, 1163, 1166, 1170, 1189, 1193, 1195,
+ /* 100 */ 1197, 1199, 1201, 1203, 1205, 1207, 1212, 1230, 1232, -211,
+ /* 110 */ -211, -211, -211, -211, -211, -211, -211, -211, -30, 427,
+ /* 120 */ -171, -145, -134, 22, 279, 287, 279, 287, 99, -211,
+ /* 130 */ -211, -211, -211, -211, -165, -165, -165, 123, 135, 175,
+ /* 140 */ -150, 396, 337, 291, 291, -147, 185, 391, 446, 444,
+ /* 150 */ 452, 500, 501, 502, 27, -152, 295, 438, 490, 503,
+ /* 160 */ 495, 506, -73, 447, 451, 536, 570, 551, 540, 579,
+ /* 170 */ 30, 508, 535, 81, 14, 61, 115, 168, 142, 222,
+ /* 180 */ 275, 284, 397, 599, 607, 647, 654, 660, 709, 658,
+ /* 190 */ 714, 750, 754, 772, 787, 801, 817, 818, 850, 863,
+ /* 200 */ 867, 871, 466, 748, 799, 881, 888, 898, 913, 824,
+ /* 210 */ 930, 933, 934, 873, 942, 945, 849, 946, 222, 954,
+ /* 220 */ 971, 972, 976, 979, 980, 900, 874, 927, 950, 961,
+ /* 230 */ 962, 963, 824, 927, 927, 939, 970, 1018, 981, 988,
+ /* 240 */ 993, 936, 982, 937, 1009, 1000, 1031, 1011, 1014, 1040,
+ /* 250 */ 1003, 991, 990, 1026, 1072, 985, 1076, 1079, 997, 1005,
+ /* 260 */ 1091, 1037, 1082, 1060, 1083, 1087, 1088, 1098, 1124, 1141,
+ /* 270 */ 1106, 1092, 1122, 1135, 1128, 1147, 1173, 1110, 1105, 1187,
+ /* 280 */ 1192, 1176, 1202, 1198, 1206, 1200, 1182, 1213, 1214, 1215,
+ /* 290 */ 1209, 1216, 1218, 1219, 1220, 1224, 1222, 1223, 1221, 1171,
+ /* 300 */ 1177, 1233, 1196, 1194, 1204, 1210, 1211, 1225, 1226, 1228,
+ /* 310 */ 1253, 1190, 1256, 1191, 1227, 1229, 1234, 1236, 1235, 1263,
+ /* 320 */ 1268, 1278, 1279, 1289, 1291, 1295, 1185, 1237, 1238, 1282,
+ /* 330 */ 1274, 1283, 1286, 1287, 1290, 1269, 1270, 1293, 1298, 1299,
+ /* 340 */ 1300, 1301,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1286, 1276, 1276, 1276, 1209, 1209, 1209, 1209, 1133, 1133,
- /* 10 */ 1260, 1036, 1005, 1005, 1005, 1005, 1005, 1005, 1208, 1005,
- /* 20 */ 1005, 1005, 1005, 1108, 1139, 1005, 1005, 1005, 1005, 1210,
- /* 30 */ 1211, 1005, 1005, 1005, 1259, 1261, 1149, 1148, 1147, 1146,
- /* 40 */ 1242, 1120, 1144, 1137, 1141, 1210, 1204, 1205, 1203, 1207,
- /* 50 */ 1211, 1005, 1140, 1174, 1188, 1173, 1005, 1005, 1005, 1005,
- /* 60 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 70 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 80 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 90 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 100 */ 1005, 1005, 1182, 1187, 1194, 1186, 1183, 1176, 1175, 1177,
- /* 110 */ 1178, 1005, 1026, 1075, 1005, 1005, 1005, 1276, 1036, 1179,
- /* 120 */ 1005, 1180, 1191, 1190, 1189, 1267, 1294, 1293, 1005, 1005,
- /* 130 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 140 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 150 */ 1005, 1005, 1005, 1005, 1005, 1036, 1286, 1276, 1032, 1032,
- /* 160 */ 1005, 1276, 1276, 1276, 1276, 1276, 1276, 1272, 1108, 1099,
- /* 170 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 180 */ 1005, 1264, 1262, 1005, 1224, 1005, 1005, 1005, 1005, 1005,
- /* 190 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 200 */ 1005, 1005, 1005, 1005, 1005, 1104, 1005, 1005, 1005, 1005,
- /* 210 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1288, 1005,
- /* 220 */ 1237, 1104, 1104, 1104, 1104, 1106, 1088, 1098, 1036, 1012,
- /* 230 */ 1143, 1122, 1122, 1327, 1143, 1327, 1050, 1308, 1047, 1133,
- /* 240 */ 1122, 1206, 1133, 1133, 1105, 1098, 1005, 1330, 1113, 1113,
- /* 250 */ 1329, 1329, 1113, 1154, 1078, 1143, 1084, 1084, 1084, 1084,
- /* 260 */ 1113, 1023, 1143, 1154, 1078, 1078, 1143, 1113, 1023, 1241,
- /* 270 */ 1324, 1113, 1113, 1023, 1217, 1113, 1023, 1113, 1023, 1217,
- /* 280 */ 1076, 1076, 1076, 1065, 1217, 1076, 1050, 1076, 1065, 1076,
- /* 290 */ 1076, 1126, 1121, 1126, 1121, 1126, 1121, 1126, 1121, 1113,
- /* 300 */ 1212, 1113, 1005, 1217, 1221, 1221, 1217, 1138, 1127, 1136,
- /* 310 */ 1134, 1143, 1029, 1068, 1291, 1291, 1287, 1287, 1287, 1335,
- /* 320 */ 1335, 1272, 1303, 1036, 1036, 1036, 1036, 1303, 1052, 1052,
- /* 330 */ 1036, 1036, 1036, 1036, 1303, 1005, 1005, 1005, 1005, 1005,
- /* 340 */ 1005, 1298, 1005, 1226, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 350 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 360 */ 1005, 1005, 1159, 1005, 1008, 1269, 1005, 1005, 1268, 1005,
- /* 370 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 380 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1326,
- /* 390 */ 1005, 1005, 1005, 1005, 1005, 1005, 1240, 1239, 1005, 1005,
- /* 400 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 410 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005,
- /* 420 */ 1005, 1090, 1005, 1005, 1005, 1312, 1005, 1005, 1005, 1005,
- /* 430 */ 1005, 1005, 1005, 1135, 1005, 1128, 1005, 1005, 1317, 1005,
- /* 440 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1278,
- /* 450 */ 1005, 1005, 1005, 1277, 1005, 1005, 1005, 1005, 1005, 1161,
- /* 460 */ 1005, 1160, 1164, 1005, 1017, 1005,
+ /* 0 */ 1297, 1349, 1221, 1014, 1119, 1221, 1221, 1221, 1221, 1014,
+ /* 10 */ 1145, 1145, 1272, 1045, 1014, 1014, 1014, 1014, 1014, 1220,
+ /* 20 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 30 */ 1014, 1151, 1014, 1014, 1014, 1014, 1222, 1223, 1014, 1014,
+ /* 40 */ 1014, 1271, 1273, 1161, 1160, 1159, 1158, 1254, 1132, 1156,
+ /* 50 */ 1149, 1153, 1216, 1217, 1215, 1219, 1222, 1223, 1014, 1152,
+ /* 60 */ 1186, 1200, 1185, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 70 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 80 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 90 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 100 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1194,
+ /* 110 */ 1199, 1206, 1198, 1195, 1188, 1187, 1189, 1190, 1014, 1035,
+ /* 120 */ 1084, 1014, 1014, 1014, 1289, 1288, 1014, 1014, 1045, 1191,
+ /* 130 */ 1192, 1203, 1202, 1201, 1279, 1305, 1304, 1014, 1014, 1014,
+ /* 140 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 150 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 160 */ 1014, 1014, 1014, 1014, 1014, 1014, 1045, 1297, 1041, 1041,
+ /* 170 */ 1014, 1284, 1119, 1110, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 180 */ 1014, 1014, 1014, 1014, 1014, 1276, 1274, 1014, 1236, 1014,
+ /* 190 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 200 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 210 */ 1014, 1014, 1014, 1115, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 220 */ 1014, 1014, 1014, 1014, 1299, 1014, 1249, 1098, 1115, 1115,
+ /* 230 */ 1115, 1115, 1117, 1099, 1097, 1109, 1045, 1021, 1155, 1134,
+ /* 240 */ 1134, 1338, 1155, 1338, 1059, 1319, 1056, 1145, 1145, 1145,
+ /* 250 */ 1134, 1218, 1116, 1109, 1014, 1341, 1124, 1124, 1340, 1340,
+ /* 260 */ 1124, 1166, 1087, 1155, 1093, 1093, 1093, 1093, 1124, 1032,
+ /* 270 */ 1155, 1166, 1087, 1087, 1155, 1124, 1032, 1253, 1335, 1124,
+ /* 280 */ 1032, 1229, 1124, 1032, 1124, 1032, 1229, 1085, 1085, 1085,
+ /* 290 */ 1074, 1229, 1085, 1059, 1085, 1074, 1085, 1085, 1229, 1233,
+ /* 300 */ 1233, 1229, 1138, 1133, 1138, 1133, 1138, 1133, 1138, 1133,
+ /* 310 */ 1124, 1224, 1124, 1014, 1150, 1139, 1148, 1146, 1155, 1038,
+ /* 320 */ 1077, 1302, 1302, 1298, 1298, 1298, 1346, 1346, 1284, 1314,
+ /* 330 */ 1045, 1045, 1045, 1045, 1314, 1061, 1061, 1045, 1045, 1045,
+ /* 340 */ 1045, 1314, 1014, 1014, 1014, 1014, 1014, 1014, 1309, 1014,
+ /* 350 */ 1238, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 360 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1171,
+ /* 370 */ 1014, 1017, 1281, 1014, 1014, 1280, 1014, 1014, 1014, 1014,
+ /* 380 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 390 */ 1014, 1014, 1014, 1014, 1014, 1014, 1337, 1014, 1014, 1014,
+ /* 400 */ 1014, 1014, 1014, 1252, 1251, 1014, 1014, 1126, 1014, 1014,
+ /* 410 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 420 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 430 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 440 */ 1014, 1014, 1147, 1014, 1140, 1014, 1014, 1014, 1014, 1328,
+ /* 450 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
+ /* 460 */ 1014, 1014, 1014, 1323, 1101, 1173, 1014, 1172, 1176, 1014,
+ /* 470 */ 1026, 1014,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -139293,7 +140969,7 @@ static const char *const yyTokenName[] = {
/* 194 */ "fullname",
/* 195 */ "selectnowith",
/* 196 */ "oneselect",
- /* 197 */ "with",
+ /* 197 */ "wqlist",
/* 198 */ "multiselect_op",
/* 199 */ "distinct",
/* 200 */ "selcollist",
@@ -139315,39 +140991,39 @@ static const char *const yyTokenName[] = {
/* 216 */ "on_opt",
/* 217 */ "using_opt",
/* 218 */ "idlist",
- /* 219 */ "setlist",
- /* 220 */ "insert_cmd",
- /* 221 */ "idlist_opt",
- /* 222 */ "likeop",
- /* 223 */ "between_op",
- /* 224 */ "in_op",
- /* 225 */ "paren_exprlist",
- /* 226 */ "case_operand",
- /* 227 */ "case_exprlist",
- /* 228 */ "case_else",
- /* 229 */ "uniqueflag",
- /* 230 */ "collate",
- /* 231 */ "nmnum",
- /* 232 */ "trigger_decl",
- /* 233 */ "trigger_cmd_list",
- /* 234 */ "trigger_time",
- /* 235 */ "trigger_event",
- /* 236 */ "foreach_clause",
- /* 237 */ "when_clause",
- /* 238 */ "trigger_cmd",
- /* 239 */ "trnm",
- /* 240 */ "tridxby",
- /* 241 */ "database_kw_opt",
- /* 242 */ "key_opt",
- /* 243 */ "add_column_fullname",
- /* 244 */ "kwcolumn_opt",
- /* 245 */ "create_vtab",
- /* 246 */ "vtabarglist",
- /* 247 */ "vtabarg",
- /* 248 */ "vtabargtoken",
- /* 249 */ "lp",
- /* 250 */ "anylist",
- /* 251 */ "wqlist",
+ /* 219 */ "with",
+ /* 220 */ "setlist",
+ /* 221 */ "insert_cmd",
+ /* 222 */ "idlist_opt",
+ /* 223 */ "likeop",
+ /* 224 */ "between_op",
+ /* 225 */ "in_op",
+ /* 226 */ "paren_exprlist",
+ /* 227 */ "case_operand",
+ /* 228 */ "case_exprlist",
+ /* 229 */ "case_else",
+ /* 230 */ "uniqueflag",
+ /* 231 */ "collate",
+ /* 232 */ "nmnum",
+ /* 233 */ "trigger_decl",
+ /* 234 */ "trigger_cmd_list",
+ /* 235 */ "trigger_time",
+ /* 236 */ "trigger_event",
+ /* 237 */ "foreach_clause",
+ /* 238 */ "when_clause",
+ /* 239 */ "trigger_cmd",
+ /* 240 */ "trnm",
+ /* 241 */ "tridxby",
+ /* 242 */ "database_kw_opt",
+ /* 243 */ "key_opt",
+ /* 244 */ "add_column_fullname",
+ /* 245 */ "kwcolumn_opt",
+ /* 246 */ "create_vtab",
+ /* 247 */ "vtabarglist",
+ /* 248 */ "vtabarg",
+ /* 249 */ "vtabargtoken",
+ /* 250 */ "lp",
+ /* 251 */ "anylist",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -139435,256 +141111,259 @@ static const char *const yyRuleName[] = {
/* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
/* 78 */ "cmd ::= DROP VIEW ifexists fullname",
/* 79 */ "cmd ::= select",
- /* 80 */ "select ::= with selectnowith",
- /* 81 */ "selectnowith ::= selectnowith multiselect_op oneselect",
- /* 82 */ "multiselect_op ::= UNION",
- /* 83 */ "multiselect_op ::= UNION ALL",
- /* 84 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 85 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 86 */ "values ::= VALUES LP nexprlist RP",
- /* 87 */ "values ::= values COMMA LP exprlist RP",
- /* 88 */ "distinct ::= DISTINCT",
- /* 89 */ "distinct ::= ALL",
- /* 90 */ "distinct ::=",
- /* 91 */ "sclp ::=",
- /* 92 */ "selcollist ::= sclp scanpt expr scanpt as",
- /* 93 */ "selcollist ::= sclp scanpt STAR",
- /* 94 */ "selcollist ::= sclp scanpt nm DOT STAR",
- /* 95 */ "as ::= AS nm",
- /* 96 */ "as ::=",
- /* 97 */ "from ::=",
- /* 98 */ "from ::= FROM seltablist",
- /* 99 */ "stl_prefix ::= seltablist joinop",
- /* 100 */ "stl_prefix ::=",
- /* 101 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 102 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
- /* 103 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 104 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 105 */ "dbnm ::=",
- /* 106 */ "dbnm ::= DOT nm",
- /* 107 */ "fullname ::= nm dbnm",
- /* 108 */ "joinop ::= COMMA|JOIN",
- /* 109 */ "joinop ::= JOIN_KW JOIN",
- /* 110 */ "joinop ::= JOIN_KW nm JOIN",
- /* 111 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 112 */ "on_opt ::= ON expr",
- /* 113 */ "on_opt ::=",
- /* 114 */ "indexed_opt ::=",
- /* 115 */ "indexed_opt ::= INDEXED BY nm",
- /* 116 */ "indexed_opt ::= NOT INDEXED",
- /* 117 */ "using_opt ::= USING LP idlist RP",
- /* 118 */ "using_opt ::=",
- /* 119 */ "orderby_opt ::=",
- /* 120 */ "orderby_opt ::= ORDER BY sortlist",
- /* 121 */ "sortlist ::= sortlist COMMA expr sortorder",
- /* 122 */ "sortlist ::= expr sortorder",
- /* 123 */ "sortorder ::= ASC",
- /* 124 */ "sortorder ::= DESC",
- /* 125 */ "sortorder ::=",
- /* 126 */ "groupby_opt ::=",
- /* 127 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 128 */ "having_opt ::=",
- /* 129 */ "having_opt ::= HAVING expr",
- /* 130 */ "limit_opt ::=",
- /* 131 */ "limit_opt ::= LIMIT expr",
- /* 132 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 133 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 134 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt",
- /* 135 */ "where_opt ::=",
- /* 136 */ "where_opt ::= WHERE expr",
- /* 137 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 138 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 139 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 140 */ "setlist ::= nm EQ expr",
- /* 141 */ "setlist ::= LP idlist RP EQ expr",
- /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select",
- /* 143 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES",
- /* 144 */ "insert_cmd ::= INSERT orconf",
- /* 145 */ "insert_cmd ::= REPLACE",
- /* 146 */ "idlist_opt ::=",
- /* 147 */ "idlist_opt ::= LP idlist RP",
- /* 148 */ "idlist ::= idlist COMMA nm",
- /* 149 */ "idlist ::= nm",
- /* 150 */ "expr ::= LP expr RP",
- /* 151 */ "expr ::= ID|INDEXED",
- /* 152 */ "expr ::= JOIN_KW",
- /* 153 */ "expr ::= nm DOT nm",
- /* 154 */ "expr ::= nm DOT nm DOT nm",
- /* 155 */ "term ::= NULL|FLOAT|BLOB",
- /* 156 */ "term ::= STRING",
- /* 157 */ "term ::= INTEGER",
- /* 158 */ "expr ::= VARIABLE",
- /* 159 */ "expr ::= expr COLLATE ID|STRING",
- /* 160 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 161 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 162 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 163 */ "term ::= CTIME_KW",
- /* 164 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 165 */ "expr ::= expr AND expr",
- /* 166 */ "expr ::= expr OR expr",
- /* 167 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 168 */ "expr ::= expr EQ|NE expr",
- /* 169 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 170 */ "expr ::= expr PLUS|MINUS expr",
- /* 171 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 172 */ "expr ::= expr CONCAT expr",
- /* 173 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 174 */ "expr ::= expr likeop expr",
- /* 175 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 176 */ "expr ::= expr ISNULL|NOTNULL",
- /* 177 */ "expr ::= expr NOT NULL",
- /* 178 */ "expr ::= expr IS expr",
- /* 179 */ "expr ::= expr IS NOT expr",
- /* 180 */ "expr ::= NOT expr",
- /* 181 */ "expr ::= BITNOT expr",
- /* 182 */ "expr ::= MINUS expr",
- /* 183 */ "expr ::= PLUS expr",
- /* 184 */ "between_op ::= BETWEEN",
- /* 185 */ "between_op ::= NOT BETWEEN",
- /* 186 */ "expr ::= expr between_op expr AND expr",
- /* 187 */ "in_op ::= IN",
- /* 188 */ "in_op ::= NOT IN",
- /* 189 */ "expr ::= expr in_op LP exprlist RP",
- /* 190 */ "expr ::= LP select RP",
- /* 191 */ "expr ::= expr in_op LP select RP",
- /* 192 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 193 */ "expr ::= EXISTS LP select RP",
- /* 194 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 195 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 196 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 197 */ "case_else ::= ELSE expr",
- /* 198 */ "case_else ::=",
- /* 199 */ "case_operand ::= expr",
- /* 200 */ "case_operand ::=",
- /* 201 */ "exprlist ::=",
- /* 202 */ "nexprlist ::= nexprlist COMMA expr",
- /* 203 */ "nexprlist ::= expr",
- /* 204 */ "paren_exprlist ::=",
- /* 205 */ "paren_exprlist ::= LP exprlist RP",
- /* 206 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 207 */ "uniqueflag ::= UNIQUE",
- /* 208 */ "uniqueflag ::=",
- /* 209 */ "eidlist_opt ::=",
- /* 210 */ "eidlist_opt ::= LP eidlist RP",
- /* 211 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 212 */ "eidlist ::= nm collate sortorder",
- /* 213 */ "collate ::=",
- /* 214 */ "collate ::= COLLATE ID|STRING",
- /* 215 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 216 */ "cmd ::= VACUUM",
- /* 217 */ "cmd ::= VACUUM nm",
- /* 218 */ "cmd ::= PRAGMA nm dbnm",
- /* 219 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 220 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 221 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 222 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 223 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 224 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 225 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 226 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 227 */ "trigger_time ::= BEFORE|AFTER",
- /* 228 */ "trigger_time ::= INSTEAD OF",
- /* 229 */ "trigger_time ::=",
- /* 230 */ "trigger_event ::= DELETE|INSERT",
- /* 231 */ "trigger_event ::= UPDATE",
- /* 232 */ "trigger_event ::= UPDATE OF idlist",
- /* 233 */ "when_clause ::=",
- /* 234 */ "when_clause ::= WHEN expr",
- /* 235 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 236 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 237 */ "trnm ::= nm DOT nm",
- /* 238 */ "tridxby ::= INDEXED BY nm",
- /* 239 */ "tridxby ::= NOT INDEXED",
- /* 240 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
- /* 241 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt",
- /* 242 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 243 */ "trigger_cmd ::= scanpt select scanpt",
- /* 244 */ "expr ::= RAISE LP IGNORE RP",
- /* 245 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 246 */ "raisetype ::= ROLLBACK",
- /* 247 */ "raisetype ::= ABORT",
- /* 248 */ "raisetype ::= FAIL",
- /* 249 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 250 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 251 */ "cmd ::= DETACH database_kw_opt expr",
- /* 252 */ "key_opt ::=",
- /* 253 */ "key_opt ::= KEY expr",
- /* 254 */ "cmd ::= REINDEX",
- /* 255 */ "cmd ::= REINDEX nm dbnm",
- /* 256 */ "cmd ::= ANALYZE",
- /* 257 */ "cmd ::= ANALYZE nm dbnm",
- /* 258 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 259 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 260 */ "add_column_fullname ::= fullname",
- /* 261 */ "cmd ::= create_vtab",
- /* 262 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 263 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 264 */ "vtabarg ::=",
- /* 265 */ "vtabargtoken ::= ANY",
- /* 266 */ "vtabargtoken ::= lp anylist RP",
- /* 267 */ "lp ::= LP",
- /* 268 */ "with ::=",
- /* 269 */ "with ::= WITH wqlist",
- /* 270 */ "with ::= WITH RECURSIVE wqlist",
- /* 271 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 272 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 273 */ "input ::= cmdlist",
- /* 274 */ "cmdlist ::= cmdlist ecmd",
- /* 275 */ "cmdlist ::= ecmd",
- /* 276 */ "ecmd ::= SEMI",
- /* 277 */ "ecmd ::= explain cmdx SEMI",
- /* 278 */ "explain ::=",
- /* 279 */ "trans_opt ::=",
- /* 280 */ "trans_opt ::= TRANSACTION",
- /* 281 */ "trans_opt ::= TRANSACTION nm",
- /* 282 */ "savepoint_opt ::= SAVEPOINT",
- /* 283 */ "savepoint_opt ::=",
- /* 284 */ "cmd ::= create_table create_table_args",
- /* 285 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 286 */ "columnlist ::= columnname carglist",
- /* 287 */ "nm ::= ID|INDEXED",
- /* 288 */ "nm ::= STRING",
- /* 289 */ "nm ::= JOIN_KW",
- /* 290 */ "typetoken ::= typename",
- /* 291 */ "typename ::= ID|STRING",
- /* 292 */ "signed ::= plus_num",
- /* 293 */ "signed ::= minus_num",
- /* 294 */ "carglist ::= carglist ccons",
- /* 295 */ "carglist ::=",
- /* 296 */ "ccons ::= NULL onconf",
- /* 297 */ "conslist_opt ::= COMMA conslist",
- /* 298 */ "conslist ::= conslist tconscomma tcons",
- /* 299 */ "conslist ::= tcons",
- /* 300 */ "tconscomma ::=",
- /* 301 */ "defer_subclause_opt ::= defer_subclause",
- /* 302 */ "resolvetype ::= raisetype",
- /* 303 */ "selectnowith ::= oneselect",
- /* 304 */ "oneselect ::= values",
- /* 305 */ "sclp ::= selcollist COMMA",
- /* 306 */ "as ::= ID|STRING",
- /* 307 */ "expr ::= term",
- /* 308 */ "likeop ::= LIKE_KW|MATCH",
- /* 309 */ "exprlist ::= nexprlist",
- /* 310 */ "nmnum ::= plus_num",
- /* 311 */ "nmnum ::= nm",
- /* 312 */ "nmnum ::= ON",
- /* 313 */ "nmnum ::= DELETE",
- /* 314 */ "nmnum ::= DEFAULT",
- /* 315 */ "plus_num ::= INTEGER|FLOAT",
- /* 316 */ "foreach_clause ::=",
- /* 317 */ "foreach_clause ::= FOR EACH ROW",
- /* 318 */ "trnm ::= nm",
- /* 319 */ "tridxby ::=",
- /* 320 */ "database_kw_opt ::= DATABASE",
- /* 321 */ "database_kw_opt ::=",
- /* 322 */ "kwcolumn_opt ::=",
- /* 323 */ "kwcolumn_opt ::= COLUMNKW",
- /* 324 */ "vtabarglist ::= vtabarg",
- /* 325 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 326 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 327 */ "anylist ::=",
- /* 328 */ "anylist ::= anylist LP anylist RP",
- /* 329 */ "anylist ::= anylist ANY",
+ /* 80 */ "select ::= WITH wqlist selectnowith",
+ /* 81 */ "select ::= WITH RECURSIVE wqlist selectnowith",
+ /* 82 */ "select ::= selectnowith",
+ /* 83 */ "selectnowith ::= selectnowith multiselect_op oneselect",
+ /* 84 */ "multiselect_op ::= UNION",
+ /* 85 */ "multiselect_op ::= UNION ALL",
+ /* 86 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 88 */ "values ::= VALUES LP nexprlist RP",
+ /* 89 */ "values ::= values COMMA LP exprlist RP",
+ /* 90 */ "distinct ::= DISTINCT",
+ /* 91 */ "distinct ::= ALL",
+ /* 92 */ "distinct ::=",
+ /* 93 */ "sclp ::=",
+ /* 94 */ "selcollist ::= sclp scanpt expr scanpt as",
+ /* 95 */ "selcollist ::= sclp scanpt STAR",
+ /* 96 */ "selcollist ::= sclp scanpt nm DOT STAR",
+ /* 97 */ "as ::= AS nm",
+ /* 98 */ "as ::=",
+ /* 99 */ "from ::=",
+ /* 100 */ "from ::= FROM seltablist",
+ /* 101 */ "stl_prefix ::= seltablist joinop",
+ /* 102 */ "stl_prefix ::=",
+ /* 103 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 104 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
+ /* 105 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 106 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 107 */ "dbnm ::=",
+ /* 108 */ "dbnm ::= DOT nm",
+ /* 109 */ "fullname ::= nm",
+ /* 110 */ "fullname ::= nm DOT nm",
+ /* 111 */ "joinop ::= COMMA|JOIN",
+ /* 112 */ "joinop ::= JOIN_KW JOIN",
+ /* 113 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 114 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 115 */ "on_opt ::= ON expr",
+ /* 116 */ "on_opt ::=",
+ /* 117 */ "indexed_opt ::=",
+ /* 118 */ "indexed_opt ::= INDEXED BY nm",
+ /* 119 */ "indexed_opt ::= NOT INDEXED",
+ /* 120 */ "using_opt ::= USING LP idlist RP",
+ /* 121 */ "using_opt ::=",
+ /* 122 */ "orderby_opt ::=",
+ /* 123 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 124 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 125 */ "sortlist ::= expr sortorder",
+ /* 126 */ "sortorder ::= ASC",
+ /* 127 */ "sortorder ::= DESC",
+ /* 128 */ "sortorder ::=",
+ /* 129 */ "groupby_opt ::=",
+ /* 130 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 131 */ "having_opt ::=",
+ /* 132 */ "having_opt ::= HAVING expr",
+ /* 133 */ "limit_opt ::=",
+ /* 134 */ "limit_opt ::= LIMIT expr",
+ /* 135 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 136 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 137 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt",
+ /* 138 */ "where_opt ::=",
+ /* 139 */ "where_opt ::= WHERE expr",
+ /* 140 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 141 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 142 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 143 */ "setlist ::= nm EQ expr",
+ /* 144 */ "setlist ::= LP idlist RP EQ expr",
+ /* 145 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select",
+ /* 146 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES",
+ /* 147 */ "insert_cmd ::= INSERT orconf",
+ /* 148 */ "insert_cmd ::= REPLACE",
+ /* 149 */ "idlist_opt ::=",
+ /* 150 */ "idlist_opt ::= LP idlist RP",
+ /* 151 */ "idlist ::= idlist COMMA nm",
+ /* 152 */ "idlist ::= nm",
+ /* 153 */ "expr ::= LP expr RP",
+ /* 154 */ "expr ::= ID|INDEXED",
+ /* 155 */ "expr ::= JOIN_KW",
+ /* 156 */ "expr ::= nm DOT nm",
+ /* 157 */ "expr ::= nm DOT nm DOT nm",
+ /* 158 */ "term ::= NULL|FLOAT|BLOB",
+ /* 159 */ "term ::= STRING",
+ /* 160 */ "term ::= INTEGER",
+ /* 161 */ "expr ::= VARIABLE",
+ /* 162 */ "expr ::= expr COLLATE ID|STRING",
+ /* 163 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 164 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 165 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 166 */ "term ::= CTIME_KW",
+ /* 167 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 168 */ "expr ::= expr AND expr",
+ /* 169 */ "expr ::= expr OR expr",
+ /* 170 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 171 */ "expr ::= expr EQ|NE expr",
+ /* 172 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 173 */ "expr ::= expr PLUS|MINUS expr",
+ /* 174 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 175 */ "expr ::= expr CONCAT expr",
+ /* 176 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 177 */ "expr ::= expr likeop expr",
+ /* 178 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 179 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 180 */ "expr ::= expr NOT NULL",
+ /* 181 */ "expr ::= expr IS expr",
+ /* 182 */ "expr ::= expr IS NOT expr",
+ /* 183 */ "expr ::= NOT expr",
+ /* 184 */ "expr ::= BITNOT expr",
+ /* 185 */ "expr ::= MINUS expr",
+ /* 186 */ "expr ::= PLUS expr",
+ /* 187 */ "between_op ::= BETWEEN",
+ /* 188 */ "between_op ::= NOT BETWEEN",
+ /* 189 */ "expr ::= expr between_op expr AND expr",
+ /* 190 */ "in_op ::= IN",
+ /* 191 */ "in_op ::= NOT IN",
+ /* 192 */ "expr ::= expr in_op LP exprlist RP",
+ /* 193 */ "expr ::= LP select RP",
+ /* 194 */ "expr ::= expr in_op LP select RP",
+ /* 195 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 196 */ "expr ::= EXISTS LP select RP",
+ /* 197 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 198 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 199 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 200 */ "case_else ::= ELSE expr",
+ /* 201 */ "case_else ::=",
+ /* 202 */ "case_operand ::= expr",
+ /* 203 */ "case_operand ::=",
+ /* 204 */ "exprlist ::=",
+ /* 205 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 206 */ "nexprlist ::= expr",
+ /* 207 */ "paren_exprlist ::=",
+ /* 208 */ "paren_exprlist ::= LP exprlist RP",
+ /* 209 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 210 */ "uniqueflag ::= UNIQUE",
+ /* 211 */ "uniqueflag ::=",
+ /* 212 */ "eidlist_opt ::=",
+ /* 213 */ "eidlist_opt ::= LP eidlist RP",
+ /* 214 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 215 */ "eidlist ::= nm collate sortorder",
+ /* 216 */ "collate ::=",
+ /* 217 */ "collate ::= COLLATE ID|STRING",
+ /* 218 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 219 */ "cmd ::= VACUUM",
+ /* 220 */ "cmd ::= VACUUM nm",
+ /* 221 */ "cmd ::= PRAGMA nm dbnm",
+ /* 222 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 223 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 224 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 225 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 226 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 227 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 228 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 229 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 230 */ "trigger_time ::= BEFORE|AFTER",
+ /* 231 */ "trigger_time ::= INSTEAD OF",
+ /* 232 */ "trigger_time ::=",
+ /* 233 */ "trigger_event ::= DELETE|INSERT",
+ /* 234 */ "trigger_event ::= UPDATE",
+ /* 235 */ "trigger_event ::= UPDATE OF idlist",
+ /* 236 */ "when_clause ::=",
+ /* 237 */ "when_clause ::= WHEN expr",
+ /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 240 */ "trnm ::= nm DOT nm",
+ /* 241 */ "tridxby ::= INDEXED BY nm",
+ /* 242 */ "tridxby ::= NOT INDEXED",
+ /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
+ /* 244 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt",
+ /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 246 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 247 */ "expr ::= RAISE LP IGNORE RP",
+ /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 249 */ "raisetype ::= ROLLBACK",
+ /* 250 */ "raisetype ::= ABORT",
+ /* 251 */ "raisetype ::= FAIL",
+ /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 254 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 255 */ "key_opt ::=",
+ /* 256 */ "key_opt ::= KEY expr",
+ /* 257 */ "cmd ::= REINDEX",
+ /* 258 */ "cmd ::= REINDEX nm dbnm",
+ /* 259 */ "cmd ::= ANALYZE",
+ /* 260 */ "cmd ::= ANALYZE nm dbnm",
+ /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 263 */ "add_column_fullname ::= fullname",
+ /* 264 */ "cmd ::= create_vtab",
+ /* 265 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 267 */ "vtabarg ::=",
+ /* 268 */ "vtabargtoken ::= ANY",
+ /* 269 */ "vtabargtoken ::= lp anylist RP",
+ /* 270 */ "lp ::= LP",
+ /* 271 */ "with ::= WITH wqlist",
+ /* 272 */ "with ::= WITH RECURSIVE wqlist",
+ /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP",
+ /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
+ /* 275 */ "input ::= cmdlist",
+ /* 276 */ "cmdlist ::= cmdlist ecmd",
+ /* 277 */ "cmdlist ::= ecmd",
+ /* 278 */ "ecmd ::= SEMI",
+ /* 279 */ "ecmd ::= explain cmdx SEMI",
+ /* 280 */ "explain ::=",
+ /* 281 */ "trans_opt ::=",
+ /* 282 */ "trans_opt ::= TRANSACTION",
+ /* 283 */ "trans_opt ::= TRANSACTION nm",
+ /* 284 */ "savepoint_opt ::= SAVEPOINT",
+ /* 285 */ "savepoint_opt ::=",
+ /* 286 */ "cmd ::= create_table create_table_args",
+ /* 287 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 288 */ "columnlist ::= columnname carglist",
+ /* 289 */ "nm ::= ID|INDEXED",
+ /* 290 */ "nm ::= STRING",
+ /* 291 */ "nm ::= JOIN_KW",
+ /* 292 */ "typetoken ::= typename",
+ /* 293 */ "typename ::= ID|STRING",
+ /* 294 */ "signed ::= plus_num",
+ /* 295 */ "signed ::= minus_num",
+ /* 296 */ "carglist ::= carglist ccons",
+ /* 297 */ "carglist ::=",
+ /* 298 */ "ccons ::= NULL onconf",
+ /* 299 */ "conslist_opt ::= COMMA conslist",
+ /* 300 */ "conslist ::= conslist tconscomma tcons",
+ /* 301 */ "conslist ::= tcons",
+ /* 302 */ "tconscomma ::=",
+ /* 303 */ "defer_subclause_opt ::= defer_subclause",
+ /* 304 */ "resolvetype ::= raisetype",
+ /* 305 */ "selectnowith ::= oneselect",
+ /* 306 */ "oneselect ::= values",
+ /* 307 */ "sclp ::= selcollist COMMA",
+ /* 308 */ "as ::= ID|STRING",
+ /* 309 */ "expr ::= term",
+ /* 310 */ "likeop ::= LIKE_KW|MATCH",
+ /* 311 */ "exprlist ::= nexprlist",
+ /* 312 */ "nmnum ::= plus_num",
+ /* 313 */ "nmnum ::= nm",
+ /* 314 */ "nmnum ::= ON",
+ /* 315 */ "nmnum ::= DELETE",
+ /* 316 */ "nmnum ::= DEFAULT",
+ /* 317 */ "plus_num ::= INTEGER|FLOAT",
+ /* 318 */ "foreach_clause ::=",
+ /* 319 */ "foreach_clause ::= FOR EACH ROW",
+ /* 320 */ "trnm ::= nm",
+ /* 321 */ "tridxby ::=",
+ /* 322 */ "database_kw_opt ::= DATABASE",
+ /* 323 */ "database_kw_opt ::=",
+ /* 324 */ "kwcolumn_opt ::=",
+ /* 325 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 326 */ "vtabarglist ::= vtabarg",
+ /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 328 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 329 */ "anylist ::=",
+ /* 330 */ "anylist ::= anylist LP anylist RP",
+ /* 331 */ "anylist ::= anylist ANY",
+ /* 332 */ "with ::=",
};
#endif /* NDEBUG */
@@ -139818,10 +141497,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy387));
case 202: /* where_opt */
case 204: /* having_opt */
case 216: /* on_opt */
- case 226: /* case_operand */
- case 228: /* case_else */
- case 237: /* when_clause */
- case 242: /* key_opt */
+ case 227: /* case_operand */
+ case 229: /* case_else */
+ case 238: /* when_clause */
+ case 243: /* key_opt */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy314));
}
@@ -139835,9 +141514,9 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy314));
case 208: /* nexprlist */
case 209: /* exprlist */
case 210: /* sclp */
- case 219: /* setlist */
- case 225: /* paren_exprlist */
- case 227: /* case_exprlist */
+ case 220: /* setlist */
+ case 226: /* paren_exprlist */
+ case 228: /* case_exprlist */
{
sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
}
@@ -139850,26 +141529,25 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
sqlite3SrcListDelete(pParse->db, (yypminor->yy259));
}
break;
- case 197: /* with */
- case 251: /* wqlist */
+ case 197: /* wqlist */
{
sqlite3WithDelete(pParse->db, (yypminor->yy451));
}
break;
case 217: /* using_opt */
case 218: /* idlist */
- case 221: /* idlist_opt */
+ case 222: /* idlist_opt */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy384));
}
break;
- case 233: /* trigger_cmd_list */
- case 238: /* trigger_cmd */
+ case 234: /* trigger_cmd_list */
+ case 239: /* trigger_cmd */
{
sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203));
}
break;
- case 235: /* trigger_event */
+ case 236: /* trigger_event */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy90).b);
}
@@ -139997,7 +141675,8 @@ static unsigned int yy_find_shift_action(
#endif
do{
i = yy_shift_ofst[stateno];
- assert( i>=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) );
+ assert( i>=0 );
+ assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) );
assert( iLookAhead!=YYNOCODE );
assert( iLookAhead < YYNTOKEN );
i += iLookAhead;
@@ -140247,256 +141926,259 @@ static const struct {
{ 149, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{ 149, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */
{ 149, -1 }, /* (79) cmd ::= select */
- { 163, -2 }, /* (80) select ::= with selectnowith */
- { 195, -3 }, /* (81) selectnowith ::= selectnowith multiselect_op oneselect */
- { 198, -1 }, /* (82) multiselect_op ::= UNION */
- { 198, -2 }, /* (83) multiselect_op ::= UNION ALL */
- { 198, -1 }, /* (84) multiselect_op ::= EXCEPT|INTERSECT */
- { 196, -9 }, /* (85) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- { 207, -4 }, /* (86) values ::= VALUES LP nexprlist RP */
- { 207, -5 }, /* (87) values ::= values COMMA LP exprlist RP */
- { 199, -1 }, /* (88) distinct ::= DISTINCT */
- { 199, -1 }, /* (89) distinct ::= ALL */
- { 199, 0 }, /* (90) distinct ::= */
- { 210, 0 }, /* (91) sclp ::= */
- { 200, -5 }, /* (92) selcollist ::= sclp scanpt expr scanpt as */
- { 200, -3 }, /* (93) selcollist ::= sclp scanpt STAR */
- { 200, -5 }, /* (94) selcollist ::= sclp scanpt nm DOT STAR */
- { 211, -2 }, /* (95) as ::= AS nm */
- { 211, 0 }, /* (96) as ::= */
- { 201, 0 }, /* (97) from ::= */
- { 201, -2 }, /* (98) from ::= FROM seltablist */
- { 213, -2 }, /* (99) stl_prefix ::= seltablist joinop */
- { 213, 0 }, /* (100) stl_prefix ::= */
- { 212, -7 }, /* (101) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- { 212, -9 }, /* (102) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- { 212, -7 }, /* (103) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- { 212, -7 }, /* (104) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- { 159, 0 }, /* (105) dbnm ::= */
- { 159, -2 }, /* (106) dbnm ::= DOT nm */
- { 194, -2 }, /* (107) fullname ::= nm dbnm */
- { 214, -1 }, /* (108) joinop ::= COMMA|JOIN */
- { 214, -2 }, /* (109) joinop ::= JOIN_KW JOIN */
- { 214, -3 }, /* (110) joinop ::= JOIN_KW nm JOIN */
- { 214, -4 }, /* (111) joinop ::= JOIN_KW nm nm JOIN */
- { 216, -2 }, /* (112) on_opt ::= ON expr */
- { 216, 0 }, /* (113) on_opt ::= */
- { 215, 0 }, /* (114) indexed_opt ::= */
- { 215, -3 }, /* (115) indexed_opt ::= INDEXED BY nm */
- { 215, -2 }, /* (116) indexed_opt ::= NOT INDEXED */
- { 217, -4 }, /* (117) using_opt ::= USING LP idlist RP */
- { 217, 0 }, /* (118) using_opt ::= */
- { 205, 0 }, /* (119) orderby_opt ::= */
- { 205, -3 }, /* (120) orderby_opt ::= ORDER BY sortlist */
- { 187, -4 }, /* (121) sortlist ::= sortlist COMMA expr sortorder */
- { 187, -2 }, /* (122) sortlist ::= expr sortorder */
- { 176, -1 }, /* (123) sortorder ::= ASC */
- { 176, -1 }, /* (124) sortorder ::= DESC */
- { 176, 0 }, /* (125) sortorder ::= */
- { 203, 0 }, /* (126) groupby_opt ::= */
- { 203, -3 }, /* (127) groupby_opt ::= GROUP BY nexprlist */
- { 204, 0 }, /* (128) having_opt ::= */
- { 204, -2 }, /* (129) having_opt ::= HAVING expr */
- { 206, 0 }, /* (130) limit_opt ::= */
- { 206, -2 }, /* (131) limit_opt ::= LIMIT expr */
- { 206, -4 }, /* (132) limit_opt ::= LIMIT expr OFFSET expr */
- { 206, -4 }, /* (133) limit_opt ::= LIMIT expr COMMA expr */
- { 149, -6 }, /* (134) cmd ::= with DELETE FROM fullname indexed_opt where_opt */
- { 202, 0 }, /* (135) where_opt ::= */
- { 202, -2 }, /* (136) where_opt ::= WHERE expr */
- { 149, -8 }, /* (137) cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
- { 219, -5 }, /* (138) setlist ::= setlist COMMA nm EQ expr */
- { 219, -7 }, /* (139) setlist ::= setlist COMMA LP idlist RP EQ expr */
- { 219, -3 }, /* (140) setlist ::= nm EQ expr */
- { 219, -5 }, /* (141) setlist ::= LP idlist RP EQ expr */
- { 149, -6 }, /* (142) cmd ::= with insert_cmd INTO fullname idlist_opt select */
- { 149, -7 }, /* (143) cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
- { 220, -2 }, /* (144) insert_cmd ::= INSERT orconf */
- { 220, -1 }, /* (145) insert_cmd ::= REPLACE */
- { 221, 0 }, /* (146) idlist_opt ::= */
- { 221, -3 }, /* (147) idlist_opt ::= LP idlist RP */
- { 218, -3 }, /* (148) idlist ::= idlist COMMA nm */
- { 218, -1 }, /* (149) idlist ::= nm */
- { 174, -3 }, /* (150) expr ::= LP expr RP */
- { 174, -1 }, /* (151) expr ::= ID|INDEXED */
- { 174, -1 }, /* (152) expr ::= JOIN_KW */
- { 174, -3 }, /* (153) expr ::= nm DOT nm */
- { 174, -5 }, /* (154) expr ::= nm DOT nm DOT nm */
- { 173, -1 }, /* (155) term ::= NULL|FLOAT|BLOB */
- { 173, -1 }, /* (156) term ::= STRING */
- { 173, -1 }, /* (157) term ::= INTEGER */
- { 174, -1 }, /* (158) expr ::= VARIABLE */
- { 174, -3 }, /* (159) expr ::= expr COLLATE ID|STRING */
- { 174, -6 }, /* (160) expr ::= CAST LP expr AS typetoken RP */
- { 174, -5 }, /* (161) expr ::= ID|INDEXED LP distinct exprlist RP */
- { 174, -4 }, /* (162) expr ::= ID|INDEXED LP STAR RP */
- { 173, -1 }, /* (163) term ::= CTIME_KW */
- { 174, -5 }, /* (164) expr ::= LP nexprlist COMMA expr RP */
- { 174, -3 }, /* (165) expr ::= expr AND expr */
- { 174, -3 }, /* (166) expr ::= expr OR expr */
- { 174, -3 }, /* (167) expr ::= expr LT|GT|GE|LE expr */
- { 174, -3 }, /* (168) expr ::= expr EQ|NE expr */
- { 174, -3 }, /* (169) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- { 174, -3 }, /* (170) expr ::= expr PLUS|MINUS expr */
- { 174, -3 }, /* (171) expr ::= expr STAR|SLASH|REM expr */
- { 174, -3 }, /* (172) expr ::= expr CONCAT expr */
- { 222, -2 }, /* (173) likeop ::= NOT LIKE_KW|MATCH */
- { 174, -3 }, /* (174) expr ::= expr likeop expr */
- { 174, -5 }, /* (175) expr ::= expr likeop expr ESCAPE expr */
- { 174, -2 }, /* (176) expr ::= expr ISNULL|NOTNULL */
- { 174, -3 }, /* (177) expr ::= expr NOT NULL */
- { 174, -3 }, /* (178) expr ::= expr IS expr */
- { 174, -4 }, /* (179) expr ::= expr IS NOT expr */
- { 174, -2 }, /* (180) expr ::= NOT expr */
- { 174, -2 }, /* (181) expr ::= BITNOT expr */
- { 174, -2 }, /* (182) expr ::= MINUS expr */
- { 174, -2 }, /* (183) expr ::= PLUS expr */
- { 223, -1 }, /* (184) between_op ::= BETWEEN */
- { 223, -2 }, /* (185) between_op ::= NOT BETWEEN */
- { 174, -5 }, /* (186) expr ::= expr between_op expr AND expr */
- { 224, -1 }, /* (187) in_op ::= IN */
- { 224, -2 }, /* (188) in_op ::= NOT IN */
- { 174, -5 }, /* (189) expr ::= expr in_op LP exprlist RP */
- { 174, -3 }, /* (190) expr ::= LP select RP */
- { 174, -5 }, /* (191) expr ::= expr in_op LP select RP */
- { 174, -5 }, /* (192) expr ::= expr in_op nm dbnm paren_exprlist */
- { 174, -4 }, /* (193) expr ::= EXISTS LP select RP */
- { 174, -5 }, /* (194) expr ::= CASE case_operand case_exprlist case_else END */
- { 227, -5 }, /* (195) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- { 227, -4 }, /* (196) case_exprlist ::= WHEN expr THEN expr */
- { 228, -2 }, /* (197) case_else ::= ELSE expr */
- { 228, 0 }, /* (198) case_else ::= */
- { 226, -1 }, /* (199) case_operand ::= expr */
- { 226, 0 }, /* (200) case_operand ::= */
- { 209, 0 }, /* (201) exprlist ::= */
- { 208, -3 }, /* (202) nexprlist ::= nexprlist COMMA expr */
- { 208, -1 }, /* (203) nexprlist ::= expr */
- { 225, 0 }, /* (204) paren_exprlist ::= */
- { 225, -3 }, /* (205) paren_exprlist ::= LP exprlist RP */
- { 149, -12 }, /* (206) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- { 229, -1 }, /* (207) uniqueflag ::= UNIQUE */
- { 229, 0 }, /* (208) uniqueflag ::= */
- { 178, 0 }, /* (209) eidlist_opt ::= */
- { 178, -3 }, /* (210) eidlist_opt ::= LP eidlist RP */
- { 188, -5 }, /* (211) eidlist ::= eidlist COMMA nm collate sortorder */
- { 188, -3 }, /* (212) eidlist ::= nm collate sortorder */
- { 230, 0 }, /* (213) collate ::= */
- { 230, -2 }, /* (214) collate ::= COLLATE ID|STRING */
- { 149, -4 }, /* (215) cmd ::= DROP INDEX ifexists fullname */
- { 149, -1 }, /* (216) cmd ::= VACUUM */
- { 149, -2 }, /* (217) cmd ::= VACUUM nm */
- { 149, -3 }, /* (218) cmd ::= PRAGMA nm dbnm */
- { 149, -5 }, /* (219) cmd ::= PRAGMA nm dbnm EQ nmnum */
- { 149, -6 }, /* (220) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- { 149, -5 }, /* (221) cmd ::= PRAGMA nm dbnm EQ minus_num */
- { 149, -6 }, /* (222) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- { 169, -2 }, /* (223) plus_num ::= PLUS INTEGER|FLOAT */
- { 170, -2 }, /* (224) minus_num ::= MINUS INTEGER|FLOAT */
- { 149, -5 }, /* (225) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- { 232, -11 }, /* (226) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- { 234, -1 }, /* (227) trigger_time ::= BEFORE|AFTER */
- { 234, -2 }, /* (228) trigger_time ::= INSTEAD OF */
- { 234, 0 }, /* (229) trigger_time ::= */
- { 235, -1 }, /* (230) trigger_event ::= DELETE|INSERT */
- { 235, -1 }, /* (231) trigger_event ::= UPDATE */
- { 235, -3 }, /* (232) trigger_event ::= UPDATE OF idlist */
- { 237, 0 }, /* (233) when_clause ::= */
- { 237, -2 }, /* (234) when_clause ::= WHEN expr */
- { 233, -3 }, /* (235) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- { 233, -2 }, /* (236) trigger_cmd_list ::= trigger_cmd SEMI */
- { 239, -3 }, /* (237) trnm ::= nm DOT nm */
- { 240, -3 }, /* (238) tridxby ::= INDEXED BY nm */
- { 240, -2 }, /* (239) tridxby ::= NOT INDEXED */
- { 238, -8 }, /* (240) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
- { 238, -7 }, /* (241) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */
- { 238, -6 }, /* (242) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- { 238, -3 }, /* (243) trigger_cmd ::= scanpt select scanpt */
- { 174, -4 }, /* (244) expr ::= RAISE LP IGNORE RP */
- { 174, -6 }, /* (245) expr ::= RAISE LP raisetype COMMA nm RP */
- { 192, -1 }, /* (246) raisetype ::= ROLLBACK */
- { 192, -1 }, /* (247) raisetype ::= ABORT */
- { 192, -1 }, /* (248) raisetype ::= FAIL */
- { 149, -4 }, /* (249) cmd ::= DROP TRIGGER ifexists fullname */
- { 149, -6 }, /* (250) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- { 149, -3 }, /* (251) cmd ::= DETACH database_kw_opt expr */
- { 242, 0 }, /* (252) key_opt ::= */
- { 242, -2 }, /* (253) key_opt ::= KEY expr */
- { 149, -1 }, /* (254) cmd ::= REINDEX */
- { 149, -3 }, /* (255) cmd ::= REINDEX nm dbnm */
- { 149, -1 }, /* (256) cmd ::= ANALYZE */
- { 149, -3 }, /* (257) cmd ::= ANALYZE nm dbnm */
- { 149, -6 }, /* (258) cmd ::= ALTER TABLE fullname RENAME TO nm */
- { 149, -7 }, /* (259) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- { 243, -1 }, /* (260) add_column_fullname ::= fullname */
- { 149, -1 }, /* (261) cmd ::= create_vtab */
- { 149, -4 }, /* (262) cmd ::= create_vtab LP vtabarglist RP */
- { 245, -8 }, /* (263) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- { 247, 0 }, /* (264) vtabarg ::= */
- { 248, -1 }, /* (265) vtabargtoken ::= ANY */
- { 248, -3 }, /* (266) vtabargtoken ::= lp anylist RP */
- { 249, -1 }, /* (267) lp ::= LP */
- { 197, 0 }, /* (268) with ::= */
- { 197, -2 }, /* (269) with ::= WITH wqlist */
- { 197, -3 }, /* (270) with ::= WITH RECURSIVE wqlist */
- { 251, -6 }, /* (271) wqlist ::= nm eidlist_opt AS LP select RP */
- { 251, -8 }, /* (272) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- { 144, -1 }, /* (273) input ::= cmdlist */
- { 145, -2 }, /* (274) cmdlist ::= cmdlist ecmd */
- { 145, -1 }, /* (275) cmdlist ::= ecmd */
- { 146, -1 }, /* (276) ecmd ::= SEMI */
- { 146, -3 }, /* (277) ecmd ::= explain cmdx SEMI */
- { 147, 0 }, /* (278) explain ::= */
- { 151, 0 }, /* (279) trans_opt ::= */
- { 151, -1 }, /* (280) trans_opt ::= TRANSACTION */
- { 151, -2 }, /* (281) trans_opt ::= TRANSACTION nm */
- { 153, -1 }, /* (282) savepoint_opt ::= SAVEPOINT */
- { 153, 0 }, /* (283) savepoint_opt ::= */
- { 149, -2 }, /* (284) cmd ::= create_table create_table_args */
- { 160, -4 }, /* (285) columnlist ::= columnlist COMMA columnname carglist */
- { 160, -2 }, /* (286) columnlist ::= columnname carglist */
- { 152, -1 }, /* (287) nm ::= ID|INDEXED */
- { 152, -1 }, /* (288) nm ::= STRING */
- { 152, -1 }, /* (289) nm ::= JOIN_KW */
- { 166, -1 }, /* (290) typetoken ::= typename */
- { 167, -1 }, /* (291) typename ::= ID|STRING */
- { 168, -1 }, /* (292) signed ::= plus_num */
- { 168, -1 }, /* (293) signed ::= minus_num */
- { 165, -2 }, /* (294) carglist ::= carglist ccons */
- { 165, 0 }, /* (295) carglist ::= */
- { 172, -2 }, /* (296) ccons ::= NULL onconf */
- { 161, -2 }, /* (297) conslist_opt ::= COMMA conslist */
- { 184, -3 }, /* (298) conslist ::= conslist tconscomma tcons */
- { 184, -1 }, /* (299) conslist ::= tcons */
- { 185, 0 }, /* (300) tconscomma ::= */
- { 189, -1 }, /* (301) defer_subclause_opt ::= defer_subclause */
- { 191, -1 }, /* (302) resolvetype ::= raisetype */
- { 195, -1 }, /* (303) selectnowith ::= oneselect */
- { 196, -1 }, /* (304) oneselect ::= values */
- { 210, -2 }, /* (305) sclp ::= selcollist COMMA */
- { 211, -1 }, /* (306) as ::= ID|STRING */
- { 174, -1 }, /* (307) expr ::= term */
- { 222, -1 }, /* (308) likeop ::= LIKE_KW|MATCH */
- { 209, -1 }, /* (309) exprlist ::= nexprlist */
- { 231, -1 }, /* (310) nmnum ::= plus_num */
- { 231, -1 }, /* (311) nmnum ::= nm */
- { 231, -1 }, /* (312) nmnum ::= ON */
- { 231, -1 }, /* (313) nmnum ::= DELETE */
- { 231, -1 }, /* (314) nmnum ::= DEFAULT */
- { 169, -1 }, /* (315) plus_num ::= INTEGER|FLOAT */
- { 236, 0 }, /* (316) foreach_clause ::= */
- { 236, -3 }, /* (317) foreach_clause ::= FOR EACH ROW */
- { 239, -1 }, /* (318) trnm ::= nm */
- { 240, 0 }, /* (319) tridxby ::= */
- { 241, -1 }, /* (320) database_kw_opt ::= DATABASE */
- { 241, 0 }, /* (321) database_kw_opt ::= */
- { 244, 0 }, /* (322) kwcolumn_opt ::= */
- { 244, -1 }, /* (323) kwcolumn_opt ::= COLUMNKW */
- { 246, -1 }, /* (324) vtabarglist ::= vtabarg */
- { 246, -3 }, /* (325) vtabarglist ::= vtabarglist COMMA vtabarg */
- { 247, -2 }, /* (326) vtabarg ::= vtabarg vtabargtoken */
- { 250, 0 }, /* (327) anylist ::= */
- { 250, -4 }, /* (328) anylist ::= anylist LP anylist RP */
- { 250, -2 }, /* (329) anylist ::= anylist ANY */
+ { 163, -3 }, /* (80) select ::= WITH wqlist selectnowith */
+ { 163, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */
+ { 163, -1 }, /* (82) select ::= selectnowith */
+ { 195, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */
+ { 198, -1 }, /* (84) multiselect_op ::= UNION */
+ { 198, -2 }, /* (85) multiselect_op ::= UNION ALL */
+ { 198, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */
+ { 196, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ { 207, -4 }, /* (88) values ::= VALUES LP nexprlist RP */
+ { 207, -5 }, /* (89) values ::= values COMMA LP exprlist RP */
+ { 199, -1 }, /* (90) distinct ::= DISTINCT */
+ { 199, -1 }, /* (91) distinct ::= ALL */
+ { 199, 0 }, /* (92) distinct ::= */
+ { 210, 0 }, /* (93) sclp ::= */
+ { 200, -5 }, /* (94) selcollist ::= sclp scanpt expr scanpt as */
+ { 200, -3 }, /* (95) selcollist ::= sclp scanpt STAR */
+ { 200, -5 }, /* (96) selcollist ::= sclp scanpt nm DOT STAR */
+ { 211, -2 }, /* (97) as ::= AS nm */
+ { 211, 0 }, /* (98) as ::= */
+ { 201, 0 }, /* (99) from ::= */
+ { 201, -2 }, /* (100) from ::= FROM seltablist */
+ { 213, -2 }, /* (101) stl_prefix ::= seltablist joinop */
+ { 213, 0 }, /* (102) stl_prefix ::= */
+ { 212, -7 }, /* (103) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ { 212, -9 }, /* (104) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ { 212, -7 }, /* (105) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ { 212, -7 }, /* (106) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ { 159, 0 }, /* (107) dbnm ::= */
+ { 159, -2 }, /* (108) dbnm ::= DOT nm */
+ { 194, -1 }, /* (109) fullname ::= nm */
+ { 194, -3 }, /* (110) fullname ::= nm DOT nm */
+ { 214, -1 }, /* (111) joinop ::= COMMA|JOIN */
+ { 214, -2 }, /* (112) joinop ::= JOIN_KW JOIN */
+ { 214, -3 }, /* (113) joinop ::= JOIN_KW nm JOIN */
+ { 214, -4 }, /* (114) joinop ::= JOIN_KW nm nm JOIN */
+ { 216, -2 }, /* (115) on_opt ::= ON expr */
+ { 216, 0 }, /* (116) on_opt ::= */
+ { 215, 0 }, /* (117) indexed_opt ::= */
+ { 215, -3 }, /* (118) indexed_opt ::= INDEXED BY nm */
+ { 215, -2 }, /* (119) indexed_opt ::= NOT INDEXED */
+ { 217, -4 }, /* (120) using_opt ::= USING LP idlist RP */
+ { 217, 0 }, /* (121) using_opt ::= */
+ { 205, 0 }, /* (122) orderby_opt ::= */
+ { 205, -3 }, /* (123) orderby_opt ::= ORDER BY sortlist */
+ { 187, -4 }, /* (124) sortlist ::= sortlist COMMA expr sortorder */
+ { 187, -2 }, /* (125) sortlist ::= expr sortorder */
+ { 176, -1 }, /* (126) sortorder ::= ASC */
+ { 176, -1 }, /* (127) sortorder ::= DESC */
+ { 176, 0 }, /* (128) sortorder ::= */
+ { 203, 0 }, /* (129) groupby_opt ::= */
+ { 203, -3 }, /* (130) groupby_opt ::= GROUP BY nexprlist */
+ { 204, 0 }, /* (131) having_opt ::= */
+ { 204, -2 }, /* (132) having_opt ::= HAVING expr */
+ { 206, 0 }, /* (133) limit_opt ::= */
+ { 206, -2 }, /* (134) limit_opt ::= LIMIT expr */
+ { 206, -4 }, /* (135) limit_opt ::= LIMIT expr OFFSET expr */
+ { 206, -4 }, /* (136) limit_opt ::= LIMIT expr COMMA expr */
+ { 149, -6 }, /* (137) cmd ::= with DELETE FROM fullname indexed_opt where_opt */
+ { 202, 0 }, /* (138) where_opt ::= */
+ { 202, -2 }, /* (139) where_opt ::= WHERE expr */
+ { 149, -8 }, /* (140) cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
+ { 220, -5 }, /* (141) setlist ::= setlist COMMA nm EQ expr */
+ { 220, -7 }, /* (142) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ { 220, -3 }, /* (143) setlist ::= nm EQ expr */
+ { 220, -5 }, /* (144) setlist ::= LP idlist RP EQ expr */
+ { 149, -6 }, /* (145) cmd ::= with insert_cmd INTO fullname idlist_opt select */
+ { 149, -7 }, /* (146) cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
+ { 221, -2 }, /* (147) insert_cmd ::= INSERT orconf */
+ { 221, -1 }, /* (148) insert_cmd ::= REPLACE */
+ { 222, 0 }, /* (149) idlist_opt ::= */
+ { 222, -3 }, /* (150) idlist_opt ::= LP idlist RP */
+ { 218, -3 }, /* (151) idlist ::= idlist COMMA nm */
+ { 218, -1 }, /* (152) idlist ::= nm */
+ { 174, -3 }, /* (153) expr ::= LP expr RP */
+ { 174, -1 }, /* (154) expr ::= ID|INDEXED */
+ { 174, -1 }, /* (155) expr ::= JOIN_KW */
+ { 174, -3 }, /* (156) expr ::= nm DOT nm */
+ { 174, -5 }, /* (157) expr ::= nm DOT nm DOT nm */
+ { 173, -1 }, /* (158) term ::= NULL|FLOAT|BLOB */
+ { 173, -1 }, /* (159) term ::= STRING */
+ { 173, -1 }, /* (160) term ::= INTEGER */
+ { 174, -1 }, /* (161) expr ::= VARIABLE */
+ { 174, -3 }, /* (162) expr ::= expr COLLATE ID|STRING */
+ { 174, -6 }, /* (163) expr ::= CAST LP expr AS typetoken RP */
+ { 174, -5 }, /* (164) expr ::= ID|INDEXED LP distinct exprlist RP */
+ { 174, -4 }, /* (165) expr ::= ID|INDEXED LP STAR RP */
+ { 173, -1 }, /* (166) term ::= CTIME_KW */
+ { 174, -5 }, /* (167) expr ::= LP nexprlist COMMA expr RP */
+ { 174, -3 }, /* (168) expr ::= expr AND expr */
+ { 174, -3 }, /* (169) expr ::= expr OR expr */
+ { 174, -3 }, /* (170) expr ::= expr LT|GT|GE|LE expr */
+ { 174, -3 }, /* (171) expr ::= expr EQ|NE expr */
+ { 174, -3 }, /* (172) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ { 174, -3 }, /* (173) expr ::= expr PLUS|MINUS expr */
+ { 174, -3 }, /* (174) expr ::= expr STAR|SLASH|REM expr */
+ { 174, -3 }, /* (175) expr ::= expr CONCAT expr */
+ { 223, -2 }, /* (176) likeop ::= NOT LIKE_KW|MATCH */
+ { 174, -3 }, /* (177) expr ::= expr likeop expr */
+ { 174, -5 }, /* (178) expr ::= expr likeop expr ESCAPE expr */
+ { 174, -2 }, /* (179) expr ::= expr ISNULL|NOTNULL */
+ { 174, -3 }, /* (180) expr ::= expr NOT NULL */
+ { 174, -3 }, /* (181) expr ::= expr IS expr */
+ { 174, -4 }, /* (182) expr ::= expr IS NOT expr */
+ { 174, -2 }, /* (183) expr ::= NOT expr */
+ { 174, -2 }, /* (184) expr ::= BITNOT expr */
+ { 174, -2 }, /* (185) expr ::= MINUS expr */
+ { 174, -2 }, /* (186) expr ::= PLUS expr */
+ { 224, -1 }, /* (187) between_op ::= BETWEEN */
+ { 224, -2 }, /* (188) between_op ::= NOT BETWEEN */
+ { 174, -5 }, /* (189) expr ::= expr between_op expr AND expr */
+ { 225, -1 }, /* (190) in_op ::= IN */
+ { 225, -2 }, /* (191) in_op ::= NOT IN */
+ { 174, -5 }, /* (192) expr ::= expr in_op LP exprlist RP */
+ { 174, -3 }, /* (193) expr ::= LP select RP */
+ { 174, -5 }, /* (194) expr ::= expr in_op LP select RP */
+ { 174, -5 }, /* (195) expr ::= expr in_op nm dbnm paren_exprlist */
+ { 174, -4 }, /* (196) expr ::= EXISTS LP select RP */
+ { 174, -5 }, /* (197) expr ::= CASE case_operand case_exprlist case_else END */
+ { 228, -5 }, /* (198) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ { 228, -4 }, /* (199) case_exprlist ::= WHEN expr THEN expr */
+ { 229, -2 }, /* (200) case_else ::= ELSE expr */
+ { 229, 0 }, /* (201) case_else ::= */
+ { 227, -1 }, /* (202) case_operand ::= expr */
+ { 227, 0 }, /* (203) case_operand ::= */
+ { 209, 0 }, /* (204) exprlist ::= */
+ { 208, -3 }, /* (205) nexprlist ::= nexprlist COMMA expr */
+ { 208, -1 }, /* (206) nexprlist ::= expr */
+ { 226, 0 }, /* (207) paren_exprlist ::= */
+ { 226, -3 }, /* (208) paren_exprlist ::= LP exprlist RP */
+ { 149, -12 }, /* (209) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ { 230, -1 }, /* (210) uniqueflag ::= UNIQUE */
+ { 230, 0 }, /* (211) uniqueflag ::= */
+ { 178, 0 }, /* (212) eidlist_opt ::= */
+ { 178, -3 }, /* (213) eidlist_opt ::= LP eidlist RP */
+ { 188, -5 }, /* (214) eidlist ::= eidlist COMMA nm collate sortorder */
+ { 188, -3 }, /* (215) eidlist ::= nm collate sortorder */
+ { 231, 0 }, /* (216) collate ::= */
+ { 231, -2 }, /* (217) collate ::= COLLATE ID|STRING */
+ { 149, -4 }, /* (218) cmd ::= DROP INDEX ifexists fullname */
+ { 149, -1 }, /* (219) cmd ::= VACUUM */
+ { 149, -2 }, /* (220) cmd ::= VACUUM nm */
+ { 149, -3 }, /* (221) cmd ::= PRAGMA nm dbnm */
+ { 149, -5 }, /* (222) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ { 149, -6 }, /* (223) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ { 149, -5 }, /* (224) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ { 149, -6 }, /* (225) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ { 169, -2 }, /* (226) plus_num ::= PLUS INTEGER|FLOAT */
+ { 170, -2 }, /* (227) minus_num ::= MINUS INTEGER|FLOAT */
+ { 149, -5 }, /* (228) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ { 233, -11 }, /* (229) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ { 235, -1 }, /* (230) trigger_time ::= BEFORE|AFTER */
+ { 235, -2 }, /* (231) trigger_time ::= INSTEAD OF */
+ { 235, 0 }, /* (232) trigger_time ::= */
+ { 236, -1 }, /* (233) trigger_event ::= DELETE|INSERT */
+ { 236, -1 }, /* (234) trigger_event ::= UPDATE */
+ { 236, -3 }, /* (235) trigger_event ::= UPDATE OF idlist */
+ { 238, 0 }, /* (236) when_clause ::= */
+ { 238, -2 }, /* (237) when_clause ::= WHEN expr */
+ { 234, -3 }, /* (238) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ { 234, -2 }, /* (239) trigger_cmd_list ::= trigger_cmd SEMI */
+ { 240, -3 }, /* (240) trnm ::= nm DOT nm */
+ { 241, -3 }, /* (241) tridxby ::= INDEXED BY nm */
+ { 241, -2 }, /* (242) tridxby ::= NOT INDEXED */
+ { 239, -8 }, /* (243) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ { 239, -7 }, /* (244) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */
+ { 239, -6 }, /* (245) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ { 239, -3 }, /* (246) trigger_cmd ::= scanpt select scanpt */
+ { 174, -4 }, /* (247) expr ::= RAISE LP IGNORE RP */
+ { 174, -6 }, /* (248) expr ::= RAISE LP raisetype COMMA nm RP */
+ { 192, -1 }, /* (249) raisetype ::= ROLLBACK */
+ { 192, -1 }, /* (250) raisetype ::= ABORT */
+ { 192, -1 }, /* (251) raisetype ::= FAIL */
+ { 149, -4 }, /* (252) cmd ::= DROP TRIGGER ifexists fullname */
+ { 149, -6 }, /* (253) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ { 149, -3 }, /* (254) cmd ::= DETACH database_kw_opt expr */
+ { 243, 0 }, /* (255) key_opt ::= */
+ { 243, -2 }, /* (256) key_opt ::= KEY expr */
+ { 149, -1 }, /* (257) cmd ::= REINDEX */
+ { 149, -3 }, /* (258) cmd ::= REINDEX nm dbnm */
+ { 149, -1 }, /* (259) cmd ::= ANALYZE */
+ { 149, -3 }, /* (260) cmd ::= ANALYZE nm dbnm */
+ { 149, -6 }, /* (261) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ { 149, -7 }, /* (262) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ { 244, -1 }, /* (263) add_column_fullname ::= fullname */
+ { 149, -1 }, /* (264) cmd ::= create_vtab */
+ { 149, -4 }, /* (265) cmd ::= create_vtab LP vtabarglist RP */
+ { 246, -8 }, /* (266) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ { 248, 0 }, /* (267) vtabarg ::= */
+ { 249, -1 }, /* (268) vtabargtoken ::= ANY */
+ { 249, -3 }, /* (269) vtabargtoken ::= lp anylist RP */
+ { 250, -1 }, /* (270) lp ::= LP */
+ { 219, -2 }, /* (271) with ::= WITH wqlist */
+ { 219, -3 }, /* (272) with ::= WITH RECURSIVE wqlist */
+ { 197, -6 }, /* (273) wqlist ::= nm eidlist_opt AS LP select RP */
+ { 197, -8 }, /* (274) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ { 144, -1 }, /* (275) input ::= cmdlist */
+ { 145, -2 }, /* (276) cmdlist ::= cmdlist ecmd */
+ { 145, -1 }, /* (277) cmdlist ::= ecmd */
+ { 146, -1 }, /* (278) ecmd ::= SEMI */
+ { 146, -3 }, /* (279) ecmd ::= explain cmdx SEMI */
+ { 147, 0 }, /* (280) explain ::= */
+ { 151, 0 }, /* (281) trans_opt ::= */
+ { 151, -1 }, /* (282) trans_opt ::= TRANSACTION */
+ { 151, -2 }, /* (283) trans_opt ::= TRANSACTION nm */
+ { 153, -1 }, /* (284) savepoint_opt ::= SAVEPOINT */
+ { 153, 0 }, /* (285) savepoint_opt ::= */
+ { 149, -2 }, /* (286) cmd ::= create_table create_table_args */
+ { 160, -4 }, /* (287) columnlist ::= columnlist COMMA columnname carglist */
+ { 160, -2 }, /* (288) columnlist ::= columnname carglist */
+ { 152, -1 }, /* (289) nm ::= ID|INDEXED */
+ { 152, -1 }, /* (290) nm ::= STRING */
+ { 152, -1 }, /* (291) nm ::= JOIN_KW */
+ { 166, -1 }, /* (292) typetoken ::= typename */
+ { 167, -1 }, /* (293) typename ::= ID|STRING */
+ { 168, -1 }, /* (294) signed ::= plus_num */
+ { 168, -1 }, /* (295) signed ::= minus_num */
+ { 165, -2 }, /* (296) carglist ::= carglist ccons */
+ { 165, 0 }, /* (297) carglist ::= */
+ { 172, -2 }, /* (298) ccons ::= NULL onconf */
+ { 161, -2 }, /* (299) conslist_opt ::= COMMA conslist */
+ { 184, -3 }, /* (300) conslist ::= conslist tconscomma tcons */
+ { 184, -1 }, /* (301) conslist ::= tcons */
+ { 185, 0 }, /* (302) tconscomma ::= */
+ { 189, -1 }, /* (303) defer_subclause_opt ::= defer_subclause */
+ { 191, -1 }, /* (304) resolvetype ::= raisetype */
+ { 195, -1 }, /* (305) selectnowith ::= oneselect */
+ { 196, -1 }, /* (306) oneselect ::= values */
+ { 210, -2 }, /* (307) sclp ::= selcollist COMMA */
+ { 211, -1 }, /* (308) as ::= ID|STRING */
+ { 174, -1 }, /* (309) expr ::= term */
+ { 223, -1 }, /* (310) likeop ::= LIKE_KW|MATCH */
+ { 209, -1 }, /* (311) exprlist ::= nexprlist */
+ { 232, -1 }, /* (312) nmnum ::= plus_num */
+ { 232, -1 }, /* (313) nmnum ::= nm */
+ { 232, -1 }, /* (314) nmnum ::= ON */
+ { 232, -1 }, /* (315) nmnum ::= DELETE */
+ { 232, -1 }, /* (316) nmnum ::= DEFAULT */
+ { 169, -1 }, /* (317) plus_num ::= INTEGER|FLOAT */
+ { 237, 0 }, /* (318) foreach_clause ::= */
+ { 237, -3 }, /* (319) foreach_clause ::= FOR EACH ROW */
+ { 240, -1 }, /* (320) trnm ::= nm */
+ { 241, 0 }, /* (321) tridxby ::= */
+ { 242, -1 }, /* (322) database_kw_opt ::= DATABASE */
+ { 242, 0 }, /* (323) database_kw_opt ::= */
+ { 245, 0 }, /* (324) kwcolumn_opt ::= */
+ { 245, -1 }, /* (325) kwcolumn_opt ::= COLUMNKW */
+ { 247, -1 }, /* (326) vtabarglist ::= vtabarg */
+ { 247, -3 }, /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */
+ { 248, -2 }, /* (328) vtabarg ::= vtabarg vtabargtoken */
+ { 251, 0 }, /* (329) anylist ::= */
+ { 251, -4 }, /* (330) anylist ::= anylist LP anylist RP */
+ { 251, -2 }, /* (331) anylist ::= anylist ANY */
+ { 219, 0 }, /* (332) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -140630,8 +142312,8 @@ static void yy_reduce(
case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57);
case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67);
case 76: /* ifexists ::= */ yytestcase(yyruleno==76);
- case 90: /* distinct ::= */ yytestcase(yyruleno==90);
- case 213: /* collate ::= */ yytestcase(yyruleno==213);
+ case 92: /* distinct ::= */ yytestcase(yyruleno==92);
+ case 216: /* collate ::= */ yytestcase(yyruleno==216);
{yymsp[1].minor.yy4 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
@@ -140667,7 +142349,7 @@ static void yy_reduce(
break;
case 24: /* typetoken ::= */
case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60);
- case 96: /* as ::= */ yytestcase(yyruleno==96);
+ case 98: /* as ::= */ yytestcase(yyruleno==98);
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
break;
case 25: /* typetoken ::= typename LP signed RP */
@@ -140711,6 +142393,10 @@ static void yy_reduce(
case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */
{
Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0);
+ if( p ){
+ sqlite3ExprIdToTrueFalse(p);
+ testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
+ }
sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n);
}
break;
@@ -140774,14 +142460,14 @@ static void yy_reduce(
break;
case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71);
- case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144);
+ case 147: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==147);
{yymsp[-1].minor.yy4 = yymsp[0].minor.yy4;}
break;
case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75);
- case 185: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==185);
- case 188: /* in_op ::= NOT IN */ yytestcase(yyruleno==188);
- case 214: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==214);
+ case 188: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==188);
+ case 191: /* in_op ::= NOT IN */ yytestcase(yyruleno==191);
+ case 217: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==217);
{yymsp[-1].minor.yy4 = 1;}
break;
case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
@@ -140817,7 +142503,7 @@ static void yy_reduce(
{yymsp[0].minor.yy4 = OE_Ignore;}
break;
case 73: /* resolvetype ::= REPLACE */
- case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145);
+ case 148: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==148);
{yymsp[0].minor.yy4 = OE_Replace;}
break;
case 74: /* cmd ::= DROP TABLE ifexists fullname */
@@ -140842,7 +142528,19 @@ static void yy_reduce(
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387);
}
break;
- case 80: /* select ::= with selectnowith */
+ case 80: /* select ::= WITH wqlist selectnowith */
+{
+ Select *p = yymsp[0].minor.yy387;
+ if( p ){
+ p->pWith = yymsp[-1].minor.yy451;
+ parserDoubleLinkSelect(pParse, p);
+ }else{
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451);
+ }
+ yymsp[-2].minor.yy387 = p;
+}
+ break;
+ case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */
{
Select *p = yymsp[0].minor.yy387;
if( p ){
@@ -140851,10 +142549,19 @@ static void yy_reduce(
}else{
sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451);
}
- yymsp[-1].minor.yy387 = p; /*A-overwrites-W*/
+ yymsp[-3].minor.yy387 = p;
+}
+ break;
+ case 82: /* select ::= selectnowith */
+{
+ Select *p = yymsp[0].minor.yy387;
+ if( p ){
+ parserDoubleLinkSelect(pParse, p);
+ }
+ yymsp[0].minor.yy387 = p; /*A-overwrites-X*/
}
break;
- case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */
+ case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
Select *pRhs = yymsp[0].minor.yy387;
Select *pLhs = yymsp[-2].minor.yy387;
@@ -140878,14 +142585,14 @@ static void yy_reduce(
yymsp[-2].minor.yy387 = pRhs;
}
break;
- case 82: /* multiselect_op ::= UNION */
- case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84);
+ case 84: /* multiselect_op ::= UNION */
+ case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86);
{yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-OP*/}
break;
- case 83: /* multiselect_op ::= UNION ALL */
+ case 85: /* multiselect_op ::= UNION ALL */
{yymsp[-1].minor.yy4 = TK_ALL;}
break;
- case 85: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
#if SELECTTRACE_ENABLED
Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
@@ -140904,8 +142611,7 @@ static void yy_reduce(
if( yymsp[-8].minor.yy387!=0 ){
const char *z = s.z+6;
int i;
- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName, "#%d",
- ++pParse->nSelect);
+ sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName,"#%d",++pParse->nSelect);
while( z[0]==' ' ) z++;
if( z[0]=='/' && z[1]=='*' ){
z += 2;
@@ -140917,12 +142623,12 @@ static void yy_reduce(
#endif /* SELECTRACE_ENABLED */
}
break;
- case 86: /* values ::= VALUES LP nexprlist RP */
+ case 88: /* values ::= VALUES LP nexprlist RP */
{
yymsp[-3].minor.yy387 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0);
}
break;
- case 87: /* values ::= values COMMA LP exprlist RP */
+ case 89: /* values ::= values COMMA LP exprlist RP */
{
Select *pRight, *pLeft = yymsp[-4].minor.yy387;
pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0);
@@ -140936,34 +142642,34 @@ static void yy_reduce(
}
}
break;
- case 88: /* distinct ::= DISTINCT */
+ case 90: /* distinct ::= DISTINCT */
{yymsp[0].minor.yy4 = SF_Distinct;}
break;
- case 89: /* distinct ::= ALL */
+ case 91: /* distinct ::= ALL */
{yymsp[0].minor.yy4 = SF_All;}
break;
- case 91: /* sclp ::= */
- case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119);
- case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126);
- case 201: /* exprlist ::= */ yytestcase(yyruleno==201);
- case 204: /* paren_exprlist ::= */ yytestcase(yyruleno==204);
- case 209: /* eidlist_opt ::= */ yytestcase(yyruleno==209);
+ case 93: /* sclp ::= */
+ case 122: /* orderby_opt ::= */ yytestcase(yyruleno==122);
+ case 129: /* groupby_opt ::= */ yytestcase(yyruleno==129);
+ case 204: /* exprlist ::= */ yytestcase(yyruleno==204);
+ case 207: /* paren_exprlist ::= */ yytestcase(yyruleno==207);
+ case 212: /* eidlist_opt ::= */ yytestcase(yyruleno==212);
{yymsp[1].minor.yy322 = 0;}
break;
- case 92: /* selcollist ::= sclp scanpt expr scanpt as */
+ case 94: /* selcollist ::= sclp scanpt expr scanpt as */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy314);
if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1);
sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy336,yymsp[-1].minor.yy336);
}
break;
- case 93: /* selcollist ::= sclp scanpt STAR */
+ case 95: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p);
}
break;
- case 94: /* selcollist ::= sclp scanpt nm DOT STAR */
+ case 96: /* selcollist ::= sclp scanpt nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
@@ -140971,47 +142677,47 @@ static void yy_reduce(
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot);
}
break;
- case 95: /* as ::= AS nm */
- case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106);
- case 223: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==223);
- case 224: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==224);
+ case 97: /* as ::= AS nm */
+ case 108: /* dbnm ::= DOT nm */ yytestcase(yyruleno==108);
+ case 226: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==226);
+ case 227: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==227);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 97: /* from ::= */
+ case 99: /* from ::= */
{yymsp[1].minor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy259));}
break;
- case 98: /* from ::= FROM seltablist */
+ case 100: /* from ::= FROM seltablist */
{
yymsp[-1].minor.yy259 = yymsp[0].minor.yy259;
sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy259);
}
break;
- case 99: /* stl_prefix ::= seltablist joinop */
+ case 101: /* stl_prefix ::= seltablist joinop */
{
if( ALWAYS(yymsp[-1].minor.yy259 && yymsp[-1].minor.yy259->nSrc>0) ) yymsp[-1].minor.yy259->a[yymsp[-1].minor.yy259->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy4;
}
break;
- case 100: /* stl_prefix ::= */
+ case 102: /* stl_prefix ::= */
{yymsp[1].minor.yy259 = 0;}
break;
- case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 103: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy259, &yymsp[-2].minor.yy0);
}
break;
- case 102: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ case 104: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
yymsp[-8].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy259,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy259, yymsp[-4].minor.yy322);
}
break;
- case 103: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 105: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
}
break;
- case 104: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 106: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){
yymsp[-6].minor.yy259 = yymsp[-4].minor.yy259;
@@ -141035,153 +142741,152 @@ static void yy_reduce(
}
}
break;
- case 105: /* dbnm ::= */
- case 114: /* indexed_opt ::= */ yytestcase(yyruleno==114);
+ case 107: /* dbnm ::= */
+ case 117: /* indexed_opt ::= */ yytestcase(yyruleno==117);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
- case 107: /* fullname ::= nm dbnm */
-{yymsp[-1].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 109: /* fullname ::= nm */
+{yymsp[0].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+ break;
+ case 110: /* fullname ::= nm DOT nm */
+{yymsp[-2].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 108: /* joinop ::= COMMA|JOIN */
+ case 111: /* joinop ::= COMMA|JOIN */
{ yymsp[0].minor.yy4 = JT_INNER; }
break;
- case 109: /* joinop ::= JOIN_KW JOIN */
+ case 112: /* joinop ::= JOIN_KW JOIN */
{yymsp[-1].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
- case 110: /* joinop ::= JOIN_KW nm JOIN */
+ case 113: /* joinop ::= JOIN_KW nm JOIN */
{yymsp[-2].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
- case 111: /* joinop ::= JOIN_KW nm nm JOIN */
+ case 114: /* joinop ::= JOIN_KW nm nm JOIN */
{yymsp[-3].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
- case 112: /* on_opt ::= ON expr */
- case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129);
- case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136);
- case 197: /* case_else ::= ELSE expr */ yytestcase(yyruleno==197);
+ case 115: /* on_opt ::= ON expr */
+ case 132: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==132);
+ case 139: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==139);
+ case 200: /* case_else ::= ELSE expr */ yytestcase(yyruleno==200);
{yymsp[-1].minor.yy314 = yymsp[0].minor.yy314;}
break;
- case 113: /* on_opt ::= */
- case 128: /* having_opt ::= */ yytestcase(yyruleno==128);
- case 130: /* limit_opt ::= */ yytestcase(yyruleno==130);
- case 135: /* where_opt ::= */ yytestcase(yyruleno==135);
- case 198: /* case_else ::= */ yytestcase(yyruleno==198);
- case 200: /* case_operand ::= */ yytestcase(yyruleno==200);
+ case 116: /* on_opt ::= */
+ case 131: /* having_opt ::= */ yytestcase(yyruleno==131);
+ case 133: /* limit_opt ::= */ yytestcase(yyruleno==133);
+ case 138: /* where_opt ::= */ yytestcase(yyruleno==138);
+ case 201: /* case_else ::= */ yytestcase(yyruleno==201);
+ case 203: /* case_operand ::= */ yytestcase(yyruleno==203);
{yymsp[1].minor.yy314 = 0;}
break;
- case 115: /* indexed_opt ::= INDEXED BY nm */
+ case 118: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 116: /* indexed_opt ::= NOT INDEXED */
+ case 119: /* indexed_opt ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
- case 117: /* using_opt ::= USING LP idlist RP */
+ case 120: /* using_opt ::= USING LP idlist RP */
{yymsp[-3].minor.yy384 = yymsp[-1].minor.yy384;}
break;
- case 118: /* using_opt ::= */
- case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146);
+ case 121: /* using_opt ::= */
+ case 149: /* idlist_opt ::= */ yytestcase(yyruleno==149);
{yymsp[1].minor.yy384 = 0;}
break;
- case 120: /* orderby_opt ::= ORDER BY sortlist */
- case 127: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==127);
+ case 123: /* orderby_opt ::= ORDER BY sortlist */
+ case 130: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==130);
{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;}
break;
- case 121: /* sortlist ::= sortlist COMMA expr sortorder */
+ case 124: /* sortlist ::= sortlist COMMA expr sortorder */
{
yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy314);
sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy322,yymsp[0].minor.yy4);
}
break;
- case 122: /* sortlist ::= expr sortorder */
+ case 125: /* sortlist ::= expr sortorder */
{
yymsp[-1].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy314); /*A-overwrites-Y*/
sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy322,yymsp[0].minor.yy4);
}
break;
- case 123: /* sortorder ::= ASC */
+ case 126: /* sortorder ::= ASC */
{yymsp[0].minor.yy4 = SQLITE_SO_ASC;}
break;
- case 124: /* sortorder ::= DESC */
+ case 127: /* sortorder ::= DESC */
{yymsp[0].minor.yy4 = SQLITE_SO_DESC;}
break;
- case 125: /* sortorder ::= */
+ case 128: /* sortorder ::= */
{yymsp[1].minor.yy4 = SQLITE_SO_UNDEFINED;}
break;
- case 131: /* limit_opt ::= LIMIT expr */
+ case 134: /* limit_opt ::= LIMIT expr */
{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,0);}
break;
- case 132: /* limit_opt ::= LIMIT expr OFFSET expr */
+ case 135: /* limit_opt ::= LIMIT expr OFFSET expr */
{yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);}
break;
- case 133: /* limit_opt ::= LIMIT expr COMMA expr */
+ case 136: /* limit_opt ::= LIMIT expr COMMA expr */
{yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,yymsp[-2].minor.yy314);}
break;
- case 134: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
+ case 137: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
{
- sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1);
sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0);
sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314,0,0);
}
break;
- case 137: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
+ case 140: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
- sqlite3WithPush(pParse, yymsp[-7].minor.yy451, 1);
sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0);
sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list");
sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy4,0,0);
}
break;
- case 138: /* setlist ::= setlist COMMA nm EQ expr */
+ case 141: /* setlist ::= setlist COMMA nm EQ expr */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy314);
sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1);
}
break;
- case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 142: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
yymsp[-6].minor.yy322 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy384, yymsp[0].minor.yy314);
}
break;
- case 140: /* setlist ::= nm EQ expr */
+ case 143: /* setlist ::= nm EQ expr */
{
yylhsminor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy314);
sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1);
}
yymsp[-2].minor.yy322 = yylhsminor.yy322;
break;
- case 141: /* setlist ::= LP idlist RP EQ expr */
+ case 144: /* setlist ::= LP idlist RP EQ expr */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy384, yymsp[0].minor.yy314);
}
break;
- case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
+ case 145: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
{
- sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1);
sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy4);
}
break;
- case 143: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
+ case 146: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
{
- sqlite3WithPush(pParse, yymsp[-6].minor.yy451, 1);
sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy4);
}
break;
- case 147: /* idlist_opt ::= LP idlist RP */
+ case 150: /* idlist_opt ::= LP idlist RP */
{yymsp[-2].minor.yy384 = yymsp[-1].minor.yy384;}
break;
- case 148: /* idlist ::= idlist COMMA nm */
+ case 151: /* idlist ::= idlist COMMA nm */
{yymsp[-2].minor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);}
break;
- case 149: /* idlist ::= nm */
+ case 152: /* idlist ::= nm */
{yymsp[0].minor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
- case 150: /* expr ::= LP expr RP */
+ case 153: /* expr ::= LP expr RP */
{yymsp[-2].minor.yy314 = yymsp[-1].minor.yy314;}
break;
- case 151: /* expr ::= ID|INDEXED */
- case 152: /* expr ::= JOIN_KW */ yytestcase(yyruleno==152);
+ case 154: /* expr ::= ID|INDEXED */
+ case 155: /* expr ::= JOIN_KW */ yytestcase(yyruleno==155);
{yymsp[0].minor.yy314=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 153: /* expr ::= nm DOT nm */
+ case 156: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
@@ -141189,7 +142894,7 @@ static void yy_reduce(
}
yymsp[-2].minor.yy314 = yylhsminor.yy314;
break;
- case 154: /* expr ::= nm DOT nm DOT nm */
+ case 157: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
@@ -141199,17 +142904,17 @@ static void yy_reduce(
}
yymsp[-4].minor.yy314 = yylhsminor.yy314;
break;
- case 155: /* term ::= NULL|FLOAT|BLOB */
- case 156: /* term ::= STRING */ yytestcase(yyruleno==156);
+ case 158: /* term ::= NULL|FLOAT|BLOB */
+ case 159: /* term ::= STRING */ yytestcase(yyruleno==159);
{yymsp[0].minor.yy314=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 157: /* term ::= INTEGER */
+ case 160: /* term ::= INTEGER */
{
yylhsminor.yy314 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
yymsp[0].minor.yy314 = yylhsminor.yy314;
break;
- case 158: /* expr ::= VARIABLE */
+ case 161: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
@@ -141231,18 +142936,18 @@ static void yy_reduce(
}
}
break;
- case 159: /* expr ::= expr COLLATE ID|STRING */
+ case 162: /* expr ::= expr COLLATE ID|STRING */
{
yymsp[-2].minor.yy314 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy314, &yymsp[0].minor.yy0, 1);
}
break;
- case 160: /* expr ::= CAST LP expr AS typetoken RP */
+ case 163: /* expr ::= CAST LP expr AS typetoken RP */
{
yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy314, yymsp[-3].minor.yy314, 0);
}
break;
- case 161: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 164: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
@@ -141254,19 +142959,19 @@ static void yy_reduce(
}
yymsp[-4].minor.yy314 = yylhsminor.yy314;
break;
- case 162: /* expr ::= ID|INDEXED LP STAR RP */
+ case 165: /* expr ::= ID|INDEXED LP STAR RP */
{
yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
}
yymsp[-3].minor.yy314 = yylhsminor.yy314;
break;
- case 163: /* term ::= CTIME_KW */
+ case 166: /* term ::= CTIME_KW */
{
yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
}
yymsp[0].minor.yy314 = yylhsminor.yy314;
break;
- case 164: /* expr ::= LP nexprlist COMMA expr RP */
+ case 167: /* expr ::= LP nexprlist COMMA expr RP */
{
ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy314);
yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
@@ -141277,20 +142982,20 @@ static void yy_reduce(
}
}
break;
- case 165: /* expr ::= expr AND expr */
- case 166: /* expr ::= expr OR expr */ yytestcase(yyruleno==166);
- case 167: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==167);
- case 168: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==168);
- case 169: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==169);
- case 170: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==170);
- case 171: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==171);
- case 172: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==172);
+ case 168: /* expr ::= expr AND expr */
+ case 169: /* expr ::= expr OR expr */ yytestcase(yyruleno==169);
+ case 170: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==170);
+ case 171: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==171);
+ case 172: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==172);
+ case 173: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==173);
+ case 174: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==174);
+ case 175: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==175);
{yymsp[-2].minor.yy314=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);}
break;
- case 173: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 176: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
- case 174: /* expr ::= expr likeop expr */
+ case 177: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
@@ -141302,7 +143007,7 @@ static void yy_reduce(
if( yymsp[-2].minor.yy314 ) yymsp[-2].minor.yy314->flags |= EP_InfixFunc;
}
break;
- case 175: /* expr ::= expr likeop expr ESCAPE expr */
+ case 178: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
@@ -141315,39 +143020,39 @@ static void yy_reduce(
if( yymsp[-4].minor.yy314 ) yymsp[-4].minor.yy314->flags |= EP_InfixFunc;
}
break;
- case 176: /* expr ::= expr ISNULL|NOTNULL */
+ case 179: /* expr ::= expr ISNULL|NOTNULL */
{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy314,0);}
break;
- case 177: /* expr ::= expr NOT NULL */
+ case 180: /* expr ::= expr NOT NULL */
{yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy314,0);}
break;
- case 178: /* expr ::= expr IS expr */
+ case 181: /* expr ::= expr IS expr */
{
yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-2].minor.yy314, TK_ISNULL);
}
break;
- case 179: /* expr ::= expr IS NOT expr */
+ case 182: /* expr ::= expr IS NOT expr */
{
yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy314,yymsp[0].minor.yy314);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-3].minor.yy314, TK_NOTNULL);
}
break;
- case 180: /* expr ::= NOT expr */
- case 181: /* expr ::= BITNOT expr */ yytestcase(yyruleno==181);
+ case 183: /* expr ::= NOT expr */
+ case 184: /* expr ::= BITNOT expr */ yytestcase(yyruleno==184);
{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy314, 0);/*A-overwrites-B*/}
break;
- case 182: /* expr ::= MINUS expr */
+ case 185: /* expr ::= MINUS expr */
{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy314, 0);}
break;
- case 183: /* expr ::= PLUS expr */
+ case 186: /* expr ::= PLUS expr */
{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy314, 0);}
break;
- case 184: /* between_op ::= BETWEEN */
- case 187: /* in_op ::= IN */ yytestcase(yyruleno==187);
+ case 187: /* between_op ::= BETWEEN */
+ case 190: /* in_op ::= IN */ yytestcase(yyruleno==190);
{yymsp[0].minor.yy4 = 0;}
break;
- case 186: /* expr ::= expr between_op expr AND expr */
+ case 189: /* expr ::= expr between_op expr AND expr */
{
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy314);
@@ -141360,7 +143065,7 @@ static void yy_reduce(
if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0);
}
break;
- case 189: /* expr ::= expr in_op LP exprlist RP */
+ case 192: /* expr ::= expr in_op LP exprlist RP */
{
if( yymsp[-1].minor.yy322==0 ){
/* Expressions of the form
@@ -141412,20 +143117,20 @@ static void yy_reduce(
}
}
break;
- case 190: /* expr ::= LP select RP */
+ case 193: /* expr ::= LP select RP */
{
yymsp[-2].minor.yy314 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy314, yymsp[-1].minor.yy387);
}
break;
- case 191: /* expr ::= expr in_op LP select RP */
+ case 194: /* expr ::= expr in_op LP select RP */
{
yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy314, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy314, yymsp[-1].minor.yy387);
if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0);
}
break;
- case 192: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 195: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
@@ -141435,14 +143140,14 @@ static void yy_reduce(
if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0);
}
break;
- case 193: /* expr ::= EXISTS LP select RP */
+ case 196: /* expr ::= EXISTS LP select RP */
{
Expr *p;
p = yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy387);
}
break;
- case 194: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 197: /* expr ::= CASE case_operand case_exprlist case_else END */
{
yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0);
if( yymsp[-4].minor.yy314 ){
@@ -141454,80 +143159,80 @@ static void yy_reduce(
}
}
break;
- case 195: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 198: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy314);
yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy314);
}
break;
- case 196: /* case_exprlist ::= WHEN expr THEN expr */
+ case 199: /* case_exprlist ::= WHEN expr THEN expr */
{
yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314);
yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy314);
}
break;
- case 199: /* case_operand ::= expr */
+ case 202: /* case_operand ::= expr */
{yymsp[0].minor.yy314 = yymsp[0].minor.yy314; /*A-overwrites-X*/}
break;
- case 202: /* nexprlist ::= nexprlist COMMA expr */
+ case 205: /* nexprlist ::= nexprlist COMMA expr */
{yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy314);}
break;
- case 203: /* nexprlist ::= expr */
+ case 206: /* nexprlist ::= expr */
{yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy314); /*A-overwrites-Y*/}
break;
- case 205: /* paren_exprlist ::= LP exprlist RP */
- case 210: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==210);
+ case 208: /* paren_exprlist ::= LP exprlist RP */
+ case 213: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==213);
{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;}
break;
- case 206: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 209: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4,
&yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4, SQLITE_IDXTYPE_APPDEF);
}
break;
- case 207: /* uniqueflag ::= UNIQUE */
- case 247: /* raisetype ::= ABORT */ yytestcase(yyruleno==247);
+ case 210: /* uniqueflag ::= UNIQUE */
+ case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250);
{yymsp[0].minor.yy4 = OE_Abort;}
break;
- case 208: /* uniqueflag ::= */
+ case 211: /* uniqueflag ::= */
{yymsp[1].minor.yy4 = OE_None;}
break;
- case 211: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 214: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4);
}
break;
- case 212: /* eidlist ::= nm collate sortorder */
+ case 215: /* eidlist ::= nm collate sortorder */
{
yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); /*A-overwrites-Y*/
}
break;
- case 215: /* cmd ::= DROP INDEX ifexists fullname */
+ case 218: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);}
break;
- case 216: /* cmd ::= VACUUM */
+ case 219: /* cmd ::= VACUUM */
{sqlite3Vacuum(pParse,0);}
break;
- case 217: /* cmd ::= VACUUM nm */
+ case 220: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);}
break;
- case 218: /* cmd ::= PRAGMA nm dbnm */
+ case 221: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 219: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 222: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 220: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 223: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 221: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 224: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 222: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 225: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 225: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 228: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
@@ -141535,50 +143240,50 @@ static void yy_reduce(
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all);
}
break;
- case 226: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 229: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 227: /* trigger_time ::= BEFORE|AFTER */
+ case 230: /* trigger_time ::= BEFORE|AFTER */
{ yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 228: /* trigger_time ::= INSTEAD OF */
+ case 231: /* trigger_time ::= INSTEAD OF */
{ yymsp[-1].minor.yy4 = TK_INSTEAD;}
break;
- case 229: /* trigger_time ::= */
+ case 232: /* trigger_time ::= */
{ yymsp[1].minor.yy4 = TK_BEFORE; }
break;
- case 230: /* trigger_event ::= DELETE|INSERT */
- case 231: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==231);
+ case 233: /* trigger_event ::= DELETE|INSERT */
+ case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234);
{yymsp[0].minor.yy90.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy90.b = 0;}
break;
- case 232: /* trigger_event ::= UPDATE OF idlist */
+ case 235: /* trigger_event ::= UPDATE OF idlist */
{yymsp[-2].minor.yy90.a = TK_UPDATE; yymsp[-2].minor.yy90.b = yymsp[0].minor.yy384;}
break;
- case 233: /* when_clause ::= */
- case 252: /* key_opt ::= */ yytestcase(yyruleno==252);
+ case 236: /* when_clause ::= */
+ case 255: /* key_opt ::= */ yytestcase(yyruleno==255);
{ yymsp[1].minor.yy314 = 0; }
break;
- case 234: /* when_clause ::= WHEN expr */
- case 253: /* key_opt ::= KEY expr */ yytestcase(yyruleno==253);
+ case 237: /* when_clause ::= WHEN expr */
+ case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256);
{ yymsp[-1].minor.yy314 = yymsp[0].minor.yy314; }
break;
- case 235: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
assert( yymsp[-2].minor.yy203!=0 );
yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203;
yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203;
}
break;
- case 236: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
assert( yymsp[-1].minor.yy203!=0 );
yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203;
}
break;
- case 237: /* trnm ::= nm DOT nm */
+ case 240: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -141586,37 +143291,37 @@ static void yy_reduce(
"statements within triggers");
}
break;
- case 238: /* tridxby ::= INDEXED BY nm */
+ case 241: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 239: /* tridxby ::= NOT INDEXED */
+ case 242: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 240: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
{yylhsminor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy314, yymsp[-6].minor.yy4, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy336);}
yymsp[-7].minor.yy203 = yylhsminor.yy203;
break;
- case 241: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */
+ case 244: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */
{yylhsminor.yy203 = sqlite3TriggerInsertStep(pParse->db,&yymsp[-3].minor.yy0,yymsp[-2].minor.yy384,yymsp[-1].minor.yy387,yymsp[-5].minor.yy4,yymsp[-6].minor.yy336,yymsp[0].minor.yy336);/*yylhsminor.yy203-overwrites-yymsp[-5].minor.yy4*/}
yymsp[-6].minor.yy203 = yylhsminor.yy203;
break;
- case 242: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
{yylhsminor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy314, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy336);}
yymsp[-5].minor.yy203 = yylhsminor.yy203;
break;
- case 243: /* trigger_cmd ::= scanpt select scanpt */
+ case 246: /* trigger_cmd ::= scanpt select scanpt */
{yylhsminor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy387, yymsp[-2].minor.yy336, yymsp[0].minor.yy336); /*yylhsminor.yy203-overwrites-yymsp[-1].minor.yy387*/}
yymsp[-2].minor.yy203 = yylhsminor.yy203;
break;
- case 244: /* expr ::= RAISE LP IGNORE RP */
+ case 247: /* expr ::= RAISE LP IGNORE RP */
{
yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
if( yymsp[-3].minor.yy314 ){
@@ -141624,7 +143329,7 @@ static void yy_reduce(
}
}
break;
- case 245: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
if( yymsp[-5].minor.yy314 ) {
@@ -141632,152 +143337,148 @@ static void yy_reduce(
}
}
break;
- case 246: /* raisetype ::= ROLLBACK */
+ case 249: /* raisetype ::= ROLLBACK */
{yymsp[0].minor.yy4 = OE_Rollback;}
break;
- case 248: /* raisetype ::= FAIL */
+ case 251: /* raisetype ::= FAIL */
{yymsp[0].minor.yy4 = OE_Fail;}
break;
- case 249: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 252: /* cmd ::= DROP TRIGGER ifexists fullname */
{
sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4);
}
break;
- case 250: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
sqlite3Attach(pParse, yymsp[-3].minor.yy314, yymsp[-1].minor.yy314, yymsp[0].minor.yy314);
}
break;
- case 251: /* cmd ::= DETACH database_kw_opt expr */
+ case 254: /* cmd ::= DETACH database_kw_opt expr */
{
sqlite3Detach(pParse, yymsp[0].minor.yy314);
}
break;
- case 254: /* cmd ::= REINDEX */
+ case 257: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 255: /* cmd ::= REINDEX nm dbnm */
+ case 258: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 256: /* cmd ::= ANALYZE */
+ case 259: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 257: /* cmd ::= ANALYZE nm dbnm */
+ case 260: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 258: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0);
}
break;
- case 259: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 260: /* add_column_fullname ::= fullname */
+ case 263: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259);
}
break;
- case 261: /* cmd ::= create_vtab */
+ case 264: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 262: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 265: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 263: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4);
}
break;
- case 264: /* vtabarg ::= */
+ case 267: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 265: /* vtabargtoken ::= ANY */
- case 266: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==266);
- case 267: /* lp ::= LP */ yytestcase(yyruleno==267);
+ case 268: /* vtabargtoken ::= ANY */
+ case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269);
+ case 270: /* lp ::= LP */ yytestcase(yyruleno==270);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 268: /* with ::= */
-{yymsp[1].minor.yy451 = 0;}
- break;
- case 269: /* with ::= WITH wqlist */
-{ yymsp[-1].minor.yy451 = yymsp[0].minor.yy451; }
+ case 271: /* with ::= WITH wqlist */
+ case 272: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==272);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy451, 1); }
break;
- case 270: /* with ::= WITH RECURSIVE wqlist */
-{ yymsp[-2].minor.yy451 = yymsp[0].minor.yy451; }
- break;
- case 271: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */
{
yymsp[-5].minor.yy451 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); /*A-overwrites-X*/
}
break;
- case 272: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
{
yymsp[-7].minor.yy451 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy451, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387);
}
break;
default:
- /* (273) input ::= cmdlist */ yytestcase(yyruleno==273);
- /* (274) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==274);
- /* (275) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=275);
- /* (276) ecmd ::= SEMI */ yytestcase(yyruleno==276);
- /* (277) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==277);
- /* (278) explain ::= */ yytestcase(yyruleno==278);
- /* (279) trans_opt ::= */ yytestcase(yyruleno==279);
- /* (280) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==280);
- /* (281) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==281);
- /* (282) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==282);
- /* (283) savepoint_opt ::= */ yytestcase(yyruleno==283);
- /* (284) cmd ::= create_table create_table_args */ yytestcase(yyruleno==284);
- /* (285) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==285);
- /* (286) columnlist ::= columnname carglist */ yytestcase(yyruleno==286);
- /* (287) nm ::= ID|INDEXED */ yytestcase(yyruleno==287);
- /* (288) nm ::= STRING */ yytestcase(yyruleno==288);
- /* (289) nm ::= JOIN_KW */ yytestcase(yyruleno==289);
- /* (290) typetoken ::= typename */ yytestcase(yyruleno==290);
- /* (291) typename ::= ID|STRING */ yytestcase(yyruleno==291);
- /* (292) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=292);
- /* (293) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=293);
- /* (294) carglist ::= carglist ccons */ yytestcase(yyruleno==294);
- /* (295) carglist ::= */ yytestcase(yyruleno==295);
- /* (296) ccons ::= NULL onconf */ yytestcase(yyruleno==296);
- /* (297) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==297);
- /* (298) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==298);
- /* (299) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=299);
- /* (300) tconscomma ::= */ yytestcase(yyruleno==300);
- /* (301) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=301);
- /* (302) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=302);
- /* (303) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=303);
- /* (304) oneselect ::= values */ yytestcase(yyruleno==304);
- /* (305) sclp ::= selcollist COMMA */ yytestcase(yyruleno==305);
- /* (306) as ::= ID|STRING */ yytestcase(yyruleno==306);
- /* (307) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=307);
- /* (308) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==308);
- /* (309) exprlist ::= nexprlist */ yytestcase(yyruleno==309);
- /* (310) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=310);
- /* (311) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=311);
- /* (312) nmnum ::= ON */ yytestcase(yyruleno==312);
- /* (313) nmnum ::= DELETE */ yytestcase(yyruleno==313);
- /* (314) nmnum ::= DEFAULT */ yytestcase(yyruleno==314);
- /* (315) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==315);
- /* (316) foreach_clause ::= */ yytestcase(yyruleno==316);
- /* (317) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==317);
- /* (318) trnm ::= nm */ yytestcase(yyruleno==318);
- /* (319) tridxby ::= */ yytestcase(yyruleno==319);
- /* (320) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==320);
- /* (321) database_kw_opt ::= */ yytestcase(yyruleno==321);
- /* (322) kwcolumn_opt ::= */ yytestcase(yyruleno==322);
- /* (323) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==323);
- /* (324) vtabarglist ::= vtabarg */ yytestcase(yyruleno==324);
- /* (325) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==325);
- /* (326) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==326);
- /* (327) anylist ::= */ yytestcase(yyruleno==327);
- /* (328) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==328);
- /* (329) anylist ::= anylist ANY */ yytestcase(yyruleno==329);
+ /* (275) input ::= cmdlist */ yytestcase(yyruleno==275);
+ /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276);
+ /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277);
+ /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278);
+ /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279);
+ /* (280) explain ::= */ yytestcase(yyruleno==280);
+ /* (281) trans_opt ::= */ yytestcase(yyruleno==281);
+ /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282);
+ /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283);
+ /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284);
+ /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285);
+ /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286);
+ /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287);
+ /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288);
+ /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289);
+ /* (290) nm ::= STRING */ yytestcase(yyruleno==290);
+ /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291);
+ /* (292) typetoken ::= typename */ yytestcase(yyruleno==292);
+ /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293);
+ /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294);
+ /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295);
+ /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296);
+ /* (297) carglist ::= */ yytestcase(yyruleno==297);
+ /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298);
+ /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299);
+ /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300);
+ /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301);
+ /* (302) tconscomma ::= */ yytestcase(yyruleno==302);
+ /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303);
+ /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304);
+ /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305);
+ /* (306) oneselect ::= values */ yytestcase(yyruleno==306);
+ /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307);
+ /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308);
+ /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309);
+ /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310);
+ /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311);
+ /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312);
+ /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313);
+ /* (314) nmnum ::= ON */ yytestcase(yyruleno==314);
+ /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315);
+ /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316);
+ /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317);
+ /* (318) foreach_clause ::= */ yytestcase(yyruleno==318);
+ /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319);
+ /* (320) trnm ::= nm */ yytestcase(yyruleno==320);
+ /* (321) tridxby ::= */ yytestcase(yyruleno==321);
+ /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322);
+ /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323);
+ /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324);
+ /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325);
+ /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326);
+ /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327);
+ /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328);
+ /* (329) anylist ::= */ yytestcase(yyruleno==329);
+ /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330);
+ /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331);
+ /* (332) with ::= */ yytestcase(yyruleno==332);
break;
/********** End reduce actions ************************************************/
};
@@ -143604,6 +145305,11 @@ SQLITE_API int sqlite3_initialize(void){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ if( rc==SQLITE_OK ){
+ rc = sqlite3MemdbInit();
+ }
+#endif
if( rc==SQLITE_OK ){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
@@ -143636,7 +145342,7 @@ SQLITE_API int sqlite3_initialize(void){
#ifndef NDEBUG
#ifndef SQLITE_OMIT_FLOATING_POINT
/* This section of code's only "output" is via assert() statements. */
- if ( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
u64 x = (((u64)1)<<63)-1;
double y;
assert(sizeof(x)==8);
@@ -144803,6 +146509,8 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
/* SQLITE_FORMAT */ 0,
/* SQLITE_RANGE */ "column index out of range",
/* SQLITE_NOTADB */ "file is not a database",
+ /* SQLITE_NOTICE */ "notification message",
+ /* SQLITE_WARNING */ "warning message",
};
const char *zErr = "unknown error";
switch( rc ){
@@ -144810,6 +146518,14 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
zErr = "abort due to ROLLBACK";
break;
}
+ case SQLITE_ROW: {
+ zErr = "another row available";
+ break;
+ }
+ case SQLITE_DONE: {
+ zErr = "no more rows available";
+ break;
+ }
default: {
rc &= 0xff;
if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
@@ -144826,21 +146542,40 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
** again until a timeout value is reached. The timeout value is
** an integer number of milliseconds passed in as the first
** argument.
+**
+** Return non-zero to retry the lock. Return zero to stop trying
+** and cause SQLite to return SQLITE_BUSY.
*/
static int sqliteDefaultBusyCallback(
- void *ptr, /* Database connection */
- int count /* Number of times table has been busy */
+ void *ptr, /* Database connection */
+ int count, /* Number of times table has been busy */
+ sqlite3_file *pFile /* The file on which the lock occurred */
){
#if SQLITE_OS_WIN || HAVE_USLEEP
+ /* This case is for systems that have support for sleeping for fractions of
+ ** a second. Examples: All windows systems, unix systems with usleep() */
static const u8 delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY ArraySize(delays)
sqlite3 *db = (sqlite3 *)ptr;
- int timeout = db->busyTimeout;
+ int tmout = db->busyTimeout;
int delay, prior;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
+ if( count ){
+ tmout = 0;
+ sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
+ return 0;
+ }else{
+ return 1;
+ }
+ }
+#else
+ UNUSED_PARAMETER(pFile);
+#endif
assert( count>=0 );
if( count < NDELAY ){
delay = delays[count];
@@ -144849,16 +146584,19 @@ static int sqliteDefaultBusyCallback(
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
}
- if( prior + delay > timeout ){
- delay = timeout - prior;
+ if( prior + delay > tmout ){
+ delay = tmout - prior;
if( delay<=0 ) return 0;
}
sqlite3OsSleep(db->pVfs, delay*1000);
return 1;
#else
+ /* This case for unix systems that lack usleep() support. Sleeping
+ ** must be done in increments of whole seconds */
sqlite3 *db = (sqlite3 *)ptr;
- int timeout = ((sqlite3 *)ptr)->busyTimeout;
- if( (count+1)*1000 > timeout ){
+ int tmout = ((sqlite3 *)ptr)->busyTimeout;
+ UNUSED_PARAMETER(pFile);
+ if( (count+1)*1000 > tmout ){
return 0;
}
sqlite3OsSleep(db->pVfs, 1000000);
@@ -144869,14 +146607,25 @@ static int sqliteDefaultBusyCallback(
/*
** Invoke the given busy handler.
**
-** This routine is called when an operation failed with a lock.
+** This routine is called when an operation failed to acquire a
+** lock on VFS file pFile.
+**
** If this routine returns non-zero, the lock is retried. If it
** returns 0, the operation aborts with an SQLITE_BUSY error.
*/
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
int rc;
- if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0;
- rc = p->xFunc(p->pArg, p->nBusy);
+ if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
+ if( p->bExtraFileArg ){
+ /* Add an extra parameter with the pFile pointer to the end of the
+ ** callback argument list */
+ int (*xTra)(void*,int,sqlite3_file*);
+ xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
+ rc = xTra(p->pBusyArg, p->nBusy, pFile);
+ }else{
+ /* Legacy style busy handler callback */
+ rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
+ }
if( rc==0 ){
p->nBusy = -1;
}else{
@@ -144898,9 +146647,10 @@ SQLITE_API int sqlite3_busy_handler(
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
- db->busyHandler.xFunc = xBusy;
- db->busyHandler.pArg = pArg;
+ db->busyHandler.xBusyHandler = xBusy;
+ db->busyHandler.pBusyArg = pArg;
db->busyHandler.nBusy = 0;
+ db->busyHandler.bExtraFileArg = 0;
db->busyTimeout = 0;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
@@ -144948,8 +146698,10 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
if( ms>0 ){
- sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
+ (void*)db);
db->busyTimeout = ms;
+ db->busyHandler.bExtraFileArg = 1;
}else{
sqlite3_busy_handler(db, 0, 0);
}
@@ -146942,10 +148694,8 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
}else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
*(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
rc = SQLITE_OK;
- }else if( fd->pMethods ){
- rc = sqlite3OsFileControl(fd, op, pArg);
}else{
- rc = SQLITE_NOTFOUND;
+ rc = sqlite3OsFileControl(fd, op, pArg);
}
sqlite3BtreeLeave(pBtree);
}
@@ -160796,6 +162546,7 @@ static int fts3WriteSegment(
sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
+ sqlite3_bind_null(pStmt, 2);
}
return rc;
}
@@ -160852,6 +162603,7 @@ static int fts3WriteSegdir(
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
+ sqlite3_bind_null(pStmt, 6);
}
return rc;
}
@@ -162331,6 +164083,7 @@ static void fts3UpdateDocTotals(
sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
sqlite3_step(pStmt);
*pRC = sqlite3_reset(pStmt);
+ sqlite3_bind_null(pStmt, 2);
sqlite3_free(a);
}
@@ -163519,6 +165272,7 @@ static int fts3TruncateSegment(
sqlite3_bind_int(pChomp, 4, iIdx);
sqlite3_step(pChomp);
rc = sqlite3_reset(pChomp);
+ sqlite3_bind_null(pChomp, 2);
}
}
@@ -163598,6 +165352,7 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
+ sqlite3_bind_null(pReplace, 2);
}
return rc;
@@ -164412,7 +166167,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
){
Fts3Table *p = (Fts3Table *)pVtab;
int rc = SQLITE_OK; /* Return Code */
- int isRemove = 0; /* True for an UPDATE or DELETE */
u32 *aSzIns = 0; /* Sizes of inserted documents */
u32 *aSzDel = 0; /* Sizes of deleted documents */
int nChng = 0; /* Net change in number of documents */
@@ -164510,7 +166264,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
- isRemove = 1;
}
/* If this is an INSERT or UPDATE operation, insert the new record. */
@@ -164522,7 +166275,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
rc = FTS_CORRUPT_VTAB;
}
}
- if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
+ if( rc==SQLITE_OK ){
rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
}
if( rc==SQLITE_OK ){
@@ -167830,6 +169583,7 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
sqlite3_step(p);
pNode->isDirty = 0;
rc = sqlite3_reset(p);
+ sqlite3_bind_null(p, 2);
if( pNode->iNode==0 && rc==SQLITE_OK ){
pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
nodeHashInsert(pRtree, pNode);
@@ -174517,7 +176271,7 @@ static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){
int iCid = sqlite3_column_int(pXInfo, 1);
int bDesc = sqlite3_column_int(pXInfo, 3);
const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
- zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma,
+ zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma,
iCid, pIter->azTblType[iCid], zCollate
);
zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":"");
@@ -174578,7 +176332,7 @@ static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){
** "PRIMARY KEY" to the imposter table column declaration. */
zPk = "PRIMARY KEY ";
}
- zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s",
+ zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s",
zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl,
(pIter->abNotNull[iCol] ? " NOT NULL" : "")
);
@@ -178012,7 +179766,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
*/
fd = sqlite3PagerFile(pPager);
x[0] = pCsr->iPageno;
- if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
+ if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
pCsr->iOffset = x[0];
pCsr->szPage = (int)x[1];
}
@@ -178778,7 +180532,7 @@ struct SessionBuffer {
** sqlite3changeset_start_strm()).
*/
struct SessionInput {
- int bNoDiscard; /* If true, discard no data */
+ int bNoDiscard; /* If true, do not discard in InputBuffer() */
int iCurrent; /* Offset in aData[] of current change */
int iNext; /* Offset in aData[] of next change */
u8 *aData; /* Pointer to buffer containing changeset */
@@ -178942,8 +180696,8 @@ struct SessionTable {
** statement.
**
** For a DELETE change, all fields within the record except those associated
-** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields
-** contain the values identifying the row to delete.
+** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the
+** values identifying the row to delete.
**
** For an UPDATE change, all fields except those associated with PRIMARY KEY
** columns and columns that are modified by the UPDATE are set to "undefined".
@@ -179226,7 +180980,7 @@ static int sessionPreupdateHash(
static int sessionSerialLen(u8 *a){
int e = *a;
int n;
- if( e==0 ) return 1;
+ if( e==0 || e==0xFF ) return 1;
if( e==SQLITE_NULL ) return 1;
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
return sessionVarintGet(&a[1], &n) + 1 + n;
@@ -179306,7 +181060,7 @@ static int sessionChangeEqual(
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
- if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){
+ if( n1!=n2 || memcmp(a1, a2, n1) ){
return 0;
}
a1 += n1;
@@ -179549,7 +181303,7 @@ static int sessionPreupdateEqual(
}else{
z = sqlite3_value_blob(pVal);
}
- if( memcmp(a, z, n) ) return 0;
+ if( n>0 && memcmp(a, z, n) ) return 0;
a += n;
}
}
@@ -179825,7 +181579,7 @@ static void sessionPreupdateOneChange(
int iHash;
int bNull = 0;
int rc = SQLITE_OK;
- SessionStat1Ctx stat1;
+ SessionStat1Ctx stat1 = {0};
if( pSession->rc ) return;
@@ -180893,6 +182647,7 @@ static int sessionSelectStmt(
"SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND "
"idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb
);
+ if( zSql==0 ) rc = SQLITE_NOMEM;
}else{
int i;
const char *zSep = "";
@@ -181302,7 +183057,7 @@ SQLITE_API int sqlite3changeset_start_strm(
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
- if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
+ if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
int nMove = pIn->buf.nBuf - pIn->iNext;
assert( nMove>=0 );
if( nMove>0 ){
@@ -181430,13 +183185,16 @@ static int sessionReadRecord(
if( abPK && abPK[i]==0 ) continue;
rc = sessionInputBuffer(pIn, 9);
if( rc==SQLITE_OK ){
- eType = pIn->aData[pIn->iNext++];
- }
-
- assert( apOut[i]==0 );
- if( eType ){
- apOut[i] = sqlite3ValueNew(0);
- if( !apOut[i] ) rc = SQLITE_NOMEM;
+ if( pIn->iNext>=pIn->nData ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ eType = pIn->aData[pIn->iNext++];
+ assert( apOut[i]==0 );
+ if( eType ){
+ apOut[i] = sqlite3ValueNew(0);
+ if( !apOut[i] ) rc = SQLITE_NOMEM;
+ }
+ }
}
if( rc==SQLITE_OK ){
@@ -181446,10 +183204,14 @@ static int sessionReadRecord(
pIn->iNext += sessionVarintGet(aVal, &nByte);
rc = sessionInputBuffer(pIn, nByte);
if( rc==SQLITE_OK ){
- u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
- rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
+ if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
+ rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc);
+ pIn->iNext += nByte;
+ }
}
- pIn->iNext += nByte;
}
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
sqlite3_int64 v = sessionGetI64(aVal);
@@ -181489,8 +183251,19 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
rc = sessionInputBuffer(pIn, 9);
if( rc==SQLITE_OK ){
nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
- rc = sessionInputBuffer(pIn, nRead+nCol+100);
- nRead += nCol;
+ /* The hard upper limit for the number of columns in an SQLite
+ ** database table is, according to sqliteLimit.h, 32676. So
+ ** consider any table-header that purports to have more than 65536
+ ** columns to be corrupt. This is convenient because otherwise,
+ ** if the (nCol>65536) condition below were omitted, a sufficiently
+ ** large value for nCol may cause nRead to wrap around and become
+ ** negative. Leading to a crash. */
+ if( nCol<0 || nCol>65536 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = sessionInputBuffer(pIn, nRead+nCol+100);
+ nRead += nCol;
+ }
}
while( rc==SQLITE_OK ){
@@ -181567,11 +183340,15 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
int nByte;
int nVarint;
nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol);
- nCopy -= nVarint;
- p->in.iNext += nVarint;
- nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
- p->tblhdr.nBuf = 0;
- sessionBufferGrow(&p->tblhdr, nByte, &rc);
+ if( p->nCol>0 ){
+ nCopy -= nVarint;
+ p->in.iNext += nVarint;
+ nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
+ p->tblhdr.nBuf = 0;
+ sessionBufferGrow(&p->tblhdr, nByte, &rc);
+ }else{
+ rc = SQLITE_CORRUPT_BKPT;
+ }
}
if( rc==SQLITE_OK ){
@@ -181606,7 +183383,8 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
static int sessionChangesetNext(
sqlite3_changeset_iter *p, /* Changeset iterator */
u8 **paRec, /* If non-NULL, store record pointer here */
- int *pnRec /* If non-NULL, store size of record here */
+ int *pnRec, /* If non-NULL, store size of record here */
+ int *pbNew /* If non-NULL, true if new table */
){
int i;
u8 op;
@@ -181641,6 +183419,7 @@ static int sessionChangesetNext(
op = p->in.aData[p->in.iNext++];
while( op=='T' || op=='P' ){
+ if( pbNew ) *pbNew = 1;
p->bPatchset = (op=='P');
if( sessionChangesetReadTblhdr(p) ) return p->rc;
if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc;
@@ -181649,6 +183428,13 @@ static int sessionChangesetNext(
op = p->in.aData[p->in.iNext++];
}
+ if( p->zTab==0 ){
+ /* The first record in the changeset is not a table header. Must be a
+ ** corrupt changeset. */
+ assert( p->in.iNext==1 );
+ return (p->rc = SQLITE_CORRUPT_BKPT);
+ }
+
p->op = op;
p->bIndirect = p->in.aData[p->in.iNext++];
if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
@@ -181691,9 +183477,9 @@ static int sessionChangesetNext(
** new.* to old.*, to accommodate the code that reads these arrays. */
for(i=0; i<p->nCol; i++){
assert( p->apValue[i]==0 );
- assert( p->abPK[i]==0 || p->apValue[i+p->nCol] );
if( p->abPK[i] ){
p->apValue[i] = p->apValue[i+p->nCol];
+ if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT);
p->apValue[i+p->nCol] = 0;
}
}
@@ -181712,7 +183498,7 @@ static int sessionChangesetNext(
** callback by changeset_apply().
*/
SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){
- return sessionChangesetNext(p, 0, 0);
+ return sessionChangesetNext(p, 0, 0, 0);
}
/*
@@ -182091,6 +183877,8 @@ struct SessionApplyCtx {
int bStat1; /* True if table is sqlite_stat1 */
int bDeferConstraints; /* True to defer constraints */
SessionBuffer constraints; /* Deferred constraints are stored here */
+ SessionBuffer rebase; /* Rebase information (if any) here */
+ int bRebaseStarted; /* If table header is already in rebase */
};
/*
@@ -182357,7 +184145,6 @@ static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
"AND (?4 OR stat IS ?3)"
);
}
- assert( rc==SQLITE_OK );
return rc;
}
@@ -182418,7 +184205,13 @@ static int sessionBindRow(
if( !abPK || abPK[i] ){
sqlite3_value *pVal;
(void)xValue(pIter, i, &pVal);
- rc = sessionBindValue(pStmt, i+1, pVal);
+ if( pVal==0 ){
+ /* The value in the changeset was "undefined". This indicates a
+ ** corrupt changeset blob. */
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = sessionBindValue(pStmt, i+1, pVal);
+ }
}
}
return rc;
@@ -182467,6 +184260,54 @@ static int sessionSeekToRow(
}
/*
+** This function is called from within sqlite3changset_apply_v2() when
+** a conflict is encountered and resolved using conflict resolution
+** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE)..
+** It adds a conflict resolution record to the buffer in
+** SessionApplyCtx.rebase, which will eventually be returned to the caller
+** of apply_v2() as the "rebase" buffer.
+**
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
+*/
+static int sessionRebaseAdd(
+ SessionApplyCtx *p, /* Apply context */
+ int eType, /* Conflict resolution (OMIT or REPLACE) */
+ sqlite3_changeset_iter *pIter /* Iterator pointing at current change */
+){
+ int rc = SQLITE_OK;
+ int i;
+ int eOp = pIter->op;
+ if( p->bRebaseStarted==0 ){
+ /* Append a table-header to the rebase buffer */
+ const char *zTab = pIter->zTab;
+ sessionAppendByte(&p->rebase, 'T', &rc);
+ sessionAppendVarint(&p->rebase, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
+ p->bRebaseStarted = 1;
+ }
+
+ assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
+ assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
+
+ sessionAppendByte(&p->rebase,
+ (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
+ );
+ sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
+ for(i=0; i<p->nCol; i++){
+ sqlite3_value *pVal = 0;
+ if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
+ sqlite3changeset_old(pIter, i, &pVal);
+ }else{
+ sqlite3changeset_new(pIter, i, &pVal);
+ }
+ sessionAppendValue(&p->rebase, pVal, &rc);
+ }
+
+ return rc;
+}
+
+/*
** Invoke the conflict handler for the change that the changeset iterator
** currently points to.
**
@@ -182541,7 +184382,7 @@ static int sessionConflictHandler(
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
- res = SQLITE_CHANGESET_OMIT;
+ return SQLITE_OK;
}else{
/* No other row with the new.* primary key. */
res = xConflict(pCtx, eType+1, pIter);
@@ -182567,6 +184408,9 @@ static int sessionConflictHandler(
rc = SQLITE_MISUSE;
break;
}
+ if( rc==SQLITE_OK ){
+ rc = sessionRebaseAdd(p, res, pIter);
+ }
}
return rc;
@@ -182742,42 +184586,42 @@ static int sessionApplyOneWithRetry(
int rc;
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry);
- assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) );
-
- /* If the bRetry flag is set, the change has not been applied due to an
- ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and
- ** a row with the correct PK is present in the db, but one or more other
- ** fields do not contain the expected values) and the conflict handler
- ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation,
- ** but pass NULL as the final argument so that sessionApplyOneOp() ignores
- ** the SQLITE_CHANGESET_DATA problem. */
- if( bRetry ){
- assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE );
- rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
- }
-
- /* If the bReplace flag is set, the change is an INSERT that has not
- ** been performed because the database already contains a row with the
- ** specified primary key and the conflict handler returned
- ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row
- ** before reattempting the INSERT. */
- else if( bReplace ){
- assert( pIter->op==SQLITE_INSERT );
- rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sessionBindRow(pIter,
- sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete);
- sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
- }
- if( rc==SQLITE_OK ){
- sqlite3_step(pApply->pDelete);
- rc = sqlite3_reset(pApply->pDelete);
- }
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
+ /* If the bRetry flag is set, the change has not been applied due to an
+ ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and
+ ** a row with the correct PK is present in the db, but one or more other
+ ** fields do not contain the expected values) and the conflict handler
+ ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation,
+ ** but pass NULL as the final argument so that sessionApplyOneOp() ignores
+ ** the SQLITE_CHANGESET_DATA problem. */
+ if( bRetry ){
+ assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE );
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
}
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0);
+
+ /* If the bReplace flag is set, the change is an INSERT that has not
+ ** been performed because the database already contains a row with the
+ ** specified primary key and the conflict handler returned
+ ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row
+ ** before reattempting the INSERT. */
+ else if( bReplace ){
+ assert( pIter->op==SQLITE_INSERT );
+ rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = sessionBindRow(pIter,
+ sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete);
+ sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3_step(pApply->pDelete);
+ rc = sqlite3_reset(pApply->pDelete);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0);
+ }
}
}
@@ -182853,10 +184697,12 @@ static int sessionChangesetApply(
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
sqlite3_changeset_iter *p /* Handle describing change and conflict */
),
- void *pCtx /* First argument passed to xConflict */
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase, /* OUT: Rebase information */
+ int flags /* SESSION_APPLY_XXX flags */
){
int schemaMismatch = 0;
- int rc; /* Return code */
+ int rc = SQLITE_OK; /* Return code */
const char *zTab = 0; /* Name of current table */
int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
SessionApplyCtx sApply; /* changeset_apply() context object */
@@ -182867,7 +184713,9 @@ static int sessionChangesetApply(
pIter->in.bNoDiscard = 1;
memset(&sApply, 0, sizeof(sApply));
sqlite3_mutex_enter(sqlite3_db_mutex(db));
- rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
+ if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
+ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
+ }
if( rc==SQLITE_OK ){
rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0);
}
@@ -182891,9 +184739,18 @@ static int sessionChangesetApply(
sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pSelect);
- memset(&sApply, 0, sizeof(sApply));
sApply.db = db;
+ sApply.pDelete = 0;
+ sApply.pUpdate = 0;
+ sApply.pInsert = 0;
+ sApply.pSelect = 0;
+ sApply.nCol = 0;
+ sApply.azCol = 0;
+ sApply.abPK = 0;
+ sApply.bStat1 = 0;
sApply.bDeferConstraints = 1;
+ sApply.bRebaseStarted = 0;
+ memset(&sApply.constraints, 0, sizeof(SessionBuffer));
/* If an xFilter() callback was specified, invoke it now. If the
** xFilter callback returns zero, skip this table. If it returns
@@ -182996,24 +184853,63 @@ static int sessionChangesetApply(
}
sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
- }else{
- sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
- sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
+ if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
+ }else{
+ sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
+ sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
+ }
}
+ if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){
+ *ppRebase = (void*)sApply.rebase.aBuf;
+ *pnRebase = sApply.rebase.nBuf;
+ sApply.rebase.aBuf = 0;
+ }
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pDelete);
sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pSelect);
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_free((char*)sApply.constraints.aBuf);
+ sqlite3_free((char*)sApply.rebase.aBuf);
sqlite3_mutex_leave(sqlite3_db_mutex(db));
return rc;
}
/*
+** Apply the changeset passed via pChangeset/nChangeset to the main
+** database attached to handle "db".
+*/
+SQLITE_API int sqlite3changeset_apply_v2(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int nChangeset, /* Size of changeset in bytes */
+ void *pChangeset, /* Changeset blob */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
+){
+ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
+ int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
+ if( rc==SQLITE_OK ){
+ rc = sessionChangesetApply(
+ db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
+ );
+ }
+ return rc;
+}
+
+/*
** Apply the changeset passed via pChangeset/nChangeset to the main database
** attached to handle "db". Invoke the supplied conflict handler callback
** to resolve any conflicts encountered while applying the change.
@@ -183033,12 +184929,9 @@ SQLITE_API int sqlite3changeset_apply(
),
void *pCtx /* First argument passed to xConflict */
){
- sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
- if( rc==SQLITE_OK ){
- rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx);
- }
- return rc;
+ return sqlite3changeset_apply_v2(
+ db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0
+ );
}
/*
@@ -183046,7 +184939,7 @@ SQLITE_API int sqlite3changeset_apply(
** attached to handle "db". Invoke the supplied conflict handler callback
** to resolve any conflicts encountered while applying the change.
*/
-SQLITE_API int sqlite3changeset_apply_strm(
+SQLITE_API int sqlite3changeset_apply_v2_strm(
sqlite3 *db, /* Apply change to "main" db of this handle */
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
void *pIn, /* First arg for xInput */
@@ -183059,15 +184952,38 @@ SQLITE_API int sqlite3changeset_apply_strm(
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
sqlite3_changeset_iter *p /* Handle describing change and conflict */
),
- void *pCtx /* First argument passed to xConflict */
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
if( rc==SQLITE_OK ){
- rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx);
+ rc = sessionChangesetApply(
+ db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
+ );
}
return rc;
}
+SQLITE_API int sqlite3changeset_apply_strm(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
+ void *pIn, /* First arg for xInput */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx /* First argument passed to xConflict */
+){
+ return sqlite3changeset_apply_v2_strm(
+ db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0
+ );
+}
/*
** sqlite3_changegroup handle.
@@ -183085,6 +185001,7 @@ struct sqlite3_changegroup {
*/
static int sessionChangeMerge(
SessionTable *pTab, /* Table structure */
+ int bRebase, /* True for a rebase hash-table */
int bPatchset, /* True for patchsets */
SessionChange *pExist, /* Existing change */
int op2, /* Second change operation */
@@ -183094,6 +185011,7 @@ static int sessionChangeMerge(
SessionChange **ppNew /* OUT: Merged change */
){
SessionChange *pNew = 0;
+ int rc = SQLITE_OK;
if( !pExist ){
pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
@@ -183103,9 +185021,66 @@ static int sessionChangeMerge(
memset(pNew, 0, sizeof(SessionChange));
pNew->op = op2;
pNew->bIndirect = bIndirect;
- pNew->nRecord = nRec;
pNew->aRecord = (u8*)&pNew[1];
- memcpy(pNew->aRecord, aRec, nRec);
+ if( bIndirect==0 || bRebase==0 ){
+ pNew->nRecord = nRec;
+ memcpy(pNew->aRecord, aRec, nRec);
+ }else{
+ int i;
+ u8 *pIn = aRec;
+ u8 *pOut = pNew->aRecord;
+ for(i=0; i<pTab->nCol; i++){
+ int nIn = sessionSerialLen(pIn);
+ if( *pIn==0 ){
+ *pOut++ = 0;
+ }else if( pTab->abPK[i]==0 ){
+ *pOut++ = 0xFF;
+ }else{
+ memcpy(pOut, pIn, nIn);
+ pOut += nIn;
+ }
+ pIn += nIn;
+ }
+ pNew->nRecord = pOut - pNew->aRecord;
+ }
+ }else if( bRebase ){
+ if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
+ *ppNew = pExist;
+ }else{
+ int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
+ pNew = (SessionChange*)sqlite3_malloc(nByte);
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int i;
+ u8 *a1 = pExist->aRecord;
+ u8 *a2 = aRec;
+ u8 *pOut;
+
+ memset(pNew, 0, nByte);
+ pNew->bIndirect = bIndirect || pExist->bIndirect;
+ pNew->op = op2;
+ pOut = pNew->aRecord = (u8*)&pNew[1];
+
+ for(i=0; i<pTab->nCol; i++){
+ int n1 = sessionSerialLen(a1);
+ int n2 = sessionSerialLen(a2);
+ if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){
+ *pOut++ = 0xFF;
+ }else if( *a2==0 ){
+ memcpy(pOut, a1, n1);
+ pOut += n1;
+ }else{
+ memcpy(pOut, a2, n2);
+ pOut += n2;
+ }
+ a1 += n1;
+ a2 += n2;
+ }
+ pNew->nRecord = pOut - pNew->aRecord;
+ }
+ sqlite3_free(pExist);
+ }
}else{
int op1 = pExist->op;
@@ -183199,7 +185174,7 @@ static int sessionChangeMerge(
}
*ppNew = pNew;
- return SQLITE_OK;
+ return rc;
}
/*
@@ -183208,15 +185183,15 @@ static int sessionChangeMerge(
*/
static int sessionChangesetToHash(
sqlite3_changeset_iter *pIter, /* Iterator to read from */
- sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */
+ sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */
+ int bRebase /* True if hash table is for rebasing */
){
u8 *aRec;
int nRec;
int rc = SQLITE_OK;
SessionTable *pTab = 0;
-
- while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){
+ while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){
const char *zNew;
int nCol;
int op;
@@ -183296,7 +185271,7 @@ static int sessionChangesetToHash(
}
}
- rc = sessionChangeMerge(pTab,
+ rc = sessionChangeMerge(pTab, bRebase,
pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange
);
if( rc ) break;
@@ -183404,7 +185379,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void
rc = sqlite3changeset_start(&pIter, nData, pData);
if( rc==SQLITE_OK ){
- rc = sessionChangesetToHash(pIter, pGrp);
+ rc = sessionChangesetToHash(pIter, pGrp, 0);
}
sqlite3changeset_finalize(pIter);
return rc;
@@ -183435,7 +185410,7 @@ SQLITE_API int sqlite3changegroup_add_strm(
rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
if( rc==SQLITE_OK ){
- rc = sessionChangesetToHash(pIter, pGrp);
+ rc = sessionChangesetToHash(pIter, pGrp, 0);
}
sqlite3changeset_finalize(pIter);
return rc;
@@ -183520,6 +185495,349 @@ SQLITE_API int sqlite3changeset_concat_strm(
return rc;
}
+/*
+** Changeset rebaser handle.
+*/
+struct sqlite3_rebaser {
+ sqlite3_changegroup grp; /* Hash table */
+};
+
+/*
+** Buffers a1 and a2 must both contain a sessions module record nCol
+** fields in size. This function appends an nCol sessions module
+** record to buffer pBuf that is a copy of a1, except that for
+** each field that is undefined in a1[], swap in the field from a2[].
+*/
+static void sessionAppendRecordMerge(
+ SessionBuffer *pBuf, /* Buffer to append to */
+ int nCol, /* Number of columns in each record */
+ u8 *a1, int n1, /* Record 1 */
+ u8 *a2, int n2, /* Record 2 */
+ int *pRc /* IN/OUT: error code */
+){
+ sessionBufferGrow(pBuf, n1+n2, pRc);
+ if( *pRc==SQLITE_OK ){
+ int i;
+ u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
+ for(i=0; i<nCol; i++){
+ int nn1 = sessionSerialLen(a1);
+ int nn2 = sessionSerialLen(a2);
+ if( *a1==0 || *a1==0xFF ){
+ memcpy(pOut, a2, nn2);
+ pOut += nn2;
+ }else{
+ memcpy(pOut, a1, nn1);
+ pOut += nn1;
+ }
+ a1 += nn1;
+ a2 += nn2;
+ }
+
+ pBuf->nBuf = pOut-pBuf->aBuf;
+ assert( pBuf->nBuf<=pBuf->nAlloc );
+ }
+}
+
+/*
+** This function is called when rebasing a local UPDATE change against one
+** or more remote UPDATE changes. The aRec/nRec buffer contains the current
+** old.* and new.* records for the change. The rebase buffer (a single
+** record) is in aChange/nChange. The rebased change is appended to buffer
+** pBuf.
+**
+** Rebasing the UPDATE involves:
+**
+** * Removing any changes to fields for which the corresponding field
+** in the rebase buffer is set to "replaced" (type 0xFF). If this
+** means the UPDATE change updates no fields, nothing is appended
+** to the output buffer.
+**
+** * For each field modified by the local change for which the
+** corresponding field in the rebase buffer is not "undefined" (0x00)
+** or "replaced" (0xFF), the old.* value is replaced by the value
+** in the rebase buffer.
+*/
+static void sessionAppendPartialUpdate(
+ SessionBuffer *pBuf, /* Append record here */
+ sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */
+ u8 *aRec, int nRec, /* Local change */
+ u8 *aChange, int nChange, /* Record to rebase against */
+ int *pRc /* IN/OUT: Return Code */
+){
+ sessionBufferGrow(pBuf, 2+nRec+nChange, pRc);
+ if( *pRc==SQLITE_OK ){
+ int bData = 0;
+ u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
+ int i;
+ u8 *a1 = aRec;
+ u8 *a2 = aChange;
+
+ *pOut++ = SQLITE_UPDATE;
+ *pOut++ = pIter->bIndirect;
+ for(i=0; i<pIter->nCol; i++){
+ int n1 = sessionSerialLen(a1);
+ int n2 = sessionSerialLen(a2);
+ if( pIter->abPK[i] || a2[0]==0 ){
+ if( !pIter->abPK[i] ) bData = 1;
+ memcpy(pOut, a1, n1);
+ pOut += n1;
+ }else if( a2[0]!=0xFF ){
+ bData = 1;
+ memcpy(pOut, a2, n2);
+ pOut += n2;
+ }else{
+ *pOut++ = '\0';
+ }
+ a1 += n1;
+ a2 += n2;
+ }
+ if( bData ){
+ a2 = aChange;
+ for(i=0; i<pIter->nCol; i++){
+ int n1 = sessionSerialLen(a1);
+ int n2 = sessionSerialLen(a2);
+ if( pIter->abPK[i] || a2[0]!=0xFF ){
+ memcpy(pOut, a1, n1);
+ pOut += n1;
+ }else{
+ *pOut++ = '\0';
+ }
+ a1 += n1;
+ a2 += n2;
+ }
+ pBuf->nBuf = (pOut - pBuf->aBuf);
+ }
+ }
+}
+
+/*
+** pIter is configured to iterate through a changeset. This function rebases
+** that changeset according to the current configuration of the rebaser
+** object passed as the first argument. If no error occurs and argument xOutput
+** is not NULL, then the changeset is returned to the caller by invoking
+** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL,
+** then (*ppOut) is set to point to a buffer containing the rebased changeset
+** before this function returns. In this case (*pnOut) is set to the size of
+** the buffer in bytes. It is the responsibility of the caller to eventually
+** free the (*ppOut) buffer using sqlite3_free().
+**
+** If an error occurs, an SQLite error code is returned. If ppOut and
+** pnOut are not NULL, then the two output parameters are set to 0 before
+** returning.
+*/
+static int sessionRebase(
+ sqlite3_rebaser *p, /* Rebaser hash table */
+ sqlite3_changeset_iter *pIter, /* Input data */
+ int (*xOutput)(void *pOut, const void *pData, int nData),
+ void *pOut, /* Context for xOutput callback */
+ int *pnOut, /* OUT: Number of bytes in output changeset */
+ void **ppOut /* OUT: Inverse of pChangeset */
+){
+ int rc = SQLITE_OK;
+ u8 *aRec = 0;
+ int nRec = 0;
+ int bNew = 0;
+ SessionTable *pTab = 0;
+ SessionBuffer sOut = {0,0,0};
+
+ while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){
+ SessionChange *pChange = 0;
+ int bDone = 0;
+
+ if( bNew ){
+ const char *zTab = pIter->zTab;
+ for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){
+ if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break;
+ }
+ bNew = 0;
+
+ /* A patchset may not be rebased */
+ if( pIter->bPatchset ){
+ rc = SQLITE_ERROR;
+ }
+
+ /* Append a table header to the output for this new table */
+ sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc);
+ sessionAppendVarint(&sOut, pIter->nCol, &rc);
+ sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc);
+ sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc);
+ }
+
+ if( pTab && rc==SQLITE_OK ){
+ int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange);
+
+ for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){
+ if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){
+ break;
+ }
+ }
+ }
+
+ if( pChange ){
+ assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT );
+ switch( pIter->op ){
+ case SQLITE_INSERT:
+ if( pChange->op==SQLITE_INSERT ){
+ bDone = 1;
+ if( pChange->bIndirect==0 ){
+ sessionAppendByte(&sOut, SQLITE_UPDATE, &rc);
+ sessionAppendByte(&sOut, pIter->bIndirect, &rc);
+ sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc);
+ sessionAppendBlob(&sOut, aRec, nRec, &rc);
+ }
+ }
+ break;
+
+ case SQLITE_UPDATE:
+ bDone = 1;
+ if( pChange->op==SQLITE_DELETE ){
+ if( pChange->bIndirect==0 ){
+ u8 *pCsr = aRec;
+ sessionSkipRecord(&pCsr, pIter->nCol);
+ sessionAppendByte(&sOut, SQLITE_INSERT, &rc);
+ sessionAppendByte(&sOut, pIter->bIndirect, &rc);
+ sessionAppendRecordMerge(&sOut, pIter->nCol,
+ pCsr, nRec-(pCsr-aRec),
+ pChange->aRecord, pChange->nRecord, &rc
+ );
+ }
+ }else{
+ sessionAppendPartialUpdate(&sOut, pIter,
+ aRec, nRec, pChange->aRecord, pChange->nRecord, &rc
+ );
+ }
+ break;
+
+ default:
+ assert( pIter->op==SQLITE_DELETE );
+ bDone = 1;
+ if( pChange->op==SQLITE_INSERT ){
+ sessionAppendByte(&sOut, SQLITE_DELETE, &rc);
+ sessionAppendByte(&sOut, pIter->bIndirect, &rc);
+ sessionAppendRecordMerge(&sOut, pIter->nCol,
+ pChange->aRecord, pChange->nRecord, aRec, nRec, &rc
+ );
+ }
+ break;
+ }
+ }
+
+ if( bDone==0 ){
+ sessionAppendByte(&sOut, pIter->op, &rc);
+ sessionAppendByte(&sOut, pIter->bIndirect, &rc);
+ sessionAppendBlob(&sOut, aRec, nRec, &rc);
+ }
+ if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){
+ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
+ sOut.nBuf = 0;
+ }
+ if( rc ) break;
+ }
+
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(sOut.aBuf);
+ memset(&sOut, 0, sizeof(sOut));
+ }
+
+ if( rc==SQLITE_OK ){
+ if( xOutput ){
+ if( sOut.nBuf>0 ){
+ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
+ }
+ }else{
+ *ppOut = (void*)sOut.aBuf;
+ *pnOut = sOut.nBuf;
+ sOut.aBuf = 0;
+ }
+ }
+ sqlite3_free(sOut.aBuf);
+ return rc;
+}
+
+/*
+** Create a new rebaser object.
+*/
+SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){
+ int rc = SQLITE_OK;
+ sqlite3_rebaser *pNew;
+
+ pNew = sqlite3_malloc(sizeof(sqlite3_rebaser));
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pNew, 0, sizeof(sqlite3_rebaser));
+ }
+ *ppNew = pNew;
+ return rc;
+}
+
+/*
+** Call this one or more times to configure a rebaser.
+*/
+SQLITE_API int sqlite3rebaser_configure(
+ sqlite3_rebaser *p,
+ int nRebase, const void *pRebase
+){
+ sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
+ int rc; /* Return code */
+ rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase);
+ if( rc==SQLITE_OK ){
+ rc = sessionChangesetToHash(pIter, &p->grp, 1);
+ }
+ sqlite3changeset_finalize(pIter);
+ return rc;
+}
+
+/*
+** Rebase a changeset according to current rebaser configuration
+*/
+SQLITE_API int sqlite3rebaser_rebase(
+ sqlite3_rebaser *p,
+ int nIn, const void *pIn,
+ int *pnOut, void **ppOut
+){
+ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */
+ int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn);
+
+ if( rc==SQLITE_OK ){
+ rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut);
+ sqlite3changeset_finalize(pIter);
+ }
+
+ return rc;
+}
+
+/*
+** Rebase a changeset according to current rebaser configuration
+*/
+SQLITE_API int sqlite3rebaser_rebase_strm(
+ sqlite3_rebaser *p,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int (*xOutput)(void *pOut, const void *pData, int nData),
+ void *pOut
+){
+ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */
+ int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
+
+ if( rc==SQLITE_OK ){
+ rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0);
+ sqlite3changeset_finalize(pIter);
+ }
+
+ return rc;
+}
+
+/*
+** Destroy a rebaser object
+*/
+SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
+ if( p ){
+ sessionDeleteTable(p->grp.pList);
+ sqlite3_free(p);
+ }
+}
+
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
/************** End of sqlite3session.c **************************************/
@@ -188055,7 +190373,8 @@ static unsigned int fts5yy_find_shift_action(
#endif
do{
i = fts5yy_shift_ofst[stateno];
- assert( i>=0 && i+fts5YYNFTS5TOKEN<=sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) );
+ assert( i>=0 );
+ assert( i+fts5YYNFTS5TOKEN<=(int)sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) );
assert( iLookAhead!=fts5YYNOCODE );
assert( iLookAhead < fts5YYNFTS5TOKEN );
i += iLookAhead;
@@ -192497,7 +194816,7 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
}else if( sCtx.pPhrase->nTerm ){
- sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
+ sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
}
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
}
@@ -194960,6 +197279,7 @@ static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){
sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
sqlite3_step(p->pWriter);
p->rc = sqlite3_reset(p->pWriter);
+ sqlite3_bind_null(p->pWriter, 2);
}
/*
@@ -196588,6 +198908,7 @@ static void fts5SegIterSeekInit(
bDlidx = (val & 0x0001);
}
p->rc = sqlite3_reset(pIdxSelect);
+ sqlite3_bind_null(pIdxSelect, 2);
if( iPg<pSeg->pgnoFirst ){
iPg = pSeg->pgnoFirst;
@@ -197800,6 +200121,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
p->rc = sqlite3_reset(pIdxSelect);
+ sqlite3_bind_null(pIdxSelect, 2);
}
}
#endif
@@ -197926,6 +200248,7 @@ static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){
sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
sqlite3_step(p->pIdxWriter);
p->rc = sqlite3_reset(p->pIdxWriter);
+ sqlite3_bind_null(p->pIdxWriter, 2);
}
pWriter->iBtPage = 0;
}
@@ -201239,6 +203562,12 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
aColMap[1] = nCol;
aColMap[2] = nCol+1;
+ assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
+
/* Set idxFlags flags for all WHERE clause terms that will be used. */
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
@@ -201257,11 +203586,11 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
pInfo->estimatedCost = 1e50;
return SQLITE_OK;
}
- }else{
+ }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
int j;
for(j=1; j<ArraySize(aConstraint); j++){
struct Constraint *pC = &aConstraint[j];
- if( iCol==aColMap[pC->iCol] && p->op & pC->op && p->usable ){
+ if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
pC->iConsIndex = i;
idxFlags |= pC->fts5op;
}
@@ -203333,7 +205662,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b", -1, SQLITE_TRANSIENT);
}
static int fts5Init(sqlite3 *db){
@@ -203909,6 +206238,7 @@ static int fts5StorageInsertDocsize(
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
+ sqlite3_bind_null(pReplace, 2);
}
}
return rc;
@@ -204569,6 +206899,7 @@ static int sqlite3Fts5StorageConfigValue(
}
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
+ sqlite3_bind_null(pReplace, 1);
}
if( rc==SQLITE_OK && pVal ){
int iNew = p->pConfig->iCookie + 1;
@@ -207601,9 +209932,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=207604
+#if __LINE__!=209935
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt2"
+#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd14alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h
index d8138b709a..0ba2852d78 100644
--- a/src/3rdparty/sqlite/sqlite3.h
+++ b/src/3rdparty/sqlite/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.22.0"
-#define SQLITE_VERSION_NUMBER 3022000
-#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"
+#define SQLITE_VERSION "3.23.1"
+#define SQLITE_VERSION_NUMBER 3023001
+#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1064,6 +1064,12 @@ struct sqlite3_io_methods {
** so that all subsequent write operations are independent.
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
+** a file lock using the xLock or xShmLock methods of the VFS to wait
+** for up to M milliseconds before failing, where M is the single
+** unsigned integer parameter.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1098,6 +1104,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
+#define SQLITE_FCNTL_LOCK_TIMEOUT 34
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2054,11 +2061,13 @@ struct sqlite3_mem_methods {
** connections at all to the database. If so, it performs a checkpoint
** operation before closing the connection. This option may be used to
** override this behaviour. The first parameter passed to this operation
-** is an integer - non-zero to disable checkpoints-on-close, or zero (the
-** default) to enable them. The second parameter is a pointer to an integer
+** is an integer - positive to disable checkpoints-on-close, or zero (the
+** default) to enable them, and negative to leave the setting unchanged.
+** The second parameter is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
+**
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
@@ -2068,13 +2077,20 @@ struct sqlite3_mem_methods {
** slower. But the QPSG has the advantage of more predictable behavior. With
** the QPSG active, SQLite will always use the same query plan in the field as
** was used during testing in the lab.
+** The first argument to this setting is an integer which is 0 to disable
+** the QPSG, positive to enable QPSG, or negative to leave the setting
+** unchanged. The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether the QPSG is disabled or enabled
+** following this call.
** </dd>
+**
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
** behavior. The first parameter passed to this operation is an integer -
-** non-zero to enable output for trigger programs, or zero to disable it.
+** positive to enable output for trigger programs, or zero to disable it,
+** or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which is written
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
** it is not disabled, 1 if it is.
@@ -2496,16 +2512,16 @@ SQLITE_API void sqlite3_free_table(char **result);
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
-** These routines understand most of the common K&R formatting options,
-** plus some additional non-standard formats, detailed below.
-** Note that some of the more obscure formatting options from recent
-** C-library standards are omitted from this implementation.
+** These routines understand most of the common formatting options from
+** the standard library printf()
+** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
+** See the [built-in printf()] documentation for details.
**
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
-** results into memory obtained from [sqlite3_malloc()].
+** results into memory obtained from [sqlite3_malloc64()].
** The strings returned by these two routines should be
** released by [sqlite3_free()]. ^Both routines return a
-** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
+** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
** memory to hold the resulting string.
**
** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
@@ -2529,71 +2545,7 @@ SQLITE_API void sqlite3_free_table(char **result);
**
** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
**
-** These routines all implement some additional formatting
-** options that are useful for constructing SQL statements.
-** All of the usual printf() formatting options apply. In addition, there
-** is are "%q", "%Q", "%w" and "%z" options.
-**
-** ^(The %q option works like %s in that it substitutes a nul-terminated
-** string from the argument list. But %q also doubles every '\'' character.
-** %q is designed for use inside a string literal.)^ By doubling each '\''
-** character it escapes that character and allows it to be inserted into
-** the string.
-**
-** For example, assume the string variable zText contains text as follows:
-**
-** <blockquote><pre>
-** char *zText = "It's a happy day!";
-** </pre></blockquote>
-**
-** One can use this text in an SQL statement as follows:
-**
-** <blockquote><pre>
-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-** sqlite3_exec(db, zSQL, 0, 0, 0);
-** sqlite3_free(zSQL);
-** </pre></blockquote>
-**
-** Because the %q format string is used, the '\'' character in zText
-** is escaped and the SQL generated is as follows:
-**
-** <blockquote><pre>
-** INSERT INTO table1 VALUES('It''s a happy day!')
-** </pre></blockquote>
-**
-** This is correct. Had we used %s instead of %q, the generated SQL
-** would have looked like this:
-**
-** <blockquote><pre>
-** INSERT INTO table1 VALUES('It's a happy day!');
-** </pre></blockquote>
-**
-** This second example is an SQL syntax error. As a general rule you should
-** always use %q instead of %s when inserting text into a string literal.
-**
-** ^(The %Q option works like %q except it also adds single quotes around
-** the outside of the total string. Additionally, if the parameter in the
-** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
-** single quotes).)^ So, for example, one could say:
-**
-** <blockquote><pre>
-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-** sqlite3_exec(db, zSQL, 0, 0, 0);
-** sqlite3_free(zSQL);
-** </pre></blockquote>
-**
-** The code above will render a correct SQL statement in the zSQL
-** variable even if the zText variable is a NULL pointer.
-**
-** ^(The "%w" formatting option is like "%q" except that it expects to
-** be contained within double-quotes instead of single quotes, and it
-** escapes the double-quote character instead of the single-quote
-** character.)^ The "%w" formatting option is intended for safely inserting
-** table and column names into a constructed SQL statement.
-**
-** ^(The "%z" formatting option works like "%s" but with the
-** addition that after the string has been read and copied into
-** the result, [sqlite3_free()] is called on the input string.)^
+** See also: [built-in printf()], [printf() SQL function]
*/
SQLITE_API char *sqlite3_mprintf(const char*,...);
SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
@@ -3659,13 +3611,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** </li>
+** </ol>
**
** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
** the extra prepFlags parameter, which is a bit array consisting of zero or
** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
** sqlite3_prepare_v2() interface works exactly the same as
** sqlite3_prepare_v3() with a zero prepFlags parameter.
-** </ol>
*/
SQLITE_API int sqlite3_prepare(
sqlite3 *db, /* Database handle */
@@ -7294,6 +7246,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
**
+** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
+** <dd>This parameter returns the number of dirty cache entries that have
+** been written to disk in the middle of a transaction due to the page
+** cache overflowing. Transactions are more efficient if they are written
+** to disk all at once. When pages spill mid-transaction, that introduces
+** additional overhead. This parameter can be used help identify
+** inefficiencies that can be resolve by increasing the cache size.
+** </dd>
+**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
** <dd>This parameter returns zero for the current value if and only if
** all foreign key constraints (deferred or immediate) have been
@@ -7313,7 +7274,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_WRITE 9
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
-#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_CACHE_SPILL 12
+#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
/*
@@ -8794,6 +8756,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
/*
+** CAPI3REF: Serialize a database
+**
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
+** that is a serialization of the S database on [database connection] D.
+** If P is not a NULL pointer, then the size of the database in bytes
+** is written into *P.
+**
+** For an ordinary on-disk database file, the serialization is just a
+** copy of the disk file. For an in-memory database or a "TEMP" database,
+** the serialization is the same sequence of bytes which would be written
+** to disk if that database where backed up to disk.
+**
+** The usual case is that sqlite3_serialize() copies the serialization of
+** the database into memory obtained from [sqlite3_malloc64()] and returns
+** a pointer to that memory. The caller is responsible for freeing the
+** returned value to avoid a memory leak. However, if the F argument
+** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
+** are made, and the sqlite3_serialize() function will return a pointer
+** to the contiguous memory representation of the database that SQLite
+** is currently using for that database, or NULL if the no such contiguous
+** memory representation of the database exists. A contiguous memory
+** representation of the database will usually only exist if there has
+** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
+** values of D and S.
+** The size of the database is written into *P even if the
+** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
+** of the database exists.
+**
+** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
+** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
+** allocation error occurs.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_DESERIALIZE] option.
+*/
+SQLITE_API unsigned char *sqlite3_serialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */
+ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
+ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3_serialize
+**
+** Zero or more of the following constants can be OR-ed together for
+** the F argument to [sqlite3_serialize(D,S,P,F)].
+**
+** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return
+** a pointer to contiguous in-memory database that it is currently using,
+** without making a copy of the database. If SQLite is not currently using
+** a contiguous in-memory database, then this option causes
+** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be
+** using a contiguous in-memory database if it has been initialized by a
+** prior call to [sqlite3_deserialize()].
+*/
+#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */
+
+/*
+** CAPI3REF: Deserialize a database
+**
+** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
+** [database connection] D to disconnect from database S and then
+** reopen S as an in-memory database based on the serialization contained
+** in P. The serialized database P is N bytes in size. M is the size of
+** the buffer P, which might be larger than N. If M is larger than N, and
+** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
+** permitted to add content to the in-memory database as long as the total
+** size does not exceed M bytes.
+**
+** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
+** invoke sqlite3_free() on the serialization buffer when the database
+** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
+** SQLite will try to increase the buffer size using sqlite3_realloc64()
+** if writes on the database cause it to grow larger than M bytes.
+**
+** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
+** database is currently in a read transaction or is involved in a backup
+** operation.
+**
+** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
+** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
+** [sqlite3_free()] is invoked on argument P prior to returning.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_DESERIALIZE] option.
+*/
+SQLITE_API int sqlite3_deserialize(
+ sqlite3 *db, /* The database connection */
+ const char *zSchema, /* Which DB to reopen with the deserialization */
+ unsigned char *pData, /* The serialized database content */
+ sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szBuf, /* Total size of buffer pData[] */
+ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3_deserialize()
+**
+** The following are allowed values for 6th argument (the F argument) to
+** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
+**
+** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
+** in the P argument is held in memory obtained from [sqlite3_malloc64()]
+** and that SQLite should take ownership of this memory and automatically
+** free it when it has finished using it. Without this flag, the caller
+** is resposible for freeing any dynamically allocated memory.
+**
+** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
+** grow the size of the database using calls to [sqlite3_realloc64()]. This
+** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used.
+** Without this flag, the deserialized database cannot increase in size beyond
+** the number of bytes specified by the M parameter.
+**
+** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database
+** should be treated as read-only.
+*/
+#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */
+#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
+#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
+
+/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
@@ -8940,16 +9024,23 @@ extern "C" {
/*
** CAPI3REF: Session Object Handle
+**
+** An instance of this object is a [session] that can be used to
+** record changes to a database.
*/
typedef struct sqlite3_session sqlite3_session;
/*
** CAPI3REF: Changeset Iterator Handle
+**
+** An instance of this object acts as a cursor for iterating
+** over the elements of a [changeset] or [patchset].
*/
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
/*
** CAPI3REF: Create A New Session Object
+** CONSTRUCTOR: sqlite3_session
**
** Create a new session object attached to database handle db. If successful,
** a pointer to the new object is written to *ppSession and SQLITE_OK is
@@ -8986,6 +9077,7 @@ SQLITE_API int sqlite3session_create(
/*
** CAPI3REF: Delete A Session Object
+** DESTRUCTOR: sqlite3_session
**
** Delete a session object previously allocated using
** [sqlite3session_create()]. Once a session object has been deleted, the
@@ -9001,6 +9093,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPI3REF: Enable Or Disable A Session Object
+** METHOD: sqlite3_session
**
** Enable or disable the recording of changes by a session object. When
** enabled, a session object records changes made to the database. When
@@ -9020,6 +9113,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
/*
** CAPI3REF: Set Or Clear the Indirect Change Flag
+** METHOD: sqlite3_session
**
** Each change recorded by a session object is marked as either direct or
** indirect. A change is marked as indirect if either:
@@ -9049,6 +9143,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
/*
** CAPI3REF: Attach A Table To A Session Object
+** METHOD: sqlite3_session
**
** If argument zTab is not NULL, then it is the name of a table to attach
** to the session object passed as the first argument. All subsequent changes
@@ -9111,6 +9206,7 @@ SQLITE_API int sqlite3session_attach(
/*
** CAPI3REF: Set a table filter on a Session Object.
+** METHOD: sqlite3_session
**
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session object, the filter is called
@@ -9129,6 +9225,7 @@ SQLITE_API void sqlite3session_table_filter(
/*
** CAPI3REF: Generate A Changeset From A Session Object
+** METHOD: sqlite3_session
**
** Obtain a changeset containing changes to the tables attached to the
** session object passed as the first argument. If successful,
@@ -9238,7 +9335,8 @@ SQLITE_API int sqlite3session_changeset(
);
/*
-** CAPI3REF: Load The Difference Between Tables Into A Session
+** CAPI3REF: Load The Difference Between Tables Into A Session
+** METHOD: sqlite3_session
**
** If it is not already attached to the session object passed as the first
** argument, this function attaches table zTbl in the same manner as the
@@ -9303,6 +9401,7 @@ SQLITE_API int sqlite3session_diff(
/*
** CAPI3REF: Generate A Patchset From A Session Object
+** METHOD: sqlite3_session
**
** The differences between a patchset and a changeset are that:
**
@@ -9354,6 +9453,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
+** CONSTRUCTOR: sqlite3_changeset_iter
**
** Create an iterator used to iterate through the contents of a changeset.
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
@@ -9394,6 +9494,7 @@ SQLITE_API int sqlite3changeset_start(
/*
** CAPI3REF: Advance A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function may only be used with iterators created by function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
@@ -9418,6 +9519,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -9452,6 +9554,7 @@ SQLITE_API int sqlite3changeset_op(
/*
** CAPI3REF: Obtain The Primary Key Definition Of A Table
+** METHOD: sqlite3_changeset_iter
**
** For each modified table, a changeset includes the following:
**
@@ -9483,6 +9586,7 @@ SQLITE_API int sqlite3changeset_pk(
/*
** CAPI3REF: Obtain old.* Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -9513,6 +9617,7 @@ SQLITE_API int sqlite3changeset_old(
/*
** CAPI3REF: Obtain new.* Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
@@ -9546,6 +9651,7 @@ SQLITE_API int sqlite3changeset_new(
/*
** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function should only be used with iterator objects passed to a
** conflict-handler callback by [sqlite3changeset_apply()] with either
@@ -9573,6 +9679,7 @@ SQLITE_API int sqlite3changeset_conflict(
/*
** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
+** METHOD: sqlite3_changeset_iter
**
** This function may only be called with an iterator passed to an
** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
@@ -9589,6 +9696,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
/*
** CAPI3REF: Finalize A Changeset Iterator
+** METHOD: sqlite3_changeset_iter
**
** This function is used to finalize an iterator allocated with
** [sqlite3changeset_start()].
@@ -9605,6 +9713,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** to that error is returned by this function. Otherwise, SQLITE_OK is
** returned. This is to allow the following pattern (pseudo-code):
**
+** <pre>
** sqlite3changeset_start();
** while( SQLITE_ROW==sqlite3changeset_next() ){
** // Do something with change.
@@ -9613,6 +9722,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** if( rc!=SQLITE_OK ){
** // An error has occurred
** }
+** </pre>
*/
SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
@@ -9660,6 +9770,7 @@ SQLITE_API int sqlite3changeset_invert(
** sqlite3_changegroup object. Calling it produces similar results as the
** following code fragment:
**
+** <pre>
** sqlite3_changegroup *pGrp;
** rc = sqlite3_changegroup_new(&pGrp);
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
@@ -9670,6 +9781,7 @@ SQLITE_API int sqlite3changeset_invert(
** *ppOut = 0;
** *pnOut = 0;
** }
+** </pre>
**
** Refer to the sqlite3_changegroup documentation below for details.
*/
@@ -9685,11 +9797,15 @@ SQLITE_API int sqlite3changeset_concat(
/*
** CAPI3REF: Changegroup Handle
+**
+** A changegroup is an object used to combine two or more
+** [changesets] or [patchsets]
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
** CAPI3REF: Create A New Changegroup Object
+** CONSTRUCTOR: sqlite3_changegroup
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
@@ -9727,6 +9843,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** CAPI3REF: Add A Changeset To A Changegroup
+** METHOD: sqlite3_changegroup
**
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
@@ -9804,6 +9921,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
+** METHOD: sqlite3_changegroup
**
** Obtain a buffer containing a changeset (or patchset) representing the
** current contents of the changegroup. If the inputs to the changegroup
@@ -9834,25 +9952,25 @@ SQLITE_API int sqlite3changegroup_output(
/*
** CAPI3REF: Delete A Changegroup Object
+** DESTRUCTOR: sqlite3_changegroup
*/
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
**
-** Apply a changeset to a database. This function attempts to update the
-** "main" database attached to handle db with the changes found in the
-** changeset passed via the second and third arguments.
+** Apply a changeset or patchset to a database. These functions attempt to
+** update the "main" database attached to handle db with the changes found in
+** the changeset passed via the second and third arguments.
**
-** The fourth argument (xFilter) passed to this function is the "filter
+** The fourth argument (xFilter) passed to these functions is the "filter
** callback". If it is not NULL, then for each table affected by at least one
** change in the changeset, the filter callback is invoked with
** the table name as the second argument, and a copy of the context pointer
-** passed as the sixth argument to this function as the first. If the "filter
-** callback" returns zero, then no attempt is made to apply any changes to
-** the table. Otherwise, if the return value is non-zero or the xFilter
-** argument to this function is NULL, all changes related to the table are
-** attempted.
+** passed as the sixth argument as the first. If the "filter callback"
+** returns zero, then no attempt is made to apply any changes to the table.
+** Otherwise, if the return value is non-zero or the xFilter argument to
+** is NULL, all changes related to the table are attempted.
**
** For each table that is not excluded by the filter callback, this function
** tests that the target database contains a compatible table. A table is
@@ -9897,7 +10015,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** <dl>
** <dt>DELETE Changes<dd>
-** For each DELETE change, this function checks if the target database
+** For each DELETE change, the function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all non-primary key columns also match the values stored in
@@ -9942,7 +10060,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** [SQLITE_CHANGESET_REPLACE].
**
** <dt>UPDATE Changes<dd>
-** For each UPDATE change, this function checks if the target database
+** For each UPDATE change, the function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all modified non-primary key columns also match the values
@@ -9973,11 +10091,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** This can be used to further customize the applications conflict
** resolution strategy.
**
-** All changes made by this function are enclosed in a savepoint transaction.
+** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
+**
+** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
+** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
+** may set (*ppRebase) to point to a "rebase" that may be used with the
+** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
+** is set to the size of the buffer in bytes. It is the responsibility of the
+** caller to eventually free any such buffer using sqlite3_free(). The buffer
+** is only allocated and populated if one or more conflicts were encountered
+** while applying the patchset. See comments surrounding the sqlite3_rebaser
+** APIs for further details.
+**
+** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter.
+**
+** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b>
+** and therefore subject to change.
*/
SQLITE_API int sqlite3changeset_apply(
sqlite3 *db, /* Apply change to "main" db of this handle */
@@ -9994,6 +10129,41 @@ SQLITE_API int sqlite3changeset_apply(
),
void *pCtx /* First argument passed to xConflict */
);
+SQLITE_API int sqlite3changeset_apply_v2(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int nChangeset, /* Size of changeset in bytes */
+ void *pChangeset, /* Changeset blob */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
+ int flags /* Combination of SESSION_APPLY_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_apply_v2
+**
+** The following flags may passed via the 9th parameter to
+** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]:
+**
+** <dl>
+** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd>
+** Usually, the sessions module encloses all operations performed by
+** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The
+** SAVEPOINT is committed if the changeset or patchset is successfully
+** applied, or rolled back if an error occurs. Specifying this flag
+** causes the sessions module to omit this savepoint. In this case, if the
+** caller has an open transaction or savepoint when apply_v2() is called,
+** it may revert the partially applied changeset by rolling it back.
+*/
+#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -10091,6 +10261,161 @@ SQLITE_API int sqlite3changeset_apply(
#define SQLITE_CHANGESET_REPLACE 1
#define SQLITE_CHANGESET_ABORT 2
+/*
+** CAPI3REF: Rebasing changesets
+** EXPERIMENTAL
+**
+** Suppose there is a site hosting a database in state S0. And that
+** modifications are made that move that database to state S1 and a
+** changeset recorded (the "local" changeset). Then, a changeset based
+** on S0 is received from another site (the "remote" changeset) and
+** applied to the database. The database is then in state
+** (S1+"remote"), where the exact state depends on any conflict
+** resolution decisions (OMIT or REPLACE) made while applying "remote".
+** Rebasing a changeset is to update it to take those conflict
+** resolution decisions into account, so that the same conflicts
+** do not have to be resolved elsewhere in the network.
+**
+** For example, if both the local and remote changesets contain an
+** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)":
+**
+** local: INSERT INTO t1 VALUES(1, 'v1');
+** remote: INSERT INTO t1 VALUES(1, 'v2');
+**
+** and the conflict resolution is REPLACE, then the INSERT change is
+** removed from the local changeset (it was overridden). Or, if the
+** conflict resolution was "OMIT", then the local changeset is modified
+** to instead contain:
+**
+** UPDATE t1 SET b = 'v2' WHERE a=1;
+**
+** Changes within the local changeset are rebased as follows:
+**
+** <dl>
+** <dt>Local INSERT<dd>
+** This may only conflict with a remote INSERT. If the conflict
+** resolution was OMIT, then add an UPDATE change to the rebased
+** changeset. Or, if the conflict resolution was REPLACE, add
+** nothing to the rebased changeset.
+**
+** <dt>Local DELETE<dd>
+** This may conflict with a remote UPDATE or DELETE. In both cases the
+** only possible resolution is OMIT. If the remote operation was a
+** DELETE, then add no change to the rebased changeset. If the remote
+** operation was an UPDATE, then the old.* fields of change are updated
+** to reflect the new.* values in the UPDATE.
+**
+** <dt>Local UPDATE<dd>
+** This may conflict with a remote UPDATE or DELETE. If it conflicts
+** with a DELETE, and the conflict resolution was OMIT, then the update
+** is changed into an INSERT. Any undefined values in the new.* record
+** from the update change are filled in using the old.* values from
+** the conflicting DELETE. Or, if the conflict resolution was REPLACE,
+** the UPDATE change is simply omitted from the rebased changeset.
+**
+** If conflict is with a remote UPDATE and the resolution is OMIT, then
+** the old.* values are rebased using the new.* values in the remote
+** change. Or, if the resolution is REPLACE, then the change is copied
+** into the rebased changeset with updates to columns also updated by
+** the conflicting remote UPDATE removed. If this means no columns would
+** be updated, the change is omitted.
+** </dl>
+**
+** A local change may be rebased against multiple remote changes
+** simultaneously. If a single key is modified by multiple remote
+** changesets, they are combined as follows before the local changeset
+** is rebased:
+**
+** <ul>
+** <li> If there has been one or more REPLACE resolutions on a
+** key, it is rebased according to a REPLACE.
+**
+** <li> If there have been no REPLACE resolutions on a key, then
+** the local changeset is rebased according to the most recent
+** of the OMIT resolutions.
+** </ul>
+**
+** Note that conflict resolutions from multiple remote changesets are
+** combined on a per-field basis, not per-row. This means that in the
+** case of multiple remote UPDATE operations, some fields of a single
+** local change may be rebased for REPLACE while others are rebased for
+** OMIT.
+**
+** In order to rebase a local changeset, the remote changeset must first
+** be applied to the local database using sqlite3changeset_apply_v2() and
+** the buffer of rebase information captured. Then:
+**
+** <ol>
+** <li> An sqlite3_rebaser object is created by calling
+** sqlite3rebaser_create().
+** <li> The new object is configured with the rebase buffer obtained from
+** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure().
+** If the local changeset is to be rebased against multiple remote
+** changesets, then sqlite3rebaser_configure() should be called
+** multiple times, in the same order that the multiple
+** sqlite3changeset_apply_v2() calls were made.
+** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase().
+** <li> The sqlite3_rebaser object is deleted by calling
+** sqlite3rebaser_delete().
+** </ol>
+*/
+typedef struct sqlite3_rebaser sqlite3_rebaser;
+
+/*
+** CAPI3REF: Create a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Allocate a new changeset rebaser object. If successful, set (*ppNew) to
+** point to the new object and return SQLITE_OK. Otherwise, if an error
+** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
+** to NULL.
+*/
+SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
+
+/*
+** CAPI3REF: Configure a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Configure the changeset rebaser object to rebase changesets according
+** to the conflict resolutions described by buffer pRebase (size nRebase
+** bytes), which must have been obtained from a previous call to
+** sqlite3changeset_apply_v2().
+*/
+SQLITE_API int sqlite3rebaser_configure(
+ sqlite3_rebaser*,
+ int nRebase, const void *pRebase
+);
+
+/*
+** CAPI3REF: Rebase a changeset
+** EXPERIMENTAL
+**
+** Argument pIn must point to a buffer containing a changeset nIn bytes
+** in size. This function allocates and populates a buffer with a copy
+** of the changeset rebased rebased according to the configuration of the
+** rebaser object passed as the first argument. If successful, (*ppOut)
+** is set to point to the new buffer containing the rebased changset and
+** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
+** responsibility of the caller to eventually free the new buffer using
+** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
+** are set to zero and an SQLite error code returned.
+*/
+SQLITE_API int sqlite3rebaser_rebase(
+ sqlite3_rebaser*,
+ int nIn, const void *pIn,
+ int *pnOut, void **ppOut
+);
+
+/*
+** CAPI3REF: Delete a changeset rebaser object.
+** EXPERIMENTAL
+**
+** Delete the changeset rebaser object and all associated resources. There
+** should be one call to this function for each successful invocation
+** of sqlite3rebaser_create().
+*/
+SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
+
/*
** CAPI3REF: Streaming Versions of API functions.
**
@@ -10100,6 +10425,7 @@ SQLITE_API int sqlite3changeset_apply(
** <table border=1 style="margin-left:8ex;margin-right:8ex">
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply]
+** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2]
** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat]
** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert]
** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start]
@@ -10195,6 +10521,23 @@ SQLITE_API int sqlite3changeset_apply_strm(
),
void *pCtx /* First argument passed to xConflict */
);
+SQLITE_API int sqlite3changeset_apply_v2_strm(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
+ void *pIn, /* First arg for xInput */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ const char *zTab /* Table name */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
+);
SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
@@ -10232,6 +10575,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
+SQLITE_API int sqlite3rebaser_rebase_strm(
+ sqlite3_rebaser *pRebaser,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int (*xOutput)(void *pOut, const void *pData, int nData),
+ void *pOut
+);
/*
diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp
index 9cf82c786a..8424dbe97d 100644
--- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp
+++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp
@@ -172,9 +172,10 @@ QFuture<QImage> thumbNails =
//! [13]
QList<QImage> images = ...;
-QFuture<QImage> thumbnails = QtConcurrent::mapped(images, [](const QImage &img) {
+std::function<QImage(const QImage &)> scale = [](const QImage &img) {
return img.scaledToWidth(100, Qt::SmoothTransformation);
-});
+};
+QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);
//! [13]
//! [14]
diff --git a/src/corelib/Qt5Config.cmake.in b/src/corelib/Qt5Config.cmake.in
index 75b53485b7..6b6544f932 100644
--- a/src/corelib/Qt5Config.cmake.in
+++ b/src/corelib/Qt5Config.cmake.in
@@ -1,6 +1,6 @@
-if (CMAKE_VERSION VERSION_LESS 2.8.9)
- message(FATAL_ERROR \"Qt5 requires at least CMake version 2.8.9\")
+if (CMAKE_VERSION VERSION_LESS 3.1.0)
+ message(FATAL_ERROR \"Qt5 requires at least CMake version 3.1.0\")
endif()
if (NOT Qt5_FIND_COMPONENTS)
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
index 545b9a3d1e..e0652fdcf9 100644
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
@@ -78,27 +78,10 @@ set(Qt5_POSITION_INDEPENDENT_CODE True)
# Applications now need to be compiled with the -fPIC option if the Qt option
# \"reduce relocations\" is active. For backward compatibility only, Qt accepts
# the use of -fPIE for GCC 4.x versions.
-if (CMAKE_VERSION VERSION_LESS 2.8.12
- AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
- OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
- set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
-else()
- set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP)
-endif()
+set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP)
-# Applications using qmake or cmake >= 2.8.12 as their build system will
-# adapt automatically. Applications using an older release of cmake in
-# combination with GCC 5.x need to change their CMakeLists.txt to add
-# Qt5Core_EXECUTABLE_COMPILE_FLAGS to CMAKE_CXX_FLAGS. In particular,
-# applications using cmake >= 2.8.9 and < 2.8.11 will continue to build
-# with the -fPIE option and invoke the special compatibility mode if using
-# GCC 4.x.
+# TODO Qt6: Remove
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"\")
-if (CMAKE_VERSION VERSION_LESS 2.8.12
- AND (CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\"
- AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
- set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
-endif()
!!IF !isEmpty(QT_NAMESPACE)
list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE)
@@ -157,7 +140,7 @@ if (NOT TARGET Qt5::WinMain)
)
!!ENDIF
- if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT Qt5_NO_LINK_QTMAIN)
+ if (NOT Qt5_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:Qt5_NO_LINK_QTMAIN>>>)
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
index 8d3dbe3ecf..1627de4002 100644
--- a/src/corelib/Qt5CoreMacros.cmake
+++ b/src/corelib/Qt5CoreMacros.cmake
@@ -152,9 +152,6 @@ function(QT5_GENERATE_MOC infile outfile )
set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}")
endif()
if ("x${ARGV2}" STREQUAL "xTARGET")
- if (CMAKE_VERSION VERSION_LESS 2.8.12)
- message(FATAL_ERROR "The TARGET parameter to qt5_generate_moc is only available when using CMake 2.8.12 or later.")
- endif()
set(moc_target ${ARGV3})
endif()
qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "")
@@ -178,9 +175,6 @@ function(QT5_WRAP_CPP outfiles )
set(moc_target ${_WRAP_CPP_TARGET})
set(moc_depends ${_WRAP_CPP_DEPENDS})
- if (moc_target AND CMAKE_VERSION VERSION_LESS 2.8.12)
- message(FATAL_ERROR "The TARGET parameter to qt5_wrap_cpp is only available when using CMake 2.8.12 or later.")
- endif()
foreach(it ${moc_files})
get_filename_component(it ${it} ABSOLUTE)
qt5_make_output_file(${it} moc_ cpp outfile)
@@ -300,54 +294,3 @@ function(QT5_ADD_RESOURCES outfiles )
endfunction()
set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
-
-if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
- macro(qt5_use_modules _target _link_type)
- if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11)
- if(CMAKE_WARN_DEPRECATED)
- set(messageType WARNING)
- endif()
- if(CMAKE_ERROR_DEPRECATED)
- set(messageType FATAL_ERROR)
- endif()
- if(messageType)
- message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.")
- endif()
- endif()
-
- if (NOT TARGET ${_target})
- message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.")
- endif()
- if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" )
- set(_qt5_modules ${ARGN})
- set(_qt5_link_type ${_link_type})
- else()
- set(_qt5_modules ${_link_type} ${ARGN})
- endif()
-
- if ("${_qt5_modules}" STREQUAL "")
- message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.")
- endif()
-
- foreach(_module ${_qt5_modules})
- if (NOT Qt5${_module}_FOUND)
- find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH)
- if (NOT Qt5${_module}_FOUND)
- message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.")
- endif()
- endif()
- target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
- set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS})
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS})
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
- set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
- if (Qt5_POSITION_INDEPENDENT_CODE
- AND (CMAKE_VERSION VERSION_LESS 2.8.12
- AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
- OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)))
- set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
- endif()
- endforeach()
- endmacro()
-endif()
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri
deleted file mode 100644
index e490617c6b..0000000000
--- a/src/corelib/arch/arch.pri
+++ /dev/null
@@ -1,7 +0,0 @@
-win32:HEADERS += arch/qatomic_msvc.h
-
-HEADERS += \
- arch/qatomic_bootstrap.h \
- arch/qatomic_cxx11.h
-
-qtConfig(std-atomic64): QMAKE_USE += libatomic
diff --git a/src/corelib/arch/qatomic_msvc.h b/src/corelib/arch/qatomic_msvc.h
deleted file mode 100644
index 5eae2bdc48..0000000000
--- a/src/corelib/arch/qatomic_msvc.h
+++ /dev/null
@@ -1,485 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** 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$
-**
-****************************************************************************/
-
-#ifndef QATOMIC_MSVC_H
-#define QATOMIC_MSVC_H
-
-#include <QtCore/qgenericatomic.h>
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// use compiler intrinsics for all atomic functions
-# define QT_INTERLOCKED_PREFIX _
-# define QT_INTERLOCKED_PROTOTYPE
-# define QT_INTERLOCKED_DECLARE_PROTOTYPES
-# define QT_INTERLOCKED_INTRINSIC
-# define Q_ATOMIC_INT16_IS_SUPPORTED
-
-# ifdef _WIN64
-# define Q_ATOMIC_INT64_IS_SUPPORTED
-# endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Prototype declaration
-
-#define QT_INTERLOCKED_CONCAT_I(prefix, suffix) \
- prefix ## suffix
-#define QT_INTERLOCKED_CONCAT(prefix, suffix) \
- QT_INTERLOCKED_CONCAT_I(prefix, suffix)
-
-// MSVC intrinsics prefix function names with an underscore. Also, if platform
-// SDK headers have been included, the Interlocked names may be defined as
-// macros.
-// To avoid double underscores, we paste the prefix with Interlocked first and
-// then the remainder of the function name.
-#define QT_INTERLOCKED_FUNCTION(name) \
- QT_INTERLOCKED_CONCAT( \
- QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, Interlocked), name)
-
-#ifndef QT_INTERLOCKED_VOLATILE
-# define QT_INTERLOCKED_VOLATILE volatile
-#endif
-
-#ifndef QT_INTERLOCKED_PREFIX
-#define QT_INTERLOCKED_PREFIX
-#endif
-
-#ifndef QT_INTERLOCKED_PROTOTYPE
-#define QT_INTERLOCKED_PROTOTYPE
-#endif
-
-#ifdef QT_INTERLOCKED_DECLARE_PROTOTYPES
-#undef QT_INTERLOCKED_DECLARE_PROTOTYPES
-
-extern "C" {
-
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment )(long QT_INTERLOCKED_VOLATILE *);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement )(long QT_INTERLOCKED_VOLATILE *);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange )(long QT_INTERLOCKED_VOLATILE *, long);
- long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long);
-
-# if !defined(__i386__) && !defined(_M_IX86)
- void * QT_INTERLOCKED_FUNCTION( CompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *);
- void * QT_INTERLOCKED_FUNCTION( ExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *);
- __int64 QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
-# endif
-
-# ifdef Q_ATOMIC_INT16_IS_SUPPORTED
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment16 )(short QT_INTERLOCKED_VOLATILE *);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement16 )(short QT_INTERLOCKED_VOLATILE *);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange16 )(short QT_INTERLOCKED_VOLATILE *, short, short);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange16 )(short QT_INTERLOCKED_VOLATILE *, short);
- short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd16 )(short QT_INTERLOCKED_VOLATILE *, short);
-# endif
-# ifdef Q_ATOMIC_INT64_IS_SUPPORTED
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment64 )(__int64 QT_INTERLOCKED_VOLATILE *);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement64 )(__int64 QT_INTERLOCKED_VOLATILE *);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64, __int64);
- __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
- //above already: qint64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(qint64 QT_INTERLOCKED_VOLATILE *, qint64);
-# endif
-}
-
-#endif // QT_INTERLOCKED_DECLARE_PROTOTYPES
-
-#undef QT_INTERLOCKED_PROTOTYPE
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef QT_INTERLOCKED_INTRINSIC
-#undef QT_INTERLOCKED_INTRINSIC
-
-# pragma intrinsic (_InterlockedIncrement)
-# pragma intrinsic (_InterlockedDecrement)
-# pragma intrinsic (_InterlockedExchange)
-# pragma intrinsic (_InterlockedCompareExchange)
-# pragma intrinsic (_InterlockedExchangeAdd)
-
-# if !defined(_M_IX86)
-# pragma intrinsic (_InterlockedCompareExchangePointer)
-# pragma intrinsic (_InterlockedExchangePointer)
-# pragma intrinsic (_InterlockedExchangeAdd64)
-# endif
-
-#endif // QT_INTERLOCKED_INTRINSIC
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Interlocked* replacement macros
-
-#if defined(__i386__) || defined(_M_IX86)
-
-# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
- reinterpret_cast<void *>( \
- QT_INTERLOCKED_FUNCTION(CompareExchange)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- long(newValue), \
- long(expectedValue)))
-
-# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
- QT_INTERLOCKED_FUNCTION(Exchange)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- long(newValue))
-
-# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
- QT_INTERLOCKED_FUNCTION(ExchangeAdd)( \
- reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
- (valueToAdd))
-
-#else // !defined(__i386__) && !defined(_M_IX86)
-
-# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
- QT_INTERLOCKED_FUNCTION(CompareExchangePointer)( \
- (void * QT_INTERLOCKED_VOLATILE *)(value), \
- (void *) (newValue), \
- (void *) (expectedValue))
-
-# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
- QT_INTERLOCKED_FUNCTION(ExchangePointer)( \
- (void * QT_INTERLOCKED_VOLATILE *)(value), \
- (void *) (newValue))
-
-# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
- QT_INTERLOCKED_FUNCTION(ExchangeAdd64)( \
- reinterpret_cast<qint64 QT_INTERLOCKED_VOLATILE *>(value), \
- (valueToAdd))
-
-#endif // !defined(__i386__) && !defined(_M_IX86)
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-QT_BEGIN_NAMESPACE
-
-#if 0
-// silence syncqt warnings
-QT_END_NAMESPACE
-#pragma qt_sync_skip_header_check
-#pragma qt_sync_stop_processing
-#endif
-
-#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_IS_SUPPORTED
-
-#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
-
-#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
-
-#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
-# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE
-
-template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
-#endif
-
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_WAIT_FREE
-
-# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE
-
-template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-template <int N> struct QAtomicWindowsType { typedef typename QIntegerForSize<N>::Signed Type; };
-template <> struct QAtomicWindowsType<4> { typedef long Type; };
-
-
-template <int N> struct QAtomicOpsBySize : QGenericAtomicOps<QAtomicOpsBySize<N> >
-{
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW;
- template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW;
- template <typename T>
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW;
-
-private:
- typedef typename QAtomicWindowsType<N>::Type Type;
- template <typename T> static inline Type *atomic(T *t)
- { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return reinterpret_cast<Type *>(t); }
- template <typename T> static inline Type value(T t)
- { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return Type(t); }
-};
-
-template <typename T>
-struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
-{
- typedef T Type;
-};
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::ref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::deref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Exchange)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-
-#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::ref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::deref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Exchange16)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-#endif
-
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::ref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::deref(T &_q_value) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0;
-}
-
-template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
-}
-
-template<> template <typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
-{
- *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(Exchange64)(atomic(&_q_value), value(newValue));
-}
-
-template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
-}
-#endif
-
-// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations
-template <typename T>
-struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
-{
- typedef T *Type;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW;
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW;
-};
-
-template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW
-{
- return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue;
-}
-
-template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW
-{
- *currentValue = reinterpret_cast<T *>(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue));
- return *currentValue == expectedValue;
-}
-
-template <typename T>
-inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW
-{
- return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
-}
-
-template <typename T>
-inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW
-{
- return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Cleanup
-
-#undef QT_INTERLOCKED_CONCAT_I
-#undef QT_INTERLOCKED_CONCAT
-#undef QT_INTERLOCKED_FUNCTION
-#undef QT_INTERLOCKED_PREFIX
-
-#undef QT_INTERLOCKED_VOLATILE
-
-#undef QT_INTERLOCKED_INCREMENT
-#undef QT_INTERLOCKED_DECREMENT
-#undef QT_INTERLOCKED_COMPARE_EXCHANGE
-#undef QT_INTERLOCKED_EXCHANGE
-#undef QT_INTERLOCKED_EXCHANGE_ADD
-#undef QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER
-#undef QT_INTERLOCKED_EXCHANGE_POINTER
-#undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER
-
-QT_END_NAMESPACE
-#endif // QATOMIC_MSVC_H
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 3db2e2ceb8..7f62a6f1b0 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -32,7 +32,6 @@ ANDROID_PERMISSIONS = \
freebsd|openbsd: QMAKE_LFLAGS_NOUNDEF =
include(animation/animation.pri)
-include(arch/arch.pri)
include(global/global.pri)
include(thread/thread.pri)
include(tools/tools.pri)
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
index a17e541df3..d163129d54 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
@@ -395,10 +395,10 @@ QByteArray ba = QByteArray::number(12.3456, 'E', 3);
//! [43]
static const char mydata[] = {
- 0x00, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76,
- 0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99,
+ '\x00', '\x00', '\x03', '\x84', '\x78', '\x9c', '\x3b', '\x76',
+ '\xec', '\x18', '\xc3', '\x31', '\x0a', '\xf1', '\xcc', '\x99',
...
- 0x6d, 0x5b
+ '\x6d', '\x5b'
};
QByteArray data = QByteArray::fromRawData(mydata, sizeof(mydata));
diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc
index ab35e7c178..9ef08cce07 100644
--- a/src/corelib/doc/src/objectmodel/properties.qdoc
+++ b/src/corelib/doc/src/objectmodel/properties.qdoc
@@ -133,7 +133,7 @@
editable property for (checkable) buttons. Note that QItemDelegate
gets and sets a widget's \c USER property.
- \li The presence of the \c CONSTANT attibute indicates that the property
+ \li The presence of the \c CONSTANT attribute indicates that the property
value is constant. For a given object instance, the READ method of a
constant property must return the same value every time it is called. This
constant value may be different for different instances of the object. A
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index 86ef1a2613..3469ebe5e6 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -87,6 +87,7 @@
#define QT_FEATURE_journald -1
#define QT_FEATURE_futimens -1
#define QT_FEATURE_futimes -1
+#define QT_FEATURE_itemmodel -1
#define QT_FEATURE_library -1
#ifdef __linux__
# define QT_FEATURE_linkat 1
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 2d8b860c5b..ad015ee048 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2856,7 +2856,7 @@ enum {
};
/*!
- \since 5.10
+ \since 5.11
Returns a unique ID for this machine, if one can be determined. If no
unique ID could be determined, this function returns an empty byte array.
@@ -2929,7 +2929,7 @@ QByteArray QSysInfo::machineUniqueId()
}
/*!
- \since 5.10
+ \since 5.11
Returns a unique ID for this machine's boot, if one can be determined. If
no unique ID could be determined, this function returns an empty byte
@@ -4439,7 +4439,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
Calls the message handler with the critical message \a message. If no
message handler has been installed, the message is printed to
stderr. Under Windows, the message is sent to the debugger.
- On QNX the message is sent to slogger2
+ On QNX the message is sent to slogger2.
It exits if the environment variable QT_FATAL_CRITICALS is not empty.
@@ -4472,7 +4472,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
Calls the message handler with the fatal message \a message. If no
message handler has been installed, the message is printed to
stderr. Under Windows, the message is sent to the debugger.
- On QNX the message is sent to slogger2
+ On QNX the message is sent to slogger2.
If you are using the \b{default message handler} this function will
abort to create a core dump. On Windows, for debug builds,
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index cd4b4a29a9..e31d4d9ad7 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -242,8 +242,13 @@ typedef unsigned int quint32; /* 32 bit unsigned */
typedef __int64 qint64; /* 64 bit signed */
typedef unsigned __int64 quint64; /* 64 bit unsigned */
#else
+#ifdef __cplusplus
# define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */
# define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */
+#else
+# define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */
+# define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */
+#endif
typedef long long qint64; /* 64 bit signed */
typedef unsigned long long quint64; /* 64 bit unsigned */
#endif
@@ -742,12 +747,13 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW;
# define QT_DEBUG
#endif
+// QtPrivate::asString defined in qstring.h
#ifndef qPrintable
-# define qPrintable(string) QString(string).toLocal8Bit().constData()
+# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
#endif
#ifndef qUtf8Printable
-# define qUtf8Printable(string) QString(string).toUtf8().constData()
+# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData()
#endif
/*
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 99c57c3b7a..17002c4231 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -91,8 +91,7 @@
# include "private/qcore_unix_p.h"
#endif
-#ifndef QT_BOOTSTRAPPED
-#if !defined QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
# ifdef __UCLIBC__
# if __UCLIBC_HAS_BACKTRACE__
# define QLOGGING_HAVE_BACKTRACE
@@ -106,6 +105,7 @@
extern char *__progname;
#endif
+#ifndef QT_BOOTSTRAPPED
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
# include <sys/syscall.h>
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 9143e04d45..ebf9864b15 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -48,9 +48,7 @@
#include <errno.h>
-#if QT_CONFIG(getentropy)
-# include <sys/random.h>
-#elif !defined(Q_OS_BSD4) && !defined(Q_OS_WIN)
+#if !QT_CONFIG(getentropy) && !defined(Q_OS_BSD4) && !defined(Q_OS_WIN)
# include "qdeadlinetimer.h"
# include "qhashfunctions.h"
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 520f98b18f..e4d384e4ca 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -750,13 +750,47 @@ QString QDir::filePath(const QString &fileName) const
QString QDir::absoluteFilePath(const QString &fileName) const
{
const QDirPrivate* d = d_ptr.constData();
- if (isAbsolutePath(fileName))
+ // Don't trust our own isAbsolutePath(); Q_OS_WIN needs a drive.
+ if (QFileSystemEntry(fileName).isAbsolute())
return fileName;
d->resolveAbsoluteEntry();
const QString absoluteDirPath = d->absoluteDirEntry.filePath();
if (fileName.isEmpty())
return absoluteDirPath;
+#ifdef Q_OS_WIN
+ // Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
+ int size = absoluteDirPath.length();
+ if ((fileName.startsWith(QLatin1Char('/'))
+ || fileName.startsWith(QLatin1Char('\\')))
+ && size > 1) {
+ // Combine absoluteDirPath's drive with fileName
+ int drive = 2; // length of drive prefix
+ if (Q_UNLIKELY(absoluteDirPath.at(1).unicode() != ':')) {
+ // Presumably, absoluteDirPath is an UNC path; use its //server/share
+ // part as "drive" - it's as sane a thing as we can do.
+ for (int i = 2; i-- > 0; ) { // Scan two "path fragments":
+ while (drive < size && absoluteDirPath.at(drive).unicode() == '/')
+ drive++;
+ if (drive >= size) {
+ qWarning("Base directory starts with neither a drive nor a UNC share: %s",
+ qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
+ return QString();
+ }
+ while (drive < size && absoluteDirPath.at(drive).unicode() != '/')
+ drive++;
+ }
+ // We'll append fileName, which starts with a slash; so omit trailing slash:
+ if (absoluteDirPath.at(drive).unicode() == '/')
+ drive--;
+ } else if (!absoluteDirPath.at(0).isLetter()) {
+ qWarning("Base directory's drive is not a letter: %s",
+ qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
+ return QString();
+ }
+ return absoluteDirPath.leftRef(drive) % fileName;
+ }
+#endif // Q_OS_WIN
if (!absoluteDirPath.endsWith(QLatin1Char('/')))
return absoluteDirPath % QLatin1Char('/') % fileName;
return absoluteDirPath % fileName;
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 33b0b2eb66..3166fa1b83 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -676,8 +676,11 @@ QFile::rename(const QString &newName)
return !error;
}
close();
+ d->setError(QFile::RenameError,
+ tr("Cannot open destination file: %1").arg(out.errorString()));
+ } else {
+ d->setError(QFile::RenameError, errorString());
}
- d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString());
}
return false;
}
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index ea85498b70..0c38731052 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -91,26 +91,35 @@ extern "C" NSString *NSTemporaryDirectory();
# include <sys/syscall.h>
# include <sys/sendfile.h>
# include <linux/fs.h>
+# include <linux/stat.h>
// in case linux/fs.h is too old and doesn't define it:
#ifndef FICLONE
# define FICLONE _IOW(0x94, 9, int)
#endif
-# if !QT_CONFIG(renameat2) && defined(SYS_renameat2)
+# if defined(Q_OS_ANDROID)
+// renameat2() and statx() are disabled on Android because quite a few systems
+// come with sandboxes that kill applications that make system calls outside a
+// whitelist and several Android vendors can't be bothered to update the list.
+# undef SYS_renameat2
+# undef SYS_statx
+# undef STATX_BASIC_STATS
+# else
+# if !QT_CONFIG(renameat2) && defined(SYS_renameat2)
static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newpath, unsigned flags)
{ return syscall(SYS_renameat2, oldfd, oldpath, newfd, newpath, flags); }
-# endif
+# endif
-# if !QT_CONFIG(statx) && defined(SYS_statx) && QT_HAS_INCLUDE(<linux/stat.h>)
-# include <linux/stat.h>
+# if !QT_CONFIG(statx) && defined(SYS_statx)
static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struct statx *statxbuf)
{ return syscall(SYS_statx, dirfd, pathname, flag, mask, statxbuf); }
-# endif
+# endif
+# endif // !Q_OS_ANDROID
#endif
-#ifndef STATX_BASIC_STATS
-struct statx { mode_t stx_mode; };
+#ifndef STATX_ALL
+struct statx { mode_t stx_mode; }; // dummy
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index 02b12f635a..039e291b43 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -216,7 +216,10 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
quint16 x = ll;
- if (!ok || ll != x)
+ // Reject malformed fields:
+ // - failed to parse
+ // - too many hex digits
+ if (!ok || endptr > ptr + 4)
return begin + (ptr - buffer.data());
if (*endptr == '.') {
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 35a0de4fb7..7502fb57a3 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -116,7 +116,7 @@ public:
inline bool isContainer(int node) const { return flags(node) & Directory; }
inline bool isCompressed(int node) const { return flags(node) & Compressed; }
const uchar *data(int node, qint64 *size) const;
- QDateTime lastModified(int node) const;
+ quint64 lastModified(int node) const;
QStringList children(int node) const;
virtual QString mappingRoot() const { return QString(); }
bool mappingRootSubdir(const QString &path, QString *match=0) const;
@@ -245,7 +245,7 @@ public:
mutable qint64 size;
mutable const uchar *data;
mutable QStringList children;
- mutable QDateTime lastModified;
+ mutable quint64 lastModified;
QResource *q_ptr;
Q_DECLARE_PUBLIC(QResource)
@@ -259,7 +259,7 @@ QResourcePrivate::clear()
data = 0;
size = 0;
children.clear();
- lastModified = QDateTime();
+ lastModified = 0;
container = 0;
for(int i = 0; i < related.size(); ++i) {
QResourceRoot *root = related.at(i);
@@ -301,7 +301,7 @@ QResourcePrivate::load(const QString &file)
data = 0;
size = 0;
compressed = 0;
- lastModified = QDateTime();
+ lastModified = 0;
res->ref.ref();
related.append(res);
}
@@ -539,7 +539,7 @@ QDateTime QResource::lastModified() const
{
Q_D(const QResource);
d->ensureInitialized();
- return d->lastModified;
+ return d->lastModified ? QDateTime::fromMSecsSinceEpoch(d->lastModified) : QDateTime();
}
/*!
@@ -797,18 +797,14 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
return 0;
}
-QDateTime QResourceRoot::lastModified(int node) const
+quint64 QResourceRoot::lastModified(int node) const
{
if (node == -1 || version < 0x02)
- return QDateTime();
+ return 0;
const int offset = findOffset(node) + 14;
- const quint64 timeStamp = qFromBigEndian<quint64>(tree + offset);
- if (timeStamp == 0)
- return QDateTime();
-
- return QDateTime::fromMSecsSinceEpoch(timeStamp);
+ return qFromBigEndian<quint64>(tree + offset);
}
QStringList QResourceRoot::children(int node) const
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index e49edd9a40..748ce67dac 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -42,7 +42,9 @@
#include <qfile.h>
#include <qhash.h>
#include <qtextstream.h>
+#if QT_CONFIG(regularexpression)
#include <qregularexpression.h>
+#endif
#include <private/qfilesystemengine_p.h>
#include <errno.h>
#include <stdlib.h>
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 3055fb392e..2312d5ca63 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -316,15 +316,15 @@ void QWindowsPipeReader::emitPendingReadyRead()
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
- if (!readSequenceStarted)
- return false;
-
if (readyReadPending) {
if (!inReadyRead)
emitPendingReadyRead();
return true;
}
+ if (!readSequenceStarted)
+ return false;
+
if (!waitForNotification(msecs))
return false;
diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri
index 83ec4c5dbf..068a8c4b3a 100644
--- a/src/corelib/itemmodels/itemmodels.pri
+++ b/src/corelib/itemmodels/itemmodels.pri
@@ -1,20 +1,46 @@
# Qt itemmodels core module
+!qtConfig(itemmodel): return()
+
HEADERS += \
itemmodels/qabstractitemmodel.h \
itemmodels/qabstractitemmodel_p.h \
- itemmodels/qabstractproxymodel.h \
- itemmodels/qabstractproxymodel_p.h \
itemmodels/qitemselectionmodel.h \
- itemmodels/qitemselectionmodel_p.h \
- itemmodels/qidentityproxymodel.h \
- itemmodels/qsortfilterproxymodel.h \
- itemmodels/qstringlistmodel.h
+ itemmodels/qitemselectionmodel_p.h
SOURCES += \
itemmodels/qabstractitemmodel.cpp \
- itemmodels/qabstractproxymodel.cpp \
- itemmodels/qitemselectionmodel.cpp \
- itemmodels/qidentityproxymodel.cpp \
- itemmodels/qsortfilterproxymodel.cpp \
- itemmodels/qstringlistmodel.cpp
+ itemmodels/qitemselectionmodel.cpp
+
+qtConfig(proxymodel) {
+ HEADERS += \
+ itemmodels/qabstractproxymodel.h \
+ itemmodels/qabstractproxymodel_p.h
+
+ SOURCES += \
+ itemmodels/qabstractproxymodel.cpp
+
+ qtConfig(identityproxymodel) {
+ HEADERS += \
+ itemmodels/qidentityproxymodel.h
+
+ SOURCES += \
+ itemmodels/qidentityproxymodel.cpp
+ }
+
+ qtConfig(sortfilterproxymodel) {
+ HEADERS += \
+ itemmodels/qsortfilterproxymodel.h
+
+ SOURCES += \
+ itemmodels/qsortfilterproxymodel.cpp
+ }
+}
+
+qtConfig(stringlistmodel) {
+ HEADERS += \
+ itemmodels/qstringlistmodel.h
+
+ SOURCES += \
+ itemmodels/qstringlistmodel.cpp
+}
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index fca21b9bbc..21171124f9 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -45,6 +45,8 @@
#include <QtCore/qhash.h>
#include <QtCore/qvector.h>
+QT_REQUIRE_CONFIG(itemmodel);
+
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h
index 7086ae730a..12fd93d217 100644
--- a/src/corelib/itemmodels/qabstractitemmodel_p.h
+++ b/src/corelib/itemmodels/qabstractitemmodel_p.h
@@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
+QT_REQUIRE_CONFIG(itemmodel);
+
class QPersistentModelIndexData
{
public:
diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp
index 39bfdd7782..b7c49a53e4 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.cpp
+++ b/src/corelib/itemmodels/qabstractproxymodel.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include "qabstractproxymodel.h"
-
-#ifndef QT_NO_PROXYMODEL
-
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
#include <QtCore/QSize>
@@ -471,5 +468,3 @@ Qt::DropActions QAbstractProxyModel::supportedDropActions() const
QT_END_NAMESPACE
#include "moc_qabstractproxymodel.cpp"
-
-#endif // QT_NO_PROXYMODEL
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index 6aa82b21ee..c4e5d67908 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -42,10 +42,9 @@
#include <QtCore/qabstractitemmodel.h>
-QT_BEGIN_NAMESPACE
-
+QT_REQUIRE_CONFIG(proxymodel);
-#ifndef QT_NO_PROXYMODEL
+QT_BEGIN_NAMESPACE
class QAbstractProxyModelPrivate;
class QItemSelection;
@@ -112,8 +111,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed())
};
-#endif // QT_NO_PROXYMODEL
-
QT_END_NAMESPACE
#endif // QABSTRACTPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h
index 929bf1eb75..3a9f33baba 100644
--- a/src/corelib/itemmodels/qabstractproxymodel_p.h
+++ b/src/corelib/itemmodels/qabstractproxymodel_p.h
@@ -54,7 +54,7 @@
#include "private/qabstractitemmodel_p.h"
-#ifndef QT_NO_PROXYMODEL
+QT_REQUIRE_CONFIG(proxymodel);
QT_BEGIN_NAMESPACE
@@ -71,6 +71,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_PROXYMODEL
-
#endif // QABSTRACTPROXYMODEL_P_H
diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp
index 7c306799d0..e984ec194e 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.cpp
+++ b/src/corelib/itemmodels/qidentityproxymodel.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include "qidentityproxymodel.h"
-
-#ifndef QT_NO_IDENTITYPROXYMODEL
-
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
@@ -616,5 +613,3 @@ void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent,
QT_END_NAMESPACE
#include "moc_qidentityproxymodel.cpp"
-
-#endif // QT_NO_IDENTITYPROXYMODEL
diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h
index d2b1ed9498..3e6f5e4c48 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.h
+++ b/src/corelib/itemmodels/qidentityproxymodel.h
@@ -43,7 +43,7 @@
#include <QtCore/qabstractproxymodel.h>
-#ifndef QT_NO_IDENTITYPROXYMODEL
+QT_REQUIRE_CONFIG(identityproxymodel);
QT_BEGIN_NAMESPACE
@@ -110,7 +110,5 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_IDENTITYPROXYMODEL
-
#endif // QIDENTITYPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index 091c5a21a5..63e5f0ca9c 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -47,6 +47,8 @@
#include <QtCore/qlist.h>
#include <QtCore/qabstractitemmodel.h>
+QT_REQUIRE_CONFIG(itemmodel);
+
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QItemSelectionRange
diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h
index dfc0387563..187d4a2c1d 100644
--- a/src/corelib/itemmodels/qitemselectionmodel_p.h
+++ b/src/corelib/itemmodels/qitemselectionmodel_p.h
@@ -53,6 +53,8 @@
#include "private/qobject_p.h"
+QT_REQUIRE_CONFIG(itemmodel);
+
QT_BEGIN_NAMESPACE
class QItemSelectionModelPrivate: public QObjectPrivate
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 220c6be79e..78093727b8 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include "qsortfilterproxymodel.h"
-
-#ifndef QT_NO_SORTFILTERPROXYMODEL
-
#include "qitemselectionmodel.h"
#include <qsize.h>
#include <qdebug.h>
@@ -2883,5 +2880,3 @@ QItemSelection QSortFilterProxyModel::mapSelectionFromSource(const QItemSelectio
QT_END_NAMESPACE
#include "moc_qsortfilterproxymodel.cpp"
-
-#endif // QT_NO_SORTFILTERPROXYMODEL
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 196dab2770..907ceb8e6d 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -41,11 +41,10 @@
#define QSORTFILTERPROXYMODEL_H
#include <QtCore/qabstractproxymodel.h>
-
-#ifndef QT_NO_SORTFILTERPROXYMODEL
-
#include <QtCore/qregexp.h>
+QT_REQUIRE_CONFIG(sortfilterproxymodel);
+
QT_BEGIN_NAMESPACE
@@ -198,6 +197,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_SORTFILTERPROXYMODEL
-
#endif // QSORTFILTERPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index bcfd88fb19..567e6fa35e 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -47,8 +47,6 @@
#include <algorithm>
-#ifndef QT_NO_STRINGLISTMODEL
-
QT_BEGIN_NAMESPACE
/*!
@@ -329,5 +327,3 @@ Qt::DropActions QStringListModel::supportedDropActions() const
QT_END_NAMESPACE
#include "moc_qstringlistmodel.cpp"
-
-#endif // QT_NO_STRINGLISTMODEL
diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h
index 38da1022ea..a40c13ae40 100644
--- a/src/corelib/itemmodels/qstringlistmodel.h
+++ b/src/corelib/itemmodels/qstringlistmodel.h
@@ -43,10 +43,9 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtCore/qstringlist.h>
-QT_BEGIN_NAMESPACE
-
+QT_REQUIRE_CONFIG(stringlistmodel);
-#ifndef QT_NO_STRINGLISTMODEL
+QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QStringListModel : public QAbstractListModel
{
@@ -78,8 +77,6 @@ private:
QStringList lst;
};
-#endif // QT_NO_STRINGLISTMODEL
-
QT_END_NAMESPACE
#endif // QSTRINGLISTMODEL_H
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 24d73fa8be..5ecd86a30e 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -346,15 +346,15 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
void qt_apple_check_os_version()
{
-#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
- const char *os = "iOS";
- const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
+#if defined(__WATCH_OS_VERSION_MIN_REQUIRED)
+ const char *os = "watchOS";
+ const int version = __WATCH_OS_VERSION_MIN_REQUIRED;
#elif defined(__TV_OS_VERSION_MIN_REQUIRED)
const char *os = "tvOS";
const int version = __TV_OS_VERSION_MIN_REQUIRED;
-#elif defined(__WATCH_OS_VERSION_MIN_REQUIRED)
- const char *os = "watchOS";
- const int version = __WATCH_OS_VERSION_MIN_REQUIRED;
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+ const char *os = "iOS";
+ const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
const char *os = "macOS";
const int version = __MAC_OS_X_VERSION_MIN_REQUIRED;
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 1e6b328c75..58ca8279ea 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -194,7 +194,7 @@ QT_BEGIN_NAMESPACE
\omitvalue Pointer
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
- \value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
+ \value QueryWhatsThis The widget should accept the event if it has "What's This?" help (QHelpEvent).
\value ReadOnlyChange Widget's read-only state has changed (since Qt 5.4).
\value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
\value Resize Widget's size changed (QResizeEvent).
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index 04c9a9bcba..712e8bbcab 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -599,7 +599,7 @@ void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *liste
jobject QtAndroidPrivate::callOnBindListener(jobject intent)
{
QMutexLocker lock(g_onBindListenerMutex);
- if (g_onBindListener)
+ if (*g_onBindListener)
return (*g_onBindListener)->onBind(intent);
return nullptr;
}
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 5abc2ebd70..fc40668c9a 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -53,12 +53,14 @@
#include "qdatastream.h"
#include "qmetatypeswitcher_p.h"
+#if QT_CONFIG(regularexpression)
+# include "qregularexpression.h"
+#endif
+
#ifndef QT_BOOTSTRAPPED
# include "qbitarray.h"
# include "qurl.h"
# include "qvariant.h"
-# include "qabstractitemmodel.h"
-# include "qregularexpression.h"
# include "qjsonvalue.h"
# include "qjsonobject.h"
# include "qjsonarray.h"
@@ -66,6 +68,10 @@
# include "qbytearraylist.h"
#endif
+#if QT_CONFIG(itemmodel)
+# include "qabstractitemmodel.h"
+#endif
+
#ifndef QT_NO_GEOM_VARIANT
# include "qsize.h"
# include "qpoint.h"
@@ -1346,8 +1352,10 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
+#if QT_CONFIG(itemmodel)
case QMetaType::QModelIndex:
case QMetaType::QPersistentModelIndex:
+#endif
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
@@ -1481,12 +1489,12 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
stream << *static_cast<const NS(QRegExp)*>(data);
break;
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
case QMetaType::QRegularExpression:
stream << *static_cast<const NS(QRegularExpression)*>(data);
break;
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
+#ifndef QT_BOOTSTRAPPED
case QMetaType::QEasingCurve:
stream << *static_cast<const NS(QEasingCurve)*>(data);
break;
@@ -1570,8 +1578,10 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::Void:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
+#if QT_CONFIG(itemmodel)
case QMetaType::QModelIndex:
case QMetaType::QPersistentModelIndex:
+#endif
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
@@ -1711,12 +1721,12 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
stream >> *static_cast< NS(QRegExp)*>(data);
break;
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
case QMetaType::QRegularExpression:
stream >> *static_cast< NS(QRegularExpression)*>(data);
break;
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
+#ifndef QT_BOOTSTRAPPED
case QMetaType::QEasingCurve:
stream >> *static_cast< NS(QEasingCurve)*>(data);
break;
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 455d0350e0..a0969ee908 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -89,6 +89,14 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
F(VoidStar, 31, void*) \
+#if QT_CONFIG(itemmodel)
+#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
+ F(QModelIndex, 42, QModelIndex) \
+ F(QPersistentModelIndex, 50, QPersistentModelIndex)
+#else
+#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
+#endif
+
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QString, 10, QString) \
@@ -112,13 +120,12 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QEasingCurve, 29, QEasingCurve) \
F(QUuid, 30, QUuid) \
F(QVariant, 41, QVariant) \
- F(QModelIndex, 42, QModelIndex) \
F(QRegularExpression, 44, QRegularExpression) \
F(QJsonValue, 45, QJsonValue) \
F(QJsonObject, 46, QJsonObject) \
F(QJsonArray, 47, QJsonArray) \
F(QJsonDocument, 48, QJsonDocument) \
- F(QPersistentModelIndex, 50, QPersistentModelIndex) \
+ QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
F(QObjectStar, 39, QObject*)
@@ -1381,7 +1388,7 @@ namespace QtPrivate
};
template<typename T, typename Enable = void>
- struct IsGadgetHelper { enum { Value = false }; };
+ struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
template<typename T>
struct IsGadgetHelper<T, typename T::QtGadgetHelper>
@@ -1389,11 +1396,14 @@ namespace QtPrivate
template <typename X>
static char checkType(void (X::*)());
static void *checkType(void (T::*)());
- enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
+ enum {
+ IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
+ IsGadgetOrDerivedFrom = true
+ };
};
template<typename T, typename Enable = void>
- struct IsPointerToGadgetHelper { enum { Value = false }; };
+ struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
template<typename T>
struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
@@ -1402,7 +1412,10 @@ namespace QtPrivate
template <typename X>
static char checkType(void (X::*)());
static void *checkType(void (T::*)());
- enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
+ enum {
+ IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
+ IsGadgetOrDerivedFrom = true
+ };
};
@@ -1435,12 +1448,12 @@ namespace QtPrivate
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
- struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::Value>::type>
+ struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
- struct MetaObjectForType<T, typename QEnableIf<IsPointerToGadgetHelper<T>::Value>::Type>
+ struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
};
@@ -1599,8 +1612,8 @@ namespace QtPrivate
template <typename T, int =
QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
- QtPrivate::IsGadgetHelper<T>::Value ? QMetaType::IsGadget :
- QtPrivate::IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget :
+ QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
+ QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
struct QMetaTypeIdQObject
{
@@ -1653,8 +1666,8 @@ namespace QtPrivate {
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
| (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
| (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
- | (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0)
- | (IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget : 0)
+ | (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
+ | (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
};
};
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index 6f1334d082..cef20a5d12 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -201,8 +201,6 @@ template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = f
template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonObject> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonValue> { static const bool IsAvailable = false; };
-template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable = false; };
-template<> struct TypeDefinition<QPersistentModelIndex> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QUrl> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QByteArrayList> { static const bool IsAvailable = false; };
#endif
@@ -219,7 +217,7 @@ template<> struct TypeDefinition<QPointF> { static const bool IsAvailable = fals
#ifdef QT_NO_REGEXP
template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = false; };
#endif
-#if defined(QT_BOOTSTRAPPED) || defined(QT_NO_REGULAREXPRESSION)
+#if !QT_CONFIG(regularexpression)
template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
#endif
#ifdef QT_NO_SHORTCUT
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index dcbf0f83d4..6747864db4 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -50,7 +50,9 @@
#include "qvariant.h"
#include "qmetaobject.h"
#include <qregexp.h>
-#include <qregularexpression.h>
+#if QT_CONFIG(regularexpression)
+# include <qregularexpression.h>
+#endif
#include <qthread.h>
#include <private/qthread_p.h>
#include <qdebug.h>
@@ -1926,7 +1928,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
}
#endif // QT_NO_REGEXP
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\internal
*/
@@ -1948,7 +1950,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re
qt_qFindChildren_helper(obj, re, mo, list, options);
}
}
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*!
\internal
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 0e608a3208..aac9bcdee9 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -74,7 +74,7 @@ class QWidget;
#ifndef QT_NO_REGEXP
class QRegExp;
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
class QRegularExpression;
#endif
#ifndef QT_NO_USERDATA
@@ -187,7 +187,7 @@ public:
}
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
template<typename T>
inline QList<T> findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
@@ -197,7 +197,7 @@ public:
reinterpret_cast<QList<void *> *>(&list), options);
return list;
}
-#endif
+#endif // QT_CONFIG(regularexpression)
inline const QObjectList &children() const { return d_ptr->children; }
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 96299b9eaf..6192b66487 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -48,14 +48,18 @@
#include "qdatetime.h"
#include "qeasingcurve.h"
#include "qlist.h"
+#if QT_CONFIG(regularexpression)
#include "qregularexpression.h"
+#endif
#include "qstring.h"
#include "qstringlist.h"
#include "qurl.h"
#include "qlocale.h"
#include "quuid.h"
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(itemmodel)
#include "qabstractitemmodel.h"
+#endif
+#ifndef QT_BOOTSTRAPPED
#include "qjsonvalue.h"
#include "qjsonobject.h"
#include "qjsonarray.h"
@@ -391,6 +395,8 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
}
break;
+#endif // QT_BOOTSTRAPPED
+#if QT_CONFIG(itemmodel)
case QVariant::ModelIndex:
switch (d->type) {
case QVariant::PersistentModelIndex:
@@ -409,7 +415,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
}
break;
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(itemmodel)
case QVariant::String: {
QString *str = static_cast<QString *>(result);
switch (d->type) {
@@ -1941,21 +1947,15 @@ QVariant::QVariant(const QRegExp &regExp)
: d(RegExp)
{ v_construct<QRegExp>(&d, regExp); }
#endif // QT_NO_REGEXP
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QVariant::QVariant(const QRegularExpression &re)
: d(RegularExpression)
{ v_construct<QRegularExpression>(&d, re); }
-#endif
+#endif // QT_CONFIG(regularexpression)
+#ifndef QT_BOOTSTRAPPED
QVariant::QVariant(const QUuid &uuid)
: d(Uuid)
{ v_construct<QUuid>(&d, uuid); }
-QVariant::QVariant(const QModelIndex &modelIndex)
- : d(ModelIndex)
-{ v_construct<QModelIndex>(&d, modelIndex); }
-QVariant::QVariant(const QPersistentModelIndex &modelIndex)
- : d(PersistentModelIndex)
-{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
QVariant::QVariant(const QJsonValue &jsonValue)
: d(QMetaType::QJsonValue)
{ v_construct<QJsonValue>(&d, jsonValue); }
@@ -1969,6 +1969,14 @@ QVariant::QVariant(const QJsonDocument &jsonDocument)
: d(QMetaType::QJsonDocument)
{ v_construct<QJsonDocument>(&d, jsonDocument); }
#endif // QT_BOOTSTRAPPED
+#if QT_CONFIG(itemmodel)
+QVariant::QVariant(const QModelIndex &modelIndex)
+ : d(ModelIndex)
+{ v_construct<QModelIndex>(&d, modelIndex); }
+QVariant::QVariant(const QPersistentModelIndex &modelIndex)
+ : d(PersistentModelIndex)
+{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
+#endif
/*!
Returns the storage type of the value stored in the variant.
@@ -2371,7 +2379,7 @@ inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &han
\l QMetaType::QVariantList of a type that can be converted to QString;
otherwise returns an empty list.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QStringList QVariant::toStringList() const
{
@@ -2379,14 +2387,19 @@ QStringList QVariant::toStringList() const
}
/*!
- Returns the variant as a QString if the variant has userType() \l
- QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray,
+ Returns the variant as a QString if the variant has a userType()
+ including, but not limited to:
+
+ \l QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray,
\l QMetaType::QChar, \l QMetaType::QDate, \l QMetaType::QDateTime,
\l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
\l QMetaType::QStringList, \l QMetaType::QTime, \l QMetaType::UInt, or
- \l QMetaType::ULongLong; otherwise returns an empty string.
+ \l QMetaType::ULongLong.
- \sa canConvert(), convert()
+ Calling QVariant::toString() on an unsupported variant returns an empty
+ string.
+
+ \sa canConvert(int targetTypeId), convert()
*/
QString QVariant::toString() const
{
@@ -2397,7 +2410,7 @@ QString QVariant::toString() const
Returns the variant as a QMap<QString, QVariant> if the variant
has type() \l QMetaType::QVariantMap; otherwise returns an empty map.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QVariantMap QVariant::toMap() const
{
@@ -2408,7 +2421,7 @@ QVariantMap QVariant::toMap() const
Returns the variant as a QHash<QString, QVariant> if the variant
has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QVariantHash QVariant::toHash() const
{
@@ -2425,7 +2438,7 @@ QVariantHash QVariant::toHash() const
If the type() is \l QMetaType::QString, an invalid date will be returned if
the string cannot be parsed as a Qt::ISODate format date.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QDate QVariant::toDate() const
{
@@ -2442,7 +2455,7 @@ QDate QVariant::toDate() const
If the type() is \l QMetaType::QString, an invalid time will be returned if
the string cannot be parsed as a Qt::ISODate format time.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QTime QVariant::toTime() const
{
@@ -2459,7 +2472,7 @@ QTime QVariant::toTime() const
If the type() is \l QMetaType::QString, an invalid date/time will be
returned if the string cannot be parsed as a Qt::ISODate format date/time.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QDateTime QVariant::toDateTime() const
{
@@ -2473,7 +2486,7 @@ QDateTime QVariant::toDateTime() const
Returns the variant as a QEasingCurve if the variant has userType()
\l QMetaType::QEasingCurve; otherwise returns a default easing curve.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
#ifndef QT_BOOTSTRAPPED
QEasingCurve QVariant::toEasingCurve() const
@@ -2489,7 +2502,7 @@ QEasingCurve QVariant::toEasingCurve() const
\l QMetaType::QByteArray or \l QMetaType::QString (converted using
QString::fromUtf8()); otherwise returns an empty byte array.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QByteArray QVariant::toByteArray() const
{
@@ -2504,7 +2517,7 @@ QByteArray QVariant::toByteArray() const
\l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPoint.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QPoint QVariant::toPoint() const
{
@@ -2517,7 +2530,7 @@ QPoint QVariant::toPoint() const
Returns the variant as a QRect if the variant has userType()
\l QMetaType::QRect; otherwise returns an invalid QRect.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QRect QVariant::toRect() const
{
@@ -2530,7 +2543,7 @@ QRect QVariant::toRect() const
Returns the variant as a QSize if the variant has userType()
\l QMetaType::QSize; otherwise returns an invalid QSize.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QSize QVariant::toSize() const
{
@@ -2543,7 +2556,7 @@ QSize QVariant::toSize() const
Returns the variant as a QSizeF if the variant has userType() \l
QMetaType::QSizeF; otherwise returns an invalid QSizeF.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QSizeF QVariant::toSizeF() const
{
@@ -2557,7 +2570,7 @@ QSizeF QVariant::toSizeF() const
\l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
QRectF.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QRectF QVariant::toRectF() const
{
@@ -2570,7 +2583,7 @@ QRectF QVariant::toRectF() const
Returns the variant as a QLineF if the variant has userType()
\l QMetaType::QLineF; otherwise returns an invalid QLineF.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QLineF QVariant::toLineF() const
{
@@ -2583,7 +2596,7 @@ QLineF QVariant::toLineF() const
Returns the variant as a QLine if the variant has userType()
\l QMetaType::QLine; otherwise returns an invalid QLine.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QLine QVariant::toLine() const
{
@@ -2597,7 +2610,7 @@ QLine QVariant::toLine() const
QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPointF.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QPointF QVariant::toPointF() const
{
@@ -2613,7 +2626,7 @@ QPointF QVariant::toPointF() const
Returns the variant as a QUrl if the variant has userType()
\l QMetaType::QUrl; otherwise returns an invalid QUrl.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QUrl QVariant::toUrl() const
{
@@ -2627,7 +2640,7 @@ QUrl QVariant::toUrl() const
Returns the variant as a QLocale if the variant has userType()
\l QMetaType::QLocale; otherwise returns an invalid QLocale.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QLocale QVariant::toLocale() const
{
@@ -2641,7 +2654,7 @@ QLocale QVariant::toLocale() const
Returns the variant as a QRegExp if the variant has userType()
\l QMetaType::QRegExp; otherwise returns an empty QRegExp.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
#ifndef QT_NO_REGEXP
QRegExp QVariant::toRegExp() const
@@ -2650,7 +2663,7 @@ QRegExp QVariant::toRegExp() const
}
#endif
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(regularexpression)
/*!
\fn QRegularExpression QVariant::toRegularExpression() const
\since 5.0
@@ -2658,36 +2671,22 @@ QRegExp QVariant::toRegExp() const
Returns the variant as a QRegularExpression if the variant has userType() \l
QRegularExpression; otherwise returns an empty QRegularExpression.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
-#ifndef QT_NO_REGULAREXPRESSION
QRegularExpression QVariant::toRegularExpression() const
{
return qVariantToHelper<QRegularExpression>(d, handlerManager);
}
-#endif // QT_NO_REGULAREXPRESSION
-
-/*!
- \since 5.0
-
- Returns the variant as a QUuid if the variant has type()
- \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
- otherwise returns a default-constructed QUuid.
-
- \sa canConvert(), convert()
-*/
-QUuid QVariant::toUuid() const
-{
- return qVariantToHelper<QUuid>(d, handlerManager);
-}
+#endif // QT_CONFIG(regularexpression)
+#if QT_CONFIG(itemmodel)
/*!
\since 5.0
Returns the variant as a QModelIndex if the variant has userType() \l
QModelIndex; otherwise returns a default constructed QModelIndex.
- \sa canConvert(), convert(), toPersistentModelIndex()
+ \sa canConvert(int targetTypeId), convert(), toPersistentModelIndex()
*/
QModelIndex QVariant::toModelIndex() const
{
@@ -2700,12 +2699,28 @@ QModelIndex QVariant::toModelIndex() const
Returns the variant as a QPersistentModelIndex if the variant has userType() \l
QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
- \sa canConvert(), convert(), toModelIndex()
+ \sa canConvert(int targetTypeId), convert(), toModelIndex()
*/
QPersistentModelIndex QVariant::toPersistentModelIndex() const
{
return qVariantToHelper<QPersistentModelIndex>(d, handlerManager);
}
+#endif // QT_CONFIG(itemmodel)
+
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \since 5.0
+
+ Returns the variant as a QUuid if the variant has type()
+ \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
+ otherwise returns a default-constructed QUuid.
+
+ \sa canConvert(int targetTypeId), convert()
+*/
+QUuid QVariant::toUuid() const
+{
+ return qVariantToHelper<QUuid>(d, handlerManager);
+}
/*!
\since 5.0
@@ -2713,7 +2728,7 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const
Returns the variant as a QJsonValue if the variant has userType() \l
QJsonValue; otherwise returns a default constructed QJsonValue.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QJsonValue QVariant::toJsonValue() const
{
@@ -2726,7 +2741,7 @@ QJsonValue QVariant::toJsonValue() const
Returns the variant as a QJsonObject if the variant has userType() \l
QJsonObject; otherwise returns a default constructed QJsonObject.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QJsonObject QVariant::toJsonObject() const
{
@@ -2739,7 +2754,7 @@ QJsonObject QVariant::toJsonObject() const
Returns the variant as a QJsonArray if the variant has userType() \l
QJsonArray; otherwise returns a default constructed QJsonArray.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QJsonArray QVariant::toJsonArray() const
{
@@ -2752,13 +2767,13 @@ QJsonArray QVariant::toJsonArray() const
Returns the variant as a QJsonDocument if the variant has userType() \l
QJsonDocument; otherwise returns a default constructed QJsonDocument.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QJsonDocument QVariant::toJsonDocument() const
{
return qVariantToHelper<QJsonDocument>(d, handlerManager);
}
-#endif
+#endif // QT_BOOTSTRAPPED
/*!
\fn QChar QVariant::toChar() const
@@ -2767,7 +2782,7 @@ QJsonDocument QVariant::toJsonDocument() const
\l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
returns an invalid QChar.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QChar QVariant::toChar() const
{
@@ -2778,7 +2793,7 @@ QChar QVariant::toChar() const
Returns the variant as a QBitArray if the variant has userType()
\l QMetaType::QBitArray; otherwise returns an empty bit array.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QBitArray QVariant::toBitArray() const
{
@@ -2821,7 +2836,7 @@ inline T qNumVariantToHelper(const QVariant::Private &d,
will not be reflected in \a ok. A simple workaround is to use
QString::toInt().
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
int QVariant::toInt(bool *ok) const
{
@@ -2843,7 +2858,7 @@ int QVariant::toInt(bool *ok) const
overflow will not be reflected in \a ok. A simple workaround is to use
QString::toUInt().
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
uint QVariant::toUInt(bool *ok) const
{
@@ -2860,7 +2875,7 @@ uint QVariant::toUInt(bool *ok) const
If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\c{ok} is set to false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
qlonglong QVariant::toLongLong(bool *ok) const
{
@@ -2877,7 +2892,7 @@ qlonglong QVariant::toLongLong(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
qulonglong QVariant::toULongLong(bool *ok) const
{
@@ -2894,7 +2909,7 @@ qulonglong QVariant::toULongLong(bool *ok) const
\l QMetaType::QByteArray and its lower-case content is not one of the
following: empty, "0" or "false"; otherwise returns \c false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
bool QVariant::toBool() const
{
@@ -2917,7 +2932,7 @@ bool QVariant::toBool() const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
double QVariant::toDouble(bool *ok) const
{
@@ -2936,7 +2951,7 @@ double QVariant::toDouble(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
float QVariant::toFloat(bool *ok) const
{
@@ -2955,7 +2970,7 @@ float QVariant::toFloat(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
qreal QVariant::toReal(bool *ok) const
{
@@ -2967,7 +2982,7 @@ qreal QVariant::toReal(bool *ok) const
\l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns
an empty list.
- \sa canConvert(), convert()
+ \sa canConvert(int targetTypeId), convert()
*/
QVariantList QVariant::toList() const
{
@@ -3180,9 +3195,11 @@ bool QVariant::canConvert(int targetTypeId) const
if (d.type == targetTypeId)
return true;
+#if QT_CONFIG(itemmodel)
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
return true;
+#endif
if (targetTypeId == QMetaType::QVariantList
&& (d.type == QMetaType::QVariantList
@@ -3347,7 +3364,7 @@ bool QVariant::canConvert(int targetTypeId) const
failed a previous conversion will always fail, changing the type, remaining null,
and returning \c false.
- \sa canConvert(), clear()
+ \sa canConvert(int targetTypeId), clear()
*/
bool QVariant::convert(int targetTypeId)
@@ -3896,7 +3913,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa setValue(), value()
*/
-/*! \fn static inline QVariant fromStdVariant(const std::variant<T, Types...> &value)
+/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
\since 5.11
Returns a QVariant with the type and value of the active variant of \a value. If
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index fe1ef1bdfc..9a5fc63d03 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -81,9 +81,9 @@ class QRectF;
#ifndef QT_NO_REGEXP
class QRegExp;
#endif // QT_NO_REGEXP
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
class QRegularExpression;
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
class QTextFormat;
class QTextLength;
class QUrl;
@@ -165,8 +165,10 @@ class Q_CORE_EXPORT QVariant
Hash = QMetaType::QVariantHash,
EasingCurve = QMetaType::QEasingCurve,
Uuid = QMetaType::QUuid,
+#if QT_CONFIG(itemmodel)
ModelIndex = QMetaType::QModelIndex,
PersistentModelIndex = QMetaType::QPersistentModelIndex,
+#endif
LastCoreType = QMetaType::LastCoreType,
Font = QMetaType::QFont,
@@ -248,20 +250,22 @@ class Q_CORE_EXPORT QVariant
#ifndef QT_NO_REGEXP
QVariant(const QRegExp &regExp);
#endif // QT_NO_REGEXP
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QVariant(const QRegularExpression &re);
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
+#ifndef QT_BOOTSTRAPPED
QVariant(const QUrl &url);
QVariant(const QEasingCurve &easing);
QVariant(const QUuid &uuid);
- QVariant(const QModelIndex &modelIndex);
- QVariant(const QPersistentModelIndex &modelIndex);
QVariant(const QJsonValue &jsonValue);
QVariant(const QJsonObject &jsonObject);
QVariant(const QJsonArray &jsonArray);
QVariant(const QJsonDocument &jsonDocument);
#endif // QT_BOOTSTRAPPED
+#if QT_CONFIG(itemmodel)
+ QVariant(const QModelIndex &modelIndex);
+ QVariant(const QPersistentModelIndex &modelIndex);
+#endif
QVariant& operator=(const QVariant &other);
#ifdef Q_COMPILER_RVALUE_REFS
@@ -322,20 +326,22 @@ class Q_CORE_EXPORT QVariant
#ifndef QT_NO_REGEXP
QRegExp toRegExp() const;
#endif // QT_NO_REGEXP
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QRegularExpression toRegularExpression() const;
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
+#ifndef QT_BOOTSTRAPPED
QUrl toUrl() const;
QEasingCurve toEasingCurve() const;
QUuid toUuid() const;
- QModelIndex toModelIndex() const;
- QPersistentModelIndex toPersistentModelIndex() const;
QJsonValue toJsonValue() const;
QJsonObject toJsonObject() const;
QJsonArray toJsonArray() const;
QJsonDocument toJsonDocument() const;
#endif // QT_BOOTSTRAPPED
+#if QT_CONFIG(itemmodel)
+ QModelIndex toModelIndex() const;
+ QPersistentModelIndex toPersistentModelIndex() const;
+#endif
#ifndef QT_NO_DATASTREAM
void load(QDataStream &ds);
@@ -359,7 +365,7 @@ class Q_CORE_EXPORT QVariant
static inline QVariant fromValue(const T &value)
{ return qVariantFromValue(value); }
-#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#if defined(Q_CLANG_QDOC) || (QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L)
template<typename... Types>
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
{
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index edc414fa0a..7d529372c4 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -214,6 +214,8 @@ QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileNam
void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
{
QMutexLocker locker(&mutex);
+ if (mimePrivate.name.isEmpty())
+ return; // invalid mimetype
if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
Q_ASSERT(mimePrivate.fromCache);
QMimeBinaryProvider::loadMimeTypePrivate(mimePrivate);
diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h
index b463f817bd..b463f817bd 100644
--- a/src/corelib/arch/qatomic_bootstrap.h
+++ b/src/corelib/thread/qatomic_bootstrap.h
diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h
index 2fc0bf5419..2fc0bf5419 100644
--- a/src/corelib/arch/qatomic_cxx11.h
+++ b/src/corelib/thread/qatomic_cxx11.h
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 92db7a6228..aacd12f220 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -45,20 +45,8 @@
#if defined(QT_BOOTSTRAPPED)
# include <QtCore/qatomic_bootstrap.h>
-
-// If C++11 atomics are supported, use them!
-// Note that constexpr support is sometimes disabled in QNX builds but its
-// library has <atomic>.
-#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX))
-# include <QtCore/qatomic_cxx11.h>
-
-// We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support
-#elif defined(Q_CC_MSVC)
-# include <QtCore/qatomic_msvc.h>
-
-// No fallback
#else
-# error "Qt requires C++11 support"
+# include <QtCore/qatomic_cxx11.h>
#endif
QT_WARNING_PUSH
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index 79414838d3..adc851efb5 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -580,7 +580,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
This signal is emitted when the watched future reports a ready result at
\a index. If the future reports multiple results, the index will indicate
which one it is. Results can be reported out-of-order. To get the result,
- call future().result(index);
+ call resultAt(index);
*/
/*!
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index 5c4c02a2ec..89c4fe9a11 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -253,12 +253,15 @@ template <typename BaseClass> struct QGenericAtomicOps
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
{
// implement fetchAndSub on top of fetchAndAdd
return fetchAndAddRelaxed(_q_value, -operand);
}
+QT_WARNING_POP
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 012628ef63..e91e859975 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -119,28 +119,44 @@ using namespace QtFutex;
acquire tokens. Which ones get woken up is unspecified.
If the system has the ability to wake up a precise number of threads, has
- Linux's FUTEX_WAKE_OP functionality, and is 64-bit, we'll use the high word
- as a copy of the low word, but the sign bit indicating the presence of a
- thread waiting for multiple tokens. So when releasing n tokens on those
- systems, we tell the kernel to wake up n single-token threads and all of
- the multi-token ones, then clear that wait bit. Which threads get woken up
- is unspecified, but it's likely single-token threads will get woken up
- first.
+ Linux's FUTEX_WAKE_OP functionality, and is 64-bit, instead of using a
+ single bit indicating a contended semaphore, we'll store the number of
+ tokens *plus* total number of waiters in the high word. Additionally, all
+ multi-token waiters will be waiting on that high word. So when releasing n
+ tokens on those systems, we tell the kernel to wake up n single-token
+ threads and all of the multi-token ones. Which threads get woken up is
+ unspecified, but it's likely single-token threads will get woken up first.
*/
-static const quint32 futexContendedBit = 1U << 31;
+
+#if defined(FUTEX_OP) && QT_POINTER_SIZE > 4
+static Q_CONSTEXPR bool futexHasWaiterCount = true;
+#else
+static Q_CONSTEXPR bool futexHasWaiterCount = false;
+#endif
+
+static const quintptr futexNeedsWakeAllBit =
+ Q_UINT64_C(1) << (sizeof(quintptr) * CHAR_BIT - 1);
static int futexAvailCounter(quintptr v)
{
// the low 31 bits
- return int(v & (futexContendedBit - 1));
+ if (futexHasWaiterCount) {
+ // the high bit of the low word isn't used
+ Q_ASSERT((v & 0x80000000U) == 0);
+
+ // so we can be a little faster
+ return int(unsigned(v));
+ }
+ return int(v & 0x7fffffffU);
}
-static quintptr futexCounterParcel(int n)
+static bool futexNeedsWake(quintptr v)
{
- // replicate the 31 bits if we're on 64-bit
- quint64 nn = quint32(n);
- nn |= (nn << 32);
- return quintptr(nn);
+ // If we're counting waiters, the number of waiters is stored in the low 31
+ // bits of the high word (that is, bits 32-62). If we're not, then we use
+ // bit 31 to indicate anyone is waiting. Either way, if any bit 31 or above
+ // is set, there are waiters.
+ return v >> 31;
}
static QBasicAtomicInteger<quint32> *futexLow32(QBasicAtomicInteger<quintptr> *ptr)
@@ -152,9 +168,6 @@ static QBasicAtomicInteger<quint32> *futexLow32(QBasicAtomicInteger<quintptr> *p
return result;
}
-#ifdef FUTEX_OP
-// quintptr might be 32bit, in which case we want this to be 0, without implicitly casting.
-static const quintptr futexMultiWaiterBit = static_cast<quintptr>(Q_UINT64_C(1) << 63);
static QBasicAtomicInteger<quint32> *futexHigh32(QBasicAtomicInteger<quintptr> *ptr)
{
auto result = reinterpret_cast<QBasicAtomicInteger<quint32> *>(ptr);
@@ -163,18 +176,21 @@ static QBasicAtomicInteger<quint32> *futexHigh32(QBasicAtomicInteger<quintptr> *
#endif
return result;
}
-#endif
-template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintptr> &u, int n, int timeout)
+template <bool IsTimed> bool
+futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValue, quintptr nn, int timeout)
{
QDeadlineTimer timer(IsTimed ? QDeadlineTimer(timeout) : QDeadlineTimer());
- quintptr curValue = u.loadAcquire();
qint64 remainingTime = timeout * Q_INT64_C(1000) * 1000;
+ int n = int(unsigned(nn));
+
+ // we're called after one testAndSet, so start by waiting first
+ goto start_wait;
+
forever {
- int available = futexAvailCounter(curValue);
- if (available >= n) {
+ if (futexAvailCounter(curValue) >= n) {
// try to acquire
- quintptr newValue = curValue - futexCounterParcel(n);
+ quintptr newValue = curValue - nn;
if (u.testAndSetOrdered(curValue, newValue, curValue))
return true; // succeeded!
continue;
@@ -184,19 +200,18 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
if (remainingTime == 0)
return false;
- // set the contended and multi-wait bits
- quintptr bitsToSet = futexContendedBit;
+ // indicate we're waiting
+start_wait:
auto ptr = futexLow32(&u);
-#ifdef FUTEX_OP
- if (n > 1 && sizeof(curValue) >= sizeof(int)) {
- bitsToSet |= futexMultiWaiterBit;
- ptr = futexHigh32(&u);
+ if (n > 1 || !futexHasWaiterCount) {
+ u.fetchAndOrRelaxed(futexNeedsWakeAllBit);
+ curValue |= futexNeedsWakeAllBit;
+ if (n > 1 && futexHasWaiterCount) {
+ ptr = futexHigh32(&u);
+ //curValue >>= 32; // but this is UB in 32-bit, so roundabout:
+ curValue = quint64(curValue) >> 32;
+ }
}
-#endif
-
- // the value is the same for either branch
- u.fetchAndOrRelaxed(bitsToSet);
- curValue |= bitsToSet;
if (IsTimed && remainingTime > 0) {
bool timedout = !futexWait(*ptr, curValue, remainingTime);
@@ -212,6 +227,51 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
}
}
+template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintptr> &u, int n, int timeout)
+{
+ // Try to acquire without waiting (we still loop because the testAndSet
+ // call can fail).
+ quintptr nn = unsigned(n);
+ if (futexHasWaiterCount)
+ nn |= quint64(nn) << 32; // token count replicated in high word
+
+ quintptr curValue = u.loadAcquire();
+ while (futexAvailCounter(curValue) >= n) {
+ // try to acquire
+ quintptr newValue = curValue - nn;
+ if (u.testAndSetOrdered(curValue, newValue, curValue))
+ return true; // succeeded!
+ }
+ if (timeout == 0)
+ return false;
+
+ // we need to wait
+ quintptr oneWaiter = quintptr(Q_UINT64_C(1) << 32); // zero on 32-bit
+ if (futexHasWaiterCount) {
+ // increase the waiter count
+ u.fetchAndAddRelaxed(oneWaiter);
+
+ // We don't use the fetched value from above so futexWait() fails if
+ // it changed after the testAndSetOrdered above.
+ if ((quint64(curValue) >> 32) == 0x7fffffff)
+ return false; // overflow!
+ curValue += oneWaiter;
+
+ // Also adjust nn to subtract oneWaiter when we succeed in acquiring.
+ nn += oneWaiter;
+ }
+
+ if (futexSemaphoreTryAcquire_loop<IsTimed>(u, curValue, nn, timeout))
+ return true;
+
+ if (futexHasWaiterCount) {
+ // decrement the number of threads waiting
+ Q_ASSERT(futexHigh32(&u)->load() & 0x7fffffffU);
+ u.fetchAndSubRelaxed(oneWaiter);
+ }
+ return false;
+}
+
class QSemaphorePrivate {
public:
inline QSemaphorePrivate(int n) : avail(n) { }
@@ -231,10 +291,14 @@ public:
QSemaphore::QSemaphore(int n)
{
Q_ASSERT_X(n >= 0, "QSemaphore", "parameter 'n' must be non-negative");
- if (futexAvailable())
- u.store(n);
- else
+ if (futexAvailable()) {
+ quintptr nn = unsigned(n);
+ if (futexHasWaiterCount)
+ nn |= quint64(nn) << 32; // token count replicated in high word
+ u.store(nn);
+ } else {
d = new QSemaphorePrivate(n);
+ }
}
/*!
@@ -289,10 +353,13 @@ void QSemaphore::release(int n)
Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative");
if (futexAvailable()) {
- quintptr prevValue = u.fetchAndAddRelease(futexCounterParcel(n));
- if (prevValue & futexContendedBit) {
+ quintptr nn = unsigned(n);
+ if (futexHasWaiterCount)
+ nn |= quint64(nn) << 32; // token count replicated in high word
+ quintptr prevValue = u.fetchAndAddRelease(nn);
+ if (futexNeedsWake(prevValue)) {
#ifdef FUTEX_OP
- if (sizeof(u) == sizeof(int)) {
+ if (!futexHasWaiterCount) {
/*
On 32-bit systems, all waiters are waiting on the same address,
so we'll wake them all and ask the kernel to clear the high bit.
@@ -317,9 +384,6 @@ void QSemaphore::release(int n)
the kernel to wake up n single-token waiters and all multi-token
waiters (if any), then clear the multi-token wait bit.
- That means we must clear the contention bit ourselves. See
- below for handling the race.
-
atomic {
int oldval = *upper;
*upper = oldval & ~(1 << 31);
@@ -332,7 +396,6 @@ void QSemaphore::release(int n)
quint32 oparg = 31;
quint32 cmp = FUTEX_OP_CMP_LT;
quint32 cmparg = 0;
- futexLow32(&u)->fetchAndAndRelease(futexContendedBit - 1);
futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg));
}
#else
@@ -343,7 +406,7 @@ void QSemaphore::release(int n)
// its acquisition anyway, so it has to wait;
// 2) it did not see the new counter value, in which case its
// futexWait will fail.
- u.fetchAndAndRelease(futexContendedBit - 1);
+ u.fetchAndAndRelease(futexNeedsWakeAllBit - 1);
futexWakeAll(u);
#endif
}
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index e4972a57b3..47775f3fde 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -10,6 +10,8 @@ HEADERS += thread/qmutex.h \
thread/qthreadstorage.h \
thread/qwaitcondition.h \
thread/qatomic.h \
+ thread/qatomic_bootstrap.h \
+ thread/qatomic_cxx11.h \
thread/qbasicatomic.h \
thread/qgenericatomic.h
@@ -67,3 +69,5 @@ win32 {
thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
}
+
+qtConfig(std-atomic64): QMAKE_USE += libatomic
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index 1a03bfaac4..b658d8afcf 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -590,6 +590,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NO
}
#elif defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_PROCESSOR_ARM)
#define QT_POPCOUNT_CONSTEXPR
+#define QT_POPCOUNT_RELAXED_CONSTEXPR
#define QT_HAS_BUILTIN_CTZ
Q_ALWAYS_INLINE unsigned long qt_builtin_ctz(quint32 val)
{
@@ -676,6 +677,7 @@ Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NOTHROW
#ifndef QT_POPCOUNT_CONSTEXPR
#define QT_POPCOUNT_CONSTEXPR Q_DECL_CONSTEXPR
+#define QT_POPCOUNT_RELAXED_CONSTEXPR Q_DECL_RELAXED_CONSTEXPR
#endif
} //namespace QAlgorithmsPrivate
@@ -819,7 +821,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOT
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
{
#if defined(QT_HAS_BUILTIN_CLZ)
return v ? QAlgorithmsPrivate::qt_builtin_clz(v)-24U : 8U;
@@ -831,7 +833,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTH
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
{
#if defined(QT_HAS_BUILTIN_CLZS)
return v ? QAlgorithmsPrivate::qt_builtin_clzs(v) : 16U;
@@ -844,7 +846,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOT
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
{
#if defined(QT_HAS_BUILTIN_CLZLL)
return v ? QAlgorithmsPrivate::qt_builtin_clzll(v) : 64U;
@@ -859,7 +861,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOT
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW
{
return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index adfa939cc6..421e716d14 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -4337,7 +4337,6 @@ QByteArray &QByteArray::setRawData(const char *data, uint size)
} else {
d->offset = sizeof(QByteArrayData);
d->size = 0;
- *d->data() = 0;
}
}
return *this;
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index 0b8fa4ca74..e66db58ed7 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -797,27 +797,60 @@ struct BezierEase : public QEasingCurveFunction
return t3;
}
- qreal static inline findTForX(const SingleCubicBezier &singleCubicBezier, qreal x)
- {
- const qreal p0 = singleCubicBezier.p0x;
- const qreal p1 = singleCubicBezier.p1x;
- const qreal p2 = singleCubicBezier.p2x;
- const qreal p3 = singleCubicBezier.p3x;
-
- const qreal factorT3 = p3 - p0 + 3 * p1 - 3 * p2;
- const qreal factorT2 = 3 * p0 - 6 * p1 + 3 * p2;
- const qreal factorT1 = -3 * p0 + 3 * p1;
- const qreal factorT0 = p0 - x;
-
- const qreal a = factorT2 / factorT3;
- const qreal b = factorT1 / factorT3;
- const qreal c = factorT0 / factorT3;
-
- return singleRealSolutionForCubic(a, b, c);
-
- //one new iteration to increase numeric stability
- //return newtonIteration(singleCubicBezier, t, x);
- }
+ bool static inline almostZero(qreal value)
+ {
+ // 1e-3 might seem excessively fuzzy, but any smaller value will make the
+ // factors a, b, and c large enough to knock out the cubic solver.
+ return value > -1e-3 && value < 1e-3;
+ }
+
+ qreal static inline findTForX(const SingleCubicBezier &singleCubicBezier, qreal x)
+ {
+ const qreal p0 = singleCubicBezier.p0x;
+ const qreal p1 = singleCubicBezier.p1x;
+ const qreal p2 = singleCubicBezier.p2x;
+ const qreal p3 = singleCubicBezier.p3x;
+
+ const qreal factorT3 = p3 - p0 + 3 * p1 - 3 * p2;
+ const qreal factorT2 = 3 * p0 - 6 * p1 + 3 * p2;
+ const qreal factorT1 = -3 * p0 + 3 * p1;
+ const qreal factorT0 = p0 - x;
+
+ // Cases for quadratic, linear and invalid equations
+ if (almostZero(factorT3)) {
+ if (almostZero(factorT2)) {
+ if (almostZero(factorT1))
+ return 0.0;
+
+ return -factorT0 / factorT1;
+ }
+ const qreal discriminant = factorT1 * factorT1 - 4.0 * factorT2 * factorT0;
+ if (discriminant < 0.0)
+ return 0.0;
+
+ if (discriminant == 0.0)
+ return -factorT1 / (2.0 * factorT2);
+
+ const qreal solution1 = (-factorT1 + std::sqrt(discriminant)) / (2.0 * factorT2);
+ if (solution1 >= 0.0 && solution1 <= 1.0)
+ return solution1;
+
+ const qreal solution2 = (-factorT1 - std::sqrt(discriminant)) / (2.0 * factorT2);
+ if (solution2 >= 0.0 && solution2 <= 1.0)
+ return solution2;
+
+ return 0.0;
+ }
+
+ const qreal a = factorT2 / factorT3;
+ const qreal b = factorT1 / factorT3;
+ const qreal c = factorT0 / factorT3;
+
+ return singleRealSolutionForCubic(a, b, c);
+
+ //one new iteration to increase numeric stability
+ //return newtonIteration(singleCubicBezier, t, x);
+ }
};
struct TCBEase : public BezierEase
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 7eb8b7372c..6669ae7c8b 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -419,15 +419,15 @@ QString qt_readEscapedFormatString(QStringView format, int *idx);
bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry);
int qt_repeatCount(QStringView s);
-enum { AsciiSpaceMask = (1 << (' ' - 1)) |
- (1 << ('\t' - 1)) | // 9: HT - horizontal tab
- (1 << ('\n' - 1)) | // 10: LF - line feed
- (1 << ('\v' - 1)) | // 11: VT - vertical tab
- (1 << ('\f' - 1)) | // 12: FF - form feed
- (1 << ('\r' - 1)) }; // 13: CR - carriage return
+enum { AsciiSpaceMask = (1u << (' ' - 1)) |
+ (1u << ('\t' - 1)) | // 9: HT - horizontal tab
+ (1u << ('\n' - 1)) | // 10: LF - line feed
+ (1u << ('\v' - 1)) | // 11: VT - vertical tab
+ (1u << ('\f' - 1)) | // 12: FF - form feed
+ (1u << ('\r' - 1)) }; // 13: CR - carriage return
Q_DECL_CONSTEXPR inline bool ascii_isspace(uchar c)
{
- return c >= 1U && c <= 32U && (uint(AsciiSpaceMask) >> uint(c - 1)) & 1U;
+ return c >= 1u && c <= 32u && (AsciiSpaceMask >> uint(c - 1)) & 1u;
}
#if defined(Q_COMPILER_CONSTEXPR)
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 86bc99716d..13eff07c04 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -41,8 +41,6 @@
#include "qregularexpression.h"
-#ifndef QT_NO_REGULAREXPRESSION
-
#include <QtCore/qcoreapplication.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qreadwritelock.h>
@@ -2912,5 +2910,3 @@ static const char *pcreCompileErrorCodes[] =
#endif // #if 0
QT_END_NAMESPACE
-
-#endif // QT_NO_REGULAREXPRESSION
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 050841e70e..398fc9ec9c 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -43,13 +43,13 @@
#include <QtCore/qglobal.h>
-#ifndef QT_NO_REGULAREXPRESSION
-
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qvariant.h>
+QT_REQUIRE_CONFIG(regularexpression);
+
QT_BEGIN_NAMESPACE
class QStringView;
@@ -277,6 +277,4 @@ Q_DECLARE_SHARED(QRegularExpressionMatchIterator)
QT_END_NAMESPACE
-#endif // QT_NO_REGULAREXPRESSION
-
#endif // QREGULAREXPRESSION_H
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index dbf0907a0f..780f2331a8 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -115,7 +115,11 @@ public:
#ifdef Q_COMPILER_RVALUE_REFS
QSharedDataPointer(QSharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; }
inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) Q_DECL_NOTHROW
- { qSwap(d, other.d); return *this; }
+ {
+ QSharedDataPointer moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
#endif
inline bool operator!() const { return !d; }
@@ -204,7 +208,11 @@ public:
#ifdef Q_COMPILER_RVALUE_REFS
inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; }
inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) Q_DECL_NOTHROW
- { qSwap(d, other.d); return *this; }
+ {
+ QExplicitlySharedDataPointer moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
#endif
inline bool operator!() const { return !d; }
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index f88153db5d..22cf516b68 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -309,7 +309,7 @@
\endomit
- \sa QSharedDataPointer, QWeakPointer, QScopedPointer
+ \sa QSharedDataPointer, QWeakPointer, QScopedPointer, QEnableSharedFromThis
*/
/*!
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b56ad34546..f6360f5504 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -40,7 +40,9 @@
#include "qstringlist.h"
#include "qregexp.h"
+#if QT_CONFIG(regularexpression)
#include "qregularexpression.h"
+#endif
#include "qunicodetables_p.h"
#ifndef QT_NO_TEXTCODEC
#include <qtextcodec.h>
@@ -3695,7 +3697,7 @@ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs
}
-#if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION))
+#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression))
struct QStringCapture
{
int pos;
@@ -3862,8 +3864,7 @@ QString& QString::replace(const QRegExp &rx, const QString &after)
}
#endif
-#ifndef QT_NO_REGULAREXPRESSION
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(regularexpression)
/*!
\overload replace()
\since 5.0
@@ -3991,8 +3992,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
return *this;
}
-#endif // QT_BOOTSTRAPPED
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*!
Returns the number of (potentially overlapping) occurrences of
@@ -4207,8 +4207,7 @@ int QString::count(const QRegExp& rx) const
}
#endif // QT_NO_REGEXP
-#ifndef QT_NO_REGULAREXPRESSION
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(regularexpression)
/*!
\overload indexOf()
\since 5.0
@@ -4386,8 +4385,7 @@ int QString::count(const QRegularExpression &re) const
}
return count;
}
-#endif // QT_BOOTSTRAPPED
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*! \fn int QString::count() const
@@ -4509,7 +4507,7 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
return ret;
}
-#if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION))
+#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression))
class qt_section_chunk {
public:
qt_section_chunk() {}
@@ -4619,8 +4617,7 @@ QString QString::section(const QRegExp &reg, int start, int end, SectionFlags fl
}
#endif
-#ifndef QT_NO_REGULAREXPRESSION
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(regularexpression)
/*!
\overload section()
\since 5.0
@@ -4664,8 +4661,7 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
return extractSections(sections, start, end, flags);
}
-#endif // QT_BOOTSTRAPPED
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*!
Returns a substring that contains the \a n leftmost characters
@@ -7586,8 +7582,7 @@ QVector<QStringRef> QString::splitRef(const QRegExp &rx, SplitBehavior behavior)
}
#endif
-#ifndef QT_NO_REGULAREXPRESSION
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(regularexpression)
namespace {
template<class ResultList, typename MidMethod>
static ResultList splitString(const QString &source, MidMethod mid, const QRegularExpression &re,
@@ -7667,8 +7662,7 @@ QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavio
{
return splitString<QVector<QStringRef> >(*this, &QString::midRef, re, behavior);
}
-#endif // QT_BOOTSTRAPPED
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*!
\enum QString::NormalizationForm
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 0138ae4098..f27f7efa2b 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -353,7 +353,7 @@ public:
inline bool contains(QRegExp &rx) const { return indexOf(rx) != -1; }
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
int indexOf(const QRegularExpression &re, int from = 0) const;
int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
int lastIndexOf(const QRegularExpression &re, int from = -1) const;
@@ -377,7 +377,7 @@ public:
#ifndef QT_NO_REGEXP
QString section(const QRegExp &reg, int start, int end = -1, SectionFlags flags = SectionDefault) const;
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QString section(const QRegularExpression &re, int start, int end = -1, SectionFlags flags = SectionDefault) const;
#endif
Q_REQUIRED_RESULT QString left(int n) const;
@@ -502,7 +502,7 @@ public:
inline QString &remove(const QRegExp &rx)
{ return replace(rx, QString()); }
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QString &replace(const QRegularExpression &re, const QString &after);
inline QString &remove(const QRegularExpression &re)
{ return replace(re, QString()); }
@@ -522,7 +522,7 @@ public:
Q_REQUIRED_RESULT QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const;
Q_REQUIRED_RESULT QVector<QStringRef> splitRef(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const;
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
Q_REQUIRED_RESULT QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const;
Q_REQUIRED_RESULT QVector<QStringRef> splitRef(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const;
#endif
@@ -1857,6 +1857,12 @@ QT_DEPRECATED inline QString escape(const QString &plain) {
#endif
}
+namespace QtPrivate {
+// used by qPrintable() and qUtf8Printable() macros
+inline const QString &asString(const QString &s) { return s; }
+inline QString &&asString(QString &&s) { return std::move(s); }
+}
+
QT_END_NAMESPACE
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 17f6bd8539..d10d9ad9d0 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -39,7 +39,9 @@
#include <qstringlist.h>
#include <qset.h>
-#include <qregularexpression.h>
+#if QT_CONFIG(regularexpression)
+# include <qregularexpression.h>
+#endif
#include <algorithm>
@@ -361,8 +363,7 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegExp
}
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\fn QStringList QStringList::filter(const QRegularExpression &re) const
\overload
@@ -380,8 +381,7 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula
}
return res;
}
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
/*!
\fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
@@ -436,8 +436,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &r
}
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\fn QStringList &QStringList::replaceInStrings(const QRegularExpression &re, const QString &after)
\overload
@@ -466,8 +465,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx
for (int i = 0; i < that->size(); ++i)
(*that)[i].replace(re, after);
}
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
static int accumulatedSize(const QStringList &list, int seplen)
{
@@ -674,8 +672,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int
}
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\fn int QStringList::indexOf(const QRegularExpression &re, int from) const
\overload
@@ -732,8 +729,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx
}
return -1;
}
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
/*!
\fn int QStringList::removeDuplicates()
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index b11856d9be..e58445b8c0 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -84,12 +84,10 @@ public:
inline QStringList &replaceInStrings(const QRegExp &rx, const QString &after);
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
inline QStringList filter(const QRegularExpression &re) const;
inline QStringList &replaceInStrings(const QRegularExpression &re, const QString &after);
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
#ifndef Q_QDOC
private:
@@ -138,12 +136,10 @@ public:
inline int lastIndexOf(QRegExp &rx, int from = -1) const;
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
inline int indexOf(const QRegularExpression &re, int from = 0) const;
inline int lastIndexOf(const QRegularExpression &re, int from = -1) const;
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
using QList<QString>::indexOf;
using QList<QString>::lastIndexOf;
@@ -179,14 +175,12 @@ namespace QtPrivate {
int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from);
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QRegularExpression &rx, const QString &after);
QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QRegularExpression &re);
int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegularExpression &re, int from);
int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, int from);
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
}
inline void QListSpecialMethods<QString>::sort(Qt::CaseSensitivity cs)
@@ -275,8 +269,7 @@ inline int QStringList::lastIndexOf(QRegExp &rx, int from) const
}
#endif
-#ifndef QT_BOOTSTRAPPED
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QRegularExpression &rx, const QString &after)
{
QtPrivate::QStringList_replaceInStrings(self(), rx, after);
@@ -297,8 +290,7 @@ inline int QStringList::lastIndexOf(const QRegularExpression &rx, int from) cons
{
return QtPrivate::QStringList_lastIndexOf(this, rx, from);
}
-#endif // QT_NO_REGULAREXPRESSION
-#endif // QT_BOOTSTRAPPED
+#endif // QT_CONFIG(regularexpression)
#endif // Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index bc22ea26f6..a6bd7847a5 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -176,11 +176,11 @@ public:
inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
{ append(t); return *this; }
inline QVarLengthArray<T, Prealloc> &operator<<(T &&t)
- { append(t); return *this; }
+ { append(std::move(t)); return *this; }
inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
{ append(t); return *this; }
inline QVarLengthArray<T, Prealloc> &operator+=(T &&t)
- { append(t); return *this; }
+ { append(std::move(t)); return *this; }
void prepend(T &&t);
void prepend(const T &t);
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index e4c7fd06d8..345ba4b097 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -284,9 +284,9 @@ public:
inline QVector<T> &operator<<(const QVector<T> &l)
{ *this += l; return *this; }
inline QVector<T> &operator+=(T &&t)
- { append(t); return *this; }
+ { append(std::move(t)); return *this; }
inline QVector<T> &operator<<(T &&t)
- { append(t); return *this; }
+ { append(std::move(t)); return *this; }
QList<T> toList() const;
diff --git a/src/dbus/LIBDBUS-1-LICENSE.txt b/src/dbus/LIBDBUS-1-LICENSE.txt
new file mode 100644
index 0000000000..ff2c19be45
--- /dev/null
+++ b/src/dbus/LIBDBUS-1-LICENSE.txt
@@ -0,0 +1,157 @@
+Copyright (C) 2002, 2003 CodeFactory AB
+Copyright (C) 2004, 2005 Red Hat, Inc.
+
+Licensed under the Academic Free License version 2.1
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+---
+
+The Academic Free License
+v.2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+ 1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
+ a) to reproduce the Original Work in copies;
+ b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+ c) to distribute copies of the Original Work and Derivative Works to the public;
+ d) to perform the Original Work publicly; and
+ e) to display the Original Work publicly.
+ 2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
+ 3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
+ 4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
+ 5) This section intentionally omitted.
+ 6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
+ 7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
+ 8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
+ 9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
+ 10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
+ 11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
+ 12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
+ 13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
+ 14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+ 15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
+Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.
+
+
+---
+
+GNU GENERAL PUBLIC LICENSE
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+ 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+
+ You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+ 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+ a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+ b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+ c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+
+ These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+ 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+ a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+ b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+ c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+
+ The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+ If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+ 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+ 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+ 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+ 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+ It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+ 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+ 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+ 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+
+<one line to give the program's name and an idea of what it does.>
+Copyright (C) <yyyy> <name of author>
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice
diff --git a/src/dbus/Qt5DBusMacros.cmake b/src/dbus/Qt5DBusMacros.cmake
index 0bd7364637..b381ab0934 100644
--- a/src/dbus/Qt5DBusMacros.cmake
+++ b/src/dbus/Qt5DBusMacros.cmake
@@ -61,8 +61,7 @@ function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename)
COMMAND ${Qt5DBus_QDBUSXML2CPP_EXECUTABLE} ${_params} -p ${_basename} ${_infile}
DEPENDS ${_infile} VERBATIM)
- set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
- set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
+ set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
qt5_generate_moc("${_header}" "${_moc}")
@@ -147,8 +146,7 @@ function(QT5_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optio
endif()
qt5_generate_moc("${_header}" "${_moc}")
- set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
- set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
+ set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE)
macro_add_file_dependencies("${_impl}" "${_moc}")
list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}")
diff --git a/src/dbus/doc/src/qtdbus-index.qdoc b/src/dbus/doc/src/qtdbus-index.qdoc
index eed5e42731..18a4aa6d0f 100644
--- a/src/dbus/doc/src/qtdbus-index.qdoc
+++ b/src/dbus/doc/src/qtdbus-index.qdoc
@@ -200,7 +200,7 @@
Information about the messages will be written to the console the application
was launched from.
- \section1 Licenses
+ \section1 Licenses and Attributions
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,
@@ -209,6 +209,11 @@
the \l{GNU General Public License, version 2}.
See \l{Qt Licensing} for further details.
+ Furthermore, Qt D-Bus in Qt \QtVersion may contain third party
+ modules under following permissive licenses:
+
+ \generatelist{groupsbymodule attributions-qtdbus}
+
\section1 Further Reading
The following documents contain information about Qt's D-Bus integration
diff --git a/src/dbus/qt_attribution.json b/src/dbus/qt_attribution.json
new file mode 100644
index 0000000000..52636ba89b
--- /dev/null
+++ b/src/dbus/qt_attribution.json
@@ -0,0 +1,15 @@
+{
+ "Id": "libdbus-1-headers",
+ "Name": "libdus-1 headers",
+ "QDocModule": "qtdbus",
+ "QtUsage": "Qt D-Bus uses constants and typedefs from libdbus-1 headers.",
+
+ "Description": "D-Bus is a message bus system, a simple way for applications to talk to one another.",
+ "Homepage": "https://www.freedesktop.org/wiki/Software/dbus/",
+ "LicenseId": "AFL-2.1 OR GPL-2.0-or-later",
+ "License": "Academic Free License v2.1, or GNU General Public License v2.0 or later",
+ "LicenseFile": "LIBDBUS-1-LICENSE.txt",
+ "Files": "dbus_minimal_p.h",
+ "Copyright": "Copyright (C) 2002, 2003 CodeFactory AB
+Copyright (C) 2004, 2005 Red Hat, Inc."
+}
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 805f872431..413305be4b 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -1272,7 +1272,7 @@
"label": "XCB",
"section": "Platform plugins",
"autoDetect": "!config.darwin",
- "enable": "input.xcb == 'system' || input.xcb == 'qt'",
+ "enable": "input.xcb == 'system' || input.xcb == 'qt' || input.xcb == 'yes'",
"condition": "libs.xcb",
"output": [ "privateFeature" ]
},
diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc
index 010659df8c..a425c8a84d 100644
--- a/src/gui/doc/src/qtgui.qdoc
+++ b/src/gui/doc/src/qtgui.qdoc
@@ -195,19 +195,6 @@
For more information, see the \l{Hello Vulkan Widget Example}
and the \l {Hello Vulkan Window Example}.
- \section1 Qt GUI Prior to Qt 5.0
-
- Prior to Qt 5.0, the Qt GUI module was the monolithic container
- for all things relating to graphical user interfaces in Qt, and
- included the Qt widget set, the item views, the graphics view
- framework and also printing. Starting Qt 5, these classes have
- been moved to the Qt Widgets module. Printing has been
- moved to the Qt Print Support module. Please note that these
- modules can be excluded from a Qt installation.
-
- Qt GUI now contains only a small set of enablers, which are generally
- useful for all graphical applications.
-
\section1 Drag and Drop
More info in \l{Drag and Drop}
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 4eef617336..1b4d3e63dd 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -1333,14 +1333,18 @@ void dither_to_Mono(QImageData *dst, const QImageData *src,
} else {
bit--;
}
+ const int e7 = ((err * 7) + 8) >> 4;
+ const int e5 = ((err * 5) + 8) >> 4;
+ const int e3 = ((err * 3) + 8) >> 4;
+ const int e1 = err - (e7 + e5 + e3);
if (x < w)
- *b1 += (err*7)>>4; // spread error to right pixel
+ *b1 += e7; // spread error to right pixel
if (not_last_line) {
- b2[0] += (err*5)>>4; // pixel below
+ b2[0] += e5; // pixel below
if (x > 1)
- b2[-1] += (err*3)>>4; // pixel below left
+ b2[-1] += e3; // pixel below left
if (x < w)
- b2[1] += err>>4; // pixel below right
+ b2[1] += e1; // pixel below right
}
b2++;
}
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index befecbfe8b..f5fea2ed00 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -172,6 +172,31 @@ inline int qt_depthForFormat(QImage::Format format)
#pragma optimize("", on)
#endif
+inline QImage::Format qt_opaqueVersion(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_ARGB8565_Premultiplied:
+ return QImage::Format_RGB16;
+ case QImage::Format_ARGB8555_Premultiplied:
+ return QImage::Format_RGB555;
+ case QImage::Format_ARGB6666_Premultiplied:
+ return QImage::Format_RGB666;
+ case QImage::Format_ARGB4444_Premultiplied:
+ return QImage::Format_RGB444;
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ return QImage::Format_RGBX8888;
+ case QImage::Format_A2BGR30_Premultiplied:
+ return QImage::Format_BGR30;
+ case QImage::Format_A2RGB30_Premultiplied:
+ return QImage::Format_RGB30;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ default:
+ return QImage::Format_RGB32;
+ }
+}
+
inline QImage::Format qt_alphaVersion(QImage::Format format)
{
switch (format) {
@@ -201,6 +226,11 @@ inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format;
}
+inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format)
+{
+ return qt_opaqueVersion(format);
+}
+
inline QImage::Format qt_alphaVersionForPainting(QImage::Format format)
{
QImage::Format toFormat = qt_alphaVersion(format);
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 5b3e3985a7..1ea503a268 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1467,12 +1467,18 @@ QBitmap QPixmap::mask() const
On all platforms the depth of the primary screen will be returned.
+ \note QGuiApplication must be created before calling this function.
+
\sa depth(), QColormap::depth(), {QPixmap#Pixmap Information}{Pixmap Information}
*/
int QPixmap::defaultDepth()
{
- return QGuiApplication::primaryScreen()->depth();
+ QScreen *primary = QGuiApplication::primaryScreen();
+ if (Q_LIKELY(primary))
+ return primary->depth();
+ qWarning("QPixmap: QGuiApplication must be created before calling defaultDepth().");
+ return 0;
}
/*!
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 51b4309e0a..431002d032 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -89,7 +89,7 @@ QRasterPlatformPixmap::~QRasterPlatformPixmap()
{
}
-QImage::Format QRasterPlatformPixmap::systemOpaqueFormat()
+QImage::Format QRasterPlatformPixmap::systemNativeFormat()
{
if (!QGuiApplication::primaryScreen())
return QImage::Format_RGB32;
@@ -107,7 +107,7 @@ void QRasterPlatformPixmap::resize(int width, int height)
if (pixelType() == BitmapType)
format = QImage::Format_MonoLSB;
else
- format = systemOpaqueFormat();
+ format = systemNativeFormat();
image = QImage(width, height, format);
w = width;
@@ -314,8 +314,9 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage sourceImage, Qt::ImageCo
? QImage::Format_ARGB32_Premultiplied
: QImage::Format_RGB32;
} else {
- QImage::Format opaqueFormat = systemOpaqueFormat();
- QImage::Format alphaFormat = qt_alphaVersionForPainting(opaqueFormat);
+ QImage::Format nativeFormat = systemNativeFormat();
+ QImage::Format opaqueFormat = qt_opaqueVersionForPainting(nativeFormat);
+ QImage::Format alphaFormat = qt_alphaVersionForPainting(nativeFormat);
if (!sourceImage.hasAlphaChannel()) {
format = opaqueFormat;
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index cff962181a..fe2a1e581d 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -88,7 +88,7 @@ protected:
void createPixmapForImage(QImage sourceImage, Qt::ImageConversionFlags flags);
void setImage(const QImage &image);
QImage image;
- static QImage::Format systemOpaqueFormat();
+ static QImage::Format systemNativeFormat();
private:
friend class QPixmap;
diff --git a/src/gui/itemmodels/itemmodels.pri b/src/gui/itemmodels/itemmodels.pri
index 65bcd7c1ba..cab0594174 100644
--- a/src/gui/itemmodels/itemmodels.pri
+++ b/src/gui/itemmodels/itemmodels.pri
@@ -1,3 +1,5 @@
+!qtConfig(standarditemmodel): return()
+
HEADERS += \
itemmodels/qstandarditemmodel.h \
itemmodels/qstandarditemmodel_p.h \
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index 050c9a662b..c340bddc51 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -39,8 +39,6 @@
#include "qstandarditemmodel.h"
-#ifndef QT_NO_STANDARDITEMMODEL
-
#include <QtCore/qdatetime.h>
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
@@ -3259,5 +3257,3 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
QT_END_NAMESPACE
#include "moc_qstandarditemmodel.cpp"
-
-#endif // QT_NO_STANDARDITEMMODEL
diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h
index d8f06b629a..d1c04d6b51 100644
--- a/src/gui/itemmodels/qstandarditemmodel.h
+++ b/src/gui/itemmodels/qstandarditemmodel.h
@@ -49,10 +49,9 @@
#include <QtCore/qdatastream.h>
#endif
-QT_BEGIN_NAMESPACE
-
+QT_REQUIRE_CONFIG(standarditemmodel);
-#ifndef QT_NO_STANDARDITEMMODEL
+QT_BEGIN_NAMESPACE
template <class T> class QList;
@@ -454,8 +453,6 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QStandardItem &item);
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &out, const QStandardItem &item);
#endif
-#endif // QT_NO_STANDARDITEMMODEL
-
QT_END_NAMESPACE
#endif //QSTANDARDITEMMODEL_H
diff --git a/src/gui/itemmodels/qstandarditemmodel_p.h b/src/gui/itemmodels/qstandarditemmodel_p.h
index bd28ec3029..d3ff2787a5 100644
--- a/src/gui/itemmodels/qstandarditemmodel_p.h
+++ b/src/gui/itemmodels/qstandarditemmodel_p.h
@@ -54,8 +54,6 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "private/qabstractitemmodel_p.h"
-#ifndef QT_NO_STANDARDITEMMODEL
-
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qstack.h>
@@ -63,6 +61,8 @@
#include <QtCore/qvector.h>
#include <QtCore/qdebug.h>
+QT_REQUIRE_CONFIG(standarditemmodel);
+
QT_BEGIN_NAMESPACE
class QStandardItemData
@@ -224,6 +224,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_STANDARDITEMMODEL
-
#endif // QSTANDARDITEMMODEL_P_H
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 03efabfc7c..30b942b30c 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -598,6 +598,12 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
applications.
\endlist
+ The following parameter is available for \c {-platform cocoa} (on macOS):
+
+ \list
+ \li \c {fontengine=freetype}, uses the FreeType font engine.
+ \endlist
+
For more information about the platform-specific arguments available for
embedded Linux platforms, see \l{Qt for Embedded Linux}.
@@ -1292,6 +1298,21 @@ void QGuiApplicationPrivate::createPlatformIntegration()
#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
platformName = QT_QPA_DEFAULT_PLATFORM_NAME;
#endif
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+ QByteArray sessionType = qgetenv("XDG_SESSION_TYPE");
+ if (!sessionType.isEmpty()) {
+ if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb")))
+ platformName = QByteArrayLiteral("xcb");
+ else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland")))
+ platformName = QByteArrayLiteral("wayland");
+ }
+#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
+ // Add it as fallback in case XDG_SESSION_TYPE is something wrong
+ if (!platformName.contains(QT_QPA_DEFAULT_PLATFORM_NAME))
+ platformName += QByteArrayLiteral(";" QT_QPA_DEFAULT_PLATFORM_NAME);
+#endif
+#endif
+
QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM");
if (!platformNameEnv.isEmpty()) {
platformName = platformNameEnv;
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index cf3d712421..c3a264f1e8 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -222,6 +222,9 @@ void QOpenGLWindowPrivate::initialize()
if (context)
return;
+ if (!q->handle())
+ qWarning("Attempted to initialize QOpenGLWindow without a platform window");
+
context.reset(new QOpenGLContext);
context->setShareContext(shareContext);
context->setFormat(q->requestedFormat());
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index b2d968c046..48060a2c37 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -551,7 +551,7 @@ void QStyleHints::setMouseQuickSelectionThreshold(int threshold)
if (d->m_mouseQuickSelectionThreshold == threshold)
return;
d->m_mouseQuickSelectionThreshold = threshold;
- emit mouseDoubleClickIntervalChanged(threshold);
+ emit mouseQuickSelectionThresholdChanged(threshold);
}
/*!
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 318a280a40..5243ae66a2 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -251,7 +251,7 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt:
{
Q_ASSERT(window);
if (oldState < Qt::WindowNoState)
- oldState = window->windowState();
+ oldState = window->windowStates();
QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index 1fe30f7e0e..2ae9c6d327 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -46,7 +46,6 @@
#include <QtCore/qfile.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
-#include <QtCore/qregularexpression.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qcoreapplication.h>
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index b825b56d45..cea4b51a5c 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -2800,6 +2800,11 @@ QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
return d->format;
}
+static bool isNpot(int width, int height = 1, int depth = 1)
+{
+ return width & (width-1) || height & (height-1) || depth & (depth-1);
+}
+
/*!
Sets the dimensions of this texture object to \a width,
\a height, and \a depth. The default for each dimension is 1.
@@ -2807,6 +2812,10 @@ QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
implementation. Allocating storage for a texture less than the
maximum size can still fail if your system is low on resources.
+ If a non-power-of-two \a width, \a height or \a depth is provided and your
+ OpenGL implementation doesn't have support for repeating non-power-of-two
+ textures, then the wrap mode is automatically set to ClampToEdge.
+
\sa width(), height(), depth()
*/
void QOpenGLTexture::setSize(int width, int height, int depth)
@@ -2819,6 +2828,9 @@ void QOpenGLTexture::setSize(int width, int height, int depth)
return;
}
+ if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
+ d->setWrapMode(WrapMode::ClampToEdge);
+
switch (d->target) {
case QOpenGLTexture::Target1D:
case QOpenGLTexture::Target1DArray:
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
index 167f725143..dc7a4dfe8c 100644
--- a/src/gui/painting/qblendfunctions_p.h
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -137,6 +137,16 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
+ const int ystart = srcy >> 16;
+ if (ystart >= srch && iy < 0) {
+ srcy += iy;
+ --h;
+ }
+ const int xstart = basex >> 16;
+ if (xstart >= (int)(sbpl/sizeof(SRC)) && ix < 0) {
+ basex += ix;
+ --w;
+ }
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;
@@ -248,6 +258,16 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
+ const int ystart = srcy >> 16;
+ if (ystart >= srch && iy < 0) {
+ srcy += iy;
+ --h;
+ }
+ const int xstart = basex >> 16;
+ if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) {
+ basex += ix;
+ --w;
+ }
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 23c8e42ded..f3df62b855 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -2249,17 +2249,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper(uint *
#endif
while (b < boundedEnd) {
int x = (fx >> 16);
-#if defined(__SSE2__) || defined(__ARM_NEON__)
- int distx8 = (fx & 0x0000ffff) >> 8;
- *b = interpolate_4_pixels(s1 + x, s2 + x, distx8, disty8);
-#else
- uint tl = s1[x];
- uint tr = s1[x + 1];
- uint bl = s2[x];
- uint br = s2[x + 1];
- int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12;
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4);
-#endif
+ if (hasFastInterpolate4()) {
+ int distx8 = (fx & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(s1 + x, s2 + x, distx8, disty8);
+ } else {
+ int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ *b = interpolate_4_pixels_16(s1[x], s1[x + 1], s2[x], s2[x + 1], distx4, disty4);
+ }
fx += fdx;
++b;
}
@@ -2273,14 +2269,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper(uint *
uint tr = s1[x2];
uint bl = s2[x1];
uint br = s2[x2];
-#if defined(__SSE2__) || defined(__ARM_NEON__)
- // The optimized interpolate_4_pixels are faster than interpolate_4_pixels_16.
- int distx8 = (fx & 0x0000ffff) >> 8;
- *b = interpolate_4_pixels(tl, tr, bl, br, distx8, disty8);
-#else
- int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12;
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4);
-#endif
+ if (hasFastInterpolate4()) {
+ int distx8 = (fx & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx8, disty8);
+ } else {
+ int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4);
+ }
fx += fdx;
++b;
}
@@ -2345,15 +2340,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
uint tr = s1[x2];
uint bl = s2[x1];
uint br = s2[x2];
-#if defined(__SSE2__) || defined(__ARM_NEON__)
- int distx = (fx & 0x0000ffff) >> 8;
- int disty = (fy & 0x0000ffff) >> 8;
- *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
-#else
- int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
- int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
-#endif
+ if (hasFastInterpolate4()) {
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
+ } else {
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
+ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
+ }
fx += fdx;
fy += fdy;
++b;
@@ -2495,19 +2490,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
const uint *s1 = (const uint *)image.scanLine(y);
const uint *s2 = (const uint *)image.scanLine(y + 1);
-#if defined(__SSE2__) || defined(__ARM_NEON__)
- int distx = (fx & 0x0000ffff) >> 8;
- int disty = (fy & 0x0000ffff) >> 8;
- *b = interpolate_4_pixels(s1 + x, s2 + x, distx, disty);
-#else
- uint tl = s1[x];
- uint tr = s1[x + 1];
- uint bl = s2[x];
- uint br = s2[x + 1];
- int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
- int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
-#endif
+ if (hasFastInterpolate4()) {
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(s1 + x, s2 + x, distx, disty);
+ } else {
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
+ *b = interpolate_4_pixels_16(s1[x], s1[x + 1], s2[x], s2[x + 1], distx, disty);
+ }
fx += fdx;
fy += fdy;
@@ -2532,16 +2523,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
uint bl = s2[x1];
uint br = s2[x2];
-#if defined(__SSE2__) || defined(__ARM_NEON__)
- // The optimized interpolate_4_pixels are faster than interpolate_4_pixels_16.
- int distx = (fx & 0x0000ffff) >> 8;
- int disty = (fy & 0x0000ffff) >> 8;
- *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
-#else
- int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
- int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
- *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
-#endif
+ if (hasFastInterpolate4()) {
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
+ } else {
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
+ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
+ }
fx += fdx;
fy += fdy;
@@ -2939,7 +2929,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
- if (qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y)
+ if (hasFastInterpolate4() || qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y)
int disty = (fy & 0x0000ffff) >> 8;
for (int i = 0; i < len; ++i) {
int distx = (fx & 0x0000ffff) >> 8;
@@ -2974,7 +2964,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
- if (qAbs(data->m11) < qreal(1./8.)|| qAbs(data->m22) < qreal(1./8.)) {
+ if (hasFastInterpolate4() || qAbs(data->m11) < qreal(1./8.) || qAbs(data->m22) < qreal(1./8.)) {
// If we are zooming more than 8 times, we use 8bit precision for the position.
for (int i = 0; i < len; ++i) {
int distx = (fx & 0x0000ffff) >> 8;
@@ -5670,6 +5660,8 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL
// nothing
} else if (coverage == 255) {
*dst = src;
+ } else if (!colorProfile) {
+ *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
} else {
if (*dst >= 0xff000000) {
grayBlendPixel(dst, coverage, srcLinear, colorProfile);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index ebf215a3eb..b94fd34b51 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -685,6 +685,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis
__m128i vb = _mm_loadl_epi64((const __m128i*)b);
return interpolate_4_pixels_sse2(vt, vb, distx, disty);
}
+
+static constexpr inline bool hasFastInterpolate4() { return true; }
+
#elif defined(__ARM_NEON__)
static Q_ALWAYS_INLINE uint interpolate_4_pixels_neon(uint32x2_t vt32, uint32x2_t vb32, uint distx, uint disty)
{
@@ -717,6 +720,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis
uint32x2_t vb32 = vld1_u32(b);
return interpolate_4_pixels_neon(vt32, vb32, distx, disty);
}
+
+static constexpr inline bool hasFastInterpolate4() { return true; }
+
#else
static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
{
@@ -731,6 +737,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis
{
return interpolate_4_pixels(t[0], t[1], b[0], b[1], distx, disty);
}
+
+static constexpr inline bool hasFastInterpolate4() { return false; }
+
#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index bfe2080298..3212ffdd2d 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -558,6 +558,16 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
// this bounds check here is required as floating point rounding above might in some cases lead to
// w/h values that are one pixel too large, falling outside of the valid image area.
+ const int ystart = srcy >> 16;
+ if (ystart >= srch && iy < 0) {
+ srcy += iy;
+ --h;
+ }
+ const int xstart = basex >> 16;
+ if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) {
+ basex += ix;
+ --w;
+ }
int yend = (srcy + iy * (h - 1)) >> 16;
if (yend < 0 || yend >= srch)
--h;
diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp
index f3f7f5f956..2634a448a5 100644
--- a/src/gui/painting/qpagelayout.cpp
+++ b/src/gui/painting/qpagelayout.cpp
@@ -123,7 +123,6 @@ class QPageLayoutPrivate : public QSharedData
{
public:
- QPageLayoutPrivate();
QPageLayoutPrivate(const QPageSize &pageSize, QPageLayout::Orientation orientation,
const QMarginsF &margins, QPageLayout::Unit units,
const QMarginsF &minMargins);
@@ -166,12 +165,6 @@ private:
QMarginsF m_maxMargins;
};
-QPageLayoutPrivate::QPageLayoutPrivate()
- : m_orientation(QPageLayout::Landscape),
- m_mode(QPageLayout::StandardMode)
-{
-}
-
QPageLayoutPrivate::QPageLayoutPrivate(const QPageSize &pageSize, QPageLayout::Orientation orientation,
const QMarginsF &margins, QPageLayout::Unit units,
const QMarginsF &minMargins)
@@ -356,7 +349,7 @@ QRectF QPageLayoutPrivate::paintRect() const
*/
QPageLayout::QPageLayout()
- : d(new QPageLayoutPrivate())
+ : QPageLayout(QPageSize(), QPageLayout::Landscape, QMarginsF())
{
}
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 0e3163eefb..6336b2943e 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -641,6 +641,7 @@ QRasterPaintEngineState::QRasterPaintEngineState()
txscale = 1.;
flags.fast_pen = true;
+ flags.non_complex_pen = false;
flags.antialiased = false;
flags.bilinear = false;
flags.legacy_rounding = false;
@@ -697,6 +698,11 @@ void QRasterPaintEngine::setState(QPainterState *s)
{
Q_D(QRasterPaintEngine);
QPaintEngineEx::setState(s);
+ QRasterPaintEngineState *t = state();
+ if (t->clip && t->clip->enabled != t->clipEnabled) {
+ // Since we do not "detach" clipdata when changing only enabled state, we need to resync state here
+ t->clip->enabled = t->clipEnabled;
+ }
d->rasterBuffer->compositionMode = s->composition_mode;
}
@@ -2340,8 +2346,12 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) {
QRectF targetBounds = s->matrix.mapRect(r);
- bool exceedsPrecision = targetBounds.width() > 0x7fff
- || targetBounds.height() > 0x7fff;
+ bool exceedsPrecision = r.width() > 0x7fff
+ || r.height() > 0x7fff
+ || targetBounds.width() > 0x7fff
+ || targetBounds.height() > 0x7fff
+ || s->matrix.m11() >= 512
+ || s->matrix.m22() >= 512;
if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
if (s->matrix.type() > QTransform::TxScale) {
@@ -4638,9 +4648,13 @@ void QSpanData::setupMatrix(const QTransform &matrix, int bilin)
bilinear = bilin;
const bool affine = inv.isAffine();
+ const qreal f1 = m11 * m11 + m21 * m21;
+ const qreal f2 = m12 * m12 + m22 * m22;
fast_matrix = affine
- && m11 * m11 + m21 * m21 < 1e4
- && m12 * m12 + m22 * m22 < 1e4
+ && f1 < 1e4
+ && f2 < 1e4
+ && f1 > (1.0 / 65536)
+ && f2 > (1.0 / 65536)
&& qAbs(dx) < 1e4
&& qAbs(dy) < 1e4;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 27bd2e59e6..2574a00838 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1033,7 +1033,6 @@ void QPainterPath::addRect(const QRectF &r)
bool first = d_func()->elements.size() < 2;
- d_func()->elements.reserve(d_func()->elements.size() + 5);
moveTo(r.x(), r.y());
Element l1 = { r.x() + r.width(), r.y(), LineToElement };
@@ -1071,8 +1070,6 @@ void QPainterPath::addPolygon(const QPolygonF &polygon)
ensureData();
detach();
- d_func()->elements.reserve(d_func()->elements.size() + polygon.size());
-
moveTo(polygon.constFirst());
for (int i=1; i<polygon.size(); ++i) {
Element elm = { polygon.at(i).x(), polygon.at(i).y(), LineToElement };
@@ -1115,9 +1112,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect)
ensureData();
detach();
- Q_D(QPainterPath);
bool first = d_func()->elements.size() < 2;
- d->elements.reserve(d->elements.size() + 13);
QPointF pts[12];
int point_count;
@@ -1294,7 +1289,6 @@ void QPainterPath::addRegion(const QRegion &region)
ensureData();
detach();
- d_func()->elements.reserve(region.rectCount() * 5);
for (const QRect &rect : region)
addRect(rect);
}
@@ -2463,7 +2457,6 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
Q_ASSERT(p.d_func()->elements.at(0).type == QPainterPath::MoveToElement);
p.d_func()->elements.clear();
}
- p.d_func()->elements.reserve(p.d_func()->elements.size() + size);
for (int i=0; i<size; ++i) {
int type;
double x, y;
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index e421055ef3..e58f9cee4c 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -2045,7 +2045,6 @@ void QPdfEnginePrivate::printString(const QString &string)
}
-// For strings up to 10000 bytes only !
void QPdfEnginePrivate::xprintf(const char* fmt, ...)
{
if (!stream)
@@ -2057,12 +2056,18 @@ void QPdfEnginePrivate::xprintf(const char* fmt, ...)
va_list args;
va_start(args, fmt);
int bufsize = qvsnprintf(buf, msize, fmt, args);
-
- Q_ASSERT(bufsize<msize);
-
va_end(args);
- stream->writeRawData(buf, bufsize);
+ if (Q_LIKELY(bufsize < msize)) {
+ stream->writeRawData(buf, bufsize);
+ } else {
+ // Fallback for abnormal cases
+ QScopedArrayPointer<char> tmpbuf(new char[bufsize + 1]);
+ va_start(args, fmt);
+ bufsize = qvsnprintf(tmpbuf.data(), bufsize + 1, fmt, args);
+ va_end(args);
+ stream->writeRawData(tmpbuf.data(), bufsize);
+ }
streampos += bufsize;
}
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 404a722e29..a4e5130937 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -2889,7 +2889,7 @@ Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script
uint order = i;
if (testFamily == nullptr
|| (testFamily->writingSystems[writingSystem] & QtFontFamily::Supported) == 0) {
- order |= 1 << 31;
+ order |= 1u << 31;
}
supported.insert(order, family);
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index e27b388762..44d1b2f201 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -47,7 +47,9 @@
#include "qtextlist.h"
#include <qdebug.h>
#include <qregexp.h>
+#if QT_CONFIG(regularexpression)
#include <qregularexpression.h>
+#endif
#include <qvarlengtharray.h>
#include <qtextcodec.h>
#include <qthread.h>
@@ -1488,7 +1490,7 @@ QTextCursor QTextDocument::find(const QRegExp &expr, const QTextCursor &cursor,
}
#endif // QT_REGEXP
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
static bool findInBlock(const QTextBlock &block, const QRegularExpression &expression, int offset,
QTextDocument::FindFlags options, QTextCursor *cursor)
{
@@ -1613,7 +1615,7 @@ QTextCursor QTextDocument::find(const QRegularExpression &expr, const QTextCurso
}
return find(expr, pos, options);
}
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*!
\fn QTextObject *QTextDocument::createObject(const QTextFormat &format)
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index c847d3ce88..64e39d4648 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -175,7 +175,7 @@ public:
QTextCursor find(const QRegExp &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const;
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QTextCursor find(const QRegularExpression &expr, int from = 0, FindFlags options = FindFlags()) const;
QTextCursor find(const QRegularExpression &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const;
#endif
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 77ccc02aa5..dfd190ddd0 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -226,8 +226,11 @@ bool QDesktopServices::openUrl(const QUrl &url)
qWarning("The platform plugin does not support services.");
return false;
}
- return url.scheme() == QLatin1String("file") ?
- platformServices->openDocument(url) : platformServices->openUrl(url);
+ // We only use openDocument if there is no fragment for the URL to
+ // avoid it being lost when using openDocument
+ if (url.isLocalFile() && !url.hasFragment())
+ return platformServices->openDocument(url);
+ return platformServices->openUrl(url);
}
/*!
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
index 31c2f74746..ae45c03fd1 100644
--- a/src/gui/util/qshadergenerator.cpp
+++ b/src/gui/util/qshadergenerator.cpp
@@ -61,6 +61,8 @@ namespace
return ""; // Although fragment shaders for <=2 only have fixed outputs
case QShaderLanguage::Uniform:
return "uniform";
+ case QShaderLanguage::BuiltIn:
+ return "//";
}
} else {
switch (qualifier) {
@@ -72,6 +74,8 @@ namespace
return "out";
case QShaderLanguage::Uniform:
return "uniform";
+ case QShaderLanguage::BuiltIn:
+ return "//";
}
}
diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h
index 5c7819a3b8..e392a6c7bb 100644
--- a/src/gui/util/qshaderlanguage_p.h
+++ b/src/gui/util/qshaderlanguage_p.h
@@ -64,6 +64,7 @@ namespace QShaderLanguage
enum StorageQualifier : char {
Const = 1,
Input,
+ BuiltIn,
Output,
Uniform
};
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 1709012291..7982ad967e 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -916,7 +916,7 @@ void QRegExpValidator::setRegExp(const QRegExp& rx)
#endif
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\class QRegularExpressionValidator
@@ -1067,7 +1067,7 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr
}
}
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
QT_END_NAMESPACE
diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h
index ad23092537..cc7cbcb559 100644
--- a/src/gui/util/qvalidator.h
+++ b/src/gui/util/qvalidator.h
@@ -45,7 +45,9 @@
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
#include <QtCore/qregexp.h>
-#include <QtCore/qregularexpression.h>
+#if QT_CONFIG(regularexpression)
+# include <QtCore/qregularexpression.h>
+#endif
#include <QtCore/qlocale.h>
QT_BEGIN_NAMESPACE
@@ -194,7 +196,7 @@ private:
#endif // QT_NO_REGEXP
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
class QRegularExpressionValidatorPrivate;
@@ -223,7 +225,7 @@ private:
Q_DECLARE_PRIVATE(QRegularExpressionValidator)
};
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
#endif // QT_NO_VALIDATOR
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index 0cdcee6b59..22541e83ba 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -212,6 +212,9 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
void QHttp2ProtocolHandler::_q_uploadDataReadyRead()
{
+ if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted.
+ return;
+
auto data = qobject_cast<QNonContiguousByteDevice *>(sender());
Q_ASSERT(data);
const qint32 streamID = data->property("HTTP2StreamID").toInt();
@@ -917,10 +920,11 @@ void QHttp2ProtocolHandler::handleContinuedHEADERS()
if (activeStreams.contains(streamID)) {
Stream &stream = activeStreams[streamID];
if (stream.state != Stream::halfClosedLocal
- && stream.state != Stream::remoteReserved) {
+ && stream.state != Stream::remoteReserved
+ && stream.state != Stream::open) {
// We can receive HEADERS on streams initiated by our requests
- // (these streams are in halfClosedLocal state) or remote-reserved
- // streams from a server's PUSH_PROMISE.
+ // (these streams are in halfClosedLocal or open state) or
+ // remote-reserved streams from a server's PUSH_PROMISE.
finishStreamWithError(stream, QNetworkReply::ProtocolFailure,
QLatin1String("HEADERS on invalid stream"));
sendRST_STREAM(streamID, CANCEL);
@@ -1109,6 +1113,17 @@ void QHttp2ProtocolHandler::updateStream(Stream &stream, const HPack::HttpHeader
if (QHttpNetworkReply::isHttpRedirect(statusCode) && redirectUrl.isValid())
httpReply->setRedirectUrl(redirectUrl);
+ if (QHttpNetworkReply::isHttpRedirect(statusCode)
+ || statusCode == 401 || statusCode == 407) {
+ // These are the status codes that can trigger uploadByteDevice->reset()
+ // in QHttpNetworkConnectionChannel::handleStatus. Alas, we have no
+ // single request/reply, we multiplex several requests and thus we never
+ // simply call 'handleStatus'. If we have byte-device - we try to reset
+ // it here, we don't (and can't) handle any error during reset operation.
+ if (stream.data())
+ stream.data()->reset();
+ }
+
if (connectionType == Qt::DirectConnection)
emit httpReply->headerChanged();
else
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 54930a351a..a794b492e7 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -1125,6 +1125,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
setRequest(req);
setUrl(req.url());
setOperation(op);
+ setFinished(true);
qRegisterMetaType<QNetworkReply::NetworkError>();
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 70674e9adf..75a26848a6 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -706,7 +706,7 @@ int QNetworkInterface::index() const
\sa QUdpSocket
*/
-int QNetworkInterface::maxTransmissionUnit() const
+int QNetworkInterface::maximumTransmissionUnit() const
{
return d ? d->mtu : 0;
}
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index f7ef192dc0..148fd5e10d 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -153,7 +153,7 @@ public:
bool isValid() const;
int index() const;
- int maxTransmissionUnit() const;
+ int maximumTransmissionUnit() const;
QString name() const;
QString humanReadableName() const;
InterfaceFlags flags() const;
diff --git a/src/network/kernel/qnetworkinterface_linux.cpp b/src/network/kernel/qnetworkinterface_linux.cpp
index 01b2811070..23ed2e0e15 100644
--- a/src/network/kernel/qnetworkinterface_linux.cpp
+++ b/src/network/kernel/qnetworkinterface_linux.cpp
@@ -41,6 +41,8 @@
#include "qnetworkinterface_p.h"
#include "qnetworkinterface_unix_p.h"
+#ifndef QT_NO_NETWORKINTERFACE
+
#include <qendian.h>
#include <qobjectdefs.h>
#include <qvarlengtharray.h>
@@ -382,7 +384,14 @@ static void getAddresses(int sock, char *buf, QList<QNetworkInterfacePrivate *>
auto payloadPtr = reinterpret_cast<uchar *>(RTA_DATA(rta));
switch (rta->rta_type) {
- case IFA_ADDRESS: // address
+ case IFA_ADDRESS:
+ // Local address (all interfaces except for point-to-point)
+ if (entry.ip().isNull())
+ entry.setIp(makeAddress(payloadPtr, payloadLen));
+ break;
+
+ case IFA_LOCAL:
+ // Override the local address (point-to-point interfaces)
entry.setIp(makeAddress(payloadPtr, payloadLen));
break;
@@ -441,3 +450,5 @@ QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
}
QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKINTERFACE
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 9df5f0c500..7ac6297de6 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -87,6 +87,9 @@ typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation;
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcNetworkSocket, "qt.network.socket");
+Q_LOGGING_CATEGORY(lcNetworkSocketVerbose, "qt.network.socket.verbose");
+
#if _MSC_VER >= 1900
static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr<IThreadNetworkContext> &context)
{
@@ -167,11 +170,14 @@ public:
SocketEngineWorker(QNativeSocketEnginePrivate *engine)
: enginePrivate(engine)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << engine;
}
~SocketEngineWorker()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
if (Q_UNLIKELY(initialReadOp)) {
+ qCDebug(lcNetworkSocket) << Q_FUNC_INFO << "Closing initial read operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = initialReadOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -184,6 +190,7 @@ public:
}
if (readOp) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing read operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -196,6 +203,7 @@ public:
}
if (connectOp) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing connect operation";
ComPtr<IAsyncInfo> info;
HRESULT hr = connectOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -210,30 +218,13 @@ public:
signals:
void connectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString);
- void newDatagramsReceived(const QList<WinRtDatagram> &datagram);
- void newDataReceived(const QVector<QByteArray> &data);
+ void newDataReceived();
void socketErrorOccured(QAbstractSocket::SocketError error);
-public slots:
- Q_INVOKABLE void notifyAboutNewDatagrams()
- {
- QMutexLocker locker(&mutex);
- QList<WinRtDatagram> datagrams = pendingDatagrams;
- pendingDatagrams.clear();
- emit newDatagramsReceived(datagrams);
- }
-
- Q_INVOKABLE void notifyAboutNewData()
- {
- QMutexLocker locker(&mutex);
- const QVector<QByteArray> newData = std::move(pendingData);
- pendingData.clear();
- emit newDataReceived(newData);
- }
-
public:
void startReading()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
ComPtr<IBuffer> buffer;
HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
Q_ASSERT_SUCCEEDED(hr);
@@ -249,6 +240,7 @@ public:
HRESULT onConnectOpFinished(IAsyncAction *action, AsyncStatus)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
HRESULT hr = action->GetResults();
if (FAILED(hr)) {
if (hr == HRESULT_FROM_WIN32(WSAETIMEDOUT)) {
@@ -287,6 +279,7 @@ public:
HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
WinRtDatagram datagram;
QHostAddress returnAddress;
ComPtr<IHostName> remoteHost;
@@ -311,10 +304,11 @@ public:
datagram.data.resize(length);
hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data()));
RETURN_OK_IF_FAILED("Could not read datagram");
+
QMutexLocker locker(&mutex);
// Notify the engine about new datagrams being present at the next event loop iteration
- if (pendingDatagrams.isEmpty())
- QMetaObject::invokeMethod(this, "notifyAboutNewDatagrams", Qt::QueuedConnection);
+ if (emitDataReceived)
+ emit newDataReceived();
pendingDatagrams << datagram;
return S_OK;
@@ -322,6 +316,7 @@ public:
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
if (asyncInfo == initialReadOp.Get()) {
initialReadOp.Reset();
} else if (asyncInfo == readOp.Get()) {
@@ -334,6 +329,7 @@ public:
// that the connection was closed. The socket cannot be closed here, as the subsequent read
// might fail then.
if (status == Error || status == Canceled) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed";
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
@@ -358,6 +354,7 @@ public:
// the closing of the socket won't be communicated to the caller. So only the error is set. The
// actual socket close happens inside of read.
if (!bufferLength) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed";
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
@@ -378,10 +375,10 @@ public:
}
QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength));
+
QMutexLocker readLocker(&mutex);
- if (pendingData.isEmpty())
- QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection);
- pendingData << newData;
+ emit newDataReceived();
+ pendingData.append(newData);
readLocker.unlock();
hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() {
@@ -433,7 +430,8 @@ private:
ComPtr<IStreamSocket> tcpSocket;
QList<WinRtDatagram> pendingDatagrams;
- QVector<QByteArray> pendingData;
+ bool emitDataReceived = true;
+ QByteArray pendingData;
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex mutex;
@@ -487,6 +485,12 @@ static QByteArray socketDescription(const QAbstractSocketEngine *s)
" not in "#state1" or "#state2); \
return (returnValue); \
} } while (0)
+#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \
+ if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \
+ qWarning(""#function" was called" \
+ " not in "#state1", "#state2" or "#state3); \
+ return (returnValue); \
+ } } while (0)
#define Q_CHECK_TYPE(function, type, returnValue) do { \
if (d->socketType != (type)) { \
qWarning(#function" was called by a" \
@@ -509,6 +513,7 @@ static AsyncStatus opStatus(const ComPtr<T> &op)
static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint64 len)
{
+ qCDebug(lcNetworkSocket) << Q_FUNC_INFO << data << len;
ComPtr<IBuffer> buffer;
HRESULT hr = g->bufferFactory->Create(len, &buffer);
Q_ASSERT_SUCCEEDED(hr);
@@ -533,6 +538,7 @@ static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint
QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << parent;
qRegisterMetaType<WinRtDatagram>();
qRegisterMetaType<WinRTSocketEngine::ErrorString>();
Q_D(QNativeSocketEngine);
@@ -541,25 +547,28 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
d->sslSocket = qobject_cast<QSslSocket *>(parent->parent());
#endif
- connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection);
- connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection);
- connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
+ connect(this, &QNativeSocketEngine::connectionReady,
+ this, &QNativeSocketEngine::connectionNotification, Qt::QueuedConnection);
+ connect(this, &QNativeSocketEngine::readReady,
+ this, &QNativeSocketEngine::processReadReady, Qt::QueuedConnection);
+ connect(this, &QNativeSocketEngine::writeReady,
+ this, &QNativeSocketEngine::writeNotification, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished, Qt::QueuedConnection);
- connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection);
- connect(d->worker, &SocketEngineWorker::newDataReceived,
- this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
+ connect(d->worker, &SocketEngineWorker::newDataReceived, this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::socketErrorOccured,
this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection);
}
QNativeSocketEngine::~QNativeSocketEngine()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
close();
}
bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << type << protocol;
Q_D(QNativeSocketEngine);
if (isValid())
close();
@@ -568,6 +577,28 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract
if (!d->createNewSocket(type, protocol))
return false;
+ if (type == QAbstractSocket::UdpSocket) {
+ // Set the broadcasting flag if it's a UDP socket.
+ if (!setOption(BroadcastSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ WinRTSocketEngine::BroadcastingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+ // Set some extra flags that are interesting to us, but accept failure
+ setOption(ReceivePacketInformation, 1);
+ setOption(ReceiveHopLimit, 1);
+ }
+
+
+ // Make sure we receive out-of-band data
+ if (type == QAbstractSocket::TcpSocket
+ && !setOption(ReceiveOutOfBandData, 1)) {
+ qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data");
+ }
+
+
d->socketType = type;
d->socketProtocol = protocol;
return true;
@@ -575,6 +606,7 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract
bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketDescriptor << socketState;
Q_D(QNativeSocketEngine);
if (isValid())
@@ -622,18 +654,28 @@ bool QNativeSocketEngine::isValid() const
bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port;
+ Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false);
+ Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState,
+ QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
const QString addressString = address.toString();
return connectToHostByName(addressString, port);
}
bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << name << port;
Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHostByName(), false);
+ Q_CHECK_STATES3(QNativeSocketEngine::connectToHostByName(), QAbstractSocket::BoundState,
+ QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
HRESULT hr;
#if _MSC_VER >= 1900
ComPtr<IThreadNetworkContext> networkContext;
if (!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT")) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Creating network context";
hr = qt_winrt_try_create_thread_network_context(name, networkContext);
if (FAILED(hr)) {
setError(QAbstractSocket::ConnectionRefusedError, QLatin1String("Could not create thread network context."));
@@ -668,6 +710,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
#if _MSC_VER >= 1900
if (networkContext != nullptr) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing network context";
ComPtr<IClosable> networkContextCloser;
hr = networkContext.As(&networkContextCloser);
Q_ASSERT_SUCCEEDED(hr);
@@ -691,7 +734,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port;
Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false);
+ Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
+
HRESULT hr;
// runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result.
// hr is set inside the lambda though. If an error occurred hr will point that out.
@@ -773,10 +820,16 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
bool QNativeSocketEngine::listen()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false);
+#if QT_CONFIG(sctp)
+ Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket,
+ QAbstractSocket::SctpSocket, false);
+#else
Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
+#endif
if (d->tcpListener && d->socketDescriptor != -1) {
d->socketState = QAbstractSocket::ListeningState;
@@ -787,10 +840,16 @@ bool QNativeSocketEngine::listen()
int QNativeSocketEngine::accept()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1);
+#if QT_CONFIG(sctp)
+ Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket,
+ QAbstractSocket::SctpSocket, -1);
+#else
Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1);
+#endif
if (d->socketDescriptor == -1 || d->pendingConnections.isEmpty()) {
d->setError(QAbstractSocket::TemporaryError, WinRTSocketEngine::TemporaryErrorString);
@@ -810,17 +869,21 @@ int QNativeSocketEngine::accept()
void QNativeSocketEngine::close()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
if (d->closingDown)
return;
- d->closingDown = true;
+ if (d->pendingReadNotification)
+ processReadReady();
+ d->closingDown = true;
d->notifyOnRead = false;
d->notifyOnWrite = false;
d->notifyOnException = false;
+ d->emitReadReady = false;
HRESULT hr;
if (d->socketType == QAbstractSocket::TcpSocket) {
@@ -878,29 +941,41 @@ void QNativeSocketEngine::close()
bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
{
- Q_UNUSED(groupAddress);
- Q_UNUSED(iface);
+ Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
+ Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
+ Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface;
Q_UNIMPLEMENTED();
return false;
}
bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
{
- Q_UNUSED(groupAddress);
- Q_UNUSED(iface);
+ Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false);
+ Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
+ Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface;
Q_UNIMPLEMENTED();
return false;
}
QNetworkInterface QNativeSocketEngine::multicastInterface() const
{
+ Q_D(const QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface());
+ Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface());
Q_UNIMPLEMENTED();
return QNetworkInterface();
}
bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
{
- Q_UNUSED(iface);
+ Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false);
+ Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false);
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << iface;
Q_UNIMPLEMENTED();
return false;
}
@@ -908,55 +983,66 @@ bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
qint64 QNativeSocketEngine::bytesAvailable() const
{
Q_D(const QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1);
+ Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1);
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
- return d->bytesAvailable;
+ QMutexLocker locker(&d->worker->mutex);
+ const qint64 bytesAvailable = d->worker->pendingData.length();
+
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << bytesAvailable;
+ return bytesAvailable;
}
qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << maxlen;
Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1);
+ Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
// There will be a read notification when the socket was closed by the remote host. If that
// happens and there isn't anything left in the buffer, we have to return -1 in order to signal
// the closing of the socket.
- QMutexLocker mutexLocker(&d->readMutex);
- if (d->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) {
+ QMutexLocker mutexLocker(&d->worker->mutex);
+ if (d->worker->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) {
close();
return -1;
}
QByteArray readData;
- qint64 leftToMaxLen = maxlen;
- while (leftToMaxLen > 0 && !d->pendingData.isEmpty()) {
- QByteArray pendingData = d->pendingData.takeFirst();
- // Do not read the whole data. Put the rest of it back into the "queue"
- if (leftToMaxLen < pendingData.length()) {
- readData += pendingData.left(leftToMaxLen);
- pendingData = pendingData.remove(0, maxlen);
- d->pendingData.prepend(pendingData);
- break;
- } else {
- readData += pendingData;
- leftToMaxLen -= pendingData.length();
+ const int copyLength = qMin(maxlen, qint64(d->worker->pendingData.length()));
+ if (maxlen >= d->worker->pendingData.length()) {
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading full buffer";
+ readData = d->worker->pendingData;
+ d->worker->pendingData.clear();
+ d->emitReadReady = true;
+ } else {
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading part of the buffer ("
+ << copyLength << "of" << d->worker->pendingData.length() << "bytes";
+ readData = d->worker->pendingData.left(maxlen);
+ d->worker->pendingData.remove(0, maxlen);
+ if (d->notifyOnRead) {
+ d->pendingReadNotification = true;
+ emit readReady();
}
}
- const int copyLength = qMin(maxlen, qint64(readData.length()));
- d->bytesAvailable -= copyLength;
mutexLocker.unlock();
memcpy(data, readData, copyLength);
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Read" << copyLength << "bytes";
return copyLength;
}
qint64 QNativeSocketEngine::write(const char *data, qint64 len)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len;
Q_D(QNativeSocketEngine);
- if (!isValid())
- return -1;
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1);
+ Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
HRESULT hr = E_FAIL;
ComPtr<IOutputStream> stream;
@@ -978,28 +1064,35 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len)
qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header,
PacketHeaderOptions)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << maxlen;
#ifndef QT_NO_UDPSOCKET
Q_D(QNativeSocketEngine);
- QMutexLocker locker(&d->readMutex);
- if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) {
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
+ Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState,
+ QAbstractSocket::ConnectedState, -1);
+
+ QMutexLocker locker(&d->worker->mutex);
+ if (d->socketType != QAbstractSocket::UdpSocket || d->worker->pendingDatagrams.isEmpty()) {
if (header)
header->clear();
return -1;
}
- WinRtDatagram datagram = d->pendingDatagrams.takeFirst();
+ WinRtDatagram datagram = d->worker->pendingDatagrams.takeFirst();
if (header)
*header = datagram.header;
QByteArray readOrigin;
- // Do not read the whole datagram. Put the rest of it back into the "queue"
- if (maxlen < datagram.data.length()) {
+ if (maxlen < datagram.data.length())
readOrigin = datagram.data.left(maxlen);
- datagram.data = datagram.data.remove(0, maxlen);
- d->pendingDatagrams.prepend(datagram);
- } else {
+ else
readOrigin = datagram.data;
+ if (d->worker->pendingDatagrams.isEmpty()) {
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "That's all folks";
+ d->worker->emitDataReceived = true;
+ d->emitReadReady = true;
}
+
locker.unlock();
memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length())));
return readOrigin.length();
@@ -1013,8 +1106,13 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea
qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len;
#ifndef QT_NO_UDPSOCKET
Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
+ Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState,
+ QAbstractSocket::ConnectedState, -1);
+
if (d->socketType != QAbstractSocket::UdpSocket)
return -1;
@@ -1051,18 +1149,25 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI
bool QNativeSocketEngine::hasPendingDatagrams() const
{
Q_D(const QNativeSocketEngine);
- QMutexLocker locker(&d->readMutex);
- return d->pendingDatagrams.length() > 0;
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false);
+ Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
+ Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
+
+ QMutexLocker locker(&d->worker->mutex);
+ return d->worker->pendingDatagrams.length() > 0;
}
qint64 QNativeSocketEngine::pendingDatagramSize() const
{
Q_D(const QNativeSocketEngine);
- QMutexLocker locker(&d->readMutex);
- if (d->pendingDatagrams.isEmpty())
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1);
+ Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1);
+
+ QMutexLocker locker(&d->worker->mutex);
+ if (d->worker->pendingDatagrams.isEmpty())
return -1;
- return d->pendingDatagrams.at(0).data.length();
+ return d->worker->pendingDatagrams.at(0).data.length();
}
qint64 QNativeSocketEngine::bytesToWrite() const
@@ -1078,6 +1183,7 @@ qint64 QNativeSocketEngine::receiveBufferSize() const
void QNativeSocketEngine::setReceiveBufferSize(qint64 bufferSize)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize;
Q_D(QNativeSocketEngine);
d->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, bufferSize);
}
@@ -1090,6 +1196,7 @@ qint64 QNativeSocketEngine::sendBufferSize() const
void QNativeSocketEngine::setSendBufferSize(qint64 bufferSize)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize;
Q_D(QNativeSocketEngine);
d->setOption(QAbstractSocketEngine::SendBufferSocketOption, bufferSize);
}
@@ -1102,12 +1209,14 @@ int QNativeSocketEngine::option(QAbstractSocketEngine::SocketOption option) cons
bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option, int value)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << option << value;
Q_D(QNativeSocketEngine);
return d->setOption(option, value);
}
bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs;
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
@@ -1124,8 +1233,8 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
return true;
// If we are a client, we are ready to read if our buffer has data
- QMutexLocker locker(&d->readMutex);
- if (!d->pendingData.isEmpty())
+ QMutexLocker locker(&d->worker->mutex);
+ if (!d->worker->pendingData.isEmpty())
return true;
// Nothing to do, wait for more events
@@ -1142,9 +1251,13 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
{
- Q_UNUSED(msecs);
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs;
Q_UNUSED(timedOut);
Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
+ Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
+ QAbstractSocket::UnconnectedState, false);
+
if (d->socketState == QAbstractSocket::ConnectingState) {
HRESULT hr = QWinRTFunctions::await(d->worker->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
if (SUCCEEDED(hr)) {
@@ -1157,11 +1270,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << checkRead << checkWrite << msecs;
+ Q_D(QNativeSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false);
+ Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
+ QAbstractSocket::UnconnectedState, false);
+
Q_UNUSED(readyToRead);
Q_UNUSED(readyToWrite);
- Q_UNUSED(checkRead);
- Q_UNUSED(checkWrite);
- Q_UNUSED(msecs);
Q_UNUSED(timedOut);
return false;
}
@@ -1174,6 +1290,7 @@ bool QNativeSocketEngine::isReadNotificationEnabled() const
void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnRead = enable;
}
@@ -1186,6 +1303,7 @@ bool QNativeSocketEngine::isWriteNotificationEnabled() const
void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnWrite = enable;
if (enable && d->socketState == QAbstractSocket::ConnectedState) {
@@ -1203,12 +1321,14 @@ bool QNativeSocketEngine::isExceptionNotificationEnabled() const
void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable;
Q_D(QNativeSocketEngine);
d->notifyOnException = enable;
}
void QNativeSocketEngine::establishRead()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
HRESULT hr;
@@ -1222,16 +1342,19 @@ void QNativeSocketEngine::establishRead()
void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << success << error << errorString;
Q_D(QNativeSocketEngine);
disconnect(d->worker, &SocketEngineWorker::connectOpFinished,
this, &QNativeSocketEngine::handleConnectOpFinished);
if (!success) {
d->setError(error, errorString);
d->socketState = QAbstractSocket::UnconnectedState;
+ close();
return;
}
d->socketState = QAbstractSocket::ConnectedState;
+ d->fetchConnectionParameters();
emit connectionReady();
if (d->socketType != QAbstractSocket::TcpSocket)
@@ -1246,29 +1369,25 @@ void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket:
establishRead();
}
-void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagrams)
+void QNativeSocketEngine::handleNewData()
{
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO;
Q_D(QNativeSocketEngine);
- QMutexLocker locker(&d->readMutex);
- d->pendingDatagrams.append(datagrams);
- if (d->notifyOnRead)
- emit readReady();
-}
-void QNativeSocketEngine::handleNewData(const QVector<QByteArray> &data)
-{
- Q_D(QNativeSocketEngine);
- QMutexLocker locker(&d->readMutex);
- d->pendingData.append(data);
- for (const QByteArray &newData : data)
- d->bytesAvailable += newData.length();
- locker.unlock();
- if (d->notifyOnRead)
- readNotification();
+ if (d->notifyOnRead && d->emitReadReady) {
+ if (d->socketType == QAbstractSocket::UdpSocket && !d->worker->emitDataReceived)
+ return;
+ qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Emitting readReady";
+ d->pendingReadNotification = true;
+ emit readReady();
+ d->worker->emitDataReceived = false;
+ d->emitReadReady = false;
+ }
}
void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error;
Q_D(QNativeSocketEngine);
WinRTSocketEngine::ErrorString errorString;
switch (error) {
@@ -1280,13 +1399,22 @@ void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
}
d->setError(error, errorString);
- d->socketState = QAbstractSocket::UnconnectedState;
- if (d->notifyOnRead)
- emit readReady();
+ close();
+}
+
+void QNativeSocketEngine::processReadReady()
+{
+ Q_D(QNativeSocketEngine);
+ if (d->closingDown)
+ return;
+
+ d->pendingReadNotification = false;
+ readNotification();
}
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketType << socketProtocol;
Q_UNUSED(socketProtocol);
HRESULT hr;
@@ -1343,10 +1471,12 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, sslSocket(nullptr)
, connectionToken( { -1 } )
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
if (socketDescriptor == -1 || connectionToken.value == -1)
return;
@@ -1362,6 +1492,7 @@ QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error << errorString;
if (hasSetSocketError) {
// Only set socket errors once for one engine; expect the
// socket to recreate its engine after an error. Note: There's
@@ -1523,6 +1654,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt)
bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption opt, int v)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << opt << v;
ComPtr<IStreamSocketControl> control;
if (socketType == QAbstractSocket::TcpSocket) {
if (FAILED(tcpSocket()->get_Control(&control))) {
@@ -1583,6 +1715,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o
bool QNativeSocketEnginePrivate::fetchConnectionParameters()
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
localPort = 0;
localAddress.clear();
peerPort = 0;
@@ -1659,6 +1792,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args)
{
+ qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO;
Q_Q(QNativeSocketEngine);
Q_UNUSED(listener)
IStreamSocket *socket;
@@ -1670,40 +1804,6 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
-{
- Q_Q(QNativeSocketEngine);
- Q_UNUSED(socket);
-
- WinRtDatagram datagram;
- QHostAddress returnAddress;
- ComPtr<IHostName> remoteHost;
- HRESULT hr = args->get_RemoteAddress(&remoteHost);
- RETURN_OK_IF_FAILED("Could not obtain remote host");
- HString remoteHostString;
- remoteHost->get_CanonicalName(remoteHostString.GetAddressOf());
- RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name");
- returnAddress.setAddress(qt_QStringFromHString(remoteHostString));
- datagram.header.senderAddress = returnAddress;
- HString remotePort;
- hr = args->get_RemotePort(remotePort.GetAddressOf());
- RETURN_OK_IF_FAILED("Could not obtain remote port");
- datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt();
-
- ComPtr<IDataReader> reader;
- hr = args->GetDataReader(&reader);
- RETURN_OK_IF_FAILED("Could not obtain data reader");
- quint32 length;
- hr = reader->get_UnconsumedBufferLength(&length);
- RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length");
- datagram.data.resize(length);
- hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data()));
- RETURN_OK_IF_FAILED("Could not read datagram");
- emit q->newDatagramReceived(datagram);
-
- return S_OK;
-}
-
QT_END_NAMESPACE
#include "qnativesocketengine_winrt.moc"
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 13922cb397..6688bfe35c 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -54,6 +54,7 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtCore/QEventLoop>
#include <QtCore/QBuffer>
+#include <QtCore/QLoggingCategory>
#include <QtCore/QMutex>
#include <QtCore/QAtomicInteger>
#include "QtNetwork/qhostaddress.h"
@@ -63,6 +64,9 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocket)
+Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocketVerbose)
+
namespace WinRTSocketEngine {
enum ErrorString {
NonBlockingInitFailedErrorString,
@@ -178,9 +182,9 @@ private slots:
void establishRead();
void handleConnectOpFinished(bool success, QAbstractSocket::SocketError error,
WinRTSocketEngine::ErrorString errorString);
- void handleNewDatagrams(const QList<WinRtDatagram> &datagram);
- void handleNewData(const QVector<QByteArray> &data);
+ void handleNewData();
void handleTcpError(QAbstractSocket::SocketError error);
+ void processReadReady();
private:
Q_DECLARE_PRIVATE(QNativeSocketEngine)
@@ -218,28 +222,15 @@ private:
{ return reinterpret_cast<ABI::Windows::Networking::Sockets::IDatagramSocket *>(socketDescriptor); }
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
- // In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is
- // pendingDatagrams. They are written inside native callbacks (handleReadyRead and
- // handleNewDatagrams/putIntoPendingDatagramsList)
- mutable QMutex readMutex;
-
- // Protected by readMutex. Written in handleReadyRead (native callback)
- QAtomicInteger<int> bytesAvailable;
-
- // Protected by readMutex. Written in handleNewData/putIntoPendingData (native callback)
- QVector<QByteArray> pendingData;
-
- // Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList
- QList<WinRtDatagram> pendingDatagrams;
-
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
QEventLoop eventLoop;
QAbstractSocket *sslSocket;
EventRegistrationToken connectionToken;
- HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
- ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
+ bool emitReadReady = true;
+ bool pendingReadNotification = false;
+
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
};
diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri
index a8a37492b7..44ff5b7b39 100644
--- a/src/network/socket/socket.pri
+++ b/src/network/socket/socket.pri
@@ -73,7 +73,7 @@ qtConfig(localserver) {
SOURCES += socket/qlocalsocket.cpp \
socket/qlocalserver.cpp
- intergrity|winrt {
+ integrity|winrt {
SOURCES += socket/qlocalsocket_tcp.cpp \
socket/qlocalserver_tcp.cpp
DEFINES += QT_LOCALSOCKET_TCP
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 8a5540e8bd..51779dec33 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -116,18 +116,18 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
Describes the protocol of the cipher.
- \value SslV3 SSLv3
- \value SslV2 SSLv2
+ \value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0
+ \value SslV2 SSLv2. Note, SSLv2 support was removed in OpenSSL 1.1.
\value TlsV1_0 TLSv1.0
\value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1 Obsolete, means the same as TlsV1_0
- \value TlsV1_1 TLSv1.1
+ \value TlsV1_1 TLSv1.1. When using the WinRT backend this option will also enable TLSv1.0.
\value TlsV1_1OrLater TLSv1.1 and later versions. This option is not available when using the WinRT backend due to platform limitations.
- \value TlsV1_2 TLSv1.2
+ \value TlsV1_2 TLSv1.2. When using the WinRT backend this option will also enable TLSv1.0 and TLSv1.1.
\value TlsV1_2OrLater TLSv1.2 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value UnknownProtocol The cipher's protocol cannot be determined.
- \value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1.0. This
- value is used by QSslSocket only.
+ \value AnyProtocol The socket understands SSLv2, SSLv3, TLSv1.0 and all
+ supported later versions of TLS. This value is used by QSslSocket only.
\value TlsV1SslV3 On the client side, this will send
a TLS 1.0 Client Hello, enabling TLSv1_0 and SSLv3 connections.
On the server side, this will enable both SSLv3 and TLSv1_0 connections.
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
index 4c0b59adb7..73a246419f 100644
--- a/src/network/ssl/qsslcertificate_openssl.cpp
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
@@ -225,7 +225,7 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
result.insert(QSsl::EmailEntry, altName);
}
- q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_OPENSSL_sk_free));
+ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_GENERAL_NAME_free));
}
return result;
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index e0c705f97e..1071662d96 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -876,12 +876,12 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame
Returns the backend-specific configuration.
- Only options set by addBackendConfig() or setBackendConfig() will be
+ Only options set by setBackendConfigurationOption() or setBackendConfiguration() will be
returned. The internal standard configuration of the backend is not reported.
- \sa setBackendConfigOption(), setBackendConfig()
+ \sa setBackendConfigurationOption(), setBackendConfiguration()
*/
-QMap<QByteArray, QVariant> QSslConfiguration::backendConfig() const
+QMap<QByteArray, QVariant> QSslConfiguration::backendConfiguration() const
{
return d->backendConfig;
}
@@ -902,9 +902,9 @@ QMap<QByteArray, QVariant> QSslConfiguration::backendConfig() const
configuration. Using the backend-specific configuration to set a general
configuration option again will overwrite the general configuration option.
- \sa backendConfig(), setBackendConfig()
+ \sa backendConfiguration(), setBackendConfiguration()
*/
-void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVariant &value)
+void QSslConfiguration::setBackendConfigurationOption(const QByteArray &name, const QVariant &value)
{
d->backendConfig[name] = value;
}
@@ -914,15 +914,15 @@ void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVa
Sets or clears the backend-specific configuration.
- Without a \a backendConfig parameter this function will clear the
+ Without a \a backendConfiguration parameter this function will clear the
backend-specific configuration. More information about the supported
- options is available in the documentation of addBackendConfig().
+ options is available in the documentation of setBackendConfigurationOption().
- \sa backendConfig(), setBackendConfigOption()
+ \sa backendConfiguration(), setBackendConfigurationOption()
*/
-void QSslConfiguration::setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig)
+void QSslConfiguration::setBackendConfiguration(const QMap<QByteArray, QVariant> &backendConfiguration)
{
- d->backendConfig = backendConfig;
+ d->backendConfig = backendConfiguration;
}
/*!
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index b3264126dd..fe4181d755 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -150,9 +150,9 @@ public:
QSslDiffieHellmanParameters diffieHellmanParameters() const;
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
- QMap<QByteArray, QVariant> backendConfig() const;
- void setBackendConfigOption(const QByteArray &name, const QVariant &value);
- void setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig = QMap<QByteArray, QVariant>());
+ QMap<QByteArray, QVariant> backendConfiguration() const;
+ void setBackendConfigurationOption(const QByteArray &name, const QVariant &value);
+ void setBackendConfiguration(const QMap<QByteArray, QVariant> &backendConfiguration = QMap<QByteArray, QVariant>());
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index 386c280659..41b759364b 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -245,7 +245,7 @@ QString QSslContext::errorString() const
// static
void QSslContext::applyBackendConfig(QSslContext *sslContext)
{
- if (sslContext->sslConfiguration.backendConfig().isEmpty())
+ if (sslContext->sslConfiguration.backendConfiguration().isEmpty())
return;
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
@@ -255,7 +255,7 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext)
q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
- const auto &backendConfig = sslContext->sslConfiguration.backendConfig();
+ const auto &backendConfig = sslContext->sslConfiguration.backendConfiguration();
for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) {
if (!i.value().canConvert(QMetaType::QByteArray)) {
sslContext->errorCode = QSslError::UnspecifiedError;
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
index 7be7be46b8..5c68ed41db 100644
--- a/src/network/ssl/qsslcontext_openssl11.cpp
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -100,6 +100,68 @@ init_context:
return;
}
+ long minVersion = TLS_ANY_VERSION;
+ long maxVersion = TLS_ANY_VERSION;
+ switch (sslContext->sslConfiguration.protocol()) {
+ // The single-protocol versions first:
+ case QSsl::SslV3:
+ minVersion = SSL3_VERSION;
+ maxVersion = SSL3_VERSION;
+ break;
+ case QSsl::TlsV1_0:
+ minVersion = TLS1_VERSION;
+ maxVersion = TLS1_VERSION;
+ break;
+ case QSsl::TlsV1_1:
+ minVersion = TLS1_1_VERSION;
+ maxVersion = TLS1_1_VERSION;
+ break;
+ case QSsl::TlsV1_2:
+ minVersion = TLS1_2_VERSION;
+ maxVersion = TLS1_2_VERSION;
+ break;
+ // Ranges:
+ case QSsl::TlsV1SslV3:
+ case QSsl::AnyProtocol:
+ minVersion = SSL3_VERSION;
+ maxVersion = TLS_MAX_VERSION;
+ break;
+ case QSsl::SecureProtocols:
+ case QSsl::TlsV1_0OrLater:
+ minVersion = TLS1_VERSION;
+ maxVersion = TLS_MAX_VERSION;
+ break;
+ case QSsl::TlsV1_1OrLater:
+ minVersion = TLS1_1_VERSION;
+ maxVersion = TLS_MAX_VERSION;
+ break;
+ case QSsl::TlsV1_2OrLater:
+ minVersion = TLS1_2_VERSION;
+ maxVersion = TLS_MAX_VERSION;
+ break;
+ case QSsl::SslV2:
+ // This protocol is not supported by OpenSSL 1.1 and we handle
+ // it as an error (see the code above).
+ Q_UNREACHABLE();
+ break;
+ case QSsl::UnknownProtocol:
+ break;
+ }
+
+ if (minVersion != TLS_ANY_VERSION
+ && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
+ sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ if (maxVersion != TLS_ANY_VERSION
+ && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
+ sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
// Enable bug workarounds.
long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
q_SSL_CTX_set_options(sslContext->ctx, options);
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 833d676192..4273904c12 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -922,7 +922,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
- d->configuration.backendConfig = configuration.backendConfig();
+ d->configuration.backendConfig = configuration.backendConfiguration();
d->configuration.sslOptions = configuration.d->sslOptions;
d->configuration.sslSession = configuration.sessionTicket();
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
diff --git a/src/network/ssl/qsslsocket_mac_shared.cpp b/src/network/ssl/qsslsocket_mac_shared.cpp
index d239fe23dd..4f0adf16f9 100644
--- a/src/network/ssl/qsslsocket_mac_shared.cpp
+++ b/src/network/ssl/qsslsocket_mac_shared.cpp
@@ -128,10 +128,10 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
QList<QSslCertificate> systemCerts;
// SecTrustSettingsCopyCertificates is not defined on iOS.
#ifdef Q_OS_OSX
- QCFType<CFArrayRef> cfCerts;
// iterate through all enum members, order:
// kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem
for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) {
+ QCFType<CFArrayRef> cfCerts;
OSStatus status = SecTrustSettingsCopyCertificates(SecTrustSettingsDomain(dom), &cfCerts);
if (status == noErr) {
const CFIndex size = CFArrayGetCount(cfCerts);
diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
index 2980b3d23e..ac8d46ce6d 100644
--- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
@@ -129,4 +129,10 @@ const char *q_OpenSSL_version(int type);
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
+#define q_SSL_CTX_set_min_proto_version(ctx, version) \
+ q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
+
+#define q_SSL_CTX_set_max_proto_version(ctx, version) \
+ q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr)
+
#endif
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 9bb67771fd..82ff5e9e3a 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -465,6 +465,7 @@ DEFINEFUNC(int, X509_EXTENSION_get_critical, X509_EXTENSION *a, a, return 0, ret
DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return 0, return)
DEFINEFUNC(void, BASIC_CONSTRAINTS_free, BASIC_CONSTRAINTS *a, a, return, DUMMYARG)
DEFINEFUNC(void, AUTHORITY_KEYID_free, AUTHORITY_KEYID *a, a, return, DUMMYARG)
+DEFINEFUNC(void, GENERAL_NAME_free, GENERAL_NAME *a, a, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0, return)
#else
@@ -1185,6 +1186,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_EXTENSION_get_data)
RESOLVEFUNC(BASIC_CONSTRAINTS_free)
RESOLVEFUNC(AUTHORITY_KEYID_free)
+ RESOLVEFUNC(GENERAL_NAME_free)
RESOLVEFUNC(ASN1_STRING_print)
RESOLVEFUNC(X509_check_issued)
RESOLVEFUNC(X509_get_issuer_name)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index be67f38b64..4fb8f26cf6 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -480,6 +480,9 @@ void q_PKCS12_free(PKCS12 *pkcs12);
#define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
#define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st))
#define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i))
+
+void q_GENERAL_NAME_free(GENERAL_NAME *a);
+
#define q_sk_X509_num(st) q_SKM_sk_num(X509, (st))
#define q_sk_X509_value(st, i) q_SKM_sk_value(X509, (st), (i))
#define q_sk_SSL_CIPHER_num(st) q_SKM_sk_num(SSL_CIPHER, (st))
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index f64ae2e020..53a8a8b61b 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -236,10 +236,9 @@ void QSslSocketBackendPrivate::startClientEncryption()
switch (q->protocol()) {
case QSsl::AnyProtocol:
case QSsl::SslV3:
+ case QSsl::TlsV1SslV3:
protectionLevel = SocketProtectionLevel_Ssl; // Only use this value if weak cipher support is required
break;
- case QSsl::SecureProtocols:
- case QSsl::TlsV1SslV3:
case QSsl::TlsV1_0:
protectionLevel = SocketProtectionLevel_Tls10;
break;
@@ -257,6 +256,11 @@ void QSslSocketBackendPrivate::startClientEncryption()
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QStringLiteral("unsupported protocol"));
return;
+ case QSsl::SecureProtocols:
+ // SocketProtectionLevel_Tls12 actually means "use TLS1.0, 1.1 or 1.2"
+ // https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel
+ protectionLevel = SocketProtectionLevel_Tls12;
+ break;
default:
protectionLevel = SocketProtectionLevel_Tls12; // default to highest
protocol = QSsl::TlsV1_2;
diff --git a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
index de369e0b00..aa7bb102c6 100644
--- a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
+++ b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
@@ -134,6 +134,7 @@ messageDebugEntries[] = {
{WM_XBUTTONUP, "WM_XBUTTONUP", true},
{WM_XBUTTONDBLCLK, "WM_XBUTTONDBLCLK", true},
{WM_MOUSEHWHEEL, "WM_MOUSEHWHEEL", true},
+ {WM_GETOBJECT, "WM_GETOBJECT", true},
{WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true},
{WM_INPUTLANGCHANGE, "WM_INPUTLANGCHANGE", true},
{WM_IME_NOTIFY, "WM_IME_NOTIFY", true},
@@ -162,6 +163,7 @@ messageDebugEntries[] = {
{WM_GETMINMAXINFO, "WM_GETMINMAXINFO", true},
{WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING", true},
{WM_NCCREATE, "WM_NCCREATE", true},
+ {WM_NCDESTROY, "WM_NCDESTROY", true},
{WM_NCCALCSIZE, "WM_NCCALCSIZE", true},
{WM_NCACTIVATE, "WM_NCACTIVATE", true},
{WM_NCMOUSEMOVE, "WM_NCMOUSEMOVE", true},
@@ -180,7 +182,9 @@ messageDebugEntries[] = {
{WM_CHANGECBCHAIN, "WM_CHANGECBCHAIN", true},
{WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE", true},
{WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD", true},
- {WM_THEMECHANGED, "WM_THEMECHANGED", true}
+ {WM_THEMECHANGED, "WM_THEMECHANGED", true},
+ {0x90, "WM_UAHDESTROYWINDOW", true},
+ {0x272, "WM_UNREGISTER_WINDOW_SERVICES", true}
};
static inline const MessageDebugEntry *messageDebugEntry(UINT msg)
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
index add442ebc5..8cd6f269a5 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
@@ -2095,10 +2095,7 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const
if (!cacheEnabled && glyph != &emptyGlyph)
delete glyph;
- if (!img.isNull())
- return img;
-
- return QFontEngine::alphaMapForGlyph(g, subPixelPosition, t);
+ return img;
}
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 5eb5cd8a30..f31f58945b 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -521,6 +521,8 @@ static void addExtraFallbacks(QStringList *fallbackList)
// add Apple Symbols to cover those too.
if (!fallbackList->contains(QStringLiteral("Apple Symbols")))
fallbackList->append(QStringLiteral("Apple Symbols"));
+#else
+ Q_UNUSED(fallbackList)
#endif
}
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
index 78477de38a..299dfd40cd 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
@@ -119,7 +119,7 @@ static FontKeys &fontKeys()
QSettings::NativeFormat);
const QStringList allKeys = fontRegistry.allKeys();
const QString trueType = QStringLiteral("(TrueType)");
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+"));
#else
const QRegExp sizeListMatch(QLatin1String("\\s(\\d+,)+\\d+"));
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 76f42d764d..f339938f86 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -254,6 +254,12 @@ void QIBusPlatformInputContext::setFocusObject(QObject *object)
if (!d->busConnected)
return;
+ // It would seem natural here to call FocusOut() on the input method if we
+ // transition from an IME accepted focus object to one that does not accept it.
+ // Mysteriously however that is not sufficient to fix bug QTBUG-63066.
+ if (!inputMethodAccepted())
+ return;
+
if (debug)
qDebug() << "setFocusObject" << object;
if (object)
@@ -647,7 +653,7 @@ QString QIBusPlatformInputContextPrivate::getSocketPath()
if (pos2 > 0)
displayNumber = display.mid(pos, pos2 - pos);
else
- displayNumber = display.right(pos);
+ displayNumber = display.mid(pos);
if (debug)
qDebug() << "host=" << host << "displayNumber" << displayNumber;
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 8b6dcb35a6..654e6210c8 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -226,7 +226,6 @@ bool shouldBeIgnored(QAccessibleInterface *interface)
const QAccessible::Role role = interface->role();
if (role == QAccessible::Border || // QFrame
role == QAccessible::Application || // We use the system-provided application element.
- role == QAccessible::MenuItem || // The system also provides the menu items.
role == QAccessible::ToolBar || // Access the tool buttons directly.
role == QAccessible::Pane || // Scroll areas.
role == QAccessible::Client) // The default for QWidget.
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 57a03905ab..091453785e 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -163,9 +163,11 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
const qreal devicePixelRatio = m_image.devicePixelRatio();
// If the flushed window is a content view, and not in unified toolbar mode,
- // we can get away with copying the backingstore instead of blending.
- const NSCompositingOperation compositingOperation = static_cast<QCocoaWindow *>(
- window->handle())->isContentView() && !windowHasUnifiedToolbar() ?
+ // and is fully opaque, we can get away with copying the backingstore instead
+ // of blending.
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
+ && cocoaWindow->isOpaque() && !windowHasUnifiedToolbar() ?
NSCompositingOperationCopy : NSCompositingOperationSourceOver;
#ifdef QT_DEBUG
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 7c6f879b18..bad91a2d5d 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -90,7 +90,9 @@ QPalette * qt_mac_createSystemPalette()
palette->setColor(QPalette::Disabled, QPalette::Text, qc);
palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
- palette->setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
+
+ palette->setBrush(QPalette::ToolTipBase, qt_mac_toQBrush([NSColor controlColor]));
+
return palette;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f9c676a5b0..54254455e4 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -503,7 +503,7 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
{
const Qt::WindowType type = static_cast<Qt::WindowType>(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
+ const bool resizeable = !(flags & Qt::CustomizeWindowHint); // Remove zoom button by disabling resize
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 7b7b3f53d5..a88cd5feda 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -487,8 +487,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
NSPoint screenPoint;
if (theEvent) {
NSPoint windowPoint = [theEvent locationInWindow];
- NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
- screenPoint = screenRect.origin;
+ if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) {
+ screenPoint = [NSEvent mouseLocation];
+ } else {
+ NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
+ screenPoint = screenRect.origin;
+ }
} else {
screenPoint = [NSEvent mouseLocation];
}
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
index 1b8f50a1c6..f151713400 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
@@ -140,7 +140,7 @@ QByteArray QEglFSDeviceIntegration::fbDeviceName() const
int QEglFSDeviceIntegration::framebufferIndex() const
{
int fbIndex = 0;
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)"));
QRegularExpressionMatch match = fbIndexRx.match(QString::fromLocal8Bit(fbDeviceName()));
if (match.hasMatch())
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 9cdbed303c..a56c1e4568 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -50,11 +50,10 @@
@implementation QIOSApplicationDelegate
-- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
Q_UNUSED(application);
- Q_UNUSED(sourceApplication);
- Q_UNUSED(annotation);
+ Q_UNUSED(options);
if (!QGuiApplication::instance())
return NO;
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.h b/src/plugins/platforms/ios/qiosapplicationstate.h
index a68147a72a..8a15a4a51b 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.h
+++ b/src/plugins/platforms/ios/qiosapplicationstate.h
@@ -56,8 +56,8 @@ public:
static Qt::ApplicationState toQtApplicationState(UIApplicationState state);
Q_SIGNALS:
- void applicationStateWillChange(Qt::ApplicationState);
- void applicationStateDidChange(Qt::ApplicationState);
+ void applicationStateWillChange(Qt::ApplicationState oldState, Qt::ApplicationState newState);
+ void applicationStateDidChange(Qt::ApplicationState oldState, Qt::ApplicationState newState);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
index 3407aebf8f..6d9bcdacbf 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -87,18 +87,18 @@ QIOSApplicationState::QIOSApplicationState()
void QIOSApplicationState::handleApplicationStateChanged(UIApplicationState uiState, const QString &reason)
{
- Qt::ApplicationState state = toQtApplicationState(uiState);
- qCDebug(lcQpaApplication) << qPrintable(reason)
- << "- moving from" << QGuiApplication::applicationState() << "to" << state;
+ Qt::ApplicationState oldState = QGuiApplication::applicationState();
+ Qt::ApplicationState newState = toQtApplicationState(uiState);
+ qCDebug(lcQpaApplication) << qPrintable(reason) << "- moving from" << oldState << "to" << newState;
if (QIOSIntegration *integration = QIOSIntegration::instance()) {
- emit integration->applicationState.applicationStateWillChange(state);
- QWindowSystemInterface::handleApplicationStateChanged(state);
- emit integration->applicationState.applicationStateDidChange(state);
- qCDebug(lcQpaApplication) << "done moving to" << state;
+ emit integration->applicationState.applicationStateWillChange(oldState, newState);
+ QWindowSystemInterface::handleApplicationStateChanged(newState);
+ emit integration->applicationState.applicationStateDidChange(oldState, newState);
+ qCDebug(lcQpaApplication) << "done moving to" << newState;
} else {
qCDebug(lcQpaApplication) << "no platform integration yet, setting state directly";
- QGuiApplicationPrivate::applicationState = state;
+ QGuiApplicationPrivate::applicationState = newState;
}
}
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index 03643c19a9..fff66049ff 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -301,29 +301,34 @@ bool QIOSContext::verifyGraphicsHardwareAvailability()
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState;
- connect(applicationState, &QIOSApplicationState::applicationStateWillChange, [](Qt::ApplicationState state) {
- if (applicationBackgrounded && state != Qt::ApplicationSuspended) {
- qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled";
- applicationBackgrounded = false;
+ connect(applicationState, &QIOSApplicationState::applicationStateWillChange,
+ [](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
+ Q_UNUSED(oldState);
+ if (applicationBackgrounded && newState != Qt::ApplicationSuspended) {
+ qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled";
+ applicationBackgrounded = true;
+ }
}
- });
- connect(applicationState, &QIOSApplicationState::applicationStateDidChange, [](Qt::ApplicationState state) {
- if (state != Qt::ApplicationSuspended)
- return;
-
- qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled";
- applicationBackgrounded = true;
-
- // By the time we receive this signal the application has moved into
- // Qt::ApplactionStateSuspended, and all windows have been obscured,
- // which should stop all rendering. If there's still an active GL context,
- // we follow Apple's advice and call glFinish before making it inactive.
- if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) {
- qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext;
- glFinish();
- currentContext->doneCurrent();
+ );
+ connect(applicationState, &QIOSApplicationState::applicationStateDidChange,
+ [](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
+ Q_UNUSED(oldState);
+ if (newState != Qt::ApplicationSuspended)
+ return;
+
+ qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled";
+
+ // By the time we receive this signal the application has moved into
+ // Qt::ApplactionStateSuspended, and all windows have been obscured,
+ // which should stop all rendering. If there's still an active GL context,
+ // we follow Apple's advice and call glFinish before making it inactive.
+ if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) {
+ qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext;
+ glFinish();
+ currentContext->doneCurrent();
+ }
}
- });
+ );
});
if (applicationBackgrounded) {
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 6be8855020..818250fcee 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -62,6 +62,8 @@ public:
QIOSIntegration();
~QIOSIntegration();
+ void initialize() override;
+
bool hasCapability(Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 92c1e39d72..2e657b3798 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -95,7 +95,10 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
+}
+void QIOSIntegration::initialize()
+{
UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:mainScreen]) {
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index a7663b9e94..d7db6ba856 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -273,6 +273,20 @@
m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties];
});
+
+ QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState;
+ QObject::connect(applicationState, &QIOSApplicationState::applicationStateDidChange,
+ [self](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
+ if (oldState == Qt::ApplicationSuspended && newState != Qt::ApplicationSuspended) {
+ // We may have ignored an earlier layout because the application was suspended,
+ // and we didn't want to render anything at that moment in fear of being killed
+ // due to rendering in the background, so we trigger an explicit layout when
+ // coming out of the suspended state.
+ qCDebug(lcQpaWindow) << "triggering root VC layout when coming out of suspended state";
+ [self.view setNeedsLayout];
+ }
+ }
+ );
}
return self;
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 584dfe9b41..29afae7176 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -439,7 +439,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
}
if (m_activeTouches.isEmpty())
return;
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
+
if (!static_cast<QUIWindow *>(self.window).sendingEvent) {
// The event is likely delivered as part of delayed touch delivery, via
// _UIGestureEnvironmentSortAndSendDelayedTouches, due to one of the two
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 38b61fd782..4a547aa158 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -63,6 +63,18 @@
QT_BEGIN_NAMESPACE
+#define DECLARE_DEBUG_VAR(variable) \
+ static bool debug_ ## variable() \
+ { static bool value = qgetenv("QNX_SCREEN_DEBUG").contains(QT_STRINGIFY(variable)); return value; }
+DECLARE_DEBUG_VAR(fps)
+DECLARE_DEBUG_VAR(posts)
+DECLARE_DEBUG_VAR(blits)
+DECLARE_DEBUG_VAR(updates)
+DECLARE_DEBUG_VAR(cpu_time)
+DECLARE_DEBUG_VAR(gpu_time)
+DECLARE_DEBUG_VAR(statistics)
+#undef DECLARE_DEBUG_VAR
+
/*!
\class QQnxWindow
\brief The QQnxWindow is the base class of the various classes used as instances of
@@ -211,6 +223,35 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
// it'll cause us not to join a group (the app will presumably join at some future time).
if (windowGroup.isValid() && windowGroup.canConvert<QByteArray>())
joinWindowGroup(windowGroup.toByteArray());
+
+ int debug = 0;
+ if (Q_UNLIKELY(debug_fps())) {
+ debug |= SCREEN_DEBUG_GRAPH_FPS;
+ }
+ if (Q_UNLIKELY(debug_posts())) {
+ debug |= SCREEN_DEBUG_GRAPH_POSTS;
+ }
+ if (Q_UNLIKELY(debug_blits())) {
+ debug |= SCREEN_DEBUG_GRAPH_BLITS;
+ }
+ if (Q_UNLIKELY(debug_updates())) {
+ debug |= SCREEN_DEBUG_GRAPH_UPDATES;
+ }
+ if (Q_UNLIKELY(debug_cpu_time())) {
+ debug |= SCREEN_DEBUG_GRAPH_CPU_TIME;
+ }
+ if (Q_UNLIKELY(debug_gpu_time())) {
+ debug |= SCREEN_DEBUG_GRAPH_GPU_TIME;
+ }
+ if (Q_UNLIKELY(debug_statistics())) {
+ debug = SCREEN_DEBUG_STATISTICS;
+ }
+
+ if (debug > 0) {
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_DEBUG, &debug),
+ "Could not set SCREEN_PROPERTY_DEBUG");
+ qWindowDebug() << "window SCREEN_PROPERTY_DEBUG= " << debug;
+ }
}
QQnxWindow::~QQnxWindow()
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index ac6a34d7c2..5976fd23c0 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -43,7 +43,7 @@
#include <QtCore/QOperatingSystemVersion>
#include <QtCore/private/qsystemlibrary_p.h>
-#if defined(Q_CC_MINGW)
+#if defined(Q_CC_MINGW) || defined(Q_CC_CLANG)
# define HAS_UI_VIEW_SETTINGS_INTEROP
// Present from MSVC2015 + SDK 10 onwards
#elif (!defined(Q_CC_MSVC) || _MSC_VER >= 1900) && NTDDI_VERSION >= 0xa000000
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 3d0dbd7b1a..072012064f 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -1083,7 +1083,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::LeaveEvent:
{
QWindow *window = platformWindow->window();
- while (window->flags() & Qt::WindowTransparentForInput)
+ while (window && (window->flags() & Qt::WindowTransparentForInput))
window = window->parent();
if (!window)
return false;
@@ -1364,9 +1364,10 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result, &platformWindow);
if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) {
- qCDebug(lcQpaEvents) << "EVENT: hwd=" << hwnd << eventName << hex << "msg=0x" << message
- << "et=0x" << et << dec << "wp=" << int(wParam) << "at"
- << GET_X_LPARAM(lParam) << GET_Y_LPARAM(lParam) << "handled=" << handled;
+ qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName
+ << " msg=0x" << hex << message << " et=0x" << et << dec << " wp="
+ << int(wParam) << " at " << GET_X_LPARAM(lParam) << ','
+ << GET_Y_LPARAM(lParam) << " handled=" << handled;
}
}
if (!handled)
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 4772f3fce5..53f185358b 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -107,6 +107,7 @@ public:
void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
void setOverrideCursor(const QCursor &cursor) override;
void clearOverrideCursor() override;
+ bool hasOverrideCursor() const { return m_overriddenCursor != nullptr; }
QPoint pos() const override;
void setPos(const QPoint &pos) override;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 4bdf3167e4..e9c52e2c02 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -391,6 +391,15 @@ static PIXELFORMATDESCRIPTOR
pfd.dwFlags |= PFD_DOUBLEBUFFER;
pfd.cDepthBits =
format.depthBufferSize() >= 0 ? format.depthBufferSize() : 32;
+ const int redBufferSize = format.redBufferSize();
+ if (redBufferSize != -1)
+ pfd.cRedBits = BYTE(redBufferSize);
+ const int greenBufferSize = format.greenBufferSize();
+ if (greenBufferSize != -1)
+ pfd.cGreenBits = BYTE(greenBufferSize);
+ const int blueBufferSize = format.blueBufferSize();
+ if (blueBufferSize != -1)
+ pfd.cBlueBits = BYTE(blueBufferSize);
pfd.cAlphaBits = format.alphaBufferSize() > 0 ? format.alphaBufferSize() : 8;
pfd.cStencilBits = format.stencilBufferSize() > 0 ? format.stencilBufferSize() : 8;
if (additional.formatFlags & QWindowsGLAccumBuffer)
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 66d3b140e2..d56dc870ea 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -396,9 +396,6 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
*/
QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTypeHint() const
{
-#if !defined(FT_LCD_FILTER_H) || !defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
- return QPlatformScreen::Subpixel_None;
-#else
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
if (type == QPlatformScreen::Subpixel_None) {
QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Avalon.Graphics\\DISPLAY1"), QSettings::NativeFormat);
@@ -419,7 +416,6 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
}
}
return type;
-#endif
}
/*!
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 78e33e57ab..280519d39d 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -111,6 +111,61 @@ inline QPointF QWindowsTabletDeviceData::scaleCoordinates(int coordX, int coordY
return QPointF(x, y);
}
+template <class Stream>
+static void formatOptions(Stream &str, unsigned options)
+{
+ if (options & CXO_SYSTEM)
+ str << " CXO_SYSTEM";
+ if (options & CXO_PEN)
+ str << " CXO_PEN";
+ if (options & CXO_MESSAGES)
+ str << " CXO_MESSAGES";
+ if (options & CXO_MARGIN)
+ str << " CXO_MARGIN";
+ if (options & CXO_MGNINSIDE)
+ str << " CXO_MGNINSIDE";
+ if (options & CXO_CSRMESSAGES)
+ str << " CXO_CSRMESSAGES";
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
+ << ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
+ << t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ
+ << ".." << t.maxX << t.maxY << t.maxZ << " device " << t.currentDevice
+ << " pointer " << t.currentPointerType;
+ return d;
+}
+
+QDebug operator<<(QDebug d, const LOGCONTEXT &lc)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "LOGCONTEXT(\"" << QString::fromWCharArray(lc.lcName) << "\", options=0x"
+ << hex << lc.lcOptions << dec;
+ formatOptions(d, lc.lcOptions);
+ d << ", status=0x" << hex << lc.lcStatus << ", device=0x" << lc.lcDevice
+ << dec << ", PktRate=" << lc.lcPktRate
+ << ", PktData=" << lc.lcPktData << ", PktMode=" << lc.lcPktMode
+ << ", MoveMask=0x" << hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask
+ << ", BtnUpMask=0x" << lc.lcBtnUpMask << dec << ", SysMode=" << lc.lcSysMode
+ << ", InOrg=(" << lc.lcInOrgX << ", " << lc.lcInOrgY << ", " << lc.lcInOrgZ
+ << "), InExt=(" << lc.lcInExtX << ", " << lc.lcInExtY << ", " << lc.lcInExtZ
+ << ") OutOrg=(" << lc.lcOutOrgX << ", " << lc.lcOutOrgY << ", "
+ << lc.lcOutOrgZ << "), OutExt=(" << lc.lcOutExtX << ", " << lc.lcOutExtY
+ << ", " << lc.lcOutExtZ
+ << "), Sens=(" << lc.lcSensX << ", " << lc.lcSensX << ", " << lc.lcSensZ
+ << ") SysOrg=(" << lc.lcSysOrgX << ", " << lc.lcSysOrgY
+ << "), SysExt=(" << lc.lcSysExtX << ", " << lc.lcSysExtY
+ << "), SysSens=(" << lc.lcSysSensX << ", " << lc.lcSysSensY << "))";
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL;
/*!
@@ -186,6 +241,7 @@ QWindowsTabletSupport *QWindowsTabletSupport::create()
LOGCONTEXT lcMine;
// build our context from the default context
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEFSYSCTX, 0, &lcMine);
+ qCDebug(lcQpaTablet) << "Default: " << lcMine;
// Go for the raw coordinates, the tablet event will return good stuff
lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
lcMine.lcPktData = lcMine.lcMoveMask = PACKETDATA;
@@ -194,6 +250,7 @@ QWindowsTabletSupport *QWindowsTabletSupport::create()
lcMine.lcOutExtX = lcMine.lcInExtX;
lcMine.lcOutOrgY = 0;
lcMine.lcOutExtY = -lcMine.lcInExtY;
+ qCDebug(lcQpaTablet) << "Requesting: " << lcMine;
const HCTX context = QWindowsTabletSupport::m_winTab32DLL.wTOpen(window, &lcMine, true);
if (!context) {
qCDebug(lcQpaTablet) << __FUNCTION__ << "Unable to open tablet.";
@@ -215,7 +272,7 @@ QWindowsTabletSupport *QWindowsTabletSupport::create()
} // mismatch
qCDebug(lcQpaTablet) << "Opened tablet context " << context << " on window "
<< window << "changed packet queue size " << currentQueueSize
- << "->" << TabletPacketQSize;
+ << "->" << TabletPacketQSize << "\nobtained: " << lcMine;
return new QWindowsTabletSupport(window, context);
}
@@ -238,17 +295,23 @@ QString QWindowsTabletSupport::description() const
WORD specificationVersion = 0;
m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specificationVersion);
const unsigned opts = options();
- QString result = QString::fromLatin1("%1 specification: v%2.%3 implementation: v%4.%5 options: 0x%6")
- .arg(QString::fromWCharArray(winTabId.data()))
- .arg(specificationVersion >> 8).arg(specificationVersion & 0xFF)
- .arg(implementationVersion >> 8).arg(implementationVersion & 0xFF)
- .arg(opts, 0, 16);
- if (opts & CXO_MESSAGES)
- result += QLatin1String(" CXO_MESSAGES");
- if (opts & CXO_CSRMESSAGES)
- result += QLatin1String(" CXO_CSRMESSAGES");
+ WORD devices = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_NDEVICES, &devices);
+ WORD cursors = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_NCURSORS, &cursors);
+ WORD extensions = 0;
+ m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_NEXTENSIONS, &extensions);
+ QString result;
+ QTextStream str(&result);
+ str << '"' << QString::fromWCharArray(winTabId.data())
+ << "\" specification: v" << (specificationVersion >> 8)
+ << '.' << (specificationVersion & 0xFF) << " implementation: v"
+ << (implementationVersion >> 8) << '.' << (implementationVersion & 0xFF)
+ << ' ' << devices << " device(s), " << cursors << " cursor(s), "
+ << extensions << " extensions" << ", options: 0x" << hex << opts << dec;
+ formatOptions(str, opts);
if (m_tiltSupport)
- result += QLatin1String(" tilt");
+ str << " tilt";
return result;
}
@@ -306,20 +369,6 @@ static inline QTabletEvent::PointerType pointerType(unsigned currentCursor)
return QTabletEvent::UnknownPointer;
}
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
- << ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
- << t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ
- << ".." << t.maxX << t.maxY << t.maxZ << " device " << t.currentDevice
- << " pointer " << t.currentPointerType;
- return d;
-}
-#endif // !QT_NO_DEBUG_STREAM
-
QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(qint64 uniqueId, UINT cursorType) const
{
QWindowsTabletDeviceData result;
@@ -357,6 +406,7 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
if (m_currentDevice < 0 || m_currentDevice >= m_devices.size()) // QTBUG-65120, spurious leave observed
return false;
+ m_state = PenUp;
if (totalPacks > 0) {
QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
m_devices.at(m_currentDevice).currentDevice,
@@ -389,6 +439,7 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_devices.push_back(tabletInit(uniqueId, cursorType));
}
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
+ m_state = PenProximity;
qCDebug(lcQpaTablet) << "enter proximity for device #"
<< m_currentDevice << m_devices.at(m_currentDevice);
QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
@@ -409,7 +460,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
const int currentPointer = m_devices.at(m_currentDevice).currentPointerType;
const qint64 uniqueId = m_devices.at(m_currentDevice).uniqueId;
- // The tablet can be used in 2 different modes, depending on it settings:
+ // The tablet can be used in 2 different modes (reflected in enum Mode),
+ // depending on its settings:
// 1) Absolute (pen) mode:
// The coordinates are scaled to the virtual desktop (by default). The user
// can also choose to scale to the monitor or a region of the screen.
@@ -424,8 +476,11 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
const QRect virtualDesktopArea =
QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle());
- qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount
- << "target:" << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target;
+ if (QWindowsContext::verbose > 1) {
+ qCDebug(lcQpaTablet) << __FUNCTION__ << "processing" << packetCount
+ << "mode=" << m_mode << "target:"
+ << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target;
+ }
const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
@@ -436,20 +491,24 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
// This code is to delay the tablet data one cycle to sync with the mouse location.
QPointF globalPosF = m_oldGlobalPosF;
- m_oldGlobalPosF = m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
+ const QPointF currentGlobalPosF =
+ m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea);
+ m_oldGlobalPosF = currentGlobalPosF;
QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it.
- QPoint globalPos = globalPosF.toPoint();
// Get Mouse Position and compare to tablet info
const QPoint mouseLocation = QWindowsCursor::mousePosition();
-
- // Positions should be almost the same if we are in absolute
- // mode. If they are not, use the mouse location.
- if ((mouseLocation - globalPos).manhattanLength() > m_absoluteRange) {
- globalPos = mouseLocation;
- globalPosF = globalPos;
+ if (m_state == PenProximity) {
+ m_state = PenDown;
+ m_mode = (mouseLocation - currentGlobalPosF).manhattanLength() > m_absoluteRange
+ ? MouseMode : PenMode;
+ qCDebug(lcQpaTablet) << __FUNCTION__ << "mode=" << m_mode << "pen:"
+ << currentGlobalPosF << "mouse:" << mouseLocation;
}
+ if (m_mode == MouseMode)
+ globalPosF = mouseLocation;
+ const QPoint globalPos = globalPosF.toPoint();
if (!target)
target = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index 7878e962e1..340818c3f7 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -112,6 +112,19 @@ class QWindowsTabletSupport
explicit QWindowsTabletSupport(HWND window, HCTX context);
public:
+ enum Mode
+ {
+ PenMode,
+ MouseMode
+ };
+
+ enum State
+ {
+ PenUp,
+ PenProximity,
+ PenDown
+ };
+
~QWindowsTabletSupport();
static QWindowsTabletSupport *create();
@@ -137,6 +150,8 @@ private:
QVector<QWindowsTabletDeviceData> m_devices;
int m_currentDevice;
QPointF m_oldGlobalPosF;
+ Mode m_mode = PenMode;
+ State m_state = PenUp;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 159e1250d0..f1762146ec 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1077,6 +1077,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
*/
const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
+const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
QWindowsBaseWindow(aWindow),
@@ -1106,7 +1107,6 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
updateDropSite(window()->isTopLevel());
registerTouchWindow();
- setWindowState(aWindow->windowStates());
const qreal opacity = qt_window_private(aWindow)->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
@@ -1115,6 +1115,8 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
if (aWindow->isTopLevel())
setWindowIcon(aWindow->icon());
+ if (aWindow->property(hasBorderInFullScreenProperty).toBool())
+ setFlag(HasBorderInFullScreen);
clearFlag(WithinCreate);
}
@@ -1133,9 +1135,11 @@ void QWindowsWindow::initialize()
QWindowCreationContextPtr creationContext =
QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr());
+ QWindow *w = window();
+ setWindowState(w->windowStates());
+
// Trigger geometry change (unless it has a special state in which case setWindowState()
// will send the message) and screen change signals of QWindow.
- QWindow *w = window();
if (w->type() != Qt::Desktop) {
const Qt::WindowState state = w->windowState();
if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
@@ -1157,23 +1161,19 @@ void QWindowsWindow::fireExpose(const QRegion &region, bool force)
QWindowSystemInterface::handleExposeEvent(window(), region);
}
-static inline QWindow *findTransientChild(const QWindow *parent)
-{
- foreach (QWindow *w, QGuiApplication::topLevelWindows())
- if (w->transientParent() == parent)
- return w;
- return 0;
-}
-
void QWindowsWindow::destroyWindow()
{
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd;
if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
setFlag(WithinDestroy);
// Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666)
- if (QWindow *transientChild = findTransientChild(window()))
- if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(transientChild))
- tw->updateTransientParent();
+ const auto tlw = QGuiApplication::topLevelWindows();
+ for (QWindow *w : tlw) {
+ if (w->transientParent() == window()) {
+ if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(w))
+ tw->updateTransientParent();
+ }
+ }
QWindowsContext *context = QWindowsContext::instance();
if (context->windowUnderMouse() == window())
context->clearWindowUnderMouse();
@@ -2410,6 +2410,8 @@ static inline bool applyNewCursor(const QWindow *w)
void QWindowsWindow::applyCursor()
{
+ if (static_cast<const QWindowsCursor *>(screen()->cursor())->hasOverrideCursor())
+ return;
#ifndef QT_NO_CURSOR
if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
@@ -2662,15 +2664,26 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border
if (QPlatformWindow *handle = window->handle())
static_cast<QWindowsWindow *>(handle)->setHasBorderInFullScreen(border);
else
- qWarning("%s invoked without window handle; call has no effect.", Q_FUNC_INFO);
+ window->setProperty(hasBorderInFullScreenProperty, QVariant(border));
}
void QWindowsWindow::setHasBorderInFullScreen(bool border)
{
+ if (testFlag(HasBorderInFullScreen) == border)
+ return;
if (border)
setFlag(HasBorderInFullScreen);
else
clearFlag(HasBorderInFullScreen);
+ // Directly apply the flag in case we are fullscreen.
+ if (m_windowState == Qt::WindowFullScreen) {
+ LONG_PTR style = GetWindowLongPtr(handle(), GWL_STYLE);
+ if (border)
+ style |= WS_BORDER;
+ else
+ style &= ~WS_BORDER;
+ SetWindowLongPtr(handle(), GWL_STYLE, style);
+ }
}
QString QWindowsWindow::formatWindowTitle(const QString &title)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 8d29b871bf..fe2518e329 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -340,6 +340,7 @@ public:
static QString formatWindowTitle(const QString &title);
static const char *embeddedNativeParentHandleProperty;
+ static const char *hasBorderInFullScreenProperty;
private:
inline void show_sys() const;
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
index 8a250c516a..eeb79be2e6 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
@@ -354,6 +354,12 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const char *procName)
return eglGetProcAddress(procName);
}
+bool QWinRTEGLContext::isValid() const
+{
+ Q_D(const QWinRTEGLContext);
+ return d->eglContext != EGL_NO_CONTEXT;
+}
+
EGLDisplay QWinRTEGLContext::display()
{
return g->eglDisplay;
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h
index 5c75aa90d0..325dc82c40 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.h
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.h
@@ -60,6 +60,7 @@ public:
QSurfaceFormat format() const override;
QFunctionPointer getProcAddress(const char *procName) override;
+ bool isValid() const override;
static EGLDisplay display();
private:
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 21024385b0..cc982b3379 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -86,6 +86,30 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
+#ifndef GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#endif
+
+#ifndef GL_RESET_NOTIFICATION_STRATEGY_ARB
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#endif
+
+#ifndef GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#endif
+
+#ifndef GL_LOSE_CONTEXT_ON_RESET_ARB
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#endif
+
+#ifndef GLX_LOSE_CONTEXT_ON_RESET_ARB
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#endif
+
+#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
+#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7
+#endif
+
static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
{
Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
@@ -141,6 +165,11 @@ static void updateFormatFromContext(QSurfaceFormat &format)
format.setOption(QSurfaceFormat::StereoBuffers);
if (format.renderableType() == QSurfaceFormat::OpenGL) {
+ GLint value = 0;
+ glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &value);
+ if (value == GL_LOSE_CONTEXT_ON_RESET_ARB)
+ format.setOption(QSurfaceFormat::ResetNotification);
+
if (format.version() < qMakePair(3, 0)) {
format.setOption(QSurfaceFormat::DeprecatedFunctions);
return;
@@ -148,7 +177,7 @@ static void updateFormatFromContext(QSurfaceFormat &format)
// Version 3.0 onwards - check if it includes deprecated functionality or is
// a debug context
- GLint value = 0;
+ value = 0;
glGetIntegerv(GL_CONTEXT_FLAGS, &value);
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
format.setOption(QSurfaceFormat::DeprecatedFunctions);
@@ -179,6 +208,8 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_isPBufferCurrent(false)
, m_swapInterval(-1)
, m_ownsContext(nativeHandle.isNull())
+ , m_getGraphicsResetStatus(0)
+ , m_lost(false)
{
if (nativeHandle.isNull())
init(screen, share);
@@ -214,6 +245,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
+ const bool supportsRobustness = glxExt.contains("GLX_ARB_create_context_robustness");
+ const bool supportsVideoMemoryPurge = glxExt.contains("GLX_NV_robustness_video_memory_purge");
// Use glXCreateContextAttribsARB if available
// Also, GL ES context creation requires GLX_EXT_create_context_es2_profile
@@ -266,6 +299,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
int flags = 0;
+ if (supportsRobustness)
+ flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+
if (m_format.testOption(QSurfaceFormat::DebugContext))
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
@@ -279,14 +315,30 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
}
- contextAttributes << None;
+ if (supportsRobustness && m_format.testOption(QSurfaceFormat::ResetNotification)) {
+ QVector<int> contextAttributesWithRobustness = contextAttributes;
+ contextAttributesWithRobustness << GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB << GLX_LOSE_CONTEXT_ON_RESET_ARB;
+ if (supportsVideoMemoryPurge)
+ contextAttributesWithRobustness << GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV << GL_TRUE;
+
+ contextAttributesWithRobustness << None;
+ m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true,
+ contextAttributesWithRobustness.data());
+ // Context creation against a shared context may fail specifically due to this request, so try
+ // without before dropping sharing.
+ }
- m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data());
- if (!m_context && m_shareContext) {
- // re-try without a shared glx context
- m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data());
- if (m_context)
- m_shareContext = 0;
+ if (m_context) {
+ m_getGraphicsResetStatus = reinterpret_cast<GLenum (QOPENGLF_APIENTRYP)()>(getProcAddress("glGetGraphicsResetStatusARB"));
+ } else {
+ contextAttributes << None;
+ m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data());
+ if (!m_context && m_shareContext) {
+ // re-try without a shared glx context
+ m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data());
+ if (m_context)
+ m_shareContext = 0;
+ }
}
}
}
@@ -494,11 +546,23 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
QXcbWindow *window = static_cast<QXcbWindow *>(surface);
glxDrawable = window->xcb_window();
success = glXMakeCurrent(m_display, glxDrawable, m_context);
+ m_lost = false;
+ if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
+ m_lost = true;
+ success = false;
+ // Drop the surface. Will recreate on the next makeCurrent.
+ window->invalidateSurface();
+ }
} else if (surfaceClass == QSurface::Offscreen) {
m_isPBufferCurrent = true;
QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
glxDrawable = pbuffer->pbuffer();
success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context);
+ m_lost = false;
+ if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
+ m_lost = true;
+ success = false;
+ }
}
if (success && surfaceClass == QSurface::Window) {
@@ -585,6 +649,8 @@ QFunctionPointer QGLXContext::getProcAddress(const char *procName)
extern const QString qt_gl_library_name();
// QLibrary lib(qt_gl_library_name());
QLibrary lib(QLatin1String("GL"));
+ if (!lib.load())
+ lib.setFileNameAndVersion(QLatin1String("GL"), 1);
glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
#endif
}
@@ -609,7 +675,7 @@ bool QGLXContext::isSharing() const
bool QGLXContext::isValid() const
{
- return m_context != 0;
+ return m_context != 0 && !m_lost;
}
bool QGLXContext::m_queriedDummyContext = false;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
index f6372582db..be9d3f5dcb 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
@@ -89,6 +89,8 @@ private:
bool m_isPBufferCurrent;
int m_swapInterval;
bool m_ownsContext;
+ GLenum (APIENTRY * m_getGraphicsResetStatus)();
+ bool m_lost;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 6ae52d9fd3..8cfcc49f9a 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -70,11 +70,15 @@
QT_BEGIN_NAMESPACE
-class QXcbShmImage : public QXcbObject
+class QXcbBackingStore;
+
+class QXcbBackingStoreImage : public QXcbObject
{
public:
- QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format);
- ~QXcbShmImage() { destroy(); }
+ QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size);
+ ~QXcbBackingStoreImage() { destroy(true); }
+
+ void resize(const QSize &size);
void flushScrolledRegion(bool clientSideScroll);
@@ -95,7 +99,8 @@ private:
void createShmSegment(size_t segmentSize);
void destroyShmSegment(size_t segmentSize);
- void destroy();
+ void create(const QSize &size, const xcb_format_t *fmt, QImage::Format format);
+ void destroy(bool destroyShm);
void ensureGC(xcb_drawable_t dst);
void shmPutImage(xcb_drawable_t drawable, const QRegion &region, const QPoint &offset = QPoint());
@@ -103,21 +108,23 @@ private:
void setClip(const QRegion &region);
xcb_shm_segment_info_t m_shm_info;
+ QXcbBackingStore *m_backingStore = nullptr;
+ size_t m_segmentSize = 0;
- xcb_image_t *m_xcb_image;
+ xcb_image_t *m_xcb_image = nullptr;
QImage m_qimage;
- QPlatformGraphicsBuffer *m_graphics_buffer;
+ QPlatformGraphicsBuffer *m_graphics_buffer = nullptr;
- xcb_gcontext_t m_gc;
- xcb_drawable_t m_gc_drawable;
+ xcb_gcontext_t m_gc = 0;
+ xcb_drawable_t m_gc_drawable = 0;
// When using shared memory these variables are used only for server-side scrolling.
// When not using shared memory, we maintain a server-side pixmap with the backing
// store as well as repainted content not yet flushed to the pixmap. We only flush
// the regions we need and only when these are marked dirty. This way we can just
// do a server-side copy on expose instead of sending the pixels every time
- xcb_pixmap_t m_xcb_pixmap;
+ xcb_pixmap_t m_xcb_pixmap = 0;
QRegion m_pendingFlush;
// This is the scrolled region which is stored in server-side pixmap
@@ -130,16 +137,15 @@ private:
// as a pixmap region to server
QByteArray m_flushBuffer;
- bool m_hasAlpha;
- bool m_clientSideScroll;
+ bool m_hasAlpha = false;
+ bool m_clientSideScroll = false;
};
-class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer
+class QXcbGraphicsBuffer : public QPlatformGraphicsBuffer
{
public:
- QXcbShmGraphicsBuffer(QImage *image)
+ QXcbGraphicsBuffer(QImage *image)
: QPlatformGraphicsBuffer(image->size(), QImage::toPixelFormat(image->format()))
- , m_access_lock(QPlatformGraphicsBuffer::None)
, m_image(image)
{ }
@@ -159,9 +165,10 @@ public:
int bytesPerLine() const override { return m_image->bytesPerLine(); }
Origin origin() const override { return QPlatformGraphicsBuffer::OriginTopLeft; }
+
private:
- AccessTypes m_access_lock;
- QImage *m_image;
+ AccessTypes m_access_lock = QPlatformGraphicsBuffer::None;
+ QImage *m_image = nullptr;
};
static inline size_t imageDataSize(const xcb_image_t *image)
@@ -169,17 +176,37 @@ static inline size_t imageDataSize(const xcb_image_t *image)
return static_cast<size_t>(image->stride) * image->height;
}
-QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format)
- : QXcbObject(screen->connection())
- , m_graphics_buffer(nullptr)
- , m_gc(0)
- , m_gc_drawable(0)
- , m_xcb_pixmap(0)
- , m_clientSideScroll(false)
+QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size)
+ : QXcbObject(backingStore->connection())
+ , m_backingStore(backingStore)
{
- const xcb_format_t *fmt = connection()->formatForDepth(depth);
+ QXcbWindow *window = static_cast<QXcbWindow *>(backingStore->window()->handle());
+ const xcb_format_t *fmt = connection()->formatForDepth(window->depth());
Q_ASSERT(fmt);
+ memset(&m_shm_info, 0, sizeof m_shm_info);
+
+ QImage::Format format = window->imageFormat();
+ m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha;
+ if (!m_hasAlpha)
+ create(size, fmt, qt_maybeAlphaVersionWithSameDepth(format));
+ else
+ create(size, fmt, format);
+}
+
+void QXcbBackingStoreImage::resize(const QSize &size)
+{
+ xcb_format_t fmt;
+ fmt.depth = m_xcb_image->depth;
+ fmt.bits_per_pixel = m_xcb_image->bpp;
+ fmt.scanline_pad = m_xcb_image->scanline_pad;
+ memset(fmt.pad0, 0, sizeof(fmt.pad0));
+ destroy(false);
+ create(size, &fmt, m_qimage.format());
+}
+
+void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, QImage::Format format)
+{
m_xcb_image = xcb_image_create(size.width(), size.height(),
XCB_IMAGE_FORMAT_Z_PIXMAP,
fmt->scanline_pad,
@@ -192,26 +219,57 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
if (!segmentSize)
return;
- createShmSegment(segmentSize);
+ if (connection()->hasShm()) {
+ if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
+ destroyShmSegment(m_segmentSize);
+ if (!m_shm_info.shmaddr) {
+ qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for"
+ << size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel;
+ createShmSegment(segmentSize);
+ }
+ }
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)
- format = qt_maybeAlphaVersionWithSameDepth(format);
-
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
- m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage);
+ m_graphics_buffer = new QXcbGraphicsBuffer(&m_qimage);
m_xcb_pixmap = xcb_generate_id(xcb_connection());
+ auto xcbScreen = static_cast<QXcbScreen *>(m_backingStore->window()->screen()->handle());
xcb_create_pixmap(xcb_connection(),
m_xcb_image->depth,
m_xcb_pixmap,
- screen->screen()->root,
+ xcbScreen->root(),
m_xcb_image->width, m_xcb_image->height);
}
-void QXcbShmImage::flushScrolledRegion(bool clientSideScroll)
+void QXcbBackingStoreImage::destroy(bool destroyShm)
+{
+ if (m_xcb_image->data) {
+ if (m_shm_info.shmaddr) {
+ if (destroyShm)
+ destroyShmSegment(m_segmentSize);
+ } else {
+ free(m_xcb_image->data);
+ }
+ }
+
+ xcb_image_destroy(m_xcb_image);
+
+ if (m_gc) {
+ xcb_free_gc(xcb_connection(), m_gc);
+ m_gc = 0;
+ }
+ m_gc_drawable = 0;
+
+ delete m_graphics_buffer;
+ m_graphics_buffer = nullptr;
+
+ xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
+ m_xcb_pixmap = 0;
+}
+
+void QXcbBackingStoreImage::flushScrolledRegion(bool clientSideScroll)
{
if (m_clientSideScroll == clientSideScroll)
return;
@@ -259,12 +317,10 @@ void QXcbShmImage::flushScrolledRegion(bool clientSideScroll)
}
}
-void QXcbShmImage::createShmSegment(size_t segmentSize)
+void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
{
- m_shm_info.shmaddr = nullptr;
-
- if (!connection()->hasShm())
- return;
+ Q_ASSERT(connection()->hasShm());
+ Q_ASSERT(m_segmentSize == 0);
#ifdef XCB_USE_SHM_FD
if (connection()->hasShmFd()) {
@@ -302,6 +358,8 @@ void QXcbShmImage::createShmSegment(size_t segmentSize)
close(fds[0]);
m_shm_info.shmseg = seg;
m_shm_info.shmaddr = static_cast<quint8 *>(addr);
+
+ m_segmentSize = segmentSize;
} else
#endif
{
@@ -338,10 +396,12 @@ void QXcbShmImage::createShmSegment(size_t segmentSize)
m_shm_info.shmseg = seg;
m_shm_info.shmid = id; // unused
m_shm_info.shmaddr = static_cast<quint8 *>(addr);
+
+ m_segmentSize = segmentSize;
}
}
-void QXcbShmImage::destroyShmSegment(size_t segmentSize)
+void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize)
{
#ifndef XCB_USE_SHM_FD
Q_UNUSED(segmentSize)
@@ -350,6 +410,7 @@ void QXcbShmImage::destroyShmSegment(size_t segmentSize)
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
if (error)
connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error);
+ m_shm_info.shmseg = 0;
#ifdef XCB_USE_SHM_FD
if (connection()->hasShmFd()) {
@@ -364,12 +425,16 @@ void QXcbShmImage::destroyShmSegment(size_t segmentSize)
qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p",
errno, strerror(errno), m_shm_info.shmaddr);
}
+ m_shm_info.shmid = 0; // unused
}
+ m_shm_info.shmaddr = nullptr;
+
+ m_segmentSize = 0;
}
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
-bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
+bool QXcbBackingStoreImage::scroll(const QRegion &area, int dx, int dy)
{
const QRect bounds(QPoint(), size());
const QRegion scrollArea(area & bounds);
@@ -413,27 +478,7 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
return true;
}
-void QXcbShmImage::destroy()
-{
- 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);
-
- if (m_gc)
- xcb_free_gc(xcb_connection(), m_gc);
- delete m_graphics_buffer;
- m_graphics_buffer = nullptr;
-
- xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
- m_xcb_pixmap = 0;
-}
-
-void QXcbShmImage::ensureGC(xcb_drawable_t dst)
+void QXcbBackingStoreImage::ensureGC(xcb_drawable_t dst)
{
if (m_gc_drawable != dst) {
if (m_gc)
@@ -513,7 +558,7 @@ static inline quint32 round_up_scanline(quint32 base, quint32 pad)
return (base + pad - 1) & -pad;
}
-void QXcbShmImage::shmPutImage(xcb_drawable_t drawable, const QRegion &region, const QPoint &offset)
+void QXcbBackingStoreImage::shmPutImage(xcb_drawable_t drawable, const QRegion &region, const QPoint &offset)
{
for (const QRect &rect : region) {
const QPoint source = rect.translated(offset).topLeft();
@@ -534,7 +579,7 @@ void QXcbShmImage::shmPutImage(xcb_drawable_t drawable, const QRegion &region, c
m_dirtyShm |= region.translated(offset);
}
-void QXcbShmImage::flushPixmap(const QRegion &region, bool fullRegion)
+void QXcbBackingStoreImage::flushPixmap(const QRegion &region, bool fullRegion)
{
if (!fullRegion) {
auto actualRegion = m_pendingFlush.intersected(region);
@@ -603,7 +648,7 @@ void QXcbShmImage::flushPixmap(const QRegion &region, bool fullRegion)
}
}
-void QXcbShmImage::setClip(const QRegion &region)
+void QXcbBackingStoreImage::setClip(const QRegion &region)
{
if (region.isEmpty()) {
static const uint32_t mask = XCB_GC_CLIP_MASK;
@@ -619,7 +664,7 @@ void QXcbShmImage::setClip(const QRegion &region)
}
}
-void QXcbShmImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset)
+void QXcbBackingStoreImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset)
{
Q_ASSERT(!m_clientSideScroll);
@@ -660,7 +705,7 @@ void QXcbShmImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &
setClip(QRegion());
}
-void QXcbShmImage::preparePaint(const QRegion &region)
+void QXcbBackingStoreImage::preparePaint(const QRegion &region)
{
if (hasShm()) {
// to prevent X from reading from the image region while we're writing to it
@@ -675,7 +720,6 @@ void QXcbShmImage::preparePaint(const QRegion &region)
QXcbBackingStore::QXcbBackingStore(QWindow *window)
: QPlatformBackingStore(window)
- , m_image(0)
{
QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle());
setConnection(screen->connection());
@@ -805,7 +849,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
if (m_image && size == m_image->size())
return;
- QXcbScreen *screen = static_cast<QXcbScreen *>(window()->screen()->handle());
QPlatformWindow *pw = window()->handle();
if (!pw) {
window()->create();
@@ -813,8 +856,11 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
}
QXcbWindow* win = static_cast<QXcbWindow *>(pw);
- delete m_image;
- m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat());
+ if (m_image)
+ m_image->resize(size);
+ else
+ m_image = new QXcbBackingStoreImage(this, size);
+
// Slow path for bgr888 VNC: Create an additional image, paint into that and
// swap R and B while copying to m_image after each paint.
if (win->imageNeedsRgbSwap()) {
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index 2e8fbfb7fa..747626c213 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
-class QXcbShmImage;
+class QXcbBackingStoreImage;
class QXcbBackingStore : public QXcbObject, public QPlatformBackingStore
{
@@ -75,7 +75,7 @@ public:
void endPaint() override;
private:
- QXcbShmImage *m_image;
+ QXcbBackingStoreImage *m_image = nullptr;
QStack<QRegion> m_paintRegions;
QImage m_rgbImage;
};
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 2431f99ab8..444e3a7669 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -2136,17 +2136,22 @@ void QXcbConnection::initializeXRender()
{
#if QT_CONFIG(xcb_render)
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_render_id);
- if (!reply || !reply->present)
+ if (!reply || !reply->present) {
+ qCDebug(lcQpaXcb, "XRender extension not present on the X server");
return;
+ }
auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection,
XCB_RENDER_MAJOR_VERSION,
XCB_RENDER_MINOR_VERSION);
- if (!xrender_query || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
- qWarning("QXcbConnection: Failed to initialize XRender");
+ if (!xrender_query) {
+ qCWarning(lcQpaXcb, "xcb_render_query_version failed");
return;
}
+
has_render_extension = true;
+ m_xrenderVersion.first = xrender_query->major_version;
+ m_xrenderVersion.second = xrender_query->minor_version;
#endif
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index ced5208c81..d9321d94d0 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -478,7 +478,13 @@ public:
bool hasXRandr() const { return has_randr_extension; }
bool hasInputShape() const { return has_input_shape; }
bool hasXKB() const { return has_xkb; }
- bool hasXRender() const { return has_render_extension; }
+ bool hasXRender(int major = -1, int minor = -1) const
+ {
+ if (has_render_extension && major != -1 && minor != -1)
+ return m_xrenderVersion >= qMakePair(major, minor);
+
+ return has_render_extension;
+ }
bool hasXInput2() const { return m_xi2Enabled; }
bool hasShm() const { return has_shm; }
bool hasShmFd() const { return has_shm_fd; }
@@ -707,6 +713,8 @@ private:
bool has_shm = false;
bool has_shm_fd = false;
+ QPair<int, int> m_xrenderVersion;
+
Qt::MouseButtons m_buttonState = 0;
Qt::MouseButton m_button = Qt::NoButton;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 39d2857212..0302d585b5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -956,7 +956,7 @@ void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
return;
}
QPointF lastScrollPosition;
- if (lcQpaXInput().isDebugEnabled())
+ if (lcQpaXInputEvents().isDebugEnabled())
lastScrollPosition = scrollingDevice.lastScrollPosition;
for (int c = 0; c < deviceInfo->num_classes; ++c) {
XIAnyClassInfo *classInfo = deviceInfo->classes[c];
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 34b7d0d236..8d151b760b 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -301,6 +301,9 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
: QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false)
{
+ // see NUM_BITMAPS in libXcursor/src/xcursorint.h
+ m_bitmapCache.setMaxCost(8);
+
if (cursorCount++)
return;
@@ -351,37 +354,38 @@ QXcbCursor::~QXcbCursor()
}
#ifndef QT_NO_CURSOR
-void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
+void QXcbCursor::changeCursor(QCursor *cursor, QWindow *window)
{
- QXcbWindow *w = 0;
- if (widget && widget->handle())
- w = static_cast<QXcbWindow *>(widget->handle());
- else
- // No X11 cursor control when there is no widget under the cursor
+ if (!window || !window->handle())
return;
xcb_cursor_t c = XCB_CURSOR_NONE;
- bool isBitmapCursor = false;
-
if (cursor) {
+ const QXcbCursorCacheKey key(*cursor);
const Qt::CursorShape shape = cursor->shape();
- isBitmapCursor = shape == Qt::BitmapCursor;
- if (!isBitmapCursor) {
- const QXcbCursorCacheKey key(*cursor);
- CursorHash::iterator it = m_cursorHash.find(key);
- if (it == m_cursorHash.end()) {
- it = m_cursorHash.insert(key, createFontCursor(shape));
+ if (shape == Qt::BitmapCursor) {
+ auto *bitmap = m_bitmapCache.object(key);
+ if (bitmap) {
+ c = bitmap->cursor;
+ } else {
+ c = createBitmapCursor(cursor);
+ m_bitmapCache.insert(key, new CachedCursor(xcb_connection(), c));
}
- c = it.value();
} else {
- // Do not cache bitmap cursors, as otherwise they have unclear
- // lifetime (we effectively leak xcb_cursor_t).
- c = createBitmapCursor(cursor);
+ auto it = m_cursorHash.find(key);
+ if (it == m_cursorHash.end()) {
+ c = createFontCursor(shape);
+ m_cursorHash.insert(key, c);
+ } else {
+ c = it.value();
+ }
}
}
- w->setCursor(c, isBitmapCursor);
+ auto *w = static_cast<QXcbWindow *>(window->handle());
+ xcb_change_window_attributes(xcb_connection(), w->xcb_window(), XCB_CW_CURSOR, &c);
+ xcb_flush(xcb_connection());
}
static int cursorIdForShape(int cshape)
@@ -597,12 +601,19 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
{
- xcb_connection_t *conn = xcb_connection();
QPoint spot = cursor->hotSpot();
xcb_cursor_t c = XCB_NONE;
- if (cursor->pixmap().depth() > 1)
- c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
- if (!c) {
+ if (cursor->pixmap().depth() > 1) {
+#if QT_CONFIG(xcb_render)
+ if (connection()->hasXRender(0, 5))
+ c = qt_xcb_createCursorXRender(m_screen, cursor->pixmap().toImage(), spot);
+ else
+ qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors");
+#else
+ qCWarning(lcQpaXcb, "This build of Qt does not support pixmap cursors");
+#endif
+ } else {
+ xcb_connection_t *conn = xcb_connection();
xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage());
xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage());
c = xcb_generate_id(conn);
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index e3f88518fe..5bc806381c 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -43,6 +43,8 @@
#include <qpa/qplatformcursor.h>
#include "qxcbscreen.h"
+#include <QtCore/QCache>
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CURSOR
@@ -76,7 +78,7 @@ public:
QXcbCursor(QXcbConnection *conn, QXcbScreen *screen);
~QXcbCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *cursor, QWindow *widget) override;
+ void changeCursor(QCursor *cursor, QWindow *window) override;
#endif
QPoint pos() const override;
void setPos(const QPoint &pos) override;
@@ -89,9 +91,20 @@ public:
#endif
private:
+
#ifndef QT_NO_CURSOR
typedef QHash<QXcbCursorCacheKey, xcb_cursor_t> CursorHash;
+ struct CachedCursor
+ {
+ explicit CachedCursor(xcb_connection_t *conn, xcb_cursor_t c)
+ : cursor(c), connection(conn) {}
+ ~CachedCursor() { xcb_free_cursor(connection, cursor); }
+ xcb_cursor_t cursor;
+ xcb_connection_t *connection;
+ };
+ typedef QCache<QXcbCursorCacheKey, CachedCursor> BitmapCursorCache;
+
xcb_cursor_t createFontCursor(int cshape);
xcb_cursor_t createBitmapCursor(QCursor *cursor);
xcb_cursor_t createNonStandardCursor(int cshape);
@@ -100,6 +113,7 @@ private:
QXcbScreen *m_screen;
#ifndef QT_NO_CURSOR
CursorHash m_cursorHash;
+ BitmapCursorCache m_bitmapCache;
#endif
#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index e9a6e536a7..f87da28ee0 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -562,10 +562,6 @@ void QXcbWindow::create()
QXcbWindow::~QXcbWindow()
{
- if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
- xcb_free_cursor(xcb_connection(), m_currentBitmapCursor);
- }
-
destroy();
}
@@ -2333,7 +2329,7 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
#if QT_CONFIG(xinput2)
static inline int fixed1616ToInt(FP1616 val)
{
- return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF);
+ return int(qreal(val) / 0x10000);
}
void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source)
@@ -2591,24 +2587,6 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
return result;
}
-void QXcbWindow::setCursor(xcb_cursor_t cursor, bool isBitmapCursor)
-{
- xcb_connection_t *conn = xcb_connection();
-
- xcb_change_window_attributes(conn, m_window, XCB_CW_CURSOR, &cursor);
- xcb_flush(conn);
-
- if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
- xcb_free_cursor(conn, m_currentBitmapCursor);
- }
-
- if (isBitmapCursor) {
- m_currentBitmapCursor = cursor;
- } else {
- m_currentBitmapCursor = XCB_CURSOR_NONE;
- }
-}
-
void QXcbWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 957c4e9cbd..cb8af9e666 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -103,8 +103,6 @@ public:
bool setKeyboardGrabEnabled(bool grab) override;
bool setMouseGrabEnabled(bool grab) override;
- void setCursor(xcb_cursor_t cursor, bool isBitmapCursor);
-
QSurfaceFormat format() const override;
void windowEvent(QEvent *event) override;
@@ -285,7 +283,6 @@ protected:
SyncState m_syncState = NoSyncNeeded;
QXcbSyncWindowRequest *m_pendingSyncRequest = nullptr;
- xcb_cursor_t m_currentBitmapCursor = XCB_CURSOR_NONE;
};
class QXcbForeignWindow : public QXcbWindow
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
index 1a24015ce5..186084abd4 100644
--- a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
+++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
@@ -51,6 +51,7 @@
#include <QMetaType>
#include <QMimeType>
#include <QMimeDatabase>
+#include <QRandomGenerator>
#include <QWindow>
QT_BEGIN_NAMESPACE
@@ -231,6 +232,8 @@ void QFlatpakFileDialog::openPortal()
if (!filterList.isEmpty())
options.insert(QLatin1String("filters"), QVariant::fromValue(filterList));
+ options.insert(QLatin1String("handle_token"), QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate()));
+
// TODO choices a(ssa(ss)s)
// List of serialized combo boxes to add to the file chooser.
diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
index 04abd707e1..6c5e1389cf 100644
--- a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
+++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
@@ -95,41 +95,25 @@ QFlatpakTheme::QFlatpakTheme()
QPlatformMenuItem* QFlatpakTheme::createPlatformMenuItem() const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->createPlatformMenuItem();
-
- return QPlatformTheme::createPlatformMenuItem();
+ return d->baseTheme->createPlatformMenuItem();
}
QPlatformMenu* QFlatpakTheme::createPlatformMenu() const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->createPlatformMenu();
-
- return QPlatformTheme::createPlatformMenu();
+ return d->baseTheme->createPlatformMenu();
}
QPlatformMenuBar* QFlatpakTheme::createPlatformMenuBar() const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->createPlatformMenuBar();
-
- return QFlatpakTheme::createPlatformMenuBar();
+ return d->baseTheme->createPlatformMenuBar();
}
void QFlatpakTheme::showPlatformMenuBar()
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->showPlatformMenuBar();
-
- return QFlatpakTheme::showPlatformMenuBar();
+ return d->baseTheme->showPlatformMenuBar();
}
bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const
@@ -139,10 +123,7 @@ bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const
if (type == FileDialog)
return true;
- if (d->baseTheme)
- return d->baseTheme->usePlatformNativeDialog(type);
-
- return QFlatpakTheme::usePlatformNativeDialog(type);
+ return d->baseTheme->usePlatformNativeDialog(type);
}
QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type) const
@@ -152,103 +133,64 @@ QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type
if (type == FileDialog)
return new QFlatpakFileDialog;
- if (d->baseTheme)
- return d->baseTheme->createPlatformDialogHelper(type);
-
- return QFlatpakTheme::createPlatformDialogHelper(type);
+ return d->baseTheme->createPlatformDialogHelper(type);
}
#ifndef QT_NO_SYSTEMTRAYICON
QPlatformSystemTrayIcon* QFlatpakTheme::createPlatformSystemTrayIcon() const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->createPlatformSystemTrayIcon();
-
- return QPlatformTheme::createPlatformSystemTrayIcon();
+ return d->baseTheme->createPlatformSystemTrayIcon();
}
#endif
const QPalette *QFlatpakTheme::palette(Palette type) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->palette(type);
-
- return QPlatformTheme::palette(type);
+ return d->baseTheme->palette(type);
}
const QFont* QFlatpakTheme::font(Font type) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->font(type);
-
- return QPlatformTheme::font(type);
+ return d->baseTheme->font(type);
}
QVariant QFlatpakTheme::themeHint(ThemeHint hint) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->themeHint(hint);
-
- return QPlatformTheme::themeHint(hint);
+ return d->baseTheme->themeHint(hint);
}
QPixmap QFlatpakTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->standardPixmap(sp, size);
-
- return QPlatformTheme::standardPixmap(sp, size);
+ return d->baseTheme->standardPixmap(sp, size);
}
QIcon QFlatpakTheme::fileIcon(const QFileInfo &fileInfo,
QPlatformTheme::IconOptions iconOptions) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->fileIcon(fileInfo, iconOptions);
-
- return QPlatformTheme::fileIcon(fileInfo, iconOptions);
+ return d->baseTheme->fileIcon(fileInfo, iconOptions);
}
QIconEngine * QFlatpakTheme::createIconEngine(const QString &iconName) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->createIconEngine(iconName);
-
- return QPlatformTheme::createIconEngine(iconName);
+ return d->baseTheme->createIconEngine(iconName);
}
QList<QKeySequence> QFlatpakTheme::keyBindings(QKeySequence::StandardKey key) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->keyBindings(key);
-
- return QPlatformTheme::keyBindings(key);
+ return d->baseTheme->keyBindings(key);
}
QString QFlatpakTheme::standardButtonText(int button) const
{
Q_D(const QFlatpakTheme);
-
- if (d->baseTheme)
- return d->baseTheme->standardButtonText(button);
-
- return QPlatformTheme::standardButtonText(button);
+ return d->baseTheme->standardButtonText(button);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
index 1bbd463119..4f0bd9d9a0 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
@@ -426,9 +426,9 @@ QPoint QGtk3Menu::targetPos() const
void QGtk3Menu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
{
- int index = m_items.indexOf(static_cast<QGtk3MenuItem *>(const_cast<QPlatformMenuItem *>(item)));
- if (index != -1)
- gtk_menu_set_active(GTK_MENU(m_menu), index);
+ const QGtk3MenuItem *menuItem = static_cast<const QGtk3MenuItem *>(item);
+ if (menuItem)
+ gtk_menu_shell_select_item(GTK_MENU_SHELL(m_menu), menuItem->handle());
m_targetPos = QPoint(targetRect.x(), targetRect.y() + targetRect.height());
diff --git a/src/plugins/platformthemes/platformthemes.pro b/src/plugins/platformthemes/platformthemes.pro
index ebf92ba9d5..17b1d91c6a 100644
--- a/src/plugins/platformthemes/platformthemes.pro
+++ b/src/plugins/platformthemes/platformthemes.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += widgets-private
-qtConfig(dbus): SUBDIRS += flatpak
+qtConfig(dbus):qtConfig(regularexpression): SUBDIRS += flatpak
qtHaveModule(widgets):qtConfig(gtk3): SUBDIRS += gtk3
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 53a72779a9..18c8b48462 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -1160,14 +1160,14 @@ static void qLibraryInit()
# endif // MYSQL_VERSION_ID
#endif // Q_NO_MYSQL_EMBEDDED
-#ifdef MARIADB_BASE_VERSION
+#if defined(MARIADB_BASE_VERSION) || defined(MARIADB_VERSION_ID)
qAddPostRoutine([]() { mysql_server_end(); });
#endif
}
static void qLibraryEnd()
{
-#if !defined(MARIADB_BASE_VERSION)
+#if !defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID)
# if !defined(Q_NO_MYSQL_EMBEDDED)
# if MYSQL_VERSION_ID > 40000
# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003
diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp
index 272e1bc083..aee8e92b36 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci.cpp
+++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp
@@ -1318,7 +1318,7 @@ struct QOCIBatchColumn
ub4 maxLen;
ub4 recordCount;
char* data;
- ub2* lengths;
+ ub4* lengths;
sb2* indicators;
ub4 maxarr_len;
ub4 curelep;
@@ -1392,7 +1392,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
QOCIBatchColumn &col = columns[i];
col.recordCount = boundValues.at(i).toList().count();
- col.lengths = new ub2[col.recordCount];
+ col.lengths = new ub4[col.recordCount];
col.indicators = new sb2[col.recordCount];
col.maxarr_len = col.recordCount;
col.curelep = col.recordCount;
@@ -1556,7 +1556,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
// binding the column
- r = OCIBindByPos(
+ r = OCIBindByPos2(
d->sql, &bindColumn.bindh, d->err, i + 1,
bindColumn.data,
bindColumn.maxLen,
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index b4eb69e6cf..5e0f7626b4 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -462,8 +462,10 @@ void QPSQLResult::cleanup()
d->result = nullptr;
while (!d->nextResultSets.isEmpty())
PQclear(d->nextResultSets.takeFirst());
- if (d->stmtId != InvalidStatementId)
- d->drv_d_func()->finishQuery(d->stmtId);
+ if (d->stmtId != InvalidStatementId) {
+ if (d->drv_d_func())
+ d->drv_d_func()->finishQuery(d->stmtId);
+ }
d->stmtId = InvalidStatementId;
setAt(QSql::BeforeFirstRow);
d->currentSize = -1;
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index d1a6582c5a..6375825720 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -51,11 +51,12 @@
#include <qstringlist.h>
#include <qvector.h>
#include <qdebug.h>
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
#include <qcache.h>
#include <qregularexpression.h>
#endif
#include <QTimeZone>
+#include <QScopedValueRollback>
#if defined Q_OS_WIN
# include <qt_windows.h>
@@ -129,6 +130,7 @@ protected:
bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) override;
bool reset(const QString &query) override;
bool prepare(const QString &query) override;
+ bool execBatch(bool arrayBind) override;
bool exec() override;
int size() override;
int numRowsAffected() override;
@@ -443,6 +445,29 @@ static QString timespecToString(const QDateTime &dateTime)
}
}
+bool QSQLiteResult::execBatch(bool arrayBind)
+{
+ Q_UNUSED(arrayBind);
+ Q_D(QSqlResult);
+ QScopedValueRollback<QVector<QVariant>> valuesScope(d->values);
+ QVector<QVariant> values = d->values;
+ if (values.count() == 0)
+ return false;
+
+ for (int i = 0; i < values.at(0).toList().count(); ++i) {
+ d->values.clear();
+ QScopedValueRollback<QHash<QString, QVector<int>>> indexesScope(d->indexes);
+ QHash<QString, QVector<int>>::const_iterator it = d->indexes.constBegin();
+ while (it != d->indexes.constEnd()) {
+ bindValue(it.key(), values.at(it.value().first()).toList().at(i), QSql::In);
+ ++it;
+ }
+ if (!exec())
+ return false;
+ }
+ return true;
+}
+
bool QSQLiteResult::exec()
{
Q_D(QSQLiteResult);
@@ -467,8 +492,11 @@ bool QSQLiteResult::exec()
#if (SQLITE_VERSION_NUMBER >= 3003011)
// In the case of the reuse of a named placeholder
- if (paramCount < values.count()) {
- const auto countIndexes = [](int counter, const QList<int>& indexList) {
+ // We need to check explicitly that paramCount is greater than 1, as sqlite
+ // can end up in a case where for virtual tables it returns 0 even though it
+ // has parameters
+ if (paramCount > 1 && paramCount < values.count()) {
+ const auto countIndexes = [](int counter, const QVector<int> &indexList) {
return counter + indexList.length();
};
@@ -482,13 +510,14 @@ bool QSQLiteResult::exec()
// placeholders. So we need to ensure the QVector has only one instance of
// each value as SQLite will do the rest for us.
QVector<QVariant> prunedValues;
- QList<int> handledIndexes;
+ QVector<int> handledIndexes;
for (int i = 0, currentIndex = 0; i < values.size(); ++i) {
if (handledIndexes.contains(i))
continue;
const auto placeHolder = QString::fromUtf8(sqlite3_bind_parameter_name(d->stmt, currentIndex + 1));
- handledIndexes << d->indexes[placeHolder];
- prunedValues << values.at(d->indexes[placeHolder].first());
+ const auto &indexes = d->indexes.value(placeHolder);
+ handledIndexes << indexes;
+ prunedValues << values.at(indexes.first());
++currentIndex;
}
values = prunedValues;
@@ -622,7 +651,7 @@ QVariant QSQLiteResult::handle() const
/////////////////////////////////////////////////////////
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
static void _q_regexp(sqlite3_context* context, int argc, sqlite3_value** argv)
{
if (Q_UNLIKELY(argc != 2)) {
@@ -721,7 +750,7 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
bool sharedCache = false;
bool openReadOnlyOption = false;
bool openUriOption = false;
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
static const QLatin1String regexpConnectOption = QLatin1String("QSQLITE_ENABLE_REGEXP");
bool defineRegexp = false;
int regexpCacheSize = 25;
@@ -745,7 +774,7 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
} else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) {
sharedCache = true;
}
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
else if (option.startsWith(regexpConnectOption)) {
option = option.mid(regexpConnectOption.size()).trimmed();
if (option.isEmpty()) {
@@ -774,7 +803,7 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
sqlite3_busy_timeout(d->access, timeOut);
setOpen(true);
setOpenError(false);
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
if (defineRegexp) {
auto cache = new QCache<QString, QRegularExpression>(regexpCacheSize);
sqlite3_create_function_v2(d->access, "regexp", 2, SQLITE_UTF8, cache, &_q_regexp, NULL,
diff --git a/src/plugins/styles/mac/mac.pro b/src/plugins/styles/mac/mac.pro
index f3c7c1c067..9044354c07 100644
--- a/src/plugins/styles/mac/mac.pro
+++ b/src/plugins/styles/mac/mac.pro
@@ -10,7 +10,7 @@ HEADERS += \
qmacstyle_mac_p.h \
qmacstyle_mac_p_p.h
-LIBS_PRIVATE += -framework AppKit -framework ApplicationServices -framework Carbon
+LIBS_PRIVATE += -framework AppKit
DISTFILES += macstyle.json
diff --git a/src/plugins/styles/mac/qmacstyle.qdoc b/src/plugins/styles/mac/qmacstyle.qdoc
deleted file mode 100644
index 30b3d7775f..0000000000
--- a/src/plugins/styles/mac/qmacstyle.qdoc
+++ /dev/null
@@ -1,207 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-/*!
- \class QMacStyle
- \brief The QMacStyle class provides a \macos style using the Apple Appearance Manager.
-
- \ingroup appearance
- \inmodule QtWidgets
- \internal
-
- This class is implemented as a wrapper to the HITheme
- APIs, allowing applications to be styled according to the current
- theme in use on \macos. This is done by having primitives
- in QStyle implemented in terms of what \macos would normally theme.
-
- \warning This style is only available on \macos because it relies on the
- HITheme APIs.
-
- There are additional issues that should be taken
- into consideration to make an application compatible with the
- \l{Apple Human Interface Guidelines}{Apple Human Interface Guidelines}. Some of these issues are outlined
- below.
-
- \list
-
- \li Layout - The restrictions on window layout are such that some
- aspects of layout that are style-dependent cannot be achieved
- using QLayout. Changes are being considered (and feedback would be
- appreciated) to make layouts QStyle-able. Some of the restrictions
- involve horizontal and vertical widget alignment and widget size
- (covered below).
-
- \li Widget size - \macos allows widgets to have specific fixed sizes. Qt
- does not fully implement this behavior so as to maintain cross-platform
- compatibility. As a result some widgets sizes may be inappropriate (and
- subsequently not rendered correctly by the HITheme APIs).The
- QWidget::sizeHint() will return the appropriate size for many
- managed widgets (widgets enumerated in \l QStyle::ContentsType).
-
- \li Effects - QMacStyle uses HITheme for performing most of the drawing, but
- also uses emulation in a few cases where HITheme does not provide the
- required functionality (for example, tab bars on Panther, the toolbar
- separator, etc). We tried to make the emulation as close to the original as
- possible. Please report any issues you see in effects or non-standard
- widgets.
-
- \endlist
-
- There are other issues that need to be considered in the feel of
- your application (including the general color scheme to match the
- Aqua colors). The Guidelines mentioned above will remain current
- with new advances and design suggestions for \macos.
-
- Note that the functions provided by QMacStyle are
- reimplementations of QStyle functions; see QStyle for their
- documentation.
-
- \image qmacstyle.png
- \sa QWindowsVistaStyle, QWindowsStyle, QFusionStyle
-*/
-
-
-/*!
- \enum QStyleHelper::WidgetSizePolicy
-
- \value SizeSmall
- \value SizeLarge
- \value SizeMini
- \value SizeDefault
-*/
-
-/*! \fn QMacStyle::QMacStyle()
- Constructs a QMacStyle object.
-*/
-
-/*! \fn QMacStyle::~QMacStyle()
- Destructs a QMacStyle object.
-*/
-
-/*! \fn void QMacStyle::polish(QPalette &pal)
- \reimp
-*/
-
-/*! \fn void QMacStyle::polish(QApplication *)
- \reimp
-*/
-
-/*! \fn void QMacStyle::unpolish(QApplication *)
- \reimp
-*/
-
-/*! \fn void QMacStyle::polish(QWidget* w)
- \reimp
-*/
-
-/*! \fn void QMacStyle::unpolish(QWidget* w)
- \reimp
-*/
-
-/*! \fn int QMacStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn QPalette QMacStyle::standardPalette() const
- \reimp
-*/
-
-/*! \fn int QMacStyle::styleHint(QStyle::StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const
- \reimp
-*/
-
-/*! \fn QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
- \reimp
-*/
-
-/*! \fn QPixmap QMacStyle::standardPixmap(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn void QStyleHelper::setWidgetSizePolicy(const QWidget *widget, QStyleHelper::WidgetSizePolicy policy)
-
- \obsolete
-
- Call QWidget::setAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize,
- or Qt::WA_MacNormalSize instead.
-*/
-
-/*! \fn QStyleHelper::WidgetSizePolicy QStyleHelper::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt)
- \obsolete
-
- Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize,
- or Qt::WA_MacNormalSize instead.
-*/
-
-/*! \fn void QMacStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
-
- \reimp
-*/
-
-/*! \fn void QMacStyle::drawControl(QStyle::ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const
-
- \reimp
-*/
-
-/*! \fn QRect QMacStyle::subElementRect(QStyle::SubElement sr, const QStyleOption *opt, const QWidget *widget) const
-
- \reimp
-*/
-
-/*! \fn void QMacStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn QRect QMacStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn QSize QMacStyle::sizeFromContents(QStyle::ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const
- \reimp
-*/
-
-/*! \fn bool QMacStyle::event(QEvent *e)
- \reimp
-*/
-
-/*! \fn QIcon QMacStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const
- \reimp
-*/
-
-/*! \fn int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const
- \reimp
-*/
-
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 9e8af78a8e..569eeef0ff 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -43,7 +43,6 @@
*/
#include <AppKit/AppKit.h>
-#include <ApplicationServices/ApplicationServices.h>
#include "qmacstyle_mac_p.h"
#include "qmacstyle_mac_p_p.h"
@@ -250,18 +249,30 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
}
@end
+#if !QT_CONFIG(appstore_compliant)
+
+// This API was requested to Apple in rdar #36197888.
+// We know it's safe to use up to macOS 10.13.3.
+// See drawComplexControl(CC_ComboBox) for its usage.
+
+@interface NSComboBoxCell (QtButtonCell)
+@property (readonly) NSButtonCell *qt_buttonCell;
+@end
+
+@implementation NSComboBoxCell (QtButtonCell)
+- (NSButtonCell *)qt_buttonCell {
+ return self->_buttonCell;
+}
+@end
+
+#endif
+
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
// of push buttons so that they are drawn inside their bounds.
const int QMacStylePrivate::PushButtonLeftOffset = 6;
-const int QMacStylePrivate::PushButtonTopOffset = 4;
const int QMacStylePrivate::PushButtonRightOffset = 12;
-const int QMacStylePrivate::PushButtonBottomOffset = 12;
-const int QMacStylePrivate::MiniButtonH = 26;
-const int QMacStylePrivate::SmallButtonH = 30;
-const int QMacStylePrivate::BevelButtonW = 50;
-const int QMacStylePrivate::BevelButtonH = 22;
const int QMacStylePrivate::PushButtonContentPadding = 6;
QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
@@ -331,14 +342,45 @@ static const qreal closeButtonCornerRadius = 2.0;
static const int headerSectionArrowHeight = 6;
static const int headerSectionSeparatorInset = 2;
-#if QT_CONFIG(tabbar)
-static bool isVerticalTabs(const QTabBar::Shape shape) {
- return (shape == QTabBar::RoundedEast
- || shape == QTabBar::TriangularEast
- || shape == QTabBar::RoundedWest
- || shape == QTabBar::TriangularWest);
-}
-#endif
+// One for each of QStyleHelper::WidgetSizePolicy
+static const QMarginsF comboBoxFocusRingMargins[3] = {
+ { 0.5, 2, 3.5, 4 },
+ { 0.5, 1, 2.5, 4 },
+ { 0.5, 1.5, 2.5, 3.5 }
+};
+
+static const QMarginsF pullDownButtonShadowMargins[3] = {
+ { 0.5, -1, 0.5, 2 },
+ { 0.5, -1.5, 0.5, 2.5 },
+ { 0.5, 0, 0.5, 1 }
+};
+
+static const QMarginsF pushButtonShadowMargins[3] = {
+ { 1.5, -1.5, 1.5, 4.5 },
+ { 1.5, -1, 1.5, 4 },
+ { 1.5, 0.5, 1.5, 2.5 }
+};
+
+// These are frame heights as reported by Xcode 9's Interface Builder.
+// Alignemnet rectangle's heights match for push and popup buttons
+// with respective values 21, 18 and 15.
+
+static const qreal comboBoxDefaultHeight[3] = {
+ 26, 22, 19
+};
+
+static const qreal pushButtonDefaultHeight[3] = {
+ 32, 28, 16
+};
+
+static const qreal popupButtonDefaultHeight[3] = {
+ 26, 22, 15
+};
+
+static const int toolButtonArrowSize = 7;
+static const int toolButtonArrowMargin = 2;
+
+static const qreal focusRingWidth = 3.5;
static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb)
{
@@ -444,10 +486,10 @@ static void drawTabCloseButton(QPainter *p, bool hover, bool selected, bool pres
#if QT_CONFIG(tabbar)
QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
{
- if (isVerticalTabs(shape)) {
+ const auto tabDirection = QMacStylePrivate::tabDirection(shape);
+ if (QMacStylePrivate::verticalTabs(tabDirection)) {
int newX, newY, newRot;
- if (shape == QTabBar::RoundedEast
- || shape == QTabBar::TriangularEast) {
+ if (tabDirection == QMacStylePrivate::East) {
newX = tabRect.width();
newY = tabRect.y();
newRot = 90;
@@ -468,23 +510,10 @@ QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, int tabOverlap)
{
QRect rect = tabOpt->rect;
-
- switch (tabOpt->shape) {
- case QTabBar::RoundedNorth:
- case QTabBar::TriangularNorth:
- case QTabBar::RoundedSouth:
- case QTabBar::TriangularSouth:
- rect.adjust(-tabOverlap, 0, 0, 0);
- break;
- case QTabBar::RoundedEast:
- case QTabBar::TriangularEast:
- case QTabBar::RoundedWest:
- case QTabBar::TriangularWest:
- rect.adjust(0, -tabOverlap, 0, 0);
- break;
- default:
- break;
- }
+ if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tabOpt->shape)))
+ rect = rect.adjusted(-tabOverlap, 0, 0, 0);
+ else
+ rect = rect.adjusted(0, -tabOverlap, 0, 0);
p->translate(rect.x(), rect.y());
rect.moveLeft(0);
@@ -535,11 +564,11 @@ void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, in
void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w)
{
QRect r = tbb->rect;
- if (isVerticalTabs(tbb->shape)) {
+ if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tbb->shape)))
r.setWidth(w->width());
- } else {
+ else
r.setHeight(w->height());
- }
+
const QRect tabRect = rotateTabPainter(p, tbb->shape, r);
const int width = tabRect.width();
const int height = tabRect.height();
@@ -575,34 +604,7 @@ static QStyleHelper::WidgetSizePolicy getControlSize(const QStyleOption *option,
static inline bool isTreeView(const QWidget *widget)
{
return (widget && widget->parentWidget() &&
- (qobject_cast<const QTreeView *>(widget->parentWidget())
- ));
-}
-#endif
-
-#if QT_CONFIG(tabbar)
-static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape)
-{
- ThemeTabDirection ttd;
- switch (shape) {
- case QTabBar::RoundedSouth:
- case QTabBar::TriangularSouth:
- ttd = kThemeTabSouth;
- break;
- case QTabBar::RoundedNorth:
- case QTabBar::TriangularNorth:
- ttd = kThemeTabNorth;
- break;
- case QTabBar::RoundedWest:
- case QTabBar::TriangularWest:
- ttd = kThemeTabWest;
- break;
- case QTabBar::RoundedEast:
- case QTabBar::TriangularEast:
- ttd = kThemeTabEast;
- break;
- }
- return ttd;
+ qobject_cast<const QTreeView *>(widget->parentWidget()));
}
#endif
@@ -640,15 +642,6 @@ static QString qt_mac_removeMnemonics(const QString &original)
return returnText;
}
-bool qt_macWindowIsTextured(const QWidget *window)
-{
- if (QWindow *w = window->windowHandle())
- if (w->handle())
- if (NSWindow *nswindow = static_cast<NSWindow*>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("NSWindow"), w)))
- return ([nswindow styleMask] & NSTexturedBackgroundWindowMask) ? true : false;
- return false;
-}
-
static bool qt_macWindowMainWindow(const QWidget *window)
{
if (QWindow *w = window->windowHandle()) {
@@ -664,7 +657,6 @@ static bool qt_macWindowMainWindow(const QWidget *window)
/*****************************************************************************
QMacCGStyle globals
*****************************************************************************/
-const int qt_mac_hitheme_version = 0; //the HITheme version we speak
const int macItemFrame = 2; // menu item frame width
const int macItemHMargin = 3; // menu item hor text margin
const int macRightBorder = 12; // right border on mac
@@ -672,10 +664,6 @@ const int macRightBorder = 12; // right border on mac
/*****************************************************************************
QMacCGStyle utility functions
*****************************************************************************/
-static inline int qt_mac_hitheme_tab_version()
-{
- return 1;
-}
enum QAquaMetric {
// Prepend kThemeMetric to get the HIToolBox constant.
@@ -858,7 +846,11 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
// However, this doesn't work for German, therefore only do it for English,
// I suppose it would be better to do some sort of lookups for languages
// that like to have really long words.
- ret.setWidth(77 - 8);
+ // FIXME This is not exactly true. Out of context, OK buttons have their
+ // implicit size calculated the same way as any other button. Inside a
+ // QDialogButtonBox, their size should be calculated such that the action
+ // or accept button (i.e., rightmost) and cancel button have the same width.
+ ret.setWidth(69);
}
} else {
// The only sensible thing to do is to return whatever the style suggests...
@@ -1087,160 +1079,115 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
return QStyleHelper::SizeLarge;
}
-#if QT_CONFIG(mainwindow)
- if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) {
- //if (small.width() != -1 || small.height() != -1)
+ if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL"))
return QStyleHelper::SizeSmall;
- } else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) {
+ else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI"))
return QStyleHelper::SizeMini;
- }
-#endif
-#if 0
- /* Figure out which size we're closer to, I just hacked this in, I haven't
- tested it as it would probably look pretty strange to have some widgets
- big and some widgets small in the same window?? -Sam */
- int large_delta=0;
- if (large.width() != -1) {
- int delta = large.width() - widg->width();
- large_delta += delta * delta;
- }
- if (large.height() != -1) {
- int delta = large.height() - widg->height();
- large_delta += delta * delta;
- }
- int small_delta=0;
- if (small.width() != -1) {
- int delta = small.width() - widg->width();
- small_delta += delta * delta;
- }
- if (small.height() != -1) {
- int delta = small.height() - widg->height();
- small_delta += delta * delta;
- }
- int mini_delta=0;
- if (mini.width() != -1) {
- int delta = mini.width() - widg->width();
- mini_delta += delta * delta;
- }
- if (mini.height() != -1) {
- int delta = mini.height() - widg->height();
- mini_delta += delta * delta;
- }
- if (mini_delta < small_delta && mini_delta < large_delta)
- return QStyleHelper::SizeMini;
- else if (small_delta < large_delta)
- return QStyleHelper::SizeSmall;
-#endif
return QStyleHelper::SizeLarge;
}
#endif
-void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const
+void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
- const qreal pixelRatio = p->device()->devicePixelRatioF();
- static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4");
- const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio);
- QPixmap focusRingPixmap;
-
- if (!QPixmapCache::find(key, focusRingPixmap)) {
- const qreal size = radius * 2 + 5;
- focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio);
- focusRingPixmap.fill(Qt::transparent);
- focusRingPixmap.setDevicePixelRatio(pixelRatio);
-
- static const qreal focusRingWidth = 3.5;
- const auto focusRingRect = QRectF(hMargin, vMargin, size, size);
- QPainterPath focusRingPath;
- focusRingPath.setFillRule(Qt::OddEvenFill);
- const auto innerRect = radius > 0 ? focusRingRect : focusRingRect.adjusted(0.5, 0.5, -0.5, -0.5);
- if (radius > 0)
- focusRingPath.addRoundedRect(innerRect, radius, radius);
- else
- focusRingPath.addRect(innerRect);
-
- const auto outterRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
- const auto outterRadius = radius + focusRingWidth;
- focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius);
-
- QPainter pp(&focusRingPixmap);
- pp.setOpacity(0.5);
- pp.setRenderHint(QPainter::Antialiasing);
- const auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
- pp.fillPath(focusRingPath, focusRingColor);
-
- QPixmapCache::insert(key, focusRingPixmap);
- }
-
- // Add 2 for the actual ring tickness going inwards
- const qreal hCornerSize = 2 + hMargin + radius;
- const qreal vCornerSize = 2 + vMargin + radius;
- const qreal shCornerSize = hCornerSize * pixelRatio;
- const qreal svCornerSize = vCornerSize * pixelRatio;
- // top-left corner
- p->drawPixmap(QPointF(targetRect.left(), targetRect.top()), focusRingPixmap,
- QRectF(0, 0, shCornerSize, svCornerSize));
- // top-right corner
- p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.top()), focusRingPixmap,
- QRectF(focusRingPixmap.width() - shCornerSize, 0, shCornerSize, svCornerSize));
- // bottom-left corner
- p->drawPixmap(QPointF(targetRect.left(), targetRect.bottom() - vCornerSize + 1), focusRingPixmap,
- QRectF(0, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize));
- // bottom-right corner
- p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.bottom() - vCornerSize + 1), focusRingPixmap,
- QRect(focusRingPixmap.width() - shCornerSize, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize));
- // top edge
- p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.top(), targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap,
- QRect(shCornerSize, 0, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize));
- // bottom edge
- p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.bottom() - vCornerSize + 1, targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap,
- QRect(shCornerSize, focusRingPixmap.height() - svCornerSize, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize));
- // left edge
- p->drawPixmap(QRectF(targetRect.left(), targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap,
- QRect(0, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize));
- // right edge
- p->drawPixmap(QRectF(targetRect.right() - hCornerSize + 1, targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap,
- QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize));
-}
-
-void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
-{
- static const auto focusRingWidth = 3.5;
-
QPainterPath focusRingPath;
+ focusRingPath.setFillRule(Qt::OddEvenFill);
+
qreal hOffset = 0.0;
qreal vOffset = 0.0;
- switch (cw.first) {
+ switch (cw.type) {
+ case Box:
+ case Button_SquareButton:
+ case SegmentedControl_Middle:
+ case TextField: {
+ auto innerRect = targetRect;
+ if (cw.type == TextField)
+ innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5);
+ const auto outerRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
+ const auto outerRadius = focusRingWidth;
+ focusRingPath.addRect(innerRect);
+ focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
+ break;
+ }
case Button_CheckBox: {
- const auto cbInnerRadius = (cw.second == QStyleHelper::SizeMini ? 2.0 : 3.0);
- const auto cbSize = cw.second == QStyleHelper::SizeLarge ? 13 :
- cw.second == QStyleHelper::SizeSmall ? 11 : 9; // As measured
- hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 2.5 :
- cw.second == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured
+ const auto cbInnerRadius = (cw.size == QStyleHelper::SizeMini ? 2.0 : 3.0);
+ const auto cbSize = cw.size == QStyleHelper::SizeLarge ? 13 :
+ cw.size == QStyleHelper::SizeSmall ? 11 : 9; // As measured
+ hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 2.5 :
+ cw.size == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured
vOffset = 0.5 * qreal(targetRect.height() - cbSize);
const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize);
- const auto cbOutterRadius = cbInnerRadius + focusRingWidth;
- const auto cbOutterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
- focusRingPath.setFillRule(Qt::OddEvenFill);
- focusRingPath.addRoundedRect(cbOutterRect, cbOutterRadius, cbOutterRadius);
+ const auto cbOuterRadius = cbInnerRadius + focusRingWidth;
+ const auto cbOuterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
+ focusRingPath.addRoundedRect(cbOuterRect, cbOuterRadius, cbOuterRadius);
focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius);
break;
}
case Button_RadioButton: {
- const auto rbSize = cw.second == QStyleHelper::SizeLarge ? 15 :
- cw.second == QStyleHelper::SizeSmall ? 13 : 9; // As measured
- hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 1.5 :
- cw.second == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured
+ const auto rbSize = cw.size == QStyleHelper::SizeLarge ? 15 :
+ cw.size == QStyleHelper::SizeSmall ? 13 : 9; // As measured
+ hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 1.5 :
+ cw.size == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured
vOffset = 0.5 * qreal(targetRect.height() - rbSize);
const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize);
- const auto rbOutterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
- focusRingPath.setFillRule(Qt::OddEvenFill);
+ const auto rbOuterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
focusRingPath.addEllipse(rbInnerRect);
- focusRingPath.addEllipse(rbOutterRect);
+ focusRingPath.addEllipse(rbOuterRect);
+ break;
+ }
+ case Button_PopupButton:
+ case Button_PullDown:
+ case Button_PushButton:
+ case SegmentedControl_Single: {
+ const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4;
+ const qreal outerRadius = innerRadius + focusRingWidth;
+ hOffset = targetRect.left();
+ vOffset = targetRect.top();
+ const auto innerRect = targetRect.translated(-targetRect.topLeft());
+ const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
+ focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius);
+ focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
+ break;
+ }
+ case ComboBox:
+ case SegmentedControl_First:
+ case SegmentedControl_Last: {
+ hOffset = targetRect.left();
+ vOffset = targetRect.top();
+ const qreal innerRadius = 8;
+ const qreal outerRadius = innerRadius + focusRingWidth;
+ const auto innerRect = targetRect.translated(-targetRect.topLeft());
+ const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
+
+ const auto cbFocusFramePath = [](const QRectF &rect, qreal tRadius, qreal bRadius) {
+ QPainterPath path;
+
+ if (tRadius > 0) {
+ const auto topLeftCorner = QRectF(rect.topLeft(), QSizeF(tRadius, tRadius));
+ path.arcMoveTo(topLeftCorner, 180);
+ path.arcTo(topLeftCorner, 180, -90);
+ } else {
+ path.moveTo(rect.topLeft());
+ }
+ const auto rightEdge = rect.right() - bRadius;
+ path.arcTo(rightEdge, rect.top(), bRadius, bRadius, 90, -90);
+ path.arcTo(rightEdge, rect.bottom() - bRadius, bRadius, bRadius, 0, -90);
+ if (tRadius > 0)
+ path.arcTo(rect.left(), rect.bottom() - tRadius, tRadius, tRadius, 270, -90);
+ else
+ path.lineTo(rect.bottomLeft());
+ path.closeSubpath();
+
+ return path;
+ };
+
+ const auto innerPath = cbFocusFramePath(innerRect, 0, innerRadius);
+ focusRingPath.addPath(innerPath);
+ const auto outerPath = cbFocusFramePath(outerRect, 2 * focusRingWidth, outerRadius);
+ focusRingPath.addPath(outerPath);
break;
}
default:
- Q_UNUSED(vMargin);
Q_UNREACHABLE();
}
@@ -1249,6 +1196,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h
p->save();
p->setRenderHint(QPainter::Antialiasing);
p->setOpacity(0.5);
+ if (cw.type == SegmentedControl_First) {
+ // TODO Flip left-right
+ }
p->translate(hOffset, vOffset);
p->fillPath(focusRingPath, focusRingColor);
p->restore();
@@ -1374,6 +1324,31 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg
*textRect = tr;
}
+
+QMacStylePrivate::Direction QMacStylePrivate::tabDirection(QTabBar::Shape shape)
+{
+ switch (shape) {
+ case QTabBar::RoundedSouth:
+ case QTabBar::TriangularSouth:
+ return South;
+ case QTabBar::RoundedNorth:
+ case QTabBar::TriangularNorth:
+ return North;
+ case QTabBar::RoundedWest:
+ case QTabBar::TriangularWest:
+ return West;
+ case QTabBar::RoundedEast:
+ case QTabBar::TriangularEast:
+ return East;
+ }
+}
+
+bool QMacStylePrivate::verticalTabs(QMacStylePrivate::Direction direction)
+{
+ return (direction == QMacStylePrivate::East
+ || direction == QMacStylePrivate::West);
+}
+
#endif // QT_CONFIG(tabbar)
QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option,
@@ -1460,225 +1435,161 @@ QStyleHelper::WidgetSizePolicy QMacStylePrivate::aquaSizeConstrain(const QStyleO
#endif
}
-/**
- Returns the free space awailable for contents inside the
- button (and not the size of the contents itself)
-*/
-CGRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
- const HIThemeButtonDrawInfo *bdi) const
+uint qHash(const QMacStylePrivate::CocoaControl &cw, uint seed = 0)
{
- CGRect outerBounds = btn->rect.toCGRect();
- // Adjust the bounds to correct for
- // carbon not calculating the content bounds fully correct
- if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){
- outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset;
- outerBounds.size.height -= QMacStylePrivate::PushButtonBottomOffset;
- } else if (bdi->kind == kThemePushButtonMini) {
- outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset;
- }
+ return ((cw.type << 2) | cw.size) ^ seed;
+}
- CGRect contentBounds;
- HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds);
- return contentBounds;
+QMacStylePrivate::CocoaControl::CocoaControl()
+ : type(NoControl), size(QStyleHelper::SizeDefault)
+{
}
-/**
- Calculates the size of the button contents.
- This includes both the text and the icon.
-*/
-QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const
+QMacStylePrivate::CocoaControl::CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s)
+ : type(t), size(s)
{
- Q_Q(const QMacStyle);
- QSize csz(0, 0);
- QSize iconSize = btn->icon.isNull() ? QSize(0, 0)
- : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0));
- QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1)
- : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text);
- csz.setWidth(iconSize.width() + textRect.width()
- + ((btn->features & QStyleOptionButton::HasMenu)
- ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
- csz.setHeight(qMax(iconSize.height(), textRect.height()));
- return csz;
}
-/**
- Checks if the actual contents of btn fits inside the free content bounds of
- 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton'
- for determining which button kind to use for drawing.
-*/
-bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn,
- HIThemeButtonDrawInfo *bdi,
- ThemeButtonKind buttonKindToCheck) const
+bool QMacStylePrivate::CocoaControl::operator==(const CocoaControl &other) const
{
- ThemeButtonKind tmp = bdi->kind;
- bdi->kind = buttonKindToCheck;
- QSize contentSize = pushButtonSizeFromContents(btn);
- QRect freeContentRect = QRectF::fromCGRect(pushButtonContentBounds(btn, bdi)).toRect();
- bdi->kind = tmp;
- return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(),
- contentSize.width(), contentSize.height()));
+ return other.type == type && other.size == size;
}
-/**
- Creates a HIThemeButtonDrawInfo structure that specifies the correct button
- kind and other details to use for drawing the given push button. Which
- button kind depends on the size of the button, the size of the contents,
- explicit user style settings, etc.
-*/
-void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn,
- const QWidget *widget,
- const ThemeDrawState tds,
- HIThemeButtonDrawInfo *bdi) const
+QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const
{
- ThemeDrawState tdsModified = tds;
- if (btn->state & QStyle::State_On)
- tdsModified = kThemeStatePressed;
- bdi->version = qt_mac_hitheme_version;
- bdi->state = tdsModified;
- bdi->value = kThemeButtonOff;
-
- if (tds == kThemeStateInactive)
- bdi->state = kThemeStateActive;
- if (btn->state & QStyle::State_HasFocus)
- bdi->adornment = kThemeAdornmentFocus;
- else
- bdi->adornment = kThemeAdornmentNone;
+ // We need this because things like NSView.alignmentRectInsets
+ // or -[NSCell titleRectForBounds:] won't work unless the control
+ // has a reasonable frame set. IOW, it's a chicken and egg problem.
+ // These values are as observed in Xcode 9's Interface Builder.
+ if (type == Button_PushButton)
+ return QSizeF(-1, pushButtonDefaultHeight[size]);
+
+ if (type == Button_PopupButton
+ || type == Button_PullDown)
+ return QSizeF(-1, popupButtonDefaultHeight[size]);
+
+ if (type == ComboBox)
+ return QSizeF(-1, comboBoxDefaultHeight[size]);
+
+ return QSizeF();
+}
- if (btn->features & (QStyleOptionButton::Flat)) {
- bdi->kind = kThemeBevelButton;
+QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect) const
+{
+ QRectF frameRect;
+ const auto frameSize = defaultFrameSize();
+ if (type == QMacStylePrivate::Button_SquareButton) {
+ frameRect = rect.adjusted(3, 1, -3, -5)
+ .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth);
+ } else if (type == QMacStylePrivate::Button_PushButton) {
+ // Start from the style option's top-left corner.
+ frameRect = QRectF(rect.topLeft(),
+ QSizeF(rect.width(), frameSize.height()));
+ if (size == QStyleHelper::SizeSmall)
+ frameRect = frameRect.translated(0, 1.5);
+ else if (size == QStyleHelper::SizeMini)
+ frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4);
} else {
- switch (aquaSizeConstrain(btn, widget)) {
- case QStyleHelper::SizeSmall:
- bdi->kind = kThemePushButtonSmall;
- break;
- case QStyleHelper::SizeMini:
- bdi->kind = kThemePushButtonMini;
- break;
- case QStyleHelper::SizeLarge:
- // ... We should honor if the user is explicit about using the
- // large button. But right now Qt will specify the large button
- // as default rather than QStyleHelper::SizeDefault.
- // So we treat it like QStyleHelper::SizeDefault
- // to get the dynamic choosing of button kind.
- case QStyleHelper::SizeDefault:
- // Choose the button kind that closest match the button rect, but at the
- // same time displays the button contents without clipping.
- bdi->kind = kThemeBevelButton;
- if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){
- if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) {
- if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){
- if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini))
- bdi->kind = kThemePushButtonMini;
- } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){
- if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall))
- bdi->kind = kThemePushButtonSmall;
- } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) {
- bdi->kind = kThemePushButton;
- }
- } else {
- bdi->kind = kThemePushButton;
- }
- }
+ // Center in the style option's rect.
+ frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0),
+ QSizeF(rect.width(), frameSize.height()));
+ frameRect = frameRect.translated(rect.topLeft());
+ if (type == QMacStylePrivate::Button_PullDown || type == QMacStylePrivate::Button_PopupButton) {
+ if (size == QStyleHelper::SizeLarge)
+ frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1);
+ else if (size == QStyleHelper::SizeSmall)
+ frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1);
+ else if (size == QStyleHelper::SizeMini)
+ frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0);
+ } else if (type == QMacStylePrivate::ComboBox) {
+ frameRect = frameRect.adjusted(0, 0, -6, 0).translated(4, 0);
}
}
+
+ return frameRect;
}
-/**
- Creates a HIThemeButtonDrawInfo structure that specifies the correct button
- kind and other details to use for drawing the given combobox. Which button
- kind depends on the size of the combo, wether or not it is editable,
- explicit user style settings, etc.
-*/
-void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi,
- CocoaControl *cw,
- const QWidget *widget, const ThemeDrawState &tds) const
+QMarginsF QMacStylePrivate::CocoaControl::titleMargins() const
{
- bdi->version = qt_mac_hitheme_version;
- bdi->adornment = kThemeAdornmentArrowLeftArrow;
- bdi->value = kThemeButtonOff;
- if (combo->state & QStyle::State_HasFocus)
- bdi->adornment = kThemeAdornmentFocus;
- if (combo->activeSubControls & QStyle::SC_ComboBoxArrow)
- bdi->state = kThemeStatePressed;
- else
- bdi->state = tds;
-
- QStyleHelper::WidgetSizePolicy aSize = aquaSizeConstrain(combo, widget);
- cw->first = combo->editable ? ComboBox : Button_PopupButton;
- cw->second = aSize;
- switch (aSize) {
- case QStyleHelper::SizeMini:
- bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini)
- : ThemeButtonKind(kThemePopupButtonMini);
- break;
- case QStyleHelper::SizeSmall:
- bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall)
- : ThemeButtonKind(kThemePopupButtonSmall);
- break;
- case QStyleHelper::SizeLarge:
- case QStyleHelper::SizeDefault:
- // Unless the user explicitly specified large buttons, determine the
- // kind by looking at the combox size.
- // ... specifying small and mini-buttons it not a current feature of
- // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add
- // an extra check here before using the mini and small buttons.
- int h = combo->rect.size().height();
- if (combo->editable){
-#if QT_CONFIG(datetimeedit)
- if (qobject_cast<const QDateTimeEdit *>(widget)) {
- // Except when, you know, we get a QDateTimeEdit with calendarPopup
- // enabled. And then things get weird, basically because it's a
- // transvestite spinbox with editable combobox tendencies. Meaning
- // that it wants to look a combobox, except that it isn't one, so it
- // doesn't get all those extra free margins around. (Don't know whose
- // idea those margins were, but now it looks like we're stuck with
- // them forever). So anyway, the height threshold should be smaller
- // in this case, or the style gets confused when it needs to render
- // or return any subcontrol size of the poor thing.
- if (h < 9) {
- bdi->kind = kThemeComboBoxMini;
- cw->second = QStyleHelper::SizeMini;
- } else if (h < 22) {
- bdi->kind = kThemeComboBoxSmall;
- cw->second = QStyleHelper::SizeSmall;
- } else {
- bdi->kind = kThemeComboBox;
- cw->second = QStyleHelper::SizeLarge;
- }
- } else
-#endif
- {
- if (h < 21) {
- bdi->kind = kThemeComboBoxMini;
- cw->second = QStyleHelper::SizeMini;
- } else if (h < 26) {
- bdi->kind = kThemeComboBoxSmall;
- cw->second = QStyleHelper::SizeSmall;
- } else {
- bdi->kind = kThemeComboBox;
- cw->second = QStyleHelper::SizeLarge;
- }
- }
- } else {
- // Even if we specify that we want the kThemePopupButton, Carbon
- // will use the kThemePopupButtonSmall if the size matches. So we
- // do the same size check explicit to have the size of the inner
- // text field be correct. Therefore, do this even if the user specifies
- // the use of LargeButtons explicit.
- if (h < 21) {
- bdi->kind = kThemePopupButtonMini;
- cw->second = QStyleHelper::SizeMini;
- } else if (h < 26) {
- bdi->kind = kThemePopupButtonSmall;
- cw->second = QStyleHelper::SizeSmall;
- } else {
- bdi->kind = kThemePopupButton;
- cw->second = QStyleHelper::SizeLarge;
- }
- }
+ if (type == QMacStylePrivate::Button_PushButton) {
+ if (size == QStyleHelper::SizeLarge)
+ return QMarginsF(12, 5, 12, 9);
+ if (size == QStyleHelper::SizeSmall)
+ return QMarginsF(12, 4, 12, 9);
+ if (size == QStyleHelper::SizeMini)
+ return QMarginsF(10, 1, 10, 2);
+ }
+
+ if (type == QMacStylePrivate::Button_PullDown) {
+ if (size == QStyleHelper::SizeLarge)
+ return QMarginsF(7.5, 2.5, 22.5, 5.5);
+ if (size == QStyleHelper::SizeSmall)
+ return QMarginsF(7.5, 2, 20.5, 4);
+ if (size == QStyleHelper::SizeMini)
+ return QMarginsF(4.5, 0, 16.5, 2);
+ }
+
+ if (type == QMacStylePrivate::Button_SquareButton)
+ return QMarginsF(6, 1, 6, 2);
+
+ return QMarginsF();
+}
+
+bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const
+{
+ switch (type) {
+ case Button_CheckBox:
+ *buttonType = NSSwitchButton;
+ *bezelStyle = NSRegularSquareBezelStyle;
break;
+ case Button_Disclosure:
+ *buttonType = NSOnOffButton;
+ *bezelStyle = NSDisclosureBezelStyle;
+ break;
+ case Button_RadioButton:
+ *buttonType = NSRadioButton;
+ *bezelStyle = NSRegularSquareBezelStyle;
+ break;
+ case Button_SquareButton:
+ *buttonType = NSPushOnPushOffButton;
+ *bezelStyle = NSShadowlessSquareBezelStyle;
+ break;
+ case Button_PushButton:
+ *buttonType = NSPushOnPushOffButton;
+ *bezelStyle = NSRoundedBezelStyle;
+ break;
+ default:
+ return false;
}
+
+ return true;
+}
+
+QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, const QWidget *w)
+{
+ if (const auto *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
+ const bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
+ // When the contents won't fit in a large sized button,
+ // and WA_MacNormalSize is not set, make the button square.
+ // Threshold used to be at 34, not 32.
+ const auto maxNonSquareHeight = pushButtonDefaultHeight[QStyleHelper::SizeLarge];
+ const bool isSquare = (btn->features & QStyleOptionButton::Flat)
+ || (btn->rect.height() > maxNonSquareHeight
+ && !(w && w->testAttribute(Qt::WA_MacNormalSize)));
+ return (isSquare? QMacStylePrivate::Button_SquareButton :
+ hasMenu ? QMacStylePrivate::Button_PullDown :
+ QMacStylePrivate::Button_PushButton);
+ }
+
+ if (const auto *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
+ if (combo->editable)
+ return QMacStylePrivate::ComboBox;
+ // TODO Me may support square, non-editable combo boxes, but not more than that
+ return QMacStylePrivate::Button_PopupButton;
+ }
+
+ return QMacStylePrivate::NoControl;
}
/**
@@ -1691,8 +1602,8 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co
// Carbon draw parts of the view outside the rect.
// So make the rect a bit smaller to compensate
// (I wish HIThemeGetButtonBackgroundBounds worked)
- if (cocoaWidget.first == Button_PopupButton) {
- switch (cocoaWidget.second) {
+ if (cocoaWidget.type == Button_PopupButton) {
+ switch (cocoaWidget.size) {
case QStyleHelper::SizeSmall:
innerBounds.origin.x += 3;
innerBounds.origin.y += 3;
@@ -1712,8 +1623,8 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co
innerBounds.size.width -= 5;
innerBounds.size.height -= 6;
}
- } else if (cocoaWidget.first == ComboBox) {
- switch (cocoaWidget.second) {
+ } else if (cocoaWidget.type == ComboBox) {
+ switch (cocoaWidget.size) {
case QStyleHelper::SizeSmall:
innerBounds.origin.x += 3;
innerBounds.origin.y += 3;
@@ -1742,85 +1653,43 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co
Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind
of combobox we choose to draw. This function calculates and returns this size.
*/
-QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi)
+QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const CocoaControl &cw)
{
- QRect ret = outerBounds;
- switch (bdi.kind){
- case kThemeComboBox:
- ret.adjust(5, 5, -22, -5);
- break;
- case kThemeComboBoxSmall:
- ret.adjust(4, 5, -18, 0);
- ret.setHeight(16);
- break;
- case kThemeComboBoxMini:
- ret.adjust(4, 5, -16, 0);
- ret.setHeight(13);
- break;
- case kThemePopupButton:
- ret.adjust(10, 2, -23, -4);
- break;
- case kThemePopupButtonSmall:
- ret.adjust(9, 3, -20, -3);
- break;
- case kThemePopupButtonMini:
- ret.adjust(8, 3, -19, 0);
- ret.setHeight(13);
- break;
- }
- return ret;
-}
-
-/**
- Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version,
- create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop
- it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly.
-*/
-void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p)
-{
- if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){
- // We have an unscaled combobox, or popup-button; use Carbon directly.
- const CGRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, cw);
- HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0);
- } else {
- QPixmap buffer;
- QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment));
- if (!QPixmapCache::find(key, buffer)) {
- CGRect innerBoundsSmallCombo = {{3, 3}, {29, 25}};
- buffer = QPixmap(35, 28);
- buffer.fill(Qt::transparent);
- QPainter buffPainter(&buffer);
- HIThemeDrawButton(&innerBoundsSmallCombo, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0);
- buffPainter.end();
- QPixmapCache::insert(key, buffer);
+ QRectF ret = outerBounds;
+ if (cw.type == ComboBox) {
+ switch (cw.size) {
+ case QStyleHelper::SizeLarge:
+ ret = ret.adjusted(0, 0, -28, 0).translated(3, 4.5);
+ ret.setHeight(16);
+ break;
+ case QStyleHelper::SizeSmall:
+ ret = ret.adjusted(0, 0, -24, 0).translated(3, 2);
+ ret.setHeight(14);
+ break;
+ case QStyleHelper::SizeMini:
+ ret = ret.adjusted(0, 0, -21, 0).translated(2, 3);
+ ret.setHeight(11);
+ break;
+ default:
+ break;
+ }
+ } else if (cw.type == Button_PopupButton) {
+ switch (cw.size) {
+ case QStyleHelper::SizeLarge:
+ ret.adjust(14, 1, -23, -4);
+ break;
+ case QStyleHelper::SizeSmall:
+ ret.adjust(13, 4, -20, -3);
+ break;
+ case QStyleHelper::SizeMini:
+ ret.adjust(12, 0, -19, 0);
+ ret.setHeight(13);
+ break;
+ default:
+ break;
}
-
- const int bwidth = 20;
- const int fwidth = 10;
- const int fheight = 10;
- int w = qRound(outerBounds.size.width);
- int h = qRound(outerBounds.size.height);
- int bstart = w - bwidth;
- int blower = fheight + 1;
- int flower = h - fheight;
- int sheight = flower - fheight;
- int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2;
-
- // Draw upper and lower gap
- p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight);
- p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight);
- // Draw left and right gap. Right gap is drawn top and bottom separatly
- p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1);
- p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1);
- p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1);
- // Draw arrow
- p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6);
- // Draw corners
- p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight);
- p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight);
- p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight);
- p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower);
}
+ return ret;
}
QMacStylePrivate::QMacStylePrivate()
@@ -1841,94 +1710,15 @@ QMacStylePrivate::~QMacStylePrivate()
[cell release];
}
-ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
-{
- ThemeDrawState tds = kThemeStateActive;
- if (flags & QStyle::State_Sunken) {
- tds = kThemeStatePressed;
- } else if (flags & QStyle::State_Active) {
- if (!(flags & QStyle::State_Enabled))
- tds = kThemeStateUnavailable;
- } else {
- if (flags & QStyle::State_Enabled)
- tds = kThemeStateInactive;
- else
- tds = kThemeStateUnavailableInactive;
- }
- return tds;
-}
-
- QMacStylePrivate::CocoaControl QMacStylePrivate::cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind)
-{
- CocoaControl w;
-
- switch (kind) {
- case kThemePopupButton:
- case kThemePopupButtonSmall:
- case kThemePopupButtonMini:
- w.first = Button_PopupButton;
- break;
- case kThemeComboBox:
- w.first = ComboBox;
- break;
- case kThemeArrowButton:
- w.first = Button_Disclosure;
- break;
- case kThemeCheckBox:
- case kThemeCheckBoxSmall:
- case kThemeCheckBoxMini:
- w.first = Button_CheckBox;
- break;
- case kThemeRadioButton:
- case kThemeRadioButtonSmall:
- case kThemeRadioButtonMini:
- w.first = Button_RadioButton;
- break;
- case kThemePushButton:
- case kThemePushButtonSmall:
- case kThemePushButtonMini:
- w.first = Button_PushButton;
- break;
- default:
- break;
- }
-
- switch (kind) {
- case kThemePushButtonSmall:
- case kThemePopupButtonSmall:
- case kThemeCheckBoxSmall:
- case kThemeRadioButtonSmall:
- w.second = QStyleHelper::SizeSmall;
- break;
- case kThemePushButtonMini:
- case kThemePopupButtonMini:
- case kThemeCheckBoxMini:
- case kThemeRadioButtonMini:
- w.second = QStyleHelper::SizeMini;
- break;
- default:
- w.second = QStyleHelper::SizeLarge;
- break;
- }
-
- return w;
-}
-
-static NSButton *makeButton(NSButtonType type, NSBezelStyle style)
-{
- NSButton *b = [[NSButton alloc] init];
- b.title = @"";
- b.buttonType = type;
- b.bezelStyle = style;
- return b;
-}
-
NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
{
- NSView *bv = cocoaControls.value(widget, nil);
+ if (widget.type == QMacStylePrivate::NoControl
+ || widget.size == QStyleHelper::SizeDefault)
+ return nil;
+ NSView *bv = cocoaControls.value(widget, nil);
if (!bv) {
- switch (widget.first) {
+ switch (widget.type) {
case Box: {
NSBox *bc = [[NSBox alloc] init];
bc.title = @"";
@@ -1939,31 +1729,30 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
break;
}
case Button_CheckBox:
- bv = makeButton(NSSwitchButton, NSRegularSquareBezelStyle);
- break;
case Button_Disclosure:
- bv = makeButton(NSOnOffButton, NSDisclosureBezelStyle);
+ case Button_PushButton:
+ case Button_RadioButton:
+ case Button_SquareButton: {
+ NSButton *bc = [[NSButton alloc] init];
+ bc.title = @"";
+ // See below for style and bezel setting.
+ bv = bc;
break;
+ }
case Button_PopupButton:
case Button_PullDown: {
NSPopUpButton *bc = [[NSPopUpButton alloc] init];
bc.title = @"";
- if (widget.first == Button_PullDown)
+ if (widget.type == Button_PullDown)
bc.pullsDown = YES;
bv = bc;
break;
}
- case Button_PushButton:
- bv = makeButton(NSMomentaryLightButton, NSRoundedBezelStyle);
- break;
- case Button_RadioButton:
- bv = makeButton(NSRadioButton, NSRegularSquareBezelStyle);
- break;
case Button_WindowClose:
case Button_WindowMiniaturize:
case Button_WindowZoom: {
const NSWindowButton button = [=] {
- switch (widget.first) {
+ switch (widget.type) {
case Button_WindowClose:
return NSWindowCloseButton;
case Button_WindowMiniaturize:
@@ -2030,7 +1819,7 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
if ([bv isKindOfClass:[NSControl class]]) {
auto *ctrl = static_cast<NSControl *>(bv);
- switch (widget.second) {
+ switch (widget.size) {
case QStyleHelper::SizeSmall:
ctrl.controlSize = NSSmallControlSize;
break;
@@ -2040,11 +1829,11 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
default:
break;
}
- } else if (widget.first == ProgressIndicator_Determinate ||
- widget.first == ProgressIndicator_Indeterminate) {
+ } else if (widget.type == ProgressIndicator_Determinate ||
+ widget.type == ProgressIndicator_Indeterminate) {
auto *pi = static_cast<NSProgressIndicator *>(bv);
- pi.indeterminate = (widget.first == ProgressIndicator_Indeterminate);
- switch (widget.second) {
+ pi.indeterminate = (widget.type == ProgressIndicator_Indeterminate);
+ switch (widget.size) {
case QStyleHelper::SizeSmall:
pi.controlSize = NSSmallControlSize;
break;
@@ -2059,6 +1848,16 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
cocoaControls.insert(widget, bv);
}
+ NSButtonType buttonType;
+ NSBezelStyle bezelStyle;
+ if (widget.getCocoaButtonTypeAndBezelStyle(&buttonType, &bezelStyle)) {
+ // FIXME We need to reset the button's type and
+ // bezel style properties, even when cached.
+ auto *button = static_cast<NSButton *>(bv);
+ button.buttonType = buttonType;
+ button.bezelStyle = bezelStyle;
+ }
+
return bv;
}
@@ -2066,7 +1865,7 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
{
NSCell *cell = cocoaCells[widget];
if (!cell) {
- switch (widget.first) {
+ switch (widget.type) {
case Stepper:
cell = [[NSStepperCell alloc] init];
break;
@@ -2081,7 +1880,7 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
break;
}
- switch (widget.second) {
+ switch (widget.size) {
case QStyleHelper::SizeSmall:
cell.controlSize = NSSmallControlSize;
break;
@@ -2098,28 +1897,13 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
return cell;
}
-void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const
+void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRectF &qtRect, QPainter *p,
+ __attribute__((noescape)) DrawRectBlock drawRectBlock) const
{
- QPoint offset;
- if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall))
- offset.setY(1);
- else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeMini))
- offset = QPoint(2, -1);
- else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeLarge))
- offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3);
- else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeSmall))
- offset = QPoint(2, 1);
- else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeMini))
- offset = QPoint(5, 0);
- else if (widget == CocoaControl(ComboBox, QStyleHelper::SizeLarge))
- offset = QPoint(3, 0);
-
QMacCGContext ctx(p);
setupNSGraphicsContext(ctx, YES);
- CGContextTranslateCTM(ctx, offset.x(), offset.y());
-
- const CGRect rect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
+ const CGRect rect = qtRect.toCGRect();
[backingStoreNSView addSubview:view];
view.frame = rect;
@@ -2137,148 +1921,6 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const
backingStoreNSView = window ? (NSView *)window->winId() : nil;
}
-void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, const CocoaControl &cw,
- QPainter *p, const QStyleOption *opt) const
-{
- int xoff = 0,
- yoff = 0,
- extraWidth = 0,
- extraHeight = 0,
- finalyoff = 0;
-
- const bool combo = opt->type == QStyleOption::SO_ComboBox;
- const bool editableCombo = bdi->kind == kThemeComboBox
- || bdi->kind == kThemeComboBoxSmall
- || bdi->kind == kThemeComboBoxMini;
- const bool button = opt->type == QStyleOption::SO_Button;
- const bool viewItem = opt->type == QStyleOption::SO_ViewItem;
- const bool pressed = bdi->state == kThemeStatePressed;
-
- if (button && pressed) {
- if (bdi->kind == kThemePushButton) {
- extraHeight = 2;
- } else if (bdi->kind == kThemePushButtonSmall) {
- xoff = 1;
- extraWidth = 2;
- extraHeight = 5;
- }
- }
-
- int devicePixelRatio = p->device()->devicePixelRatioF();
- int width = devicePixelRatio * (int(macRect.size.width) + extraWidth);
- int height = devicePixelRatio * (int(macRect.size.height) + extraHeight);
-
- if (width <= 0 || height <= 0)
- return; // nothing to draw
-
- QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_')
- + QString::number(bdi->value) + QLatin1Char('_')
- + (button ? QString::number(bdi->state) + QLatin1Char('_') : QString())
- + QLatin1Char('_') + QString::number(width) + QLatin1Char('_') + QString::number(height);
- QPixmap pm;
- if (!QPixmapCache::find(key, pm)) {
- QPixmap activePixmap(width, height);
- activePixmap.setDevicePixelRatio(devicePixelRatio);
- activePixmap.fill(Qt::transparent);
- {
- if (combo){
- // Carbon combos don't scale. Therefore we draw it
- // ourselves, if a scaled version is needed.
- QPainter tmpPainter(&activePixmap);
- QMacStylePrivate::drawCombobox(macRect, *bdi, cw, &tmpPainter);
- } else {
- QMacCGContext cg(&activePixmap);
- CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
- if (button && pressed)
- bdi->state = kThemeStateActive;
- else if (viewItem)
- bdi->state = kThemeStateInactive;
- HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
- }
- }
-
- if (!combo && !button && bdi->value == kThemeButtonOff) {
- pm = activePixmap;
- } else if ((combo && !editableCombo) || button) {
- CocoaControl cw = cocoaControlFromHIThemeButtonKind(bdi->kind);
- NSButton *bc = (NSButton *)cocoaControl(cw);
- [bc highlight:pressed];
- bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive;
- bc.allowsMixedState = YES;
- bc.state = bdi->value == kThemeButtonOn ? NSOnState :
- bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState;
- // The view frame may differ from what we pass to HITheme
- QRect rect = opt->rect;
- if (bdi->kind == kThemePopupButtonMini)
- rect.adjust(0, 0, -5, 0);
- drawNSViewInRect(cw, bc, rect, p);
- return;
- } else if (editableCombo || viewItem) {
- QImage image = activePixmap.toImage();
-
- for (int y = 0; y < height; ++y) {
- QRgb *scanLine = reinterpret_cast<QRgb *>(image.scanLine(y));
-
- for (int x = 0; x < width; ++x) {
- QRgb &pixel = scanLine[x];
- int gray = qRed(pixel); // We know the image is grayscale
- int alpha = qAlpha(pixel);
-
- if (gray == 128 && alpha == 128) {
- pixel = qRgba(255, 255, 255, 255);
- } else if (alpha == 0) {
- pixel = 0;
- } else {
- bool belowThreshold = (alpha * gray) / 255 + 255 - alpha < 128;
- gray = belowThreshold ? 0 : 2 * gray - 255;
- alpha = belowThreshold ? 0 : 2 * alpha - 255;
- pixel = qRgba(gray, gray, gray, alpha);
- }
- }
- }
- pm = QPixmap::fromImage(image);
- } else {
- QImage activeImage = activePixmap.toImage();
- QImage colorlessImage;
- {
- QPixmap colorlessPixmap(width, height);
- colorlessPixmap.setDevicePixelRatio(devicePixelRatio);
- colorlessPixmap.fill(Qt::transparent);
-
- QMacCGContext cg(&colorlessPixmap);
- CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
- int oldValue = bdi->value;
- bdi->value = kThemeButtonOff;
- HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
- bdi->value = oldValue;
- colorlessImage = colorlessPixmap.toImage();
- }
-
- for (int y = 0; y < height; ++y) {
- QRgb *colorlessScanLine = reinterpret_cast<QRgb *>(colorlessImage.scanLine(y));
- const QRgb *activeScanLine = reinterpret_cast<const QRgb *>(activeImage.scanLine(y));
-
- for (int x = 0; x < width; ++x) {
- QRgb &colorlessPixel = colorlessScanLine[x];
- QRgb activePixel = activeScanLine[x];
-
- if (activePixel != colorlessPixel) {
- int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)),
- qBlue(activePixel));
- QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel));
- if (qGray(newPixel) < qGray(colorlessPixel)
- || qAlpha(newPixel) > qAlpha(colorlessPixel))
- colorlessPixel = newPixel;
- }
- }
- }
- pm = QPixmap::fromImage(colorlessImage);
- }
- QPixmapCache::insert(key, pm);
- }
- p->drawPixmap(int(macRect.origin.x) - xoff, int(macRect.origin.y) + finalyoff, width / devicePixelRatio, height / devicePixelRatio , pm);
-}
-
QMacStyle::QMacStyle()
: QCommonStyle(*new QMacStylePrivate)
{
@@ -2458,6 +2100,10 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = 0;
break;
+ case PM_MenuButtonIndicator:
+ ret = toolButtonArrowSize;
+ break;
+
case QStyle::PM_MenuDesktopFrameWidth:
ret = 5;
break;
@@ -3164,7 +2810,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
const QWidget *w) const
{
Q_D(const QMacStyle);
- ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
QWindow *window = w && w->window() ? w->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
@@ -3233,17 +2878,17 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
QStyleOptionTabWidgetFrame twf;
twf.QStyleOption::operator=(*tbb);
twf.shape = tbb->shape;
- switch (getTabDirection(twf.shape)) {
- case kThemeTabNorth:
+ switch (QMacStylePrivate::tabDirection(twf.shape)) {
+ case QMacStylePrivate::North:
twf.rect = twf.rect.adjusted(0, 0, 0, 10);
break;
- case kThemeTabSouth:
+ case QMacStylePrivate::South:
twf.rect = twf.rect.adjusted(0, -10, 0, 0);
break;
- case kThemeTabWest:
+ case QMacStylePrivate::West:
twf.rect = twf.rect.adjusted(0, 0, 10, 0);
break;
- case kThemeTabEast:
+ case QMacStylePrivate::East:
twf.rect = twf.rect.adjusted(0, -10, 0, 0);
break;
}
@@ -3256,20 +2901,25 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase));
break;
case PE_FrameGroupBox:
- if (const QStyleOptionFrame *groupBox = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ if (const auto *groupBox = qstyleoption_cast<const QStyleOptionFrame *>(opt))
if (groupBox->features & QStyleOptionFrame::Flat) {
QCommonStyle::drawPrimitive(pe, groupBox, p, w);
- } else {
- const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeDefault);
- auto *box = static_cast<NSBox *>(d->cocoaControl(cw));
- d->drawNSViewInRect(cw, box, groupBox->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
- CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
- CGContextScaleCTM(ctx, 1, -1);
- [box drawRect:rect];
- });
+ break;
}
- }
+#if QT_CONFIG(tabwidget)
+ Q_FALLTHROUGH();
+ case PE_FrameTabWidget:
+#endif
+ {
+ const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge);
+ auto *box = static_cast<NSBox *>(d->cocoaControl(cw));
+ d->drawNSViewInRect(box, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
+ CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
+ CGContextScaleCTM(ctx, 1, -1);
+ [box drawRect:rect];
+ });
break;
+ }
case PE_IndicatorToolBarSeparator: {
QPainterPath path;
if (opt->state & State_Horizontal) {
@@ -3423,7 +3073,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0;
} ();
- d->drawNSViewInRect(cw, tb, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ d->drawNSViewInRect(tb, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
CGContextTranslateCTM(ctx, 0, vOffset);
[tb.cell drawInteriorWithFrame:rect inView:tb];
});
@@ -3434,7 +3084,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_IndicatorBranch: {
if (!(opt->state & State_Children))
break;
- const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge);
+ const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge);
NSButtonCell *triangleCell = static_cast<NSButtonCell *>(d->cocoaCell(cw));
[triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState];
bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
@@ -3476,7 +3126,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
tf.bezeled = YES;
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect();
- d->drawNSViewInRect(cw, tf, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
Q_UNUSED(ctx);
[tf.cell drawWithFrame:rect inView:tf];
});
@@ -3502,22 +3152,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
}
break;
-#if QT_CONFIG(tabwidget)
- case PE_FrameTabWidget:
- if (const QStyleOptionTabWidgetFrame *twf
- = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
- CGRect cgRect = twf->rect.toCGRect();
- HIThemeTabPaneDrawInfo tpdi;
- tpdi.version = qt_mac_hitheme_tab_version();
- tpdi.state = tds;
- tpdi.direction = getTabDirection(twf->shape);
- tpdi.size = kHIThemeTabSizeNormal;
- tpdi.kind = kHIThemeTabKindNormal;
- tpdi.adornment = kHIThemeTabPaneAdornmentNormal;
- HIThemeDrawTabPane(&cgRect, &tpdi, cg, kHIThemeOrientationNormal);
- }
- break;
-#endif
case PE_PanelScrollAreaCorner: {
const QBrush brush(opt->palette.brush(QPalette::Base));
p->fillRect(opt->rect, brush);
@@ -3582,7 +3216,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
}
}
-static inline QPixmap darkenPixmap(const QPixmap &pixmap)
+static QPixmap darkenPixmap(const QPixmap &pixmap)
{
QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
int imgh = img.height();
@@ -3605,8 +3239,6 @@ static inline QPixmap darkenPixmap(const QPixmap &pixmap)
return QPixmap::fromImage(img);
}
-
-
void QMacStylePrivate::setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const
{
if (vertical) {
@@ -3623,7 +3255,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const QWidget *w) const
{
Q_D(const QMacStyle);
- ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
QWindow *window = w && w->window() ? w->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
@@ -3795,120 +3426,81 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
break;
}
+ const bool hasFocus = btn->state & State_HasFocus;
+ const bool isActive = btn->state & State_Active;
+
// a focused auto-default button within an active window
// takes precedence over a normal default button
if ((btn->features & QStyleOptionButton::AutoDefaultButton)
- && (opt->state & State_Active)
- && (opt->state & State_HasFocus))
- d->autoDefaultButton = opt->styleObject;
- else if (d->autoDefaultButton == opt->styleObject)
+ && isActive && hasFocus)
+ d->autoDefaultButton = btn->styleObject;
+ else if (d->autoDefaultButton == btn->styleObject)
d->autoDefaultButton = nullptr;
- bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
- HIThemeButtonDrawInfo bdi;
- d->initHIThemePushButton(btn, w, tds, &bdi);
-
- if (!hasMenu) {
- // HITheme is not drawing a nice focus frame around buttons.
- // We'll do it ourselves further down.
- bdi.adornment &= ~kThemeAdornmentFocus;
-
- // We can't rely on an animation existing to test for the default look. That means a bit
- // more logic (notice that the logic is slightly different for the bevel and the label).
- if (tds == kThemeStateActive
- && (btn->features & QStyleOptionButton::DefaultButton
- || (btn->features & QStyleOptionButton::AutoDefaultButton
- && d->autoDefaultButton == btn->styleObject)))
- bdi.adornment |= kThemeAdornmentDefault;
- }
+ const bool isEnabled = btn->state & State_Enabled;
+ const bool isPressed = btn->state & State_Sunken;
+ const bool isHighlighted = isActive &&
+ ((btn->state & State_On)
+ || (btn->features & QStyleOptionButton::DefaultButton)
+ || (btn->features & QStyleOptionButton::AutoDefaultButton
+ && d->autoDefaultButton == btn->styleObject));
+ const bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
+ const auto ct = cocoaControlType(btn, w);
+ const auto cs = d->effectiveAquaSizeConstrain(btn, w);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
+ // Ensure same size and location as we used to have with HITheme.
+ // This is more convoluted than we initialy thought. See for example
+ // differences between plain and menu button frames.
+ const QRectF frameRect = cw.adjustedControlFrame(btn->rect);
+ pb.frame = frameRect.toCGRect();
+
+ pb.enabled = isEnabled;
+ [pb highlight:isPressed];
+ pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
+ d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ [pb.cell drawBezelWithFrame:r inView:pb.superview];
+ });
+ [pb highlight:NO];
+
+ if (hasMenu && cw.type == QMacStylePrivate::Button_SquareButton) {
+ // Using -[NSPopuButtonCell drawWithFrame:inView:] above won't do
+ // it right because we don't set the text in the native button.
+ const int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
+ const auto ir = frameRect.toRect();
+ int arrowYOffset = 0;
+#if 0
+ // FIXME What's this for again?
+ if (!w) {
+ // adjustment for Qt Quick Controls
+ arrowYOffset -= ir.top();
+ if (cw.second == QStyleHelper::SizeSmall)
+ arrowYOffset += 1;
+ }
+#endif
+ const auto ar = visualRect(btn->direction, ir, QRect(ir.right() - mbi - 6, ir.height() / 2 - arrowYOffset, mbi, mbi));
- // Unlike Carbon, we want the button to always be drawn inside its bounds.
- // Therefore, make the button a bit smaller, so that even if it got focus,
- // the focus 'shadow' will be inside.
- CGRect newRect = btn->rect.toCGRect();
- if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) {
- newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset;
- newRect.origin.y += QMacStylePrivate::PushButtonTopOffset;
- newRect.size.width -= QMacStylePrivate::PushButtonRightOffset;
- newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset;
- } else if (bdi.kind == kThemePushButtonMini) {
- newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2;
- newRect.origin.y += QMacStylePrivate::PushButtonTopOffset;
- newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4;
+ QStyleOption arrowOpt = *opt;
+ arrowOpt.rect = ar;
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, w);
}
- QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind);
- if (hasMenu)
- cw.first = QMacStylePrivate::Button_PullDown;
- if (hasMenu && bdi.kind != kThemeBevelButton) {
- NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw);
- [pdb highlight:(bdi.state == kThemeStatePressed)];
- pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive;
- QRect rect = opt->rect;
- rect.adjust(0, 0, cw.second == QStyleHelper::SizeSmall ? -4 : cw.second == QStyleHelper::SizeMini ? -9 : -6, 0);
- d->drawNSViewInRect(cw, pdb, rect, p, w != 0);
- } else if (hasMenu && bdi.state == kThemeStatePressed)
- d->drawColorlessButton(newRect, &bdi, cw, p, opt);
- else
- HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
if (btn->state & State_HasFocus) {
- CGRect focusRect = newRect;
- if (bdi.kind == kThemePushButton)
- focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about.
- else if (bdi.kind == kThemePushButtonMini)
- focusRect.size.height = 15; // Our QPushButton sizes are really weird
-
- if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) {
- if (bdi.kind == kThemePushButtonSmall) {
- focusRect = CGRectInset(focusRect, -1, 0);
- } else if (bdi.kind == kThemePushButtonMini) {
- focusRect = CGRectInset(focusRect, 1, 0);
- }
- } else {
- if (bdi.kind == kThemePushButton) {
- focusRect = CGRectInset(focusRect, 1, 1);
- } else if (bdi.kind == kThemePushButtonSmall) {
- focusRect = CGRectInset(focusRect, 0, 2);
- } else if (bdi.kind == kThemePushButtonMini) {
- focusRect = CGRectInset(focusRect, 2, 1);
- }
- }
-
- const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 3;
+ // TODO Remove and use QFocusFrame instead.
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w);
- const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height);
- d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius);
- }
-
- if (hasMenu && bdi.kind == kThemeBevelButton) {
- int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
- QRect ir = btn->rect;
- int arrowXOffset = bdi.kind == kThemePushButton ? 6 :
- bdi.kind == kThemePushButtonSmall ? 7 : 8;
- int arrowYOffset = bdi.kind == kThemePushButton ? 3 :
- bdi.kind == kThemePushButtonSmall ? 1 : 2;
- if (!w) {
- // adjustment for Qt Quick Controls
- arrowYOffset -= ir.top();
- if (bdi.kind == kThemePushButtonSmall)
- arrowYOffset += 1;
+ QRectF focusRect;
+ if (cw.type == QMacStylePrivate::Button_SquareButton) {
+ focusRect = frameRect;
+ } else {
+ focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]);
+ if (cw.type == QMacStylePrivate::Button_PushButton)
+ focusRect -= pushButtonShadowMargins[cw.size];
+ else if (cw.type == QMacStylePrivate::Button_PullDown)
+ focusRect -= pullDownButtonShadowMargins[cw.size];
}
- QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset,
- ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2);
- ar = visualRect(btn->direction, ir, ar);
- CGRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height());
-
- HIThemePopupArrowDrawInfo pdi;
- pdi.version = qt_mac_hitheme_version;
- pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds;
- pdi.orientation = kThemeArrowDown;
- if (bdi.kind == kThemePushButtonMini)
- pdi.size = kThemeArrow5pt;
- else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall)
- pdi.size = kThemeArrow7pt;
- HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal);
+ d->drawFocusRing(p, focusRect, hMargin, vMargin, cw);
}
}
break;
@@ -3919,14 +3511,20 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// windows style if it has an icon and text, then it should be more like a
// tab. So, cheat a little here. However, if it *is* only an icon
// the windows style works great, so just use that implementation.
+ const bool isEnabled = btn.state & State_Enabled;
const bool hasMenu = btn.features & QStyleOptionButton::HasMenu;
const bool hasIcon = !btn.icon.isNull();
const bool hasText = !btn.text.isEmpty();
+ const bool isActive = btn.state & State_Active;
+ const bool isPressed = btn.state & State_Sunken;
- if (!hasMenu) {
- if (tds == kThemeStatePressed
- || (tds == kThemeStateActive
- && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
+ const auto ct = cocoaControlType(&btn, w);
+
+ if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) {
+ if (isPressed
+ || (isActive && isEnabled
+ && ((btn.state & State_On)
+ || ((btn.features & QStyleOptionButton::DefaultButton) && !d->autoDefaultButton)
|| d->autoDefaultButton == btn.styleObject)))
btn.palette.setColor(QPalette::ButtonText, Qt::white);
}
@@ -3936,7 +3534,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
} else {
QRect freeContentRect = btn.rect;
QRect textRect = itemTextRect(
- btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text);
+ btn.fontMetrics, freeContentRect, Qt::AlignCenter, isEnabled, btn.text);
if (hasMenu) {
textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls
}
@@ -3945,7 +3543,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
int contentW = textRect.width();
if (hasMenu)
contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
- QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+ QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
if (mode == QIcon::Normal && btn.state & State_HasFocus)
mode = QIcon::Active;
// Decide if the icon is should be on or off:
@@ -3969,21 +3567,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (hasText) {
textRect = visualRect(btn.direction, freeContentRect, textRect);
proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette,
- (btn.state & State_Enabled), btn.text, QPalette::ButtonText);
+ isEnabled, btn.text, QPalette::ButtonText);
}
}
}
break;
+#if QT_CONFIG(combobox)
case CE_ComboBoxLabel:
- if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- QStyleOptionComboBox comboCopy = *cb;
+ if (const auto *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
+ auto comboCopy = *cb;
comboCopy.direction = Qt::LeftToRight;
+ // The rectangle will be adjusted to SC_ComboBoxEditField with comboboxEditBounds()
QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w);
}
break;
+#endif // #if QT_CONFIG(combobox)
#if QT_CONFIG(tabbar)
case CE_TabBarTabShape:
- if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
+ if (const auto *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
if (tabOpt->documentMode) {
p->save();
bool isUnified = false;
@@ -4000,111 +3601,198 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return;
}
- HIThemeTabDrawInfo tdi;
- tdi.version = 1;
- tdi.style = kThemeTabNonFront;
- tdi.direction = getTabDirection(tabOpt->shape);
- switch (d->aquaSizeConstrain(opt, w)) {
- case QStyleHelper::SizeDefault:
- case QStyleHelper::SizeLarge:
- tdi.size = kHIThemeTabSizeNormal;
- break;
- case QStyleHelper::SizeSmall:
- tdi.size = kHIThemeTabSizeSmall;
- break;
- case QStyleHelper::SizeMini:
- tdi.size = kHIThemeTabSizeMini;
- break;
- }
- bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast;
- QRect tabRect = tabOpt->rect;
-
- bool selected = tabOpt->state & State_Selected;
- if (selected) {
- if (!(tabOpt->state & State_Active))
- tdi.style = kThemeTabFrontUnavailable;
- else if (!(tabOpt->state & State_Enabled))
- tdi.style = kThemeTabFrontInactive;
- else
- tdi.style = kThemeTabFront;
- } else if (!(tabOpt->state & State_Active)) {
- tdi.style = kThemeTabNonFrontUnavailable;
- } else if (!(tabOpt->state & State_Enabled)) {
- tdi.style = kThemeTabNonFrontInactive;
- } else if (tabOpt->state & State_Sunken) {
- tdi.style = kThemeTabNonFrontPressed;
- }
- if (tabOpt->state & State_HasFocus)
- tdi.adornment = kHIThemeTabAdornmentFocus;
- else
- tdi.adornment = kHIThemeTabAdornmentNone;
- tdi.kind = kHIThemeTabKindNormal;
+ const bool isActive = tabOpt->state & State_Active;
+ const bool isEnabled = tabOpt->state & State_Enabled;
+ const bool isPressed = tabOpt->state & State_Sunken;
+ const bool isSelected = tabOpt->state & State_Selected;
+ const auto tabDirection = QMacStylePrivate::tabDirection(tabOpt->shape);
+ const bool verticalTabs = tabDirection == QMacStylePrivate::East
+ || tabDirection == QMacStylePrivate::West;
QStyleOptionTab::TabPosition tp = tabOpt->position;
QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition;
if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) {
+ if (tp == QStyleOptionTab::Beginning)
+ tp = QStyleOptionTab::End;
+ else if (tp == QStyleOptionTab::End)
+ tp = QStyleOptionTab::Beginning;
+
if (sp == QStyleOptionTab::NextIsSelected)
sp = QStyleOptionTab::PreviousIsSelected;
else if (sp == QStyleOptionTab::PreviousIsSelected)
sp = QStyleOptionTab::NextIsSelected;
- switch (tp) {
- case QStyleOptionTab::Beginning:
- tp = QStyleOptionTab::End;
- break;
- case QStyleOptionTab::End:
- tp = QStyleOptionTab::Beginning;
- break;
- default:
- break;
- }
}
- bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22);
+ // Alas, NSSegmentedControl and NSSegmentedCell are letting us down.
+ // We're not able to draw it at will, either calling -[drawSegment:
+ // inFrame:withView:], -[drawRect:] or anything in between. Besides,
+ // there's no public API do draw the pressed state, AFAICS. We'll use
+ // a push NSButton instead and clip the CGContext.
+
+ const auto cs = d->effectiveAquaSizeConstrain(opt, w);
+ // Extra hacks to get the proper pressed appreance when not selected or selected and inactive
+ const bool needsInactiveHack = (!isActive && isSelected);
+ const auto ct = !needsInactiveHack && (isSelected || tp == QStyleOptionTab::OnlyOneTab) ?
+ QMacStylePrivate::Button_PushButton :
+ QMacStylePrivate::Button_PopupButton;
+ const bool isPopupButton = ct == QMacStylePrivate::Button_PopupButton;
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
+
+ auto vOffset = isPopupButton ? 1 : 2;
+ if (tabDirection == QMacStylePrivate::East)
+ vOffset -= 1;
+ const auto outerAdjust = isPopupButton ? 1 : 4;
+ const auto innerAdjust = isPopupButton ? 20 : 10;
+ QRectF frameRect = tabOpt->rect;
+ if (verticalTabs)
+ frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width());
+ // Adjust before clipping
+ frameRect = frameRect.translated(0, vOffset);
switch (tp) {
case QStyleOptionTab::Beginning:
- tdi.position = kHIThemeTabPositionFirst;
- if (sp != QStyleOptionTab::NextIsSelected || stretchTabs)
- tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
+ // Pressed state hack: tweak adjustments in preparation for flip below
+ if (!isSelected && tabDirection == QMacStylePrivate::West)
+ frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
+ else
+ frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
break;
case QStyleOptionTab::Middle:
- tdi.position = kHIThemeTabPositionMiddle;
- if (selected)
- tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
- if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected.
- tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
+ frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0);
break;
case QStyleOptionTab::End:
- tdi.position = kHIThemeTabPositionLast;
- if (selected)
- tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
+ // Pressed state hack: tweak adjustments in preparation for flip below
+ if (isSelected || tabDirection == QMacStylePrivate::West)
+ frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
+ else
+ frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
break;
case QStyleOptionTab::OnlyOneTab:
- tdi.position = kHIThemeTabPositionOnly;
+ frameRect = frameRect.adjusted(-outerAdjust, 0, outerAdjust, 0);
break;
}
- // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves.
- if (stretchTabs) {
- CGRect cgRect = CGRectMake(0, 0, 23, 23);
- QPixmap pm(23, 23);
- pm.fill(Qt::transparent);
- {
- QMacCGContext pmcg(&pm);
- HIThemeDrawTab(&cgRect, &tdi, pmcg, kHIThemeOrientationNormal, 0);
+ pb.frame = frameRect.toCGRect();
+
+ pb.enabled = isEnabled;
+ [pb highlight:isPressed];
+ // Set off state when inactive. See needsInactiveHack for when it's selected
+ pb.state = (isActive && isSelected && !isPressed) ? NSOnState : NSOffState;
+
+ const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) {
+ CGContextClipToRect(ctx, opt->rect.toCGRect());
+ if (!isSelected || needsInactiveHack) {
+ // Final stage of the pressed state hack: flip NSPopupButton rendering
+ if (!verticalTabs && tp == QStyleOptionTab::End) {
+ CGContextTranslateCTM(ctx, opt->rect.right(), 0);
+ CGContextScaleCTM(ctx, -1, 1);
+ CGContextTranslateCTM(ctx, -frameRect.left(), 0);
+ } else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) {
+ CGContextScaleCTM(ctx, 1, -1);
+ CGContextTranslateCTM(ctx, 0, -frameRect.right());
+ } else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) {
+ CGContextTranslateCTM(ctx, 0, opt->rect.bottom());
+ CGContextScaleCTM(ctx, 1, -1);
+ CGContextTranslateCTM(ctx, 0, -frameRect.left());
+ }
+ }
+
+ // Rotate and translate CTM when vertical
+ // On macOS: positive angle is CW, negative is CCW
+ if (tabDirection == QMacStylePrivate::West) {
+ CGContextTranslateCTM(ctx, 0, frameRect.right());
+ CGContextRotateCTM(ctx, -M_PI_2);
+ CGContextTranslateCTM(ctx, -frameRect.left(), 0);
+ } else if (tabDirection == QMacStylePrivate::East) {
+ CGContextTranslateCTM(ctx, opt->rect.right(), 0);
+ CGContextRotateCTM(ctx, M_PI_2);
}
- QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7);
+
+ [pb.cell drawBezelWithFrame:r inView:pb.superview];
+ };
+
+ if (needsInactiveHack) {
+ // First, render tab as non-selected tab on a pixamp
+ const qreal pixelRatio = p->device()->devicePixelRatioF();
+ QImage tabPixmap(opt->rect.size() * pixelRatio, QImage::Format_ARGB32_Premultiplied);
+ tabPixmap.setDevicePixelRatio(pixelRatio);
+ tabPixmap.fill(Qt::transparent);
+ QPainter tabPainter(&tabPixmap);
+ d->drawNSViewInRect(pb, frameRect, &tabPainter, ^(CGContextRef ctx, const CGRect &r) {
+ CGContextTranslateCTM(ctx, -opt->rect.left(), -opt->rect.top());
+ drawBezelBlock(ctx, r);
+ });
+ tabPainter.end();
+
+ // Then, darken it with the proper shade of gray
+ const qreal inactiveGray = 0.898; // As measured
+ const int inactiveGray8 = qRound(inactiveGray * 255.0);
+ const QRgb inactiveGrayRGB = qRgb(inactiveGray8, inactiveGray8, inactiveGray8);
+ for (int l = 0; l < tabPixmap.height(); ++l) {
+ auto *line = reinterpret_cast<QRgb*>(tabPixmap.scanLine(l));
+ for (int i = 0; i < tabPixmap.width(); ++i) {
+ if (qAlpha(line[i]) == 255) {
+ line[i] = inactiveGrayRGB;
+ } else if (qAlpha(line[i]) > 128) {
+ const int g = qRound(inactiveGray * qRed(line[i]));
+ line[i] = qRgba(g, g, g, qAlpha(line[i]));
+ }
+ }
+ }
+
+ // Finally, draw the tab pixmap on the current painter
+ p->drawImage(opt->rect, tabPixmap);
} else {
- CGRect cgRect = tabRect.toCGRect();
- HIThemeDrawTab(&cgRect, &tdi, cg, kHIThemeOrientationNormal, 0);
+ d->drawNSViewInRect(pb, frameRect, p, drawBezelBlock);
+ }
+
+ if (!isSelected && sp != QStyleOptionTab::NextIsSelected
+ && tp != QStyleOptionTab::End
+ && tp != QStyleOptionTab::OnlyOneTab) {
+ static const QPen separatorPen(Qt::black, 1.0);
+ p->save();
+ p->setOpacity(isEnabled ? 0.105 : 0.06); // As measured
+ p->setPen(separatorPen);
+ if (tabDirection == QMacStylePrivate::West) {
+ p->drawLine(QLineF(opt->rect.left() + 1.5, opt->rect.bottom(),
+ opt->rect.right() - 0.5, opt->rect.bottom()));
+ } else if (tabDirection == QMacStylePrivate::East) {
+ p->drawLine(QLineF(opt->rect.left(), opt->rect.bottom(),
+ opt->rect.right() - 0.5, opt->rect.bottom()));
+ } else {
+ p->drawLine(QLineF(opt->rect.right(), opt->rect.top() + 1.0,
+ opt->rect.right(), opt->rect.bottom() - 0.5));
+ }
+ p->restore();
+ }
+
+ // TODO Needs size adjustment to fit the focus ring
+ if (tabOpt->state & State_HasFocus) {
+ QMacStylePrivate::CocoaControlType focusRingType;
+ switch (tp) {
+ case QStyleOptionTab::Beginning:
+ focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_Last
+ : QMacStylePrivate::SegmentedControl_First;
+ break;
+ case QStyleOptionTab::Middle:
+ focusRingType = QMacStylePrivate::SegmentedControl_Middle;
+ break;
+ case QStyleOptionTab::End:
+ focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_First
+ : QMacStylePrivate::SegmentedControl_Last;
+ break;
+ case QStyleOptionTab::OnlyOneTab:
+ focusRingType = QMacStylePrivate::SegmentedControl_Single;
+ break;
+ }
}
}
break;
case CE_TabBarTabLabel:
- if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
+ if (const auto *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QStyleOptionTab myTab = *tab;
- const bool verticalTabs = tab->shape == QTabBar::RoundedWest
- || tab->shape == QTabBar::RoundedEast
- || tab->shape == QTabBar::TriangularWest
- || tab->shape == QTabBar::TriangularEast;
+ const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape);
+ const bool verticalTabs = tabDirection == QMacStylePrivate::East
+ || tabDirection == QMacStylePrivate::West;
// Check to see if we use have the same as the system font
// (QComboMenuItem is internal and should never be seen by the
@@ -4179,20 +3867,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return QMacStylePrivate::Button_CheckBox;
if (ffw->inherits("QRadioButton"))
return QMacStylePrivate::Button_RadioButton;
+ if (ffw->inherits("QLineEdit") || ffw->inherits("QTextEdit"))
+ return QMacStylePrivate::TextField;
}
return QMacStylePrivate::Box; // Not really, just make it the default
} ();
+ const auto cs = ffw ? (ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini :
+ ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall :
+ QStyleHelper::SizeLarge) :
+ QStyleHelper::SizeLarge;
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);
- if (ct == QMacStylePrivate::Box) {
- d->drawFocusRing(p, opt->rect, hMargin, vMargin);
- } else if (ffw) {
- const auto cs = ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini :
- ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall :
- QStyleHelper::SizeLarge;
- d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs));
- }
+ d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs));
break; }
case CE_MenuEmptyArea:
// Skip: PE_PanelMenu fills in everything
@@ -4463,7 +4150,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize);
auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw));
- d->drawNSViewInRect(cw, pi, rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx, const CGRect &rect) {
d->setupVerticalInvertedXform(ctx, reverse, vertical, rect);
pi.minValue = pb->minimum;
pi.maxValue = pb->maximum;
@@ -4513,7 +4200,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
auto *sv = static_cast<NSSplitView *>(d->cocoaControl(cw));
sv.frame = opt->rect.toCGRect();
- d->drawNSViewInRect(cw, sv, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
[sv drawDividerInRect:rect];
});
} else {
@@ -4654,13 +4341,20 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_PushButtonContents:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- // Unlike Carbon, we want the button to always be drawn inside its bounds.
- // Therefore, the button is a bit smaller, so that even if it got focus,
- // the focus 'shadow' will be inside. Adjust the content rect likewise.
- HIThemeButtonDrawInfo bdi;
- d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi);
- CGRect contentRect = d->pushButtonContentBounds(btn, &bdi);
- rect = QRectF::fromCGRect(contentRect).toRect();
+ // Comment from the old HITheme days:
+ // "Unlike Carbon, we want the button to always be drawn inside its bounds.
+ // Therefore, the button is a bit smaller, so that even if it got focus,
+ // the focus 'shadow' will be inside. Adjust the content rect likewise."
+ // In the future, we should consider using -[NSCell titleRectForBounds:].
+ // Since it requires configuring the NSButton fully, i.e. frame, image,
+ // title and font, we keep things more manual until we are more familiar
+ // with side effects when changing NSButton state.
+ const auto ct = cocoaControlType(btn, widget);
+ const auto cs = d->effectiveAquaSizeConstrain(btn, widget);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ const auto frameRect = cw.adjustedControlFrame(btn->rect);
+ const auto titleMargins = cw.titleMargins();
+ rect = (frameRect - titleMargins).toRect();
}
break;
case SE_HeaderLabel: {
@@ -4706,23 +4400,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
rect = opt->rect;
break;
case SE_TreeViewDisclosureItem: {
- CGRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(),
- opt->rect.width(), opt->rect.height());
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = kThemeStateActive;
- bdi.kind = kThemeDisclosureButton;
- bdi.value = kThemeDisclosureRight;
- bdi.adornment = kThemeAdornmentNone;
- CGRect contentRect;
- HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect);
- QCFType<HIShapeRef> shape;
- CGRect outRect;
- HIThemeGetButtonShape(&inRect, &bdi, &shape);
- HIShapeGetBounds(shape, &outRect);
- rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y),
- int(contentRect.origin.x - outRect.origin.x + DisclosureOffset),
- int(outRect.size.height));
+ rect = opt->rect;
+ // As previously returned by HIThemeGetButtonContentBounds
+ rect.setLeft(rect.left() + 2 + DisclosureOffset);
break;
}
#if QT_CONFIG(tabwidget)
@@ -4768,20 +4448,19 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_TabWidgetTabContents:
rect = QCommonStyle::subElementRect(sr, opt, widget);
- if (const QStyleOptionTabWidgetFrame *twf
- = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ if (const auto *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
if (twf->lineWidth != 0) {
- switch (getTabDirection(twf->shape)) {
- case kThemeTabNorth:
+ switch (QMacStylePrivate::tabDirection(twf->shape)) {
+ case QMacStylePrivate::North:
rect.adjust(+1, +14, -1, -1);
break;
- case kThemeTabSouth:
+ case QMacStylePrivate::South:
rect.adjust(+1, +1, -1, -14);
break;
- case kThemeTabWest:
+ case QMacStylePrivate::West:
rect.adjust(+14, +1, -1, -1);
break;
- case kThemeTabEast:
+ case QMacStylePrivate::East:
rect.adjust(+1, +1, -14, -1);
}
}
@@ -5121,16 +4800,15 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
return rect;
}
-static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg)
+void QMacStylePrivate::drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const
{
- QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5);
- HIThemePopupArrowDrawInfo padi;
- padi.version = qt_mac_hitheme_version;
- padi.state = tds;
- padi.orientation = kThemeArrowDown;
- padi.size = kThemeArrow7pt;
- CGRect cgRect = arrowRect.toCGRect();
- HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal);
+ Q_Q(const QMacStyle);
+ QStyleOption arrowOpt = *opt;
+ arrowOpt.rect = QRect(opt->rect.right() - (toolButtonArrowSize + toolButtonArrowMargin),
+ opt->rect.bottom() - (toolButtonArrowSize + toolButtonArrowMargin),
+ toolButtonArrowSize,
+ toolButtonArrowSize);
+ q->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p);
}
void QMacStylePrivate::setupNSGraphicsContext(CGContextRef cg, bool flipped) const
@@ -5152,7 +4830,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const QWidget *widget) const
{
Q_D(const QMacStyle);
- ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
@@ -5368,7 +5045,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[slider.cell startTrackingAt:pressPoint inView:slider];
}
- d->drawNSViewInRect(cw, slider, opt->rect, p, widget != 0, ^(CGContextRef ctx, const CGRect &rect) {
+ d->drawNSViewInRect(slider, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
if (isHorizontal && sl->upsideDown) {
CGContextTranslateCTM(ctx, rect.size.width, 0);
CGContextScaleCTM(ctx, -1, 1);
@@ -5506,25 +5183,69 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
break;
#endif
+#if QT_CONFIG(combobox)
case CC_ComboBox:
- if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
- HIThemeButtonDrawInfo bdi;
- QMacStylePrivate::CocoaControl cw;
- d->initComboboxBdi(combo, &bdi, &cw, widget, tds);
- CGRect rect = combo->rect.toCGRect();
- if (combo->editable)
- rect.origin.y += tds == kThemeStateInactive ? 1 : 2;
- if (tds != kThemeStateInactive)
- QMacStylePrivate::drawCombobox(rect, bdi, cw, p);
- else if (!widget && combo->editable) {
- const auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind);
- NSView *cb = d->cocoaControl(cw);
- QRect r = combo->rect.adjusted(3, 0, 0, 0);
- d->drawNSViewInRect(cw, cb, r, p, widget != 0);
- } else
- d->drawColorlessButton(rect, &bdi, cw, p, opt);
+ if (const auto *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
+ const bool isEnabled = combo->state & State_Enabled;
+ const bool isPressed = combo->state & State_Sunken;
+
+ const auto ct = cocoaControlType(combo, widget);
+ const auto cs = d->effectiveAquaSizeConstrain(combo, widget);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ auto *cc = static_cast<NSControl *>(d->cocoaControl(cw));
+ cc.enabled = isEnabled;
+ QRectF frameRect = cw.adjustedControlFrame(combo->rect);;
+ if (cw.type == QMacStylePrivate::Button_PopupButton) {
+ // Non-editable QComboBox
+ auto *pb = static_cast<NSPopUpButton *>(cc);
+ // FIXME Old offsets. Try to move to adjustedControlFrame()
+ if (cw.size == QStyleHelper::SizeSmall) {
+ frameRect = frameRect.translated(0, 1);
+ } else if (cw.size == QStyleHelper::SizeMini) {
+ // Same 0.5 pt misalignment as AppKit and fit the focus ring
+ frameRect = frameRect.translated(2, -0.5);
+ }
+ pb.frame = frameRect.toCGRect();
+ [pb highlight:isPressed];
+ d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ [pb.cell drawBezelWithFrame:r inView:pb.superview];
+ });
+ } else if (cw.type == QMacStylePrivate::ComboBox) {
+ // Editable QComboBox
+ auto *cb = static_cast<NSComboBox *>(cc);
+ const auto frameRect = cw.adjustedControlFrame(combo->rect);
+ cb.frame = frameRect.toCGRect();
+#if !QT_CONFIG(appstore_compliant)
+ static_cast<NSComboBoxCell *>(cc.cell).qt_buttonCell.highlighted = isPressed;
+#else
+ // TODO Render to pixmap and darken the button manually
+#endif
+ d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ // FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case
+ [cb.cell drawWithFrame:r inView:cb];
+ });
+ }
+
+ if (combo->state & State_HasFocus) {
+ // TODO Remove and use QFocusFrame instead.
+ const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, combo, widget);
+ const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, combo, widget);
+ QRectF focusRect;
+ if (cw.type == QMacStylePrivate::Button_PopupButton) {
+ focusRect = QRectF::fromCGRect([cc alignmentRectForFrame:cc.frame]);
+ focusRect -= pullDownButtonShadowMargins[cw.size];
+ if (cw.size == QStyleHelper::SizeSmall)
+ focusRect = focusRect.translated(0, 1);
+ else if (cw.size == QStyleHelper::SizeMini)
+ focusRect = focusRect.translated(2, -1);
+ } else if (cw.type == QMacStylePrivate::ComboBox) {
+ focusRect = frameRect - comboBoxFocusRingMargins[cw.size];
+ }
+ d->drawFocusRing(p, focusRect, hMargin, vMargin, cw);
+ }
}
break;
+#endif // QT_CONFIG(combobox)
case CC_TitleBar:
if (const auto *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
const bool isActive = (titlebar->state & State_Active)
@@ -5536,12 +5257,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// FIXME A single drawPath() with 0-sized pen
// doesn't look as good as this double fillPath().
- const auto outterFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height()));
- QPainterPath outterFramePath = d->windowPanelPath(outterFrameRect);
- p->fillPath(outterFramePath, opt->palette.dark());
+ const auto outerFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height()));
+ QPainterPath outerFramePath = d->windowPanelPath(outerFrameRect);
+ p->fillPath(outerFramePath, opt->palette.dark());
const auto frameAdjust = 1.0 / p->device()->devicePixelRatioF();
- const auto innerFrameRect = outterFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
+ const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect);
if (isActive) {
QLinearGradient g;
@@ -5577,7 +5298,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
auto *wbCell = static_cast<NSButtonCell *>(wb.cell);
[wbCell drawWithFrame:rect inView:wb];
};
- d->drawNSViewInRect(cw, wb, buttonRect, p, widget != nullptr, drawBlock);
+ d->drawNSViewInRect(wb, buttonRect, p, drawBlock);
}
}
@@ -5639,7 +5360,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
} else if ((tb->features & QStyleOptionToolButton::HasMenu)
&& (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
- drawToolbarButtonArrow(tb->rect, tds, cg);
+ d->drawToolbarButtonArrow(tb, p);
}
if (tb->state & State_On) {
QWindow *window = 0;
@@ -5664,81 +5385,45 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
} else
#endif // QT_NO_ACCESSIBILITY
{
- ThemeButtonKind bkind = kThemeBevelButton;
- switch (d->aquaSizeConstrain(opt, widget)) {
- case QStyleHelper::SizeDefault:
- case QStyleHelper::SizeLarge:
- bkind = kThemeBevelButton;
- break;
- case QStyleHelper::SizeMini:
- case QStyleHelper::SizeSmall:
- bkind = kThemeSmallBevelButton;
- break;
- }
-
- QRect button, menuarea;
- button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
- menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
- State bflags = tb->state,
- mflags = tb->state;
+ auto bflags = tb->state;
if (tb->subControls & SC_ToolButton)
bflags |= State_Sunken;
+ auto mflags = tb->state;
if (tb->subControls & SC_ToolButtonMenu)
mflags |= State_Sunken;
if (tb->subControls & SC_ToolButton) {
if (bflags & (State_Sunken | State_On | State_Raised)) {
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = tds;
- bdi.adornment = kThemeAdornmentNone;
- bdi.kind = bkind;
- bdi.value = kThemeButtonOff;
- if (tb->state & State_HasFocus)
- bdi.adornment = kThemeAdornmentFocus;
- if (tb->state & State_Sunken)
- bdi.state = kThemeStatePressed;
- if (tb->state & State_On)
- bdi.value = kThemeButtonOn;
-
- CGRect myRect, macRect;
- myRect = CGRectMake(tb->rect.x(), tb->rect.y(),
- tb->rect.width(), tb->rect.height());
- HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
-
- const auto offMargins = QMargins(int(myRect.origin.x - macRect.origin.x),
- int(myRect.origin.y - macRect.origin.y),
- int(macRect.size.width - myRect.size.width),
- int(macRect.size.height - myRect.size.height));
- myRect = button.marginsRemoved(offMargins).toCGRect();
- HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0);
+ const bool isEnabled = tb->state & State_Enabled;
+ const bool isPressed = tb->state & State_Sunken;
+ const bool isHighlighted = (tb->state & State_Active) && (tb->state & State_On);
+ const auto ct = QMacStylePrivate::Button_PushButton;
+ const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
+ pb.bezelStyle = NSShadowlessSquareBezelStyle; // TODO Use NSTexturedRoundedBezelStyle in the future.
+ pb.frame = opt->rect.toCGRect();
+ pb.buttonType = NSPushOnPushOffButton;
+ pb.enabled = isEnabled;
+ [pb highlight:isPressed];
+ pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
+ const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
+ d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
+ [pb.cell drawBezelWithFrame:rect inView:pb];
+ });
}
}
if (tb->subControls & SC_ToolButtonMenu) {
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = tds;
- bdi.value = kThemeButtonOff;
- bdi.adornment = kThemeAdornmentNone;
- bdi.kind = bkind;
- if (tb->state & State_HasFocus)
- bdi.adornment = kThemeAdornmentFocus;
- if (tb->state & (State_On | State_Sunken)
- || (tb->activeSubControls & SC_ToolButtonMenu))
- bdi.state = kThemeStatePressed;
- CGRect cgRect = menuarea.toCGRect();
- HIThemeDrawButton(&cgRect, &bdi, cg, kHIThemeOrientationNormal, 0);
- QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8);
- HIThemePopupArrowDrawInfo padi;
- padi.version = qt_mac_hitheme_version;
- padi.state = tds;
- padi.orientation = kThemeArrowDown;
- padi.size = kThemeArrow7pt;
- cgRect = r.toCGRect();
- HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal);
+ const auto menuRect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
+ QStyleOption arrowOpt = *tb;
+ arrowOpt.rect = QRect(menuRect.x() + ((menuRect.width() - toolButtonArrowSize) / 2),
+ menuRect.height() - (toolButtonArrowSize + toolButtonArrowMargin),
+ toolButtonArrowSize,
+ toolButtonArrowSize);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
} else if (tb->features & QStyleOptionToolButton::HasMenu) {
- drawToolbarButtonArrow(tb->rect, tds, cg);
+ d->drawToolbarButtonArrow(tb, p);
}
QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
@@ -5979,32 +5664,29 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
break;
case CC_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- HIThemeButtonDrawInfo bdi;
- QMacStylePrivate::CocoaControl cw;
- d->initComboboxBdi(combo, &bdi, &cw, widget, d->getDrawState(opt->state));
+ const auto ct = cocoaControlType(combo, widget);
+ const auto cs = d->effectiveAquaSizeConstrain(combo, widget);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ const auto editRect = QMacStylePrivate::comboboxEditBounds(cw.adjustedControlFrame(combo->rect), cw);
switch (sc) {
case SC_ComboBoxEditField:{
- ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
- // 10.10 and above need a slight shift
- ret.setHeight(ret.height() - 1);
+ ret = editRect.toAlignedRect();
break; }
case SC_ComboBoxArrow:{
- ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
+ ret = editRect.toAlignedRect();
ret.setX(ret.x() + ret.width());
ret.setWidth(combo->rect.right() - ret.right());
break; }
case SC_ComboBoxListBoxPopup:{
if (combo->editable) {
const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), cw);
- QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
const int comboTop = combo->rect.top();
ret = QRect(qRound(inner.origin.x),
comboTop,
qRound(inner.origin.x - combo->rect.left() + inner.size.width),
editRect.bottom() - comboTop + 2);
} else {
- QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
ret = QRect(combo->rect.x() + 4 - 11,
combo->rect.y() + 1,
editRect.width() + 10 + 11,
@@ -6211,7 +5893,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_SpinBox:
if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
const int buttonWidth = 20; // FIXME Use subControlRect()
- sz += QSize(buttonWidth, -3);
+ sz += QSize(buttonWidth, 0);
}
break;
#endif
@@ -6257,7 +5939,9 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget);
const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap;
- if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) {
+ const auto tabDirection = QMacStylePrivate::tabDirection(twf->shape);
+ if (tabDirection == QMacStylePrivate::North
+ || tabDirection == QMacStylePrivate::South) {
extra = QSize(2, gapBetweenTabbarAndStackWidget + 1);
} else {
extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2);
@@ -6269,18 +5953,17 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#if QT_CONFIG(tabbar)
case QStyle::CT_TabBarTab:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- const QStyleHelper::WidgetSizePolicy AquaSize = d->aquaSizeConstrain(opt, widget);
const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont))
|| !QApplication::desktopSettingsAware();
- ThemeTabDirection ttd = getTabDirection(tab->shape);
- bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
- if (vertTabs)
+ const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape);
+ const bool verticalTabs = tabDirection == QMacStylePrivate::East
+ || tabDirection == QMacStylePrivate::West;
+ if (verticalTabs)
sz = sz.transposed();
+
int defaultTabHeight;
- int extraHSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget);
- QFontMetrics fm = opt->fontMetrics;
- switch (AquaSize) {
- case QStyleHelper::SizeDefault:
+ const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
+ switch (cs) {
case QStyleHelper::SizeLarge:
if (tab->documentMode)
defaultTabHeight = 24;
@@ -6293,19 +5976,21 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case QStyleHelper::SizeMini:
defaultTabHeight = 16;
break;
+ default:
+ break;
}
- bool setWidth = false;
- if (differentFont || !tab->icon.isNull()) {
- sz.rheight() = qMax(defaultTabHeight, sz.height());
- } else {
- QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text);
- sz.rheight() = qMax(defaultTabHeight, textSize.height());
+
+ const bool widthSet = !differentFont && tab->icon.isNull();
+ if (widthSet) {
+ const auto textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, tab->text);
sz.rwidth() = textSize.width();
- setWidth = true;
+ sz.rheight() = qMax(defaultTabHeight, textSize.height());
+ } else {
+ sz.rheight() = qMax(defaultTabHeight, sz.height());
}
- sz.rwidth() += extraHSpace;
+ sz.rwidth() += proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget);
- if (vertTabs)
+ if (verticalTabs)
sz = sz.transposed();
int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height());
@@ -6325,27 +6010,44 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
widgetHeight += tab->rightButtonSize.height();
}
- if (vertTabs) {
- sz.setHeight(sz.height() + widgetHeight + padding);
+ if (verticalTabs) {
sz.setWidth(qMax(sz.width(), maxWidgetWidth));
+ sz.setHeight(sz.height() + widgetHeight + padding);
} else {
- if (setWidth)
+ if (widthSet)
sz.setWidth(sz.width() + widgetWidth + padding);
sz.setHeight(qMax(sz.height(), maxWidgetHeight));
}
}
break;
#endif
- case QStyle::CT_PushButton:
+ case QStyle::CT_PushButton: {
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt))
+ if (btn->features & QStyleOptionButton::CommandLinkButton)
+ return QCommonStyle::sizeFromContents(ct, opt, sz, widget);
+
// By default, we fit the contents inside a normal rounded push button.
// Do this by add enough space around the contents so that rounded
// borders (including highlighting when active) will show.
- sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12;
- if (opt->state & QStyle::State_Small)
- sz.rheight() += 14;
+ // TODO Use QFocusFrame and get rid of these horrors.
+ QSize macsz;
+ const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget, CT_PushButton, sz, &macsz);
+ // FIXME See comment in CT_PushButton case in qt_aqua_get_known_size().
+ if (macsz.width() != -1)
+ sz.setWidth(macsz.width());
else
- sz.rheight() += 4;
+ sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12;
+ // All values as measured from HIThemeGetButtonBackgroundBounds()
+ if (controlSize != QStyleHelper::SizeMini)
+ sz.rwidth() += 12; // We like 12 over here.
+ if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16)
+ sz.rheight() += pushButtonDefaultHeight[QStyleHelper::SizeLarge] - 16;
+ else if (controlSize == QStyleHelper::SizeMini)
+ sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this.
+ else
+ sz.setHeight(pushButtonDefaultHeight[controlSize]);
break;
+ }
case QStyle::CT_MenuItem:
if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
int maxpmw = mi->maxIconWidth;
@@ -6407,13 +6109,35 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
sz.rwidth() += 10;
sz.rheight() += 10;
return sz;
- case CT_ComboBox: {
- sz.rwidth() += 50;
- const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
- if (cb && !cb->editable)
- sz.rheight() += 2;
+ case CT_ComboBox:
+ if (const auto *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
+ const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget);
+ if (!cb->editable) {
+ // Same as CT_PushButton, because we have to fit the focus
+ // ring and a non-editable combo box is a NSPopUpButton.
+ sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12;
+ // All values as measured from HIThemeGetButtonBackgroundBounds()
+ if (controlSize != QStyleHelper::SizeMini)
+ sz.rwidth() += 12; // We like 12 over here.
+#if 0
+ // TODO Maybe support square combo boxes
+ if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16)
+ sz.rheight() += popupButtonDefaultHeight[QStyleHelper::SizeLarge] - 16;
+ else
+#endif
+ } else {
+ sz.rwidth() += 50; // FIXME Double check this
+ }
+
+ // This should be enough to fit the focus ring
+ if (controlSize == QStyleHelper::SizeMini)
+ sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this for CT_PushButton.
+ else
+ sz.setHeight(pushButtonDefaultHeight[controlSize]);
+
+ return sz;
+ }
break;
- }
case CT_Menu: {
if (proxy() == this) {
sz = csz;
@@ -6452,7 +6176,8 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget);
}
- if (useAquaGuideline){
+ if (useAquaGuideline && ct != CT_PushButton) {
+ // TODO Probably going away at some point
QSize macsz;
if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QStyleHelper::SizeDefault) {
if (macsz.width() != -1)
@@ -6465,67 +6190,15 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
// The sizes that Carbon and the guidelines gives us excludes the focus frame.
// We compensate for this by adding some extra space here to make room for the frame when drawing:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
- const auto widgetSize = d->aquaSizeConstrain(opt, widget);
- QMacStylePrivate::CocoaControl cw;
- cw.first = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton;
- cw.second = widgetSize;
- const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw);
- sz.rwidth() -= qRound(diffRect.size.width);
- sz.rheight() -= qRound(diffRect.size.height);
- } else if (ct == CT_PushButton || ct == CT_ToolButton){
- ThemeButtonKind bkind;
- QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, widget);
- switch (ct) {
- default:
- case CT_PushButton:
- if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- if (btn->features & QStyleOptionButton::CommandLinkButton) {
- return QCommonStyle::sizeFromContents(ct, opt, sz, widget);
- }
- }
-
- switch (widgetSize) {
- case QStyleHelper::SizeDefault:
- case QStyleHelper::SizeLarge:
- bkind = kThemePushButton;
- break;
- case QStyleHelper::SizeSmall:
- bkind = kThemePushButtonSmall;
- break;
- case QStyleHelper::SizeMini:
- bkind = kThemePushButtonMini;
- break;
- }
- break;
- case CT_ToolButton:
- switch (widgetSize) {
- case QStyleHelper::SizeDefault:
- case QStyleHelper::SizeLarge:
- bkind = kThemeLargeBevelButton;
- break;
- case QStyleHelper::SizeMini:
- case QStyleHelper::SizeSmall:
- bkind = kThemeSmallBevelButton;
- }
- break;
+ if (combo->editable) {
+ const auto widgetSize = d->aquaSizeConstrain(opt, widget);
+ QMacStylePrivate::CocoaControl cw;
+ cw.type = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton;
+ cw.size = widgetSize;
+ const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw);
+ sz.rwidth() -= qRound(diffRect.size.width);
+ sz.rheight() -= qRound(diffRect.size.height);
}
-
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = kThemeStateActive;
- bdi.kind = bkind;
- bdi.value = kThemeButtonOff;
- bdi.adornment = kThemeAdornmentNone;
- CGRect macRect, myRect;
- myRect = CGRectMake(0, 0, sz.width(), sz.height());
- HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
- // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess),
- if (bkind == kThemePushButtonMini)
- macRect.size.height += 8.;
- else if (bkind == kThemePushButtonSmall)
- macRect.size.height -= 10;
- sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width));
- sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height));
}
return sz;
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 00dc8a9b53..4eac0a59d6 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -41,9 +41,6 @@
#ifndef QMACSTYLE_MAC_P_P_H
#define QMACSTYLE_MAC_P_P_H
-#include <Carbon/Carbon.h>
-#undef check
-
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtWidgets/private/qcommonstyle_p.h>
#include "qmacstyle_mac_p.h"
@@ -181,6 +178,10 @@ class QMacStylePrivate : public QCommonStylePrivate
{
Q_DECLARE_PUBLIC(QMacStyle)
public:
+ enum Direction {
+ North, South, East, West
+ };
+
enum CocoaControlType {
NoControl, // For when there's no such a control in Cocoa
Box, // QGroupBox
@@ -188,8 +189,9 @@ public:
Button_Disclosure, // Disclosure triangle, like in QTreeView
Button_PopupButton, // Non-editable QComboBox
Button_PullDown, // QPushButton with menu
- Button_PushButton,
+ Button_PushButton, // Plain QPushButton and QTabBar buttons
Button_RadioButton,
+ Button_SquareButton, // Oversized QPushButton
Button_WindowClose,
Button_WindowMiniaturize,
Button_WindowZoom,
@@ -198,6 +200,10 @@ public:
ProgressIndicator_Indeterminate,
Scroller_Horizontal,
Scroller_Vertical,
+ SegmentedControl_First, // QTabBar buttons focus ring
+ SegmentedControl_Middle,
+ SegmentedControl_Last,
+ SegmentedControl_Single,
Slider_Horizontal,
Slider_Vertical,
SplitView_Horizontal,
@@ -206,7 +212,22 @@ public:
TextField
};
- typedef QPair<CocoaControlType, QStyleHelper::WidgetSizePolicy> CocoaControl;
+ struct CocoaControl {
+ CocoaControl();
+ CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s);
+
+ CocoaControlType type;
+ QStyleHelper::WidgetSizePolicy size;
+
+ bool operator==(const CocoaControl &other) const;
+
+ QSizeF defaultFrameSize() const;
+ QRectF adjustedControlFrame(const QRectF &rect) const;
+ QMarginsF titleMargins() const;
+
+ bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const;
+ };
+
typedef void (^DrawRectBlock)(CGContextRef, const CGRect &);
@@ -215,69 +236,39 @@ public:
// Ideally these wouldn't exist, but since they already exist we need some accessors.
static const int PushButtonLeftOffset;
- static const int PushButtonTopOffset;
static const int PushButtonRightOffset;
- static const int PushButtonBottomOffset;
- static const int MiniButtonH;
- static const int SmallButtonH;
- static const int BevelButtonW;
- static const int BevelButtonH;
static const int PushButtonContentPadding;
enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar };
- static ThemeDrawState getDrawState(QStyle::State flags);
QStyleHelper::WidgetSizePolicy aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
QStyle::ContentsType ct = QStyle::CT_CustomBase,
QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
QStyleHelper::WidgetSizePolicy effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
QStyle::ContentsType ct = QStyle::CT_CustomBase,
QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
- void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider,
- HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const;
inline int animateSpeed(Animates) const { return 33; }
// Utility functions
- void drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi,
- const CocoaControl &cw,
- QPainter *p, const QStyleOption *opt) const;
-
- QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const;
-
- CGRect pushButtonContentBounds(const QStyleOptionButton *btn,
- const HIThemeButtonDrawInfo *bdi) const;
-
- void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi,
- CocoaControl *cw,
- const QWidget *widget, const ThemeDrawState &tds) const;
+ static CGRect comboboxInnerBounds(const CGRect &outterBounds, const CocoaControl &cocoaWidget);
- static CGRect comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget);
-
- static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi);
-
- static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p);
- bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi,
- ThemeButtonKind buttonKindToCheck) const;
- void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget,
- const ThemeDrawState tds,
- HIThemeButtonDrawInfo *bdi) const;
+ static QRectF comboboxEditBounds(const QRectF &outterBounds, const CocoaControl &cw);
void setAutoDefaultButton(QObject *button) const;
NSView *cocoaControl(CocoaControl widget) const;
NSCell *cocoaCell(CocoaControl widget) const;
- static CocoaControl cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind);
-
void setupNSGraphicsContext(CGContextRef cg, bool flipped) const;
void restoreNSGraphicsContext(CGContextRef cg) const;
void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
- void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
+ void drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window) const;
- void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const;
- void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
+ void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
+
+ void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const;
QPainterPath windowPanelPath(const QRectF &r) const;
@@ -285,6 +276,8 @@ public:
#if QT_CONFIG(tabbar)
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const;
+ static Direction tabDirection(QTabBar::Shape shape);
+ static bool verticalTabs(QMacStylePrivate::Direction tabDirection);
#endif
public:
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index ff27cab98a..733b3a9e9c 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -122,7 +122,8 @@ static inline HDC hdcForWidgetBackingStore(const QWidget *widget)
{
if (QBackingStore *backingStore = backingStoreForWidget(widget)) {
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- return static_cast<HDC>(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore));
+ if (nativeInterface)
+ return static_cast<HDC>(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore));
}
return 0;
}
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 291b35f8a6..2c7b4b83db 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -229,12 +229,14 @@ QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)
dict->lock.lockForRead();
QSqlDatabase db = dict->value(name);
dict->lock.unlock();
- if (db.driver() && db.driver()->thread() != QThread::currentThread()) {
+ if (!db.isValid())
+ return db;
+ if (db.driver()->thread() != QThread::currentThread()) {
qWarning("QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
return QSqlDatabase();
}
- if (db.isValid() && !db.isOpen() && open) {
+ if (open && !db.isOpen()) {
if (!db.open())
qWarning() << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index cdb1379502..915a980bf0 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -690,7 +690,7 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param
{
Q_D(QSqlResult);
d->binds = PositionalBinding;
- QList<int>& indexes = d->indexes[d->fieldSerial(index)];
+ QVector<int> &indexes = d->indexes[d->fieldSerial(index)];
if (!indexes.contains(index))
indexes.append(index);
if (d->values.count() <= index)
@@ -717,7 +717,7 @@ void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
d->binds = NamedBinding;
// if the index has already been set when doing emulated named
// bindings - don't reset it
- const QList<int> indexes = d->indexes.value(placeholder);
+ const QVector<int> indexes = d->indexes.value(placeholder);
for (int idx : indexes) {
if (d->values.count() <= idx)
d->values.resize(idx + 1);
@@ -764,7 +764,7 @@ QVariant QSqlResult::boundValue(int index) const
QVariant QSqlResult::boundValue(const QString& placeholder) const
{
Q_D(const QSqlResult);
- QList<int> indexes = d->indexes.value(placeholder);
+ const QVector<int> indexes = d->indexes.value(placeholder);
return d->values.value(indexes.value(0,-1));
}
diff --git a/src/sql/kernel/qsqlresult_p.h b/src/sql/kernel/qsqlresult_p.h
index 7b312800c1..f0816a7fb5 100644
--- a/src/sql/kernel/qsqlresult_p.h
+++ b/src/sql/kernel/qsqlresult_p.h
@@ -135,7 +135,7 @@ public:
QString executedQuery;
QHash<int, QSql::ParamType> types;
QVector<QVariant> values;
- typedef QHash<QString, QList<int> > IndexMap;
+ typedef QHash<QString, QVector<int> > IndexMap;
IndexMap indexes;
typedef QVector<QHolder> QHolderVector;
diff --git a/src/testlib/configure.json b/src/testlib/configure.json
new file mode 100644
index 0000000000..c464037205
--- /dev/null
+++ b/src/testlib/configure.json
@@ -0,0 +1,22 @@
+{
+ "module": "testlib",
+ "depends": [
+ "core"
+ ],
+
+ "features": {
+ "itemmodeltester": {
+ "label": "Tester for item models",
+ "purpose": "Provides a utility to test item models.",
+ "condition": "features.itemmodel",
+ "output": [ "publicFeature" ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt Testlib",
+ "entries": [ "itemmodeltester" ]
+ }
+ ]
+}
diff --git a/src/testlib/qabstractitemmodeltester.h b/src/testlib/qabstractitemmodeltester.h
index 617e189817..706c0ac16f 100644
--- a/src/testlib/qabstractitemmodeltester.h
+++ b/src/testlib/qabstractitemmodeltester.h
@@ -30,7 +30,7 @@
#define QABSTRACTITEMMODELTESTER_H
#include <QtCore/QObject>
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#ifdef QT_GUI_LIB
#include <QtGui/QFont>
@@ -41,6 +41,8 @@
#include <QtGui/QIcon>
#endif
+QT_REQUIRE_CONFIG(itemmodeltester);
+
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
diff --git a/src/testlib/qbenchmark.h b/src/testlib/qbenchmark.h
index 1340fd7715..4a55fcc23e 100644
--- a/src/testlib/qbenchmark.h
+++ b/src/testlib/qbenchmark.h
@@ -40,7 +40,7 @@
#ifndef QBENCHMARK_H
#define QBENCHMARK_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qbenchmarkmetric.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h
index dbfa0127b6..3fa9c5f534 100644
--- a/src/testlib/qbenchmark_p.h
+++ b/src/testlib/qbenchmark_p.h
@@ -69,7 +69,7 @@
#include <QtTest/private/qbenchmarkmeasurement_p.h>
#include <QtCore/QMap>
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#ifdef QTESTLIB_USE_VALGRIND
#include <QtTest/private/qbenchmarkvalgrind_p.h>
#endif
diff --git a/src/testlib/qbenchmarkmetric.h b/src/testlib/qbenchmarkmetric.h
index 6e423473b1..6605606402 100644
--- a/src/testlib/qbenchmarkmetric.h
+++ b/src/testlib/qbenchmarkmetric.h
@@ -41,7 +41,7 @@
#ifndef QBENCHMARKMETRIC_H
#define QBENCHMARKMETRIC_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qbenchmarkmetric_p.h b/src/testlib/qbenchmarkmetric_p.h
index a036c645bf..049b9711e2 100644
--- a/src/testlib/qbenchmarkmetric_p.h
+++ b/src/testlib/qbenchmarkmetric_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qbenchmarkmetric.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index a5df27e3b9..1cb6a91d33 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -41,7 +41,7 @@
#ifndef QTEST_H
#define QTEST_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qtestcase.h>
#include <QtTest/qtestdata.h>
#include <QtTest/qbenchmark.h>
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index 0470d15ed7..d14dcec031 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -54,7 +54,7 @@
#include <QtCore/qdebug.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qguiapplication.h>
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qtestsystem.h>
#if QT_CONFIG(accessibility)
diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h
index df205fc77b..08ce052231 100644
--- a/src/testlib/qtestblacklist_p.h
+++ b/src/testlib/qtestblacklist_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 7e01c43869..cd4e7f66e1 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -75,6 +75,7 @@
#include <QtTest/private/qtestutil_macos_p.h>
#endif
+#include <cmath>
#include <numeric>
#include <algorithm>
@@ -208,8 +209,13 @@ static void stackTrace()
if (debuggerPresent())
return;
+#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
+ const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
+ const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
+ fprintf(stderr, "\n=== Received signal at function time: %dms, total time: %dms, dumping stack ===\n",
+ msecsFunctionTime, msecsTotalTime);
+#endif
#ifdef Q_OS_LINUX
- fprintf(stderr, "\n========= Received signal, dumping stack ==============\n");
char cmd[512];
qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n"
"set prompt\n"
@@ -221,9 +227,8 @@ static void stackTrace()
(int)getpid());
if (system(cmd) == -1)
fprintf(stderr, "calling gdb failed\n");
- fprintf(stderr, "========= End of stack trace ==============\n");
+ fprintf(stderr, "=== End of stack trace ===\n");
#elif defined(Q_OS_OSX)
- fprintf(stderr, "\n========= Received signal, dumping stack ==============\n");
char cmd[512];
qsnprintf(cmd, 512, "lldb -p %d 2>/dev/null <<EOF\n"
"bt all\n"
@@ -232,7 +237,7 @@ static void stackTrace()
(int)getpid());
if (system(cmd) == -1)
fprintf(stderr, "calling lldb failed\n");
- fprintf(stderr, "========= End of stack trace ==============\n");
+ fprintf(stderr, "=== End of stack trace ===\n");
#endif
}
@@ -1973,7 +1978,7 @@ void QTest::ignoreMessage(QtMsgType type, const char *message)
QTestLog::ignoreMessage(type, message);
}
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
/*!
\overload
@@ -1993,7 +1998,7 @@ void QTest::ignoreMessage(QtMsgType type, const QRegularExpression &messagePatte
{
QTestLog::ignoreMessage(type, messagePattern);
}
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
/*! \internal
*/
@@ -2441,7 +2446,16 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const
bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected,
const char *file, int line)
{
- return compare_helper(qFuzzyCompare(t1, t2), "Compared doubles are not the same (fuzzy compare)",
+ bool equal = false;
+ int cl1 = std::fpclassify(t1);
+ int cl2 = std::fpclassify(t2);
+ if (cl1 == FP_INFINITE)
+ equal = ((t1 < 0) == (t2 < 0)) && cl2 == FP_INFINITE;
+ else if (cl1 == FP_NAN)
+ equal = (cl2 == FP_NAN);
+ else
+ equal = qFuzzyCompare(t1, t2);
+ return compare_helper(equal, "Compared doubles are not the same (fuzzy compare)",
toString(t1), toString(t2), actual, expected, file, line);
}
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index f38f7ed4df..54669c11de 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -40,7 +40,7 @@
#ifndef QTESTCASE_H
#define QTESTCASE_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
@@ -290,7 +290,7 @@ namespace QTest
const char *file, int line);
Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = nullptr, int line = 0);
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message);
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern);
#endif
diff --git a/src/testlib/qtestdata.h b/src/testlib/qtestdata.h
index c87236fcfc..cf10fed8f3 100644
--- a/src/testlib/qtestdata.h
+++ b/src/testlib/qtestdata.h
@@ -40,7 +40,7 @@
#ifndef QTESTDATA_H
#define QTESTDATA_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qstring.h>
diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h
index 159e3e01ff..faad914a47 100644
--- a/src/testlib/qtestevent.h
+++ b/src/testlib/qtestevent.h
@@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#ifdef QT_GUI_LIB
#include <QtTest/qtestkeyboard.h>
#include <QtTest/qtestmouse.h>
@@ -103,7 +103,10 @@ class QTestKeyClicksEvent: public QTestEvent
{
public:
inline QTestKeyClicksEvent(const QString &keys, Qt::KeyboardModifiers modifiers, int delay)
- : _keys(keys), _modifiers(modifiers), _delay(delay) {}
+ : _keys(keys), _modifiers(modifiers), _delay(delay)
+ {
+ Q_UNUSED(_delay) // Silence -Werror,-Wunused-private-field
+ }
inline QTestEvent *clone() const override { return new QTestKeyClicksEvent(*this); }
#ifdef QT_WIDGETS_LIB
@@ -124,7 +127,12 @@ class QTestMouseEvent: public QTestEvent
public:
inline QTestMouseEvent(QTest::MouseAction action, Qt::MouseButton button,
Qt::KeyboardModifiers modifiers, QPoint position, int delay)
- : _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay) {}
+ : _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay)
+ {
+ Q_UNUSED(_action)
+ Q_UNUSED(_button)
+ Q_UNUSED(_delay)
+ }
inline QTestEvent *clone() const override { return new QTestMouseEvent(*this); }
#ifdef QT_WIDGETS_LIB
@@ -147,7 +155,10 @@ private:
class QTestDelayEvent: public QTestEvent
{
public:
- inline QTestDelayEvent(int msecs): _delay(msecs) {}
+ inline QTestDelayEvent(int msecs): _delay(msecs)
+ {
+ Q_UNUSED(_delay)
+ }
inline QTestEvent *clone() const override { return new QTestDelayEvent(*this); }
#ifdef QT_WIDGETS_LIB
diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h
index 81c0b9126c..19ad22565e 100644
--- a/src/testlib/qtesteventloop.h
+++ b/src/testlib/qtesteventloop.h
@@ -40,7 +40,7 @@
#ifndef QTESTEVENTLOOP_H
#define QTESTEVENTLOOP_H
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qeventloop.h>
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index a7cf78f25a..63501ffb1e 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -46,7 +46,7 @@
#endif
#include <QtTest/qtestassert.h>
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 4964c6538e..6260b9e3fd 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -55,7 +55,9 @@
#include <QtCore/qbytearray.h>
#include <QtCore/QElapsedTimer>
#include <QtCore/QVariant>
+#if QT_CONFIG(regularexpression)
#include <QtCore/QRegularExpression>
+#endif
#include <stdlib.h>
#include <string.h>
@@ -139,7 +141,7 @@ namespace QTest {
return tp == type
&& (pattern.type() == QVariant::String ?
stringsMatch(pattern.toString(), message) :
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
pattern.toRegularExpression().match(message).hasMatch());
#else
false);
@@ -364,7 +366,7 @@ void QTestLog::printUnhandledIgnoreMessages()
if (list->pattern.type() == QVariant::String) {
message = QStringLiteral("Did not receive message: \"") + list->pattern.toString() + QLatin1Char('"');
} else {
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
message = QStringLiteral("Did not receive any message matching: \"") + list->pattern.toRegularExpression().pattern() + QLatin1Char('"');
#endif
}
@@ -548,14 +550,14 @@ void QTestLog::ignoreMessage(QtMsgType type, const char *msg)
QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QString::fromLocal8Bit(msg));
}
-#ifndef QT_NO_REGULAREXPRESSION
+#if QT_CONFIG(regularexpression)
void QTestLog::ignoreMessage(QtMsgType type, const QRegularExpression &expression)
{
QTEST_ASSERT(expression.isValid());
QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QVariant(expression));
}
-#endif // QT_NO_REGULAREXPRESSION
+#endif // QT_CONFIG(regularexpression)
void QTestLog::setMaxWarnings(int m)
{
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index f72c047c35..3d28795188 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtestmouse.cpp b/src/testlib/qtestmouse.cpp
index eda7edbd89..76369e0490 100644
--- a/src/testlib/qtestmouse.cpp
+++ b/src/testlib/qtestmouse.cpp
@@ -39,7 +39,7 @@
#include <QtCore/QtGlobal>
#include <QtCore/qnamespace.h>
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index e2835828a1..e3e446577d 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qtestassert.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>
diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h
index 061ca5f311..4df75b2805 100644
--- a/src/testlib/qtestresult_p.h
+++ b/src/testlib/qtestresult_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtesttable_p.h b/src/testlib/qtesttable_p.h
index 53de9a2f43..d2f389a134 100644
--- a/src/testlib/qtesttable_p.h
+++ b/src/testlib/qtesttable_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h
index 83ca83602e..20a9476ee7 100644
--- a/src/testlib/qtesttouch.h
+++ b/src/testlib/qtesttouch.h
@@ -45,7 +45,7 @@
#pragma qt_no_master_include
#endif
-#include <QtTest/qtest_global.h>
+#include <QtTest/qttestglobal.h>
#include <QtTest/qtestassert.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/qtestspontaneevent.h>
diff --git a/src/testlib/qtest_global.h b/src/testlib/qttestglobal.h
index 3fbb1d428c..9561e56ba3 100644
--- a/src/testlib/qtest_global.h
+++ b/src/testlib/qttestglobal.h
@@ -37,14 +37,14 @@
**
****************************************************************************/
-#ifndef QTEST_GLOBAL_H
-#define QTEST_GLOBAL_H
+#ifndef QTTESTGLOBAL_H
+#define QTTESTGLOBAL_H
#include <QtCore/qglobal.h>
+#include <QtTest/qttestlib-config.h>
QT_BEGIN_NAMESPACE
-
#if defined(QT_STATIC)
# define Q_TESTLIB_EXPORT
#else
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 109feee630..06a6f8b8e5 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -12,7 +12,6 @@ unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \
QMAKE_DOCS = $$PWD/doc/qttestlib.qdocconf
HEADERS = \
- qabstractitemmodeltester.h \
qbenchmark.h \
qbenchmark_p.h \
qbenchmarkmeasurement_p.h \
@@ -29,7 +28,6 @@ HEADERS = \
qtestdata.h \
qtestevent.h \
qtesteventloop.h \
- qtest_global.h \
qtest_gui.h \
qtest_network.h \
qtest_widgets.h \
@@ -40,10 +38,10 @@ HEADERS = \
qtestsystem.h \
qtesttouch.h \
qtestblacklist_p.h \
- qtesthelpers_p.h
+ qtesthelpers_p.h \
+ qttestglobal.h
SOURCES = \
- qabstractitemmodeltester.cpp \
qtestcase.cpp \
qtestlog.cpp \
qtesttable.cpp \
@@ -69,6 +67,14 @@ SOURCES = \
qxunittestlogger.cpp \
qtestblacklist.cpp
+qtConfig(itemmodeltester) {
+ HEADERS += \
+ qabstractitemmodeltester.h
+
+ SOURCES += \
+ qabstractitemmodeltester.cpp
+}
+
DEFINES *= QT_NO_CAST_TO_ASCII \
QT_NO_CAST_FROM_ASCII \
QT_NO_FOREACH \
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 92d3c5c171..4c7d095ca3 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -504,38 +504,8 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (QDir::isRelativePath(absFileName))
absFileName.prepend(currentPath);
QFileInfo file(absFileName);
- if (!file.exists()) {
- m_failedResources.push_back(absFileName);
- const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n")
- .arg(fname, fileName);
- m_errorDevice->write(msg.toUtf8());
- if (ignoreErrors)
- continue;
- else
- return false;
- } else if (file.isFile()) {
- const bool arc =
- addFile(alias,
- RCCFileInfo(alias.section(slash, -1),
- file,
- language,
- country,
- RCCFileInfo::NoFlags,
- compressLevel,
- compressThreshold)
- );
- if (!arc)
- m_failedResources.push_back(absFileName);
- } else {
- QDir dir;
- if (file.isDir()) {
- dir.setPath(file.filePath());
- } else {
- dir.setPath(file.path());
- dir.setNameFilters(QStringList(file.fileName()));
- if (alias.endsWith(file.fileName()))
- alias = alias.left(alias.length()-file.fileName().length());
- }
+ if (file.isDir()) {
+ QDir dir(file.filePath());
if (!alias.endsWith(slash))
alias += slash;
QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories);
@@ -557,6 +527,33 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
m_failedResources.push_back(child.fileName());
}
}
+ } else if (file.isFile()) {
+ const bool arc =
+ addFile(alias,
+ RCCFileInfo(alias.section(slash, -1),
+ file,
+ language,
+ country,
+ RCCFileInfo::NoFlags,
+ compressLevel,
+ compressThreshold)
+ );
+ if (!arc)
+ m_failedResources.push_back(absFileName);
+ } else if (file.exists()) {
+ m_failedResources.push_back(absFileName);
+ const QString msg = QString::fromLatin1("RCC: Error in '%1': Entry '%2' is neither a file nor a directory\n")
+ .arg(fname, fileName);
+ m_errorDevice->write(msg.toUtf8());
+ return false;
+ } else {
+ m_failedResources.push_back(absFileName);
+ const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n")
+ .arg(fname, fileName);
+ m_errorDevice->write(msg.toUtf8());
+ if (ignoreErrors)
+ continue;
+ return false;
}
}
break;
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 896baed6c5..cf1119254b 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -1299,7 +1299,7 @@ QColorShower::QColorShower(QColorDialog *parent)
lblHtml->setBuddy(htEd);
#endif
-#if !defined(QT_NO_REGULAREXPRESSION)
+#if QT_CONFIG(regularexpression)
QRegularExpression regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
htEd->setValidator(validator);
diff --git a/src/widgets/doc/images/graphicsflowlayout.png b/src/widgets/doc/images/graphicsflowlayout.png
new file mode 100644
index 0000000000..ea70e102c3
--- /dev/null
+++ b/src/widgets/doc/images/graphicsflowlayout.png
Binary files differ
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index b7048d1616..00e9ff7400 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -1175,9 +1175,10 @@ bool QHeaderView::sectionsMovable() const
*/
/*!
- \since 5.10
+ \property QHeaderView::firstSectionMovable
+ \brief Whether the first column can be moved by the user
- If \a movable is true, the first column can be moved by the user.
+ This property controls whether the first column can be moved by the user.
In a QTreeView, the first column holds the tree structure and is
therefore non-movable by default, even after setSectionsMovable(true).
@@ -1186,8 +1187,11 @@ bool QHeaderView::sectionsMovable() const
In such a scenario, it is recommended to call QTreeView::setRootIsDecorated(false)
as well.
- This method has no effect unless setSectionsMovable(true) is called as well.
+ Setting it to true has no effect unless setSectionsMovable(true) is called
+ as well.
+
\sa setSectionsMovable()
+ \since 5.11
*/
void QHeaderView::setFirstSectionMovable(bool movable)
{
@@ -1195,13 +1199,7 @@ void QHeaderView::setFirstSectionMovable(bool movable)
d->allowUserMoveOfSection0 = movable;
}
-/*!
- \since 5.10
-
- Returns \c true if the first column can be moved by the user,
- when this header is used in a QTreeView.
-*/
-bool QHeaderView::firstSectionMovable() const
+bool QHeaderView::isFirstSectionMovable() const
{
Q_D(const QHeaderView);
return d->allowUserMoveOfSection0;
diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h
index c09081cd80..7e950add1f 100644
--- a/src/widgets/itemviews/qheaderview.h
+++ b/src/widgets/itemviews/qheaderview.h
@@ -53,6 +53,7 @@ class QStyleOptionHeader;
class Q_WIDGETS_EXPORT QHeaderView : public QAbstractItemView
{
Q_OBJECT
+ Q_PROPERTY(bool firstSectionMovable READ isFirstSectionMovable WRITE setFirstSectionMovable)
Q_PROPERTY(bool showSortIndicator READ isSortIndicatorShown WRITE setSortIndicatorShown)
Q_PROPERTY(bool highlightSections READ highlightSections WRITE setHighlightSections)
Q_PROPERTY(bool stretchLastSection READ stretchLastSection WRITE setStretchLastSection)
@@ -119,7 +120,7 @@ public:
inline QT_DEPRECATED bool isMovable() const { return sectionsMovable(); }
#endif
void setFirstSectionMovable(bool movable);
- bool firstSectionMovable() const;
+ bool isFirstSectionMovable() const;
void setSectionsClickable(bool clickable);
bool sectionsClickable() const;
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index 1cb88cbeeb..301d5dbe4d 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -1525,7 +1525,7 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
\snippet qtablewidget-resizing/mainwindow.cpp 0
\snippet qtablewidget-resizing/mainwindow.cpp 1
- Items are created ouside the table (with no parent widget) and inserted
+ Items are created outside the table (with no parent widget) and inserted
into the table with setItem():
\snippet qtablewidget-resizing/mainwindow.cpp 2
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 8c8217bb75..0ef4ed0634 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -1088,7 +1088,7 @@ QAction::event(QEvent *e)
"QAction::event",
"Received shortcut event from incorrect shortcut");
if (se->isAmbiguous())
- qWarning("QAction::eventFilter: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
+ qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
else
activate(Trigger);
return true;
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index b855e32f2d..0d434c7097 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -113,8 +113,10 @@
static void initResources()
{
Q_INIT_RESOURCE(qstyle);
- Q_INIT_RESOURCE(qmessagebox);
+#if QT_CONFIG(messagebox)
+ Q_INIT_RESOURCE(qmessagebox);
+#endif
}
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 9983cc7d9e..019fad3fc3 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -242,7 +242,7 @@ public:
static HWND getHWNDForWidget(const QWidget *widget)
{
if (QWindow *window = windowForWidget(widget))
- if (window->handle())
+ if (window->handle() && QGuiApplication::platformNativeInterface())
return static_cast<HWND> (QGuiApplication::platformNativeInterface()->
nativeResourceForWindow(QByteArrayLiteral("handle"), window));
return 0;
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index 5c4fc20687..52640daf55 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -839,7 +839,7 @@ int QWidgetItemV2::heightForWidth(int width) const
const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
if (size.width() == width) {
if (q_hfwCacheSize == HfwCacheMaxSize)
- q_firstCachedHfw = offset;
+ q_firstCachedHfw = offset % HfwCacheMaxSize;
return size.height();
}
}
diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp
index 32600d4152..fde039c75e 100644
--- a/src/widgets/kernel/qshortcut.cpp
+++ b/src/widgets/kernel/qshortcut.cpp
@@ -187,8 +187,15 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge
active_window = active_window->parentWidget()->window();
}
- if (active_window != tlw)
+ if (active_window != tlw) {
+#if QT_CONFIG(menubar)
+ // If the tlw is a QMenuBar then we allow it to proceed as this indicates that
+ // the QMenuBar is a parentless one and is therefore used for multiple top level
+ // windows in the application. This is common on macOS platforms for example.
+ if (!qobject_cast<QMenuBar *>(tlw))
+#endif
return false;
+ }
/* if we live in a MDI subwindow, ignore the event if we are
not the active document window */
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index baf717d715..ed7184302a 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -317,15 +317,13 @@ void QTipLabel::timerEvent(QTimerEvent *e)
bool QTipLabel::eventFilter(QObject *o, QEvent *e)
{
switch (e->type()) {
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
+#ifdef Q_OS_MACOS
case QEvent::KeyPress:
case QEvent::KeyRelease: {
- int key = static_cast<QKeyEvent *>(e)->key();
- Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers();
- if (!(mody & Qt::KeyboardModifierMask)
- && key != Qt::Key_Shift && key != Qt::Key_Control
- && key != Qt::Key_Alt && key != Qt::Key_Meta)
- hideTip();
+ const int key = static_cast<QKeyEvent *>(e)->key();
+ // Anything except key modifiers or caps-lock, etc.
+ if (key < Qt::Key_Shift || key > Qt::Key_ScrollLock)
+ hideTipImmediately();
break;
}
#endif
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 06ac2313f5..41c19375d7 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5484,11 +5484,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
QPainter p(pdev);
p.translate(offset);
- context.painter = context.sharedPainter = &p;
+ context.painter = &p;
graphicsEffect->draw(&p);
setSystemClip(pdev->paintEngine(), 1, QRegion());
} else {
- context.painter = context.sharedPainter = sharedPainter;
+ context.painter = sharedPainter;
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
sourced->invalidateCache();
sourced->lastEffectTransform = sharedPainter->worldTransform();
@@ -11150,7 +11150,7 @@ void QWidgetPrivate::macUpdateSizeAttribute()
for (int i = 0; i < children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(children.at(i));
if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
- && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
+ && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
&& !w->testAttribute(Qt::WA_MacSmallSize)
&& !w->testAttribute(Qt::WA_MacNormalSize))
w->d_func()->macUpdateSizeAttribute();
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 6873ca876e..0c6825cb36 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -778,8 +778,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
} 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());
+ penWidth = qMax<qreal>(penWidth, 0.13 * rect.height());
+ penWidth = qMin<qreal>(penWidth, 0.20 * rect.height());
QPen checkPen = QPen(checkMarkColor, penWidth);
checkMarkColor.setAlpha(210);
painter->translate(dpiScaled(-0.8), dpiScaled(0.5));
@@ -1562,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.79,
- qMax(menuItem->maxIconWidth * 1.0, dpiScaled(21))); // icon checkbox's highlihgt column width
+ int checkcol = qMax<int>(menuItem->rect.height() * 0.79,
+ qMax<int>(menuItem->maxIconWidth, dpiScaled(21))); // icon checkbox's highlight column width
if (
#if QT_CONFIG(combobox)
qobject_cast<const QComboBox*>(widget) ||
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 7ca47e9f0f..e059f2d52f 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -611,12 +611,11 @@ void QAbstractSpinBox::stepDown()
}
/*!
Virtual function that is called whenever the user triggers a step.
- The \a steps parameter indicates how many steps were taken, e.g.
- Pressing Qt::Key_Down will trigger a call to stepBy(-1),
- whereas pressing Qt::Key_Prior will trigger a call to
- stepBy(10).
+ The \a steps parameter indicates how many steps were taken.
+ For example, pressing \c Qt::Key_Down will trigger a call to \c stepBy(-1),
+ whereas pressing \c Qt::Key_PageUp will trigger a call to \c stepBy(10).
- If you subclass QAbstractSpinBox you must reimplement this
+ If you subclass \c QAbstractSpinBox you must reimplement this
function. Note that this function is called even if the resulting
value will be outside the bounds of minimum and maximum. It's this
function's job to handle these situations.
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index e17c2c1f4c..84cb78a474 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -160,9 +160,13 @@ bool QDockWidgetTitleButton::event(QEvent *event)
static inline bool isWindowsStyle(const QStyle *style)
{
// Note: QStyleSheetStyle inherits QWindowsStyle
- const QStyle *effectiveStyle = style->inherits("QStyleSheetStyle")
- ? static_cast<const QStyleSheetStyle *>(style)->baseStyle()
- : style;
+ const QStyle *effectiveStyle = style;
+
+#if QT_CONFIG(style_stylesheet)
+ if (style->inherits("QStyleSheetStyle"))
+ effectiveStyle = static_cast<const QStyleSheetStyle *>(style)->baseStyle();
+#endif
+
return effectiveStyle->inherits("QWindowsStyle");
}
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index ee4825d3e5..947da273dd 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -963,7 +963,9 @@ bool QLabel::event(QEvent *e)
if (type == QEvent::Shortcut) {
QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
if (se->shortcutId() == d->shortcutId) {
- QWidget * w = d->buddy;
+ QWidget *w = d->buddy;
+ if (!w)
+ return QFrame::event(e);
if (w->focusPolicy() != Qt::NoFocus)
w->setFocus(Qt::ShortcutFocusReason);
#if QT_CONFIG(abstractbutton)
@@ -1006,7 +1008,7 @@ void QLabel::paintEvent(QPaintEvent *)
: layoutDirection(), QFlag(d->align));
#if QT_CONFIG(movie)
- if (d->movie) {
+ if (d->movie && !d->movie->currentPixmap().isNull()) {
if (d->scaledcontents)
style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size()));
else
@@ -1163,7 +1165,15 @@ void QLabelPrivate::updateLabel()
void QLabel::setBuddy(QWidget *buddy)
{
Q_D(QLabel);
+
+ if (d->buddy)
+ disconnect(d->buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted()));
+
d->buddy = buddy;
+
+ if (buddy)
+ connect(buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted()));
+
if (d->isTextLabel) {
if (d->shortcutId)
releaseShortcut(d->shortcutId);
@@ -1204,6 +1214,13 @@ void QLabelPrivate::updateShortcut()
shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
}
+
+void QLabelPrivate::_q_buddyDeleted()
+{
+ Q_Q(QLabel);
+ q->setBuddy(nullptr);
+}
+
#endif // QT_NO_SHORTCUT
#if QT_CONFIG(movie)
diff --git a/src/widgets/widgets/qlabel.h b/src/widgets/widgets/qlabel.h
index e1cc333a1c..2f5db5a7d3 100644
--- a/src/widgets/widgets/qlabel.h
+++ b/src/widgets/widgets/qlabel.h
@@ -158,6 +158,9 @@ private:
#endif
Q_PRIVATE_SLOT(d_func(), void _q_linkHovered(const QString &))
+#ifndef QT_NO_SHORTCUT
+ Q_PRIVATE_SLOT(d_func(), void _q_buddyDeleted())
+#endif
friend class QTipLabel;
friend class QMessageBoxPrivate;
friend class QBalloonTip;
diff --git a/src/widgets/widgets/qlabel_p.h b/src/widgets/widgets/qlabel_p.h
index e05a5b5c35..59188563a9 100644
--- a/src/widgets/widgets/qlabel_p.h
+++ b/src/widgets/widgets/qlabel_p.h
@@ -89,6 +89,7 @@ public:
#endif
#ifndef QT_NO_SHORTCUT
void updateShortcut();
+ void _q_buddyDeleted();
#endif
inline bool needTextControl() const {
return isTextLabel
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 9b38da340c..d4ce0ffa4c 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -68,6 +68,7 @@
#include <qstack.h>
#include <qmap.h>
#include <qtimer.h>
+#include <qpointer.h>
#ifndef QT_NO_DEBUG_STREAM
# include <qdebug.h>
@@ -316,6 +317,9 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
// We might need to show the widget again
destroyOrHideIfEmpty();
break;
+ case QEvent::Resize:
+ updateCurrentGapRect();
+ emit resized();
default:
break;
}
@@ -466,6 +470,8 @@ void QDockWidgetGroupWindow::adjustFlags()
}
if (oldFlags != flags) {
+ if (!windowHandle())
+ create(); // The desired geometry is forgotten if we call setWindowFlags before having a window
setWindowFlags(flags);
const bool gainedNativeDecos = (oldFlags & Qt::FramelessWindowHint) && !(flags & Qt::FramelessWindowHint);
const bool lostNativeDecos = !(oldFlags & Qt::FramelessWindowHint) && (flags & Qt::FramelessWindowHint);
@@ -545,12 +551,18 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP
currentGapPos = newGapPos;
newState.insertGap(currentGapPos, widgetItem);
newState.fitItems();
- currentGapRect = newState.info(currentGapPos)->itemRect(currentGapPos.last(), true);
*layoutInfo() = std::move(newState);
+ updateCurrentGapRect();
layoutInfo()->apply(opts & QMainWindow::AnimatedDocks);
return true;
}
+void QDockWidgetGroupWindow::updateCurrentGapRect()
+{
+ if (!currentGapPos.isEmpty())
+ currentGapRect = layoutInfo()->info(currentGapPos)->itemRect(currentGapPos.last(), true);
+}
+
/*
Remove the gap that was created by hover()
*/
@@ -1654,7 +1666,7 @@ void QMainWindowLayout::keepSize(QDockWidget *w)
class QMainWindowTabBar : public QTabBar
{
QMainWindow *mainWindow;
- QDockWidget *draggingDock; // Currently dragging (detached) dock widget
+ QPointer<QDockWidget> draggingDock; // Currently dragging (detached) dock widget
public:
QMainWindowTabBar(QMainWindow *parent);
protected:
@@ -1665,7 +1677,7 @@ protected:
};
QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent)
- : QTabBar(parent), mainWindow(parent), draggingDock(0)
+ : QTabBar(parent), mainWindow(parent)
{
setExpanding(false);
}
@@ -1976,6 +1988,8 @@ void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w)
if (currentHoveredFloat) {
disconnect(currentHoveredFloat.data(), &QObject::destroyed,
this, &QMainWindowLayout::updateGapIndicator);
+ disconnect(currentHoveredFloat.data(), &QDockWidgetGroupWindow::resized,
+ this, &QMainWindowLayout::updateGapIndicator);
if (currentHoveredFloat)
currentHoveredFloat->restore();
} else if (w) {
@@ -1987,6 +2001,8 @@ void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w)
if (w) {
connect(w, &QObject::destroyed,
this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
+ connect(w, &QDockWidgetGroupWindow::resized,
+ this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
}
updateGapIndicator();
@@ -2558,6 +2574,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
dropTo->show();
dropTo->d_func()->plug(QRect());
w = floatingTabs;
+ widget->raise(); // raise, as our newly created drop target is now on top
}
Q_ASSERT(qobject_cast<QDockWidgetGroupWindow *>(w));
auto group = static_cast<QDockWidgetGroupWindow *>(w);
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index 168d4444b9..53e045aaae 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -338,12 +338,16 @@ public:
bool hasNativeDecos() const;
bool hover(QLayoutItem *widgetItem, const QPoint &mousePos);
+ void updateCurrentGapRect();
void restore();
void apply();
QRect currentGapRect;
QList<int> currentGapPos;
+signals:
+ void resized();
+
protected:
bool event(QEvent *) override;
void paintEvent(QPaintEvent*) override;
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 024f9a75a1..363647aee0 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -3641,6 +3641,13 @@ void QMenu::internalDelayedPopup()
if (subMenuPos.x() > screen.right())
subMenuPos.setX(QCursor::pos().x());
+ const auto &subMenuActions = d->activeMenu->actions();
+ if (!subMenuActions.isEmpty()) {
+ // Offset by the submenu's 1st action position to align with the current action
+ const auto subMenuActionRect = d->activeMenu->actionGeometry(subMenuActions.first());
+ subMenuPos.ry() -= subMenuActionRect.top();
+ }
+
d->activeMenu->popup(subMenuPos);
d->sloppyState.setSubMenuPopup(actionRect, d->currentAction, d->activeMenu);
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 8e4c846402..6ee49aa9f0 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -1200,8 +1200,8 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
/*!
\fn int QSplitter::indexOf(QWidget *widget) const
- Returns the index in the splitter's layout of the specified \a widget. This
- also works for handles.
+ Returns the index in the splitter's layout of the specified \a widget,
+ or -1 if \a widget is not found. This also works for handles.
Handles are numbered from 0. There are as many handles as there
are child widgets, but the handle at position 0 is always hidden.
@@ -1234,9 +1234,9 @@ QSplitterHandle *QSplitter::createHandle()
}
/*!
- Returns the handle to the left (or above) for the item in the
- splitter's layout at the given \a index. The handle at index 0 is
- always hidden.
+ Returns the handle to the left of (or above) the item in the
+ splitter's layout at the given \a index, or \c nullptr if there is no such item.
+ The handle at index 0 is always hidden.
For right-to-left languages such as Arabic and Hebrew, the layout
of horizontal splitters is reversed. The handle will be to the
@@ -1253,7 +1253,8 @@ QSplitterHandle *QSplitter::handle(int index) const
}
/*!
- Returns the widget at the given \a index in the splitter's layout.
+ Returns the widget at the given \a index in the splitter's layout,
+ or \c nullptr if there is no such widget.
\sa count(), handle(), indexOf(), insertWidget()
*/
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 258e018151..2f2d1bceee 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -2166,8 +2166,12 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event)
QStyleOptionTabBarBase optTabBase;
optTabBase.initFrom(this);
optTabBase.documentMode = d->documentMode;
- if (style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this) == QEvent::MouseButtonRelease)
+ const bool selectOnRelease =
+ (style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this) == QEvent::MouseButtonRelease);
+ if (selectOnRelease)
setCurrentIndex(i);
+ if (!selectOnRelease || !d->validIndex(i) || d->currentIndex == i)
+ repaint(tabRect(i));
}
/*!\reimp
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index df2d7c3ce8..17f87804e9 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -2544,7 +2544,7 @@ QDomNode QDomNode::insertAfter(const QDomNode& newChild, const QDomNode& refChil
If \a newChild is a QDomDocumentFragment, then \a oldChild is
replaced by all of the children of the fragment.
- Returns a new reference to \a oldChild on success or a \l{isNull()}{null node} an failure.
+ Returns a new reference to \a oldChild on success or a \l{isNull()}{null node} on failure.
\sa insertBefore(), insertAfter(), removeChild(), appendChild()
*/
diff --git a/sync.profile b/sync.profile
index 6a50e31102..c674aab2f3 100644
--- a/sync.profile
+++ b/sync.profile
@@ -73,6 +73,9 @@
},
"QtDBus" => {
"qdbusmacros.h" => "QtDbus/qtdbusglobal.h"
+ },
+ "QtTest" => {
+ "qtest_global.h" => "QtTest/qttestglobal.h"
}
);
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 40c86132e9..f1d8657091 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -47,17 +47,7 @@ find_package(Qt5Core REQUIRED)
include("${_Qt5CTestMacros}")
-if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.9)
- # Requires INCLUDE_DIRECTORIES target property in CMake 2.8.8
- # and POSITION_INDEPENDENT_CODE target property in 2.8.9
- if (NOT NO_GUI)
- expect_pass(test_use_modules_function)
- endif()
- expect_pass(test_umbrella_config)
-else()
- message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\" or \"test_umbrella_config\"")
-endif()
-
+expect_pass(test_umbrella_config)
expect_pass(test_wrap_cpp_and_resources)
if (NOT NO_WIDGETS)
expect_pass(test_dependent_modules)
@@ -90,12 +80,8 @@ if (NOT NO_DBUS)
expect_pass(test_dbus_module)
endif()
expect_pass(test_multiple_find_package)
-if (NOT WIN32 OR (WIN32 AND NOT CMAKE_VERSION VERSION_LESS 2.8.11))
- # Broken on windows on earlier CMake versions.
- # http://public.kitware.com/Bug/view.php?id=13392
- expect_pass(test_add_resources_delayed_file)
- expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file)
-endif()
+expect_pass(test_add_resources_delayed_file)
+expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file)
expect_pass(test_private_includes)
expect_pass(test_private_targets)
expect_pass(test_testlib_definitions)
@@ -153,7 +139,7 @@ if (QT_WITH_ANGLE OR (NOT WIN32 AND NOT APPLE AND NOT NO_EGL))
endif()
expect_pass(test_opengl_lib)
-if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT NO_WIDGETS)
+if (NOT NO_WIDGETS)
expect_pass(test_interface)
endif()
@@ -166,4 +152,3 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here
# Reason: SKIP_* properties were added in CMake 3.8 only
expect_pass(test_QTBUG-63422)
-endif()
diff --git a/tests/auto/cmake/test_use_modules_function/CMakeLists.txt b/tests/auto/cmake/test_use_modules_function/CMakeLists.txt
deleted file mode 100644
index be05c75054..0000000000
--- a/tests/auto/cmake/test_use_modules_function/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-cmake_minimum_required(VERSION 2.8)
-
-project(test_use_modules_function)
-
-set(CMAKE_AUTOMOC ON)
-
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-add_executable(two two.cpp)
-add_executable(three three.cpp)
-
-find_package(Qt5Core)
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
-
-qt5_use_modules(two Test)
-qt5_use_modules(three Gui Test)
diff --git a/tests/auto/cmake/test_use_modules_function/three.cpp b/tests/auto/cmake/test_use_modules_function/three.cpp
deleted file mode 100644
index 507cc8479d..0000000000
--- a/tests/auto/cmake/test_use_modules_function/three.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** 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-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest>
-#include <QWindow>
-
-class Three : public QObject
-{
- Q_OBJECT
-public:
- Three(QObject *parent = 0)
- {
- QWindow *w = new QWindow;
- w->show();
- }
-};
-
-QTEST_MAIN(Three)
-
-#include "three.moc"
diff --git a/tests/auto/cmake/test_use_modules_function/two.cpp b/tests/auto/cmake/test_use_modules_function/two.cpp
deleted file mode 100644
index 44eb7fe96e..0000000000
--- a/tests/auto/cmake/test_use_modules_function/two.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** 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 General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** 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-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest>
-
-class Two : public QObject
-{
- Q_OBJECT
-public:
- Two(QObject *parent = 0)
- {
-
- }
-};
-
-QTEST_MAIN(Two)
-
-#include "two.moc"
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index 9d47bb2884..83492188a9 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -1384,16 +1384,25 @@ void tst_QDir::absoluteFilePath_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<QString>("expectedFilePath");
- QTest::newRow("0") << "/etc" << "/passwd" << "/passwd";
- QTest::newRow("1") << "/etc" << "passwd" << "/etc/passwd";
- QTest::newRow("2") << "/" << "passwd" << "/passwd";
- QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path";
- QTest::newRow("4") << "" << "" << QDir::currentPath();
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- QTest::newRow("5") << "//machine" << "share" << "//machine/share";
+ QTest::newRow("UNC") << "//machine" << "share" << "//machine/share";
+ QTest::newRow("Drive") << "c:/side/town" << "/my/way/home" << "c:/my/way/home";
+#endif
+
+#ifdef Q_OS_WIN
+#define DRIVE "Q:"
+#else
+#define DRIVE
#endif
+ QTest::newRow("0") << DRIVE "/etc" << "/passwd" << DRIVE "/passwd";
+ QTest::newRow("1") << DRIVE "/etc" << "passwd" << DRIVE "/etc/passwd";
+ QTest::newRow("2") << DRIVE "/" << "passwd" << DRIVE "/passwd";
+ QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path";
+ QTest::newRow("4") << "" << "" << QDir::currentPath();
+
QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
+#undef DRIVE
}
void tst_QDir::absoluteFilePath()
diff --git a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
index ba5e9eaaa1..d41efa18f5 100644
--- a/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
+++ b/tests/auto/corelib/io/qipaddress/tst_qipaddress.cpp
@@ -288,9 +288,6 @@ void tst_QIpAddress::parseIp6_data()
<< "ffee:ddcc:bbaa:9988:7766:5544:3322:1100"
<< Ip6(0xffee, 0xddcc, 0xbbaa, 0x9988, 0x7766, 0x5544, 0x3322, 0x1100);
- // too many zeroes
- QTest::newRow("0:0:0:0:0:0:0:00103") << "0:0:0:0:0:0:0:00103" << Ip6(0,0,0,0,0,0,0,0x103);
-
// double-colon
QTest::newRow("::1:2:3:4:5:6:7") << "::1:2:3:4:5:6:7" << Ip6(0,1,2,3,4,5,6,7);
QTest::newRow("1:2:3:4:5:6:7::") << "1:2:3:4:5:6:7::" << Ip6(1,2,3,4,5,6,7,0);
@@ -382,6 +379,9 @@ void tst_QIpAddress::invalidParseIp6_data()
// too big number
QTest::newRow("0:0:0:0:0:0:0:10103") << "0:0:0:0:0:0:0:10103";
+ // too many zeroes
+ QTest::newRow("0:0:0:0:0:0:0:00103") << "0:0:0:0:0:0:0:00103";
+
// too short
QTest::newRow("0:0:0:0:0:0:0:") << "0:0:0:0:0:0:0:";
QTest::newRow("0:0:0:0:0:0:0") << "0:0:0:0:0:0:0";
@@ -438,6 +438,8 @@ void tst_QIpAddress::invalidParseIp6()
#if defined(__GLIBC__) && defined(AF_INET6)
Ip6 inet_result;
bool inet_ok = inet_pton(AF_INET6, address.toLatin1(), &inet_result.u8);
+ if (__GLIBC_MINOR__ < 26)
+ QEXPECT_FAIL("0:0:0:0:0:0:0:00103", "Bug fixed in glibc 2.26", Continue);
QVERIFY(!inet_ok);
#endif
diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
index 571288675e..11a9b3f189 100644
--- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
+++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
@@ -203,6 +203,7 @@ private:
private slots:
void initTestCase()
{
+ qputenv("XDG_CONFIG_DIRS", "/does/not/exist");
qputenv("QT_MESSAGE_PATTERN", QByteArray("%{category}: %{type},%{message}"));
oldMessageHandler = qInstallMessageHandler(myCustomMessageHandler);
// Create configuration
diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
index a74ea3a89e..5b61a6007d 100644
--- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
+++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
@@ -50,6 +50,7 @@ private slots:
{
// ensure a clean environment
QStandardPaths::setTestModeEnabled(true);
+ qputenv("XDG_CONFIG_DIRS", "/does/not/exist");
qunsetenv("QT_LOGGING_CONF");
qunsetenv("QT_LOGGING_RULES");
}
diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST
index a278af12d3..b355bb0f75 100644
--- a/tests/auto/corelib/io/qprocess/BLACKLIST
+++ b/tests/auto/corelib/io/qprocess/BLACKLIST
@@ -4,3 +4,6 @@ redhatenterpriselinuxworkstation-6.6
[fileWriterProcess]
msvc-2015 ci
msvc-2017 ci
+[softExitInSlots]
+# QTBUG-66903
+windows
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
index 109f5b77f6..482ed8d130 100644
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
@@ -586,7 +586,6 @@ void tst_QEventLoop::deliverInDefinedOrder()
}
}
- QTest::qWait(30);
for (int o = 0; o < NbObject; o++) {
QTRY_COMPARE(objects[o].count, int(NbEvent));
}
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index cc628ee26e..c6fd5d17c2 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -141,6 +141,14 @@ public:
class CustomNonQObject {};
class GadgetDerived : public CustomGadget {};
+// cannot use Q_GADGET due to moc limitations but wants to behave like
+// a Q_GADGET in Qml land
+template<typename T>
+class GadgetDerivedAndTyped : public CustomGadget {};
+
+Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>)
+Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>*)
+
void tst_QMetaType::defined()
{
QCOMPARE(int(QMetaTypeId2<QString>::Defined), 1);
@@ -157,6 +165,10 @@ void tst_QMetaType::defined()
QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
QVERIFY(!QMetaTypeId2<CustomNonQObject*>::Defined);
QVERIFY(!QMetaTypeId2<CustomGadget_NonDefaultConstructible>::Defined);
+
+ // registered with Q_DECLARE_METATYPE
+ QVERIFY(QMetaTypeId2<GadgetDerivedAndTyped<int>>::Defined);
+ QVERIFY(QMetaTypeId2<GadgetDerivedAndTyped<int>*>::Defined);
}
struct Bar
@@ -396,6 +408,10 @@ void tst_QMetaType::typeName_data()
QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*");
QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId<CustomQObject::CustomQEnum>() << QString::fromLatin1("CustomQObject::CustomQEnum");
QTest::newRow("Qt::ArrowType") << ::qMetaTypeId<Qt::ArrowType>() << QString::fromLatin1("Qt::ArrowType");
+
+ // template instance class derived from Q_GADGET enabled class
+ QTest::newRow("GadgetDerivedAndTyped<int>") << ::qMetaTypeId<GadgetDerivedAndTyped<int>>() << QString::fromLatin1("GadgetDerivedAndTyped<int>");
+ QTest::newRow("GadgetDerivedAndTyped<int>*") << ::qMetaTypeId<GadgetDerivedAndTyped<int>*>() << QString::fromLatin1("GadgetDerivedAndTyped<int>*");
}
void tst_QMetaType::typeName()
@@ -1703,6 +1719,9 @@ void tst_QMetaType::metaObject_data()
QTest::newRow("MyGadget*") << ::qMetaTypeId<MyGadget*>() << &MyGadget::staticMetaObject << false << true << false;
QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false << false;
QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false << false;
+
+ QTest::newRow("GadgetDerivedAndTyped<int>") << ::qMetaTypeId<GadgetDerivedAndTyped<int>>() << &GadgetDerivedAndTyped<int>::staticMetaObject << true << false << false;
+ QTest::newRow("GadgetDerivedAndTyped<int>*") << ::qMetaTypeId<GadgetDerivedAndTyped<int>*>() << &GadgetDerivedAndTyped<int>::staticMetaObject << false << true << false;
}
diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
index 76efa008f7..e2a0c2dad3 100644
--- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
+++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
@@ -125,6 +125,7 @@ public:
HANDLE eventHandle() const { return notifier.handle(); }
int numberOfTimesActivated() const { return activatedCount; }
void setEnabled(bool b) { notifier.setEnabled(b); }
+ bool isEnabled() const { return notifier.isEnabled(); }
signals:
void activated();
@@ -218,8 +219,9 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot()
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;
+ auto isActivatedOrDisabled = [&events](int i) {
+ return !events.at(i) || !events.at(i)->isEnabled()
+ || events.at(i)->numberOfTimesActivated() > 0;
};
for (auto &e : events) {
@@ -230,8 +232,10 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot()
else
events.at(i)->setEnabled(false);
}
- if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), isActivatedOrNull))
+ if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(),
+ isActivatedOrDisabled)) {
QTimer::singleShot(0, &QTestEventLoop::instance(), SLOT(exitLoop()));
+ }
});
}
for (int i : notifiersToSignal)
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index abc06bfe85..3144c3071c 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -214,6 +214,8 @@ void tst_QMimeDatabase::mimeTypeForName()
QMimeType doesNotExist = db.mimeTypeForName(QString::fromLatin1("foobar/x-doesnot-exist"));
QVERIFY(!doesNotExist.isValid());
+ QCOMPARE(doesNotExist.comment(), QString());
+ QCOMPARE(doesNotExist.aliases(), QStringList());
// TODO move to findByFile
#ifdef Q_OS_LINUX
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 17763f31f9..810698fb4e 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -4667,11 +4667,14 @@ void tst_QStateMachine::clonedSignals()
s1->addTransition(t1);
machine.setInitialState(s1);
+ QSignalSpy startedSpy(&machine, &QStateMachine::started);
machine.start();
- QTest::qWait(1);
+ QVERIFY(startedSpy.wait());
+ QSignalSpy transitionSpy(t1, &CloneSignalTransition::triggered);
emitter.emitSignalWithDefaultArg();
- QTest::qWait(1);
+ QTRY_COMPARE(transitionSpy.count(), 1);
+
QCOMPARE(t1->eventSignalIndex, emitter.metaObject()->indexOfSignal("signalWithDefaultArg()"));
TEST_ACTIVE_CHANGED(s1, 2);
TEST_ACTIVE_CHANGED(s2, 1);
diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
index a16e9e377c..b2ef516b4e 100644
--- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
+++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
@@ -82,11 +82,11 @@ void tst_QFutureWatcher::startFinish()
QVERIFY(finishedSpy.isValid());
futureWatcher.setFuture(QtConcurrent::run(sleeper));
- QTest::qWait(10); // spin the event loop to deliver queued signals.
+ QVERIFY(startedSpy.wait());
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 0);
futureWatcher.future().waitForFinished();
- QTest::qWait(10);
+ QVERIFY(finishedSpy.wait());
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 1);
}
@@ -232,13 +232,12 @@ void tst_QFutureWatcher::resultAt()
void tst_QFutureWatcher::resultReadyAt()
{
QFutureWatcher<int> futureWatcher;
- QObject::connect(&futureWatcher, SIGNAL(resultReadyAt(int)), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+ QSignalSpy resultSpy(&futureWatcher, &QFutureWatcher<int>::resultReadyAt);
QFuture<int> future = (new IntTask())->start();
futureWatcher.setFuture(future);
- QTestEventLoop::instance().enterLoop(1);
- QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(resultSpy.wait());
// Setting the future again should give us another signal.
// (this is to prevent the race where the task associated
@@ -246,8 +245,7 @@ void tst_QFutureWatcher::resultReadyAt()
futureWatcher.setFuture(QFuture<int>());
futureWatcher.setFuture(future);
- QTestEventLoop::instance().enterLoop(1);
- QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(resultSpy.wait());
}
class SignalSlotObject : public QObject
@@ -320,19 +318,17 @@ void tst_QFutureWatcher::futureSignals()
const int progress = 1;
a.setProgressValue(progress);
- QTest::qWait(10);
- QCOMPARE(progressSpy.count(), 2);
+ QTRY_COMPARE(progressSpy.count(), 2);
QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 0);
QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 1);
const int result = 10;
a.reportResult(&result);
- QTest::qWait(10);
+ QVERIFY(resultReadySpy.wait());
QCOMPARE(resultReadySpy.count(), 1);
a.reportFinished(&result);
- QTest::qWait(10);
- QCOMPARE(resultReadySpy.count(), 2);
+ QTRY_COMPARE(resultReadySpy.count(), 2);
QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 0); // check the index
QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 1);
@@ -373,7 +369,7 @@ void tst_QFutureWatcher::watchFinishedFuture()
QVERIFY(canceledSpy.isValid());
watcher.setFuture(f);
- QTest::qWait(10);
+ QVERIFY(finishedSpy.wait());
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 1);
@@ -407,7 +403,7 @@ void tst_QFutureWatcher::watchCanceledFuture()
QVERIFY(canceledSpy.isValid());
watcher.setFuture(f);
- QTest::qWait(10);
+ QVERIFY(finishedSpy.wait());
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 1);
@@ -434,7 +430,7 @@ void tst_QFutureWatcher::disconnectRunningFuture()
const int result = 10;
a.reportResult(&result);
- QTest::qWait(10);
+ QVERIFY(resultReadySpy.wait());
QCOMPARE(resultReadySpy.count(), 1);
delete watcher;
@@ -624,7 +620,7 @@ void tst_QFutureWatcher::changeFuture()
QSignalSpy resultReadySpy(&watcher, &QFutureWatcher<int>::resultReadyAt);
QVERIFY(resultReadySpy.isValid());
- watcher.setFuture(a); // Watch 'a' which will genere a resultReady event.
+ watcher.setFuture(a); // Watch 'a' which will generate a resultReady event.
watcher.setFuture(b); // But oh no! we're switching to another future
QTest::qWait(10); // before the event gets delivered.
@@ -633,7 +629,7 @@ void tst_QFutureWatcher::changeFuture()
watcher.setFuture(a);
watcher.setFuture(b);
watcher.setFuture(a); // setting it back gets us one event, not two.
- QTest::qWait(10);
+ QVERIFY(resultReadySpy.wait());
QCOMPARE(resultReadySpy.count(), 1);
}
@@ -653,13 +649,15 @@ void tst_QFutureWatcher::cancelEvents()
SignalSlotObject object;
connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int)));
+ QSignalSpy finishedSpy(&watcher, &QFutureWatcher<int>::finished);
QSignalSpy resultReadySpy(&watcher, &QFutureWatcher<int>::resultReadyAt);
+ QVERIFY(finishedSpy.isValid());
QVERIFY(resultReadySpy.isValid());
watcher.setFuture(a);
watcher.cancel();
- QTest::qWait(10);
+ QVERIFY(finishedSpy.wait());
QCOMPARE(resultReadySpy.count(), 0);
}
@@ -730,15 +728,17 @@ void tst_QFutureWatcher::finishedState()
iface.reportStarted();
QFuture<int> future = iface.future();
QFutureWatcher<int> watcher;
+ QSignalSpy startedSpy(&watcher, &QFutureWatcher<int>::started);
+ QSignalSpy finishedSpy(&watcher, &QFutureWatcher<int>::finished);
watcher.setFuture(future);
- QTest::qWait(10);
+ QVERIFY(startedSpy.wait());
iface.reportFinished();
QVERIFY(future.isFinished());
QVERIFY(!watcher.isFinished());
- QTest::qWait(10);
+ QVERIFY(finishedSpy.wait());
QVERIFY(watcher.isFinished());
}
@@ -752,18 +752,20 @@ void tst_QFutureWatcher::throttling()
iface.reportStarted();
QFuture<int> future = iface.future();
QFutureWatcher<int> watcher;
+ QSignalSpy resultSpy(&watcher, &QFutureWatcher<int>::resultReadyAt);
watcher.setFuture(future);
QVERIFY(!iface.isThrottled());
- for (int i = 0; i < 1000; ++i) {
+ const int resultCount = 1000;
+ for (int i = 0; i < resultCount; ++i) {
int result = 0;
iface.reportResult(result);
}
QVERIFY(iface.isThrottled());
- QTest::qWait(100); // process events.
+ QTRY_COMPARE(resultSpy.count(), resultCount); // Process the results
QVERIFY(!iface.isThrottled());
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index a67ecc2471..b7134d0454 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -37,6 +37,8 @@ class tst_QSemaphore : public QObject
Q_OBJECT
private slots:
void acquire();
+ void multiRelease();
+ void multiAcquireRelease();
void tryAcquire();
void tryAcquireWithTimeout_data();
void tryAcquireWithTimeout();
@@ -149,6 +151,73 @@ void tst_QSemaphore::acquire()
QCOMPARE(semaphore.available(), 0);
}
+void tst_QSemaphore::multiRelease()
+{
+ class Thread : public QThread
+ {
+ public:
+ QSemaphore &sem;
+ Thread(QSemaphore &sem) : sem(sem) {}
+
+ void run() override
+ {
+ sem.acquire();
+ }
+ };
+
+ QSemaphore sem;
+ QVector<Thread *> threads;
+ threads.resize(4);
+
+ for (Thread *&t : threads)
+ t = new Thread(sem);
+ for (Thread *&t : threads)
+ t->start();
+
+ // wait for all threads to reach the sem.acquire() and then
+ // release them all
+ QTest::qSleep(1);
+ sem.release(threads.size());
+
+ for (Thread *&t : threads)
+ t->wait();
+ qDeleteAll(threads);
+}
+
+void tst_QSemaphore::multiAcquireRelease()
+{
+ class Thread : public QThread
+ {
+ public:
+ QSemaphore &sem;
+ Thread(QSemaphore &sem) : sem(sem) {}
+
+ void run() override
+ {
+ sem.acquire();
+ sem.release();
+ }
+ };
+
+ QSemaphore sem;
+ QVector<Thread *> threads;
+ threads.resize(4);
+
+ for (Thread *&t : threads)
+ t = new Thread(sem);
+ for (Thread *&t : threads)
+ t->start();
+
+ // wait for all threads to reach the sem.acquire() and then
+ // release them all
+ QTest::qSleep(1);
+ sem.release();
+
+ for (Thread *&t : threads)
+ t->wait();
+ qDeleteAll(threads);
+}
+
void tst_QSemaphore::tryAcquire()
{
QSemaphore semaphore;
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index 0405896ca7..aee243d880 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -988,9 +988,7 @@ void tst_QThread::exitAndStart()
connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
- QTest::qWait(50);
- while(!thread.wait(10))
- QTest::qWait(10);
+ QTRY_VERIFY(thread.wait(10));
QCOMPARE(sync2.m_prop, 89);
QCOMPARE(sync1.m_prop, 89);
}
@@ -1026,9 +1024,7 @@ void tst_QThread::exitAndExec()
connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
- QTest::qWait(50);
- while(!thread.wait(10))
- QTest::qWait(10);
+ QTRY_VERIFY(thread.wait(10));
QCOMPARE(sync2.m_prop, 89);
QCOMPARE(sync1.m_prop, 89);
}
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 919f9cb718..f8432b8472 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -2658,8 +2658,8 @@ void tst_QDateTime::zoneAtTime_data()
ADDROW("before:NPT", "Asia/Kathmandu", QDate(1985, 12, 31), 19800); // 5:30
ADDROW("after:NPT", "Asia/Kathmandu", QDate(1986, 1, 1), 20700); // 5:45
// The two that have skipped a day (each):
- ADDROW("before:LINT", "Pacific/Kiritimati", QDate(1994, 12, 31), -36000);
- ADDROW("after:LINT", "Pacific/Kiritimati", QDate(1995, 2, 1), 14 * 3600);
+ ADDROW("before:LINT", "Pacific/Kiritimati", QDate(1994, 12, 30), -36000);
+ ADDROW("after:LINT", "Pacific/Kiritimati", QDate(1995, 1, 2), 14 * 3600);
ADDROW("after:WST", "Pacific/Apia", QDate(2011, 12, 31), 14 * 3600);
#endif // MS lacks ACWST, NPT; doesn't grok date-line crossings; and Windows 7 lacks LINT.
ADDROW("before:WST", "Pacific/Apia", QDate(2011, 12, 29), -36000);
diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
index 0714883855..79309f960d 100644
--- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
+++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
@@ -54,6 +54,7 @@ private slots:
void testCbrtDouble();
void testCbrtFloat();
void cpp11();
+ void quadraticEquation();
};
void tst_QEasingCurve::type()
@@ -804,5 +805,74 @@ void tst_QEasingCurve::cpp11()
#endif
}
+void tst_QEasingCurve::quadraticEquation() {
+ // We find the value for a given time by solving a cubic equation.
+ // ax^3 + bx^2 + cx + d = 0
+ // However, the solver also needs to take care of cases where a = 0,
+ // b = 0 or c = 0, and the equation becomes quadratic, linear or invalid.
+ // A naive cubic solver might divide by zero and return nan, even
+ // when the solution is a real number.
+ // This test should triggers those cases.
+
+ {
+ // If the control points are spaced 1/3 apart of the distance of the
+ // start- and endpoint, the equation becomes linear.
+ QEasingCurve test(QEasingCurve::BezierSpline);
+ const qreal p1 = 1.0 / 3.0;
+ const qreal p2 = 1.0 - 1.0 / 3.0;
+ const qreal p3 = 1.0;
+
+ test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
+ QVERIFY(qAbs(test.valueForProgress(0.25) - 0.15625) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.5) - 0.5) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.75) - 0.84375) < 1e-6);
+ }
+
+ {
+ // If both the start point and the first control point
+ // are placed a 0.0, and the second control point is
+ // placed at 1/3, we get a case where a = 0 and b != 0
+ // i.e. a quadratic equation.
+ QEasingCurve test(QEasingCurve::BezierSpline);
+ const qreal p1 = 0.0;
+ const qreal p2 = 1.0 / 3.0;
+ const qreal p3 = 1.0;
+ test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
+ QVERIFY(qAbs(test.valueForProgress(0.25) - 0.5) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792893) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950962) < 1e-6);
+ }
+
+ {
+ // If both the start point and the first control point
+ // are placed a 0.0, and the second control point is
+ // placed close to 1/3, we get a case where a = ~0 and b != 0.
+ // It's not truly a quadratic equation, but should be treated
+ // as one, because it causes some cubic solvers to fail.
+ QEasingCurve test(QEasingCurve::BezierSpline);
+ const qreal p1 = 0.0;
+ const qreal p2 = 1.0 / 3.0 + 1e-6;
+ const qreal p3 = 1.0;
+ test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
+ QVERIFY(qAbs(test.valueForProgress(0.25) - 0.499999) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792892) < 1e-6);
+ QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950961) < 1e-6);
+ }
+
+ {
+ // A bad case, where the segment is of zero length.
+ // However, it might still happen in user code,
+ // and we should return a sensible answer.
+ QEasingCurve test(QEasingCurve::BezierSpline);
+ const qreal p0 = 0.0;
+ const qreal p1 = p0;
+ const qreal p2 = p0;
+ const qreal p3 = p0;
+ test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0));
+ test.addCubicBezierSegment(QPointF(p3, 1.0), QPointF(1.0, 1.0), QPointF(1.0, 1.0));
+ QCOMPARE(test.valueForProgress(0.0), 0.0);
+ }
+}
+
QTEST_MAIN(tst_QEasingCurve)
#include "tst_qeasingcurve.moc"
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index d5e2935d28..375cecd521 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -79,9 +79,7 @@ private slots:
void ctor();
void emptyCtor();
- void legacyNames();
void consistentC();
- void unixLocaleName();
void matchingLocales();
void stringToDouble_data();
void stringToDouble();
@@ -108,8 +106,6 @@ private slots:
void toDateTime();
void negativeNumbers();
void numberOptions();
- void testNames_data();
- void testNames();
void dayName_data();
void dayName();
void standaloneDayName_data();
@@ -141,8 +137,18 @@ private slots:
void formattedDataSize();
void bcp47Name();
+ void systemLocale_data();
void systemLocale();
+ // *** ORDER-DEPENDENCY *** (This Is Bad.)
+ // Test order is determined by order of declaration here: *all* tests that
+ // QLocale::setDefault() *must* appear *after* all other tests !
+ void defaulted_ctor(); // This one must be the first of these.
+ void legacyNames();
+ void unixLocaleName();
+ void testNames_data();
+ void testNames();
+ // DO NOT add tests here unless they QLocale::setDefault(); see above.
private:
QString m_decimal, m_thousand, m_sdate, m_ldate, m_time;
QString m_sysapp;
@@ -232,6 +238,23 @@ void tst_QLocale::ctor()
TEST_CTOR(Chinese, LatinScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
#undef TEST_CTOR
+}
+
+void tst_QLocale::defaulted_ctor()
+{
+ QLocale default_locale = QLocale::system();
+ QLocale::Language default_lang = default_locale.language();
+ QLocale::Country default_country = default_locale.country();
+
+ qDebug("Default: %s/%s", QLocale::languageToString(default_lang).toLatin1().constData(),
+ QLocale::countryToString(default_country).toLatin1().constData());
+
+ {
+ QLocale l(QLocale::C, QLocale::AnyCountry);
+ QCOMPARE(l.language(), QLocale::C);
+ QCOMPARE(l.country(), QLocale::AnyCountry);
+ }
+
#define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \
{ \
QLocale l(QLocale::req_lang, QLocale::req_country); \
@@ -239,11 +262,6 @@ void tst_QLocale::ctor()
QCOMPARE((int)l.country(), (int)exp_country); \
}
- {
- QLocale l(QLocale::C, QLocale::AnyCountry);
- QCOMPARE(l.language(), QLocale::C);
- QCOMPARE(l.country(), QLocale::AnyCountry);
- }
TEST_CTOR(AnyLanguage, AnyCountry, default_lang, default_country)
TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry)
TEST_CTOR(Aymara, AnyCountry, default_lang, default_country)
@@ -1961,10 +1979,11 @@ void tst_QLocale::testNames_data()
QTest::addColumn<int>("language");
QTest::addColumn<int>("country");
+ QLocale::setDefault(QLocale(QLocale::C)); // Ensures predictable fall-backs
+
for (int i = 0; i < locale_data_count; ++i) {
const QLocaleData &item = locale_data[i];
-
const QString testName = QLatin1String("data_") + QString::number(i) + QLatin1String(" (")
+ QLocale::languageToString((QLocale::Language)item.m_language_id)
+ QLatin1Char('/') + QLocale::countryToString((QLocale::Country)item.m_country_id)
@@ -2664,27 +2683,31 @@ private:
const QLocale m_locale;
};
+void tst_QLocale::systemLocale_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QLocale::Language>("language");
+ QTest::addRow("catalan") << QString("ca") << QLocale::Catalan;
+ QTest::addRow("ukrainian") << QString("uk") << QLocale::Ukrainian;
+ QTest::addRow("german") << QString("de") << QLocale::German;
+}
+
void tst_QLocale::systemLocale()
{
QLocale originalLocale;
+ QLocale originalSystemLocale = QLocale::system();
- MySystemLocale *sLocale = new MySystemLocale(QLocale("uk"));
- QCOMPARE(QLocale().language(), QLocale::Ukrainian);
- QCOMPARE(QLocale::system().language(), QLocale::Ukrainian);
- delete sLocale;
-
- sLocale = new MySystemLocale(QLocale("ca"));
- QCOMPARE(QLocale().language(), QLocale::Catalan);
- QCOMPARE(QLocale::system().language(), QLocale::Catalan);
- delete sLocale;
+ QFETCH(QString, name);
+ QFETCH(QLocale::Language, language);
- sLocale = new MySystemLocale(QLocale("de"));
- QCOMPARE(QLocale().language(), QLocale::German);
- QCOMPARE(QLocale::system().language(), QLocale::German);
- delete sLocale;
+ {
+ MySystemLocale sLocale(name);
+ QCOMPARE(QLocale().language(), language);
+ QCOMPARE(QLocale::system().language(), language);
+ }
QCOMPARE(QLocale(), originalLocale);
- QCOMPARE(QLocale::system(), originalLocale);
+ QCOMPARE(QLocale::system(), originalSystemLocale);
}
QTEST_MAIN(tst_QLocale)
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index ced1d08d65..5737db760c 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -957,44 +957,74 @@ void tst_QVarLengthArray::insertMove()
QCOMPARE(MyBase::copyCount, 0);
{
- QVarLengthArray<MyMovable, 4> vec;
+ QVarLengthArray<MyMovable, 6> vec;
MyMovable m1;
MyMovable m2;
MyMovable m3;
MyMovable m4;
+ MyMovable m5;
+ MyMovable m6;
QCOMPARE(MyBase::copyCount, 0);
- QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::liveCount, 6);
vec.append(std::move(m3));
+ QVERIFY(m3.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m3));
QCOMPARE(MyBase::errorCount, 0);
- QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 1);
vec.push_back(std::move(m4));
+ QVERIFY(m4.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m3));
QVERIFY(vec.at(1).wasConstructedAt(&m4));
QCOMPARE(MyBase::errorCount, 0);
- QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 2);
vec.prepend(std::move(m1));
+ QVERIFY(m1.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m3));
QVERIFY(vec.at(2).wasConstructedAt(&m4));
QCOMPARE(MyBase::errorCount, 0);
- QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 3);
vec.insert(1, std::move(m2));
+ QVERIFY(m2.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::liveCount, 6);
+ QCOMPARE(MyBase::movedCount, 4);
+
+ vec += std::move(m5);
+ QVERIFY(m5.wasConstructedAt(nullptr));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ QVERIFY(vec.at(4).wasConstructedAt(&m5));
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::liveCount, 6);
+ QCOMPARE(MyBase::movedCount, 5);
+
+ vec << std::move(m6);
+ QVERIFY(m6.wasConstructedAt(nullptr));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ QVERIFY(vec.at(4).wasConstructedAt(&m5));
+ QVERIFY(vec.at(5).wasConstructedAt(&m6));
QCOMPARE(MyBase::copyCount, 0);
- QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::errorCount, 0);
- QCOMPARE(MyBase::movedCount, 4);
+ QCOMPARE(MyBase::movedCount, 6);
}
QCOMPARE(MyBase::liveCount, 0);
QCOMPARE(MyBase::errorCount, 0);
@@ -1008,24 +1038,48 @@ void tst_QVarLengthArray::nonCopyable()
std::unique_ptr<int> val2(new int(2));
std::unique_ptr<int> val3(new int(3));
std::unique_ptr<int> val4(new int(4));
+ std::unique_ptr<int> val5(new int(5));
+ std::unique_ptr<int> val6(new int(6));
int *const ptr1 = val1.get();
int *const ptr2 = val2.get();
int *const ptr3 = val3.get();
int *const ptr4 = val4.get();
+ int *const ptr5 = val5.get();
+ int *const ptr6 = val6.get();
vec.append(std::move(val3));
+ QVERIFY(!val3);
QVERIFY(ptr3 == vec.at(0).get());
vec.append(std::move(val4));
+ QVERIFY(!val4);
QVERIFY(ptr3 == vec.at(0).get());
QVERIFY(ptr4 == vec.at(1).get());
vec.prepend(std::move(val1));
+ QVERIFY(!val1);
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr3 == vec.at(1).get());
QVERIFY(ptr4 == vec.at(2).get());
vec.insert(1, std::move(val2));
+ QVERIFY(!val2);
+ QVERIFY(ptr1 == vec.at(0).get());
+ QVERIFY(ptr2 == vec.at(1).get());
+ QVERIFY(ptr3 == vec.at(2).get());
+ QVERIFY(ptr4 == vec.at(3).get());
+ vec += std::move(val5);
+ QVERIFY(!val5);
+ QVERIFY(ptr1 == vec.at(0).get());
+ QVERIFY(ptr2 == vec.at(1).get());
+ QVERIFY(ptr3 == vec.at(2).get());
+ QVERIFY(ptr4 == vec.at(3).get());
+ QVERIFY(ptr5 == vec.at(4).get());
+ vec << std::move(val6);
+ QVERIFY(!val6);
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr2 == vec.at(1).get());
QVERIFY(ptr3 == vec.at(2).get());
+ QVERIFY(ptr4 == vec.at(3).get());
+ QVERIFY(ptr5 == vec.at(4).get());
+ QVERIFY(ptr6 == vec.at(5).get());
}
QTEST_APPLESS_MAIN(tst_QVarLengthArray)
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index ef10357b6d..a7faeb5ca5 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -2895,26 +2895,59 @@ void tst_QVector::insertMove() const
const int instancesCount = Movable::counter.loadAcquire();
{
QVector<Movable> vec;
+ vec.reserve(7);
+ Movable m0;
Movable m1;
Movable m2;
Movable m3;
Movable m4;
+ Movable m5;
+ Movable m6;
vec.append(std::move(m3));
+ QVERIFY(m3.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m3));
vec.push_back(std::move(m4));
+ QVERIFY(m4.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m3));
QVERIFY(vec.at(1).wasConstructedAt(&m4));
vec.prepend(std::move(m1));
+ QVERIFY(m1.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m3));
QVERIFY(vec.at(2).wasConstructedAt(&m4));
vec.insert(1, std::move(m2));
+ QVERIFY(m2.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m2));
QVERIFY(vec.at(2).wasConstructedAt(&m3));
-
- QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 8);
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ vec += std::move(m5);
+ QVERIFY(m5.wasConstructedAt(nullptr));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ QVERIFY(vec.at(4).wasConstructedAt(&m5));
+ vec << std::move(m6);
+ QVERIFY(m6.wasConstructedAt(nullptr));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+ QVERIFY(vec.at(3).wasConstructedAt(&m4));
+ QVERIFY(vec.at(4).wasConstructedAt(&m5));
+ QVERIFY(vec.at(5).wasConstructedAt(&m6));
+ vec.push_front(std::move(m0));
+ QVERIFY(m0.wasConstructedAt(nullptr));
+ QVERIFY(vec.at(0).wasConstructedAt(&m0));
+ QVERIFY(vec.at(1).wasConstructedAt(&m1));
+ QVERIFY(vec.at(2).wasConstructedAt(&m2));
+ QVERIFY(vec.at(3).wasConstructedAt(&m3));
+ QVERIFY(vec.at(4).wasConstructedAt(&m4));
+ QVERIFY(vec.at(5).wasConstructedAt(&m5));
+ QVERIFY(vec.at(6).wasConstructedAt(&m6));
+
+ QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14);
}
QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
}
diff --git a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
index 80f22ad867..fdcd8b07c7 100644
--- a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
+++ b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
@@ -768,9 +768,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNot()
con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
obj.emitSignal("scriptableSignalVoid", QVariant());
obj.emitSignal("nonScriptableSignalVoid", QVariant());
- QTest::qWait(200);
- QCOMPARE(spy.count, 1); // only /p1 must have emitted
+ QTRY_COMPARE(spy.count, 1); // only /p1 must have emitted
QCOMPARE(spy.interface, QString("local.MyObject"));
QCOMPARE(spy.name, QString("scriptableSignalVoid"));
QCOMPARE(spy.path, QString("/p1"));
@@ -788,9 +787,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNot()
con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
obj.emitSignal("nonScriptableSignalVoid", QVariant());
- QTest::qWait(200);
- QCOMPARE(spy.count, 1); // only /p2 must have emitted now
+ QTRY_COMPARE(spy.count, 1); // only /p2 must have emitted now
QCOMPARE(spy.interface, QString("local.MyObject"));
QCOMPARE(spy.name, QString("nonScriptableSignalVoid"));
QCOMPARE(spy.path, QString("/p2"));
@@ -1306,9 +1304,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer()
con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant());
emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant());
- QTest::qWait(200);
- QCOMPARE(spy.count, 1); // only /p1 must have emitted
+ QTRY_COMPARE(spy.count, 1); // only /p1 must have emitted
QCOMPARE(spy.interface, QString("local.MyObject"));
QCOMPARE(spy.name, QString("scriptableSignalVoid"));
QCOMPARE(spy.path, QString("/p1"));
@@ -1327,9 +1324,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer()
con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant());
- QTest::qWait(200);
- QCOMPARE(spy.count, 1); // only /p2 must have emitted now
+ QTRY_COMPARE(spy.count, 1); // only /p2 must have emitted now
QCOMPARE(spy.interface, QString("local.MyObject"));
QCOMPARE(spy.name, QString("nonScriptableSignalVoid"));
QCOMPARE(spy.path, QString("/p2"));
diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
index d521c18cef..77ae6f154d 100644
--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
+++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
@@ -136,9 +136,7 @@ void tst_QDBusConnection::sendSignalToName()
QVERIFY(con.send(msg));
- QTest::qWait(1000);
-
- QCOMPARE(spy.args.count(), 1);
+ QTRY_COMPARE(spy.args.count(), 1);
QCOMPARE(spy.args.at(0).toString(), QString("ping"));
}
@@ -215,8 +213,7 @@ void tst_QDBusConnection::sendAsync()
"/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
QVERIFY(con.callWithCallback(msg, &spy, SLOT(asyncReply(QDBusMessage))));
- QTest::qWait(1000);
-
+ QTRY_COMPARE(spy.args.count(), 1);
QCOMPARE(spy.args.value(0).typeName(), "QStringList");
QVERIFY(spy.args.at(0).toStringList().contains(con.baseService()));
}
@@ -239,9 +236,7 @@ void tst_QDBusConnection::connect()
QVERIFY(con.send(msg));
- QTest::qWait(1000);
-
- QCOMPARE(spy.args.count(), 1);
+ QTRY_COMPARE(spy.args.count(), 1);
QCOMPARE(spy.args.at(0).toString(), QString("ping"));
}
@@ -1072,9 +1067,8 @@ void tst_QDBusConnection::connectSignal()
QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), &recv, SLOT(oneSlot(QString))));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString());
- QCOMPARE(recv.signalsReceived, 1);
// disconnect and try with a signature
recv.argumentReceived.clear();
@@ -1084,9 +1078,8 @@ void tst_QDBusConnection::connectSignal()
QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), "s", &recv, SLOT(oneSlot(QString))));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString());
- QCOMPARE(recv.signalsReceived, 1);
// confirm that we are, indeed, a unique connection
recv.argumentReceived.clear();
@@ -1094,9 +1087,8 @@ void tst_QDBusConnection::connectSignal()
QVERIFY(!con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), "s", &recv, SLOT(oneSlot(QString))));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString());
- QCOMPARE(recv.signalsReceived, 1);
}
void tst_QDBusConnection::slotsWithLessParameters()
@@ -1114,9 +1106,8 @@ void tst_QDBusConnection::slotsWithLessParameters()
QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), &recv, SLOT(oneSlot())));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, QString());
- QCOMPARE(recv.signalsReceived, 1);
// disconnect and try with a signature
recv.signalsReceived = 0;
@@ -1125,18 +1116,16 @@ void tst_QDBusConnection::slotsWithLessParameters()
QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), "s", &recv, SLOT(oneSlot())));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, QString());
- QCOMPARE(recv.signalsReceived, 1);
// confirm that we are, indeed, a unique connection
recv.signalsReceived = 0;
QVERIFY(!con.connect(con.baseService(), signal.path(), signal.interface(),
signal.member(), "s", &recv, SLOT(oneSlot())));
QVERIFY(con.send(signal));
- QTest::qWait(100);
+ QTRY_COMPARE(recv.signalsReceived, 1);
QCOMPARE(recv.argumentReceived, QString());
- QCOMPARE(recv.signalsReceived, 1);
}
void SignalReceiver::secondCallWithCallback()
diff --git a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
index 8bda5f5641..018b7c2a35 100644
--- a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
+++ b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
@@ -414,8 +414,7 @@ void tst_QDBusThreading::registerObjectInOtherThread()
QCOMPARE(functionSpy, Object_method);
QCOMPARE(threadSpy, th);
- QTest::qWait(100);
- QCOMPARE(signalSpy, 1);
+ QTRY_COMPARE(signalSpy, 1);
sem2.acquire(); // the object is gone
functionSpy = NoMethod;
@@ -462,8 +461,7 @@ void tst_QDBusThreading::registerAdaptorInOtherThread()
QCOMPARE(functionSpy, Adaptor_method);
QCOMPARE(threadSpy, th);
- QTest::qWait(100);
- QCOMPARE(signalSpy, 1);
+ QTRY_COMPARE(signalSpy, 1);
functionSpy = NoMethod;
threadSpy = 0;
diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
index 87fd5c0dc6..993ebbaac6 100644
--- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
+++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
@@ -41,10 +41,8 @@ class tst_QClipboard : public QObject
{
Q_OBJECT
private slots:
-#ifdef QT_NO_CLIPBOARD
void initTestCase();
- void cleanupTestCase();
-#else
+#if QT_CONFIG(clipboard)
void init();
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(Q_OS_QNX)
void copy_exit_paste();
@@ -58,19 +56,16 @@ private slots:
#endif
};
-#ifdef QT_NO_CLIPBOARD
void tst_QClipboard::initTestCase()
{
+#if !QT_CONFIG(clipboard)
QSKIP("This test requires clipboard support");
+#endif
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("Wayland: Manipulating the clipboard requires real input events. Can't auto test.");
}
-void tst_QClipboard::cleanupTestCase()
-{
- QSKIP("This test requires clipboard support");
-}
-
-#else
-
+#if QT_CONFIG(clipboard)
void tst_QClipboard::init()
{
#if QT_CONFIG(process)
@@ -436,7 +431,7 @@ void tst_QClipboard::clearBeforeSetText()
QCOMPARE(QGuiApplication::clipboard()->text(), text);
}
-#endif
+#endif // QT_CONFIG(clipboard)
QTEST_MAIN(tst_QClipboard)
diff --git a/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp
index d505f5a655..eb33cce95b 100644
--- a/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp
+++ b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp
@@ -93,6 +93,9 @@ void tst_QCursor::equality()
VERIFY_DIFFERENT(bitmapCursor, pixmapCursor);
// Empty pixmap
+ for (int i = 0; i < 18; ++i)
+ QTest::ignoreMessage(QtWarningMsg, "QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+
QPixmap emptyPixmap;
QCursor emptyPixmapCursor(emptyPixmap);
QCOMPARE(emptyPixmapCursor.shape(), Qt::ArrowCursor);
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index 4f27aeb899..fc011d726d 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -35,9 +35,12 @@
#include <QtGui/QFont>
#include <QtGui/QPalette>
#include <QtGui/QStyleHints>
+#include <qpa/qplatformintegration.h>
#include <qpa/qwindowsysteminterface.h>
#include <qgenericplugin.h>
+#include <private/qguiapplication_p.h>
+
#if defined(Q_OS_QNX)
#include <QOpenGLContext>
#endif
@@ -203,8 +206,8 @@ void tst_QGuiApplication::focusObject()
int argc = 0;
QGuiApplication app(argc, 0);
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
QObject obj1, obj2, obj3;
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
@@ -374,8 +377,8 @@ void tst_QGuiApplication::changeFocusWindow()
int argc = 0;
QGuiApplication app(argc, 0);
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
@@ -1096,6 +1099,8 @@ void tst_QGuiApplication::staticFunctions()
QGuiApplication::setQuitOnLastWindowClosed(true);
QGuiApplication::quitOnLastWindowClosed();
QGuiApplication::applicationState();
+
+ QPixmap::defaultDepth();
}
void tst_QGuiApplication::settableStyleHints_data()
diff --git a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp
index 509f8bd45f..15c905f943 100644
--- a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp
+++ b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp
@@ -186,8 +186,8 @@ void tst_qinputmethod::cursorRectangle()
{
QCOMPARE(qApp->inputMethod()->cursorRectangle(), QRectF());
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
DummyWindow window;
window.show();
@@ -284,8 +284,8 @@ void tst_qinputmethod::inputDirection()
void tst_qinputmethod::inputMethodAccepted()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
if (!QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive)
|| !QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) {
diff --git a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp
index 8ffd1bb9b4..9c36b6898a 100644
--- a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp
+++ b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp
@@ -42,6 +42,7 @@ private slots:
void initTestCase();
void create();
void basic();
+ void resize();
void painter();
void partial_data();
void partial();
@@ -115,8 +116,7 @@ void tst_QOpenGLWindow::basic()
// Check that the virtuals are invoked.
QCOMPARE(w.initCount, 1);
- int resCount = w.resizeCount;
- QVERIFY(resCount >= 1);
+ QVERIFY(w.resizeCount >= 1);
QVERIFY(w.paintCount >= 1);
// Check that something has been drawn;
@@ -132,13 +132,31 @@ void tst_QOpenGLWindow::basic()
QCOMPARE(v[2], GLint(w.width() * w.devicePixelRatio()));
QCOMPARE(v[3], GLint(w.height() * w.devicePixelRatio()));
w.doneCurrent();
+}
+
+static bool isPlatformWayland()
+{
+ return QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive);
+}
+
+void tst_QOpenGLWindow::resize()
+{
+ if (isPlatformWayland())
+ QSKIP("Wayland: Crashes on Intel Mesa due to a driver bug (QTBUG-66848).");
+
+ Window w;
+ w.reset();
+ w.resize(640, 480);
+ w.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
+
+ // Check that the virtuals are invoked.
+ int resCount = w.resizeCount;
+ QVERIFY(resCount >= 1);
// Check that a future resize triggers resizeGL.
w.resize(800, 600);
- int maxWait = 1000;
- while (w.resizeCount == resCount && maxWait-- >= 0)
- QTest::qWait(10);
- QVERIFY(w.resizeCount > resCount);
+ QTRY_VERIFY(w.resizeCount > resCount);
}
class PainterWindow : public QOpenGLWindow
@@ -218,9 +236,7 @@ void tst_QOpenGLWindow::partial()
for (int i = 0; i < 10; ++i) {
w.paintCount = 0;
w.update();
- int maxWait = 1000;
- while (w.paintCount == 0 && maxWait-- >= 0)
- QTest::qWait(10);
+ QTRY_VERIFY(w.paintCount > 0);
}
// Now since the painting went to an extra framebuffer, all the rects should
diff --git a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp
index ffc440ac2d..deb4837956 100644
--- a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp
+++ b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp
@@ -76,11 +76,7 @@ void tst_QRasterWindow::basic()
w.reset();
w.update();
- int maxWait = 1000;
- while (w.paintCount == 0 && --maxWait > 0)
- QTest::qWait(10);
-
- QVERIFY(w.paintCount >= 1);
+ QTRY_VERIFY(w.paintCount >= 1);
}
#include <tst_qrasterwindow.moc>
diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
index 706c66ef14..db5e83e2c7 100644
--- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
@@ -317,9 +317,6 @@ void tst_QTouchEvent::touchDisabledByDefault()
void tst_QTouchEvent::touchEventAcceptedByDefault()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
// QWidget
{
// enabling touch events should automatically accept touch events
@@ -606,15 +603,12 @@ QPointF normalized(const QPointF &pos, const QRectF &rect)
void tst_QTouchEvent::basicRawEventTranslation()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
tst_QTouchEventWidget touchWidget;
touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 400, 300);
touchWidget.show();
- QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
+ QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
QPointF pos = touchWidget.rect().center();
QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
@@ -733,9 +727,6 @@ void tst_QTouchEvent::basicRawEventTranslation()
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
tst_QTouchEventWidget touchWidget;
touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
@@ -750,7 +741,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
rightWidget.setGeometry(300, 100, 100, 100);
touchWidget.show();
- QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
+ QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
QPointF leftPos = leftWidget.rect().center();
QPointF rightPos = rightWidget.rect().center();
@@ -962,9 +953,6 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
tst_QTouchEventWidget touchWidget;
touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
@@ -980,7 +968,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
rightWidget.setGeometry(300, 100, 100, 100);
touchWidget.show();
- QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
+ QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
QPointF leftPos = leftWidget.rect().center();
QPointF rightPos = rightWidget.rect().center();
@@ -1191,15 +1179,12 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
void tst_QTouchEvent::basicRawEventTranslationOfIds()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
tst_QTouchEventWidget touchWidget;
touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 400, 300);
touchWidget.show();
- QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
+ QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
QVarLengthArray<QPointF, 2> pos;
QVarLengthArray<QPointF, 2> screenPos;
@@ -1311,9 +1296,6 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds()
void tst_QTouchEvent::deleteInEventHandler()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
// QWidget
{
QWidget window;
@@ -1463,9 +1445,6 @@ void tst_QTouchEvent::deleteInEventHandler()
void tst_QTouchEvent::deleteInRawEventTranslation()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This fails. Figure out why.");
-
tst_QTouchEventWidget touchWidget;
touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
index 734e928f7d..cd1cb99c3c 100644
--- a/tests/auto/gui/kernel/qwindow/BLACKLIST
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -13,7 +13,6 @@ opensuse
[modalWindowEnterEventOnHide_QTBUG35109]
ubuntu-16.04
osx ci
-windows ci
[modalDialogClosingOneOfTwoModal]
osx
[modalWindowModallity]
@@ -24,5 +23,6 @@ osx-10.12 ci
[testInputEvents]
rhel-7.4
-# QTBUG-66798
-windows
+[isActive]
+# QTBUG-67768
+ubuntu
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 8dfaa6f5cd..ba405e2860 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -153,6 +153,7 @@ private slots:
void setEqualClipRegionAndPath();
void clipRectSaveRestore();
+ void clipStateSaveRestore();
void clippedFillPath_data();
void clippedFillPath();
@@ -3425,6 +3426,35 @@ void tst_QPainter::clipRectSaveRestore()
QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba());
}
+void tst_QPainter::clipStateSaveRestore()
+{
+ QImage img(16, 16, QImage::Format_RGB32);
+ img.fill(Qt::blue);
+ {
+ QPainter p(&img);
+ p.setClipRect(QRect(5, 5, 10, 10));
+ p.save();
+ p.setClipping(false);
+ p.restore();
+ p.fillRect(0, 0, 16, 16, Qt::red);
+ p.end();
+ QCOMPARE(img.pixel(0, 0), QColor(Qt::blue).rgb());
+ }
+
+ img.fill(Qt::blue);
+ {
+ QPainter p(&img);
+ p.setClipRect(QRect(5, 5, 10, 10));
+ p.setClipping(false);
+ p.save();
+ p.setClipping(true);
+ p.restore();
+ p.fillRect(0, 0, 16, 16, Qt::red);
+ p.end();
+ QCOMPARE(img.pixel(0, 0), QColor(Qt::red).rgb());
+ }
+}
+
void tst_QPainter::clippedImage()
{
QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
index d0a0225055..82197f815e 100644
--- a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
+++ b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
@@ -372,6 +372,8 @@ namespace {
return "const";
case QShaderLanguage::Input:
return "varying";
+ case QShaderLanguage::BuiltIn:
+ return "//";
case QShaderLanguage::Output:
return ""; // Although fragment shaders for <=2 only have fixed outputs
case QShaderLanguage::Uniform:
@@ -383,6 +385,8 @@ namespace {
return "const";
case QShaderLanguage::Input:
return "in";
+ case QShaderLanguage::BuiltIn:
+ return "//";
case QShaderLanguage::Output:
return "out";
case QShaderLanguage::Uniform:
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index 69e480b164..b0bae13bad 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -123,6 +123,12 @@ void Http2Server::emulateGOAWAY(int timeout)
goawayTimeout = timeout;
}
+void Http2Server::redirectOpenStream(quint16 port)
+{
+ redirectWhileReading = true;
+ targetPort = port;
+}
+
void Http2Server::startServer()
{
#ifdef QT_NO_SSL
@@ -775,7 +781,19 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
if (emptyBody)
writer.addFlag(FrameFlag::END_STREAM);
- HttpHeader header = {{":status", "200"}};
+ HttpHeader header;
+ if (redirectWhileReading) {
+ qDebug("server received HEADERS frame (followed by DATA frames), redirecting ...");
+ Q_ASSERT(targetPort);
+ header.push_back({":status", "308"});
+ const QString url("%1://localhost:%2/");
+ header.push_back({"location", url.arg(clearTextHTTP2 ? QStringLiteral("http") : QStringLiteral("https"),
+ QString::number(targetPort)).toLatin1()});
+
+ } else {
+ header.push_back({":status", "200"});
+ }
+
if (!emptyBody) {
header.push_back(HPack::HeaderField("content-length",
QString("%1").arg(responseBody.size()).toLatin1()));
@@ -871,7 +889,13 @@ void Http2Server::processRequest()
activeRequests[streamID] = decoder.decodedHeader();
if (headersFrame.flags().testFlag(FrameFlag::END_STREAM))
emit receivedRequest(streamID);
- // else - we're waiting for incoming DATA frames ...
+
+ if (redirectWhileReading) {
+ sendResponse(streamID, true);
+ // Don't try to read any DATA frames ...
+ socket->disconnect();
+ } // else - we're waiting for incoming DATA frames ...
+
continuedRequest.clear();
}
diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h
index 76c5a0ee36..14b41cc67d 100644
--- a/tests/auto/network/access/http2/http2srv.h
+++ b/tests/auto/network/access/http2/http2srv.h
@@ -74,6 +74,7 @@ public:
void enablePushPromise(bool enabled, const QByteArray &path = QByteArray());
void setResponseBody(const QByteArray &body);
void emulateGOAWAY(int timeout);
+ void redirectOpenStream(quint16 targetPort);
// Invokables, since we can call them from the main thread,
// but server (can) work on its own thread.
@@ -186,6 +187,10 @@ private:
// We need it for PUSH_PROMISE, with the correct port number appended,
// when replying to essentially 1.1 request.
QByteArray authority;
+ // Redirect, with status code 308, as soon as we've seen headers, while client
+ // may still be sending DATA frames. See tst_Http2::earlyResponse().
+ bool redirectWhileReading = false;
+ quint16 targetPort = 0;
protected slots:
void ignoreErrorSlot();
};
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 51e1849512..ecf4c5814a 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -74,6 +74,7 @@ private slots:
void pushPromise();
void goaway_data();
void goaway();
+ void earlyResponse();
protected slots:
// Slots to listen to our in-process server:
@@ -439,6 +440,47 @@ void tst_Http2::goaway()
QVERIFY(!serverGotSettingsACK);
}
+void tst_Http2::earlyResponse()
+{
+ // In this test we'd like to verify client side can handle HEADERS frame while
+ // its stream is in 'open' state. To achieve this, we send a POST request
+ // with some payload, so that the client is first sending HEADERS and then
+ // DATA frames without END_STREAM flag set yet (thus the stream is in Stream::open
+ // state). Upon receiving the client's HEADERS frame our server ('redirector')
+ // immediately (without trying to read any DATA frames) responds with status
+ // code 308. The client should properly handle this.
+
+ clearHTTP2State();
+
+ serverPort = 0;
+ nRequests = 1;
+
+ ServerPtr targetServer(newServer(defaultServerSettings));
+
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ const quint16 targetPort = serverPort;
+ serverPort = 0;
+
+ ServerPtr redirector(newServer(defaultServerSettings));
+ redirector->redirectOpenStream(targetPort);
+
+ QMetaObject::invokeMethod(redirector.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort);
+ sendRequest(1, QNetworkRequest::NormalPriority, {10000000, Qt::Uninitialized});
+
+ runEventLoop();
+
+ QVERIFY(nRequests == 0);
+ QVERIFY(prefaceOK);
+ QVERIFY(serverGotSettingsACK);
+}
+
void tst_Http2::serverStarted(quint16 port)
{
serverPort = port;
@@ -500,6 +542,7 @@ void tst_Http2::sendRequest(int streamNumber,
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
+ request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true));
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
request.setPriority(priority);
@@ -592,6 +635,10 @@ void tst_Http2::replyFinished()
const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute));
QVERIFY(spdyUsed.isValid());
QVERIFY(!spdyUsed.toBool());
+ const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute));
+ QVERIFY(code.isValid());
+ QVERIFY(code.canConvert<int>());
+ QCOMPARE(code.value<int>(), 200);
}
--nRequests;
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
index bc2e2822cb..120b1c4b66 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -84,6 +84,15 @@ void tst_QNetworkAccessManager::networkAccessible()
QNetworkAccessManager::NotAccessible);
QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible);
+ // When network is not accessible, all requests fail
+ QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("http://www.example.org")));
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy errorSpy(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error));
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(reply->isFinished(), true);
+ QCOMPARE(reply->errorString(), QStringLiteral("Network access is disabled."));
+ QCOMPARE(errorSpy.count(), 1);
+
manager.setNetworkAccessible(QNetworkAccessManager::Accessible);
QCOMPARE(spy.count(), expectedCount);
diff --git a/tests/auto/network/kernel/qdnslookup/BLACKLIST b/tests/auto/network/kernel/qdnslookup/BLACKLIST
new file mode 100644
index 0000000000..edf6436384
--- /dev/null
+++ b/tests/auto/network/kernel/qdnslookup/BLACKLIST
@@ -0,0 +1,2 @@
+[lookup]
+ci
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 0b4ed4870d..b73ed8eaec 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -143,7 +143,7 @@ void tst_QNetworkInterface::dump()
qDebug() << " flags: " << qPrintable(flags);
qDebug() << " type: " << i.type();
qDebug() << " hw address:" << qPrintable(i.hardwareAddress());
- qDebug() << " MTU: " << i.maxTransmissionUnit();
+ qDebug() << " MTU: " << i.maximumTransmissionUnit();
int count = 0;
foreach (const QNetworkAddressEntry &e, i.addressEntries()) {
@@ -187,7 +187,7 @@ void tst_QNetworkInterface::consistencyCheck()
if (iface.index())
interfaceIndexes << iface.index();
- QVERIFY(iface.maxTransmissionUnit() >= 0);
+ QVERIFY(iface.maximumTransmissionUnit() >= 0);
const QList<QNetworkAddressEntry> addresses = iface.addressEntries();
for (auto entry : addresses) {
@@ -275,7 +275,7 @@ void tst_QNetworkInterface::localAddress()
<< "pmtu" << pmtu;
// check that the Path MTU is less than or equal the interface's MTU
- QVERIFY(pmtu <= outgoingIface->maxTransmissionUnit());
+ QVERIFY(pmtu <= outgoingIface->maximumTransmissionUnit());
}
void tst_QNetworkInterface::interfaceFromXXX_data()
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 9a821deefe..53d260f19e 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -42,6 +42,10 @@
#include <unistd.h> // for unlink()
#endif
+#ifdef Q_OS_WIN
+#include <QtCore/qt_windows.h>
+#endif
+
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketError)
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketState)
Q_DECLARE_METATYPE(QLocalServer::SocketOption)
@@ -629,6 +633,14 @@ void tst_QLocalSocket::readBufferOverflow()
QCOMPARE(client.bytesAvailable(), 0);
#ifdef Q_OS_WIN
+ serverSocket->write(buffer, readBufferSize);
+ QVERIFY(serverSocket->waitForBytesWritten());
+
+ // ensure the read completion routine is called
+ SleepEx(100, true);
+ QVERIFY(client.waitForReadyRead());
+ QCOMPARE(client.read(buffer, readBufferSize), qint64(readBufferSize));
+
// Test overflow caused by an asynchronous pipe operation.
client.setReadBufferSize(1);
serverSocket->write(buffer, 2);
@@ -1193,7 +1205,8 @@ void tst_QLocalSocket::writeToClientAndDisconnect()
void tst_QLocalSocket::debug()
{
// Make sure this compiles
- QTest::ignoreMessage(QtDebugMsg, "QLocalSocket::ConnectionRefusedError QLocalSocket::UnconnectedState");
+ if (QLoggingCategory::defaultCategory()->isDebugEnabled())
+ QTest::ignoreMessage(QtDebugMsg, "QLocalSocket::ConnectionRefusedError QLocalSocket::UnconnectedState");
qDebug() << QLocalSocket::ConnectionRefusedError << QLocalSocket::UnconnectedState;
}
diff --git a/tests/auto/network/ssl/qsslkey/BLACKLIST b/tests/auto/network/ssl/qsslkey/BLACKLIST
index a08e1f35eb..c0dfe5eb86 100644
--- a/tests/auto/network/ssl/qsslkey/BLACKLIST
+++ b/tests/auto/network/ssl/qsslkey/BLACKLIST
@@ -1 +1,2 @@
-linux
+redhatenterpriselinuxworkstation-6.6
+rhel-7.4
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index f77afd2364..bb01116240 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -1188,13 +1188,7 @@ void tst_QSslSocket::protocolServerSide_data()
#if !defined(OPENSSL_NO_SSL2)
// OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ...
#define OPENSSL_NO_SSL2
-#endif
- // A client using our OpenSSL1.1 backend will negotiate up from TLS 1.0 or 1.1
- // to TLS 1.2 if the server asks for it, where our older backend fails to compromise.
- // So some tests that fail for the old pass with the new.
- const bool willUseTLS12 = true;
-#else
- const bool willUseTLS12 = false;
+#endif // OPENSSL_NO_SSL2
#endif // opensslv11
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
@@ -1290,7 +1284,7 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false;
#endif
- QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << willUseTLS12;
+ QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true;
QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true;
@@ -1300,8 +1294,8 @@ void tst_QSslSocket::protocolServerSide_data()
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false;
#endif
- QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << willUseTLS12;
- QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << willUseTLS12;
+ QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << false;
+ QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << false;
QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true;
QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true;
@@ -4016,12 +4010,12 @@ void tst_QSslSocket::signatureAlgorithm()
SslServer server;
server.protocol = serverProtocol;
server.config.setCiphers({QSslCipher("ECDHE-RSA-AES256-SHA")});
- server.config.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), serverSigAlgPairs.join(':'));
+ server.config.setBackendConfigurationOption(QByteArrayLiteral("SignatureAlgorithms"), serverSigAlgPairs.join(':'));
QVERIFY(server.listen());
QSslConfiguration clientConfig = QSslConfiguration::defaultConfiguration();
clientConfig.setProtocol(clientProtocol);
- clientConfig.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), clientSigAlgPairs.join(':'));
+ clientConfig.setBackendConfigurationOption(QByteArrayLiteral("SignatureAlgorithms"), clientSigAlgPairs.join(':'));
QSslSocket client;
client.setSslConfiguration(clientConfig);
socket = &client;
diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp
index 46e2345c6a..7666bf81e4 100644
--- a/tests/auto/opengl/qgl/tst_qgl.cpp
+++ b/tests/auto/opengl/qgl/tst_qgl.cpp
@@ -923,8 +923,7 @@ void tst_QGL::partialGLWidgetUpdates()
widget.setFixedSize(150, 150);
widget.setAutoFillBackground(autoFillBackground);
widget.show();
-
- QTest::qWait(200);
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
if (widget.format().doubleBuffer() != doubleBufferedContext)
QSKIP("Platform does not support requested format");
diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp
index 0410856790..b2b45bb237 100644
--- a/tests/auto/other/compiler/tst_compiler.cpp
+++ b/tests/auto/other/compiler/tst_compiler.cpp
@@ -693,7 +693,7 @@ QT_WARNING_DISABLE_GCC("-Wunused-local-typedefs")
[[noreturn]] void attribute_f1();
void attribute_f2 [[noreturn]] ();
# if (defined(__cpp_namespace_attributes) && __cpp_namespace_attributes >= 201411) && __has_cpp_attribute(deprecated)
-namespace NS [[deprecated]] { }
+namespace [[deprecated]] NS { }
# endif
#endif
diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST
index 1d89178fe5..169117b36a 100644
--- a/tests/auto/other/gestures/BLACKLIST
+++ b/tests/auto/other/gestures/BLACKLIST
@@ -1,2 +1,6 @@
[]
rhel-7.4
+[customGesture]
+# QTBUG-67254
+ubuntu
+opensuse
diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp
index 8419f93e3b..074644393d 100644
--- a/tests/auto/other/lancelot/paintcommands.cpp
+++ b/tests/auto/other/lancelot/paintcommands.cpp
@@ -192,7 +192,7 @@ QList<QPair<QString,QStringList> > PaintCommands::s_enumsTable = QList<QPair<QSt
QMultiHash<QString, int> PaintCommands::s_commandHash;
#define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \
- s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegExp(regexp), \
+ s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegularExpression(regexp), \
QLatin1String(syntax), QLatin1String(sample) );
#define DECL_PAINTCOMMANDSECTION(title) \
@@ -418,7 +418,7 @@ void PaintCommands::staticInit()
"\n- a width or height of -1 means maximum space",
"drawImage :/images/face.png 0 0 -1 -1 0 0 -1 -1");
DECL_PAINTCOMMAND("drawPolygon", command_drawPolygon,
- "^drawPolygon\\s+\\[([\\w\\s-.]*)\\]\\s*(\\w*)$",
+ "^drawPolygon\\s+\\[([\\w\\s\\-.]*)\\]\\s*(\\w*)$",
"drawPolygon <[ <x1> <y1> ... <xn> <yn> ]> <Winding|OddEven>",
"drawPolygon [ 1 4 6 8 5 3 ] Winding");
DECL_PAINTCOMMAND("drawConvexPolygon", command_drawConvexPolygon,
@@ -615,6 +615,8 @@ void PaintCommands::staticInit()
// populate the command lookup hash
for (int i=0; i<s_commandInfoTable.size(); i++) {
+ // and pre-optimize the regexps.
+ s_commandInfoTable.at(i).regExp.optimize();
if (s_commandInfoTable.at(i).isSectionHeader() ||
s_commandInfoTable.at(i).identifier == QLatin1String("comment") ||
s_commandInfoTable.at(i).identifier == QLatin1String("noop"))
@@ -682,20 +684,23 @@ void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands)
**********************************************************************************/
void PaintCommands::runCommand(const QString &scriptLine)
{
+ static QRegularExpression separators("\\s");
if (scriptLine.isEmpty()) {
- command_noop(QRegExp());
+ command_noop(QRegularExpressionMatch());
return;
}
if (scriptLine.startsWith('#')) {
- command_comment(QRegExp());
+ command_comment(QRegularExpressionMatch());
return;
}
- QString firstWord = scriptLine.section(QRegExp("\\s"), 0, 0);
+ QString firstWord = scriptLine.section(separators, 0, 0);
QList<int> indices = s_commandHash.values(firstWord);
foreach(int idx, indices) {
PaintCommandInfos command = s_commandInfoTable.at(idx);
- if (command.regExp.indexIn(scriptLine) >= 0) {
- (this->*(command.paintMethod))(command.regExp);
+ Q_ASSERT(command.regExp.isValid());
+ QRegularExpressionMatch match = command.regExp.match(scriptLine);
+ if (match.hasMatch()) {
+ (this->*(command.paintMethod))(match);
return;
}
}
@@ -751,7 +756,7 @@ float PaintCommands::convertToFloat(const QString &str)
double PaintCommands::convertToDouble(const QString &str)
{
- static QRegExp re("cp([0-9])([xy])");
+ static QRegularExpression re("cp([0-9])([xy])");
if (str.toLower() == "width") {
if (m_painter->device()->devType() == Qt::Widget)
return m_painter->window().width();
@@ -764,9 +769,10 @@ double PaintCommands::convertToDouble(const QString &str)
else
return 800;
}
- if (re.indexIn(str) >= 0) {
- int index = re.cap(1).toInt();
- bool is_it_x = re.cap(2) == "x";
+ QRegularExpressionMatch match = re.match(str);
+ if (match.hasMatch()) {
+ int index = match.captured(1).toInt();
+ bool is_it_x = match.captured(2) == "x";
if (index < 0 || index >= m_controlPoints.size()) {
qWarning("ERROR: control point index=%d is out of bounds", index);
return 0;
@@ -778,21 +784,23 @@ double PaintCommands::convertToDouble(const QString &str)
QColor PaintCommands::convertToColor(const QString &str)
{
- static QRegExp alphaColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
- static QRegExp opaqueColor("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
-
- Q_ASSERT(alphaColor.isValid());
- Q_ASSERT(opaqueColor.isValid());
-
- if (alphaColor.indexIn(str) >= 0) {
- return QColor(alphaColor.cap(2).toInt(0, 16),
- alphaColor.cap(3).toInt(0, 16),
- alphaColor.cap(4).toInt(0, 16),
- alphaColor.cap(1).toInt(0, 16));
- } else if (opaqueColor.indexIn(str) >= 0) {
- return QColor(opaqueColor.cap(1).toInt(0, 16),
- opaqueColor.cap(2).toInt(0, 16),
- opaqueColor.cap(3).toInt(0, 16));
+ static QRegularExpression alphaColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
+ static QRegularExpression opaqueColorRe("#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})");
+
+ Q_ASSERT(alphaColorRe.isValid());
+ Q_ASSERT(opaqueColorRe.isValid());
+
+ QRegularExpressionMatch alphaColor = alphaColorRe.match(str);
+ QRegularExpressionMatch opaqueColor = opaqueColorRe.match(str);
+ if (alphaColor.hasMatch()) {
+ return QColor(alphaColor.captured(2).toInt(0, 16),
+ alphaColor.captured(3).toInt(0, 16),
+ alphaColor.captured(4).toInt(0, 16),
+ alphaColor.captured(1).toInt(0, 16));
+ } else if (opaqueColor.hasMatch()) {
+ return QColor(opaqueColor.captured(1).toInt(0, 16),
+ opaqueColor.captured(2).toInt(0, 16),
+ opaqueColor.captured(3).toInt(0, 16));
}
return QColor(str);
}
@@ -800,16 +808,16 @@ QColor PaintCommands::convertToColor(const QString &str)
/*********************************************************************************
** command implementations
**********************************************************************************/
-void PaintCommands::command_comment(QRegExp)
+void PaintCommands::command_comment(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) comment: %s\n", qPrintable(m_currentCommand));
}
/***************************************************************************************************/
-void PaintCommands::command_import(QRegExp re)
+void PaintCommands::command_import(QRegularExpressionMatch re)
{
- QString importFile(re.cap(1));
+ QString importFile(re.captured(1));
QFileInfo fi(m_filepath);
QDir dir = fi.absoluteDir();
QFile *file = new QFile(dir.absolutePath() + QDir::separator() + importFile);
@@ -862,9 +870,9 @@ void PaintCommands::command_import(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_begin_block(QRegExp re)
+void PaintCommands::command_begin_block(QRegularExpressionMatch re)
{
- const QString &blockName = re.cap(1);
+ const QString &blockName = re.captured(1);
if (m_verboseMode)
printf(" -(lance) begin_block (%s)\n", qPrintable(blockName));
@@ -891,7 +899,7 @@ void PaintCommands::command_begin_block(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_end_block(QRegExp)
+void PaintCommands::command_end_block(QRegularExpressionMatch)
{
printf(" - end_block should be consumed by begin_block command.\n");
printf(" You will never see this if your block markers are in sync\n");
@@ -899,9 +907,9 @@ void PaintCommands::command_end_block(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_repeat_block(QRegExp re)
+void PaintCommands::command_repeat_block(QRegularExpressionMatch re)
{
- QString blockName = re.cap(1);
+ QString blockName = re.captured(1);
if (m_verboseMode)
printf(" -(lance) repeating block (%s)\n", qPrintable(blockName));
@@ -916,7 +924,7 @@ void PaintCommands::command_repeat_block(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawLine(QRegExp re)
+void PaintCommands::command_drawLine(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x1 = convertToDouble(caps.at(1));
@@ -931,28 +939,28 @@ void PaintCommands::command_drawLine(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawPath(QRegExp re)
+void PaintCommands::command_drawPath(QRegularExpressionMatch re)
{
if (m_verboseMode)
- printf(" -(lance) drawPath(name=%s)\n", qPrintable(re.cap(1)));
+ printf(" -(lance) drawPath(name=%s)\n", qPrintable(re.captured(1)));
- QPainterPath &path = m_pathMap[re.cap(1)];
+ QPainterPath &path = m_pathMap[re.captured(1)];
m_painter->drawPath(path);
}
/***************************************************************************************************/
-void PaintCommands::command_drawPixmap(QRegExp re)
+void PaintCommands::command_drawPixmap(QRegularExpressionMatch re)
{
QPixmap pm;
- pm = m_pixmapMap[re.cap(1)]; // try cache first
+ pm = m_pixmapMap[re.captured(1)]; // try cache first
if (pm.isNull())
- pm = image_load<QPixmap>(re.cap(1));
+ pm = image_load<QPixmap>(re.captured(1));
if (pm.isNull()) {
QFileInfo fi(m_filepath);
QDir dir = fi.absoluteDir();
dir.cdUp();
dir.cd("images");
- QString fileName = dir.absolutePath() + QLatin1Char('/') + re.cap(1);
+ QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1);
pm = QPixmap(fileName);
if (pm.isNull() && !fileName.endsWith(".png")) {
fileName.append(".png");
@@ -961,19 +969,19 @@ void PaintCommands::command_drawPixmap(QRegExp re)
}
if (pm.isNull()) {
fprintf(stderr, "ERROR(drawPixmap): failed to load pixmap: '%s'\n",
- qPrintable(re.cap(1)));
+ qPrintable(re.captured(1)));
return;
}
- qreal tx = convertToFloat(re.cap(2));
- qreal ty = convertToFloat(re.cap(3));
- qreal tw = convertToFloat(re.cap(4));
- qreal th = convertToFloat(re.cap(5));
+ qreal tx = convertToFloat(re.captured(2));
+ qreal ty = convertToFloat(re.captured(3));
+ qreal tw = convertToFloat(re.captured(4));
+ qreal th = convertToFloat(re.captured(5));
- qreal sx = convertToFloat(re.cap(6));
- qreal sy = convertToFloat(re.cap(7));
- qreal sw = convertToFloat(re.cap(8));
- qreal sh = convertToFloat(re.cap(9));
+ qreal sx = convertToFloat(re.captured(6));
+ qreal sy = convertToFloat(re.captured(7));
+ qreal sw = convertToFloat(re.captured(8));
+ qreal sh = convertToFloat(re.captured(9));
if (tw == 0) tw = -1;
if (th == 0) th = -1;
@@ -982,26 +990,26 @@ void PaintCommands::command_drawPixmap(QRegExp re)
if (m_verboseMode)
printf(" -(lance) drawPixmap('%s' dim=(%d, %d), depth=%d, (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
- qPrintable(re.cap(1)), pm.width(), pm.height(), pm.depth(),
+ qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(),
tx, ty, tw, th, sx, sy, sw, sh);
m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh));
}
/***************************************************************************************************/
-void PaintCommands::command_drawImage(QRegExp re)
+void PaintCommands::command_drawImage(QRegularExpressionMatch re)
{
QImage im;
- im = m_imageMap[re.cap(1)]; // try cache first
+ im = m_imageMap[re.captured(1)]; // try cache first
if (im.isNull())
- im = image_load<QImage>(re.cap(1));
+ im = image_load<QImage>(re.captured(1));
if (im.isNull()) {
QFileInfo fi(m_filepath);
QDir dir = fi.absoluteDir();
dir.cdUp();
dir.cd("images");
- QString fileName = dir.absolutePath() + QLatin1Char('/') + re.cap(1);
+ QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1);
im = QImage(fileName);
if (im.isNull() && !fileName.endsWith(".png")) {
fileName.append(".png");
@@ -1009,19 +1017,19 @@ void PaintCommands::command_drawImage(QRegExp re)
}
}
if (im.isNull()) {
- fprintf(stderr, "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.cap(1)));
+ fprintf(stderr, "ERROR(drawImage): failed to load image: '%s'\n", qPrintable(re.captured(1)));
return;
}
- qreal tx = convertToFloat(re.cap(2));
- qreal ty = convertToFloat(re.cap(3));
- qreal tw = convertToFloat(re.cap(4));
- qreal th = convertToFloat(re.cap(5));
+ qreal tx = convertToFloat(re.captured(2));
+ qreal ty = convertToFloat(re.captured(3));
+ qreal tw = convertToFloat(re.captured(4));
+ qreal th = convertToFloat(re.captured(5));
- qreal sx = convertToFloat(re.cap(6));
- qreal sy = convertToFloat(re.cap(7));
- qreal sw = convertToFloat(re.cap(8));
- qreal sh = convertToFloat(re.cap(9));
+ qreal sx = convertToFloat(re.captured(6));
+ qreal sy = convertToFloat(re.captured(7));
+ qreal sw = convertToFloat(re.captured(8));
+ qreal sh = convertToFloat(re.captured(9));
if (tw == 0) tw = -1;
if (th == 0) th = -1;
@@ -1030,24 +1038,24 @@ void PaintCommands::command_drawImage(QRegExp re)
if (m_verboseMode)
printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
- qPrintable(re.cap(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh);
+ qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh);
m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh), Qt::OrderedDither | Qt::OrderedAlphaDither);
}
/***************************************************************************************************/
-void PaintCommands::command_drawTiledPixmap(QRegExp re)
+void PaintCommands::command_drawTiledPixmap(QRegularExpressionMatch re)
{
QPixmap pm;
- pm = m_pixmapMap[re.cap(1)]; // try cache first
+ pm = m_pixmapMap[re.captured(1)]; // try cache first
if (pm.isNull())
- pm = image_load<QPixmap>(re.cap(1));
+ pm = image_load<QPixmap>(re.captured(1));
if (pm.isNull()) {
QFileInfo fi(m_filepath);
QDir dir = fi.absoluteDir();
dir.cdUp();
dir.cd("images");
- QString fileName = dir.absolutePath() + QLatin1Char('/') + re.cap(1);
+ QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1);
pm = QPixmap(fileName);
if (pm.isNull() && !fileName.endsWith(".png")) {
fileName.append(".png");
@@ -1056,30 +1064,30 @@ void PaintCommands::command_drawTiledPixmap(QRegExp re)
}
if (pm.isNull()) {
fprintf(stderr, "ERROR(drawTiledPixmap): failed to load pixmap: '%s'\n",
- qPrintable(re.cap(1)));
+ qPrintable(re.captured(1)));
return;
}
- int tx = convertToInt(re.cap(2));
- int ty = convertToInt(re.cap(3));
- int tw = convertToInt(re.cap(4));
- int th = convertToInt(re.cap(5));
+ int tx = convertToInt(re.captured(2));
+ int ty = convertToInt(re.captured(3));
+ int tw = convertToInt(re.captured(4));
+ int th = convertToInt(re.captured(5));
- int sx = convertToInt(re.cap(6));
- int sy = convertToInt(re.cap(7));
+ int sx = convertToInt(re.captured(6));
+ int sy = convertToInt(re.captured(7));
if (tw == 0) tw = -1;
if (th == 0) th = -1;
if (m_verboseMode)
printf(" -(lance) drawTiledPixmap('%s' dim=(%d, %d), (%d, %d, %d, %d), (%d, %d)\n",
- qPrintable(re.cap(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy);
+ qPrintable(re.captured(1)), pm.width(), pm.height(), tx, ty, tw, th, sx, sy);
m_painter->drawTiledPixmap(tx, ty, tw, th, pm, sx, sy);
}
/***************************************************************************************************/
-void PaintCommands::command_drawPoint(QRegExp re)
+void PaintCommands::command_drawPoint(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
float x = convertToFloat(caps.at(1));
@@ -1092,9 +1100,9 @@ void PaintCommands::command_drawPoint(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawPolygon(QRegExp re)
+void PaintCommands::command_drawPolygon(QRegularExpressionMatch re)
{
- static QRegExp separators("\\s");
+ static QRegularExpression separators("\\s");
QStringList caps = re.capturedTexts();
QString cap = caps.at(1);
QStringList numbers = cap.split(separators, QString::SkipEmptyParts);
@@ -1110,10 +1118,10 @@ void PaintCommands::command_drawPolygon(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawPolyline(QRegExp re)
+void PaintCommands::command_drawPolyline(QRegularExpressionMatch re)
{
- static QRegExp separators("\\s");
- QStringList numbers = re.cap(1).split(separators, QString::SkipEmptyParts);
+ static QRegularExpression separators("\\s");
+ QStringList numbers = re.captured(1).split(separators, QString::SkipEmptyParts);
QPolygonF array;
for (int i=0; i + 1<numbers.size(); i+=2)
@@ -1126,7 +1134,7 @@ void PaintCommands::command_drawPolyline(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawRect(QRegExp re)
+void PaintCommands::command_drawRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
float x = convertToFloat(caps.at(1));
@@ -1141,7 +1149,7 @@ void PaintCommands::command_drawRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawRoundedRect(QRegExp re)
+void PaintCommands::command_drawRoundedRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
float x = convertToFloat(caps.at(1));
@@ -1162,7 +1170,7 @@ void PaintCommands::command_drawRoundedRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawRoundRect(QRegExp re)
+void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
int x = convertToInt(caps.at(1));
@@ -1179,7 +1187,7 @@ void PaintCommands::command_drawRoundRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawEllipse(QRegExp re)
+void PaintCommands::command_drawEllipse(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
float x = convertToFloat(caps.at(1));
@@ -1194,7 +1202,7 @@ void PaintCommands::command_drawEllipse(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawPie(QRegExp re)
+void PaintCommands::command_drawPie(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
int x = convertToInt(caps.at(1));
@@ -1211,7 +1219,7 @@ void PaintCommands::command_drawPie(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawChord(QRegExp re)
+void PaintCommands::command_drawChord(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
int x = convertToInt(caps.at(1));
@@ -1228,7 +1236,7 @@ void PaintCommands::command_drawChord(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawArc(QRegExp re)
+void PaintCommands::command_drawArc(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
int x = convertToInt(caps.at(1));
@@ -1245,7 +1253,7 @@ void PaintCommands::command_drawArc(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawText(QRegExp re)
+void PaintCommands::command_drawText(QRegularExpressionMatch re)
{
if (!m_shouldDrawText)
return;
@@ -1260,7 +1268,7 @@ void PaintCommands::command_drawText(QRegExp re)
m_painter->drawText(x, y, txt);
}
-void PaintCommands::command_drawStaticText(QRegExp re)
+void PaintCommands::command_drawStaticText(QRegularExpressionMatch re)
{
if (!m_shouldDrawText)
return;
@@ -1276,7 +1284,7 @@ void PaintCommands::command_drawStaticText(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_noop(QRegExp)
+void PaintCommands::command_noop(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) noop: %s\n", qPrintable(m_currentCommand));
@@ -1287,7 +1295,7 @@ void PaintCommands::command_noop(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_path_addText(QRegExp re)
+void PaintCommands::command_path_addText(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1302,7 +1310,7 @@ void PaintCommands::command_path_addText(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_addEllipse(QRegExp re)
+void PaintCommands::command_path_addEllipse(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1318,7 +1326,7 @@ void PaintCommands::command_path_addEllipse(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_addRect(QRegExp re)
+void PaintCommands::command_path_addRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1334,9 +1342,9 @@ void PaintCommands::command_path_addRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_addPolygon(QRegExp re)
+void PaintCommands::command_path_addPolygon(QRegularExpressionMatch re)
{
- static QRegExp separators("\\s");
+ static QRegularExpression separators("\\s");
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
QString cap = caps.at(2);
@@ -1353,7 +1361,7 @@ void PaintCommands::command_path_addPolygon(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_arcTo(QRegExp re)
+void PaintCommands::command_path_arcTo(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1371,7 +1379,7 @@ void PaintCommands::command_path_arcTo(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_createOutline(QRegExp re)
+void PaintCommands::command_path_createOutline(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1395,7 +1403,7 @@ void PaintCommands::command_path_createOutline(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_cubicTo(QRegExp re)
+void PaintCommands::command_path_cubicTo(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1413,7 +1421,7 @@ void PaintCommands::command_path_cubicTo(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_moveTo(QRegExp re)
+void PaintCommands::command_path_moveTo(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1427,7 +1435,7 @@ void PaintCommands::command_path_moveTo(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_lineTo(QRegExp re)
+void PaintCommands::command_path_lineTo(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1441,7 +1449,7 @@ void PaintCommands::command_path_lineTo(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_setFillRule(QRegExp re)
+void PaintCommands::command_path_setFillRule(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1454,7 +1462,7 @@ void PaintCommands::command_path_setFillRule(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_closeSubpath(QRegExp re)
+void PaintCommands::command_path_closeSubpath(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1466,7 +1474,7 @@ void PaintCommands::command_path_closeSubpath(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_path_getClipPath(QRegExp re)
+void PaintCommands::command_path_getClipPath(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1496,7 +1504,7 @@ static void qt_debug_path(const QPainterPath &path, const QString &name)
}
/***************************************************************************************************/
-void PaintCommands::command_path_debugPrint(QRegExp re)
+void PaintCommands::command_path_debugPrint(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1504,7 +1512,7 @@ void PaintCommands::command_path_debugPrint(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_region_addRect(QRegExp re)
+void PaintCommands::command_region_addRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1520,7 +1528,7 @@ void PaintCommands::command_region_addRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_region_addEllipse(QRegExp re)
+void PaintCommands::command_region_addEllipse(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1536,7 +1544,7 @@ void PaintCommands::command_region_addEllipse(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_region_getClipRegion(QRegExp re)
+void PaintCommands::command_region_getClipRegion(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString name = caps.at(1);
@@ -1553,7 +1561,7 @@ void PaintCommands::command_region_getClipRegion(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_resetMatrix(QRegExp)
+void PaintCommands::command_resetMatrix(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) resetMatrix()\n");
@@ -1562,7 +1570,7 @@ void PaintCommands::command_resetMatrix(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_restore(QRegExp)
+void PaintCommands::command_restore(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) restore()\n");
@@ -1571,7 +1579,7 @@ void PaintCommands::command_restore(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_rotate(QRegExp re)
+void PaintCommands::command_rotate(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double angle = convertToDouble(caps.at(1));
@@ -1583,7 +1591,7 @@ void PaintCommands::command_rotate(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_rotate_x(QRegExp re)
+void PaintCommands::command_rotate_x(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double angle = convertToDouble(caps.at(1));
@@ -1597,7 +1605,7 @@ void PaintCommands::command_rotate_x(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_rotate_y(QRegExp re)
+void PaintCommands::command_rotate_y(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double angle = convertToDouble(caps.at(1));
@@ -1611,7 +1619,7 @@ void PaintCommands::command_rotate_y(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_save(QRegExp)
+void PaintCommands::command_save(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) save()\n");
@@ -1620,7 +1628,7 @@ void PaintCommands::command_save(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_mapQuadToQuad(QRegExp re)
+void PaintCommands::command_mapQuadToQuad(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x1 = convertToDouble(caps.at(1));
@@ -1666,7 +1674,7 @@ void PaintCommands::command_mapQuadToQuad(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setMatrix(QRegExp re)
+void PaintCommands::command_setMatrix(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double m11 = convertToDouble(caps.at(1));
@@ -1692,7 +1700,7 @@ void PaintCommands::command_setMatrix(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_scale(QRegExp re)
+void PaintCommands::command_scale(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double sx = convertToDouble(caps.at(1));
@@ -1706,7 +1714,7 @@ void PaintCommands::command_scale(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setBackground(QRegExp re)
+void PaintCommands::command_setBackground(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QColor color = convertToColor(caps.at(1));
@@ -1723,7 +1731,7 @@ void PaintCommands::command_setBackground(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setOpacity(QRegExp re)
+void PaintCommands::command_setOpacity(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double opacity = convertToDouble(caps.at(1));
@@ -1735,9 +1743,9 @@ void PaintCommands::command_setOpacity(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setBgMode(QRegExp re)
+void PaintCommands::command_setBgMode(QRegularExpressionMatch re)
{
- QString cap = re.cap(2);
+ QString cap = re.captured(2);
Qt::BGMode mode = Qt::TransparentMode;
if (cap.toLower() == QLatin1String("opaquemode") || cap.toLower() == QLatin1String("opaque"))
mode = Qt::OpaqueMode;
@@ -1749,7 +1757,7 @@ void PaintCommands::command_setBgMode(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setBrush(QRegExp re)
+void PaintCommands::command_setBrush(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -1780,10 +1788,10 @@ void PaintCommands::command_setBrush(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setBrushOrigin(QRegExp re)
+void PaintCommands::command_setBrushOrigin(QRegularExpressionMatch re)
{
- int x = convertToInt(re.cap(1));
- int y = convertToInt(re.cap(2));
+ int x = convertToInt(re.captured(1));
+ int y = convertToInt(re.captured(2));
if (m_verboseMode)
printf(" -(lance) setBrushOrigin(%d, %d)\n", x, y);
@@ -1792,7 +1800,7 @@ void PaintCommands::command_setBrushOrigin(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_brushTranslate(QRegExp re)
+void PaintCommands::command_brushTranslate(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double dx = convertToDouble(caps.at(1));
@@ -1809,7 +1817,7 @@ void PaintCommands::command_brushTranslate(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_brushScale(QRegExp re)
+void PaintCommands::command_brushScale(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double sx = convertToDouble(caps.at(1));
@@ -1826,7 +1834,7 @@ void PaintCommands::command_brushScale(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_brushRotate(QRegExp re)
+void PaintCommands::command_brushRotate(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double rot = convertToDouble(caps.at(1));
@@ -1842,7 +1850,7 @@ void PaintCommands::command_brushRotate(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_brushShear(QRegExp re)
+void PaintCommands::command_brushShear(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double sx = convertToDouble(caps.at(1));
@@ -1859,9 +1867,9 @@ void PaintCommands::command_brushShear(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setClipping(QRegExp re)
+void PaintCommands::command_setClipping(QRegularExpressionMatch re)
{
- bool clipping = re.cap(1).toLower() == "true";
+ bool clipping = re.captured(1).toLower() == "true";
if (m_verboseMode)
printf(" -(lance) setClipping(%d)\n", clipping);
@@ -1870,7 +1878,7 @@ void PaintCommands::command_setClipping(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setClipRect(QRegExp re)
+void PaintCommands::command_setClipRect(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
int x = convertToInt(caps.at(1));
@@ -1889,48 +1897,48 @@ void PaintCommands::command_setClipRect(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setClipPath(QRegExp re)
+void PaintCommands::command_setClipPath(QRegularExpressionMatch re)
{
- int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1);
+ int combine = translateEnum(clipOperationTable, re.captured(2), Qt::IntersectClip + 1);
if (combine == -1)
combine = Qt::ReplaceClip;
if (m_verboseMode)
- printf(" -(lance) setClipPath(name=%s), %s\n", qPrintable(re.cap(1)), clipOperationTable[combine]);
+ printf(" -(lance) setClipPath(name=%s), %s\n", qPrintable(re.captured(1)), clipOperationTable[combine]);
- if (!m_pathMap.contains(re.cap(1)))
+ if (!m_pathMap.contains(re.captured(1)))
fprintf(stderr, " - setClipPath, no such path");
- m_painter->setClipPath(m_pathMap[re.cap(1)], Qt::ClipOperation(combine));
+ m_painter->setClipPath(m_pathMap[re.captured(1)], Qt::ClipOperation(combine));
}
/***************************************************************************************************/
-void PaintCommands::command_setClipRegion(QRegExp re)
+void PaintCommands::command_setClipRegion(QRegularExpressionMatch re)
{
- int combine = translateEnum(clipOperationTable, re.cap(2), Qt::IntersectClip + 1);
+ int combine = translateEnum(clipOperationTable, re.captured(2), Qt::IntersectClip + 1);
if (combine == -1)
combine = Qt::ReplaceClip;
- QRegion r = m_regionMap[re.cap(1)];
+ QRegion r = m_regionMap[re.captured(1)];
if (m_verboseMode)
printf(" -(lance) setClipRegion(name=%s), bounds=[%d, %d, %d, %d], %s\n",
- qPrintable(re.cap(1)),
+ qPrintable(re.captured(1)),
r.boundingRect().x(),
r.boundingRect().y(),
r.boundingRect().width(),
r.boundingRect().height(),
clipOperationTable[combine]);
- m_painter->setClipRegion(m_regionMap[re.cap(1)], Qt::ClipOperation(combine));
+ m_painter->setClipRegion(m_regionMap[re.captured(1)], Qt::ClipOperation(combine));
}
/***************************************************************************************************/
-void PaintCommands::command_setFont(QRegExp re)
+void PaintCommands::command_setFont(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString family = caps.at(1);
int size = convertToInt(caps.at(2));
- int weight = translateEnum(fontWeightTable, re.cap(3).toLower(), 5);
+ int weight = translateEnum(fontWeightTable, re.captured(3).toLower(), 5);
if (weight != -1) {
switch (weight) {
case 0: weight = QFont::Light; break;
@@ -1940,7 +1948,7 @@ void PaintCommands::command_setFont(QRegExp re)
case 4: weight = QFont::Black; break;
}
} else {
- weight = convertToInt(re.cap(3));
+ weight = convertToInt(re.captured(3));
}
bool italic = caps.at(4).toLower() == "true" || caps.at(4).toLower() == "italic";
@@ -1960,9 +1968,9 @@ void PaintCommands::command_setFont(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setPen(QRegExp re)
+void PaintCommands::command_setPen(QRegularExpressionMatch re)
{
- QString cap = re.cap(1);
+ QString cap = re.captured(1);
int style = translateEnum(penStyleTable, cap, Qt::DashDotDotLine + 1);
if (style >= 0) {
if (m_verboseMode)
@@ -1986,7 +1994,7 @@ void PaintCommands::command_setPen(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setPen2(QRegExp re)
+void PaintCommands::command_setPen2(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2024,10 +2032,10 @@ void PaintCommands::command_setPen2(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_setRenderHint(QRegExp re)
+void PaintCommands::command_setRenderHint(QRegularExpressionMatch re)
{
- QString hintString = re.cap(1).toLower();
- bool on = re.cap(2).isEmpty() || re.cap(2).toLower() == "true";
+ QString hintString = re.captured(1).toLower();
+ bool on = re.captured(2).isEmpty() || re.captured(2).toLower() == "true";
if (hintString.contains("antialiasing")) {
if (m_verboseMode)
printf(" -(lance) setRenderHint Antialiasing\n");
@@ -2043,7 +2051,7 @@ void PaintCommands::command_setRenderHint(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_clearRenderHint(QRegExp /*re*/)
+void PaintCommands::command_clearRenderHint(QRegularExpressionMatch /*re*/)
{
m_painter->setRenderHint(QPainter::Antialiasing, false);
m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false);
@@ -2052,9 +2060,9 @@ void PaintCommands::command_clearRenderHint(QRegExp /*re*/)
}
/***************************************************************************************************/
-void PaintCommands::command_setCompositionMode(QRegExp re)
+void PaintCommands::command_setCompositionMode(QRegularExpressionMatch re)
{
- QString modeString = re.cap(1).toLower();
+ QString modeString = re.captured(1).toLower();
int mode = translateEnum(compositionModeTable, modeString, 33);
if (mode < 0 || mode > QPainter::RasterOp_SourceAndNotDestination) {
@@ -2069,7 +2077,7 @@ void PaintCommands::command_setCompositionMode(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_translate(QRegExp re)
+void PaintCommands::command_translate(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double dx = convertToDouble(caps.at(1));
@@ -2082,7 +2090,7 @@ void PaintCommands::command_translate(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_pixmap_load(QRegExp re)
+void PaintCommands::command_pixmap_load(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2104,7 +2112,7 @@ void PaintCommands::command_pixmap_load(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_bitmap_load(QRegExp re)
+void PaintCommands::command_bitmap_load(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2125,7 +2133,7 @@ void PaintCommands::command_bitmap_load(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_pixmap_setMask(QRegExp re)
+void PaintCommands::command_pixmap_setMask(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QBitmap mask = image_load<QBitmap>(caps.at(2));
@@ -2138,7 +2146,7 @@ void PaintCommands::command_pixmap_setMask(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_image_load(QRegExp re)
+void PaintCommands::command_image_load(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2159,7 +2167,7 @@ void PaintCommands::command_image_load(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_image_setColorCount(QRegExp re)
+void PaintCommands::command_image_setColorCount(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2174,7 +2182,7 @@ void PaintCommands::command_image_setColorCount(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_image_setColor(QRegExp re)
+void PaintCommands::command_image_setColor(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2189,13 +2197,13 @@ void PaintCommands::command_image_setColor(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_abort(QRegExp)
+void PaintCommands::command_abort(QRegularExpressionMatch)
{
m_abort = true;
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_clearStops(QRegExp)
+void PaintCommands::command_gradient_clearStops(QRegularExpressionMatch)
{
if (m_verboseMode)
printf(" -(lance) gradient_clearStops\n");
@@ -2203,7 +2211,7 @@ void PaintCommands::command_gradient_clearStops(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_appendStop(QRegExp re)
+void PaintCommands::command_gradient_appendStop(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double pos = convertToDouble(caps.at(1));
@@ -2216,7 +2224,7 @@ void PaintCommands::command_gradient_appendStop(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setLinear(QRegExp re)
+void PaintCommands::command_gradient_setLinear(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x1 = convertToDouble(caps.at(1));
@@ -2239,7 +2247,7 @@ void PaintCommands::command_gradient_setLinear(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setLinearPen(QRegExp re)
+void PaintCommands::command_gradient_setLinearPen(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x1 = convertToDouble(caps.at(1));
@@ -2261,7 +2269,7 @@ void PaintCommands::command_gradient_setLinearPen(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setRadial(QRegExp re)
+void PaintCommands::command_gradient_setRadial(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double cx = convertToDouble(caps.at(1));
@@ -2286,7 +2294,7 @@ void PaintCommands::command_gradient_setRadial(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setRadialExtended(QRegExp re)
+void PaintCommands::command_gradient_setRadialExtended(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double cx = convertToDouble(caps.at(1));
@@ -2312,7 +2320,7 @@ void PaintCommands::command_gradient_setRadialExtended(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setConical(QRegExp re)
+void PaintCommands::command_gradient_setConical(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double cx = convertToDouble(caps.at(1));
@@ -2335,9 +2343,9 @@ void PaintCommands::command_gradient_setConical(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_gradient_setSpread(QRegExp re)
+void PaintCommands::command_gradient_setSpread(QRegularExpressionMatch re)
{
- int spreadMethod = translateEnum(spreadMethodTable, re.cap(1), 3);
+ int spreadMethod = translateEnum(spreadMethodTable, re.captured(1), 3);
if (m_verboseMode)
printf(" -(lance) gradient_setSpread %d=[%s]\n", spreadMethod, spreadMethodTable[spreadMethod]);
@@ -2345,9 +2353,9 @@ void PaintCommands::command_gradient_setSpread(QRegExp re)
m_gradientSpread = QGradient::Spread(spreadMethod);
}
-void PaintCommands::command_gradient_setCoordinateMode(QRegExp re)
+void PaintCommands::command_gradient_setCoordinateMode(QRegularExpressionMatch re)
{
- int coord = translateEnum(coordinateMethodTable, re.cap(1), 3);
+ int coord = translateEnum(coordinateMethodTable, re.captured(1), 3);
if (m_verboseMode)
printf(" -(lance) gradient_setCoordinateMode %d=[%s]\n", coord,
@@ -2357,7 +2365,7 @@ void PaintCommands::command_gradient_setCoordinateMode(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_surface_begin(QRegExp re)
+void PaintCommands::command_surface_begin(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x = convertToDouble(caps.at(1));
@@ -2417,7 +2425,7 @@ void PaintCommands::command_surface_begin(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_surface_end(QRegExp)
+void PaintCommands::command_surface_end(QRegularExpressionMatch)
{
if (!m_surface_painter) {
fprintf(stderr, "ERROR: surface not active");
@@ -2466,7 +2474,7 @@ void PaintCommands::command_surface_end(QRegExp)
}
/***************************************************************************************************/
-void PaintCommands::command_image_convertToFormat(QRegExp re)
+void PaintCommands::command_image_convertToFormat(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2499,7 +2507,7 @@ void PaintCommands::command_image_convertToFormat(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_textlayout_draw(QRegExp re)
+void PaintCommands::command_textlayout_draw(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
@@ -2532,7 +2540,7 @@ void PaintCommands::command_textlayout_draw(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_pen_setDashOffset(QRegExp re)
+void PaintCommands::command_pen_setDashOffset(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double offset = convertToDouble(caps.at(1));
@@ -2546,9 +2554,9 @@ void PaintCommands::command_pen_setDashOffset(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_pen_setDashPattern(QRegExp re)
+void PaintCommands::command_pen_setDashPattern(QRegularExpressionMatch re)
{
- static QRegExp separators("\\s");
+ static QRegularExpression separators("\\s");
QStringList caps = re.capturedTexts();
QString cap = caps.at(1);
QStringList numbers = cap.split(separators, QString::SkipEmptyParts);
@@ -2566,7 +2574,7 @@ void PaintCommands::command_pen_setDashPattern(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_pen_setCosmetic(QRegExp re)
+void PaintCommands::command_pen_setCosmetic(QRegularExpressionMatch re)
{
QString hm = re.capturedTexts().at(1);
bool on = hm == "true" || hm == "yes" || hm == "on";
@@ -2582,9 +2590,9 @@ void PaintCommands::command_pen_setCosmetic(QRegExp re)
}
/***************************************************************************************************/
-void PaintCommands::command_drawConvexPolygon(QRegExp re)
+void PaintCommands::command_drawConvexPolygon(QRegularExpressionMatch re)
{
- static QRegExp separators("\\s");
+ static QRegularExpression separators("\\s");
QStringList caps = re.capturedTexts();
QString cap = caps.at(1);
QStringList numbers = cap.split(separators, QString::SkipEmptyParts);
diff --git a/tests/auto/other/lancelot/paintcommands.h b/tests/auto/other/lancelot/paintcommands.h
index fc7496ce11..e3fb96744c 100644
--- a/tests/auto/other/lancelot/paintcommands.h
+++ b/tests/auto/other/lancelot/paintcommands.h
@@ -32,13 +32,13 @@
#include <qmap.h>
#include <qpainterpath.h>
#include <qregion.h>
+#include <qregularexpression.h>
#include <qstringlist.h>
#include <qpixmap.h>
#include <qbrush.h>
#include <qhash.h>
QT_FORWARD_DECLARE_CLASS(QPainter)
-QT_FORWARD_DECLARE_CLASS(QRegExp)
#ifndef QT_NO_OPENGL
QT_FORWARD_DECLARE_CLASS(QOpenGLFramebufferObject)
QT_FORWARD_DECLARE_CLASS(QOpenGLPaintDevice)
@@ -128,121 +128,121 @@ private:
QColor convertToColor(const QString &str);
// commands: comments
- void command_comment(QRegExp re);
+ void command_comment(QRegularExpressionMatch re);
// commands: importer
- void command_import(QRegExp re);
+ void command_import(QRegularExpressionMatch re);
// commands: blocks
- void command_begin_block(QRegExp re);
- void command_end_block(QRegExp re);
- void command_repeat_block(QRegExp re);
+ void command_begin_block(QRegularExpressionMatch re);
+ void command_end_block(QRegularExpressionMatch re);
+ void command_repeat_block(QRegularExpressionMatch re);
// commands: misc
- void command_textlayout_draw(QRegExp re);
- void command_abort(QRegExp re);
+ void command_textlayout_draw(QRegularExpressionMatch re);
+ void command_abort(QRegularExpressionMatch re);
// commands: noops
- void command_noop(QRegExp re);
+ void command_noop(QRegularExpressionMatch re);
// commands: setters
- void command_setBgMode(QRegExp re);
- void command_setBackground(QRegExp re);
- void command_setOpacity(QRegExp re);
- void command_path_setFillRule(QRegExp re);
- void command_setBrush(QRegExp re);
- void command_setBrushOrigin(QRegExp re);
- void command_brushTranslate(QRegExp re);
- void command_brushRotate(QRegExp re);
- void command_brushScale(QRegExp re);
- void command_brushShear(QRegExp re);
- void command_setClipPath(QRegExp re);
- void command_setClipRect(QRegExp re);
- void command_setClipRectangle(QRegExp re);
- void command_setClipRegion(QRegExp re);
- void command_setClipping(QRegExp re);
- void command_setCompositionMode(QRegExp re);
- void command_setFont(QRegExp re);
- void command_setPen(QRegExp re);
- void command_setPen2(QRegExp re);
- void command_pen_setDashOffset(QRegExp re);
- void command_pen_setDashPattern(QRegExp re);
- void command_pen_setCosmetic(QRegExp re);
- void command_setRenderHint(QRegExp re);
- void command_clearRenderHint(QRegExp re);
- void command_gradient_appendStop(QRegExp re);
- void command_gradient_clearStops(QRegExp re);
- void command_gradient_setConical(QRegExp re);
- void command_gradient_setLinear(QRegExp re);
- void command_gradient_setRadial(QRegExp re);
- void command_gradient_setRadialExtended(QRegExp re);
- void command_gradient_setLinearPen(QRegExp re);
- void command_gradient_setSpread(QRegExp re);
- void command_gradient_setCoordinateMode(QRegExp re);
+ void command_setBgMode(QRegularExpressionMatch re);
+ void command_setBackground(QRegularExpressionMatch re);
+ void command_setOpacity(QRegularExpressionMatch re);
+ void command_path_setFillRule(QRegularExpressionMatch re);
+ void command_setBrush(QRegularExpressionMatch re);
+ void command_setBrushOrigin(QRegularExpressionMatch re);
+ void command_brushTranslate(QRegularExpressionMatch re);
+ void command_brushRotate(QRegularExpressionMatch re);
+ void command_brushScale(QRegularExpressionMatch re);
+ void command_brushShear(QRegularExpressionMatch re);
+ void command_setClipPath(QRegularExpressionMatch re);
+ void command_setClipRect(QRegularExpressionMatch re);
+ void command_setClipRectangle(QRegularExpressionMatch re);
+ void command_setClipRegion(QRegularExpressionMatch re);
+ void command_setClipping(QRegularExpressionMatch re);
+ void command_setCompositionMode(QRegularExpressionMatch re);
+ void command_setFont(QRegularExpressionMatch re);
+ void command_setPen(QRegularExpressionMatch re);
+ void command_setPen2(QRegularExpressionMatch re);
+ void command_pen_setDashOffset(QRegularExpressionMatch re);
+ void command_pen_setDashPattern(QRegularExpressionMatch re);
+ void command_pen_setCosmetic(QRegularExpressionMatch re);
+ void command_setRenderHint(QRegularExpressionMatch re);
+ void command_clearRenderHint(QRegularExpressionMatch re);
+ void command_gradient_appendStop(QRegularExpressionMatch re);
+ void command_gradient_clearStops(QRegularExpressionMatch re);
+ void command_gradient_setConical(QRegularExpressionMatch re);
+ void command_gradient_setLinear(QRegularExpressionMatch re);
+ void command_gradient_setRadial(QRegularExpressionMatch re);
+ void command_gradient_setRadialExtended(QRegularExpressionMatch re);
+ void command_gradient_setLinearPen(QRegularExpressionMatch re);
+ void command_gradient_setSpread(QRegularExpressionMatch re);
+ void command_gradient_setCoordinateMode(QRegularExpressionMatch re);
// commands: drawing ops
- void command_drawArc(QRegExp re);
- void command_drawChord(QRegExp re);
- void command_drawConvexPolygon(QRegExp re);
- void command_drawEllipse(QRegExp re);
- void command_drawImage(QRegExp re);
- void command_drawLine(QRegExp re);
- void command_drawPath(QRegExp re);
- void command_drawPie(QRegExp re);
- void command_drawPixmap(QRegExp re);
- void command_drawPoint(QRegExp re);
- void command_drawPolygon(QRegExp re);
- void command_drawPolyline(QRegExp re);
- void command_drawRect(QRegExp re);
- void command_drawRoundedRect(QRegExp re);
- void command_drawRoundRect(QRegExp re);
- void command_drawText(QRegExp re);
- void command_drawStaticText(QRegExp re);
- void command_drawTiledPixmap(QRegExp re);
- void command_path_addEllipse(QRegExp re);
- void command_path_addPolygon(QRegExp re);
- void command_path_addRect(QRegExp re);
- void command_path_addText(QRegExp re);
- void command_path_arcTo(QRegExp re);
- void command_path_closeSubpath(QRegExp re);
- void command_path_createOutline(QRegExp re);
- void command_path_cubicTo(QRegExp re);
- void command_path_debugPrint(QRegExp re);
- void command_path_lineTo(QRegExp re);
- void command_path_moveTo(QRegExp re);
- void command_region_addEllipse(QRegExp re);
- void command_region_addRect(QRegExp re);
+ void command_drawArc(QRegularExpressionMatch re);
+ void command_drawChord(QRegularExpressionMatch re);
+ void command_drawConvexPolygon(QRegularExpressionMatch re);
+ void command_drawEllipse(QRegularExpressionMatch re);
+ void command_drawImage(QRegularExpressionMatch re);
+ void command_drawLine(QRegularExpressionMatch re);
+ void command_drawPath(QRegularExpressionMatch re);
+ void command_drawPie(QRegularExpressionMatch re);
+ void command_drawPixmap(QRegularExpressionMatch re);
+ void command_drawPoint(QRegularExpressionMatch re);
+ void command_drawPolygon(QRegularExpressionMatch re);
+ void command_drawPolyline(QRegularExpressionMatch re);
+ void command_drawRect(QRegularExpressionMatch re);
+ void command_drawRoundedRect(QRegularExpressionMatch re);
+ void command_drawRoundRect(QRegularExpressionMatch re);
+ void command_drawText(QRegularExpressionMatch re);
+ void command_drawStaticText(QRegularExpressionMatch re);
+ void command_drawTiledPixmap(QRegularExpressionMatch re);
+ void command_path_addEllipse(QRegularExpressionMatch re);
+ void command_path_addPolygon(QRegularExpressionMatch re);
+ void command_path_addRect(QRegularExpressionMatch re);
+ void command_path_addText(QRegularExpressionMatch re);
+ void command_path_arcTo(QRegularExpressionMatch re);
+ void command_path_closeSubpath(QRegularExpressionMatch re);
+ void command_path_createOutline(QRegularExpressionMatch re);
+ void command_path_cubicTo(QRegularExpressionMatch re);
+ void command_path_debugPrint(QRegularExpressionMatch re);
+ void command_path_lineTo(QRegularExpressionMatch re);
+ void command_path_moveTo(QRegularExpressionMatch re);
+ void command_region_addEllipse(QRegularExpressionMatch re);
+ void command_region_addRect(QRegularExpressionMatch re);
// getters
- void command_region_getClipRegion(QRegExp re);
- void command_path_getClipPath(QRegExp re);
+ void command_region_getClipRegion(QRegularExpressionMatch re);
+ void command_path_getClipPath(QRegularExpressionMatch re);
// commands: surface begin/end
- void command_surface_begin(QRegExp re);
- void command_surface_end(QRegExp re);
+ void command_surface_begin(QRegularExpressionMatch re);
+ void command_surface_end(QRegularExpressionMatch re);
// commands: save/restore painter state
- void command_restore(QRegExp re);
- void command_save(QRegExp re);
+ void command_restore(QRegularExpressionMatch re);
+ void command_save(QRegularExpressionMatch re);
// commands: pixmap/image
- void command_pixmap_load(QRegExp re);
- void command_pixmap_setMask(QRegExp re);
- void command_bitmap_load(QRegExp re);
- void command_image_convertToFormat(QRegExp re);
- void command_image_load(QRegExp re);
- void command_image_setColor(QRegExp re);
- void command_image_setColorCount(QRegExp re);
+ void command_pixmap_load(QRegularExpressionMatch re);
+ void command_pixmap_setMask(QRegularExpressionMatch re);
+ void command_bitmap_load(QRegularExpressionMatch re);
+ void command_image_convertToFormat(QRegularExpressionMatch re);
+ void command_image_load(QRegularExpressionMatch re);
+ void command_image_setColor(QRegularExpressionMatch re);
+ void command_image_setColorCount(QRegularExpressionMatch re);
// commands: transformation
- void command_resetMatrix(QRegExp re);
- void command_translate(QRegExp re);
- void command_rotate(QRegExp re);
- void command_rotate_x(QRegExp re);
- void command_rotate_y(QRegExp re);
- void command_scale(QRegExp re);
- void command_mapQuadToQuad(QRegExp re);
- void command_setMatrix(QRegExp re);
+ void command_resetMatrix(QRegularExpressionMatch re);
+ void command_translate(QRegularExpressionMatch re);
+ void command_rotate(QRegularExpressionMatch re);
+ void command_rotate_x(QRegularExpressionMatch re);
+ void command_rotate_y(QRegularExpressionMatch re);
+ void command_scale(QRegularExpressionMatch re);
+ void command_mapQuadToQuad(QRegularExpressionMatch re);
+ void command_setMatrix(QRegularExpressionMatch re);
// attributes
QPainter *m_painter;
@@ -302,7 +302,7 @@ private:
public:
struct PaintCommandInfos
{
- PaintCommandInfos(QString id, void (PaintCommands::*p)(QRegExp), QRegExp r, QString sy, QString sa)
+ PaintCommandInfos(QString id, void (PaintCommands::*p)(QRegularExpressionMatch), QRegularExpression r, QString sy, QString sa)
: identifier(id)
, regExp(r)
, syntax(sy)
@@ -313,10 +313,10 @@ public:
: identifier(title), paintMethod(0) {}
bool isSectionHeader() const { return paintMethod == 0; }
QString identifier;
- QRegExp regExp;
+ QRegularExpression regExp;
QString syntax;
QString sample;
- void (PaintCommands::*paintMethod)(QRegExp);
+ void (PaintCommands::*paintMethod)(QRegularExpressionMatch);
};
static PaintCommandInfos *findCommandById(const QString &identifier) {
diff --git a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
index 70e696e703..37521a64aa 100644
--- a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
+++ b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
@@ -196,7 +196,6 @@ void tst_QFocusEvent::checkReason_BackTab()
// Now test the backtab key
QTest::keyClick( childFocusWidgetOne, Qt::Key_Backtab );
- QTest::qWait(200);
QTRY_VERIFY(childFocusWidgetOne->focusOutEventRecieved);
QVERIFY(childFocusWidgetTwo->focusInEventRecieved);
@@ -217,7 +216,6 @@ void tst_QFocusEvent::checkReason_Popup()
QMenu* popupMenu = new QMenu( testFocusWidget );
popupMenu->addMenu( "Test" );
popupMenu->popup( QPoint(0,0) );
- QTest::qWait(50);
QTRY_VERIFY(childFocusWidgetOne->focusOutEventLostFocus);
@@ -308,7 +306,7 @@ void tst_QFocusEvent::checkReason_focusWidget()
window1.show();
edit1.setFocus();
- QTest::qWait(100);
+ QTRY_VERIFY(edit1.hasFocus());
edit2.setFocus();
QVERIFY(frame1.focusWidget() != 0);
@@ -344,7 +342,6 @@ void tst_QFocusEvent::checkReason_ActiveWindow()
QVERIFY( !childFocusWidgetOne->hasFocus() );
d->hide();
- QTest::qWait(100);
if (!QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)
|| !QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive)) {
diff --git a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
index aa78d70716..e6eb51500b 100644
--- a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
@@ -420,11 +420,7 @@ void tst_QObjectRace::disconnectRace()
threads[i]->start();
}
- QTime timeLimiter;
- timeLimiter.start();
-
- while (timeLimiter.elapsed() < TimeLimit)
- QTest::qWait(10);
+ QTest::qWait(TimeLimit);
for (int i = 0; i < ThreadCount; ++i) {
threads[i]->requestInterruption();
@@ -450,11 +446,7 @@ void tst_QObjectRace::disconnectRace()
threads[i]->start();
}
- QTime timeLimiter;
- timeLimiter.start();
-
- while (timeLimiter.elapsed() < TimeLimit)
- QTest::qWait(10);
+ QTest::qWait(TimeLimit);
senderThread->requestInterruption();
QVERIFY(senderThread->wait(300));
diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp
index a78bdc34f1..f31a755f9e 100644
--- a/tests/auto/other/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp
@@ -3,27 +3,26 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of Qt Creator.
+** This file is part of the test suite of the Qt Toolkit.
**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
index 88bae686ab..f68cf5c59c 100644
--- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
+++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
@@ -592,10 +592,14 @@ void tst_QPrinter::printDialogCompleter()
{
QPrintDialog dialog;
dialog.printer()->setOutputFileName(testPdfFileName(QLatin1String("file")));
+#if defined(Q_OS_WIN) || defined(Q_OS_DARWIN)
+ if (dialog.printer()->outputFormat() != QPrinter::NativeFormat)
+ QSKIP("Dialog cannot be used with non-native formats");
+#endif
dialog.setEnabledOptions(QAbstractPrintDialog::PrintToFile);
dialog.show();
- QTest::qWait(100);
+ QVERIFY(QTest::qWaitForWindowActive(&dialog));
QTest::keyClick(&dialog, Qt::Key_Tab);
QTest::keyClick(&dialog, 'P');
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index 89978319a0..1f055e9c33 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -890,10 +890,10 @@ void tst_QSqlDatabase::recordMySQL()
static QDateTime dt(QDate::currentDate(), QTime(1, 2, 3, 0));
static const FieldDef fieldDefs[] = {
- FieldDef("tinyint", QVariant::Int, 127),
- FieldDef("tinyint unsigned", QVariant::UInt, 255),
- FieldDef("smallint", QVariant::Int, 32767),
- FieldDef("smallint unsigned", QVariant::UInt, 65535),
+ FieldDef("tinyint", static_cast<QVariant::Type>(QMetaType::Char), 127),
+ FieldDef("tinyint unsigned", static_cast<QVariant::Type>(QMetaType::UChar), 255),
+ FieldDef("smallint", static_cast<QVariant::Type>(QMetaType::Short), 32767),
+ FieldDef("smallint unsigned", static_cast<QVariant::Type>(QMetaType::UShort), 65535),
FieldDef("mediumint", QVariant::Int, 8388607),
FieldDef("mediumint unsigned", QVariant::UInt, 16777215),
FieldDef("integer", QVariant::Int, 2147483647),
@@ -2374,6 +2374,9 @@ public slots:
"QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
QSqlDatabase db = QSqlDatabase::database(dbName);
QVERIFY(!db.isValid());
+
+ QSqlDatabase invalidDb = QSqlDatabase::database("invalid");
+ QVERIFY(!invalidDb.isValid());
QThread::currentThread()->exit();
}
private:
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index a51865897f..23c8460133 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -128,6 +128,8 @@ private slots:
void mysql_outValues();
void oraClob_data() { generic_data("QOCI"); }
void oraClob();
+ void oraClobBatch_data() { generic_data("QOCI"); }
+ void oraClobBatch();
void oraLong_data() { generic_data("QOCI"); }
void oraLong();
void oraOCINumber_data() { generic_data("QOCI"); }
@@ -176,6 +178,8 @@ private slots:
void emptyTableNavigate();
void timeStampParsing_data() { generic_data(); }
void timeStampParsing();
+ void sqliteVirtualTable_data() { generic_data("QSQLITE"); }
+ void sqliteVirtualTable();
#ifdef NOT_READY_YET
void task_229811();
@@ -357,7 +361,6 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db )
<< qTableName("more_results", __FILE__, db)
<< qTableName("blobstest", __FILE__, db)
<< qTableName("oraRowId", __FILE__, db)
- << qTableName("qtest_batch", __FILE__, db)
<< qTableName("bug43874", __FILE__, db)
<< qTableName("bug6421", __FILE__, db).toUpper()
<< qTableName("bug5765", __FILE__, db)
@@ -809,6 +812,28 @@ void tst_QSqlQuery::oraClob()
QVERIFY( q.value( 1 ).toByteArray() == loong.toLatin1() );
}
+void tst_QSqlQuery::oraClobBatch()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const QString clobBatch(qTableName("clobBatch", __FILE__, db));
+ tst_Databases::safeDropTables(db, { clobBatch });
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("create table " + clobBatch + "(cl clob)"));
+
+ const QString longString(USHRT_MAX + 1, QLatin1Char('A'));
+ QVERIFY_SQL(q, prepare("insert into " + clobBatch + " (cl) values(:cl)"));
+ const QVariantList vars = { longString };
+ q.addBindValue(vars);
+ QVERIFY_SQL(q, execBatch());
+
+ QVERIFY_SQL(q, exec("select cl from " + clobBatch));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toString().count(), longString.size());
+ QVERIFY(q.value(0).toString() == longString);
+}
+
void tst_QSqlQuery::storedProceduresIBase()
{
QFETCH( QString, dbName );
@@ -2437,76 +2462,103 @@ void tst_QSqlQuery::batchExec()
QSqlDatabase db = QSqlDatabase::database( dbName );
CHECK_DATABASE( db );
- if ( !db.driver()->hasFeature( QSqlDriver::BatchOperations ) )
- QSKIP( "Database can't do BatchOperations");
-
QSqlQuery q( db );
const QString tableName = qTableName("qtest_batch", __FILE__, db);
-
- QVERIFY_SQL(q, exec("create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4), dtstamp TIMESTAMP(3))"));
- QVERIFY_SQL(q, prepare("insert into " + tableName + " (id, name, dt, num, dtstamp) values (?, ?, ?, ?, ?)"));
-
- QVariantList intCol;
- intCol << 1 << 2 << QVariant( QVariant::Int );
-
- QVariantList charCol;
- charCol << QLatin1String( "harald" ) << QLatin1String( "boris" ) << QVariant( QVariant::String );
-
- QVariantList dateCol;
- QDateTime dt = QDateTime( QDate::currentDate(), QTime( 1, 2, 3 ) );
- dateCol << dt << dt.addDays( -1 ) << QVariant( QVariant::DateTime );
-
- QVariantList numCol;
- numCol << 2.3 << 3.4 << QVariant( QVariant::Double );
-
- QVariantList timeStampCol;
- const QDateTime dtStamp = QDateTime(QDate::currentDate(), QTime(1, 2, 3, 4));
- timeStampCol << dtStamp << dtStamp.addDays(-1) << QVariant(QVariant::DateTime);
-
+ tst_Databases::safeDropTable(db, tableName);
+ QVERIFY_SQL(q, exec(QStringLiteral("create table ") + tableName +
+ QStringLiteral(" (id int, name varchar(20), dt date, num numeric(8, 4), "
+ "dtstamp TIMESTAMP(3), extraId int, extraName varchar(20))")));
+
+ const QVariantList intCol = { 1, 2, QVariant(QVariant::Int) };
+ const QVariantList charCol = { QStringLiteral("harald"), QStringLiteral("boris"),
+ QVariant(QVariant::String) };
+ const QDateTime currentDateTime = QDateTime(QDateTime::currentDateTime());
+ const QVariantList dateCol = { currentDateTime.date(), currentDateTime.date().addDays(-1),
+ QVariant(QVariant::Date) };
+ const QVariantList numCol = { 2.3, 3.4, QVariant(QVariant::Double) };
+ const QVariantList timeStampCol = { currentDateTime, currentDateTime.addDays(-1),
+ QVariant(QVariant::DateTime) };
+
+ // Test with positional placeholders
+ QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName +
+ QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) values "
+ "(?, ?, ?, ?, ?, ?, ?)")));
q.addBindValue(intCol);
q.addBindValue( charCol );
q.addBindValue( dateCol );
q.addBindValue( numCol );
q.addBindValue(timeStampCol);
+ q.addBindValue(intCol);
+ q.addBindValue(charCol);
QVERIFY_SQL( q, execBatch() );
- QVERIFY_SQL(q, exec("select id, name, dt, num, dtstamp from " + tableName + " order by id"));
+ QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, "
+ "extraId, extraName from ") + tableName));
- QVERIFY( q.next() );
- QCOMPARE( q.value( 0 ).toInt(), 1 );
- QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) );
- QCOMPARE( q.value( 2 ).toDateTime(), dt );
- QCOMPARE( q.value( 3 ).toDouble(), 2.3 );
- QCOMPARE(q.value(4).toDateTime(), dtStamp);
-
- QVERIFY( q.next() );
- QCOMPARE( q.value( 0 ).toInt(), 2 );
- QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) );
- QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) );
- QCOMPARE( q.value( 3 ).toDouble(), 3.4 );
- QCOMPARE(q.value(4).toDateTime(), dtStamp.addDays(-1));
+ for (int i = 0; i < intCol.size(); ++i) {
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), intCol.at(i));
+ QCOMPARE(q.value(1).toString(), charCol.at(i));
+ QCOMPARE(q.value(2).toDate(), dateCol.at(i));
+ QCOMPARE(q.value(3).toDouble(), numCol.at(i));
+ if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) {
+ QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the "
+ "current datetime for a timestamp field", Continue);
+ }
+ QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i));
+ QCOMPARE(q.value(5).toInt(), intCol.at(i));
+ QCOMPARE(q.value(6).toString(), charCol.at(i));
+ }
- QVERIFY( q.next() );
- QVERIFY( q.value( 0 ).isNull() );
- QVERIFY( q.value( 1 ).isNull() );
- QVERIFY( q.value( 2 ).isNull() );
- QVERIFY( q.value( 3 ).isNull() );
- QVERIFY(q.value(4).isNull());
+ // Empty table ready for retesting with duplicated named placeholders
+ QVERIFY_SQL(q, exec(QStringLiteral("delete from ") + tableName));
+ QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName +
+ QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) "
+ "values (:id, :name, :dt, :num, :dtstamp, :id, :name)")));
+ q.bindValue(":id", intCol);
+ q.bindValue(":name", charCol);
+ q.bindValue(":dt", dateCol);
+ q.bindValue(":num", numCol);
+ q.bindValue(":dtstamp", timeStampCol);
- const QString procName = qTableName("qtest_batch_proc", __FILE__, db);
- QVERIFY_SQL(q, exec("create or replace procedure " + procName + " (x in timestamp, y out timestamp) is\n"
- "begin\n"
- " y := x;\n"
- "end;\n"));
- QVERIFY(q.prepare("call " + procName + "(?, ?)"));
- q.addBindValue(timeStampCol, QSql::In);
- QVariantList emptyDateTimes;
- emptyDateTimes.reserve(timeStampCol.size());
- for (int i = 0; i < timeStampCol.size(); i++)
- emptyDateTimes << QVariant(QDateTime());
- q.addBindValue(emptyDateTimes, QSql::Out);
QVERIFY_SQL(q, execBatch());
- QCOMPARE(q.boundValue(1).toList(), timeStampCol);
+ QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, extraId, extraName from ") +
+ tableName));
+
+ for (int i = 0; i < intCol.size(); ++i) {
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toInt(), intCol.at(i));
+ QCOMPARE(q.value(1).toString(), charCol.at(i));
+ QCOMPARE(q.value(2).toDate(), dateCol.at(i));
+ QCOMPARE(q.value(3).toDouble(), numCol.at(i));
+ if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) {
+ QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the "
+ "current datetime for a timestamp field", Continue);
+ }
+ QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i));
+ QCOMPARE(q.value(5).toInt(), intCol.at(i));
+ QCOMPARE(q.value(6).toString(), charCol.at(i));
+ }
+
+ // Only test the prepared stored procedure approach where the driver has support
+ // for batch operations as this will not work without it
+ if (db.driver()->hasFeature(QSqlDriver::BatchOperations)) {
+ const QString procName = qTableName("qtest_batch_proc", __FILE__, db);
+ QVERIFY_SQL(q, exec("create or replace procedure " + procName +
+ " (x in timestamp, y out timestamp) is\n"
+ "begin\n"
+ " y := x;\n"
+ "end;\n"));
+ QVERIFY(q.prepare("call " + procName + "(?, ?)"));
+ q.addBindValue(timeStampCol, QSql::In);
+ QVariantList emptyDateTimes;
+ emptyDateTimes.reserve(timeStampCol.size());
+ for (int i = 0; i < timeStampCol.size(); i++)
+ emptyDateTimes << QVariant(QDateTime());
+ q.addBindValue(emptyDateTimes, QSql::Out);
+ QVERIFY_SQL(q, execBatch());
+ QCOMPARE(q.boundValue(1).toList(), timeStampCol);
+ }
}
void tst_QSqlQuery::QTBUG_43874()
@@ -3033,11 +3085,7 @@ void tst_QSqlQuery::nextResult()
QCOMPARE( q.record().field( 0 ).type(), QVariant::String );
QCOMPARE( q.record().field( 1 ).name().toUpper(), QString( "NUM" ) );
-
- if (dbType == QSqlDriver::MySqlServer)
- QCOMPARE( q.record().field( 1 ).type(), QVariant::String );
- else
- QCOMPARE( q.record().field( 1 ).type(), QVariant::Double );
+ QCOMPARE(q.record().field(1).type(), QVariant::Double);
QVERIFY( q.next() ); // Move to first row of the second result set
@@ -3287,6 +3335,10 @@ void tst_QSqlQuery::timeStampParsing()
QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE ") + tableName + QStringLiteral("("
"id serial NOT NULL, "
"datefield timestamp, primary key(id));")));
+ } else if (dbType == QSqlDriver::MySqlServer) {
+ QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE ") + tableName + QStringLiteral("("
+ "id integer NOT NULL AUTO_INCREMENT,"
+ "datefield timestamp, primary key(id));")));
} else {
QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE ") + tableName + QStringLiteral("("
"\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"
@@ -4623,5 +4675,44 @@ void tst_QSqlQuery::dateTime()
}
}
+void tst_QSqlQuery::sqliteVirtualTable()
+{
+ // Virtual tables can behave differently when it comes to prepared
+ // queries, so we need to check these explicitly
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const auto tableName = qTableName("sqliteVirtual", __FILE__, db);
+ QSqlQuery qry(db);
+ QVERIFY_SQL(qry, exec("create virtual table " + tableName + " using fts3(id, name)"));
+
+ // Delibrately malform the query to try and provoke a potential crash situation
+ QVERIFY_SQL(qry, prepare("select * from " + tableName + " where name match '?'"));
+ qry.addBindValue("Andy");
+ QVERIFY(!qry.exec());
+
+ QVERIFY_SQL(qry, prepare("insert into " + tableName + "(id, name) VALUES (?, ?)"));
+ qry.addBindValue(1);
+ qry.addBindValue("Andy");
+ QVERIFY_SQL(qry, exec());
+
+ QVERIFY_SQL(qry, exec("select * from " + tableName));
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toInt(), 1);
+ QCOMPARE(qry.value(1).toString(), "Andy");
+
+ QVERIFY_SQL(qry, prepare("insert into " + tableName + "(id, name) values (:id, :name)"));
+ qry.bindValue(":id", 2);
+ qry.bindValue(":name", "Peter");
+ QVERIFY_SQL(qry, exec());
+
+ QVERIFY_SQL(qry, prepare("select * from " + tableName + " where name match ?"));
+ qry.addBindValue("Peter");
+ QVERIFY_SQL(qry, exec());
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toInt(), 2);
+ QCOMPARE(qry.value(1).toString(), "Peter");
+}
+
QTEST_MAIN( tst_QSqlQuery )
#include "tst_qsqlquery.moc"
diff --git a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
index 3aef916c38..df241c030e 100644
--- a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
+++ b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
@@ -259,8 +259,7 @@ void tst_QSignalSpy::wait_signalEmittedTooLate()
QTimer::singleShot(500, this, SIGNAL(sigFoo()));
QSignalSpy spy(this, SIGNAL(sigFoo()));
QVERIFY(!spy.wait(200));
- QTest::qWait(400);
- QCOMPARE(spy.count(), 1);
+ QTRY_COMPARE(spy.count(), 1);
}
void tst_QSignalSpy::wait_signalEmittedMultipleTimes()
diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py
index 6c14d75ea6..aa11ca4fe7 100755
--- a/tests/auto/testlib/selftests/generate_expected_output.py
+++ b/tests/auto/testlib/selftests/generate_expected_output.py
@@ -257,7 +257,7 @@ def main(name, *args):
# Avoid interference from any qtlogging.ini files, e.g. in
# /etc/xdg/QtProject/, (must match tst_selftests.cpp's
# processEnvironment()'s value):
- QT_LOGGING_RULES = '*.debug=true;qt.qpa.screen=false')
+ QT_LOGGING_RULES = '*.debug=true;qt.*=false')
herePath = os.getcwd()
cleaner = Cleaner(herePath, name)
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index 93d5daa160..63e5721e7e 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -404,7 +404,6 @@ tst_Selftests::tst_Selftests()
void tst_Selftests::initTestCase()
{
QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString()));
- qputenv("QT_LOGGING_RULES", QByteArrayLiteral("*.debug=false")); // Silence any debug output
//Detect the location of the sub programs
QString subProgram = QLatin1String("float/float");
#if defined(Q_OS_WIN)
@@ -644,7 +643,7 @@ static QProcessEnvironment processEnvironment()
// Avoid interference from any qtlogging.ini files, e.g. in /etc/xdg/QtProject/:
result.insert(QStringLiteral("QT_LOGGING_RULES"),
// Must match generate_expected_output.py's main()'s value:
- QStringLiteral("*.debug=true;qt.qpa.screen=false"));
+ QStringLiteral("*.debug=true;qt.*=false"));
}
return result;
}
diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro
index d2b13f9c4e..3cbc9ebb5e 100644
--- a/tests/auto/tools/moc/moc.pro
+++ b/tests/auto/tools/moc/moc.pro
@@ -36,11 +36,11 @@ if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlin
if(*-g++*|*-clang*): HEADERS += dollars.h
SOURCES += tst_moc.cpp
-QT = core sql network testlib
-qtHaveModule(dbus) {
- DEFINES += WITH_DBUS
- QT += dbus
-}
+QT = core testlib
+qtHaveModule(dbus): QT += dbus
+qtHaveModule(concurrent): QT += concurrent
+qtHaveModule(network): QT += network
+qtHaveModule(sql): QT += sql
# tst_Moc::specifyMetaTagsFromCmdline()
# Ensure that plugin_metadata.h are moc-ed with some extra -M arguments:
diff --git a/tests/auto/tools/moc/no-keywords.h b/tests/auto/tools/moc/no-keywords.h
index d31063665b..ca77056503 100644
--- a/tests/auto/tools/moc/no-keywords.h
+++ b/tests/auto/tools/moc/no-keywords.h
@@ -37,16 +37,19 @@
#define slots Baz
#define emit Yoyodyne
+#include <QtCore/QtCore>
+
+#ifdef QT_CONCURRENT_LIB
#include <QtConcurrent/QtConcurrent>
-#include <QtCore>
+#endif
+#ifdef QT_NETWORK_LIB
#include <QtNetwork/QtNetwork>
+#endif
+#ifdef QT_SQL_LIB
#include <QtSql/QtSql>
-//#include <QtSvg>
-#if defined(WITH_DBUS)
-#include <QtDBus>
#endif
-#ifdef QT_SCRIPT_LIB
-#include <QtScript>
+#ifdef QT_DBUS_LIB
+#include <QtDBus/QtDBus>
#endif
#undef signals
diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp
index 786b9e72f1..aeedf4ae32 100644
--- a/tests/auto/tools/qmakelib/evaltest.cpp
+++ b/tests/auto/tools/qmakelib/evaltest.cpp
@@ -1604,6 +1604,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
+ QTest::newRow("$$absolute_path(): relative file & relative path")
+ << "VAR = $$absolute_path(dir/file.ext, some/where)"
+ << "VAR = " + qindir + "/some/where/dir/file.ext"
+ << ""
+ << true;
+
QTest::newRow("$$absolute_path(): file & path")
<< "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)"
<< "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext"
@@ -1642,6 +1648,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< ""
<< true;
+ QTest::newRow("$$relative_path(): relative file & relative path")
+ << "VAR = $$relative_path(dir/file.ext, some/where)"
+ << "VAR = dir/file.ext"
+ << ""
+ << true;
+
QTest::newRow("$$relative_path(): relative file to empty")
<< "VAR = $$relative_path(dir/..)"
<< "VAR = ."
@@ -2363,11 +2375,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("include(): fail")
<< "include(include/nope.pri): OK = 1"
<< "OK = UNDEF"
-#ifdef Q_OS_WIN
- << "Cannot read " + m_indir + "/include/nope.pri: The system cannot find the file specified."
-#else
<< "Cannot read " + m_indir + "/include/nope.pri: No such file or directory"
-#endif
<< true;
QTest::newRow("include(): silent fail")
@@ -2752,9 +2760,9 @@ void tst_qmakelib::proEval_data()
// Raw data leak with empty file name. Verify with Valgrind or asan.
QTest::newRow("QTBUG-54550")
- << "FULL = /there/is\n"
+ << "FULL = " EVAL_DRIVE "/there/is\n"
"VAR = $$absolute_path(, $$FULL/nothing/here/really)"
- << "VAR = /there/is/nothing/here/really"
+ << "VAR = " EVAL_DRIVE "/there/is/nothing/here/really"
<< ""
<< true;
}
@@ -2861,12 +2869,12 @@ void tst_qmakelib::proEval()
globals.environment = m_env;
globals.setProperties(m_prop);
globals.setDirectories(m_indir, m_outdir);
- ProFile *outPro = parser.parsedProBlock(QStringRef(&out), "out", 1, QMakeParser::FullGrammar);
+ ProFile *outPro = parser.parsedProBlock(QStringRef(&out), 0, "out", 1, QMakeParser::FullGrammar);
if (!outPro->isOk()) {
qWarning("Expected output is malformed");
verified = false;
}
- ProFile *pro = parser.parsedProBlock(QStringRef(&in), infile, 1, QMakeParser::FullGrammar);
+ ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, infile, 1, QMakeParser::FullGrammar);
QMakeEvaluator visitor(&globals, &parser, &vfs, &handler);
visitor.setOutputDir(m_outdir);
#ifdef Q_OS_WIN
diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp
index 70f1be5fc3..f736bf38bf 100644
--- a/tests/auto/tools/qmakelib/parsertest.cpp
+++ b/tests/auto/tools/qmakelib/parsertest.cpp
@@ -2031,7 +2031,7 @@ void tst_qmakelib::proParser()
handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts));
QMakeVfs vfs;
QMakeParser parser(0, &vfs, &handler);
- ProFile *pro = parser.parsedProBlock(QStringRef(&in), "in", 1, QMakeParser::FullGrammar);
+ ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, "in", 1, QMakeParser::FullGrammar);
if (handler.printedMessages()) {
qWarning("Got unexpected message(s)");
verified = false;
diff --git a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro
index 4ea23a896f..1cdf10d29a 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro
+++ b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro
@@ -9,5 +9,3 @@ QT += core-private gui-private
SOURCES += tst_qfiledialog.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"
-
-linux*: CONFIG += insignificant_test # Crashes on different Linux distros
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 05410f4a0f..90f8457b7f 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -471,6 +471,9 @@ void tst_QFiledialog::completer()
for (int i = 0; i < 10; ++i) {
TemporaryFilePtr file(new QTemporaryFile(startPath + QStringLiteral("/rXXXXXX")));
QVERIFY2(file->open(), qPrintable(file->errorString()));
+ // Force the temporary file to materialize with the requested name
+ (void) file->fileName();
+ QVERIFY(file->exists());
files.append(file);
}
}
diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
index dfe5baba71..a1cb729849 100644
--- a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
+++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
@@ -52,7 +52,6 @@ private slots:
void boundingRect2();
void draw();
void opacity();
- void nestedOpaqueOpacity();
void grayscale();
void colorize();
void drawPixmapItem();
@@ -408,26 +407,6 @@ void tst_QGraphicsEffect::opacity()
QCOMPARE(effect->m_opacity, qreal(0.5));
}
-void tst_QGraphicsEffect::nestedOpaqueOpacity()
-{
- // QTBUG-60231: Nesting widgets with a QGraphicsEffect on a toplevel with
- // QGraphicsOpacityEffect caused crashes due to constructing several
- // QPainter instances on a device in the fast path for
- // QGraphicsOpacityEffect::opacity=1
- QWidget topLevel;
- topLevel.setWindowTitle(QTest::currentTestFunction());
- topLevel.resize(320, 200);
- QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
- opacityEffect->setOpacity(1);
- topLevel.setGraphicsEffect(opacityEffect);
- QWidget *child = new QWidget(&topLevel);
- child->resize(topLevel.size() / 2);
- QGraphicsDropShadowEffect *childEffect = new QGraphicsDropShadowEffect;
- child->setGraphicsEffect(childEffect);
- topLevel.show();
- QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
-}
-
void tst_QGraphicsEffect::grayscale()
{
if (qApp->desktop()->depth() < 24)
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index 8287b9ebdd..4cd2fef2dc 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -281,7 +281,7 @@ void tst_QGraphicsProxyWidget::initTestCase()
// This will be called after every test function.
void tst_QGraphicsProxyWidget::cleanup()
{
- QVERIFY(QApplication::topLevelWidgets().isEmpty());
+ QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
}
void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data()
@@ -2575,6 +2575,22 @@ void tst_QGraphicsProxyWidget::changingCursor_basic()
}
#endif
+static bool findViewAndTipLabel(const QWidget *view)
+{
+ bool foundView = false;
+ bool foundTipLabel = false;
+ const QWidgetList &topLevels = QApplication::topLevelWidgets();
+ for (const QWidget *widget : topLevels) {
+ if (widget == view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ if (foundView && foundTipLabel)
+ return true;
+ }
+ return false;
+}
+
void tst_QGraphicsProxyWidget::tooltip_basic()
{
QString toolTip = "Qt rocks!";
@@ -2627,18 +2643,7 @@ void tst_QGraphicsProxyWidget::tooltip_basic()
QHelpEvent helpEvent(QEvent::ToolTip, view.mapFromScene(proxy->boundingRect().center()),
view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center())));
QApplication::sendEvent(view.viewport(), &helpEvent);
- QTest::qWait(350);
-
- bool foundView = false;
- bool foundTipLabel = false;
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
- if (widget == &view)
- foundView = true;
- if (widget->inherits("QTipLabel"))
- foundTipLabel = true;
- }
- QVERIFY(foundView);
- QVERIFY(foundTipLabel);
+ QTRY_VERIFY(findViewAndTipLabel(&view));
}
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 3d5df7506d..10129eb10c 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -2986,19 +2986,14 @@ void tst_QGraphicsView::acceptMousePressEvent()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QMouseEvent event(QEvent::MouseButtonPress,
- view.viewport()->rect().center(),
- view.viewport()->mapToGlobal(view.viewport()->rect().center()),
- Qt::LeftButton, 0, 0);
- event.setAccepted(false);
- QApplication::sendEvent(view.viewport(), &event);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton);
QVERIFY(!view.pressAccepted);
+ QSignalSpy spy(&scene, &QGraphicsScene::changed);
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(spy.wait());
- qApp->processEvents(); // ensure scene rect is updated
-
- QApplication::sendEvent(view.viewport(), &event);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton);
QVERIFY(view.pressAccepted);
}
@@ -3010,19 +3005,14 @@ void tst_QGraphicsView::acceptMouseDoubleClickEvent()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QMouseEvent event(QEvent::MouseButtonDblClick,
- view.viewport()->rect().center(),
- view.viewport()->mapToGlobal(view.viewport()->rect().center()),
- Qt::LeftButton, 0, 0);
- event.setAccepted(false);
- QApplication::sendEvent(view.viewport(), &event);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton);
QVERIFY(!view.doubleClickAccepted);
+ QSignalSpy spy(&scene, &QGraphicsScene::changed);
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(spy.wait());
- qApp->processEvents(); // ensure scene rect is updated
-
- QApplication::sendEvent(view.viewport(), &event);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton);
QVERIFY(view.doubleClickAccepted);
}
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 812ca4b223..74a2f7f2b6 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -544,11 +544,11 @@ void tst_QHeaderView::movable()
view->setSectionsMovable(true);
QCOMPARE(view->sectionsMovable(), true);
- QCOMPARE(view->firstSectionMovable(), true);
+ QCOMPARE(view->isFirstSectionMovable(), true);
view->setFirstSectionMovable(false);
- QCOMPARE(view->firstSectionMovable(), false);
+ QCOMPARE(view->isFirstSectionMovable(), false);
view->setFirstSectionMovable(true);
- QCOMPARE(view->firstSectionMovable(), true);
+ QCOMPARE(view->isFirstSectionMovable(), true);
}
void tst_QHeaderView::clickable()
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
index fea108f3fd..0f7c377194 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
@@ -2,3 +2,6 @@
opensuse-42.3 ci
[testLineEditValidation]
opensuse-42.3 ci
+[comboBox]
+# QTBUG-67282
+opensuse
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
index 2fed2e0c69..802a04b4bf 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -1389,13 +1389,12 @@ void tst_QItemDelegate::comboBox()
QTableWidget widget(1, 1);
widget.setItem(0, 0, item1);
widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
widget.editItem(item1);
- QTestEventLoop::instance().enterLoop(1);
-
- QComboBox *boolEditor = widget.viewport()->findChild<QComboBox*>();
- QVERIFY(boolEditor);
+ QComboBox *boolEditor = nullptr;
+ QTRY_VERIFY( (boolEditor = widget.viewport()->findChild<QComboBox*>()) );
QCOMPARE(boolEditor->currentIndex(), 1); // True is selected initially.
// The data must actually be different in order for the model
// to be updated.
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 5a9c5dd175..823a52ce70 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -620,7 +620,7 @@ void tst_QWidget::initTestCase()
void tst_QWidget::cleanup()
{
- QVERIFY(QApplication::topLevelWidgets().isEmpty());
+ QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
}
void tst_QWidget::fontPropagation()
@@ -1619,13 +1619,11 @@ void tst_QWidget::focusChainOnHide()
qApp->setActiveWindow(parent->window());
child->activateWindow();
child->setFocus();
- qApp->processEvents();
- QTRY_COMPARE(child->hasFocus(), true);
+ QTRY_VERIFY(child->hasFocus());
child->hide();
- qApp->processEvents();
- QTRY_COMPARE(parent->hasFocus(), true);
+ QTRY_VERIFY(parent->hasFocus());
QCOMPARE(parent.data(), qApp->focusWidget());
}
@@ -2632,25 +2630,21 @@ void tst_QWidget::normalGeometry()
QCOMPARE(parent.normalGeometry(), geom);
parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
- QTest::qWait(10);
QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
QTRY_VERIFY(parent.geometry() != geom);
QTRY_COMPARE(parent.normalGeometry(), geom);
parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
- QTest::qWait(10);
QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
QTRY_COMPARE(parent.geometry(), geom);
QTRY_COMPARE(parent.normalGeometry(), geom);
parent.showMaximized();
- QTest::qWait(10);
QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
QTRY_VERIFY(parent.geometry() != geom);
QCOMPARE(parent.normalGeometry(), geom);
parent.showNormal();
- QTest::qWait(10);
QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
QTRY_COMPARE(parent.geometry(), geom);
QCOMPARE(parent.normalGeometry(), geom);
@@ -2723,8 +2717,7 @@ void tst_QWidget::setGeometry()
tlw.setGeometry(tr);
child.setGeometry(cr);
tlw.showNormal();
- QTest::qWait(50);
- QCOMPARE(tlw.geometry().size(), tr.size());
+ QTRY_COMPARE(tlw.geometry().size(), tr.size());
QCOMPARE(child.geometry(), cr);
tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
@@ -2847,7 +2840,6 @@ void tst_QWidget::lostUpdatesOnHide()
void tst_QWidget::raise()
{
- QTest::qWait(10);
QScopedPointer<QWidget> parentPtr(new QWidget);
parentPtr->resize(200, 200);
parentPtr->setObjectName(QLatin1String("raise"));
@@ -2872,7 +2864,6 @@ void tst_QWidget::raise()
parentPtr->show();
QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data()));
- QTest::qWait(10);
#ifdef Q_OS_OSX
if (child1->internalWinId()) {
@@ -2919,15 +2910,13 @@ void tst_QWidget::raise()
QWidget *parent = parentPtr.take();
parent->setParent(&topLevel);
topLevel.show();
- QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
- QTest::qWait(50);
UpdateWidget *onTop = new UpdateWidget(&topLevel);
onTop->reset();
onTop->resize(topLevel.size());
onTop->setAutoFillBackground(true);
onTop->show();
- QTest::qWait(50);
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTRY_VERIFY(onTop->numPaintEvents > 0);
onTop->reset();
@@ -3436,7 +3425,6 @@ void tst_QWidget::widgetAt()
w2->setWindowTitle(w2->objectName());
w1->showNormal();
QVERIFY(QTest::qWaitForWindowExposed(w1.data()));
- qApp->processEvents();
const QPoint testPos = referencePos + QPoint(100, 100);
QWidget *wr;
QTRY_VERIFY((wr = QApplication::widgetAt((testPos))));
@@ -3444,29 +3432,22 @@ void tst_QWidget::widgetAt()
w2->showNormal();
QVERIFY(QTest::qWaitForWindowExposed(w2.data()));
- qApp->processEvents();
- qApp->processEvents();
- qApp->processEvents();
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)));
QCOMPARE(wr->objectName(), QString("w2"));
w2->lower();
- qApp->processEvents();
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)) && wr->objectName() == QString("w1"));
w2->raise();
- qApp->processEvents();
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)) && wr->objectName() == QString("w2"));
QWidget *w3 = new QWidget(w2.data());
w3->setGeometry(10,10,50,50);
w3->setObjectName("w3");
w3->showNormal();
- qApp->processEvents();
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)) && wr->objectName() == QString("w3"));
w3->setAttribute(Qt::WA_TransparentForMouseEvents);
- qApp->processEvents();
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)) && wr->objectName() == QString("w2"));
if (!QGuiApplicationPrivate::platformIntegration()
@@ -3478,8 +3459,6 @@ void tst_QWidget::widgetAt()
QPoint point = w2->mapFromGlobal(testPos);
rgn -= QRect(point, QSize(1,1));
w2->setMask(rgn);
- qApp->processEvents();
- QTest::qWait(10);
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)));
QTRY_COMPARE(wr->objectName(), w1->objectName());
@@ -3493,8 +3472,6 @@ void tst_QWidget::widgetAt()
p.drawPoint(w2->mapFromGlobal(testPos));
p.end();
w2->setMask(bitmap);
- qApp->processEvents();
- QTest::qWait(10);
QTRY_COMPARE(QApplication::widgetAt(testPos), w1.data());
QTRY_VERIFY(QApplication::widgetAt(testPos + QPoint(1, 1)) == w2.data());
}
@@ -3514,7 +3491,6 @@ void tst_QWidget::task110173()
QTest::keyClick( &w, Qt::Key_Tab );
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(200);
}
class Widget : public QWidget
@@ -3731,8 +3707,7 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.resize(150, 150);
parent.show();
QVERIFY(QTest::qWaitForWindowExposed(&parent));
- QTest::qWait(20);
- QTRY_COMPARE(staticWidget.gotPaintEvent, true);
+ QTRY_VERIFY(staticWidget.gotPaintEvent);
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
@@ -3751,8 +3726,7 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.gotPaintEvent = false;
staticWidget.resize(staticWidget.size() + QSize(10, 10));
- QTest::qWait(20);
- QCOMPARE(staticWidget.gotPaintEvent, true);
+ QTRY_VERIFY(staticWidget.gotPaintEvent);
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
@@ -3762,8 +3736,7 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.gotPaintEvent = false;
staticWidget.resize(staticWidget.size() + QSize(10, -10));
- QTest::qWait(20);
- QCOMPARE(staticWidget.gotPaintEvent, true);
+ QTRY_VERIFY(staticWidget.gotPaintEvent);
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
@@ -3775,8 +3748,7 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
staticWidget.resize(staticWidget.size() + QSize(10, 10));
- QTest::qWait(20);
- QCOMPARE(staticWidget.gotPaintEvent, true);
+ QTRY_VERIFY(staticWidget.gotPaintEvent);
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
@@ -3789,8 +3761,7 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
staticWidget.resize(staticWidget.size() + QSize(-10, -10));
- QTest::qWait(20);
- QCOMPARE(staticWidget.gotPaintEvent, true);
+ QTRY_VERIFY(staticWidget.gotPaintEvent);
QCOMPARE(staticWidget.partial, false);
staticWidget.setAttribute(Qt::WA_StaticContents, true);
@@ -3810,8 +3781,7 @@ void tst_QWidget::optimizedResize_topLevel()
topLevel.gotPaintEvent = false;
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
- QTest::qWait(10);
- QTRY_COMPARE(topLevel.gotPaintEvent, true);
+ QTRY_VERIFY(topLevel.gotPaintEvent);
topLevel.gotPaintEvent = false;
topLevel.partial = false;
@@ -3830,15 +3800,14 @@ void tst_QWidget::optimizedResize_topLevel()
MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
frame.width() + 10, frame.height() + 10,
true);
-#endif
-
QTest::qWait(100);
+#endif
// Expected update region: New rect - old rect.
QRegion expectedUpdateRegion(topLevel.rect());
expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
- QTRY_COMPARE(topLevel.gotPaintEvent, true);
+ QTRY_VERIFY(topLevel.gotPaintEvent);
if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("offscreen"))
QSKIP("QTBUG-26424");
QCOMPARE(topLevel.partial, true);
@@ -3886,12 +3855,10 @@ void tst_QWidget::setMinimumSize()
QCOMPARE(w.size(), defaultSize + QSize(200, 200));
QVERIFY(!w.testAttribute(Qt::WA_Resized));
- // Setting a minimum size larger than the desktop does not work on WinCE,
- // so skip this part of the test.
QSize nonDefaultSize = defaultSize + QSize(5,5);
w.setMinimumSize(nonDefaultSize);
w.showNormal();
- QTest::qWait(50);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
QVERIFY2(w.height() >= nonDefaultSize.height(),
msgComparisonFailed(w.height(), ">=", nonDefaultSize.height()));
QVERIFY2(w.width() >= nonDefaultSize.width(),
@@ -3943,7 +3910,7 @@ void tst_QWidget::setFixedSize()
w.setFixedSize(defaultSize + QSize(150, 150));
w.showNormal();
- QTest::qWait(50);
+ QVERIFY(QTest::qWaitForWindowActive(&w));
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
QCOMPARE(w.size(), defaultSize + QSize(150,150));
@@ -4306,7 +4273,6 @@ void tst_QWidget::update()
QSKIP("QTBUG-52974");
#endif
- QTest::qWait(10); // Wait for the initStuff to do it's stuff.
Q_CHECK_PAINTEVENTS
UpdateWidget w;
@@ -4315,8 +4281,6 @@ void tst_QWidget::update()
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QApplication::processEvents();
- QApplication::processEvents();
QTRY_COMPARE(w.numPaintEvents, 1);
QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
@@ -5228,7 +5192,6 @@ void tst_QWidget::moveChild()
#endif
parent.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&parent));
- QTest::qWait(30);
QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
QTRY_COMPARE(child.r, QRegion(child.rect()));
@@ -5244,10 +5207,9 @@ void tst_QWidget::moveChild()
QPoint pos = child.pos() + offset;
child.move(pos);
- QTest::qWait(100);
QTRY_COMPARE(pos, child.pos());
- QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
+ QTRY_COMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
#if !defined(Q_OS_OSX)
// should be scrolled in backingstore
QCOMPARE(child.r, QRegion());
@@ -5277,7 +5239,6 @@ void tst_QWidget::showAndMoveChild()
parent.show();
qApp->setActiveWindow(&parent);
QVERIFY(QTest::qWaitForWindowActive(&parent));
- QTest::qWait(10);
QWidget child(&parent);
child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
@@ -5315,14 +5276,12 @@ void tst_QWidget::subtractOpaqueSiblings()
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(10);
large->reset();
medium->reset();
tall->reset();
medium->update();
- QTest::qWait(10);
// QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
// to be repainted and tall from be repainted at all.
@@ -7524,7 +7483,6 @@ void tst_QWidget::repaintWhenChildDeleted()
w.setGeometry(QRect(startPoint, QSize(100, 100)));
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(10);
QTRY_COMPARE(w.r, QRegion(w.rect()));
w.r = QRegion();
@@ -7532,12 +7490,10 @@ void tst_QWidget::repaintWhenChildDeleted()
ColorWidget child(&w, Qt::Widget, Qt::blue);
child.setGeometry(10, 10, 10, 10);
child.show();
- QTest::qWait(10);
QTRY_COMPARE(child.r, QRegion(child.rect()));
w.r = QRegion();
}
- QTest::qWait(10);
QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
}
@@ -7558,7 +7514,6 @@ void tst_QWidget::hideOpaqueChildWhileHidden()
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(10);
QTRY_COMPARE(child2.r, QRegion(child2.rect()));
child.r = QRegion();
child2.r = QRegion();
@@ -7566,13 +7521,11 @@ void tst_QWidget::hideOpaqueChildWhileHidden()
child.hide();
child2.hide();
- QTest::qWait(100);
- QCOMPARE(w.r, QRegion(child.geometry()));
+ QTRY_COMPARE(w.r, QRegion(child.geometry()));
child.show();
- QTest::qWait(100);
- QCOMPARE(child.r, QRegion(child.rect()));
+ QTRY_COMPARE(child.r, QRegion(child.rect()));
QCOMPARE(child2.r, QRegion());
}
@@ -7593,7 +7546,6 @@ void tst_QWidget::updateWhileMinimized()
widget.reset();
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
- QApplication::processEvents();
QTRY_VERIFY(widget.numPaintEvents > 0);
QTest::qWait(150);
@@ -8125,7 +8077,6 @@ void tst_QWidget::doubleRepaint()
int expectedRepaints = 1;
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
- QTest::qWait(10);
QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
widget.numPaintEvents = 0;
@@ -8165,7 +8116,6 @@ void tst_QWidget::resizeInPaintEvent()
QCOMPARE(widget.numPaintEvents, 1);
widget.numPaintEvents = 0;
- QTest::qWait(10);
// Make sure the resize triggers another update.
QTRY_COMPARE(widget.numPaintEvents, 1);
}
@@ -8188,7 +8138,6 @@ void tst_QWidget::opaqueChildren()
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
- QTest::qWait(100);
// Child, grandChild and greatGrandChild are outside the ancestor clip.
QRegion expectedOpaqueRegion(50, 50, 150, 150);
@@ -8257,7 +8206,6 @@ void tst_QWidget::setMaskInResizeEvent()
testWidget.show();
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(30);
QTRY_VERIFY(w.numPaintEvents > 0);
w.reset();
@@ -8311,7 +8259,6 @@ void tst_QWidget::moveInResizeEvent()
testWidget.setGeometry(50, 50, 200, 200);
testWidget.show();
QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
- QTest::qWait(300);
QRect expectedGeometry(100,100, 100, 100);
QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
@@ -8326,7 +8273,6 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
centerOnScreen(widget.data());
widget->show();
QVERIFY(QTest::qWaitForWindowExposed(widget.data()));
- QTest::qWait(200);
widget->numPaintEvents = 0;
@@ -8489,7 +8435,7 @@ void tst_QWidget::moveRect()
child.setUpdatesEnabled(false);
child.setAttribute(Qt::WA_OpaquePaintEvent);
widget.show();
- QTest::qWait(200);
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
child.move(10, 10); // Don't crash.
}
@@ -8590,7 +8536,6 @@ void tst_QWidget::reparentStaticWidget()
window2.move(window1.geometry().topRight() + QPoint(100, 0));
window2.show();
QVERIFY(QTest::qWaitForWindowExposed(&window2));
- QTest::qWait(20);
// Reparent into another top-level.
child->setParent(&window2);
@@ -8702,7 +8647,6 @@ void tst_QWidget::translucentWidget()
label.move(labelPos);
label.show();
QVERIFY(QTest::qWaitForWindowExposed(&label));
- QTest::qWait(200);
QPixmap widgetSnapshot;
@@ -8800,7 +8744,6 @@ void tst_QWidget::setClearAndResizeMask()
const QRegion childMask(0, 0, 50, 50);
child.setMask(childMask);
QTRY_COMPARE(child.mask(), childMask);
- QTest::qWait(50);
// and ensure that the child widget doesn't get any update.
#ifdef Q_OS_OSX
// Mac always issues a full update when calling setMask, and we cannot force it to not do so.
@@ -8821,7 +8764,6 @@ void tst_QWidget::setClearAndResizeMask()
// Clear child widget mask
child.clearMask();
QTRY_COMPARE(child.mask(), QRegion());
- QTest::qWait(10);
// and ensure that that the child widget gets an update for the area outside the old mask.
QTRY_COMPARE(child.numPaintEvents, 1);
outsideOldMask = child.rect();
@@ -8839,7 +8781,6 @@ void tst_QWidget::setClearAndResizeMask()
// Mask child widget with a mask that is bigger than the rect
child.setMask(QRegion(0, 0, 1000, 1000));
- QTest::qWait(100);
#ifdef Q_OS_OSX
// Mac always issues a full update when calling setMask, and we cannot force it to not do so.
if (child.internalWinId())
@@ -9093,7 +9034,6 @@ void tst_QWidget::syntheticEnterLeave()
window.raise();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QTest::qWait(300);
#define RESET_EVENT_COUNTS \
window.numEnterEvents = 0; \
@@ -9302,7 +9242,6 @@ void tst_QWidget::updateOnDestroyedSignal()
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
- QTest::qWait(200);
// Please do not crash.
MyEvilObject evil(child);
@@ -9315,7 +9254,6 @@ void tst_QWidget::toplevelLineEditFocus()
w.setMinimumWidth(m_testWidgetSize.width());
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(20);
QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
@@ -9766,14 +9704,10 @@ void tst_QWidget::nativeChildFocus()
p1->setFocus();
p1->setAttribute(Qt::WA_NativeWindow);
p2->setAttribute(Qt::WA_NativeWindow);
- QApplication::processEvents();
QVERIFY(QTest::qWaitForWindowExposed(&w));
- QTest::qWait(10);
QCOMPARE(QApplication::activeWindow(), &w);
QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
-
- QTest::qWait(1000);
}
static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index 9021be1515..1d2bb00678 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -911,7 +911,7 @@ void tst_QWidget_window::setWindowState()
// Minimizing keeps other states
w.showMinimized();
QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
- QTest::qWait(100);
+ QTest::qWait(200);
QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized);
}
diff --git a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
index 2ab2fa4c86..a78ebdb2b9 100644
--- a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
+++ b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
@@ -128,12 +128,12 @@ void tst_QMacStyle::sizeHints()
QComboBox comboBox1(&w);
comboBox1.setEditable(false);
comboBox1.addItem("Foo");
- QCOMPARE(sh(&comboBox1).height(), SIZE(20, 17, 15));
+ QCOMPARE(sh(&comboBox1).height(), SIZE(26, 17, 15));
QComboBox comboBox2(&w);
comboBox2.setEditable(true);
comboBox2.addItem("Foo");
- QCOMPARE(sh(&comboBox2).height(), SIZE(22, 17, 15));
+ QCOMPARE(sh(&comboBox2).height(), SIZE(26, 17, 15));
// Combos in toolbars use the actual widget rect to
// avoid faulty clipping:
@@ -141,7 +141,7 @@ void tst_QMacStyle::sizeHints()
setSize(&tb, size);
QComboBox comboBox3(&tb);
comboBox3.addItem("Foo");
- QCOMPARE(sh(&comboBox3).height(), SIZE(26, -1, -1));
+ QCOMPARE(sh(&comboBox3).height(), SIZE(32, -1, -1));
QSlider slider1(Qt::Horizontal, &w);
QCOMPARE(sh(&slider1).height(), SIZE(15, 12, 10));
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index 6fbb0fe5fa..0511c278d5 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -1099,8 +1099,8 @@ void tst_QCompleter::multipleWidgets()
comboBox->show();
window.activateWindow();
QApplication::setActiveWindow(&window);
- QTest::qWait(50);
- QTRY_COMPARE(QApplication::focusWidget(), comboBox);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QCOMPARE(QApplication::focusWidget(), comboBox);
comboBox->lineEdit()->setText("it");
QCOMPARE(comboBox->currentText(), QString("it")); // should not complete with setText
QTest::keyPress(comboBox, 'e');
@@ -1112,7 +1112,6 @@ void tst_QCompleter::multipleWidgets()
lineEdit->setCompleter(&completer);
lineEdit->show();
lineEdit->setFocus();
- QTest::qWait(50);
QTRY_COMPARE(QApplication::focusWidget(), lineEdit);
lineEdit->setText("it");
QCOMPARE(lineEdit->text(), QString("it")); // should not completer with setText
diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
index 67bae43c9d..43063881b2 100644
--- a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
+++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
@@ -394,8 +394,7 @@ void tst_QScroller::scroll()
// wait until finished, check that no further first scroll is sent
sw->receivedFirst = false;
sw->receivedScroll = false;
- while (s1->state() == QScroller::Scrolling)
- QTest::qWait(100);
+ QTRY_VERIFY(s1->state() != QScroller::Scrolling);
QCOMPARE( sw->receivedFirst, false );
QCOMPARE( sw->receivedScroll, true );
@@ -409,8 +408,7 @@ void tst_QScroller::scroll()
sw->scrollArea = QRectF(0, 0, 0, 1000);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
QCOMPARE(sw->currentPos.x(), 0.0);
QCOMPARE(sw->currentPos.y(), 500.0);
@@ -443,8 +441,7 @@ void tst_QScroller::overshoot()
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
//qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
@@ -459,8 +456,7 @@ void tst_QScroller::overshoot()
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
//qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
@@ -475,8 +471,7 @@ void tst_QScroller::overshoot()
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
//qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
@@ -492,8 +487,7 @@ void tst_QScroller::overshoot()
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
@@ -509,8 +503,7 @@ void tst_QScroller::overshoot()
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
- while (s1->state() != QScroller::Inactive)
- QTest::qWait(20);
+ QTRY_COMPARE(s1->state(), QScroller::Inactive);
QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
index 500ec2e1fa..84071962bc 100644
--- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
+++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
@@ -178,9 +178,11 @@ void tst_QLabel::setBuddy()
test_label= new QLabel( test_box );
test_label->setText( "&Test with a buddy" );
QWidget *test_edit = new QLineEdit( test_box );
+ QWidget *test_edit2 = new QLineEdit( test_box );
QVBoxLayout *layout = new QVBoxLayout(test_box);
layout->addWidget(test_label);
layout->addWidget(test_edit);
+ layout->addWidget(test_edit2);
test_box->show();
qApp->setActiveWindow(test_box);
QVERIFY(test_box->isActiveWindow());
@@ -190,6 +192,16 @@ void tst_QLabel::setBuddy()
QVERIFY( !test_edit->hasFocus() );
QTest::keyClick( test_box, 't', Qt::AltModifier );
QVERIFY( test_edit->hasFocus() );
+
+ // Setting a new buddy should disconnect the old one's destroyed() signal
+ test_label->setBuddy(test_edit2);
+ delete test_edit;
+ QCOMPARE(test_label->buddy(), test_edit2);
+
+ // And deleting our own buddy should disconnect and not crash
+ delete test_edit2;
+ QTest::keyClick(test_box, 't', Qt::AltModifier );
+
delete test_box;
}
#endif
diff --git a/tests/benchmarks/gui/painting/lancebench/lancebench.pro b/tests/benchmarks/gui/painting/lancebench/lancebench.pro
new file mode 100644
index 0000000000..6458c50861
--- /dev/null
+++ b/tests/benchmarks/gui/painting/lancebench/lancebench.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = tst_bench_lancebench
+
+QT += testlib gui-private
+
+
+SOURCES += tst_lancebench.cpp
+
+SOURCES += ../../../../auto/other/lancelot/paintcommands.cpp
+HEADERS += ../../../../auto/other/lancelot/paintcommands.h
+RESOURCES += ../../../../auto/other/lancelot/images.qrc
+
+TESTDATA += ../../../../auto/other/lancelot/scripts/*
diff --git a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp
new file mode 100644
index 0000000000..bd0889bf4a
--- /dev/null
+++ b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../../../auto/other/lancelot/paintcommands.h"
+
+#include <qtest.h>
+#include <QDir>
+#include <QPainter>
+
+#ifndef QT_NO_OPENGL
+#include <QOpenGLFramebufferObjectFormat>
+#include <QOpenGLContext>
+#include <QOpenGLPaintDevice>
+#endif
+
+#include <algorithm>
+
+class tst_LanceBench : public QObject
+{
+ Q_OBJECT
+public:
+ tst_LanceBench();
+
+private:
+ enum GraphicsEngine {
+ Raster = 0,
+ OpenGL = 1
+ };
+
+ void setupTestSuite(const QStringList& blacklist = QStringList());
+ void runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat = QSurfaceFormat());
+ void paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath);
+
+ QStringList qpsFiles;
+ QHash<QString, QStringList> scripts;
+ QString scriptsDir;
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase() {}
+
+ void testRasterARGB32PM_data();
+ void testRasterARGB32PM();
+ void testRasterRGB32_data();
+ void testRasterRGB32();
+ void testRasterARGB32_data();
+ void testRasterARGB32();
+ void testRasterRGB16_data();
+ void testRasterRGB16();
+ void testRasterBGR30_data();
+ void testRasterBGR30();
+ void testRasterARGB8565PM_data();
+ void testRasterARGB8565PM();
+ void testRasterGrayscale8_data();
+ void testRasterGrayscale8();
+
+#ifndef QT_NO_OPENGL
+ void testOpenGL_data();
+ void testOpenGL();
+ void testCoreOpenGL_data();
+ void testCoreOpenGL();
+private:
+ bool checkSystemGLSupport();
+ bool checkSystemCoreGLSupport();
+#endif
+};
+
+tst_LanceBench::tst_LanceBench()
+{
+}
+
+void tst_LanceBench::initTestCase()
+{
+ QString baseDir = QFINDTESTDATA("../../../../auto/other/lancelot/scripts/text.qps");
+ scriptsDir = baseDir.left(baseDir.lastIndexOf('/')) + '/';
+ QDir qpsDir(scriptsDir);
+ qpsFiles = qpsDir.entryList(QStringList() << QLatin1String("*.qps"), QDir::Files | QDir::Readable);
+ if (qpsFiles.isEmpty()) {
+ QWARN("No qps script files found in " + qpsDir.path().toLatin1());
+ QSKIP("Aborted due to errors.");
+ }
+
+ std::sort(qpsFiles.begin(), qpsFiles.end());
+ for (const QString& fileName : qAsConst(qpsFiles)) {
+ QFile file(scriptsDir + fileName);
+ file.open(QFile::ReadOnly);
+ QByteArray cont = file.readAll();
+ scripts.insert(fileName, QString::fromUtf8(cont).split(QLatin1Char('\n'), QString::SkipEmptyParts));
+ }
+}
+
+void tst_LanceBench::testRasterARGB32PM_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterARGB32PM()
+{
+ runTestSuite(Raster, QImage::Format_ARGB32_Premultiplied);
+}
+
+void tst_LanceBench::testRasterRGB32_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterRGB32()
+{
+ runTestSuite(Raster, QImage::Format_RGB32);
+}
+
+void tst_LanceBench::testRasterARGB32_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterARGB32()
+{
+ runTestSuite(Raster, QImage::Format_ARGB32);
+}
+
+void tst_LanceBench::testRasterRGB16_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterRGB16()
+{
+ runTestSuite(Raster, QImage::Format_RGB16);
+}
+
+void tst_LanceBench::testRasterBGR30_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterBGR30()
+{
+ runTestSuite(Raster, QImage::Format_BGR30);
+}
+
+void tst_LanceBench::testRasterARGB8565PM_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterARGB8565PM()
+{
+ runTestSuite(Raster, QImage::Format_ARGB8565_Premultiplied);
+}
+
+void tst_LanceBench::testRasterGrayscale8_data()
+{
+ setupTestSuite();
+}
+
+void tst_LanceBench::testRasterGrayscale8()
+{
+ runTestSuite(Raster, QImage::Format_Grayscale8);
+}
+
+#ifndef QT_NO_OPENGL
+bool tst_LanceBench::checkSystemGLSupport()
+{
+ QWindow win;
+ win.setSurfaceType(QSurface::OpenGLSurface);
+ win.create();
+ QOpenGLFramebufferObjectFormat fmt;
+ fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fmt.setSamples(4);
+ QOpenGLContext ctx;
+ if (!ctx.create() || !ctx.makeCurrent(&win))
+ return false;
+ QOpenGLFramebufferObject fbo(800, 800, fmt);
+ if (!fbo.isValid() || !fbo.bind())
+ return false;
+
+ return true;
+}
+
+bool tst_LanceBench::checkSystemCoreGLSupport()
+{
+ if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
+ return false;
+
+ QSurfaceFormat coreFormat;
+ coreFormat.setVersion(3, 2);
+ coreFormat.setProfile(QSurfaceFormat::CoreProfile);
+ QWindow win;
+ win.setSurfaceType(QSurface::OpenGLSurface);
+ win.setFormat(coreFormat);
+ win.create();
+ QOpenGLFramebufferObjectFormat fmt;
+ fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fmt.setSamples(4);
+ QOpenGLContext ctx;
+ ctx.setFormat(coreFormat);
+ if (!ctx.create() || !ctx.makeCurrent(&win))
+ return false;
+ QOpenGLFramebufferObject fbo(800, 800, fmt);
+ if (!fbo.isValid() || !fbo.bind())
+ return false;
+
+ return true;
+}
+
+void tst_LanceBench::testOpenGL_data()
+{
+ if (!checkSystemGLSupport())
+ QSKIP("System under test does not meet preconditions for GL testing. Skipping.");
+ QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps");
+ setupTestSuite(localBlacklist);
+}
+
+void tst_LanceBench::testOpenGL()
+{
+ runTestSuite(OpenGL, QImage::Format_RGB32);
+}
+
+void tst_LanceBench::testCoreOpenGL_data()
+{
+ if (!checkSystemCoreGLSupport())
+ QSKIP("System under test does not meet preconditions for Core Profile GL testing. Skipping.");
+ QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps");
+ setupTestSuite(localBlacklist);
+}
+
+void tst_LanceBench::testCoreOpenGL()
+{
+ QSurfaceFormat coreFormat;
+ coreFormat.setVersion(3, 2);
+ coreFormat.setProfile(QSurfaceFormat::CoreProfile);
+ runTestSuite(OpenGL, QImage::Format_RGB32, coreFormat);
+}
+#endif
+
+void tst_LanceBench::setupTestSuite(const QStringList& blacklist)
+{
+ QTest::addColumn<QString>("qpsFile");
+ for (const QString &fileName : qAsConst(qpsFiles)) {
+ if (blacklist.contains(fileName))
+ continue;
+ QTest::newRow(fileName.toLatin1()) << fileName;
+ }
+}
+
+void tst_LanceBench::runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat)
+{
+ QFETCH(QString, qpsFile);
+
+ QString filePath = scriptsDir + qpsFile;
+ QStringList script = scripts.value(qpsFile);
+ QImage rendered;
+
+ if (engine == Raster) {
+ QImage img(800, 800, format);
+ paint(&img, engine, format, script, QFileInfo(filePath).absoluteFilePath());
+ rendered = img;
+#ifndef QT_NO_OPENGL
+ } else if (engine == OpenGL) {
+ QWindow win;
+ win.setSurfaceType(QSurface::OpenGLSurface);
+ win.setFormat(contextFormat);
+ win.create();
+ QOpenGLFramebufferObjectFormat fmt;
+ fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fmt.setSamples(4);
+ QOpenGLContext ctx;
+ ctx.setFormat(contextFormat);
+ QVERIFY(ctx.create());
+ QVERIFY(ctx.makeCurrent(&win));
+ QOpenGLFramebufferObject fbo(800, 800, fmt);
+ fbo.bind();
+ QOpenGLPaintDevice pdv(800, 800);
+ paint(&pdv, engine, format, script, QFileInfo(filePath).absoluteFilePath());
+ rendered = fbo.toImage().convertToFormat(format);
+#endif
+ }
+}
+
+void tst_LanceBench::paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath)
+{
+ PaintCommands pcmd(script, 800, 800, format);
+ switch (engine) {
+ case OpenGL:
+ pcmd.setType(OpenGLBufferType); // version/profile is communicated through the context's format()
+ break;
+ case Raster:
+ pcmd.setType(ImageType);
+ break;
+ }
+ pcmd.setFilePath(filePath);
+ QBENCHMARK {
+ QPainter p(device);
+ pcmd.setPainter(&p);
+ pcmd.runCommands();
+ p.end();
+ }
+}
+
+QTEST_MAIN(tst_LanceBench)
+
+#include "tst_lancebench.moc"
diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro
index bbca36259e..d08dfa707b 100644
--- a/tests/benchmarks/gui/painting/painting.pro
+++ b/tests/benchmarks/gui/painting/painting.pro
@@ -5,7 +5,8 @@ SUBDIRS = \
qpainter \
qregion \
qtransform \
- qtbench
+ qtbench \
+ lancebench
!qtHaveModule(widgets): SUBDIRS -= \
qpainter \
diff --git a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
index f2e6973e27..0248d6f855 100644
--- a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
@@ -128,7 +128,7 @@ QPixmap rasterPixmap(const QImage &image)
QPlatformPixmap *data =
new QRasterPlatformPixmap(QPlatformPixmap::PixmapType);
- data->fromImage(image, Qt::AutoColor);
+ data->fromImage(image, Qt::AutoColor | Qt::NoFormatConversion);
return QPixmap(data);
}
@@ -614,9 +614,7 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps)
QTest::addColumn<int>("type"); // 0 = circle, 1 = diag line, 2 = solid rect, 3 = alpharect
QList<QSize> sizes;
- sizes << QSize(1, 1)
- << QSize(10, 10)
- << QSize(100, 100)
+ sizes << QSize(10, 10)
<< QSize(1000, 1000);
const char *typeNames[] = {
@@ -658,7 +656,6 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps)
QImage::Format_RGB32,
QImage::Format_ARGB32_Premultiplied,
QImage::Format_RGB16,
- QImage::Format_ARGB8565_Premultiplied,
QImage::Format_BGR30,
QImage::Format_Invalid
};
@@ -683,12 +680,9 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps)
QImage::Format_ARGB32,
QImage::Format_ARGB32_Premultiplied,
QImage::Format_RGB16,
- QImage::Format_ARGB8565_Premultiplied,
QImage::Format_RGB888,
QImage::Format_RGBX8888,
QImage::Format_RGBA8888,
- QImage::Format_RGBA8888_Premultiplied,
- QImage::Format_A2BGR30_Premultiplied,
QImage::Format_RGB30,
QImage::Format_Grayscale8,
QImage::Format_Invalid
diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp
index caf8c70c6f..c0366dea63 100644
--- a/tests/manual/qtabletevent/regular_widgets/main.cpp
+++ b/tests/manual/qtabletevent/regular_widgets/main.cpp
@@ -61,23 +61,38 @@ struct TabletPoint
class ProximityEventFilter : public QObject
{
+ Q_OBJECT
public:
explicit ProximityEventFilter(QObject *parent) : QObject(parent) { }
- bool eventFilter(QObject *, QEvent *event) override
- {
- switch (event->type()) {
- case QEvent::TabletEnterProximity:
- case QEvent::TabletLeaveProximity:
- qDebug() << event;
- break;
- default:
- break;
- }
- return false;
- }
+ bool eventFilter(QObject *, QEvent *event) override;
+
+ static bool tabletPenProximity() { return m_tabletPenProximity; }
+
+signals:
+ void proximityChanged();
+
+private:
+ static bool m_tabletPenProximity;
};
+bool ProximityEventFilter::eventFilter(QObject *, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TabletEnterProximity:
+ case QEvent::TabletLeaveProximity:
+ ProximityEventFilter::m_tabletPenProximity = event->type() == QEvent::TabletEnterProximity;
+ emit proximityChanged();
+ qDebug() << event;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool ProximityEventFilter::m_tabletPenProximity = false;
+
class EventReportWidget : public QWidget
{
Q_OBJECT
@@ -111,6 +126,7 @@ private:
Qt::MouseButton m_lastButton = Qt::NoButton;
QVector<TabletPoint> m_points;
QVector<QPointF> m_touchPoints;
+ QPointF m_tabletPos;
int m_tabletMoveCount = 0;
int m_paintEventCount = 0;
};
@@ -169,6 +185,13 @@ void EventReportWidget::paintEvent(QPaintEvent *)
}
}
}
+
+ // Draw haircross when tablet pen is in proximity
+ if (ProximityEventFilter::tabletPenProximity() && geom.contains(m_tabletPos)) {
+ p.setPen(Qt::black);
+ p.drawLine(QPointF(0, m_tabletPos.y()), QPointF(geom.width(), m_tabletPos.y()));
+ p.drawLine(QPointF(m_tabletPos.x(), 0), QPointF(m_tabletPos.x(), geom.height()));
+ }
p.setPen(Qt::blue);
for (QPointF t : m_touchPoints) {
p.drawLine(t.x() - 40, t.y(), t.x() + 40, t.y());
@@ -181,20 +204,21 @@ void EventReportWidget::tabletEvent(QTabletEvent *event)
{
QWidget::tabletEvent(event);
bool isMove = false;
+ m_tabletPos = event->posF();
switch (event->type()) {
case QEvent::TabletMove:
- m_points.push_back(TabletPoint(event->pos(), TabletMove, m_lastButton, event->pointerType(), event->pressure(), event->rotation()));
+ m_points.push_back(TabletPoint(m_tabletPos, TabletMove, m_lastButton, event->pointerType(), event->pressure(), event->rotation()));
update();
isMove = true;
++m_tabletMoveCount;
break;
case QEvent::TabletPress:
- m_points.push_back(TabletPoint(event->pos(), TabletButtonPress, event->button(), event->pointerType(), event->rotation()));
+ m_points.push_back(TabletPoint(m_tabletPos, TabletButtonPress, event->button(), event->pointerType(), event->rotation()));
m_lastButton = event->button();
update();
break;
case QEvent::TabletRelease:
- m_points.push_back(TabletPoint(event->pos(), TabletButtonRelease, event->button(), event->pointerType(), event->rotation()));
+ m_points.push_back(TabletPoint(m_tabletPos, TabletButtonRelease, event->button(), event->pointerType(), event->rotation()));
update();
break;
default:
@@ -253,10 +277,14 @@ void EventReportWidget::timerEvent(QTimerEvent *)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- app.installEventFilter(new ProximityEventFilter(&app));
+
+ ProximityEventFilter *proximityEventFilter = new ProximityEventFilter(&app);
+ app.installEventFilter(proximityEventFilter);
QMainWindow mainWindow;
mainWindow.setWindowTitle(QString::fromLatin1("Tablet Test %1").arg(QT_VERSION_STR));
EventReportWidget *widget = new EventReportWidget;
+ QObject::connect(proximityEventFilter, &ProximityEventFilter::proximityChanged,
+ widget, QOverload<void>::of(&QWidget::update));
widget->setMinimumSize(640, 480);
QMenu *fileMenu = mainWindow.menuBar()->addMenu("File");
fileMenu->addAction("Clear", widget, &EventReportWidget::clearPoints);
diff --git a/tests/manual/shortcuts/main.cpp b/tests/manual/shortcuts/main.cpp
index 849f8728b3..acc2a2525c 100644
--- a/tests/manual/shortcuts/main.cpp
+++ b/tests/manual/shortcuts/main.cpp
@@ -28,6 +28,7 @@
#include <QApplication>
#include <QVBoxLayout>
+#include <QGridLayout>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
@@ -36,200 +37,123 @@
class ShortcutTester : public QWidget
{
public:
- ShortcutTester() {
- setupLayout();
- }
-protected:
- void setupLayout()
+ ShortcutTester()
{
- QVBoxLayout *layout = new QVBoxLayout(this);
- setLayout(layout);
-
- QLabel *testPurpose = new QLabel();
- testPurpose->setWordWrap(true);
- testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
- testPurpose->setText("This test come in handy to verify shortcuts under different "
- "keyboard layouts - qwerty, dvorak, non-latin (russian, arabic), etc.");
- layout->addWidget(testPurpose);
-
- QKeySequence altShiftG(Qt::AltModifier + Qt::ShiftModifier + Qt::Key_G);
- QPushButton *_altShiftG = new QPushButton(altShiftG.toString());
- _altShiftG->setShortcut(altShiftG);
- layout->addWidget(_altShiftG);
-
- QKeySequence altG(Qt::AltModifier + Qt::Key_G);
- QPushButton *_altG = new QPushButton(altG.toString());
- _altG->setShortcut(altG);
- layout->addWidget(_altG);
-
- QKeySequence ctrlShiftR(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_R);
- QPushButton *_ctrlShiftR = new QPushButton(ctrlShiftR.toString());
- _ctrlShiftR->setShortcut(ctrlShiftR);
- layout->addWidget(_ctrlShiftR);
-
- QKeySequence ctrlR(Qt::ControlModifier + Qt::Key_R);
- QPushButton *_ctrlR = new QPushButton(ctrlR.toString());
- _ctrlR->setShortcut(ctrlR);
- layout->addWidget(_ctrlR);
-
- QKeySequence ctrlReturn(Qt::ControlModifier + Qt::Key_Return);
- QPushButton *_ctrlReturn = new QPushButton(ctrlReturn.toString());
- _ctrlReturn->setShortcut(ctrlReturn);
- layout->addWidget(_ctrlReturn);
-
- QKeySequence ctrlEnter(Qt::ControlModifier + Qt::Key_Enter);
- QPushButton *_ctrlEnter = new QPushButton(ctrlEnter.toString());
- _ctrlEnter->setShortcut(ctrlEnter);
- layout->addWidget(_ctrlEnter);
-
- QKeySequence ctrlShiftAltR(Qt::ControlModifier + Qt::ShiftModifier + Qt::AltModifier + Qt::Key_R);
- QPushButton *_ctrlShiftAltR = new QPushButton(ctrlShiftAltR.toString());
- _ctrlShiftAltR->setShortcut(ctrlShiftAltR);
- layout->addWidget(_ctrlShiftAltR);
-
- QKeySequence shift5(Qt::ShiftModifier + Qt::Key_5);
- QPushButton *_shift5 = new QPushButton(shift5.toString());
- _shift5->setShortcut(shift5);
- layout->addWidget(_shift5);
-
- QKeySequence shiftPercent(Qt::ShiftModifier + Qt::Key_Percent);
- QPushButton *_shiftPercent = new QPushButton(shiftPercent.toString());
- _shiftPercent->setShortcut(shiftPercent);
- layout->addWidget(_shiftPercent);
-
- QKeySequence percent(Qt::Key_Percent);
- QPushButton *_percent = new QPushButton(percent.toString());
- _percent->setShortcut(percent);
- layout->addWidget(_percent);
-
- QKeySequence key5(Qt::Key_5);
- QPushButton *_key5 = new QPushButton(key5.toString());
- _key5->setShortcut(key5);
- layout->addWidget(_key5);
-
- QKeySequence keyQ(Qt::Key_Q);
- QPushButton *_keyQ = new QPushButton(keyQ.toString());
- _keyQ->setShortcut(keyQ);
- layout->addWidget(_keyQ);
-
- QKeySequence ctrlPercent(Qt::ControlModifier + Qt::Key_Percent);
- QPushButton *_ctrlPercent = new QPushButton(ctrlPercent.toString());
- _ctrlPercent->setShortcut(ctrlPercent);
- layout->addWidget(_ctrlPercent);
-
- QKeySequence ctrlShift5(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_5);
- QPushButton *_ctrlShift5 = new QPushButton(ctrlShift5.toString());
- _ctrlShift5->setShortcut(ctrlShift5);
- layout->addWidget(_ctrlShift5);
-
- QKeySequence ctrl5(Qt::ControlModifier + Qt::Key_5);
- QPushButton *_ctrl5 = new QPushButton(ctrl5.toString());
- _ctrl5->setShortcut(ctrl5);
- layout->addWidget(_ctrl5);
-
- QKeySequence alt5(Qt::AltModifier + Qt::Key_5);
- QPushButton *_alt5 = new QPushButton(alt5.toString());
- _alt5->setShortcut(alt5);
- layout->addWidget(_alt5);
-
- QKeySequence ctrlPlus(Qt::ControlModifier + Qt::Key_Plus);
- QPushButton *_ctrlPlus = new QPushButton(ctrlPlus.toString());
- _ctrlPlus->setShortcut(ctrlPlus);
- layout->addWidget(_ctrlPlus);
-
- QKeySequence ctrlShiftPlus(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Plus);
- QPushButton *_ctrlShiftPlus = new QPushButton(ctrlShiftPlus.toString());
- _ctrlShiftPlus->setShortcut(ctrlShiftPlus);
- layout->addWidget(_ctrlShiftPlus);
-
- QKeySequence ctrlY(Qt::ControlModifier + Qt::Key_Y);
- QPushButton *_ctrlY = new QPushButton(ctrlY.toString());
- _ctrlY->setShortcut(ctrlY);
- layout->addWidget(_ctrlY);
-
- QKeySequence shiftComma(Qt::ShiftModifier + Qt::Key_Comma);
- QPushButton *_shiftComma = new QPushButton(shiftComma.toString());
- _shiftComma->setShortcut(shiftComma);
- layout->addWidget(_shiftComma);
-
- QKeySequence ctrlComma(Qt::ControlModifier + Qt::Key_Comma);
- QPushButton *_ctrlComma = new QPushButton(ctrlComma.toString());
- _ctrlComma->setShortcut(ctrlComma);
- layout->addWidget(_ctrlComma);
-
- QKeySequence ctrlSlash(Qt::ControlModifier + Qt::Key_Slash);
- QPushButton *_ctrlSlash = new QPushButton(ctrlSlash.toString());
- _ctrlSlash->setShortcut(ctrlSlash);
- layout->addWidget(_ctrlSlash);
-
- QKeySequence ctrlBackslash(Qt::ControlModifier + Qt::Key_Backslash);
- QPushButton *_ctrlBackslash = new QPushButton(ctrlBackslash.toString());
- _ctrlBackslash->setShortcut(ctrlBackslash);
- layout->addWidget(_ctrlBackslash);
-
- QKeySequence metaShiftA(Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_A);
- QPushButton *_metaShiftA = new QPushButton(metaShiftA.toString());
- _metaShiftA->setShortcut(metaShiftA);
- layout->addWidget(_metaShiftA);
-
- QKeySequence metaShift5(Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_5);
- QPushButton *_metaShift5 = new QPushButton(metaShift5.toString());
- _metaShift5->setShortcut(metaShift5);
- layout->addWidget(_metaShift5);
-
- QKeySequence ctrlBracketRigth(Qt::ControlModifier + Qt::Key_BracketRight);
- QPushButton *_ctrlBracketRigth = new QPushButton(ctrlBracketRigth.toString());
- _ctrlBracketRigth->setShortcut(ctrlBracketRigth);
- layout->addWidget(_ctrlBracketRigth);
-
- QKeySequence shiftF3(Qt::ShiftModifier + Qt::Key_F3);
- QPushButton *_shiftF3 = new QPushButton(shiftF3.toString());
- _shiftF3->setShortcut(shiftF3);
- layout->addWidget(_shiftF3);
-
- QKeySequence ctrlF3(Qt::ControlModifier + Qt::Key_F3);
- QPushButton *_ctrlF3 = new QPushButton(ctrlF3.toString());
- _ctrlF3->setShortcut(ctrlF3);
- layout->addWidget(_ctrlF3);
-
- QKeySequence euro(0x20AC); // EURO SIGN e.g. US (with euro on 5) on 3rd keyboard level
- QPushButton *_euro = new QPushButton(euro.toString());
- _euro->setShortcut(euro);
- layout->addWidget(_euro);
-
- QKeySequence ctrlEuro(Qt::ControlModifier + 0x20AC);
- QPushButton *_ctrlEuro = new QPushButton(ctrlEuro.toString());
- _ctrlEuro->setShortcut(ctrlEuro);
- layout->addWidget(_ctrlEuro);
-
- // with german (neo 2) layout on linux under ISO_Level3_Shift + ISO_Level5_Shift + I
- QKeySequence greekPsi(QString(QStringLiteral("\u03A8")));
- QPushButton *_greekPsi = new QPushButton(greekPsi.toString());
- _greekPsi->setShortcut(greekPsi);
- layout->addWidget(_greekPsi);
-
- layout->addWidget(new QLabel("Norwegian layout"));
- // LATIN SMALL LETTER O WITH STROKE
- QKeySequence norwegianO(QString(QStringLiteral("\u00F8")));
- QPushButton *_norwegianO = new QPushButton(norwegianO.toString());
- _norwegianO->setShortcut(norwegianO);
- layout->addWidget(_norwegianO);
-
- layout->addWidget(new QLabel("Russian layout"));
- // CYRILLIC SMALL LETTER ZHE
- QKeySequence zhe(QString(QStringLiteral("\u0436")));
- QPushButton *_zhe = new QPushButton(zhe.toString());
- _zhe->setShortcut(zhe);
- layout->addWidget(_zhe);
-
- // for sequence definitons see qplatformtheme.cpp
- layout->addWidget(new QLabel("QKeySequence::StandardKey(s)"));
- QPushButton *_open = new QPushButton("Open");
- _open->setShortcut(QKeySequence::Open); // Qt::CTRL | Qt::Key_O
- layout->addWidget(_open);
+ const QString title = QLatin1String(QT_VERSION_STR) + QLatin1Char(' ')
+ + qApp->platformName();
+ setWindowTitle(title);
+ setupLayout();
}
+
+private:
+ void setupLayout();
+ void addToGrid(QWidget *w, int &row, int col);
+ void addShortcutToGrid(const QKeySequence &k, int &row, int col);
+ void addShortcutToGrid(int key, int &row, int col)
+ { addShortcutToGrid(QKeySequence(key), row, col); }
+
+ QGridLayout *m_gridLayout = new QGridLayout;
};
+inline void ShortcutTester::addToGrid(QWidget *w, int &row, int col)
+{
+ m_gridLayout->addWidget(w, row++, col);
+}
+
+void ShortcutTester::addShortcutToGrid(const QKeySequence &k, int &row, int col)
+{
+ QPushButton *button = new QPushButton(k.toString());
+ button->setShortcut(k);
+ addToGrid(button, row, col);
+}
+
+void addShortcutToGrid(int key, int &row, int col);
+
+void ShortcutTester::setupLayout()
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ QLabel *testPurpose = new QLabel();
+ testPurpose->setWordWrap(true);
+ testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
+ testPurpose->setText("This test come in handy to verify shortcuts under different "
+ "keyboard layouts - qwerty, dvorak, non-latin (russian, arabic), etc.");
+ layout->addWidget(testPurpose);
+
+ layout->addLayout(m_gridLayout);
+
+ int row = 0;
+ int col = 0;
+
+ const int keys1[] = {
+ Qt::AltModifier + Qt::ShiftModifier + Qt::Key_G,
+ Qt::AltModifier + Qt::Key_G,
+ Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_R,
+ Qt::ControlModifier + Qt::Key_R,
+ Qt::ControlModifier + Qt::Key_Return, Qt::ControlModifier + Qt::Key_Enter,
+ Qt::ControlModifier + Qt::ShiftModifier + Qt::AltModifier + Qt::Key_R,
+ Qt::ShiftModifier + Qt::Key_5, Qt::ShiftModifier + Qt::Key_Percent,
+ Qt::Key_Percent, Qt::Key_5, Qt::Key_Q
+ };
+
+ for (int k : keys1)
+ addShortcutToGrid(k, row, col);
+
+ row = 0;
+ col++;
+
+ const int keys2[] = {
+ Qt::ControlModifier + Qt::Key_Percent,
+ Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_5,
+ Qt::ControlModifier + Qt::Key_5, Qt::AltModifier + Qt::Key_5,
+ Qt::ControlModifier + Qt::Key_Plus,
+ Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Plus,
+ Qt::ControlModifier + Qt::Key_Y, Qt::ShiftModifier + Qt::Key_Comma,
+ Qt::ControlModifier + Qt::Key_Comma, Qt::ControlModifier + Qt::Key_Slash,
+ Qt::ControlModifier + Qt::Key_Backslash
+ };
+
+ for (int k : keys2)
+ addShortcutToGrid(k, row, col);
+
+ row = 0;
+ col++;
+
+ const int keys3[] = {
+ Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_A,
+ Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_5,
+ Qt::ControlModifier + Qt::Key_BracketRight,
+ Qt::ShiftModifier + Qt::Key_F3,
+ Qt::ControlModifier + Qt::Key_F3,
+ 0x20AC, // EURO SIGN e.g. US (with euro on 5) on 3rd keyboard level
+ Qt::ControlModifier + 0x20AC
+ };
+
+ for (int k : keys3)
+ addShortcutToGrid(k, row, col);
+
+ // with german (neo 2) layout on linux under ISO_Level3_Shift + ISO_Level5_Shift + I
+ const QKeySequence greekPsi(QString(QStringLiteral("\u03A8")));
+ addShortcutToGrid(greekPsi, row, col);
+
+ row = 0;
+ col++;
+
+ addToGrid(new QLabel("Norwegian layout"), row, col);
+ // LATIN SMALL LETTER O WITH STROKE
+ QKeySequence norwegianO(QString(QStringLiteral("\u00F8")));
+ addShortcutToGrid(norwegianO, row, col);
+
+ addToGrid(new QLabel("Russian layout"), row, col);
+ // CYRILLIC SMALL LETTER ZHE
+ QKeySequence zhe(QString(QStringLiteral("\u0436")));
+ addShortcutToGrid(zhe, row, col);
+
+ // for sequence definitons see qplatformtheme.cpp
+ addToGrid(new QLabel("QKeySequence::StandardKey(s)"), row, col);
+ addShortcutToGrid(QKeySequence(QKeySequence::Open), row, col); // Qt::CTRL | Qt::Key_O
+}
+
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
diff --git a/tests/shared/emulationdetector.h b/tests/shared/emulationdetector.h
index bf1192a0b2..cca11be695 100644
--- a/tests/shared/emulationdetector.h
+++ b/tests/shared/emulationdetector.h
@@ -32,7 +32,7 @@
#if defined(Q_OS_LINUX) && defined(Q_PROCESSOR_ARM)
#define SHOULD_CHECK_ARM_ON_X86
-#if QT_CONFIG(process) && !defined(QT_NO_REGULAREXPRESSION)
+#if QT_CONFIG(process) && QT_CONFIG(regularexpression)
#include <QProcess>
#include <QRegularExpression>
#endif
@@ -88,7 +88,7 @@ static bool isX86SpecificFileAvailable()
*/
static bool isReportedArchitectureX86(void)
{
-#if QT_CONFIG(process) && !defined(QT_NO_REGULAREXPRESSION)
+#if QT_CONFIG(process) && QT_CONFIG(regularexpression)
QProcess unamer;
QString machineString;